Amy0104 commented on code in PR #10096: URL: https://github.com/apache/dolphinscheduler/pull/10096#discussion_r895631369
########## dolphinscheduler-ui/src/views/security/cluster-manage/components/use-modal.ts: ########## @@ -0,0 +1,119 @@ +/* + * 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 + * + * 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 { reactive, ref, SetupContext } from 'vue' +import { useI18n } from 'vue-i18n' +import { + verifyCluster, + createCluster, + updateCluster +} from '@/service/modules/cluster' + +export function useModal( + props: any, + ctx: SetupContext<('cancelModal' | 'confirmModal')[]> +) { + const { t } = useI18n() + + const variables = reactive({ + clusterFormRef: ref(), + model: { + code: ref<number>(-1), + name: ref(''), + k8s_config: ref(''), + yarn_config: ref(''), + description: ref('') + }, + saving: false, + rules: { + name: { + required: true, + trigger: ['input', 'blur'], + validator() { + if (variables.model.name === '') { + return new Error(t('security.cluster.cluster_name_tips')) + } + } + }, + description: { + required: true, + trigger: ['input', 'blur'], + validator() { + if (variables.model.description === '') { + return new Error(t('security.cluster.cluster_description_tips')) + } + } + } + } + }) + + const handleValidate = async (statusRef: number) => { + await variables.clusterFormRef.validate() + + if (variables.saving) return + variables.saving = true + + try { + statusRef === 0 ? await submitClusterModal() : await updateClusterModal() + variables.saving = false + } catch (err) { + variables.saving = false + } Review Comment: It is better to use finally here than setting saving to false twice. ########## dolphinscheduler-ui/src/views/security/cluster-manage/index.tsx: ########## @@ -0,0 +1,170 @@ +/* + * 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 + * + * 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 { defineComponent, onMounted, toRefs, watch } from 'vue' +import { + NButton, + NCard, + NDataTable, + NIcon, + NInput, + NPagination +} from 'naive-ui' +import { SearchOutlined } from '@vicons/antd' +import { useI18n } from 'vue-i18n' +import { useTable } from './use-table' +import Card from '@/components/card' +import ClusterModal from './components/cluster-modal' +import styles from './index.module.scss' + +const clusterManage = defineComponent({ + name: 'cluster-manage', + setup() { + const { t } = useI18n() + const { variables, getTableData, createColumns } = useTable() + + const requestData = () => { + getTableData({ + pageSize: variables.pageSize, + pageNo: variables.page, + searchVal: variables.searchVal + }) + } + + const onUpdatePageSize = () => { + variables.page = 1 + requestData() + } + + const onSearch = () => { + variables.page = 1 + requestData() + } + + const handleModalChange = () => { + variables.showModalRef = true + variables.statusRef = 0 + } + + const onCancelModal = () => { + variables.showModalRef = false + } + + const onConfirmModal = () => { + variables.showModalRef = false + requestData() + } + + onMounted(() => { + createColumns(variables) + requestData() + }) + + watch(useI18n().locale, () => { + createColumns(variables) + }) + + return { + t, + ...toRefs(variables), + requestData, + onCancelModal, + onConfirmModal, + onUpdatePageSize, + handleModalChange, + onSearch + } + }, + render() { + const { + t, + requestData, + onUpdatePageSize, + onCancelModal, + onConfirmModal, + handleModalChange, + onSearch, + loadingRef + } = this + + return ( + <div> + <NCard> + <div class={styles['search-card']}> + <div> + <NButton + size='small' + type='primary' + onClick={handleModalChange} + class='btn-create-cluster' + > + {t('security.cluster.create_cluster')} + </NButton> Review Comment: It is unnecessary to wrap a div for the NButton. ########## dolphinscheduler-ui/src/views/security/cluster-manage/index.tsx: ########## @@ -0,0 +1,170 @@ +/* + * 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 + * + * 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 { defineComponent, onMounted, toRefs, watch } from 'vue' +import { + NButton, + NCard, + NDataTable, + NIcon, + NInput, + NPagination +} from 'naive-ui' +import { SearchOutlined } from '@vicons/antd' +import { useI18n } from 'vue-i18n' +import { useTable } from './use-table' +import Card from '@/components/card' +import ClusterModal from './components/cluster-modal' +import styles from './index.module.scss' + +const clusterManage = defineComponent({ + name: 'cluster-manage', + setup() { + const { t } = useI18n() + const { variables, getTableData, createColumns } = useTable() + + const requestData = () => { + getTableData({ + pageSize: variables.pageSize, + pageNo: variables.page, + searchVal: variables.searchVal + }) + } + + const onUpdatePageSize = () => { + variables.page = 1 + requestData() + } + + const onSearch = () => { + variables.page = 1 + requestData() + } + + const handleModalChange = () => { + variables.showModalRef = true + variables.statusRef = 0 + } + + const onCancelModal = () => { + variables.showModalRef = false + } + + const onConfirmModal = () => { + variables.showModalRef = false + requestData() + } + + onMounted(() => { + createColumns(variables) + requestData() + }) + + watch(useI18n().locale, () => { + createColumns(variables) + }) + + return { + t, + ...toRefs(variables), + requestData, + onCancelModal, + onConfirmModal, + onUpdatePageSize, + handleModalChange, + onSearch + } + }, + render() { + const { + t, + requestData, + onUpdatePageSize, + onCancelModal, + onConfirmModal, + handleModalChange, + onSearch, + loadingRef + } = this + + return ( + <div> + <NCard> + <div class={styles['search-card']}> + <div> + <NButton + size='small' + type='primary' + onClick={handleModalChange} + class='btn-create-cluster' + > + {t('security.cluster.create_cluster')} + </NButton> + </div> + <div class={styles.box}> + <NInput + size='small' + clearable + v-model={[this.searchVal, 'value']} + placeholder={t('security.cluster.search_tips')} + /> + <NButton size='small' type='primary' onClick={onSearch}> + {{ + icon: () => ( + <NIcon> + <SearchOutlined /> + </NIcon> + ) + }} + </NButton> + </div> + </div> Review Comment: It is better to use 'NSpace' component here. ########## dolphinscheduler-ui/src/views/security/cluster-manage/components/cluster-modal.tsx: ########## @@ -0,0 +1,191 @@ +/* + * 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 + * + * 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 { defineComponent, PropType, toRefs, watch } from 'vue' +import Modal from '@/components/modal' +import { NForm, NFormItem, NInput } from 'naive-ui' +import { useModal } from './use-modal' +import { useI18n } from 'vue-i18n' + +const envK8sConfigPlaceholder = `apiVersion: v1 +clusters: +- cluster: + certificate-authority-data: LS0tLS1CZJQ0FURS0tLS0tCg== + server: https://127.0.0.1:6443 + name: kubernetes +contexts: +- context: + cluster: kubernetes + user: kubernetes-admin + name: kubernetes-admin@kubernetes +current-context: kubernetes-admin@kubernetes +kind: Config +preferences: {} +users: +- name: kubernetes-admin + user: + client-certificate-data: LS0tLS1CZJQ0FURS0tLS0tCg= +` + +const envYarnConfigPlaceholder = 'In development...' + +const ClusterModal = defineComponent({ + name: 'ClusterModal', + props: { + showModalRef: { + type: Boolean as PropType<boolean>, + default: false + }, + statusRef: { + type: Number as PropType<number>, + default: 0 + }, + row: { + type: Object as PropType<any>, + default: {} + } + }, + emits: ['cancelModal', 'confirmModal'], + setup(props, ctx) { + const { variables, handleValidate } = useModal(props, ctx) + const { t } = useI18n() + + const cancelModal = () => { + if (props.statusRef === 0) { + variables.model.name = '' + variables.model.k8s_config = '' + variables.model.yarn_config = '' + variables.model.description = '' + } + ctx.emit('cancelModal', props.showModalRef) + } + + const confirmModal = () => { + handleValidate(props.statusRef) + } + + const setModal = (row: any) => { + variables.model.code = row.code + variables.model.name = row.name + if (row.config) { + const config = JSON.parse(row.config) + variables.model.k8s_config = config.k8s || '' + variables.model.yarn_config = config.yarn || '' + } else { + variables.model.k8s_config = '' + variables.model.yarn_config = '' + } + variables.model.description = row.description + } + + watch( + () => props.statusRef, + () => { + if (props.statusRef === 0) { + variables.model.name = '' + variables.model.k8s_config = '' + variables.model.yarn_config = '' + variables.model.description = '' + } else { + setModal(props.row) + } + } + ) + + watch( + () => props.row, + () => { + setModal(props.row) + } + ) + + return { t, ...toRefs(variables), cancelModal, confirmModal } + }, + render() { + const { t } = this + return ( + <div> + <Modal + title={ + this.statusRef === 0 + ? t('security.cluster.create_cluster') + : t('security.cluster.edit_cluster') Review Comment: Have you committed the language packs codes? ########## dolphinscheduler-ui/src/views/security/cluster-manage/index.tsx: ########## @@ -0,0 +1,170 @@ +/* + * 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 + * + * 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 { defineComponent, onMounted, toRefs, watch } from 'vue' +import { + NButton, + NCard, + NDataTable, + NIcon, + NInput, + NPagination +} from 'naive-ui' +import { SearchOutlined } from '@vicons/antd' +import { useI18n } from 'vue-i18n' +import { useTable } from './use-table' +import Card from '@/components/card' +import ClusterModal from './components/cluster-modal' +import styles from './index.module.scss' + +const clusterManage = defineComponent({ + name: 'cluster-manage', + setup() { + const { t } = useI18n() + const { variables, getTableData, createColumns } = useTable() + + const requestData = () => { + getTableData({ + pageSize: variables.pageSize, + pageNo: variables.page, + searchVal: variables.searchVal + }) + } + + const onUpdatePageSize = () => { + variables.page = 1 + requestData() + } + + const onSearch = () => { + variables.page = 1 + requestData() + } + + const handleModalChange = () => { + variables.showModalRef = true + variables.statusRef = 0 + } + + const onCancelModal = () => { + variables.showModalRef = false + } + + const onConfirmModal = () => { + variables.showModalRef = false + requestData() + } + + onMounted(() => { + createColumns(variables) + requestData() + }) + + watch(useI18n().locale, () => { + createColumns(variables) + }) + + return { + t, + ...toRefs(variables), + requestData, + onCancelModal, + onConfirmModal, + onUpdatePageSize, + handleModalChange, + onSearch + } + }, + render() { + const { + t, + requestData, + onUpdatePageSize, + onCancelModal, + onConfirmModal, + handleModalChange, + onSearch, + loadingRef + } = this + + return ( + <div> + <NCard> + <div class={styles['search-card']}> + <div> + <NButton + size='small' + type='primary' + onClick={handleModalChange} + class='btn-create-cluster' + > + {t('security.cluster.create_cluster')} + </NButton> + </div> + <div class={styles.box}> + <NInput + size='small' + clearable + v-model={[this.searchVal, 'value']} + placeholder={t('security.cluster.search_tips')} + /> + <NButton size='small' type='primary' onClick={onSearch}> + {{ + icon: () => ( + <NIcon> + <SearchOutlined /> + </NIcon> + ) + }} + </NButton> + </div> + </div> + </NCard> + <Card class={styles['table-card']}> + <NDataTable + loading={loadingRef} + row-class-name='items' + columns={this.columns} + data={this.tableData} + scrollX={this.tableWidth} + /> + <div class={styles.pagination}> + <NPagination + v-model:page={this.page} + v-model:page-size={this.pageSize} + page-count={this.totalPage} + show-size-picker + page-sizes={[10, 30, 50]} + show-quick-jumper + onUpdatePage={requestData} + onUpdatePageSize={onUpdatePageSize} + /> + </div> Review Comment: Same as above. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
