You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampark.apache.org by be...@apache.org on 2022/11/07 01:51:30 UTC
[incubator-streampark] branch dev updated: [Improve]: add npm registry and change router menu logic (#1974)
This is an automated email from the ASF dual-hosted git repository.
benjobs pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/incubator-streampark.git
The following commit(s) were added to refs/heads/dev by this push:
new a381406e2 [Improve]: add npm registry and change router menu logic (#1974)
a381406e2 is described below
commit a381406e29a5c72fd892074630dbcfd37f507d28
Author: Sizhu Wang <12...@qq.com>
AuthorDate: Mon Nov 7 09:51:23 2022 +0800
[Improve]: add npm registry and change router menu logic (#1974)
* [Improve]: add npm registry and change router menu logic
* [Fix] license header
---
.../streampark-console-newui/.gitignore | 1 -
streampark-console/streampark-console-newui/.npmrc | 16 ++
.../src/router/helper/routeHelper.ts | 12 +-
.../src/store/modules/permission.ts | 31 ---
.../flink/app/components/AppView/StatisticCard.vue | 60 ++++++
.../src/views/flink/app/components/CustomForm.tsx | 117 +++++++++++
.../src/views/flink/app/components/Dependency.vue | 91 ++++-----
.../src/views/flink/app/components/FlinkSql.vue | 223 +++++++++++++++++++++
.../views/flink/app/components/FlinkSqlHistory.vue | 60 ++++++
.../components/PodTemplate/TemplateButtonGroup.vue | 2 +-
.../src/views/flink/app/hooks/useApp.tsx | 11 +-
.../src/views/flink/app/hooks/useAppTableAction.ts | 22 +-
.../src/views/flink/app/styles/Add.less | 10 +-
.../setting/components/FlinkClusterSetting.vue | 4 +-
.../src/views/system/menu/Menu.vue | 21 +-
.../src/views/system/menu/MenuDrawer.vue | 3 +-
.../src/views/system/menu/menu.data.ts | 39 +---
17 files changed, 573 insertions(+), 150 deletions(-)
diff --git a/streampark-console/streampark-console-newui/.gitignore b/streampark-console/streampark-console-newui/.gitignore
index e6922c46d..dc8b94064 100644
--- a/streampark-console/streampark-console-newui/.gitignore
+++ b/streampark-console/streampark-console-newui/.gitignore
@@ -1,7 +1,6 @@
node_modules
.DS_Store
dist
-.npmrc
.cache
tests/server/static
diff --git a/streampark-console/streampark-console-newui/.npmrc b/streampark-console/streampark-console-newui/.npmrc
new file mode 100644
index 000000000..ec2a37c72
--- /dev/null
+++ b/streampark-console/streampark-console-newui/.npmrc
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF 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
+#
+# https://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.
+
+registry = 'https://registry.npmmirror.com'
diff --git a/streampark-console/streampark-console-newui/src/router/helper/routeHelper.ts b/streampark-console/streampark-console-newui/src/router/helper/routeHelper.ts
index ec37773b6..57df5c84f 100644
--- a/streampark-console/streampark-console-newui/src/router/helper/routeHelper.ts
+++ b/streampark-console/streampark-console-newui/src/router/helper/routeHelper.ts
@@ -42,14 +42,15 @@ function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) {
if (!item.component && item.meta?.frameSrc) {
item.component = 'IFRAME';
}
- const { component, name } = item;
- const { children } = item;
+ const { component, name, children } = item;
if (component) {
const layoutFound = LayoutMap.get(component.toUpperCase());
item.component = layoutFound || dynamicImport(dynamicViewsModules, component as string);
} else if (name) {
item.component = getParentLayout();
}
+ // Determine if all submenus are hidden, add hidenChildrenInMenu if all are hidden
+ item.meta.hideChildrenInMenu = (children || []).every((child) => child.meta?.hidden);
children && asyncImportRoute(children);
});
}
@@ -102,7 +103,12 @@ export function transformObjToRoute<T = AppRouteModule>(routeList: AppRouteModul
const meta = route.meta || {};
meta.single = true;
meta.affix = false;
- route.meta = meta;
+ route.meta = {
+ ...meta,
+ hidden: false,
+ test: 1,
+ hideMenu: meta.hidden,
+ };
}
} else {
warn('Configure the routing correctly:' + route?.name + ' component attribute');
diff --git a/streampark-console/streampark-console-newui/src/store/modules/permission.ts b/streampark-console/streampark-console-newui/src/store/modules/permission.ts
index 1c2c3b71e..1938690dd 100644
--- a/streampark-console/streampark-console-newui/src/store/modules/permission.ts
+++ b/streampark-console/streampark-console-newui/src/store/modules/permission.ts
@@ -186,37 +186,6 @@ export const usePermissionStore = defineStore({
}
return hasAuth;
};
- /**
- * @description Fix the affix tag in routes according to the homepage path set (fixed homepage)
- * */
- // const checkCurrentRouter = (routes: AppRouteRecordRaw[]) => {
- // if (!routes || routes.length === 0) return;
- // let homePath: string = nextPath || userStore.getUserInfo.homePath || PageEnum.BASE_HOME;
-
- // function patcher(routes: AppRouteRecordRaw[], parentPath = '') {
- // if (parentPath) parentPath = parentPath + '/';
- // routes.forEach((route: AppRouteRecordRaw) => {
- // const { path, children, redirect } = route;
- // const currentPath = path.startsWith('/') ? path : parentPath + path;
- // if (currentPath === homePath) {
- // if (redirect) {
- // homePath = route.redirect! as string;
- // } else {
- // route.meta = Object.assign({}, route.meta, { affix: true });
- // throw new Error('end');
- // }
- // }
- // children && children.length > 0 && patcher(children, currentPath);
- // });
- // }
-
- // try {
- // patcher(routes);
- // } catch (e) {
- // // Processed out of loop
- // }
- // return;
- // };
switch (permissionMode) {
// Role authorization
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/components/AppView/StatisticCard.vue b/streampark-console/streampark-console-newui/src/views/flink/app/components/AppView/StatisticCard.vue
new file mode 100644
index 000000000..acb79ba28
--- /dev/null
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/components/AppView/StatisticCard.vue
@@ -0,0 +1,60 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF 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
+
+ https://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.
+-->
+<script lang="ts">
+ import { defineComponent } from 'vue';
+ export default defineComponent({
+ name: 'StatisticCard',
+ });
+</script>
+<script setup lang="ts" name="StatisticCard">
+ import { Card, Statistic, Divider, Skeleton } from 'ant-design-vue';
+ defineProps({
+ loading: { type: Boolean, default: false },
+ statisticProps: {
+ type: Object as PropType<Recordable>,
+ default: () => ({ title: '', value: 0 }),
+ },
+ footerList: {
+ type: Array as PropType<Array<{ title: string; value: string | number }>>,
+ default: () => [],
+ },
+ });
+</script>
+<template>
+ <div class="gutter-box">
+ <Skeleton :loading="loading" active>
+ <Card :bordered="false" class="dash-statistic">
+ <Statistic
+ v-bind="statisticProps"
+ :value-style="{
+ color: '#3f8600',
+ fontSize: '45px',
+ fontWeight: 500,
+ textShadow: '1px 1px 0 rgba(0,0,0,0.2)',
+ }"
+ />
+ </Card>
+ <Divider class="def-margin-bottom" />
+ <template v-for="(item, index) in footerList" :key="item.field">
+ <span> {{ item.title }} </span>
+ <strong class="pl-10px">{{ item.value }}</strong>
+ <Divider type="vertical" v-if="index !== footerList.length - 1" />
+ </template>
+ </Skeleton>
+ </div>
+</template>
+<style scoped></style>
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/components/CustomForm.tsx b/streampark-console/streampark-console-newui/src/views/flink/app/components/CustomForm.tsx
new file mode 100644
index 000000000..480b5b7f5
--- /dev/null
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/components/CustomForm.tsx
@@ -0,0 +1,117 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF 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
+
+ https://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 { defineComponent } from 'vue';
+import type { PropType } from 'vue';
+import { Button, Form, Input, InputNumber, Tag, Select } from 'ant-design-vue';
+import Icon from '/@/components/Icon';
+export interface CheckPointFailure {
+ cpMaxFailureInterval: number;
+ cpFailureRateInterval: number;
+ cpFailureAction: string;
+}
+import { cpTriggerAction } from '../data';
+export default defineComponent({
+ props: {
+ value: {
+ type: Object as PropType<CheckPointFailure>,
+ required: true,
+ },
+ },
+ emits: ['updateValue'],
+ setup(props, { emit }) {
+ const formItemContext = Form.useInjectFormItemContext();
+ const triggerChange = (changedValue: Partial<CheckPointFailure>) => {
+ emit('updateValue', { ...props.value, ...changedValue });
+ formItemContext.onFieldChange();
+ };
+ const handleCpFailureRateIntervalChange = (value: any) => {
+ triggerChange({ cpFailureRateInterval: value });
+ };
+ const handleCpMaxFailureIntervalChange = (value: any) => {
+ // const newNumber = (e.target as any).value;
+ triggerChange({ cpMaxFailureInterval: value });
+ };
+ const handleFailureActionChange = (value: any) => {
+ triggerChange({ cpFailureAction: value });
+ };
+ return () => {
+ return (
+ <div>
+ <Input.Group compact class="!flex">
+ <InputNumber
+ min={1}
+ step={1}
+ name="cpMaxFailureInterval"
+ placeholder="checkpoint failure rate interval"
+ allow-clear
+ class="!w-260px mr-10px"
+ value={props.value?.cpMaxFailureInterval}
+ onChange={(value: any) => handleCpMaxFailureIntervalChange(value)}
+ />
+ <Button style="width: 70px"> minute </Button>
+ <InputNumber
+ style="margin-left: 1%"
+ name="cpFailureRateInterval"
+ min={1}
+ step={1}
+ placeholder="max failures per interval"
+ class="!mb-0 !w-200px"
+ value={props.value?.cpFailureRateInterval}
+ onChange={(value: any) => handleCpFailureRateIntervalChange(value)}
+ />
+
+ <Button style="width: 70px"> count </Button>
+ <Select
+ name="cpFailureAction"
+ style="margin-left: 1%"
+ placeholder="trigger action"
+ allow-clear
+ class="!mb-0 flex-1"
+ value={props.value?.cpFailureAction}
+ onChange={(e: any) => handleFailureActionChange(e)}
+ >
+ {cpTriggerAction.map((o) => {
+ return (
+ <Select.Option key={o.value}>
+ <Icon
+ icon={
+ o.value === 1 ? 'ant-design:alert-outlined' : 'ant-design:sync-outlined'
+ }
+ />
+ {o.label}
+ </Select.Option>
+ );
+ })}
+ </Select>
+ </Input.Group>
+ <p class="conf-desc mt-10px">
+ <span class="note-info">
+ <Tag color="#2db7f5" class="tag-note">
+ Note
+ </Tag>
+ Operation after checkpoint failure, e.g:
+ <br />
+ Within <span class="note-elem">5 minutes</span>(checkpoint failure rate interval), if
+ the number of checkpoint failures reaches <span class="note-elem">10</span> (max
+ failures per interval),action will be triggered(alert or restart job)
+ </span>
+ </p>
+ </div>
+ );
+ };
+ },
+});
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/components/Dependency.vue b/streampark-console/streampark-console-newui/src/views/flink/app/components/Dependency.vue
index cfe83b0a2..b45af62fb 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/app/components/Dependency.vue
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/components/Dependency.vue
@@ -263,6 +263,9 @@
<Tabs type="card" v-model:activeKey="activeTab" class="pom-card">
<TabPane key="pom" tab="Maven pom">
<div ref="pomBox" class="pom-box syntax-true" style="height: 300px"></div>
+ <a-button type="primary" class="apply-pom" @click="handleApplyPom()">
+ {{ t('common.apply') }}
+ </a-button>
</TabPane>
<TabPane key="jar" tab="Upload Jar">
<template v-if="isK8sExecMode(formModel?.executionMode)">
@@ -285,55 +288,45 @@
<UploadJobJar :custom-request="handleCustomDepsRequest" v-model:loading="loading" />
</TabPane>
</Tabs>
- <div class="flex justify-end">
- <div class="dependency-box" v-if="dependencyRecords.length > 0 || uploadJars.length > 0">
- <Alert
- class="dependency-item"
- v-for="(value, index) in dependencyRecords"
- :key="`dependency_${index}`"
- type="info"
- @click="handleEditPom(value)"
- >
- <template #message>
- <Space @click="handleEditPom(value)" class="tag-dependency-pom">
- <Tag class="tag-dependency" color="#2db7f5">POM</Tag>
- {{ value.artifactId }}-{{ value.version }}.jar
- <Icon
- :size="12"
- icon="ant-design:close-outlined"
- class="icon-close cursor-pointer"
- @click.stop="handleRemovePom(value)"
- />
- </Space>
- </template>
- </Alert>
- <Alert
- class="dependency-item"
- v-for="(value, index) in uploadJars"
- :key="`upload_jars_${index}`"
- type="info"
- >
- <template #message>
- <Space>
- <Tag class="tag-dependency" color="#108ee9">JAR</Tag>
- {{ value }}
- <Icon
- icon="ant-design:close-outlined"
- class="icon-close cursor-pointer"
- :size="12"
- @click="handleRemoveJar(value)"
- />
- </Space>
- </template>
- </Alert>
- </div>
- <a-button
- type="primary"
- class="apply-pom"
- @click="handleApplyPom()"
- v-show="activeTab == 'pom'"
+ <div class="dependency-box" v-if="dependencyRecords.length > 0 || uploadJars.length > 0">
+ <Alert
+ class="dependency-item"
+ v-for="(value, index) in dependencyRecords"
+ :key="`dependency_${index}`"
+ type="info"
+ @click="handleEditPom(value)"
>
- {{ t('common.apply') }}
- </a-button>
+ <template #message>
+ <Space @click="handleEditPom(value)" class="tag-dependency-pom">
+ <Tag class="tag-dependency" color="#2db7f5">POM</Tag>
+ {{ value.artifactId }}-{{ value.version }}.jar
+ <Icon
+ :size="12"
+ icon="ant-design:close-outlined"
+ class="icon-close cursor-pointer"
+ @click.stop="handleRemovePom(value)"
+ />
+ </Space>
+ </template>
+ </Alert>
+ <Alert
+ class="dependency-item"
+ v-for="(value, index) in uploadJars"
+ :key="`upload_jars_${index}`"
+ type="info"
+ >
+ <template #message>
+ <Space>
+ <Tag class="tag-dependency" color="#108ee9">JAR</Tag>
+ {{ value }}
+ <Icon
+ icon="ant-design:close-outlined"
+ class="icon-close cursor-pointer"
+ :size="12"
+ @click="handleRemoveJar(value)"
+ />
+ </Space>
+ </template>
+ </Alert>
</div>
</template>
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/components/FlinkSql.vue b/streampark-console/streampark-console-newui/src/views/flink/app/components/FlinkSql.vue
new file mode 100644
index 000000000..5b11877fc
--- /dev/null
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/components/FlinkSql.vue
@@ -0,0 +1,223 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF 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
+
+ https://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.
+-->
+<script lang="ts">
+ export default {
+ name: 'FlinkSql',
+ };
+</script>
+
+<script setup lang="ts" name="FlinkSql">
+ import { computed, reactive, ref, unref, watchEffect } from 'vue';
+ import { getMonacoOptions } from '../data';
+ import { Icon } from '/@/components/Icon';
+ import { useMonaco } from '/@/hooks/web/useMonaco';
+ import { Button } from 'ant-design-vue';
+ import { isEmpty } from '/@/utils/is';
+ import { useMessage } from '/@/hooks/web/useMessage';
+ import { fetchFlinkSqlVerify } from '/@/api/flink/app/flinkSql';
+ import { format } from '../FlinkSqlFormatter';
+ import { useFullscreen } from '@vueuse/core';
+ import { useI18n } from '/@/hooks/web/useI18n';
+ const ButtonGroup = Button.Group;
+ const { t } = useI18n();
+ const vertifyRes = reactive({
+ errorMsg: '',
+ verified: false,
+ errorStart: 0,
+ errorEnd: 0,
+ });
+ const flinkSql = ref();
+ const flinkScreen = ref();
+ const { isFullscreen, toggle } = useFullscreen(flinkScreen);
+ const emit = defineEmits(['update:value', 'preview']);
+ const { createMessage } = useMessage();
+
+ const props = defineProps({
+ value: {
+ type: String,
+ default: '',
+ },
+ versionId: {
+ type: String as PropType<Nullable<string>>,
+ },
+ suggestions: {
+ type: Array as PropType<Array<{ text: string; description: string }>>,
+ default: () => [],
+ },
+ });
+ const defaultValue = '';
+
+ /* verify */
+ async function handleVerifySql() {
+ if (isEmpty(props.value)) {
+ vertifyRes.errorMsg = 'empty sql';
+ return false;
+ }
+
+ if (!props.versionId) {
+ createMessage.error(t('flink.app.dependencyError'));
+ return false;
+ } else {
+ try {
+ const { data } = await fetchFlinkSqlVerify({
+ sql: props.value,
+ versionId: props.versionId,
+ });
+ const success = data.data === true || data.data === 'true';
+ if (success) {
+ vertifyRes.verified = true;
+ vertifyRes.errorMsg = '';
+ syntaxError();
+ return true;
+ } else {
+ vertifyRes.errorStart = parseInt(data.start);
+ vertifyRes.errorEnd = parseInt(data.end);
+ switch (data.type) {
+ case 4:
+ vertifyRes.errorMsg = 'Unsupported sql';
+ break;
+ case 5:
+ vertifyRes.errorMsg = "SQL is not endWith ';'";
+ break;
+ default:
+ vertifyRes.errorMsg = data.message;
+ break;
+ }
+ syntaxError();
+ return false;
+ }
+ } catch (error) {
+ console.error(error);
+ return false;
+ }
+ }
+ }
+
+ async function syntaxError() {
+ const editor = await getInstance();
+ if (editor) {
+ const model = editor.getModel();
+ const monaco = await getMonacoInstance();
+ if (vertifyRes.errorMsg) {
+ try {
+ monaco.editor.setModelMarkers(model, 'sql', [
+ {
+ startLineNumber: 1,
+ endLineNumber: 4,
+ severity: monaco.MarkerSeverity.Error,
+ message: 'dsadfs',
+ },
+ ]);
+ } catch (e) {
+ console.log(e);
+ }
+ } else {
+ monaco.editor.setModelMarkers(model, 'sql', []);
+ }
+ }
+ }
+ /* format */
+ function handleFormatSql() {
+ if (isEmpty(props.value)) return;
+ const formatSql = format(props.value);
+ setContent(formatSql);
+ }
+ /* full screen */
+ function handleBigScreen() {
+ toggle();
+ unref(flinkSql).style.width = '0';
+ setTimeout(() => {
+ unref(flinkSql).style.width = '100%';
+ unref(flinkSql).style.height = isFullscreen.value ? '100vh' : '550px';
+ }, 100);
+ }
+ const { onChange, setContent, getInstance, getMonacoInstance, setMonacoSuggest } = useMonaco(
+ flinkSql,
+ {
+ language: 'sql',
+ code: props.value || defaultValue,
+ options: {
+ minimap: { enabled: true },
+ ...(getMonacoOptions(false) as any),
+ autoClosingBrackets: 'never',
+ },
+ },
+ );
+
+ watchEffect(() => {
+ if (props.suggestions.length > 0) {
+ setMonacoSuggest(props.suggestions);
+ }
+ });
+ const canPreview = computed(() => {
+ return /\${.+}/.test(props.value);
+ });
+
+ onChange((data) => {
+ emit('update:value', data);
+ });
+
+ defineExpose({ handleVerifySql, setContent });
+</script>
+
+<template>
+ <div>
+ <div ref="flinkScreen">
+ <div
+ class="sql-box"
+ ref="flinkSql"
+ :class="'syntax-' + (vertifyRes.errorMsg ? 'false' : 'true')"
+ ></div>
+ <ButtonGroup class="flinksql-tool">
+ <a-button
+ class="flinksql-tool-item"
+ size="small"
+ v-if="canPreview"
+ @click="emit('preview', value)"
+ >
+ <Icon icon="ant-design:eye-outlined" />
+ preview
+ </a-button>
+ <a-button size="small" class="flinksql-tool-item" type="primary" @click="handleVerifySql">
+ <Icon icon="ant-design:check-outlined" />
+ {{ t('flink.app.flinkSql.verify') }}
+ </a-button>
+ <a-button class="flinksql-tool-item" size="small" type="default" @click="handleFormatSql">
+ <Icon icon="ant-design:thunderbolt-outlined" />
+ {{ t('flink.app.flinkSql.format') }}
+ </a-button>
+ <a-button class="flinksql-tool-item" size="small" type="default" @click="handleBigScreen">
+ <Icon
+ :icon="
+ isFullscreen
+ ? 'ant-design:fullscreen-exit-outlined'
+ : 'ant-design:fullscreen-outlined'
+ "
+ />
+ {{ isFullscreen ? t('flink.app.flinkSql.exit') : '' }}
+ {{ t('flink.app.flinkSql.fullScreen') }}
+ </a-button>
+ </ButtonGroup>
+ <p class="conf-desc mt-10px">
+ <span class="text-red-600" v-if="vertifyRes.errorMsg"> {{ vertifyRes.errorMsg }} </span>
+ <span v-else class="text-green-700">
+ <span v-if="vertifyRes.verified"> {{ t('flink.app.flinkSql.successful') }} </span>
+ </span>
+ </p>
+ </div>
+ </div>
+</template>
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/components/FlinkSqlHistory.vue b/streampark-console/streampark-console-newui/src/views/flink/app/components/FlinkSqlHistory.vue
new file mode 100644
index 000000000..d3cd8eed3
--- /dev/null
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/components/FlinkSqlHistory.vue
@@ -0,0 +1,60 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF 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
+
+ https://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.
+-->
+<script lang="ts">
+ import { defineComponent } from 'vue';
+
+ export default defineComponent({
+ name: 'FlinkSqlHistory',
+ });
+</script>
+<script setup lang="ts" name="FlinkSqlHistory">
+ import { BasicModal, useModalInner } from '/@/components/Modal';
+ import { BasicForm, useForm } from '/@/components/Form';
+ import { useI18n } from '/@/hooks/web/useI18n';
+ const { t } = useI18n();
+ const [registerModalInner] = useModalInner();
+ const [registerForm] = useForm({
+ labelWidth: 120,
+ colon: true,
+ schemas: [
+ {
+ field: 'compare_sql',
+ label: 'Version',
+ component: 'Select',
+ componentProps: {
+ placeholder: 'Please select the sql version to compare',
+ mode: 'multiple',
+ maxTagCount: 2,
+ },
+ },
+ ],
+ baseColProps: { span: 24 },
+ labelCol: { lg: { span: 5, offset: 0 }, sm: { span: 7, offset: 0 } },
+ wrapperCol: { lg: { span: 16, offset: 0 }, sm: { span: 17, offset: 0 } },
+ showActionButtonGroup: false,
+ });
+</script>
+<template>
+ <BasicModal @register="registerModalInner">
+ <template #title>
+ <Icon icon="ant-design:swap-outlined" style="color: #4a9ff5" />
+ {{ t('flink.app.flinkSql.compareFlinkSQL') }}
+ </template>
+ <BasicForm @register="registerForm" />
+ </BasicModal>
+</template>
+<style scoped></style>
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/components/PodTemplate/TemplateButtonGroup.vue b/streampark-console/streampark-console-newui/src/views/flink/app/components/PodTemplate/TemplateButtonGroup.vue
index 547f87b69..7a521c10a 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/app/components/PodTemplate/TemplateButtonGroup.vue
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/components/PodTemplate/TemplateButtonGroup.vue
@@ -71,7 +71,7 @@
{{ t('flink.app.pod.host') }}
</div>
</a-button>
- <a-button type="default" disabled class="pod-template-tool-item">
+ <a-button type="default" disabled size="small" class="pod-template-tool-item">
<div class="flex items-center">
<Icon icon="ant-design:hdd-outlined" class="pr-5px" />
PVC
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useApp.tsx b/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useApp.tsx
index 7911d6ce8..5ab909306 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useApp.tsx
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useApp.tsx
@@ -283,7 +283,8 @@ export const useFlinkApplication = (openStartModal: Fn) => {
name="mappingForm"
labelCol={{ lg: { span: 7 }, sm: { span: 7 } }}
wrapperCol={{ lg: { span: 16 }, sm: { span: 4 } }}
- v-model:model={formValue}>
+ v-model:model={formValue}
+ >
<Form.Item label="Application Name">
<Alert message={app.jobName} type="info" />
</Form.Item>
@@ -291,14 +292,16 @@ export const useFlinkApplication = (openStartModal: Fn) => {
<Form.Item
label="YARN Application Id"
name="appId"
- rules={[{ required: true, message: 'YARN ApplicationId is required' }]}>
+ rules={[{ required: true, message: 'YARN ApplicationId is required' }]}
+ >
<Input type="text" placeholder="ApplicationId" v-model:value={formValue.appId} />
</Form.Item>
)}
<Form.Item
label="JobId"
name="jobId"
- rules={[{ required: true, message: 'ApplicationId is required' }]}>
+ rules={[{ required: true, message: 'ApplicationId is required' }]}
+ >
<Input type="text" placeholder="JobId" v-model:value={formValue.jobId} />
</Form.Item>
</Form>
@@ -312,7 +315,7 @@ export const useFlinkApplication = (openStartModal: Fn) => {
await fetchMapping({
id: app.id,
appId: formValue.appId,
- jobId: formValue.jobId
+ jobId: formValue.jobId,
});
Swal.fire({
icon: 'success',
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useAppTableAction.ts b/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useAppTableAction.ts
index bc5eab9eb..e0083ffbd 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useAppTableAction.ts
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/hooks/useAppTableAction.ts
@@ -25,6 +25,7 @@ import { fetchFlamegraph } from '/@/api/flink/app/metrics';
import { ActionItem, FormProps } from '/@/components/Table';
import { useMessage } from '/@/hooks/web/useMessage';
import { ExecModeEnum } from '/@/enums/flinkEnum';
+import { usePermission } from '/@/hooks/web/usePermission';
export enum JobTypeEnum {
JAR = 1,
SQL = 2,
@@ -44,7 +45,7 @@ export const useAppTableAction = (
const flinkAppStore = useFlinkAppStore();
const router = useRouter();
const { createMessage } = useMessage();
-
+ const { hasPermission } = usePermission();
const {
handleCheckLaunchApp,
handleAppCheckStart,
@@ -210,16 +211,12 @@ export const useAppTableAction = (
}
const formConfig = computed((): Partial<FormProps> => {
- return {
+ const tableFormConfig: FormProps = {
baseColProps: { span: 5, style: { paddingRight: '20px' } },
actionColOptions: { span: 4 },
showSubmitButton: false,
+ showResetButton: false,
colon: true,
- resetButtonOptions: {
- text: 'Add New',
- color: 'primary',
- preIcon: 'ant-design:plus-outlined',
- },
async resetFunc() {
router.push({ path: '/flink/app/add' });
},
@@ -274,6 +271,17 @@ export const useAppTableAction = (
},
],
};
+ if (hasPermission('app:create')) {
+ Object.assign(tableFormConfig, {
+ showResetButton: true,
+ resetButtonOptions: {
+ text: 'Add New',
+ color: 'primary',
+ preIcon: 'ant-design:plus-outlined',
+ },
+ });
+ }
+ return tableFormConfig;
});
/* tag */
diff --git a/streampark-console/streampark-console-newui/src/views/flink/app/styles/Add.less b/streampark-console/streampark-console-newui/src/views/flink/app/styles/Add.less
index 40ad231bf..3fda47049 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/app/styles/Add.less
+++ b/streampark-console/streampark-console-newui/src/views/flink/app/styles/Add.less
@@ -163,14 +163,7 @@
color: #1890ff;
}
- .apply-pom {
- margin-top: 17px;
- cursor: pointer;
- height: 26px;
- padding: 0 12px;
- font-size: 12px;
- }
-
+ .apply-pom,
.apply-testing,
.verify-sql {
z-index: 99;
@@ -193,7 +186,6 @@
}
.dependency-box {
- flex: 1;
margin-right: 10px;
margin-top: 15px;
margin-bottom: -10px;
diff --git a/streampark-console/streampark-console-newui/src/views/flink/setting/components/FlinkClusterSetting.vue b/streampark-console/streampark-console-newui/src/views/flink/setting/components/FlinkClusterSetting.vue
index eceb9b7d3..f67b100b1 100644
--- a/streampark-console/streampark-console-newui/src/views/flink/setting/components/FlinkClusterSetting.vue
+++ b/streampark-console/streampark-console-newui/src/views/flink/setting/components/FlinkClusterSetting.vue
@@ -218,7 +218,7 @@
<Tooltip :title="t('flink.setting.cluster.edit')">
<a-button
v-if="handleIsStart(item) && item.executionMode == executionMap.YARN_SESSION"
- v-auth="'app:update'"
+ v-auth="'cluster:update'"
:disabled="true"
@click="handleEditCluster(item)"
shape="circle"
@@ -229,7 +229,7 @@
</a-button>
<a-button
v-if="!handleIsStart(item) || item.executionMode == executionMap.REMOTE"
- v-auth="'app:update'"
+ v-auth="'cluster:update'"
@click="handleEditCluster(item)"
shape="circle"
size="large"
diff --git a/streampark-console/streampark-console-newui/src/views/system/menu/Menu.vue b/streampark-console/streampark-console-newui/src/views/system/menu/Menu.vue
index 6474415b5..f9c08d098 100644
--- a/streampark-console/streampark-console-newui/src/views/system/menu/Menu.vue
+++ b/streampark-console/streampark-console-newui/src/views/system/menu/Menu.vue
@@ -17,12 +17,12 @@
<template>
<div>
<BasicTable @register="registerTable" @fetch-success="onFetchSuccess">
- <template #toolbar>
+ <!-- <template #toolbar>
<a-button type="primary" @click="handleCreate" v-auth="'menu:add'">
<Icon icon="ant-design:plus-outlined" />
{{ t('common.add') }}
</a-button>
- </template>
+ </template> -->
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'action'">
<TableAction
@@ -52,11 +52,10 @@
import { columns, searchFormSchema } from './menu.data';
import { useMessage } from '/@/hooks/web/useMessage';
import { useI18n } from '/@/hooks/web/useI18n';
- import Icon from '/@/components/Icon';
export default defineComponent({
name: 'MenuManagement',
- components: { BasicTable, MenuDrawer, TableAction, Icon },
+ components: { BasicTable, MenuDrawer, TableAction },
setup() {
const [registerDrawer, { openDrawer }] = useDrawer();
const { createMessage } = useMessage();
@@ -71,9 +70,7 @@
schemas: searchFormSchema,
fieldMapToTime: [['createTime', ['createTimeFrom', 'createTimeTo'], 'YYYY-MM-DD']],
},
- fetchSetting: {
- listField: 'rows.children',
- },
+ fetchSetting: { listField: 'rows.children' },
isTreeTable: true,
pagination: false,
striped: false,
@@ -82,11 +79,11 @@
bordered: true,
showIndexColumn: false,
canResize: false,
- actionColumn: {
- width: 100,
- title: 'Operation',
- dataIndex: 'action',
- },
+ // actionColumn: {
+ // width: 100,
+ // title: 'Operation',
+ // dataIndex: 'action',
+ // },
});
function handleCreate() {
diff --git a/streampark-console/streampark-console-newui/src/views/system/menu/MenuDrawer.vue b/streampark-console/streampark-console-newui/src/views/system/menu/MenuDrawer.vue
index 6b0256bc8..8df679642 100644
--- a/streampark-console/streampark-console-newui/src/views/system/menu/MenuDrawer.vue
+++ b/streampark-console/streampark-console-newui/src/views/system/menu/MenuDrawer.vue
@@ -54,7 +54,7 @@
resetFields();
setDrawerProps({ confirmLoading: false });
isUpdate.value = !!data?.isUpdate;
-
+ console.log('data.record', data.record);
if (unref(isUpdate)) {
setFieldsValue({
...data.record,
@@ -76,6 +76,7 @@
async function handleSubmit() {
try {
const values = await validate();
+ values.display = !!values.display;
setDrawerProps({ confirmLoading: true });
unref(isUpdate) ? await editMenu(values) : await addMenu(values);
closeDrawer();
diff --git a/streampark-console/streampark-console-newui/src/views/system/menu/menu.data.ts b/streampark-console/streampark-console-newui/src/views/system/menu/menu.data.ts
index 0a7073fa6..75d1041f3 100644
--- a/streampark-console/streampark-console-newui/src/views/system/menu/menu.data.ts
+++ b/streampark-console/streampark-console-newui/src/views/system/menu/menu.data.ts
@@ -26,7 +26,7 @@ export const enum TypeEnum {
Dir = '2',
}
-const isDir = (type: string) => type === TypeEnum.Dir;
+// const isDir = (type: string) => type === TypeEnum.Dir;
const isMenu = (type: string) => type === TypeEnum.Menu;
const isButton = (type: string) => type === TypeEnum.Button;
@@ -50,35 +50,17 @@ export const columns: BasicColumn[] = [
{
title: 'Type',
dataIndex: 'type',
+ width: 90,
customRender: ({ record }) => {
const text = isMenu(record.type) ? 'menu' : 'button';
return h(Tag, { color: isMenu(record.type) ? 'cyan' : 'pink' }, () => text);
},
},
- {
- title: 'Path',
- dataIndex: 'path',
- },
- {
- title: 'Vue Component',
- dataIndex: 'component',
- },
- {
- title: 'Permission',
- dataIndex: 'permission',
- },
- {
- title: 'Order By',
- dataIndex: 'order',
- },
- {
- title: 'Create Time',
- dataIndex: 'createTime',
- },
- {
- title: 'Modify Time',
- dataIndex: 'modifyTime',
- },
+ { title: 'Path', dataIndex: 'path' },
+ { title: 'Vue Component', dataIndex: 'component' },
+ { title: 'Permission', dataIndex: 'permission', width: 150 },
+ { title: 'Order By', dataIndex: 'order', width: 90 },
+ { title: 'Create Time', dataIndex: 'createTime' },
];
export const searchFormSchema: FormSchema[] = [
@@ -146,7 +128,6 @@ export const formSchema: FormSchema[] = [
label: 'sort',
component: 'InputNumber',
componentProps: { class: '!w-full' },
- ifShow: ({ values }) => !isButton(values.type),
},
{
field: 'icon',
@@ -172,16 +153,14 @@ export const formSchema: FormSchema[] = [
label: 'Related permissions',
component: 'Input',
rules: [{ max: 50, message: 'Length cannot exceed 50 characters' }],
- ifShow: ({ values }) => !isDir(values.type),
+ ifShow: ({ values }) => isButton(values.type),
},
{
field: 'display',
label: 'whether to display',
component: 'Switch',
- defaultValue: '1',
+ defaultValue: true,
componentProps: {
- checkedValue: '1',
- unCheckedValue: '0',
checkedChildren: 'Yes',
unCheckedChildren: 'No',
},