ManageIQ / manageiq-ui-classic

Classic UI of ManageIQ
Apache License 2.0
50 stars 358 forks source link

WEBMKS - Uncaught ReferenceError: ManageIQ is not defined #8008

Closed ccesario closed 2 years ago

ccesario commented 2 years ago

Hello,

After upgrade my current appliance running Kasparov version to Lasker, according the https://www.manageiq.org/docs/reference/latest/upgrading_appliances/ the WEBMKS console does not work, it is showed a blank screen. Using chrome dev tool I got this error

Uncaught ReferenceError: ManageIQ is not defined at HTMLDocument. (vendor-3f918ad9c9df78da5ea4.js:124) at l (vendor-3f918ad9c9df78da5ea4.js:47) at Object.fireWith [as resolveWith] (vendor-3f918ad9c9df78da5ea4.js:47) at Function.ready (vendor-3f918ad9c9df78da5ea4.js:47) at HTMLDocument.k (vendor-3f918ad9c9df78da5ea4.js:47)

image

To try identify the root cause, I have changed the file /opt/manageiq/manageiq-gemset/bundler/gems/manageiq-ui-classic-a3025406b60d/app/javascript/oldjs/i18n.js

diff --git a/before b/after
index 153a954..68c48ff 100644
--- a/before
+++ b/after
@@ -4,12 +4,10 @@ require('gettext_i18n_rails_js/lib/assets/javascripts/gettext/all.js');

 $(function() {
   // set in layouts/i18n_js
-  if (ManageIQ && ManageIQ.i18n && ManageIQ.i18n.mark_translated_strings) {
-    window.__ = function() {
-      return '\u00BB' + i18n.gettext.apply(i18n, arguments) + '\u00AB';
-    };
-    window.n__ = function() {
-      return '\u00BB' + i18n.ngettext.apply(i18n, arguments) + '\u00AB';
-    };
-  }
+  window.__ = function() {
+    return '\u00BB' + i18n.gettext.apply(i18n, arguments) + '\u00AB';
+  };
+  window.n__ = function() {
+    return '\u00BB' + i18n.ngettext.apply(i18n, arguments) + '\u00AB';
+  };
 });

EDIT by @Fryguy: converted to diff to see the changes more clearly

After remove IF condition, and run

cd /var/www/miq/vmdb/ bundle exec rake assets:clean bundle exec rake assets:precompile bin/rake update:ui && bin/rake evm:compile_assets service evmserverd restart

The console it works as expected.

image

image

Fryguy commented 2 years ago

@ccesario Can you make a PR with your changes?

Oh wait, I see what you did, but that actually breaks functionality... @kavyanekkalapu Can you take a look at this one? The mark_translated_strings should come from the API, so it's possible that value can't be retrieved at this time?

kavyanekkalapu commented 2 years ago

~@ccesario Can you make a PR with your changes?~

Oh wait, I see what you did, but that actually breaks functionality... @kavyanekkalapu Can you take a look at this one? The mark_translated_strings should come from the API, so it's possible that value can't be retrieved at this time?

@Fryguy By looking at the error ManageIQ itself is an issue. it is not even going to mark_translated_strings.

kavyanekkalapu commented 2 years ago

@ccesario Could you try to put console log inside if (!window.ManageIQ) condition in this file /opt/manageiq/manageiq-gemset/bundler/gems/manageiq-ui-classic-a3025406b60d/app/javascript/oldjs/miq_global.js?

Fryguy commented 2 years ago

@kavyanekkalapu yeah, I think the window that's popped up for the remote console loads some of the javascript files, but in that window it looks like it's missing wherever ManageIQ is defined

ccesario commented 2 years ago

@ccesario Could you try to put console log inside if (!window.ManageIQ) condition in this file /opt/manageiq/manageiq-gemset/bundler/gems/manageiq-ui-classic-a3025406b60d/app/javascript/oldjs/miq_global.js?

Hi @kavyanekkalapu, I added console.log() inside if (!window.ManageIQ) into file /opt/manageiq/manageiq-gemset/bundler/gems/manageiq-ui-classic-a3025406b60d/app/javascript/oldjs/miq_global.js, and I thin that there is a problem with ManageIQ var.

Look the Image.

image

Fryguy commented 2 years ago

It's defined immediately after that. Try moving your console.log after it's defined. I think what @kavyanekkalapu is trying to see is whether the miq_global.js is even loaded or not when you do a remote console. If it's loaded you should see your console log, if not, then you won't.

kavyanekkalapu commented 2 years ago

@ccesario Sorry should have been more clearer. Could you add couple of console logs in line no 99 and 100? Thank you.

