Skip to content

Commit 4704ac2

Browse files
JohanAhlenromainr
authored andcommitted
[frontend] Add a complete sql-scratchpad web component
This component contains the editor, execute actions, progress bar and the result table in one component
1 parent 9015d51 commit 4704ac2

File tree

5 files changed

+291
-1
lines changed

5 files changed

+291
-1
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
Licensed to Cloudera, Inc. under one
3+
or more contributor license agreements. See the NOTICE file
4+
distributed with this work for additional information
5+
regarding copyright ownership. Cloudera, Inc. licenses this file
6+
to you under the Apache License, Version 2.0 (the
7+
"License"); you may not use this file except in compliance
8+
with the License. You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
*/
18+
19+
@import 'desktop/core/src/desktop/js/components/styles/mixins';
20+
21+
.sql-scratchpad {
22+
position: relative;
23+
width: 100%;
24+
height: 100%;
25+
26+
.sql-scratchpad-container {
27+
@include fillAbsolute;
28+
@include display-flex;
29+
@include flex-direction(column);
30+
overflow: hidden;
31+
32+
.sql-scratchpad-editor {
33+
@include flex(0 1 50%);
34+
}
35+
36+
.sql-scratchpad-progress {
37+
@include flex(0 0 3px);
38+
}
39+
40+
.sql-scratchpad-actions {
41+
@include flex(0 0 25px);
42+
}
43+
44+
.sql-scratchpad-result {
45+
@include flex(0 1 50%);
46+
}
47+
}
48+
}
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
<!--
2+
Licensed to Cloudera, Inc. under one
3+
or more contributor license agreements. See the NOTICE file
4+
distributed with this work for additional information
5+
regarding copyright ownership. Cloudera, Inc. licenses this file
6+
to you under the Apache License, Version 2.0 (the
7+
"License"); you may not use this file except in compliance
8+
with the License. You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
-->
18+
19+
<template>
20+
<div class="sql-scratchpad">
21+
<HueIcons />
22+
<Spinner v-if="loading" spin="true" />
23+
<div v-if="!loading && executor" class="sql-scratchpad-container">
24+
<div class="sql-scratchpad-editor">
25+
<AceEditor
26+
:id="id"
27+
:ace-options="aceOptions"
28+
:executor="executor"
29+
:sql-parser-provider="sqlParserProvider"
30+
:sql-reference-provider="sqlReferenceProvider"
31+
@active-statement-changed="onActiveStatementChanged"
32+
/>
33+
</div>
34+
<div class="sql-scratchpad-progress">
35+
<ExecutableProgressBar :executable="activeExecutable" />
36+
</div>
37+
<div class="sql-scratchpad-actions">
38+
<ExecuteButton :executable="activeExecutable" />
39+
<ExecuteLimitInput :executable="activeExecutable" />
40+
</div>
41+
<div class="sql-scratchpad-result">
42+
<ResultTable :executable="activeExecutable" />
43+
</div>
44+
</div>
45+
<div v-else-if="!loading && !executor">
46+
Failed loading the SQL Scratchpad!
47+
</div>
48+
</div>
49+
</template>
50+
51+
<script lang="ts">
52+
import { defineComponent, onMounted, PropType, ref, toRefs } from 'vue';
53+
import { Ace } from 'ext/ace';
54+
55+
import genericAutocompleteParser from 'parse/sql/generic/genericAutocompleteParser';
56+
import genericSyntaxParser from 'parse/sql/generic/genericSyntaxParser';
57+
import { SqlParserProvider } from 'parse/types';
58+
import { SqlReferenceProvider } from 'sql/reference/types';
59+
60+
import './SqlScratchpad.scss';
61+
import AceEditor from '../aceEditor/AceEditor.vue';
62+
import { ActiveStatementChangedEventDetails } from '../aceEditor/types';
63+
import ExecutableProgressBar from '../ExecutableProgressBar.vue';
64+
import ExecuteButton from '../ExecuteButton.vue';
65+
import ExecuteLimitInput from '../ExecuteLimitInput.vue';
66+
import ResultTable from '../result/ResultTable.vue';
67+
import Executor from '../../execution/executor';
68+
import SqlExecutable from '../../execution/sqlExecutable';
69+
import contextCatalog from 'catalog/contextCatalog';
70+
import HueIcons from 'components/icons/HueIcons.vue';
71+
import Spinner from 'components/Spinner.vue';
72+
import { findEditorConnector, getConfig } from 'config/hueConfig';
73+
import { Compute, Connector, Namespace } from 'config/types';
74+
import { UUID } from 'utils/hueUtils';
75+
76+
export default defineComponent({
77+
name: 'SqlScratchpad',
78+
components: {
79+
Spinner,
80+
HueIcons,
81+
ResultTable,
82+
ExecuteLimitInput,
83+
ExecuteButton,
84+
ExecutableProgressBar,
85+
AceEditor
86+
},
87+
props: {
88+
dialect: {
89+
type: String as PropType<string | null>,
90+
default: null
91+
}
92+
},
93+
setup(props) {
94+
const { dialect } = toRefs(props);
95+
const activeExecutable = ref<SqlExecutable | null>(null);
96+
const executor = ref<Executor | null>(null);
97+
const loading = ref<boolean>(true);
98+
const id = UUID();
99+
100+
const sqlParserProvider: SqlParserProvider = {
101+
getAutocompleteParser: () => Promise.resolve(genericAutocompleteParser),
102+
getSyntaxParser: () => Promise.resolve(genericSyntaxParser)
103+
};
104+
105+
const sqlReferenceProvider: SqlReferenceProvider = {
106+
getReservedKeywords: () => Promise.resolve(new Set<string>()),
107+
getSetOptions: () => Promise.resolve({}),
108+
getUdfCategories: () => Promise.resolve([]),
109+
hasUdfCategories: () => false
110+
};
111+
112+
const aceOptions: Ace.Options = {
113+
showLineNumbers: true,
114+
showGutter: true,
115+
maxLines: null,
116+
minLines: null
117+
};
118+
119+
const initializeExecutor = async (): Promise<void> => {
120+
try {
121+
await getConfig();
122+
} catch {
123+
console.warn('Failed loading Hue config!');
124+
return;
125+
}
126+
127+
const connector = findEditorConnector(
128+
connector => !dialect.value || connector.dialect === dialect.value
129+
);
130+
if (!connector) {
131+
console.warn('No connector found!');
132+
return;
133+
}
134+
135+
try {
136+
const { namespaces } = await contextCatalog.getNamespaces({ connector });
137+
138+
if (!namespaces.length || !namespaces[0].computes.length) {
139+
console.warn('No namespaces or computes found!');
140+
return;
141+
}
142+
143+
const namespace = namespaces[0];
144+
const compute = namespace.computes[0];
145+
146+
executor.value = new Executor({
147+
connector: (() => connector as Connector) as KnockoutObservable<Connector>,
148+
namespace: (() => namespace) as KnockoutObservable<Namespace>,
149+
compute: (() => compute) as KnockoutObservable<Compute>,
150+
database: (() => 'default') as KnockoutObservable<string>
151+
});
152+
} catch {}
153+
};
154+
155+
const onActiveStatementChanged = (event: ActiveStatementChangedEventDetails) => {
156+
if (executor.value) {
157+
executor.value.update(event, false);
158+
activeExecutable.value = executor.value.activeExecutable as SqlExecutable;
159+
}
160+
};
161+
162+
onMounted(async () => {
163+
loading.value = true;
164+
try {
165+
await initializeExecutor();
166+
} catch {}
167+
loading.value = false;
168+
});
169+
170+
return {
171+
aceOptions,
172+
activeExecutable,
173+
executor,
174+
id,
175+
onActiveStatementChanged,
176+
sqlParserProvider,
177+
sqlReferenceProvider
178+
};
179+
}
180+
});
181+
</script>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Licensed to Cloudera, Inc. under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. Cloudera, Inc. licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// 'License'); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing, software
12+
// distributed under the License is distributed on an 'AS IS' BASIS,
13+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
// See the License for the specific language governing permissions and
15+
// limitations under the License.
16+
17+
declare const _default: {
18+
login(username: string, password: string): Promise<void>;
19+
setBaseUrl(baseUrl: string): void;
20+
setBearerToken(bearerToken: string): void;
21+
};
22+
23+
export default _default;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Licensed to Cloudera, Inc. under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. Cloudera, Inc. licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// 'License'); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing, software
12+
// distributed under the License is distributed on an 'AS IS' BASIS,
13+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
// See the License for the specific language governing permissions and
15+
// limitations under the License.
16+
17+
import SqlScratchpad from './SqlScratchpad.vue';
18+
import { wrap } from 'vue/webComponentWrap';
19+
import { post, setBaseUrl, setBearerToken } from 'api/utils';
20+
import 'utils/json.bigDataParse';
21+
22+
wrap('sql-scratchpad', SqlScratchpad);
23+
24+
const login = async (username: string, password: string): Promise<void> =>
25+
post('iam/v1/get/auth-token/', { username, password });
26+
27+
export default {
28+
login,
29+
setBaseUrl,
30+
setBearerToken
31+
};

