This is an automated email from the ASF dual-hosted git repository. gaojun2048 pushed a commit to branch alert_plugin_design in repository https://gitbox.apache.org/repos/asf/incubator-dolphinscheduler.git
commit 3d5c34a6aba73c50e91fddccb758a22d3f940713 Author: break60 <[email protected]> AuthorDate: Tue Sep 22 17:43:55 2020 +0800 [feature][ui]Alert plugin design (#3734) * [feature-3665][ui]Add element-ui (#3666) * [feature-3665][ui]Add element-ui * add license * Add form-create plug-in and alarm group management add sample demo * Modify node version * fix * fix * [Feature-3682][ui]Add form-create plug-in and alarm group management add sample demo (#3683) * Add form-create plug-in and alarm group management add sample demo * Modify node version * fix * fix * [feature][ui] Add alarm instance page * [feature-3665][ui]Add element-ui (#3666) * [feature-3665][ui]Add element-ui * add license * Add form-create plug-in and alarm group management add sample demo * Modify node version * fix * fix --- .../alarmPluginExample/_source/createWarning.vue | 145 +++++++++++++ .../pages/alarmPluginExample/_source/list.vue | 224 +++++++++++++++++++++ .../security/pages/alarmPluginExample/index.vue | 161 +++++++++++++++ .../src/js/conf/home/router/index.js | 8 + .../components/secondaryMenu/_source/menu.js | 9 + .../src/js/module/i18n/locale/en_US.js | 2 + .../src/js/module/i18n/locale/zh_CN.js | 2 + dolphinscheduler-ui/src/sass/common/_table.scss | 3 + 8 files changed, 554 insertions(+) diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/alarmPluginExample/_source/createWarning.vue b/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/alarmPluginExample/_source/createWarning.vue new file mode 100644 index 0000000..28d53c5 --- /dev/null +++ b/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/alarmPluginExample/_source/createWarning.vue @@ -0,0 +1,145 @@ +/* + * 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. + */ +<template> + <m-popup + ref="popup" + :ok-text="item ? $t('Edit') : $t('Submit')" + :nameText="item ? $t('Edit alarm group') : $t('Create alarm group')" + @ok="_ok"> + <template slot="content"> + <div class="create-warning-model"> + <m-list-box-f> + <template slot="name"><strong>*</strong>{{$t('Group Name')}}</template> + <template slot="content"> + <x-input + type="input" + v-model="groupName" + maxlength="60" + :placeholder="$t('Please enter group name')"> + </x-input> + </template> + </m-list-box-f> + <m-list-box-f> + <template slot="name"><strong>*</strong>{{$t('Group Type')}}</template> + <template slot="content"> + <x-select v-model="groupType"> + <x-option + v-for="city in options" + :key="city.id" + :value="city.id" + :label="city.code"> + </x-option> + </x-select> + </template> + </m-list-box-f> + <m-list-box-f> + <template slot="name">{{$t('Remarks')}}</template> + <template slot="content"> + <x-input + type="textarea" + v-model="description" + :placeholder="$t('Please enter description')"> + </x-input> + </template> + </m-list-box-f> + </div> + </template> + </m-popup> +</template> +<script> + import i18n from '@/module/i18n' + import store from '@/conf/home/store' + import mPopup from '@/module/components/popup/popup' + import mListBoxF from '@/module/components/listBoxF/listBoxF' + + export default { + name: 'create-warning', + data () { + return { + store, + groupName: '', + groupType: 'EMAIL', + description: '', + options: [{ code: `${i18n.$t('Email')}`, id: 'EMAIL' }, { code: `${i18n.$t('SMS')}`, id: 'SMS' }] + } + }, + props: { + item: Object + }, + methods: { + _ok () { + if (this._verification()) { + // The name is not verified + if (this.item && this.item.groupName === this.groupName) { + this._submit() + return + } + + // Verify username + this.store.dispatch(`security/verifyName`, { + type: 'alertgroup', + groupName: this.groupName + }).then(res => { + this._submit() + }).catch(e => { + this.$message.error(e.msg || '') + }) + } + }, + _verification () { + // group name + if (!this.groupName.replace(/\s*/g,"")) { + this.$message.warning(`${i18n.$t('Please enter group name')}`) + return false + } + return true + }, + _submit () { + let param = { + groupName: this.groupName, + groupType: this.groupType, + description: this.description + } + if (this.item) { + param.id = this.item.id + } + this.$refs['popup'].spinnerLoading = true + this.store.dispatch(`security/${this.item ? 'updateAlertgrou' : 'createAlertgrou'}`, param).then(res => { + this.$emit('onUpdate') + this.$message.success(res.msg) + setTimeout(() => { + this.$refs['popup'].spinnerLoading = false + }, 800) + }).catch(e => { + this.$message.error(e.msg || '') + this.$refs['popup'].spinnerLoading = false + }) + } + }, + watch: {}, + created () { + if (this.item) { + this.groupName = this.item.groupName + this.groupType = this.item.groupType + this.description = this.item.description + } + }, + mounted () { + }, + components: { mPopup, mListBoxF } + } +</script> \ No newline at end of file diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/alarmPluginExample/_source/list.vue b/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/alarmPluginExample/_source/list.vue new file mode 100644 index 0000000..965f941 --- /dev/null +++ b/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/alarmPluginExample/_source/list.vue @@ -0,0 +1,224 @@ +/* + * 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. + */ +<template> + <div class="list-model"> + <!-- <div class="table-box"> + <table> + <tr> + <th> + <span>{{$t('#')}}</span> + </th> + <th> + <span>{{$t('Instance type')}}</span> + </th> + <th> + <span>{{$t('name')}}</span> + </th> + <th> + <span>{{$t('Create Time')}}</span> + </th> + <th> + <span>{{$t('Update Time')}}</span> + </th> + <th width="120"> + <span>{{$t('Operation')}}</span> + </th> + </tr> + <tr v-for="(item, $index) in list" :key="$index"> + <td> + <span>{{parseInt(pageNo === 1 ? ($index + 1) : (($index + 1) + (pageSize * (pageNo - 1))))}}</span> + </td> + <td> + <span> + {{item.groupName}} + </span> + </td> + <td><span>{{item.groupType === 'EMAIL' ? `${$t('Email')}` : `${$t('SMS')}`}}</span></td> + <td> + <span v-if="item.createTime">{{item.createTime | formatDate}}</span> + <span v-else>-</span> + </td> + <td> + <span v-if="item.updateTime">{{item.updateTime | formatDate}}</span> + <span v-else>-</span> + </td> + <td> + <x-button type="info" shape="circle" size="xsmall" data-toggle="tooltip" icon="ans-icon-user-empty" :title="$t('Managing Users')" @click="_mangeUser(item)"> + </x-button> + <x-button type="info" shape="circle" size="xsmall" data-toggle="tooltip" icon="ans-icon-edit" :title="$t('Edit')" @click="_edit(item)"> + </x-button> + <x-poptip + :ref="'poptip-delete-' + $index" + placement="bottom-end" + width="90"> + <p>{{$t('Delete?')}}</p> + <div style="text-align: right; margin: 0;padding-top: 4px;"> + <x-button type="text" size="xsmall" shape="circle" @click="_closeDelete($index)">{{$t('Cancel')}}</x-button> + <x-button type="primary" size="xsmall" shape="circle" @click="_delete(item,$index)">{{$t('Confirm')}}</x-button> + </div> + <template slot="reference"> + <x-button type="error" shape="circle" size="xsmall" data-toggle="tooltip" icon="ans-icon-trash" :title="$t('delete')" :disabled="item.id==1?true: false"></x-button> + </template> + </x-poptip> + </td> + </tr> + </table> + </div> --> + <div class="table-box"> + <el-table :data="list" size="mini" style="width: 100%"> + <el-table-column prop="groupName" :label="$t('Instance type')" width="180"></el-table-column> + <el-table-column prop="Remarks" :label="$t('name')" width="180"></el-table-column> + <el-table-column :label="$t('Create Time')"> + <template slot-scope="scope"> + <span>{{scope.row.createTime | formatDate}}</span> + </template> + </el-table-column> + <el-table-column :label="$t('Update Time')"> + <template slot-scope="scope"> + <span>{{scope.row.updateTime | formatDate}}</span> + </template> + </el-table-column> + <el-table-column :label="$t('Operation')" width="100"> + <template slot-scope="scope"> + <el-tooltip :content="$t('Edit')" placement="top"> + <el-button type="primary" size="mini" icon="el-icon-edit" circle></el-button> + </el-tooltip> + <el-tooltip :content="$t('delete')" placement="top"> + <el-button type="danger" size="mini" icon="el-icon-delete" circle></el-button> + </el-tooltip> + </template> + </el-table-column> + </el-table> + </div> + </div> +</template> +<script> + import _ from 'lodash' + import i18n from '@/module/i18n' + import { mapActions } from 'vuex' + import mTransfer from '@/module/components/transfer/transfer' + + export default { + name: 'user-list', + data () { + return { + list: [] + } + }, + props: { + alertgroupList: Array, + pageNo: Number, + pageSize: Number + }, + methods: { + ...mapActions('security', ['deleteAlertgrou', 'getAuthList', 'grantAuthorization']), + _closeDelete (i) { + this.$refs[`poptip-delete-${i}`][0].doClose() + }, + _delete (item, i) { + this.deleteAlertgrou({ + id: item.id + }).then(res => { + this.$refs[`poptip-delete-${i}`][0].doClose() + this.$emit('on-update') + this.$message.success(res.msg) + }).catch(e => { + this.$refs[`poptip-delete-${i}`][0].doClose() + this.$message.error(e.msg || '') + }) + }, + _edit (item) { + this.$emit('on-edit', item) + }, + _mangeUser (item, i) { + this.getAuthList({ + id: item.id, + type: 'user', + category: 'users' + }).then(data => { + let sourceListPrs = _.map(data[0], v => { + return { + id: v.id, + name: v.userName + } + }) + let targetListPrs = _.map(data[1], v => { + return { + id: v.id, + name: v.userName + } + }) + let self = this + let modal = this.$modal.dialog({ + closable: false, + showMask: true, + escClose: true, + className: 'v-modal-custom', + transitionName: 'opacityp', + render (h) { + return h(mTransfer, { + on: { + onUpdate (userIds) { + self._grantAuthorization('alert-group/grant-user', { + userIds: userIds, + alertgroupId: item.id + }) + modal.remove() + }, + close () { + modal.remove() + } + }, + props: { + sourceListPrs: sourceListPrs, + targetListPrs: targetListPrs, + type: { + name: `${i18n.$t('Managing Users')}` + } + } + }) + } + }) + }) + }, + _grantAuthorization (api, param) { + this.grantAuthorization({ + api: api, + param: param + }).then(res => { + this.$message.success(res.msg) + }).catch(e => { + this.$message.error(e.msg || '') + }) + } + }, + watch: { + alertgroupList (a) { + this.list = [] + setTimeout(() => { + this.list = a + }) + } + }, + created () { + this.list = this.alertgroupList + }, + mounted () { + }, + components: { } + } +</script> \ No newline at end of file diff --git a/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/alarmPluginExample/index.vue b/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/alarmPluginExample/index.vue new file mode 100644 index 0000000..50a1473 --- /dev/null +++ b/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/alarmPluginExample/index.vue @@ -0,0 +1,161 @@ +/* + * 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. + */ +<template> + <m-list-construction :title="$t('Alarm plugin example')"> + <template slot="conditions"> + <m-conditions @on-conditions="_onConditions"> + <!-- <template slot="button-group" v-if="isADMIN"> + <x-button type="ghost" size="small" @click="_create('')">{{$t('Create alarm group')}}</x-button> + </template> --> + </m-conditions> + </template> + <template slot="content"> + <template v-if="alertgroupList.length || total>0"> + <m-list @on-edit="_onEdit" + @on-update="_onUpdate" + :alertgroup-list="alertgroupList" + :page-no="searchParams.pageNo" + :page-size="searchParams.pageSize"> + + </m-list> + <div class="page-box"> + <x-page :current="parseInt(searchParams.pageNo)" :total="total" :page-size="searchParams.pageSize" show-elevator @on-change="_page" show-sizer :page-size-options="[10,30,50]" @on-size-change="_pageSize"></x-page> + </div> + </template> + <template v-if="!alertgroupList.length && total<=0"> + <m-no-data></m-no-data> + </template> + <m-spin :is-spin="isLoading" :is-left="isLeft"></m-spin> + </template> + </m-list-construction> +</template> +<script> + import _ from 'lodash' + import { mapActions } from 'vuex' + import mList from './_source/list' + import store from '@/conf/home/store' + import mSpin from '@/module/components/spin/spin' + import mCreateWarning from './_source/createWarning' + import mNoData from '@/module/components/noData/noData' + import listUrlParamHandle from '@/module/mixin/listUrlParamHandle' + import mConditions from '@/module/components/conditions/conditions' + import mListConstruction from '@/module/components/listConstruction/listConstruction' + + export default { + name: 'warning-groups-index', + data () { + return { + total: null, + isLoading: false, + alertgroupList: [], + searchParams: { + pageSize: 10, + pageNo: 1, + searchVal: '' + }, + isLeft: true, + isADMIN: store.state.user.userInfo.userType === 'ADMIN_USER' + } + }, + mixins: [listUrlParamHandle], + props: {}, + methods: { + ...mapActions('security', ['getAlertgroupP']), + /** + * Inquire + */ + _onConditions (o) { + this.searchParams = _.assign(this.searchParams, o) + this.searchParams.pageNo = 1 + }, + _page (val) { + this.searchParams.pageNo = val + }, + _pageSize (val) { + this.searchParams.pageSize = val + }, + _onUpdate () { + this._debounceGET() + }, + _onEdit (item) { + this._create(item) + }, + _create (item) { + let self = this + let modal = this.$modal.dialog({ + closable: false, + showMask: true, + escClose: true, + className: 'v-modal-custom', + transitionName: 'opacityp', + render (h) { + return h(mCreateWarning, { + on: { + onUpdate () { + self._debounceGET('false') + modal.remove() + }, + close () { + modal.remove() + } + }, + props: { + item: item + } + }) + } + }) + }, + _getList (flag) { + if(sessionStorage.getItem('isLeft')==0) { + this.isLeft = false + } else { + this.isLeft = true + } + this.isLoading = !flag + this.getAlertgroupP(this.searchParams).then(res => { + if(this.searchParams.pageNo>1 && res.totalList.length == 0) { + this.searchParams.pageNo = this.searchParams.pageNo -1 + } else { + this.alertgroupList = [] + this.alertgroupList = res.totalList + this.total = res.total + this.isLoading = false + } + }).catch(e => { + this.isLoading = false + }) + } + }, + watch: { + // router + '$route' (a) { + // url no params get instance list + this.searchParams.pageNo = _.isEmpty(a.query) ? 1 : a.query.pageNo + } + }, + created () { + }, + mounted () { + this.$modal.destroy() + }, + beforeDestroy () { + sessionStorage.setItem('isLeft',1) + }, + components: { mList, mListConstruction, mConditions, mSpin, mNoData } + } +</script> diff --git a/dolphinscheduler-ui/src/js/conf/home/router/index.js b/dolphinscheduler-ui/src/js/conf/home/router/index.js index b65586c..5f6f20b 100644 --- a/dolphinscheduler-ui/src/js/conf/home/router/index.js +++ b/dolphinscheduler-ui/src/js/conf/home/router/index.js @@ -397,6 +397,14 @@ const router = new Router({ meta: { title: `${i18n.$t('Token manage')}` } + }, + { + path: '/security/Alarm-plugin-example', + name: 'Alarm-plugin-example', + component: resolve => require(['../pages/security/pages/alarmPluginExample/index'], resolve), + meta: { + title: `${i18n.$t('Alarm plugin example')}` + } } ] }, diff --git a/dolphinscheduler-ui/src/js/module/components/secondaryMenu/_source/menu.js b/dolphinscheduler-ui/src/js/module/components/secondaryMenu/_source/menu.js index 56834a2..34d3ce3 100644 --- a/dolphinscheduler-ui/src/js/module/components/secondaryMenu/_source/menu.js +++ b/dolphinscheduler-ui/src/js/module/components/secondaryMenu/_source/menu.js @@ -135,6 +135,15 @@ const menu = { icon: 'ans-icon-document', children: [], disabled: true + }, + { + name: `${i18n.$t('Alarm plugin example')}`, + id: 2, + path: 'Alarm-plugin-example', + isOpen: true, + icon: 'ans-icon-document', + children: [], + disabled: true } ], resource: [ diff --git a/dolphinscheduler-ui/src/js/module/i18n/locale/en_US.js b/dolphinscheduler-ui/src/js/module/i18n/locale/en_US.js index 07dfb7c..5912146 100755 --- a/dolphinscheduler-ui/src/js/module/i18n/locale/en_US.js +++ b/dolphinscheduler-ui/src/js/module/i18n/locale/en_US.js @@ -474,6 +474,7 @@ export default { 'Create worker group': 'Create worker group', 'Edit worker group': 'Edit worker group', 'Token manage': 'Token manage', + 'Alarm plugin example': 'Alarm plugin example', 'Create token': 'Create token', 'Edit token': 'Edit token', 'Please enter the IP address separated by commas': 'Please enter the IP address separated by commas', @@ -639,6 +640,7 @@ export default { 'Current connection settings': 'Current connection settings', 'Please save the DAG before formatting': 'Please save the DAG before formatting', 'Batch copy': 'Batch copy', + 'Instance type': 'Instance type', 'Related items': 'Related items', 'Project name is required': 'Project name is required', 'Batch move': 'Batch move', diff --git a/dolphinscheduler-ui/src/js/module/i18n/locale/zh_CN.js b/dolphinscheduler-ui/src/js/module/i18n/locale/zh_CN.js index e3f2562..39a782b 100755 --- a/dolphinscheduler-ui/src/js/module/i18n/locale/zh_CN.js +++ b/dolphinscheduler-ui/src/js/module/i18n/locale/zh_CN.js @@ -469,6 +469,7 @@ export default { 'Create worker group': '创建Worker分组', 'Edit worker group': '编辑Worker分组', 'Token manage': '令牌管理', + 'Alarm plugin example': '告警插件实例', 'Create token': '创建令牌', 'Edit token': '编辑令牌', 'Please enter the IP address separated by commas': '请输入IP地址多个用英文逗号隔开', @@ -639,6 +640,7 @@ export default { 'Current connection settings': '当前连线设置', 'Please save the DAG before formatting': '格式化前请先保存DAG', 'Batch copy': '批量复制', + 'Instance type': '实例类型', 'Related items': '关联项目', 'Project name is required': '项目名称必填', 'Batch move': '批量移动', diff --git a/dolphinscheduler-ui/src/sass/common/_table.scss b/dolphinscheduler-ui/src/sass/common/_table.scss index 688f8e3..d643053 100644 --- a/dolphinscheduler-ui/src/sass/common/_table.scss +++ b/dolphinscheduler-ui/src/sass/common/_table.scss @@ -171,3 +171,6 @@ } } } +.el-table--enable-row-hover .el-table__body tr:hover>td { + background-color: #ddecff; +}