Console.log("test1",ManageIQ); and console.log("test2",window.ManageIQ);

ccesario commented 2 years ago

@kavyanekkalapu, Sure. I did it, but I think that is not executed due ManageIQ var. Look the images image

image

ccesario commented 2 years ago

@kavyanekkalapu I don't know if this help, and if this include can be done in this file, but after I add require('./miq_global.js'); into /opt/manageiq/manageiq-gemset/bundler/gems/manageiq-ui-classic-a3025406b60d/app/javascript/oldjs/i18n.js file, the WEB Console it works as expected without error.

image

diff -uNr  /opt/manageiq/manageiq-gemset/bundler/gems/manageiq-ui-classic-a3025406b60d/app/javascript/oldjs/i18n.js.ORI  /opt/manageiq/manageiq-gemset/bundler/gems/manageiq-ui-classic-a3025406b60d/app/javascript/oldjs/i18n.js
--- /opt/manageiq/manageiq-gemset/bundler/gems/manageiq-ui-classic-a3025406b60d/app/javascript/oldjs/i18n.js.ORI        2022-01-06 18:58:12.480060103 -0300
+++ /opt/manageiq/manageiq-gemset/bundler/gems/manageiq-ui-classic-a3025406b60d/app/javascript/oldjs/i18n.js    2022-01-06 16:57:22.296720511 -0300
@@ -1,6 +1,7 @@
 require('./locale/');
 require('gettext_i18n_rails_js/vendor/assets/javascripts/gettext/jed.js');
 require('gettext_i18n_rails_js/lib/assets/javascripts/gettext/all.js');
+require('./miq_global.js');

 $(function() {
   // set in layouts/i18n_js
kavyanekkalapu commented 2 years ago

@ccesario Thanks for checking that. This helps. Tomorrow i will check about globals file.

kavyanekkalapu commented 2 years ago

@ccesario This file https://github.com/ManageIQ/manageiq-ui-classic/blob/60d3dfef59234a8df94af2ec419e8b5ce070f7ff/app/javascript/oldjs/application.js has two lines before loading i18n.js .

require('./miq_global.js'); require('./jquery_overrides.js');

Ideally it should work. we are also calling ManageIQ variable in https://github.com/ManageIQ/manageiq-ui-classic/blob/60d3dfef59234a8df94af2ec419e8b5ce070f7ff/app/javascript/oldjs/jquery_overrides.js. want to check if the variable is loading in this file. Unfortunately, i am not able to reproduce this bug . So need your help in debugging.

Could you add this code in jquery_overrides.js file and see if these prints out.


function func1() {
  console.log('func1 in jquery overrides');
  console.log("test2 ManageIQ",window.ManageIQ);
  console.log("test3 ManageIQ",ManageIQ);
}
func1();
Fryguy commented 2 years ago

I'm wondering if both jquery_overrides.js and i18n.js should just have miq_global inside them since they require them anyway. This way, when used in isolation, they will still work. i18n right now is relying on something else to define ManageIQ, which feels wrong.

ccesario commented 2 years ago

@ccesario This file https://github.com/ManageIQ/manageiq-ui-classic/blob/60d3dfef59234a8df94af2ec419e8b5ce070f7ff/app/javascript/oldjs/application.js has two lines before loading i18n.js .

require('./miq_global.js'); require('./jquery_overrides.js');

Ideally it should work. we are also calling ManageIQ variable in https://github.com/ManageIQ/manageiq-ui-classic/blob/60d3dfef59234a8df94af2ec419e8b5ce070f7ff/app/javascript/oldjs/jquery_overrides.js. want to check if the variable is loading in this file. Unfortunately, i am not able to reproduce this bug . So need your help in debugging.

Could you add this code in jquery_overrides.js file and see if these prints out.

function func1() {
  console.log('func1 in jquery overrides');
  console.log("test2 ManageIQ",window.ManageIQ);
  console.log("test3 ManageIQ",ManageIQ);
}
func1();

@kavyanekkalapu

Sure, I removed the preview include that I did into /opt/manageiq/manageiq-gemset/bundler/gems/manageiq-ui-classic-a3025406b60d/app/javascript/oldjs/i18n.js - require('./miq_global.js'); and now I changed the file according you suggested

  # diff -uNr  /opt/manageiq/manageiq-gemset/bundler/gems/manageiq-ui-classic-a3025406b60d/app/javascript/oldjs/jquery_overrides.js.ORI /opt/manageiq/manageiq-gemset/bundler/gems/manageiq-ui-classic-a3025406b60d/app/javascript/oldjs/jquery_overrides.js
--- /opt/manageiq/manageiq-gemset/bundler/gems/manageiq-ui-classic-a3025406b60d/app/javascript/oldjs/jquery_overrides.js.ORI    2022-01-07 13:54:31.186275860 -0300
+++ /opt/manageiq/manageiq-gemset/bundler/gems/manageiq-ui-classic-a3025406b60d/app/javascript/oldjs/jquery_overrides.js        2022-01-07 13:53:32.233116260 -0300
@@ -45,3 +45,11 @@
     }),
   },
 });