webpack.config.npm.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,10 @@ const hueConfigLibConfig = Object.assign({}, defaultConfig, {
9393
const webComponentsConfig = Object.assign({}, defaultConfig, {
9494
entry: {
9595
ErDiagram: [`${JS_ROOT}/components/er-diagram/webcomp.ts`],
96-
QueryEditorWebComponents: [`${JS_ROOT}/apps/editor/components/QueryEditorWebComponents.ts`]
96+
QueryEditorWebComponents: [`${JS_ROOT}/apps/editor/components/QueryEditorWebComponents.ts`],
97+
SqlScratchpadWebComponent: [
98+
`${JS_ROOT}/apps/editor/components/sqlScratchpad/SqlScratchpadWebComponent.ts`
99+
]
97100
},
98101
output: {
99102
path: `${DIST_DIR}/lib/components`,
@@ -108,6 +111,10 @@ const webComponentsConfig = Object.assign({}, defaultConfig, {
108111
{
109112
from: `${JS_ROOT}/apps/editor/components/QueryEditorWebComponents.d.ts`,
110113
to: `${DIST_DIR}/lib/components`
114+
},
115+
{
116+
from: `${JS_ROOT}/apps/editor/components/sqlScratchpad/SqlScratchpadWebComponent.d.ts`,
117+
to: `${DIST_DIR}/lib/components`
111118
}
112119
]
113120
})

0 commit comments

Comments
 (0)