<commit_before>// Licensed to Cloudera, Inc. under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  Cloudera, Inc. licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import $ from 'jquery';
import _ from 'lodash';
import ko from 'knockout';
import page from 'page';

import hueUtils from 'utils/hueUtils';
import huePubSub from 'utils/huePubSub';
import I18n from 'utils/i18n';

class OnePageViewModel {
  constructor() {
    const self = this;

    self.embeddable_cache = {};
    self.currentApp = ko.observable();
    self.currentContextParams = ko.observable(null);
    self.currentQueryString = ko.observable(null);
    self.isLoadingEmbeddable = ko.observable(false);
    self.extraEmbeddableURLParams = ko.observable('');

    self.getActiveAppViewModel = function(callback) {
      const checkInterval = window.setInterval(() => {
        const $koElement = $('#' + self.currentApp() + 'Components');
        if (
          $koElement.length > 0 &&
          ko.dataFor($koElement[0]) &&
          !(ko.dataFor($koElement[0]) instanceof OnePageViewModel)
        ) {
          window.clearInterval(checkInterval);
          callback(ko.dataFor($koElement[0]));
        }
      }, 25);
    };

    self.changeEditorType = function(type) {
      self.getActiveAppViewModel(viewModel => {
        if (viewModel && viewModel.selectedNotebook) {
          hueUtils.waitForObservable(viewModel.selectedNotebook, () => {
            if (viewModel.editorType() !== type) {
              viewModel.selectedNotebook().selectedSnippet(type);
              viewModel.editorType(type);
              viewModel.newNotebook(type);
            }
          });
        }
      });
    };

    self.currentApp.subscribe(newApp => {
      huePubSub.publish('set.current.app.name', newApp);
      self.getActiveAppViewModel(viewModel => {
        huePubSub.publish('set.current.app.view.model', viewModel);
      });
    });

    huePubSub.subscribe('get.current.app.view.model', () => {
      self.getActiveAppViewModel(viewModel => {
        huePubSub.publish('set.current.app.view.model', viewModel);
      });
    });

    huePubSub.subscribe('get.current.app.name', () => {
      huePubSub.publish('set.current.app.name', self.currentApp());
    });

    huePubSub.subscribe('open.editor.query', uuid => {
      self.loadApp('editor');
      self.getActiveAppViewModel(viewModel => {
        viewModel.openNotebook(uuid);
      });
    });

    huePubSub.subscribe('open.importer.query', data => {
      self.loadApp('importer');
      self.getActiveAppViewModel(viewModel => {
        hueUtils.waitForVariable(viewModel.createWizard, () => {
          hueUtils.waitForVariable(viewModel.createWizard.prefill, () => {
            viewModel.createWizard.prefill.source_type(data['source_type']);
            viewModel.createWizard.prefill.target_type(data['target_type']);
            viewModel.createWizard.prefill.target_path(data['target_path']);
            viewModel.createWizard.destination.outputFormat(data['target_type']);
          });
          hueUtils.waitForVariable(viewModel.createWizard.source.query, () => {
            viewModel.createWizard.source.query({ id: data.id, name: data.name });
          });
          hueUtils.waitForVariable(viewModel.createWizard.loadSampleData, () => {
            viewModel.createWizard.loadSampleData(data);
          });
        });
      });
    });

    huePubSub.subscribe('resize.form.actions', () => {
      document.styleSheets[0].addRule(
        '.form-actions',
        'width: ' + $('.page-content').width() + 'px'
      );
      if ($('.content-panel:visible').length > 0) {
        document.styleSheets[0].addRule('.form-actions', 'margin-left: -11px !important');
      }
    });

    huePubSub.subscribe('split.panel.resized', () => {
      huePubSub.publish('resize.form.actions');
      huePubSub.publish('resize.plotly.chart');
    });

    huePubSub.publish('resize.form.actions');

    huePubSub.subscribe('open.editor.new.query', statementOptions => {
      self.loadApp('editor'); // Should open in Default

      self.getActiveAppViewModel(viewModel => {
        const editorType = statementOptions['type'] || 'hive'; // Next: use file extensions and default type of Editor for SQL
        viewModel.newNotebook(editorType, () => {
          self.changeEditorType(editorType);

          if (statementOptions['statementPath']) {
            viewModel
              .selectedNotebook()
              .snippets()[0]
              .statementType(statementOptions['statementType']);
            viewModel
              .selectedNotebook()
              .snippets()[0]
              .statementPath(statementOptions['statementPath']);
          }
          if (statementOptions['directoryUuid']) {
            viewModel.selectedNotebook().directoryUuid(statementOptions['directoryUuid']);
          }
        });
      });
    });

    const loadedJs = [];
    const loadedCss = [];
    const loadedApps = [];

    $('script[src]').each(function() {
      loadedJs.push($(this).attr('src'));
    });

    $('link[href]').each(function() {
      loadedCss.push($(this).attr('href'));
    });

    const loadScript = function(scriptUrl) {
      const deferred = $.Deferred();
      $.ajax({
        url: scriptUrl,
        converters: {
          'text script': function(text) {
            return text;
          }
        }
      })
        .done(contents => {
          loadedJs.push(scriptUrl);
          deferred.resolve({ url: scriptUrl, contents: contents });
        })
        .fail(() => {
          deferred.resolve('');
        });
      return deferred.promise();
    };

    const loadScripts = function(scriptUrls) {
      const promises = [];
      while (scriptUrls.length) {
        const scriptUrl = scriptUrls.shift();
        if (loadedJs.indexOf(scriptUrl) !== -1) {
          continue;
        }
        promises.push(loadScript(scriptUrl));
      }
      return promises;
    };

    const addGlobalCss = function($el) {
      const cssFile = $el.attr('href').split('?')[0];
      if (loadedCss.indexOf(cssFile) === -1) {
        loadedCss.push(cssFile);
        $.ajaxSetup({ cache: true });
        if (window.DEV) {
          $el.attr('href', $el.attr('href') + '?dev=' + Math.random());
        }
        $el.clone().appendTo($('head'));
        $.ajaxSetup({ cache: false });
      }
      $el.remove();
    };

    // Only load CSS and JS files that are not loaded before
    self.processHeaders = function(response) {
      const promise = $.Deferred();
      const $rawHtml = $('<span>').html(response);

      const $allScripts = $rawHtml.find('script[src]');
      const scriptsToLoad = $allScripts
        .map(function() {
          return $(this).attr('src');
        })
        .toArray();
      $allScripts.remove();

      $rawHtml.find('link[href]').each(function() {
        addGlobalCss($(this)); // Also removes the elements;
      });

      $rawHtml.find('a[href]').each(function() {
        let link = $(this).attr('href');
        if (link.startsWith('/') && !link.startsWith('/hue')) {
          link = window.HUE_BASE_URL + '/hue' + link;
        }
        $(this).attr('href', link);
      });

      $rawHtml.unwrap('span');

      const scriptPromises = loadScripts(scriptsToLoad);

      const evalScriptSync = function() {
        if (scriptPromises.length) {
          // Evaluate the scripts in the order they were defined in the page
          const nextScriptPromise = scriptPromises.shift();
          nextScriptPromise.done(scriptDetails => {
            if (scriptDetails.contents) {
              $.globalEval(scriptDetails.contents);
            }
            evalScriptSync();
          });
        } else {
          // All evaluated
          promise.resolve($rawHtml);
        }
      };

      evalScriptSync();
      return promise;
    };

    huePubSub.subscribe('hue4.process.headers', opts => {
      self.processHeaders(opts.response).done(rawHtml => {
        opts.callback(rawHtml);
      });
    });

    self.loadApp = function(app, loadDeep) {
      if (self.currentApp() === 'editor' && $('#editorComponents').length) {
        const vm = ko.dataFor($('#editorComponents')[0]);
        if (vm.isPresentationMode()) {
          vm.selectedNotebook().isPresentationMode(false);
        }
      }

      if (
        self.currentApp() === 'editor' &&
        self.embeddable_cache['editor'] &&
        !$('#editorComponents').length
      ) {
        self.embeddable_cache['editor'] = undefined;<commit_msg>HUE-9082 [frontend] Prevent the same app from initializing twice<commit_after>// Licensed to Cloudera, Inc. under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  Cloudera, Inc. licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import $ from 'jquery';
import _ from 'lodash';
import ko from 'knockout';
import page from 'page';

import hueUtils from 'utils/hueUtils';
import huePubSub from 'utils/huePubSub';
import I18n from 'utils/i18n';

class OnePageViewModel {
  constructor() {
    const self = this;

    self.embeddable_cache = {};
    self.currentApp = ko.observable();
    self.currentContextParams = ko.observable(null);
    self.currentQueryString = ko.observable(null);
    self.isLoadingEmbeddable = ko.observable(false);
    self.extraEmbeddableURLParams = ko.observable('');

    self.getActiveAppViewModel = function(callback) {
      const checkInterval = window.setInterval(() => {
        const $koElement = $('#' + self.currentApp() + 'Components');
        if (
          $koElement.length > 0 &&
          ko.dataFor($koElement[0]) &&
          !(ko.dataFor($koElement[0]) instanceof OnePageViewModel)
        ) {
          window.clearInterval(checkInterval);
          callback(ko.dataFor($koElement[0]));
        }
      }, 25);
    };

    self.changeEditorType = function(type) {
      self.getActiveAppViewModel(viewModel => {
        if (viewModel && viewModel.selectedNotebook) {
          hueUtils.waitForObservable(viewModel.selectedNotebook, () => {
            if (viewModel.editorType() !== type) {
              viewModel.selectedNotebook().selectedSnippet(type);
              viewModel.editorType(type);
              viewModel.newNotebook(type);
            }
          });
        }
      });
    };

    self.currentApp.subscribe(newApp => {
      huePubSub.publish('set.current.app.name', newApp);
      self.getActiveAppViewModel(viewModel => {
        huePubSub.publish('set.current.app.view.model', viewModel);
      });
    });

    huePubSub.subscribe('get.current.app.view.model', () => {
      self.getActiveAppViewModel(viewModel => {
        huePubSub.publish('set.current.app.view.model', viewModel);
      });
    });

    huePubSub.subscribe('get.current.app.name', () => {
      huePubSub.publish('set.current.app.name', self.currentApp());
    });

    huePubSub.subscribe('open.editor.query', uuid => {
      self.loadApp('editor');
      self.getActiveAppViewModel(viewModel => {
        viewModel.openNotebook(uuid);
      });
    });

    huePubSub.subscribe('open.importer.query', data => {
      self.loadApp('importer');
      self.getActiveAppViewModel(viewModel => {
        hueUtils.waitForVariable(viewModel.createWizard, () => {
          hueUtils.waitForVariable(viewModel.createWizard.prefill, () => {
            viewModel.createWizard.prefill.source_type(data['source_type']);
            viewModel.createWizard.prefill.target_type(data['target_type']);
            viewModel.createWizard.prefill.target_path(data['target_path']);
            viewModel.createWizard.destination.outputFormat(data['target_type']);
          });
          hueUtils.waitForVariable(viewModel.createWizard.source.query, () => {
            viewModel.createWizard.source.query({ id: data.id, name: data.name });
          });
          hueUtils.waitForVariable(viewModel.createWizard.loadSampleData, () => {
            viewModel.createWizard.loadSampleData(data);
          });
        });
      });
    });

    huePubSub.subscribe('resize.form.actions', () => {
      document.styleSheets[0].addRule(
        '.form-actions',
        'width: ' + $('.page-content').width() + 'px'
      );
      if ($('.content-panel:visible').length > 0) {
        document.styleSheets[0].addRule('.form-actions', 'margin-left: -11px !important');
      }
    });

    huePubSub.subscribe('split.panel.resized', () => {
      huePubSub.publish('resize.form.actions');
      huePubSub.publish('resize.plotly.chart');
    });

    huePubSub.publish('resize.form.actions');

    huePubSub.subscribe('open.editor.new.query', statementOptions => {
      self.loadApp('editor'); // Should open in Default

      self.getActiveAppViewModel(viewModel => {
        const editorType = statementOptions['type'] || 'hive'; // Next: use file extensions and default type of Editor for SQL
        viewModel.newNotebook(editorType, () => {
          self.changeEditorType(editorType);

          if (statementOptions['statementPath']) {
            viewModel
              .selectedNotebook()
              .snippets()[0]
              .statementType(statementOptions['statementType']);
            viewModel
              .selectedNotebook()
              .snippets()[0]
              .statementPath(statementOptions['statementPath']);
          }
          if (statementOptions['directoryUuid']) {
            viewModel.selectedNotebook().directoryUuid(statementOptions['directoryUuid']);
          }
        });
      });
    });

    const loadedJs = [];
    const loadedCss = [];
    const loadedApps = [];

    $('script[src]').each(function() {
      loadedJs.push($(this).attr('src'));
    });

    $('link[href]').each(function() {
      loadedCss.push($(this).attr('href'));
    });

    const loadScript = function(scriptUrl) {
      const deferred = $.Deferred();
      $.ajax({
        url: scriptUrl,
        converters: {
          'text script': function(text) {
            return text;
          }
        }
      })
        .done(contents => {
          loadedJs.push(scriptUrl);
          deferred.resolve({ url: scriptUrl, contents: contents });
        })
        .fail(() => {
          deferred.resolve('');
        });
      return deferred.promise();
    };

    const loadScripts = function(scriptUrls) {
      const promises = [];
      while (scriptUrls.length) {
        const scriptUrl = scriptUrls.shift();
        if (loadedJs.indexOf(scriptUrl) !== -1) {
          continue;
        }
        promises.push(loadScript(scriptUrl));
      }
      return promises;
    };

    const addGlobalCss = function($el) {
      const cssFile = $el.attr('href').split('?')[0];
      if (loadedCss.indexOf(cssFile) === -1) {
        loadedCss.push(cssFile);
        $.ajaxSetup({ cache: true });
        if (window.DEV) {
          $el.attr('href', $el.attr('href') + '?dev=' + Math.random());
        }
        $el.clone().appendTo($('head'));
        $.ajaxSetup({ cache: false });
      }
      $el.remove();
    };

    // Only load CSS and JS files that are not loaded before
    self.processHeaders = function(response) {
      const promise = $.Deferred();
      const $rawHtml = $('<span>').html(response);

      const $allScripts = $rawHtml.find('script[src]');
      const scriptsToLoad = $allScripts
        .map(function() {
          return $(this).attr('src');
        })
        .toArray();
      $allScripts.remove();

      $rawHtml.find('link[href]').each(function() {
        addGlobalCss($(this)); // Also removes the elements;
      });

      $rawHtml.find('a[href]').each(function() {
        let link = $(this).attr('href');
        if (link.startsWith('/') && !link.startsWith('/hue')) {
          link = window.HUE_BASE_URL + '/hue' + link;
        }
        $(this).attr('href', link);
      });

      $rawHtml.unwrap('span');

      const scriptPromises = loadScripts(scriptsToLoad);

      const evalScriptSync = function() {
        if (scriptPromises.length) {
          // Evaluate the scripts in the order they were defined in the page
          const nextScriptPromise = scriptPromises.shift();
          nextScriptPromise.done(scriptDetails => {
            if (scriptDetails.contents) {
              $.globalEval(scriptDetails.contents);
            }
            evalScriptSync();
          });
        } else {
          // All evaluated
          promise.resolve($rawHtml);
        }
      };

      evalScriptSync();
      return promise;
    };

    huePubSub.subscribe('hue4.process.headers', opts => {
      self.processHeaders(opts.response).done(rawHtml => {
        opts.callback(rawHtml);
      });
    });

    let loadAppTimeout = -1;
    self.loadApp = (app, loadDeep) => {
      // This prevents loading an app twice when the URL is changed multiple times in one operation
      window.clearTimeout(loadAppTimeout);
      loadAppTimeout = window.setTimeout(() => {
        self.loadAppThrottled(app, loadDeep);
      }, 0);
    };

    self.loadAppThrottled = (app, loadDeep) => {
      if (self.currentApp() === 'editor' && $('#editorComponents').length) {
        const vm = ko.dataFor($('#editorComponents')[0]);
        if (vm.isPresentationMode()) {
          vm.selectedNotebook().isPresentationMode(false);
        }
      }

      if (
        self.currentApp() === 'editor' &&
        self.embeddable_cache['editor'] &&
        !$('#editorComponents').length
      ) {
        self.embeddable_cache['editor'] = undefined;
{'fraction_non_alphanumeric': 0.14933575201408525, 'fraction_numerical': 0.0030944886090807236, 'mean_word_length': 2.4386351128233352, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 64, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4884312', 'n_tokens_mistral': 5410, 'n_tokens_neox': 5301, 'n_words': 959}