+
+
+function func1() {
+  console.log('func1 in jquery overrides');
+  console.log("test2 ManageIQ",window.ManageIQ);
+  console.log("test3 ManageIQ",ManageIQ);
+}
+func1();

But I think that is not loaded, look the images after changes

image

image

kavyanekkalapu commented 2 years ago

@ccesario Interesting that it did not even get to that file. Your application.js looks same as https://github.com/ManageIQ/manageiq-ui-classic/blob/60d3dfef59234a8df94af2ec419e8b5ce070f7ff/app/javascript/oldjs/application.js ?

ccesario commented 2 years ago

@ccesario Interesting that it did not even get to that file. Your application.js looks same as https://github.com/ManageIQ/manageiq-ui-classic/blob/60d3dfef59234a8df94af2ec419e8b5ce070f7ff/app/javascript/oldjs/application.js ?

@kavyanekkalapu Yes, is the same!!


# cat /opt/manageiq/manageiq-gemset/bundler/gems/manageiq-ui-classic-a3025406b60d/app/javascript/oldjs/application.js
require('./miq_global.js');
require('./jquery_overrides.js');

// locales
require('./i18n.js');
require('./gettextCatalog.js');

// angular
require('./miq_api.js');
require('./miq_angular_application.js');
require('./controllers/');
require('./directives/');
require('./components/');
require('./services/');

require('./miq_browser_detect.js');
require('./miq_application.js');
require('./miq_flash.js');
require('./miq_change_stored_password.js');
require('./miq_qe.js');
require('./git_import.js');
require('./import.js');
require('./automate_import_export.js');
require('./miq_c3_config.js');
require('./miq_ujs_bindings.js');
require('./miq_tree.js');
require('./miq_formatters.js');
require('./miq_grid.js');
require('./miq_list_grid.js');
require('./miq_toolbar.js');
require('./miq_c3.js');
require('./miq_explorer.js');
require('./miq_timeline.js');
Fryguy commented 2 years ago

If I recall, the remote_console window itself does not load the application, but does reuse some helper javascripts. Do you ses application.js in the remote console's window?

Fryguy commented 2 years ago

When we launch the console it's done here: https://github.com/ManageIQ/manageiq-ui-classic/blob/83070ce0a3b7db143f9ea5ffa7ff9f37b5ce4f45/app/controllers/vm_remote.rb#L41 . Notice the layout => false, which will prevent loading the application. Instead it loads the remote_console directly here: https://github.com/ManageIQ/manageiq-ui-classic/blob/83070ce0a3b7db143f9ea5ffa7ff9f37b5ce4f45/app/views/layouts/remote_console.html.haml , but after that I'm not exactly sure what's happening.

ccesario commented 2 years ago

If I recall, the remote_console window itself does not load the application, but does reuse some helper javascripts. Do you ses application.js in the remote console's window?

@Fryguy No, I can't see

Fryguy commented 2 years ago

Ok that's what I expected. Spoke with kavya over voice just now to show her what I think is happening, and she is going to put up a PR to possibly fix.

ccesario commented 2 years ago

When we launch the console it's done here:

https://github.com/ManageIQ/manageiq-ui-classic/blob/83070ce0a3b7db143f9ea5ffa7ff9f37b5ce4f45/app/controllers/vm_remote.rb#L41

. Notice the layout => false, which will prevent loading the application. Instead it loads the remote_console directly here: https://github.com/ManageIQ/manageiq-ui-classic/blob/83070ce0a3b7db143f9ea5ffa7ff9f37b5ce4f45/app/views/layouts/remote_console.html.haml , but after that I'm not exactly sure what's happening.

@Fryguy

Looking this file

