Browse Source

[frontend] Gather all web component definitions under /webComponents

Johan Åhlén 4 năm trước cách đây
mục cha
commit
63abe58285

+ 1 - 1
desktop/core/src/desktop/js/hue.js

@@ -57,7 +57,7 @@ import MultiLineEllipsisHandler from 'utils/multiLineEllipsisHandler';
 import sqlUtils from 'sql/sqlUtils';
 import sqlWorkerHandler from 'sql/sqlWorkerHandler';
 
-import 'components/icons/HueIconsWebComponent';
+import 'webComponents/HueIcons';
 import 'components/sidebar/HueSidebarWebComponent';
 import 'components/assist/AssistPanelWebComponent';
 

+ 17 - 4
desktop/core/src/desktop/js/vue/webComponentWrap.ts

@@ -21,17 +21,30 @@ export interface HueComponentOptions<T extends Component> extends ComponentOptio
   hueBaseUrl?: string;
 }
 
-const isRegistered = function (tag: string): boolean {
-  return window.customElements.get(tag) !== undefined;
-};
+const isRegistered = (tag: string): boolean => !!window.customElements?.get(tag);
 
 export const wrap = <T extends Component>(
   tag: string,
   component: { new (): T },
   options?: WebComponentOptions
 ): void => {
-  if (!isRegistered(tag)) {
+  if (!isRegistered(tag) && window.customElements) {
     const customElement: CustomElementConstructor = wrapper(component, createApp, h, options);
     window.customElements.define(tag, customElement);
   }
 };
+
+export const isDefined = async (tag: string): Promise<void> => {
+  new Promise(async (resolve, reject) => {
+    if (!window.customElements) {
+      reject('Web components are not supported!');
+    }
+    try {
+      await window.customElements.whenDefined(tag);
+    } catch (e) {
+      reject(e);
+      return;
+    }
+    resolve();
+  });
+};

+ 11 - 3
desktop/core/src/desktop/js/components/icons/HueIconsWebComponent.ts → desktop/core/src/desktop/js/webComponents/HueIcons.ts

@@ -14,7 +14,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import { wrap } from 'vue/webComponentWrap';
-import HueIcons from './HueIcons.vue';
+import 'regenerator-runtime/runtime';
 
-wrap('hue-icons-web-component', HueIcons);
+import HueIcons from 'components/icons/HueIcons.vue';
+import { isDefined, wrap } from 'vue/webComponentWrap';
+
+const NAME = 'hue-icons';
+
+wrap(NAME, HueIcons);
+
+const hueIconsDefined = async (): Promise<void> => await isDefined(NAME);
+
+export default hueIconsDefined;

+ 11 - 6
desktop/core/src/desktop/js/apps/editor/components/sqlScratchpad/SqlScratchpadWebComponent.d.ts → desktop/core/src/desktop/js/webComponents/QueryEditor.ts

@@ -14,10 +14,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-declare const _default: {
-  login(username: string, password: string): Promise<void>;
-  setBaseUrl(baseUrl: string): void;
-  setBearerToken(bearerToken: string): void;
-};
+import 'regenerator-runtime/runtime';
 
-export default _default;
+import AceEditor from 'apps/editor/components/aceEditor/AceEditor.vue';
+import { isDefined, wrap } from 'vue/webComponentWrap';
+
+const NAME = 'query-editor';
+
+wrap(NAME, AceEditor);
+
+const queryEditorDefined = async (): Promise<void> => await isDefined(NAME);
+
+export default queryEditorDefined;

+ 5 - 3
desktop/core/src/desktop/js/apps/editor/components/QueryEditorWebComponents.d.ts → desktop/core/src/desktop/js/webComponents/QueryEditorComponents.d.ts

@@ -15,7 +15,7 @@
 // limitations under the License.
 
 import { ConnectorNamespaces, GetOptions } from 'catalog/contextCatalog';
-import { EditorInterpreter, HueConfig } from 'config/types';
+import { Connector, EditorInterpreter, HueConfig } from 'config/types';
 import Executor, { ExecutorOptions } from 'apps/editor/execution/executor';
 import { DataCatalog } from 'catalog/dataCatalog';
 
@@ -24,16 +24,18 @@ export interface HueComponentConfig {
 }
 
 declare const _default: {
+  clearContextCatalogCache(connector: Connector): Promise<void>;
   configure(config: HueComponentConfig): void;
-  setBaseUrl(baseUrl: string): void;
-  setBearerToken(bearerToken: string): void;
   createExecutor(options: ExecutorOptions): Executor;
   dataCatalog: DataCatalog;
   findEditorConnector(
     connectorTest: (connector: EditorInterpreter) => boolean
   ): EditorInterpreter | undefined;
   getNamespaces(options: GetOptions): Promise<ConnectorNamespaces>;
+  isQueryEditorComponentsDefined(): Promise<void>;
   refreshConfig(hueBaseUrl?: string): Promise<HueConfig>;
+  setBaseUrl(baseUrl: string): void;
+  setBearerToken(bearerToken: string): void;
 };
 
 export default _default;

+ 25 - 22
desktop/core/src/desktop/js/apps/editor/components/QueryEditorWebComponents.ts → desktop/core/src/desktop/js/webComponents/QueryEditorComponents.ts

@@ -14,33 +14,22 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import ExecutableProgressBar from './ExecutableProgressBar.vue';
-import QueryHistoryTable from './QueryHistoryTable.vue';
-import AceEditor from './aceEditor/AceEditor.vue';
-import ResultTable from './result/ResultTable.vue';
-import Executor, { ExecutorOptions } from '../execution/executor';
+import 'regenerator-runtime/runtime';
+
+import hueIconsDefined from './HueIcons';
+import queryEditorDefined from './QueryEditor';
+import queryEditorHistoryTableDefined from './QueryEditorHistoryTable';
+import queryEditorExecuteButtonDefined from './QueryEditorExecuteButton';
+import queryEditorLimitInputDefined from './QueryEditorLimitInput';
+import queryEditorResultTableDefined from './QueryEditorResultTable';
+import queryEditorProgressBarDefined from './QueryEditorProgressBar';
+import sqlContextSelectorDefined from './SqlContextSelector';
 import { setBaseUrl, setBearerToken } from 'api/utils';
-import ExecuteButton from 'apps/editor/components/ExecuteButton.vue';
-import ExecuteLimitInput from 'apps/editor/components/ExecuteLimitInput.vue';
-import SqlAssistPanel from 'components/assist/SqlAssistPanel.vue';
-import HueIcons from 'components/icons/HueIcons.vue';
-import SqlContextSelector from 'components/SqlContextSelector.vue';
+import Executor, { ExecutorOptions } from 'apps/editor/execution/executor';
 import { getNamespaces } from 'catalog/contextCatalog';
 import dataCatalog from 'catalog/dataCatalog';
 import { findEditorConnector, refreshConfig } from 'config/hueConfig';
 import { Connector } from 'config/types';
-import { wrap } from 'vue/webComponentWrap';
-import 'utils/json.bigDataParse';
-
-wrap('hue-icons', HueIcons);
-wrap('query-editor', AceEditor);
-wrap('query-editor-execute-button', ExecuteButton);
-wrap('query-editor-history-table', QueryHistoryTable);
-wrap('query-editor-limit-input', ExecuteLimitInput);
-wrap('query-editor-progress-bar', ExecutableProgressBar);
-wrap('query-editor-result-table', ResultTable);
-wrap('sql-assist-panel', SqlAssistPanel);
-wrap('sql-context-selector', SqlContextSelector);
 
 export interface HueComponentConfig {
   baseUrl?: string;
@@ -58,6 +47,19 @@ const clearContextCatalogCache = async (connector: Connector): Promise<void> =>
   await getNamespaces({ connector, clearCache: true });
 };
 
+const isQueryEditorComponentsDefined = async (): Promise<void> => {
+  await Promise.all([
+    hueIconsDefined(),
+    queryEditorDefined(),
+    queryEditorHistoryTableDefined(),
+    queryEditorExecuteButtonDefined(),
+    queryEditorLimitInputDefined(),
+    queryEditorResultTableDefined(),
+    queryEditorProgressBarDefined(),
+    sqlContextSelectorDefined()
+  ]);
+};
+
 export default {
   clearContextCatalogCache,
   configure,
@@ -65,6 +67,7 @@ export default {
   dataCatalog,
   findEditorConnector,
   getNamespaces,
+  isQueryEditorComponentsDefined,
   refreshConfig,
   setBaseUrl,
   setBearerToken

+ 28 - 0
desktop/core/src/desktop/js/webComponents/QueryEditorExecuteButton.ts

@@ -0,0 +1,28 @@
+// 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 'regenerator-runtime/runtime';
+
+import ExecuteButton from 'apps/editor/components/ExecuteButton.vue';
+import { isDefined, wrap } from 'vue/webComponentWrap';
+
+const NAME = 'query-editor-execute-button';
+
+wrap(NAME, ExecuteButton);
+
+const queryEditorDefined = async (): Promise<void> => await isDefined(NAME);
+
+export default queryEditorDefined;

+ 28 - 0
desktop/core/src/desktop/js/webComponents/QueryEditorHistoryTable.ts

@@ -0,0 +1,28 @@
+// 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 'regenerator-runtime/runtime';
+
+import QueryHistoryTable from 'apps/editor/components/QueryHistoryTable.vue';
+import { isDefined, wrap } from 'vue/webComponentWrap';
+
+const NAME = 'query-editor-history-table';
+
+wrap(NAME, QueryHistoryTable);
+
+const queryEditorHistoryTableDefined = async (): Promise<void> => await isDefined(NAME);
+
+export default queryEditorHistoryTableDefined;

+ 28 - 0
desktop/core/src/desktop/js/webComponents/QueryEditorLimitInput.ts

@@ -0,0 +1,28 @@
+// 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 'regenerator-runtime/runtime';
+
+import ExecuteLimitInput from 'apps/editor/components/ExecuteLimitInput.vue';
+import { isDefined, wrap } from 'vue/webComponentWrap';
+
+const NAME = 'query-editor-limit-input';
+
+wrap(NAME, ExecuteLimitInput);
+
+const queryEditorLimitInputDefined = async (): Promise<void> => await isDefined(NAME);
+
+export default queryEditorLimitInputDefined;

+ 28 - 0
desktop/core/src/desktop/js/webComponents/QueryEditorProgressBar.ts

@@ -0,0 +1,28 @@
+// 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 'regenerator-runtime/runtime';
+
+import ExecutableProgressBar from 'apps/editor/components/ExecutableProgressBar.vue';
+import { isDefined, wrap } from 'vue/webComponentWrap';
+
+const NAME = 'query-editor-progress-bar';
+
+wrap(NAME, ExecutableProgressBar);
+
+const executableProgressBarDefined = async (): Promise<void> => await isDefined(NAME);
+
+export default executableProgressBarDefined;

+ 28 - 0
desktop/core/src/desktop/js/webComponents/QueryEditorResultTable.ts

@@ -0,0 +1,28 @@
+// 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 'regenerator-runtime/runtime';
+
+import ResultTable from 'apps/editor/components/result/ResultTable.vue';
+import { isDefined, wrap } from 'vue/webComponentWrap';
+
+const NAME = 'query-editor-result-table';
+
+wrap(NAME, ResultTable);
+
+const queryEditorResultTableDefined = async (): Promise<void> => await isDefined(NAME);
+
+export default queryEditorResultTableDefined;

+ 28 - 0
desktop/core/src/desktop/js/webComponents/SqlContextSelector.ts

@@ -0,0 +1,28 @@
+// 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 'regenerator-runtime/runtime';
+
+import SqlContextSelector from 'components/SqlContextSelector.vue';
+import { isDefined, wrap } from 'vue/webComponentWrap';
+
+const NAME = 'sql-context-selector';
+
+wrap(NAME, SqlContextSelector);
+
+const sqlContextSelectorDefined = async (): Promise<void> => await isDefined(NAME);
+
+export default sqlContextSelectorDefined;

+ 23 - 0
desktop/core/src/desktop/js/webComponents/SqlScratchpad.d.ts

@@ -0,0 +1,23 @@
+// 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.
+
+declare const login: (username: string, password: string) => Promise<void>;
+declare const isSqlScratchpadDefined: () => Promise<void>;
+declare const setBaseUrl: (newBaseUrl: string) => void;
+declare const setBearerToken: (newBearerToken: string) => void;
+
+export default isSqlScratchpadDefined;
+export { login, setBaseUrl, setBearerToken };

+ 10 - 9
desktop/core/src/desktop/js/apps/editor/components/sqlScratchpad/SqlScratchpadWebComponent.ts → desktop/core/src/desktop/js/webComponents/SqlScratchpad.ts

@@ -15,19 +15,20 @@
 // limitations under the License.
 
 import 'regenerator-runtime/runtime';
-import SqlScratchpad from './SqlScratchpad.vue';
-import { wrap } from 'vue/webComponentWrap';
+
+import SqlScratchpad from 'apps/editor/components/sqlScratchpad/SqlScratchpad.vue';
 import { post, setBaseUrl, setBearerToken } from 'api/utils';
-import 'utils/json.bigDataParse';
+import { isDefined, wrap } from 'vue/webComponentWrap';
+
+const NAME = 'sql-scratchpad';
 
-wrap('sql-scratchpad', SqlScratchpad);
+wrap(NAME, SqlScratchpad);
 
 // Dup of auth.ts?
 const login = async (username: string, password: string): Promise<void> =>
   post('iam/v1/get/auth-token/', { username, password });
 
-export default {
-  login,
-  setBaseUrl,
-  setBearerToken
-};
+const isSqlScratchpadDefined = async (): Promise<void> => await isDefined(NAME);
+
+export default isSqlScratchpadDefined;
+export { login, setBaseUrl, setBearerToken };

+ 4 - 6
webpack.config.npm.js

@@ -93,10 +93,8 @@ const copySourceConfig = {
 const webComponentsConfig = Object.assign({}, defaultConfig, {
   entry: {
     ErDiagram: [`${JS_ROOT}/components/er-diagram/webcomp.ts`],
-    QueryEditorWebComponents: [`${JS_ROOT}/apps/editor/components/QueryEditorWebComponents.ts`],
-    SqlScratchpadWebComponent: [
-      `${JS_ROOT}/apps/editor/components/sqlScratchpad/SqlScratchpadWebComponent.ts`
-    ]
+    QueryEditorWebComponents: [`${JS_ROOT}/webComponents/QueryEditorComponents.ts`],
+    SqlScratchpadWebComponent: [`${JS_ROOT}/webComponents/SqlScratchpad.ts`]
   },
   output: {
     path: `${DIST_DIR}/lib/components`,
@@ -109,11 +107,11 @@ const webComponentsConfig = Object.assign({}, defaultConfig, {
     new CopyWebpackPlugin({
       patterns: [
         {
-          from: `${JS_ROOT}/apps/editor/components/QueryEditorWebComponents.d.ts`,
+          from: `${JS_ROOT}/webComponents/QueryEditorComponents.d.ts`,
           to: `${DIST_DIR}/lib/components`
         },
         {
-          from: `${JS_ROOT}/apps/editor/components/sqlScratchpad/SqlScratchpadWebComponent.d.ts`,
+          from: `${JS_ROOT}/webComponents/SqlScratchpad.d.ts`,
           to: `${DIST_DIR}/lib/components`
         }
       ]