# cat  /opt/manageiq/manageiq-gemset/bundler/gems/manageiq-ui-classic-a3025406b60d/app/views/layouts/remote_console.html.haml
= render :partial => 'layouts/doctype'
%html{:lang => I18n.locale.to_s.sub('-', '_')}
  %head
    %title
      = _('%{product_name} HTML5 Remote Console') % {:product_name => Vmdb::Appliance.PRODUCT_NAME}
    = miq_favicon_link_tag
    = stylesheet_link_tag 'application'
    = stylesheet_link_tag '/custom.css'
    -# Load the required JS based on the console type
    = javascript_essential_dependencies
    = javascript_pack_tag("manageiq-ui-classic/remote_consoles_#{@console[:type]}.js")
  %body
    #remote-console{'data-url' => @console[:url], 'data-secret' => @console[:secret], 'data-is-vcloud' => @console[:is_vcloud], 'data-vmx' => @console[:vmx]}
    %footer.remote-console
      .pull-left
        %span#console-type.label.label-info= j @console[:type].upcase
        %span#connection-status.label.label-warning= _('Connecting')
      .pull-right
        - if @console[:type] == 'webmks'
          = select_tag(:keymap, options_for_select(VmwareConsoleHelper::KEYBOARD_LAYOUTS), :id => 'keymap')
        %button#ctrlaltdel.btn.btn-default{:title => _('Send CTRL+ALT+DEL')}
          %i.fa.fa-keyboard-o
        %button#fullscreen.btn.btn-default{:title => _('Toggle Fullscreen')}
          %i.fa.fa-arrows-alt

In the line = javascript_pack_tag("manageiq-ui-classic/remote_consoles_#{@console[:type]}.js") I suppose that this load this file /opt/manageiq/manageiq-gemset/bundler/gems/manageiq-ui-classic-a3025406b60d/app/javascript/packs/remote_consoles_webmks.js. And it does not require the miq_global.js file or other needed.

# cat /opt/manageiq/manageiq-gemset/bundler/gems/manageiq-ui-classic-a3025406b60d/app/javascript/packs/remote_consoles_webmks.js
window.$ = window.jQuery = require('jquery');
require('jquery-ui');
require('jquery-ui/ui/unique-id.js');
require('jquery-ui/ui/widget.js');
require('jquery-ui/ui/widgets/dialog.js');
require('jquery-ui/ui/widgets/button.js');
require('../oldjs/i18n.js');
require('../oldjs/remote_console.js');

/* global WMKS */

$(function() {
  // WebMKS cannot be a part of the asset pipeline, therefore, it has to be loaded with this hack
  var WEBMKS_JS_PATH = '/webmks/wmks.min.js';
  // Test if the file exists under the given path
  fetch(WEBMKS_JS_PATH, {
    method: 'HEAD',
    cache: 'no-cache',
  }).then(function(response) {
    return new Promise(function(resolve, reject) {
      if (!response.ok) {
        // Reject the promise if there's any error with the request, i.e. the file doesn't exist
        reject();
      } else {
        // Create a <link> tag that loads the CSS file and append it to the page
        var link = document.createElement('link');
        link.rel = 'stylesheet';
        link.type = 'text/css';
        link.href = '/webmks/css/wmks-all.css';
        document.head.appendChild(link);

        // Create a <script> tag that loads the JS file
        var script = document.createElement('script');
        script.src = WEBMKS_JS_PATH;
        // Set an onload function that resolves the promise
        script.onload = function() {
          resolve();
        };
        // Append the <script> tag to the page
        document.head.appendChild(script);
      }
    });
  }).then(function() {
    // Set up the remote console after the JS is loaded
    var host = window.location.hostname;
    var encrypt = window.location.protocol === 'https:';
    var port = encrypt ? 443 : 80;
    if (window.location.port) {
      port = window.location.port;
    }
    var proto = encrypt ? 'wss' : 'ws';

    var options = {};
    // vCloud requires some extra attributes
    if ($('#remote-console').attr('data-is-vcloud')) {
      options.VCDProxyHandshakeVmxPath = $('#remote-console').attr('data-vmx');
      options.enableUint8Utf8 = true;
    }

    var wmks = WMKS.createWMKS('remote-console', options).register(WMKS.CONST.Events.CONNECTION_STATE_CHANGE, function(event, data) {
      if (data.state === WMKS.CONST.ConnectionState.CONNECTED) {
        $('#connection-status').text(__('Connected'));
      }
    });

    wmks.connect(proto + '://' + host + ':' + port + '/' + $('#remote-console').attr('data-url'));

    $('#ctrlaltdel').on('click', function() {
      wmks.sendCAD();
    });

    $('#keymap').on('change', function() {
      wmks.setOption('keyboardLayoutId', this.value);
    });
  }).catch(function() {
    $('#remote-console').html(__('The appliance has no access to the assets required to run the WebMKS console. For more info please see the documentation.'));
  });
});
Fryguy commented 2 years ago

@ccesario Can you apply the changes in #8011 and see if that fixes your issues?