This is an automated email from the ASF dual-hosted git repository. xxyu pushed a commit to branch kylin5 in repository https://gitbox.apache.org/repos/asf/kylin.git
commit cc42717d93a76707fdc85f44744f6c86235babb0 Author: Qian Xia <lauraxiaq...@gmail.com> AuthorDate: Wed Jul 19 16:11:20 2023 +0800 KYLIN-5655 refine page list layout and new %X issue --- kystudio/src/components/admin/Group/index.vue | 2 +- kystudio/src/components/admin/Group/locales.js | 6 +- kystudio/src/components/admin/User/index.vue | 2 +- kystudio/src/components/admin/User/locales.js | 2 +- .../src/components/common/GroupEditModal/index.vue | 2 +- .../components/common/GroupEditModal/locales.js | 4 +- .../common/ProjectEditModal/ProjectEditModal.vue | 2 +- .../components/common/ProjectEditModal/locales.js | 4 +- .../src/components/common/UserEditModal/index.vue | 2 +- .../src/components/common/UserEditModal/locales.js | 2 +- .../components/layout/layout_left_right_top.vue | 2 - kystudio/src/components/monitor/batchJobs/jobs.vue | 5 +- .../src/components/monitor/batchJobs/locales.js | 2 +- .../components/monitor/streamingJobs/locales.js | 71 -- .../monitor/streamingJobs/streamingJobs.vue | 1108 -------------------- kystudio/src/components/project/project_list.vue | 10 +- .../ModelList/ModelAddModal/addmodel.vue | 2 +- .../ModelList/ModelLayout/modelLayout.vue | 5 - .../ModelStreamingJob/ModelStreamingJob.vue | 362 ------- .../ModelList/ModelStreamingJob/locales.js | 34 - .../studio/StudioModel/ModelList/index.vue | 129 ++- .../studio/StudioModel/ModelList/locales.js | 6 +- kystudio/src/components/studio/snapshot/locales.js | 2 +- .../src/components/studio/snapshot/snapshot.vue | 6 +- kystudio/src/config/index.js | 4 +- kystudio/src/locale/en.js | 13 +- kystudio/src/router/index.js | 6 - kystudio/src/service/monitor.js | 9 - kystudio/src/store/model.js | 9 - kystudio/src/store/monitor.js | 9 - 30 files changed, 100 insertions(+), 1722 deletions(-) diff --git a/kystudio/src/components/admin/Group/index.vue b/kystudio/src/components/admin/Group/index.vue index 32c2dd1e6e..f122878928 100644 --- a/kystudio/src/components/admin/Group/index.vue +++ b/kystudio/src/components/admin/Group/index.vue @@ -2,7 +2,7 @@ <div class="security-group" v-loading="isLoadingUserGroups"> <div class="ksd-title-label ksd-mt-20 ksd-mrl-20">{{$t('userGroupsList')}}</div> <el-row class="ksd-mb-10 ksd-mt-10 ksd-mrl-20"> - <el-button type="primary" size="medium" v-if="groupActions.includes('addGroup')" :disabled="!isTestingSecurityProfile" icon="el-ksd-icon-add_22" @click="editGroup('new')">{{$t('userGroup')}}</el-button> + <el-button type="primary" size="medium" v-if="groupActions.includes('addGroup')" :disabled="!isTestingSecurityProfile" icon="el-ksd-icon-add_22" @click="editGroup('new')">{{$t('kylinLang.common.new')}}</el-button> <div style="width:240px;" class="ksd-fright"> <el-input class="show-search-btn" size="medium" diff --git a/kystudio/src/components/admin/Group/locales.js b/kystudio/src/components/admin/Group/locales.js index 49bfd12875..de90c7ab04 100644 --- a/kystudio/src/components/admin/Group/locales.js +++ b/kystudio/src/components/admin/Group/locales.js @@ -1,15 +1,15 @@ export default { en: { - newGroup: 'Add User Group', + newGroup: 'New User Group', assignUsers: 'Assign Users', willcheck: 'Unassigned Users', haschecked: 'Assigned Users', confirmDelGroup: 'Are you sure you want to delete the user group "{groupName}"?', usersCount: 'Number of Users', delGroupTitle: 'Delete Group', - userGroupsList: 'User Group List', + userGroupsList: 'User Group', groupFilter: 'Search by user group name', userGroup: 'User Group', - securityProfileTip: 'The current mode doesn\'t allow managing users/user groups, including operations such as adding, editing, deleting, assigning, and changing passwords.' + securityProfileTip: 'The current mode doesn\'t allow managing users/user groups, including operations such as creating, editing, deleting, assigning, and changing passwords.' } } diff --git a/kystudio/src/components/admin/User/index.vue b/kystudio/src/components/admin/User/index.vue index 79b0816a5f..2e9923d28e 100644 --- a/kystudio/src/components/admin/User/index.vue +++ b/kystudio/src/components/admin/User/index.vue @@ -16,7 +16,7 @@ icon="el-ksd-icon-add_22" v-if="userActions.includes('addUser')&&isTestingSecurityProfile" @click="editUser('new')"> - {{$t('user')}} + {{$t('kylinLang.common.new')}} </el-button> <div style="width:240px;" class="ksd-fright"> <el-input class="show-search-btn" diff --git a/kystudio/src/components/admin/User/locales.js b/kystudio/src/components/admin/User/locales.js index ee8282de7f..7d4eff330a 100644 --- a/kystudio/src/components/admin/User/locales.js +++ b/kystudio/src/components/admin/User/locales.js @@ -15,7 +15,7 @@ export default { groupMembership: 'Assign to Group', cofirmDelUser: 'Are you sure you want to delete the user {userName} ?', delUserTitle: 'Delete User', - userList: 'User List', + userList: 'User', changeUserTips: 'Are you sure you want to {status} the user {userName} ?', dataPermission: 'Data Permission' } diff --git a/kystudio/src/components/common/GroupEditModal/index.vue b/kystudio/src/components/common/GroupEditModal/index.vue index 040f26bc04..ae26752d1a 100644 --- a/kystudio/src/components/common/GroupEditModal/index.vue +++ b/kystudio/src/components/common/GroupEditModal/index.vue @@ -29,7 +29,7 @@ </el-form> <div slot="footer" class="dialog-footer"> <el-button size="medium" @click="closeHandler(false)">{{$t('kylinLang.common.cancel')}}</el-button> - <el-button type="primary" size="medium" :loading="submitLoading" :disabled="submitLoading" @click="submit">{{$t('ok')}}</el-button> + <el-button type="primary" size="medium" :loading="submitLoading" :disabled="submitLoading" @click="submit">{{$t(this.editType === 'assign' ? 'ok' : 'kylinLang.common.create')}}</el-button> </div> </el-dialog> </template> diff --git a/kystudio/src/components/common/GroupEditModal/locales.js b/kystudio/src/components/common/GroupEditModal/locales.js index 2bc4633ea7..1429c18e8e 100644 --- a/kystudio/src/components/common/GroupEditModal/locales.js +++ b/kystudio/src/components/common/GroupEditModal/locales.js @@ -1,13 +1,13 @@ export default { 'en': { - createGroup: 'Add User Group', + createGroup: 'New User Group', willCheckGroup: 'Unassigned Users', checkedGroup: 'Assigned Users', assignUser: 'Assign Users', ok: 'OK', userGroupPld: 'Please enter user group name', userPld: 'Search by username', - saveUserGroupSuccess: ' Added the user group successfully.', + saveUserGroupSuccess: ' Created the user group successfully.', updateUserOrGroupSuccess: 'Adjusted the assigned users and user groups successfully.', groupnamePld: 'Not support Chinese, nor special symbols (/:\\*?"<>|\')' } diff --git a/kystudio/src/components/common/ProjectEditModal/ProjectEditModal.vue b/kystudio/src/components/common/ProjectEditModal/ProjectEditModal.vue index cae11f1d99..7b9b8b24ce 100644 --- a/kystudio/src/components/common/ProjectEditModal/ProjectEditModal.vue +++ b/kystudio/src/components/common/ProjectEditModal/ProjectEditModal.vue @@ -110,7 +110,7 @@ <div slot="footer" class="dialog-footer ky-no-br-space" v-if="isFormShow"> <el-button size="medium" @click="closeHandler(false)">{{$t('cancel')}}</el-button> - <el-button type="primary" size="medium" :loading="saveLoading" @click="submit" class="js_addproject_submit">{{$t('kylinLang.common.ok')}}</el-button> + <el-button type="primary" size="medium" :loading="saveLoading" @click="submit" class="js_addproject_submit">{{$t('kylinLang.common.create')}}</el-button> </div> </el-dialog> </template> diff --git a/kystudio/src/components/common/ProjectEditModal/locales.js b/kystudio/src/components/common/ProjectEditModal/locales.js index 266534c662..14d4a49bea 100644 --- a/kystudio/src/components/common/ProjectEditModal/locales.js +++ b/kystudio/src/components/common/ProjectEditModal/locales.js @@ -2,14 +2,14 @@ export default { 'en': { project: 'Project', cancel: 'Cancel', - addProject: 'Add Project', + addProject: 'New Project', projectName: 'Project Name', projectType: 'Project Type', noProject: 'Please enter the project name', description: 'Description', projectPlace: 'Please enter project name', projectDescription: 'Pleaser enter project description', - saveSuccessful: 'Added the project successfully.', + saveSuccessful: 'Created the project successfully.', projectConfig: 'Project Configuration', property: 'Property', propertyCannotChange: '[{keyName}] cannot be edited', diff --git a/kystudio/src/components/common/UserEditModal/index.vue b/kystudio/src/components/common/UserEditModal/index.vue index 0b8ed07e54..72da80e8c7 100644 --- a/kystudio/src/components/common/UserEditModal/index.vue +++ b/kystudio/src/components/common/UserEditModal/index.vue @@ -141,7 +141,7 @@ </el-form> <div slot="footer" class="dialog-footer ky-no-br-space"> <el-button size="medium" v-if="showCancelBtn" @click="closeHandler(false)">{{$t('cancel')}}</el-button> - <el-button type="primary" size="medium" @click="submit" :loading="isLoading">{{$t('ok')}}</el-button> + <el-button type="primary" size="medium" @click="submit" :loading="isLoading">{{$t(editType !== 'new' ? 'ok' : 'kylinLang.common.create')}}</el-button> </div> </el-dialog> </template> diff --git a/kystudio/src/components/common/UserEditModal/locales.js b/kystudio/src/components/common/UserEditModal/locales.js index c4b3051c30..5576a237e2 100644 --- a/kystudio/src/components/common/UserEditModal/locales.js +++ b/kystudio/src/components/common/UserEditModal/locales.js @@ -1,6 +1,6 @@ export default { 'en': { - addUser: 'Add User', + addUser: 'New User', editRole: 'Edit Role', resetPassword: 'Change Password', username: 'Username', diff --git a/kystudio/src/components/layout/layout_left_right_top.vue b/kystudio/src/components/layout/layout_left_right_top.vue index 77c49829cb..b159e5e811 100644 --- a/kystudio/src/components/layout/layout_left_right_top.vue +++ b/kystudio/src/components/layout/layout_left_right_top.vue @@ -332,8 +332,6 @@ export default class LayoutLeftRightTop extends Vue { switch (menuName) { case 'snapshot': return this.availableMenus.includes(menuName.toLowerCase()) && this.$store.state.project.snapshot_manual_management_enabled - case 'streamingjob': - return this.availableMenus.includes(menuName.toLowerCase()) && this.$store.state.system.streamingEnabled === 'true' case 'ddl': return this.availableMenus.includes(menuName.toLowerCase()) && this.$store.state.system.ddlEnabled === 'true' case 'logicalView': diff --git a/kystudio/src/components/monitor/batchJobs/jobs.vue b/kystudio/src/components/monitor/batchJobs/jobs.vue index 64fda35ed3..03fa732b67 100644 --- a/kystudio/src/components/monitor/batchJobs/jobs.vue +++ b/kystudio/src/components/monitor/batchJobs/jobs.vue @@ -14,9 +14,8 @@ </div> </el-col> <el-col :span="8"> - <el-button type="primary" text size="medium" class="ksd-ml-2 ksd-fright" icon="el-ksd-icon-refresh_22" @click="manualRefreshJobs">{{$t('refreshList')}}</el-button><el-input - :placeholder="$t('pleaseSearch')" v-model="filter.key" v-global-key-event.enter.debounce="filterChange" @clear="filterChange()" class="show-search-btn ksd-fright" size="medium" prefix-icon="el-icon-search"> - </el-input> + <el-input :placeholder="$t('pleaseSearch')" v-model="filter.key" v-global-key-event.enter.debounce="filterChange" @clear="filterChange()" class="show-search-btn ksd-fright" size="medium" prefix-icon="el-icon-search"> + </el-input><el-button type="primary" text size="medium" class="ksd-ml-2 ksd-fright" icon="el-ksd-icon-refresh_22" @click="manualRefreshJobs">{{$t('refreshList')}}</el-button> </el-col> </el-row> <el-row class="filter-status-list" v-show="filterTags.length"> diff --git a/kystudio/src/components/monitor/batchJobs/locales.js b/kystudio/src/components/monitor/batchJobs/locales.js index 536ba33da8..1e6c803b8a 100644 --- a/kystudio/src/components/monitor/batchJobs/locales.js +++ b/kystudio/src/components/monitor/batchJobs/locales.js @@ -63,7 +63,7 @@ export default { triggerTime: 'Trigger Time', order: 'Order', jobTarget: 'Job Target: ', - jobsList: 'Batch Job List', + jobsList: 'Batch Job', sparkJobTip: 'Spark Job', logInfoTip: 'Log Output', openJobSteps: 'Open Job Steps', diff --git a/kystudio/src/components/monitor/streamingJobs/locales.js b/kystudio/src/components/monitor/streamingJobs/locales.js deleted file mode 100644 index e4770afe59..0000000000 --- a/kystudio/src/components/monitor/streamingJobs/locales.js +++ /dev/null @@ -1,71 +0,0 @@ -export default { - 'en': { - adminTips: 'Admin user can view all job information via Select All option in the project list.', - streamingJobsList: 'Streaming Job List', - jobStart: 'Start', - jobRestart: 'Restart', - jobStop: 'Stop', - refreshList: 'Refresh List', - pleaseSearch: 'Search Object', - streamingIngestion: 'Data Ingestion', - autoMerge: 'Auto-Merge', - TargetObject: 'Object', - JobType: 'Type', - project: 'Project', - status: 'Status', - dataDuration: 'Data Latency', - lastStatusChangeTime: 'Last Status Change Time', - lastStatusDuration: 'Last Status Duration', - Actions: 'Actions', - configurations: 'Configurations', - START: 'START', - STARTING: 'STARTING', - RUNNING: 'RUNNING', - STOPPING: 'STOPPING', - STOPPED: 'STOPPED', - STOP: 'STOP', - ERROR: 'ERROR', - clearAll: 'Clear All', - filteredTotalSize: '{totalSize} result(s)', - ProgressStatus: 'Status', - key: 'Key', - value: 'Value', - STREAMING_BUILD: 'STREAMING_BUILD', - STREAMING_MERGE: 'STREAMING_MERGE', - pleaseInputKey: 'Please enter the key', - pleaseInputValue: 'Please enter the value', - dataStatistics: 'Data Statistics', - jobRecords: 'Job Start and Stop Records', - noSelectJobs: 'Please select at least one job.', - recordStatus: 'Status Change Records', - consumptionRate: 'Consumption Rate', - dataLatency: 'Data Latency', - processingTime: 'Processing Time', - consumptionUnit: 'msg/s', - latencyUnit: 's', - processingUnit: 's', - isNoStatisticsData: 'No Statistics', - isNoRecords: 'No Records', - '30m': 'last 30 minutes', - '1h': 'last 1 hours', - '6h': 'last 6 hours', - '12h': 'last 12 hours', - '1d': 'last 1 day', - '3d': 'last 3 days', - '7d': 'last 7 days', - stopStreamingJobTips: 'Stopping the job(s) may take several minutes. Are you sure you want to stop the job(s)?', - stopStreamingJobImmeTips: 'Stopping the job immediately, some segments would be in "REFRESHING" or "LOCKED" state. They would be deleted when the job(s) starts again, or you could delete them manually. Are you sure you want to stop the job(s) immediately?', - stopJob: 'Stop Job', - stopJobImme: 'Stop Immediately', - mulParamsKeyTips: 'This key already exists.', - errorStautsTips: 'An unknown error occurred. Please contact the admin.', - errorStautsTips2: 'An unknown error occurred. Please download system diagnostic package to view the log or contact the admin.', - disableStartJobTips: 'Can\'t be used. Please add streaming indexes first.', - borkenModelDisableStartJobTips: 'Can\'t be used. Model {modelName} is currently broken.', - noPartitonColumnDisableStartJobTips: 'Can\'t be used. Please specify a timestamp field as the time partition column of this model.', - logInfoTip: 'Log', - sparkTaskDetails: 'Spark Info', - output: 'Output', - jobDiagnosis: 'Download Job Diagnostic Package' - } -} diff --git a/kystudio/src/components/monitor/streamingJobs/streamingJobs.vue b/kystudio/src/components/monitor/streamingJobs/streamingJobs.vue deleted file mode 100644 index e85a7a5dce..0000000000 --- a/kystudio/src/components/monitor/streamingJobs/streamingJobs.vue +++ /dev/null @@ -1,1108 +0,0 @@ -<template> - <div id="streamingJobListPage"> - <el-alert :title="$t('adminTips')" type="tip" class="admin-tips" v-if="isShowAdminTips" @close="closeTips" show-icon></el-alert> - <div class="streaming-jobs-list ksd-mrl-24"> - <div class="ksd-title-page ksd-mt-32">{{$t('streamingJobsList')}}</div> - <el-row :gutter="20" class="jobs_tools_row ksd-mtb-8"> - <el-col :span="16"> - <div class="action_groups ksd-btn-group-minwidth ksd-fleft" v-if="monitorActions.includes('jobActions')"> - <el-button type="primary" text size="medium" icon="el-ksd-icon-play_with_border_22" :disabled="!batchBtnsEnabled.start" :loading="startLoading" @click="batchStart">{{$t('jobStart')}}</el-button> - <el-button type="primary" text size="medium" icon="el-ksd-icon-resure_22" class="ksd-ml-2" :disabled="!batchBtnsEnabled.restart" :loading="restartLoading" @click="batchRestart">{{$t('jobRestart')}}</el-button> - <el-button type="primary" text size="medium" icon="el-ksd-icon-stop_with_border_22" class="ksd-ml-2" :disabled="!batchBtnsEnabled.stop" :loading="stopLoading" @click="batchStop(false)">{{$t('jobStop')}}</el-button> - <el-button type="primary" text size="medium" icon="el-ksd-icon-stop_with_border_22" class="ksd-ml-2" :disabled="!batchBtnsEnabled.stopImme" :loading="stopImmeLoading" @click="batchStop(true)">{{$t('stopJobImme')}}</el-button> - </div> - </el-col> - <el-col :span="8"> - <el-button type="primary" text size="medium" class="ksd-ml-2 ksd-fright" icon="el-ksd-icon-refresh_22" @click="manualRefreshJobs">{{$t('refreshList')}}</el-button><el-input - :placeholder="$t('pleaseSearch')" v-model="filter.model_name" v-global-key-event.enter.debounce="filterChange" @clear="filterChange()" class="show-search-btn ksd-fright" size="medium" prefix-icon="el-icon-search"> - </el-input> - </el-col> - </el-row> - <el-row class="filter-status-list" v-show="filterTags.length"> - <div class="tag-layout"> - <el-tag closable v-for="(item, index) in filterTags" :key="index" @close="handleClose(item)">{{`${$t(item.source)}${$t('kylinLang.common.colon')}${item.label}`}}</el-tag><span class="clear-all-tags" @click="handleClearAllTags">{{$t('clearAll')}}</span> - </div> - <span class="filter-job-size">{{$t('filteredTotalSize', {totalSize: jobTotal})}}</span> - </el-row> - <el-row :gutter="10" id="listBox"> - <el-col :span="showStep?18:24" id="leftStreamingTableBox" :class="{'show-steps': showStep}"> - <el-table class="ksd-el-table streaming-jobs-table" - tooltip-effect="dark" - v-scroll-shadow - ref="streamingJobsTable" - :data="jobsList" - highlight-current-row - :default-sort = "{prop: 'create_time', order: 'descending'}" - :empty-text="emptyText" - @sort-change="sortJobList" - @selection-change="handleSelectionChange" - @cell-click="showLineSteps" - :row-class-name="tableRowClassName" - :key="$store.state.project.isAllProject"> - <el-table-column - class-name="icon-column" - :selectable="setJobSelectable" - :checkbox-disable-tooltip="(row) => disableStartJobTips(row)" - checkbox-disable-tooltip-placement="top" - type="selection" align="center" width="32"></el-table-column> - <el-table-column class-name="icon-column" align="center" width="32" prop="icon" v-if="monitorActions.includes('jobActions')"> - <template slot-scope="scope"> - <i class="ksd-fs-22" :class="{ - 'el-ksd-icon-arrow_table_right_22': scope.row.uuid !== selectedJob.uuid || !showStep, - 'el-ksd-icon-arrow_table_down_22': scope.row.uuid == selectedJob.uuid && showStep}"></i> - </template> - </el-table-column> - <el-table-column - :label="$t('TargetObject')" - sortable="custom" - min-width="140" - :show-search-input="true" - :placeholder="$t('pleaseSearch')" - :emptyFilterText="$t('kylinLang.common.noData')" - :filter-filters-change="(v) => loadModelObjectList(v)" - customFilterClass="filter-submitter" - :filters="modelFilteArr.map(item => ({text: item, value: item}))" - :filtered-value="filter.model_names" - filter-icon="el-ksd-icon-filter_22" - :show-multiple-footer="false" - :filter-change="(v) => filterContent(v, 'model_names')" - show-overflow-tooltip - prop="model_alias"> - <template slot-scope="scope"> - <a class="link" @click="gotoModelList(scope.row)">{{scope.row.model_alias}}</a> - </template> - </el-table-column> - <el-table-column - :filters="jobTypeFilteArr.map(item => ({text: $t(item), value: item}))" - :filtered-value="filter.job_types" - :label="$t('JobType')" - filter-icon="el-ksd-icon-filter_22" - :show-multiple-footer="false" - :filter-change="(v) => filterContent(v, 'job_types')" - prop="job_type" - width="164"> - <template slot-scope="scope"> - {{$t(scope.row.job_type)}} - </template> - </el-table-column> - <el-table-column v-if="$store.state.project.isAllProject" - :label="$t('project')" - sortable='custom' - :width="120" - show-overflow-tooltip - prop="project"> - </el-table-column> - <el-table-column - width="180" - :filters="allStatus.map(item => ({text: $t(item), value: item}))" - :filtered-value="filter.status" :label="$t('status')" - filter-icon="el-ksd-icon-filter_22" - :show-multiple-footer="false" - :filter-change="(v) => filterContent(v, 'status')"> - <template slot-scope="scope"> - <common-tip :content="scope.row.launching_error?$t('errorStautsTips2'):$t('errorStautsTips')" :disabled="scope.row.job_status!=='ERROR'"> - <el-tag :type="jobStatus(scope.row.job_status)" size="small">{{$t(scope.row.job_status)}}</el-tag> - </common-tip> - </template> - </el-table-column> - <el-table-column - width="140" - sortable="custom" - prop="data_latency" - :label="$t('dataDuration')"> - <template slot-scope="scope"> - {{scope.row.data_latency | timeSize }} - </template> - </el-table-column> - <el-table-column - width="218" - :label="$t('lastStatusChangeTime')" - show-overflow-tooltip - prop="last_modified" - sortable="custom"> - <template slot-scope="scope"> - {{transToGmtTime(scope.row.last_modified)}} - </template> - </el-table-column> - <el-table-column - width="218" - :label="$t('lastStatusDuration')" - show-overflow-tooltip - prop="last_status_duration" - sortable="custom"> - <template slot-scope="scope"> - {{scope.row.last_status_duration | timeSize }} - </template> - </el-table-column> - <el-table-column - :label="$t('Actions')" - v-if="monitorActions.includes('jobActions')" - class-name="job-fc-icon" - width="96"> - <template slot-scope="scope"> - <common-tip :content="$t('jobDiagnosis')" v-if="monitorActions.includes('diagnostic')"> - <i class="el-icon-ksd-ostin_diagnose ksd-fs-14 ksd-ml-4" @click.stop="showDiagnosisDetail(scope.row.uuid)"></i> - </common-tip> - <common-tip :content="$t('configurations')"> - <i class="el-ksd-icon-controller_22 ksd-fs-22 ksd-ml-4" @click.stop="configJob(scope.row)"></i> - </common-tip> - <common-tip :content="$t('kylinLang.common.moreActions')" v-if="(!scope.row.launching_error&&scope.row.job_status!=='STARTING')||scope.row.yarn_app_url" > - <el-dropdown trigger="click"> - <span class="el-dropdown-link" @click.stop> - <common-tip :content="$t('kylinLang.common.moreActions')"> - <i class="el-icon-ksd-table_others ksd-fs-16"></i> - </common-tip> - </span> - <el-dropdown-menu slot="dropdown"> - <el-dropdown-item v-if="!scope.row.launching_error&&scope.row.job_status!=='STARTING'" @click.native="clickFile(scope.row)">{{$t('logInfoTip')}}</el-dropdown-item> - <el-dropdown-item v-if="scope.row.yarn_app_url" @click.native="skipToSparkDetail(scope.row)">{{$t('sparkTaskDetails')}}<i class="el-icon-ksd-export ksd-ml-4"></i></el-dropdown-item> - </el-dropdown-menu> - </el-dropdown> - </common-tip> - </template> - </el-table-column> - </el-table> - <kylin-pager :totalSize="jobTotal" :curPage="filter.page_offset+1" v-on:handleCurrentChange='currentChange' ref="jobPager" :refTag="pageRefTags.streamingJobPager" class="ksd-mtb-16 ksd-center" ></kylin-pager> - </el-col> - <el-col :span="6" v-if="showStep" id="rightDetail" :class="{'is-admin-tips': $store.state.user.isShowAdminTips&&isAdminRole}"> - <el-tabs v-model="jobDetailTab" @tab-click="handleChangeTab"> - <el-tab-pane :label="$t('dataStatistics')" name="statistics"> - <el-select class="ksd-fright" size="small" v-model="time_filter"> - <el-option - v-for="item in filterOptions" - :key="item.value" - :label="item.label" - :value="item.value"> - </el-option> - </el-select> - <div v-if="!isNoStatisticsData"> - <div class="data-consumption-chart"> - <div class="chart-title">{{$t('consumptionRate')}}</div> - <div id="consumption-chart" class="data-chart"></div> - </div> - <div class="data-latency-chart ksd-mt-16"> - <div class="chart-title">{{$t('dataLatency')}}</div> - <div id="latency-chart" class="data-chart"></div> - </div> - <div class="data-processing-chart ksd-mt-16"> - <div class="chart-title">{{$t('processingTime')}}</div> - <div id="processing-chart" class="data-chart"></div> - </div> - </div> - <kylin-nodata v-else :content="$t('isNoStatisticsData')"></kylin-nodata> - </el-tab-pane> - <el-tab-pane :label="$t('recordStatus')" name="records"> - <div class="ksd-list" v-if="selectedJobRecords.length"> - <p class="list" v-for="r in selectedJobRecords" :key="r.create_time"> - <span class="label">{{$t(r.action)}}</span><span class="text ksd-ml-24">{{transToGmtTime(r.create_time)}}</span> - </p> - </div> - <kylin-nodata v-else :content="$t('isNoRecords')"></kylin-nodata> - </el-tab-pane> - </el-tabs> - <div class='job-btn' id="jobDetailBtn" v-show="isShowBtn" :class="{'is-filter-list': filterTags.length}" @click='showStep=false'><i class='el-ksd-icon-arrow_right_16' aria-hidden='true'></i></div> - </el-col> - </el-row> - </div> - <el-dialog - :title="$t('configurations')" - append-to-body - class="configurations-dialog" - :close-on-press-escape="false" - :close-on-click-modal="false" - :visible.sync="showConfigurations" - @close="handleConfigurationsClose" - width="600px"> - <div> - <el-row :gutter="10"> - <el-col :span="14"><span class="title">{{$t('key')}}</span></el-col> - <el-col :span="6"><span class="title">{{$t('value')}}</span></el-col> - <el-col :span="4"></el-col> - </el-row> - <el-row :gutter="10" class="ksd-mt-10" v-for="(item, index) in paramsConfigs" :key="index"> - <el-col :span="14"> - <el-input v-model.trim="paramsConfigs[index][0]" - :disabled="paramsConfigs[index] && !!paramsConfigs[index][2].isDefault" - :class="{'is-mul-key': paramsConfigs[index][2].isMulParamsKey, 'is-empty': paramsConfigs[index][2].isEmpty&&!paramsConfigs[index][0]}" - @change="handleValidateParamsKey()" - :placeholder="$t('pleaseInputKey')"></el-input> - <div class="error-msg" v-if="paramsConfigs[index][2].isMulParamsKey&&!paramsConfigs[index][2].isDefault">{{$t('mulParamsKeyTips')}}</div> - </el-col> - <el-col :span="6"> - <el-input v-number2="paramsConfigs[index][1]" - v-model.trim="paramsConfigs[index][1]" - :class="{'is-empty': paramsConfigs[index][2].isEmpty&&!paramsConfigs[index][1]}" - :placeholder="$t('pleaseInputValue')" - @change="handleValidateParamsKey()" - v-if="numberParams.indexOf(item[0]) !== -1"></el-input> - <el-input v-else v-model.trim="paramsConfigs[index][1]" :class="{'is-empty': paramsConfigs[index][2].isEmpty&&!paramsConfigs[index][1]}" :placeholder="$t('pleaseInputValue')" /> - </el-col> - <el-col :span="4"> - <span class="action-btns ksd-ml-5"> - <el-button type="primary" icon="el-ksd-icon-add_22" plain circle size="small" @click="addParamsConfigs()"></el-button> - <el-button icon="el-ksd-icon-minus_22" class="ksd-ml-5" plain circle size="small" :disabled="[...buildDefaultParams, ...mergeDefaultParams].indexOf(item[0]) !== -1" @click="removeParamsConfigs(index)"></el-button> - </span> - </el-col> - </el-row> - </div> - <div slot="footer" class="dialog-footer ky-no-br-space"> - <el-button plain @click="handleConfigurationsClose">{{$t('kylinLang.common.cancel')}}</el-button> - <el-button type="primary" :loading="loadingSetting" @click="saveSettings">{{$t('kylinLang.common.save')}}</el-button> - </div> - </el-dialog> - <el-dialog - id="show-diagnos" - limited-area - :title="$t('output')" - :visible.sync="dialogVisible" - @close="handleCloseOutputDialog" - :close-on-press-escape="false" - :close-on-click-modal="false"> - <job_dialog :stepDetail="outputDetail" :showOutputJob="showOutputJob"></job_dialog> - <span slot="footer" class="dialog-footer"> - <el-button plain size="medium" @click="dialogVisible = false">{{$t('kylinLang.common.close')}}</el-button> - </span> - </el-dialog> - <diagnostic v-if="showDiagnostic" @close="showDiagnostic = false" :jobId="diagnosticId"/> - </div> -</template> - -<script> -import Vue from 'vue' -import { Component, Watch } from 'vue-property-decorator' -import { mapActions, mapGetters, mapMutations } from 'vuex' -import { cacheLocalStorage, objectClone, indexOfObjWithSomeKey, countObjWithSomeKey } from 'util/index' -import { handleError, handleSuccess, transToGmtTime, kylinConfirm } from 'util/business' -import { pageRefTags, bigPageCount } from 'config' -import $ from 'jquery' -import locales from './locales' -import { handleSuccessAsync } from 'util' -import charts from 'util/charts' -import echarts from 'echarts' -import jobDialog from '../job_dialog' -import Diagnostic from 'components/admin/Diagnostic/index' -@Component({ - methods: { - ...mapActions({ - loadStreamingJobsList: 'LOAD_STREAMING_JOBS_LIST', - getStreamingJobRecords: 'GET_STREAMING_JOB_RECORDS', - updateStreamingConfig: 'UPDATE_STREAMING_CONFIGURATIONS', - updateStreamingJobs: 'UPDATE_STREAMING_JOBS', - getStreamingChartData: 'GET_STREAMING_CHART_DATA', - getModelObjectList: 'GET_MODEL_OBJECT_LIST', - getJobSimpleLog: 'GET_JOB_SIMPLE_LOG' - }), - ...mapMutations({ - setProject: 'SET_PROJECT' - }), - ...mapActions('DetailDialogModal', { - callGlobalDetailDialog: 'CALL_MODAL' - }) - }, - components: { - 'job_dialog': jobDialog, - Diagnostic - }, - computed: { - ...mapGetters([ - 'currentSelectedProject', - 'monitorActions', - 'isAdminRole' - ]) - }, - locales -}) -export default class StreamingJobsList extends Vue { - pageRefTags = pageRefTags - transToGmtTime = transToGmtTime - filter = { - page_offset: 0, - page_size: +localStorage.getItem(this.pageRefTags.streamingJobPager) || bigPageCount, - job_types: [], - model_names: [], - sort_by: 'create_time', - reverse: true, - status: [], - model_name: '', - isAuto: false - } - startLoading = false - restartLoading = false - stopLoading = false - stopImmeLoading = false - batchBtnsEnabled = { - start: false, - restart: false, - stop: false, - stopImme: false - } - stCycle = null - showStep = false - jobDetailTab = 'statistics' - isNoStatisticsData = false - paramsConfigs = [] - filterTags = [] - jobsList = [] - jobTotal = 0 - multipleSelection = [] - isPausePolling = false - selectedJob = {} - settingJob = null - selectedJobRecords = [] - modelFilteArr = [] - filterOptions = [ - {value: '30', label: this.$t('30m')}, - {value: '60', label: this.$t('1h')}, - {value: '360', label: this.$t('6h')}, - {value: '720', label: this.$t('12h')}, - {value: '1440', label: this.$t('1d')}, - {value: '4320', label: this.$t('3d')}, - {value: '10080', label: this.$t('7d')} - ] - jobTypeFilteArr = ['STREAMING_BUILD', 'STREAMING_MERGE'] - allStatus = ['STARTING', 'RUNNING', 'STOPPING', 'ERROR', 'STOPPED'] - buildDefaultParams = ['spark.master', 'spark.driver.memory', 'spark.executor.instances', 'spark.executor.cores', 'spark.executor.memory', 'spark.sql.shuffle.partitions', 'kylin.streaming.duration', 'kylin.streaming.job-retry-enabled', 'kylin.streaming.kafka-conf.maxOffsetsPerTrigger'] - mergeDefaultParams = ['spark.master', 'spark.driver.memory', 'spark.executor.instances', 'spark.executor.cores', 'spark.executor.memory', 'spark.sql.shuffle.partitions', 'kylin.streaming.segment-max-size', 'kylin.streaming.segment-merge-threshold', 'kylin.streaming.job-retry-enabled'] - numberParams = ['spark.executor.cores', 'kylin.streaming.duration', 'spark.executor.instances', 'kylin.streaming.segment-merge-threshold', 'kylin.streaming.kafka-conf.maxOffsetsPerTrigger'] - showConfigurations = false - loadingSetting = false - consumpChart = null - latencyChart = null - processingChart = null - time_filter = '30' - isShowBtn = true - isMulParamsKey = false - dialogVisible = false - showOutputJob = null - outputDetail = '' - showDiagnostic = false - diagnosticId = '' - get isShowAdminTips () { - return this.$store.state.user.isShowAdminTips && this.isAdminRole && !this.$store.state.system.isShowGlobalAlter - } - get emptyText () { - return this.filter.key || this.filter.job_types.length || this.filter.status.length ? this.$t('kylinLang.common.noResults') : this.$t('kylinLang.common.noData') - } - - // 模型无索引时不让启动任务 - setJobSelectable (row) { - return row.model_indexes && row.model_indexes > 0 && !row.model_broken && !!row.partition_desc && !!row.partition_desc.partition_date_column - } - - disableStartJobTips (row) { - if (row.model_broken) { - return this.$t('borkenModelDisableStartJobTips', {modelName: row.model_alias}) - } else if (!(row.partition_desc && row.partition_desc.partition_date_column)) { - return this.$t('noPartitonColumnDisableStartJobTips') - } else { - return this.$t('disableStartJobTips') - } - } - - @Watch('$store.state.project.isAllProject') - selectAllProject (curVal) { - if (curVal) { - this.jobsList = [] - this.$nextTick(() => { - this.manualRefreshJobs() - this.loadModelObjectList() - }) - } - } - - closeTips () { - this.$store.state.user.isShowAdminTips = false - cacheLocalStorage('isHideAdminTips', true) - } - async batchStart () { - if (!this.batchBtnsEnabled.start) return - if (!this.multipleSelection.length) { - this.$message.warning(this.$t('noSelectJobs')) - } else { - try { - this.startLoading = true - const data = {project: this.currentSelectedProject, action: 'START', job_ids: this.idsArr} - if (this.$store.state.project.isAllProject) { - delete data.project - } - const res = await this.updateStreamingJobs(data) - await handleSuccessAsync(res) - this.startLoading = false - this.$message({ - type: 'success', - message: this.$t('kylinLang.common.actionSuccess') - }) - this.manualRefreshJobs() - } catch (e) { - handleError(e) - this.startLoading = false - } - } - } - async batchRestart () { - if (!this.batchBtnsEnabled.restart) return - if (!this.multipleSelection.length) { - this.$message.warning(this.$t('noSelectJobs')) - } else { - try { - this.restartLoading = true - const data = {project: this.currentSelectedProject, action: 'RESTART', job_ids: this.idsArr} - if (this.$store.state.project.isAllProject) { - delete data.project - } - const res = await this.updateStreamingJobs(data) - await handleSuccessAsync(res) - this.restartLoading = false - this.$message({ - type: 'success', - message: this.$t('kylinLang.common.actionSuccess') - }) - this.manualRefreshJobs() - } catch (e) { - handleError(e) - this.restartLoading = false - } - } - } - async stopJob (data, isStopImme) { - const loadingType = isStopImme ? 'stopImmeLoading' : 'stopLoading' - try { - this[loadingType] = true - const res = await this.updateStreamingJobs(data) - await handleSuccessAsync(res) - this[loadingType] = false - this.$message({ - type: 'success', - message: this.$t('kylinLang.common.actionSuccess') - }) - this.manualRefreshJobs() - } catch (e) { - handleError(e) - this[loadingType] = false - } - } - async batchStop (isStopImme) { - if (!isStopImme && !this.batchBtnsEnabled.stop) return - if (isStopImme && !this.batchBtnsEnabled.stopImme) return - if (!this.multipleSelection.length) { - this.$message.warning(this.$t('noSelectJobs')) - } else { - const msg = isStopImme ? this.$t('stopStreamingJobImmeTips') : this.$t('stopStreamingJobTips') - const stopJobType = isStopImme ? this.$t('stopJobImme') : this.$t('stopJob') - await kylinConfirm(msg, {confirmButtonText: stopJobType}, stopJobType) - const data = {project: this.currentSelectedProject, action: isStopImme ? 'FORCE_STOP' : 'STOP', job_ids: this.idsArr} - // const isSubmit = await this.callGlobalDetailDialog({ - // msg: this.$t('stopStreamingJobTips'), - // title: this.$t('stopJob'), - // dialogType: '', - // wid: '600px', - // showDetailBtn: false, - // isSubSubmit: true, - // submitSubText: this.$t('stopJob'), - // submitText: this.$t('stopJobImme') - // }) - // data.action = isSubmit.isOnlySave ? 'STOP' : 'FORCE_STOP' - if (this.$store.state.project.isAllProject) { - delete data.project - } - this.stopJob(data, isStopImme) - } - } - filterChange (val) { - this.searchLoading = true - this.filter.page_offset = 0 - this.manualRefreshJobs() - this.showStep = false - } - resetSelection () { - this.multipleSelection = [] - this.$refs.streamingJobsTable && this.$refs.streamingJobsTable.clearSelection && this.$refs.streamingJobsTable.clearSelection() - this.idsArrCopy = [] - this.idsArr = [] - } - configJob (rows) { - this.settingJob = rows - const defaultParams = rows.job_type === 'STREAMING_BUILD' ? this.buildDefaultParams : this.mergeDefaultParams - this.paramsConfigs = Object.entries(rows.params).map(it => ([...it, {isDefault: defaultParams.indexOf(it[0]) !== -1}])) - this.showConfigurations = true - } - handleConfigurationsClose (isSubmit) { - this.showConfigurations = false - if (isSubmit) { - this.loadList() - } - } - async clickFile (row) { - try { - const res = await this.getJobSimpleLog({ project: row.project, job_id: row.uuid }) - const data = await handleSuccessAsync(res) - this.outputDetail = data.cmd_output - this.showOutputJob = row - this.dialogVisible = true - } catch (e) { - handleError(e) - this.dialogVisible = false - this.showOutputJob = null - } - } - skipToSparkDetail (row) { - window.open(row.yarn_app_url) - } - handleCloseOutputDialog () { - this.showOutputJob = null - } - currentChange (size, count) { - this.filter.page_offset = size - this.filter.page_size = count - this.resetSelection() - this.getJobsList() - this.closeIt() - } - closeIt () { - if (this.showStep) { - this.showStep = false - } - } - // 增加配置 - addParamsConfigs () { - this.paramsConfigs.unshift(['', '', {isDefault: false}]) - } - // 删减配置 - removeParamsConfigs (index) { - this.paramsConfigs.splice(index, 1) - this.handleValidateParamsKey() - } - // 检测key是否重复 - handleValidateParamsKey () { - this.isMulParamsKey = false - this.paramsConfigs.forEach((p, index) => { - if (countObjWithSomeKey(this.paramsConfigs, 0, p[0]) > 1) { - this.$set(this.paramsConfigs[index][2], 'isMulParamsKey', true) - this.isMulParamsKey = true - } else { - this.$set(this.paramsConfigs[index][2], 'isMulParamsKey', false) - } - if (!p[0] || !p[1]) { - this.$set(this.paramsConfigs[index][2], 'isEmpty', true) - } - }) - } - saveSettings () { - this.handleValidateParamsKey() - const params = {} - let isEmptyValue - this.paramsConfigs.forEach((item, index) => { - if (!item[0] || !item[1]) { - isEmptyValue = true - } - params[item[0]] = item[1] - }) - if (isEmptyValue || this.isMulParamsKey) return // 默认参数有空值不能提交,key值重复不能提交 - this.loadingSetting = true - this.updateStreamingConfig({project: this.currentSelectedProject, job_id: this.settingJob.uuid, params}).then(() => { - this.loadingSetting = false - this.handleConfigurationsClose(true) - this.$message({ - type: 'success', - message: this.$t('kylinLang.common.actionSuccess') - }) - }).catch((e) => { - handleError(e) - this.loadingSetting = false - }) - } - // 删除单个筛选条件 - handleClose (tag) { - const index = this.filter[tag.key].indexOf(tag.label) - index > -1 && this.filter[tag.key].splice(index, 1) - this.filterTags = this.filterTags.filter(item => item.key !== tag.key || item.key === tag.key && tag.label !== item.label) - this.filter.page_offset = 0 - this.manualRefreshJobs() - } - // 清除所有的tags - handleClearAllTags () { - this.filter.page_offset = 0 - this.filter.model_names.splice(0, this.filter.model_names.length) - this.filter.job_types.splice(0, this.filter.job_types.length) - this.filter.status.splice(0, this.filter.status.length) - this.filterTags = [] - this.manualRefreshJobs() - } - sortJobList ({ column, prop, order }) { - if (order === 'ascending') { - this.filter.reverse = false - } else { - this.filter.reverse = true - } - this.filter.sort_by = prop - this.filter.page_offset = 0 - this.manualRefreshJobs() - } - handleSelectionChange (val) { - if (val && val.length) { - this.multipleSelection = val - this.isPausePolling = true - const selectedStatus = this.multipleSelection.map((item) => { - return item.job_status - }) - this.getBatchBtnStatus(selectedStatus) - this.idsArr = this.multipleSelection.map((item) => { - return item.uuid - }) - } else { - this.isPausePolling = false - this.multipleSelection = [] - this.batchBtnsEnabled = { - start: false, - restart: false, - stop: false, - stopImme: false - } - this.idsArr = [] - } - } - jobStatus (status) { - switch (status) { - case 'STARTING': return '' - case 'STOPPING': return '' - case 'STOPPED': return 'warning' - case 'ERROR': return 'danger' - default: return '' - } - } - getBatchBtnStatus (statusArr) { - const batchBtns = { - start: ['ERROR', 'STOPPED'], - restart: ['RUNNING'], - stop: ['RUNNING'], - stopImme: ['STARTING', 'RUNNING', 'STOPPING'] - } - $.each(batchBtns, (key, item) => { - this.batchBtnsEnabled[key] = this.isContain(item, statusArr) - }) - } - isContain (arr1, arr2) { - for (let i = arr2.length - 1; i >= 0; i--) { - if (!arr1.includes(arr2[i])) { - return false - } - } - return true - } - showLineSteps (row, column, cell) { - if (column.property === 'icon') { - var needShow = false - if (row.uuid !== this.selectedJob.uuid) { - needShow = true - } else { - needShow = !this.showStep - } - this.showStep = needShow - this.selectedJob = row - // this.jobDetailTab = 'statistics' - if (this.jobDetailTab === 'records') { - this.selectedJobRecords = [] - this.getRecordsData() - } else { - this.getChartData() - } - } - } - initLineChart (data) { - if (!this.showStep) return - if (data.create_time.length > 0) { - this.isNoStatisticsData = false - setTimeout(() => { - const consumptionId = document.getElementById('consumption-chart') - const latencyId = document.getElementById('latency-chart') - const processingId = document.getElementById('processing-chart') - const xDates = data.create_time && data.create_time.reverse().map(it => { - const dateSplit = transToGmtTime(+it).split(' ') - return dateSplit[0] + '\n' + dateSplit[1] + ' ' + dateSplit[2] - }) - const yConsumpVol = data.consumption_rate_hist.reverse() - const yLatencyVol = data.data_latency_hist.reverse() - const yProcessingVol = data.processing_time_hist.reverse() - const consumpDatas = {} - const latencyDatas = {} - const processingDatas = {} - data.create_time && data.create_time.forEach((k, index) => { - consumpDatas[k] = data.consumption_rate_hist[index] - latencyDatas[k] = data.data_latency_hist[index] - processingDatas[k] = data.processing_time_hist[index] - }) - this.consumpChart = echarts.init(consumptionId) - const consumpOption = charts.line(this, xDates, yConsumpVol, consumpDatas) - consumpOption.grid.left = 38 - consumpOption.yAxis.axisLabel.formatter = (val) => { - if (val > 0 && val < 1) { - return '' - } else if (val < 1000) { - return `${val}` - } else { - return `${val / 1000}K` - } - } - consumpOption.yAxis.name = this.$t('consumptionUnit') - consumpOption.tooltip.trigger = 'axis' - consumpOption.tooltip.formatter = (vals) => { - return `<div>${vals[0].name}</div><div>${vals[0].data} ${this.$t('consumptionUnit')}</div>` - } - this.consumpChart.setOption(consumpOption) - this.latencyChart = echarts.init(latencyId) - const latencyOption = charts.line(this, xDates, yLatencyVol, latencyDatas) - latencyOption.yAxis.axisLabel.formatter = (val) => { - if (val / 1000 < 1000) { - return `${val / 1000}` - } else { - return `${val / 1000 / 1000}K` - } - } - latencyOption.grid.left = 38 - latencyOption.yAxis.name = this.$t('latencyUnit') - latencyOption.tooltip.trigger = 'axis' - latencyOption.tooltip.formatter = (vals) => { - return `<span>${vals[0].name}: ${vals[0].data / 1000} ${this.$t('latencyUnit')}</span>` - } - this.latencyChart.setOption(latencyOption) - this.processingChart = echarts.init(processingId) - const processingOption = charts.line(this, xDates, yProcessingVol, processingDatas) - processingOption.yAxis.axisLabel.formatter = (val) => { - if (val / 1000 < 1000) { - return `${val / 1000}` - } else { - return `${val / 1000 / 1000}K` - } - } - processingOption.grid.left = 38 - processingOption.yAxis.name = this.$t('processingUnit') - processingOption.tooltip.trigger = 'axis' - processingOption.tooltip.formatter = (vals) => { - return `<span>${vals[0].name}: ${vals[0].data / 1000} ${this.$t('processingUnit')}</span>` - } - this.processingChart.setOption(processingOption) - }) - } else { - this.isNoStatisticsData = true - } - } - handleChangeTab (tab) { - if (tab.name === 'records') { - this.getRecordsData() - } else { - this.getChartData() - } - } - tableRowClassName ({row, rowIndex}) { - if (row.uuid === this.selectedJob.uuid && this.showStep) { - return 'current-row2' - } - } - gotoModelList (item) { - // 暂停轮询,清掉计时器 - clearTimeout(this.stCycle) - this.isPausePolling = true - // 如果是全 project 模式,需要先改变当前 project 选中值 - if (this.$store.state.project.isAllProject) { - this.setProject(item.project) - } - this.$router.push({name: 'ModelList', params: { modelAlias: item.model_alias }}) - } - // 查询状态过滤回调函数 - filterContent (val, type) { - const maps = { - job_types: 'JobType', - status: 'ProgressStatus', - model_names: 'TargetObject' - } - - this.filterTags = this.filterTags.filter((item, index) => item.key !== type || item.key === type && val.includes(item.label)) - const list = this.filterTags.filter(it => it.key === type).map(it => it.label) - val.length && val.forEach(item => { - if (!list.includes(item)) { - let label - if (type === 'model_names') { - label = item - } else { - label = this.$t(item) - } - this.filterTags.push({label: label, source: maps[type], key: type}) - } - }) - this.filter[type] = val - this.filter.page_offset = 0 - this.manualRefreshJobs() - } - getRecordsData () { - this.getStreamingJobRecords({project: this.selectedJob.project, job_id: this.selectedJob.uuid}).then((res) => { - handleSuccess(res, (data) => { - this.selectedJobRecords = data - }, (resError) => { - handleError(resError) - }) - }) - } - getChartData () { - this.getStreamingChartData({project: this.selectedJob.project, job_id: this.selectedJob.uuid, time_filter: this.time_filter}).then((res) => { - handleSuccess(res, (data) => { - this.initLineChart(data) - }) - }, (resError) => { - handleError(resError) - }) - } - getJobsList () { - return new Promise((resolve, reject) => { - if (!this.currentSelectedProject) return reject() - let data = {} - const statuses = this.filter.status.join(',') - Object.keys(this.filter).forEach(key => key !== 'status' && (data[key] = this.filter[key])) - this.loadStreamingJobsList({...data, statuses}).then((res) => { - handleSuccess(res, (data) => { - if (data.total_size) { - this.jobsList = data.value - if (this.selectedJob) { - const selectedIndex = indexOfObjWithSomeKey(this.jobsList, 'uuid', this.selectedJob.uuid) - if (selectedIndex !== -1) { - this.selectedJob = this.jobsList[selectedIndex] - if (this.jobDetailTab === 'records') { - this.getRecordsData() - } else { - this.getChartData() - } - } - } - if (this.multipleSelection.length) { - const cloneSelections = objectClone(this.multipleSelection) - this.multipleSelection = [] - cloneSelections.forEach((m) => { - const index = indexOfObjWithSomeKey(this.jobsList, 'uuid', m.uuid) - if (index !== -1) { - this.$nextTick(() => { - this.$refs.streamingJobsTable.toggleRowSelection(this.jobsList[index]) - }) - } - }) - } - this.jobTotal = data.total_size - } else { - this.jobsList = [] - this.jobTotal = 0 - } - this.searchLoading = false - }) - resolve() - }, (res) => { - handleError(res) - this.searchLoading = false - reject() - }) - }) - } - loadList () { - if (this.$store.state.project.isAllProject) { - delete this.filter.project - } else { - this.filter.project = this.currentSelectedProject - } - return this.getJobsList() - } - manualRefreshJobs () { - // 手动刷新部分,接口skip session 设为false - this.filter.isAuto = false - // this.waitingFilter.isAuto = false - this.resetSelection() - this.loadList() - } - refreshJobs () { - if (!this.isPausePolling) { - return this.loadList() - } else { - return new Promise((resolve) => { - resolve() - }) - } - } - autoFilter () { - if (this.stCycle) { - this.filter.isAuto = true - } - clearTimeout(this.stCycle) - this.stCycle = setTimeout(() => { - this.refreshJobs().then((res) => { - handleSuccess(res, (data) => { - if (this._isDestroyed) { - return - } - this.autoFilter() - }) - }, (res) => { - handleError(res) - }) - }, 5000) - } - async loadModelObjectList (filterValue) { - try { - const data = { project: this.currentSelectedProject, model_name: filterValue, page_size: 100 } - if (this.$store.state.project.isAllProject) { - delete data.project - } - const res = await this.getModelObjectList(data) - this.modelFilteArr = await handleSuccessAsync(res) - } catch (e) { - handleError(e) - } - } - created () { - // const { modelAlias, jobStatus } = this.$route.query - // modelAlias && (this.filter.subject = modelAlias) - // jobStatus && (this.filter.status = jobStatus) - // this.selectedJob = {} // 防止切换project时,发一个不存在该项目jobId的jobDetail的请求 - this.filter.project = this.currentSelectedProject - if (this.currentSelectedProject) { - this.autoFilter() - this.getJobsList() - this.loadModelObjectList() - } - } - isShowJobBtn (e) { - if (!e) return - const sTop = e.target.scrollTop - const rightDetailH = document.getElementById('rightDetail') && document.getElementById('rightDetail').clientHeight - let jobBtn = document.getElementById('jobDetailBtn') - if (jobBtn) { - const top = sTop > (rightDetailH - 20) ? rightDetailH - 70 : sTop - jobBtn.style.cssText = `top: ${top + 20}px;` - } - } - mounted () { - if (document.getElementById('scrollContent')) { - document.getElementById('scrollContent').addEventListener('scroll', this.isShowJobBtn, false) - } - } - beforeDestroy () { - clearTimeout(this.stCycle) - if (document.getElementById('scrollContent')) { - document.getElementById('scrollContent').removeEventListener('scroll', this.isShowJobBtn, false) - } - } - showDiagnosisDetail (id) { - this.diagnosticId = id - this.showDiagnostic = true - } -} -</script> - -<style lang="less"> - @import '../../../assets/styles/variables.less'; - #streamingJobListPage { - .jobs_tools_row { - font-size: 0px; - } - .show-search-btn { - width: 248px; - } - .streaming-jobs-table { - .icon-column { - .cell { - padding-left: 5px; - padding-right: 5px; - } - } - .el-ksd-icon-arrow_table_right_22, - .el-ksd-icon-arrow_table_down_22 { - color: @text-disabled-color; - } - .link{ - text-decoration: underline; - color:@base-color; - } - .el-ksd-icon-controller_22, - .el-ksd-icon-log_22 { - cursor: pointer; - } - } - #rightDetail { - width: 410px; - border-radius: 0; - box-shadow: -3px 3px 5px @ke-color-secondary; - border: 0; - padding: 16px 0 16px 16px !important; - min-height: calc(~'100vh - 168px'); - position: relative; - &.is-admin-tips { - min-height: calc(~'100vh - 205px'); - } - .el-tabs__content { - overflow: visible; - min-height: calc(~'100vh - 260px'); - .el-radio-group { - position: absolute; - right: 0px; - } - } - .job-btn { - position: absolute; - // right: 345px; - left: -9px; - top: 20px; - height: 24px; - width: 24px; - border-radius: 100%; - box-shadow: 0px 2px 8px rgba(50, 73, 107, 0.24); - cursor: pointer; - text-align: center; - background-color: @fff; - z-index: 10; - &.is-filter-list { - top: 270px; - } - i { - font-size: 16px; - margin-top: 2px; - } - &:hover { - background-color: @ke-color-primary-hover; - i { - color: @fff; - } - } - &:active { - background-color: @ke-color-primary-active; - } - } - .chart-title { - color: @text-title-color; - font-size: 14px; - line-height: 22px; - margin-bottom: 12px; - } - .data-chart { - height: 125px; - } - .record-title { - color: @text-normal-color; - font-size: 14px; - line-height: 22px; - font-weight: @font-medium; - margin-top: 24px; - } - } - #leftStreamingTableBox { - width: 100%; - &.show-steps { - width: calc(~'100% - 410px'); - } - } - } - .configurations-dialog { - .error-msg { - color: @ke-color-danger; - } - .is-mul-key .el-input__inner, - .is-empty .el-input__inner{ - border-color: #E03B3B; - box-shadow: 0px 0px 0px 2px rgba(218, 8, 8, 0.1); - } - } -</style> diff --git a/kystudio/src/components/project/project_list.vue b/kystudio/src/components/project/project_list.vue index e0403af7bc..db8f702288 100644 --- a/kystudio/src/components/project/project_list.vue +++ b/kystudio/src/components/project/project_list.vue @@ -2,7 +2,7 @@ <div class="paddingbox" id="project-list"> <div class="ksd-title-label ksd-mt-20">{{$t('projectsList')}}</div> <div> - <el-button type="primary" size="medium" class="ksd-mb-10 ksd-mt-10" icon="el-ksd-icon-add_22" v-if="projectActions.includes('addProject')" @click="newProject">{{$t('kylinLang.common.project')}}</el-button> + <el-button type="primary" size="medium" class="ksd-mb-10 ksd-mt-10" icon="el-ksd-icon-add_22" v-if="projectActions.includes('addProject')" @click="newProject">{{$t('kylinLang.common.new')}}</el-button> <div style="width:240px;" class="ksd-fright ksd-mtb-10"> <el-input class="show-search-btn" size="medium" @@ -182,13 +182,13 @@ import { Component } from 'vue-property-decorator' delProjectTitle: 'Delete Project', cancel: 'Cancel', yes: 'Ok', - saveSuccessful: 'Added the project successfully.', - saveFailed: 'Can\'t add the project at the moment.', + saveSuccessful: 'Created the project successfully.', + saveFailed: 'Can\'t create the project at the moment.', deleteProjectTip: 'The project "{projectName}" cannot be restored after deletion. Are you sure you want to delete?', projectConfig: 'Configuration', backupProject: 'Are you sure you want to backup this project ?', - noProject: 'No project was found. Please click the button to add a project.', - projectsList: 'Project List', + noProject: 'No project was found. Please click the button to new a project.', + projectsList: 'Project', projectFilter: 'Search by project name', backupPro: 'Backup Project', author: 'Authorization', diff --git a/kystudio/src/components/studio/StudioModel/ModelList/ModelAddModal/addmodel.vue b/kystudio/src/components/studio/StudioModel/ModelList/ModelAddModal/addmodel.vue index e0c1a5bee2..a6bd3e06d1 100644 --- a/kystudio/src/components/studio/StudioModel/ModelList/ModelAddModal/addmodel.vue +++ b/kystudio/src/components/studio/StudioModel/ModelList/ModelAddModal/addmodel.vue @@ -18,7 +18,7 @@ </el-form> <div slot="footer" class="dialog-footer ky-no-br-space"> <el-button @click="closeModal" size="medium">{{$t('kylinLang.common.cancel')}}</el-button> - <el-button type="primary" @click="submit" :loading="btnLoading" size="medium">{{$t('kylinLang.common.submit')}}</el-button> + <el-button type="primary" @click="submit" :loading="btnLoading" size="medium">{{$t('kylinLang.common.create')}}</el-button> </div> </el-dialog> </template> diff --git a/kystudio/src/components/studio/StudioModel/ModelList/ModelLayout/modelLayout.vue b/kystudio/src/components/studio/StudioModel/ModelList/ModelLayout/modelLayout.vue index d56c6e5a0b..f80774ee07 100644 --- a/kystudio/src/components/studio/StudioModel/ModelList/ModelLayout/modelLayout.vue +++ b/kystudio/src/components/studio/StudioModel/ModelList/ModelLayout/modelLayout.vue @@ -109,9 +109,6 @@ <el-tab-pane class="tab-pane-item" :label="$t('developers')" name="fifth"> <Developers v-if="currentModelRow.tabTypes === 'fifth'" :currentModelRow="currentModelRow"/> </el-tab-pane> - <!-- <el-tab-pane class="tab-pane-item" :label="$t('streaming')" name="streaming" v-if="currentModelRow.model_type !== 'BATCH'"> - <ModelStreamingJob v-if="currentModelRow.tabTypes === 'streaming'" class="ksd-mrl-15 ksd-mt-15" :model="currentModelRow.uuid"/> - </el-tab-pane> --> </el-tabs> <!-- 模型构建 --> @@ -154,7 +151,6 @@ import ModelActions from '../ModelActions/modelActions' import ModelRenameModal from '../ModelRenameModal/rename.vue' import ModelCloneModal from '../ModelCloneModal/clone.vue' import ModelPartition from '../ModelPartition/index.vue' -import ModelStreamingJob from '../ModelStreamingJob/ModelStreamingJob.vue' import ModelTitleDescription from '../Components/ModelTitleDescription' @Component({ @@ -224,7 +220,6 @@ import ModelTitleDescription from '../Components/ModelTitleDescription' ModelRenameModal, ModelCloneModal, ModelPartition, - ModelStreamingJob, ModelTitleDescription }, locales diff --git a/kystudio/src/components/studio/StudioModel/ModelList/ModelStreamingJob/ModelStreamingJob.vue b/kystudio/src/components/studio/StudioModel/ModelList/ModelStreamingJob/ModelStreamingJob.vue deleted file mode 100644 index 8398ed175c..0000000000 --- a/kystudio/src/components/studio/StudioModel/ModelList/ModelStreamingJob/ModelStreamingJob.vue +++ /dev/null @@ -1,362 +0,0 @@ -<template> - <div class="streaming-job"> - <div class="ksd-title-label-small streaming-header"> - <span>{{$t('streaming')}}</span> - <div class="actions"> - <el-button @click="refreshJobInfo" type="primary" :loading="isRefreshJobInfoLoading" text>{{$t('refresh')}}</el-button> - <el-button @click="stopStreaming" type="primary" :loading="isStopLoading" icon="el-icon-ksd-stop" :disabled="isDisabled" text v-if="statusOptions.streamingIngestion === 'RUNNING' || statusOptions.autoMerge === 'RUNNING'">{{$t('stop')}}</el-button><el-button @click="startStreaming" type="primary" :loading="isStartLoading" icon="el-icon-ksd-restart" text v-else :disabled="isDisabled">{{$t('restart')}}</el-button><el-dropdown trigger="click" class="ksd-ml-10" @command="handleCommand"> - <el-button type="primary" icon="el-icon-ksd-configurations" text>{{$t('setting')}}</el-button> - <el-dropdown-menu slot="dropdown"> - <!-- <el-dropdown-item command="log">{{$t('logDetails')}}</el-dropdown-item> --> - <el-dropdown-item command="configurations">{{$t('configurations')}}</el-dropdown-item> - </el-dropdown-menu> - </el-dropdown> - <!-- <span class="item" @click="startStreaming"><i class="el-icon-ksd-table_resume ksd-mr-5"></i>{{$t('restart')}}</span> - <span class="item" @click="stopStreaming"><i class="el-icon-ksd-login_intro ksd-mr-5"></i>{{$t('setting')}}</span> --> - </div> - </div> - <el-row :gutter="15" class="ksd-mt-10"> - <el-col :span="5"> - <div class="job-info"> - <div class="job-sub-title ksd-mb-15">{{$t('status')}}</div> - <p class="contain job-status" v-for="item in Object.keys(statusOptions)" :key="item"> - <span class="title">{{$t(item)}}:</span> - <span class="status"><span :class="['flag', statusOptions[item].toLocaleLowerCase(), 'ksd-mr-5']"></span><span>{{$t(statusOptions[item])}}</span></span> - </p> - </div> - </el-col> - <el-col :span="8"> - <div class="job-info"> - <div class="job-sub-title ksd-mb-15">{{$t('metrics')}}</div> - <p class="contain average-metrics" v-for="item in Object.keys(metricsOptions)" :key="item"> - <span class="title">{{$t(item)}}</span> - <span>{{metricsOptions[item]}}</span> - </p> - </div> - </el-col> - <el-col :span="11"> - <div class="job-info"> - <div class="job-sub-title ksd-mb-15">{{$t('dataIngestion')}}</div> - <p class="contain dataIngestion" v-for="item in Object.keys(dataIngestionOptions)" :key="item"> - <span class="title">{{$t(item)}}</span> - <span>{{dataIngestionOptions[item]}}</span> - </p> - </div> - </el-col> - </el-row> - <el-dialog - :title="$t('configurations')" - append-to-body - class="configurations-dialog" - :close-on-press-escape="false" - :close-on-click-modal="false" - :visible.sync="showConfigurations" - @close="handleClose" - width="480px"> - <div> - <el-tabs v-model="paramsTab" type="card" @tab-click="handleClickTab"> - <el-tab-pane :label="tab.label" :name="tab.name" v-for="tab in paramsConfigTabs" :key="tab.name"> - <el-row :gutter="10"> - <el-col :span="14"><span class="title">{{$t('key')}}</span></el-col> - <el-col :span="6"><span class="title">{{$t('value')}}</span></el-col> - <el-col :span="4"></el-col> - </el-row> - <el-row :gutter="10" class="ksd-mt-10" v-for="(item, index) in tab.config" :key="index"> - <el-col :span="14"><el-input v-model.trim="tab.config[index][0]" :disabled="tab.config[index] && !!tab.config[index][2]" :placeholder="$t('pleaseInputKey')" /></el-col> - <el-col :span="6"> - <el-input v-number2="tab.config[index][1]" v-model.trim="tab.config[index][1]" :placeholder="$t('pleaseInputValue')" :class="{'is-empty': !tab.config[index][1]}" v-if="numberParams.indexOf(item[0]) !== -1"></el-input> - <el-input v-else v-model.trim="tab.config[index][1]" :class="{'is-empty': !tab.config[index][1]}" :placeholder="$t('pleaseInputValue')" /> - </el-col> - <!-- <el-col :span="4"> - <span class="action-btns ksd-ml-5"> - <el-button type="primary" icon="el-icon-ksd-add_2" plain circle size="mini" @click="addParamsConfigs(tab.type)"></el-button> - <el-button icon="el-icon-minus" class="ksd-ml-5" plain circle size="mini" :disabled="tab.config.length === 1 && index === 0 || (tab.config[index] && !!tab.config[index][2])" @click="removeParamsConfigs(tab.type, index)"></el-button> - </span> - </el-col> --> - </el-row> - </el-tab-pane> - </el-tabs> - </div> - <div slot="footer" class="dialog-footer ky-no-br-space"> - <el-button plain @click="handleClose">{{$t('kylinLang.common.cancel')}}</el-button> - <el-button type="primary" :loading="loadingSetting" @click="saveSettings">{{$t('kylinLang.common.save')}}</el-button> - </div> - </el-dialog> - </div> -</template> - -<script> -import Vue from 'vue' -import { Component } from 'vue-property-decorator' -import { handleSuccessAsync, handleError } from 'util/index' -import { mapActions, mapGetters } from 'vuex' -import locales from './locales' -import { kylinConfirm, objectClone, transToGmtTime } from '../../../../../util' - -@Component({ - name: 'ModelStreamingJob', - props: ['model'], - locales, - computed: { - ...mapGetters([ - 'currentSelectedProject' - ]) - }, - methods: { - ...mapActions({ - getStreamingJob: 'GET_STREAMING_JOB', - changeStreamingJobStatus: 'CHANGE_STREAMING_JOB_STATUS', - updateStreamingConfig: 'UPDATE_STREAMING_CONFIGURATIONS' - }) - } -}) -export default class ModelStreamingJob extends Vue { - statusOptions = { - streamingIngestion: '', - autoMerge: '' - } - metricsOptions = { - avg_consume_rate_in_5mins: '-', - avg_consume_rate_in_15mins: '-', - avg_consume_rate_in_30mins: '-', - avg_consume_rate_in_All: '-' - } - dataIngestionOptions = { - last_build_time: '-', - last_update_time: '-', - latency: '-' - } - loadingSetting = false - showConfigurations = false - isStartLoading = false - isStopLoading = false - isRefreshJobInfoLoading = false - paramsTab = 'buildParams' - buildParamsConfigs = [[]] - buildParamsConfigsCache = [[]] - mergeParamsConfigs = [[]] - mergeParamsConfigsCache = [[]] - commonParamsConfigs = [[]] - buildDefaultParams = ['spark.master', 'spark.driver.memory', 'spark.executor.instances', 'spark.executor.cores', 'spark.executor.memory', 'spark.sql.shuffle.partitions', 'kylin.streaming.duration', 'kylin.streaming.job-retry-enabled', 'kylin.streaming.kafka-conf.maxOffsetsPerTrigger', 'kylin.streaming.watermark'] - mergeDefaultParams = ['spark.master', 'spark.driver.memory', 'spark.executor.instances', 'spark.executor.cores', 'spark.executor.memory', 'spark.sql.shuffle.partitions', 'kylin.streaming.segment-max-size', 'kylin.streaming.segment-merge-threshold', 'kylin.streaming.job-retry-enabled'] - numberParams = ['spark.executor.cores', 'kylin.streaming.duration', 'spark.executor.instances', 'kylin.streaming.segment-merge-threshold'] - get paramsConfigTabs () { - return [ - {label: this.$t('streamingIngestion'), name: 'buildParams', config: this.buildParamsConfigs, type: 'build', actions: {add: this.addParamsConfigs, remove: this.removeParamsConfigs}}, - {label: this.$t('autoMerge'), name: 'mergeParams', config: this.mergeParamsConfigs, type: 'merge', actions: {add: this.addParamsConfigs, remove: this.removeParamsConfigs}} - // {label: 'p3', name: 'commonParams', config: this.commonParamsConfigs, type: 'common', actions: {add: this.addParamsConfigs, remove: this.removeParamsConfigs}} - ] - } - get isDisabled () { - return this.statusOptions.streamingIngestion === 'STARTING' || this.statusOptions.streamingIngestion === 'STOPPING' || this.statusOptions.autoMerge === 'STARTING' || this.statusOptions.autoMerge === 'STOPPING' - } - refreshJobInfo () { - this.initData() - } - initData () { - this.getStreamingJob({project: this.currentSelectedProject, model_id: this.model}).then(async (res) => { - const results = await handleSuccessAsync(res) - const { build_job_meta, merge_job_meta, avg_consume_rate_in_5mins, avg_consume_rate_in_15mins, avg_consume_rate_in_30mins, avg_consume_rate_in_All, last_update_time, last_build_time, latency } = results - this.metricsOptions = { - avg_consume_rate_in_5mins: avg_consume_rate_in_5mins > 10000 ? (avg_consume_rate_in_5mins / 1000).toFixed(2) + ' kmsg/s' : avg_consume_rate_in_5mins.toFixed(2) + ' msg/s', - avg_consume_rate_in_15mins: avg_consume_rate_in_15mins > 10000 ? (avg_consume_rate_in_15mins / 1000).toFixed(2) + ' kmsg/s' : avg_consume_rate_in_15mins.toFixed(2) + ' msg/s', - avg_consume_rate_in_30mins: avg_consume_rate_in_30mins > 10000 ? (avg_consume_rate_in_30mins / 1000).toFixed(2) + ' kmsg/s' : avg_consume_rate_in_30mins.toFixed(2) + ' msg/s', - avg_consume_rate_in_All: avg_consume_rate_in_All > 10000 ? (avg_consume_rate_in_All / 1000).toFixed(2) + ' kmsg/s' : avg_consume_rate_in_All.toFixed(2) + ' msg/s' - } - this.dataIngestionOptions = { - last_build_time: last_build_time ? transToGmtTime(last_build_time) : '-', - last_update_time: last_update_time ? transToGmtTime(last_update_time) : '-', - latency: latency ? (latency / 60 / 1000).toFixed(2) + ' mins' : '-' - } - this.statusOptions.streamingIngestion = build_job_meta.job_status === 'NEW' ? 'STOPPED' : build_job_meta.job_status - this.statusOptions.autoMerge = merge_job_meta.job_status === 'NEW' ? 'STOPPED' : merge_job_meta.job_status - this.buildParamsConfigs = Object.entries(build_job_meta.params).map(it => ([...it, this.buildDefaultParams.indexOf(it[0]) !== -1])) - this.buildParamsConfigsCache = objectClone(this.buildParamsConfigs) - this.mergeParamsConfigs = Object.entries(merge_job_meta.params).map(it => ([...it, this.mergeDefaultParams.indexOf(it[0]) !== -1])) - this.mergeParamsConfigsCache = objectClone(this.mergeParamsConfigs) - }).catch((e) => { - handleError(e) - }) - } - // 开启任务 - async startStreaming () { - if (this.isStartLoading) return - try { - this.isStartLoading = true - const res = await this.changeStreamingJobStatus({project: this.currentSelectedProject, model_id: this.model, action: 'START'}) - await handleSuccessAsync(res) - this.isStartLoading = false - this.initData() - } catch (e) { - this.isStartLoading = false - handleError(e) - this.initData() - } - } - // 终止任务 - async stopStreaming () { - if (this.isStopLoading) return - await kylinConfirm(this.$t('cofirmStopStreaming'), {confirmButtonText: this.$t('stop')}, this.$t('stopStreamingTitle')) - try { - this.isStopLoading = true - const res = await this.changeStreamingJobStatus({project: this.currentSelectedProject, model_id: this.model, action: 'STOP'}) - await handleSuccessAsync(res) - this.isStopLoading = false - this.initData() - } catch (e) { - this.isStopLoading = false - handleError(e) - this.initData() - } - } - handleCommand (command) { - if (command === 'configurations') { - this.showConfigurations = true - this.buildParamsConfigs = objectClone(this.buildParamsConfigsCache) - this.mergeParamsConfigs = objectClone(this.mergeParamsConfigsCache) - } - } - // 关闭配置弹窗 - handleClose () { - this.showConfigurations = false - this.initData() - } - // 更新配置 - saveSettings () { - this.loadingSetting = true - const buildParams = {} - const mergeParams = {} - this.buildParamsConfigs.forEach(item => { - buildParams[item[0]] = item[1] - }) - this.mergeParamsConfigs.forEach(item => { - mergeParams[item[0]] = item[1] - }) - this.updateStreamingConfig({project: this.currentSelectedProject, model_id: this.model, build_params: buildParams, merge_params: mergeParams}).then(() => { - this.loadingSetting = false - this.handleClose() - }).catch((e) => { - handleError(e) - this.loadingSetting = false - }) - } - // 增加配置 - addParamsConfigs (type) { - this[`${type}ParamsConfigs`].push([]) - } - // 删减配置 - removeParamsConfigs (type, index) { - this[`${type}ParamsConfigs`].splice(index, 1) - } - handleClickTab () { - } - created () { - this.initData() - } -} -</script> -<style lang="less"> - @import '../../../../../assets/styles/variables.less'; - .streaming-job { - margin: 15px; - padding: 15px; - box-shadow: none; - border: 1px solid @line-border-color4; - background-color: @fff; - .streaming-header { - position: relative; - .actions { - position: absolute; - top: 0; - right: 0; - .item { - padding: 0 5px; - cursor: pointer; - &:hover { - color: @color-primary; - } - } - } - } - .job-info { - padding: 15px; - background-color: @regular-background-color; - font-size: 12px; - box-sizing: border-box; - .job-sub-title { - color: @color-text-secondary; - } - .contain { - margin-bottom: 10px; - &.average-metrics { - display: inline-block; - width: 50%; - margin-bottom: 10px; - &:nth-last-child(2) { - margin-bottom: 0; - } - } - &.dataIngestion { - display: inline-block; - margin-bottom: 10px; - margin-right: 30px; - &:nth-last-child(2) { - margin-bottom: 0; - } - } - .title { - color: @color-text-primary; - font-size: 12px; - font-weight: bold; - } - &.job-status { - .title { - width: 120px; - display: inline-block; - } - } - .status { - color: @color-text-primary; - font-size: 12px; - font-weight: bold; - display: inline-flex; - align-items: center; - vertical-align: top; - } - &:last-child { - margin-bottom: 0; - } - .flag { - display: inline-block; - width: 12px; - height: 12px; - border-radius: 100%; - &.running { - background: @color-success; - } - &.error { - background: @error-color-1; - } - &.stopped { - background: @color-text-disabled; - } - &.starting, - &.stopping { - background: @base-color; - } - } - } - } - } - .configurations-dialog { - .action-btns { - .el-button { - // margin-top: 3px; - } - } - .el-dialog__body { - max-height: 350px; - overflow: auto; - } - } -</style> diff --git a/kystudio/src/components/studio/StudioModel/ModelList/ModelStreamingJob/locales.js b/kystudio/src/components/studio/StudioModel/ModelList/ModelStreamingJob/locales.js deleted file mode 100644 index 8365fc6040..0000000000 --- a/kystudio/src/components/studio/StudioModel/ModelList/ModelStreamingJob/locales.js +++ /dev/null @@ -1,34 +0,0 @@ -export default { - 'en': { - streaming: 'Streaming', - status: 'Status', - streamingIngestion: 'Data Ingestion', - autoMerge: 'Auto-Merge', - RUNNING: 'Running', - ERROR: 'Error', - STOPPED: 'Stopped', - STARTING: 'Restarting', - STOPPING: 'Stopping', - metrics: 'Metrics', - avg_consume_rate_in_5mins: '5 Minute Rate: ', - avg_consume_rate_in_15mins: '15 Minutes Rate: ', - avg_consume_rate_in_30mins: '30 Minutes Rate: ', - avg_consume_rate_in_All: 'Ave Rate: ', - dataIngestion: 'Last Event Time: ', - last_build_time: 'Event Time: ', - last_update_time: 'Processing Finish Time: ', - latency: 'Data Latency: ', - restart: 'Restart', - stop: 'Stop', - refresh: 'Refresh', - setting: 'Setting', - logDetails: 'Logs', - configurations: 'Configurations', - key: 'Key', - value: 'Value', - pleaseInputKey: 'Please enter the key', - pleaseInputValue: 'Please enter the value', - cofirmStopStreaming: 'Are you sure you want to stop the streaming job?', - stopStreamingTitle: 'Stop Job' - } -} diff --git a/kystudio/src/components/studio/StudioModel/ModelList/index.vue b/kystudio/src/components/studio/StudioModel/ModelList/index.vue index 3e246bfeef..57c4a18ff3 100644 --- a/kystudio/src/components/studio/StudioModel/ModelList/index.vue +++ b/kystudio/src/components/studio/StudioModel/ModelList/index.vue @@ -1,21 +1,11 @@ <template> <div class="mode-list" :class="{'full-cell': showFull}" id="modelListPage"> - <div class="ksd-title-page ksd-mt-32">{{$t('kylinLang.model.modelList')}}</div> - <div class="model-list-contain ksd-mt-16"> - <div class="clearfix"> - <div class="ksd-fright"> - <el-input :placeholder="$t('filterModelOrOwner')" style="width:250px" size="medium" :prefix-icon="searchLoading? 'el-ksd-icon-loading_22':'el-ksd-icon-search_22'" :value="filterArgs.model_alias_or_owner" @input="handleFilterInput" v-global-key-event.enter.debounce="searchModels" @clear="searchModels()" class="show-search-btn" > - </el-input> - <el-button - text - class="filter-button" - type="primary" - @click="handleToggleFilters"> - <span>{{$t('filterButton')}}</span> - <i :class="['el-ksd-icon-arrow_up_22', isShowFilters && 'reverse']" /> - </el-button> - </div> - <div class="ky-no-br-space model-list-header clearfix"> + <div class="clearfix ksd-mt-32"> + <div class="ksd-fleft"> + <div class="ksd-title-page">{{$t('kylinLang.model.modelList')}}</div> + </div> + <div class="ksd-fright"> + <div class="ky-no-br-space model-list-header"> <el-dropdown split-button class="ksd-fleft" @@ -25,7 +15,7 @@ placement="bottom-start" btn-icon="el-ksd-icon-add_22" v-if="datasourceActions.includes('modelActions')" - @click="showAddModelDialog">{{$t('kylinLang.common.model')}} + @click="showAddModelDialog">{{$t('kylinLang.common.new')}} <el-dropdown-menu slot="dropdown" class="model-actions-dropdown"> <el-dropdown-item v-if="metadataActions.includes('executeModelMetadata')" @@ -41,49 +31,58 @@ </common-tip> </div> </div> - <div class="table-filters clearfix ksd-mt-24" v-show="isShowFilters"> - <DropdownFilter - type="checkbox" - trigger="click" - :value="filterArgs.status" - hideArrow - @input="v => filterContent(v, 'status')" - :options="[ - { renderLabel: renderStatusLabel, value: 'ONLINE' }, - { renderLabel: renderStatusLabel, value: 'OFFLINE' }, - { renderLabel: renderStatusLabel, value: 'BROKEN' }, - { renderLabel: renderStatusLabel, value: 'WARNING' }, - ]"> - <el-button text type="primary" iconr="el-ksd-icon-arrow_down_22">{{$t('status_c')}}{{selectedStatus}}</el-button> - </DropdownFilter> - <DropdownFilter - class="ksd-ml-8" - type="datetimerange" - trigger="click" - :value="filterArgs.last_modify" - hideArrow - :shortcuts="['lastDay', 'lastWeek', 'lastMonth']" - @input="v => filterContent(v, 'last_modify')"> - <el-button text type="primary" iconr="el-ksd-icon-arrow_down_22">{{$t('lastModifyTime_c')}}{{selectedRange}}</el-button> - </DropdownFilter> - <DropdownFilter - class="ksd-ml-8" - type="checkbox" - trigger="click" - hideArrow - :value="filterArgs.model_attributes" - :options="modelAttributesOptions" - @input="v => filterContent(v, 'model_attributes')"> - <el-button text type="primary" iconr="el-ksd-icon-arrow_down_22">{{$t('modelType_c')}}{{selectedModelAttributes}}</el-button> - </DropdownFilter> - <div class="actions"> - <el-button - text - type="primary" - icon="el-ksd-icon-resure_22" - class="reset-filters-btn" - :disabled="isResetFilterDisabled" - @click="handleResetFilters">{{$t('reset')}}</el-button> + </div> + <div class="model-list-contain ksd-mt-16"> + <!-- <div class="layout-mask" v-if="loadingModels"></div> --> + <div class="clearfix"> + <div class="table-filters ksd-fleft"> + <DropdownFilter + type="checkbox" + trigger="click" + :value="filterArgs.status" + hideArrow + @input="v => filterContent(v, 'status')" + :options="[ + { renderLabel: renderStatusLabel, value: 'ONLINE' }, + { renderLabel: renderStatusLabel, value: 'OFFLINE' }, + { renderLabel: renderStatusLabel, value: 'BROKEN' }, + { renderLabel: renderStatusLabel, value: 'WARNING' }, + ]"> + <el-button text type="primary" iconr="el-ksd-icon-arrow_down_22">{{$t('status_c')}}{{selectedStatus.length > 1 ? `${selectedStatus[0]} +${selectedStatus.length - 1}` : selectedStatus.join('')}}</el-button> + </DropdownFilter> + <DropdownFilter + class="ksd-ml-8" + type="datetimerange" + trigger="click" + :value="filterArgs.last_modify" + hideArrow + :shortcuts="['lastDay', 'lastWeek', 'lastMonth']" + @input="v => filterContent(v, 'last_modify')"> + <el-button text type="primary" iconr="el-ksd-icon-arrow_down_22">{{$t('lastModifyTime_c')}}{{selectedRange}}</el-button> + </DropdownFilter> + <DropdownFilter + class="ksd-ml-8" + type="checkbox" + trigger="click" + hideArrow + :value="filterArgs.model_attributes" + :options="modelAttributesOptions" + @input="v => filterContent(v, 'model_attributes')"> + <el-button text type="primary" iconr="el-ksd-icon-arrow_down_22">{{$t('modelType_c')}}{{selectedModelAttributes.length > 1 ? `${selectedModelAttributes[0]} +${selectedModelAttributes.length - 1}` : selectedModelAttributes.join('')}}</el-button> + </DropdownFilter> + <div class="actions"> + <el-button + text + type="primary" + icon="el-ksd-icon-resure_22" + class="reset-filters-btn" + :disabled="isResetFilterDisabled" + @click="handleResetFilters">{{$t('reset')}}</el-button> + </div> + </div> + <div class="ksd-fright"> + <el-input :placeholder="$t('filterModelOrOwner')" style="width:250px" size="medium" :prefix-icon="searchLoading? 'el-ksd-icon-loading_22':'el-ksd-icon-search_22'" :value="filterArgs.model_alias_or_owner" @input="handleFilterInput" v-global-key-event.enter.debounce="searchModels" @clear="searchModels()" class="show-search-btn" > + </el-input> </div> </div> <el-table class="model_list_table" @@ -513,9 +512,7 @@ export default class ModelList extends Vue { } get selectedStatus () { const { filterArgs } = this - return filterArgs.status.length && this.statusList.length !== filterArgs.status.length - ? filterArgs.status.map(status => this.$t(status)).join(', ') - : this.$t('ALL') + return filterArgs.status } get selectedRange () { const { filterArgs } = this @@ -525,13 +522,11 @@ export default class ModelList extends Vue { const endDate = dayjs(endTime).format('YYYY-MM-DD HH:mm:ss') return `${startDate} - ${endDate}` } - return this.$t('allTimeRange') + return '' } get selectedModelAttributes () { const { filterArgs } = this - return filterArgs.model_attributes.length && this.modelTypeList.length !== filterArgs.model_attributes.length - ? filterArgs.model_attributes.map(attributes => this.$t(attributes)).join(', ') - : this.$t('ALL') + return filterArgs.model_attributes } get isResetFilterDisabled () { return !this.filterArgs.last_modify.length && !this.filterArgs.status.length && !this.filterArgs.model_attributes.length diff --git a/kystudio/src/components/studio/StudioModel/ModelList/locales.js b/kystudio/src/components/studio/StudioModel/ModelList/locales.js index a05c38a8df..c73e7e054c 100644 --- a/kystudio/src/components/studio/StudioModel/ModelList/locales.js +++ b/kystudio/src/components/studio/StudioModel/ModelList/locales.js @@ -53,11 +53,11 @@ export default { ONLINE: 'ONLINE', OFFLINE: 'OFFLINE', BROKEN: 'BROKEN', - status_c: 'Status: ', - modelType_c: 'Model Attributes: ', + status_c: 'Status ', + modelType_c: 'Model Attributes ', others: 'Others', reset: 'Reset', - lastModifyTime_c: 'Last Updated Time: ', + lastModifyTime_c: 'Last Updated Time ', lastBuildTime: 'Last Build Time: ', allTimeRange: 'All Time Range', filterButton: 'Filter', diff --git a/kystudio/src/components/studio/snapshot/locales.js b/kystudio/src/components/studio/snapshot/locales.js index 88b73e4344..2345e3056c 100644 --- a/kystudio/src/components/studio/snapshot/locales.js +++ b/kystudio/src/components/studio/snapshot/locales.js @@ -1,6 +1,6 @@ export default { 'en': { - snapshotList: 'Snapshot List', + snapshotList: 'Snapshot', snapshotDesc: 'The snapshot is a read-only static view of a source table. Snapshot could reduce costs for building costs in some cases.', snapshotDesc1: 'Support independent query of dimension table. The snapshot will be used first to answer such queries.', snapshotDesc2: 'The dimensions on the dimension table can also serve the query by adding the join key to the aggregate group without generating an index, thereby avoiding the problem of dimension explosion.', diff --git a/kystudio/src/components/studio/snapshot/snapshot.vue b/kystudio/src/components/studio/snapshot/snapshot.vue index 8bf289e2fe..3590dc06fa 100644 --- a/kystudio/src/components/studio/snapshot/snapshot.vue +++ b/kystudio/src/components/studio/snapshot/snapshot.vue @@ -3,18 +3,18 @@ <div class="ksd-title-page">{{$t('snapshotList')}} <common-tip placement="bottom-start"> <div slot="content" class="snapshot-desc"> + <div class="ksd-mb-8 snapshot-desc">{{$t('snapshotDesc')}}</div> <p>* {{$t('snapshotDesc1')}}</p> <p>* {{$t('snapshotDesc2')}}</p> <p>* {{$t('snapshotDesc3')}}</p> </div> <i class="el-ksd-icon-more_info_22 snapshot-icon ksd-fs-22"></i> </common-tip> + <el-button type="primary" class="ksd-fright" icon="el-ksd-icon-add_22" @click="addSnapshot">{{$t('kylinLang.common.add')}}</el-button> </div> - <div class="ksd-mb-16 snapshot-desc">{{$t('snapshotDesc')}}</div> - <div class="clearfix"> + <div class="ksd-mt-8 clearfix"> <div class="ksd-fleft ky-no-br-space" v-if="datasourceActions.includes('snapshotAction')"> - <el-button type="primary" class="ksd-mr-8 ksd-fleft" icon="el-ksd-icon-add_22" @click="addSnapshot">{{$t('snapshot')}}</el-button> <div class="ke-it-other_actions ksd-fleft"> <el-button type="primary" text icon="el-ksd-icon-refresh_22" :disabled="!multipleSelection.length || hasEventAuthority('refresh')" @click="refreshSnapshot">{{$t('kylinLang.common.refresh')}}</el-button> <el-button type="primary" text icon="el-ksd-icon-table_delete_22" :disabled="!multipleSelection.length || hasEventAuthority('delete')" @click="deleteSnap">{{$t('kylinLang.common.delete')}}</el-button> diff --git a/kystudio/src/config/index.js b/kystudio/src/config/index.js index bd269fe1d2..dd5eac9aa8 100644 --- a/kystudio/src/config/index.js +++ b/kystudio/src/config/index.js @@ -67,8 +67,7 @@ export const menusData = [ path: '/monitor', icon: 'el-ksd-icon-nav_monitor_24', children: [ - {name: 'job', path: '/monitor/job'}, - {name: 'streamingjob', path: '/monitor/streamingJob'} + {name: 'job', path: '/monitor/job'} ] }, { @@ -136,7 +135,6 @@ export const pageRefTags = { projectDetail: 'projectDetail', sqlListsPager: 'sqlListsPager', jobPager: 'jobPager', - streamingJobPager: 'streamingJobPager', queryHistoryPager: 'queryHistoryPager', queryResultPager: 'queryResultPager', modleConfigPager: 'modleConfigPager', diff --git a/kystudio/src/locale/en.js b/kystudio/src/locale/en.js index 6dfce7ea6c..8fab4839b2 100644 --- a/kystudio/src/locale/en.js +++ b/kystudio/src/locale/en.js @@ -3,7 +3,7 @@ exports.default = { common: { // 常规操作 dialogHiveTreeNoData: 'Please click data source to load source tables', - noProjectTips: 'You can click the button above to add a project', + noProjectTips: 'You can click the button above to new a project', seconds: 'seconds', minutes: 'minutes', hours: 'hours', @@ -26,6 +26,8 @@ exports.default = { load: 'Load', loadMetadata: 'Load metadata', ok: 'OK', + create: 'Create', + new: 'New', confirmClose: 'Turn Off', exit: 'Exit', retry: 'Retry', @@ -236,7 +238,7 @@ exports.default = { modelName: 'Model Name', computedColumn: 'Computed Column', modelNameGrid: 'Model Name', - modelList: 'Model List', + modelList: 'Model', index: 'index', indexGroup: 'Index Group', tableIndex: 'table index', @@ -297,7 +299,7 @@ exports.default = { sameCCExpression1: 'In this model, there has been a computed column "', sameCCExpression2: '" defined as expression.Please define another one.', ccWrongPosition: 'The computed column should be defined in table "', - addModel: 'Add Model', + addModel: 'New Model', hasNoFact: 'Fact Table is mandatory for model', cycleLinkTip: 'The join may lead some tables joining in a circle.', aloneTableTip: '{aloneCount} tables haven\'t been joined with the fact table directly or via other dimension tables. The model may lose them if you continue to save the model anyway.', @@ -364,7 +366,7 @@ exports.default = { mustSelectProject: 'Please select a project first', selectProject: 'Please select a project', projectList: 'Project List', - addProject: 'Add Project' + addProject: 'New Project' }, query: { saveQuery: 'Save Query', @@ -484,7 +486,6 @@ exports.default = { acceleration: 'Acceleration', design: 'Studio', job: 'Batch Job', - streamingjob: 'Streaming Job', cluster: 'Cluster', admin: 'Admin', user: 'User', @@ -511,7 +512,7 @@ exports.default = { notOtherChars: 'Not support special symbols (/:\\*?"<>|\')' }, guide: { - addProjectTip: 'When you add a new project, choose a proper project type is essential. To analysis based on multi-dimensional models, you may choose the AI augmented mode.', + addProjectTip: 'When you create a new project, choose a proper project type is essential. To analysis based on multi-dimensional models, you may choose the AI augmented mode.', // loadTableTipAuto: 'The Kylin platform may need to connect with your source data. Choose your desired dataset and sync its schema. Here we use the SSB dataset to do further tasks.', queryTipAuto: 'Once source tables synced, you can explore data among the SSB dataset.', speedTipAuto: 'SQL statements in the Waiting List are filtered by the system. You can adjust these rules to manage accelerating workload.', diff --git a/kystudio/src/router/index.js b/kystudio/src/router/index.js index 148c3756f8..fa7b220e9a 100644 --- a/kystudio/src/router/index.js +++ b/kystudio/src/router/index.js @@ -9,7 +9,6 @@ import login from 'components/user/login' import Insight from 'components/query/insight' import queryHistory from 'components/query/query_history' import jobs from 'components/monitor/batchJobs/jobs' -import streamingJobs from 'components/monitor/streamingJobs/streamingJobs' import dashboard from 'components/dashboard/dashboard' import { bindRouterGuard } from './routerGuard.js' @@ -122,11 +121,6 @@ let routerOptions = { path: 'monitor/job', component: jobs }, - { - name: 'StreamingJob', - path: 'monitor/streamingJob', - component: streamingJobs - }, { name: 'Insight', path: 'query/insight', diff --git a/kystudio/src/service/monitor.js b/kystudio/src/service/monitor.js index 65959fde3c..af998c1079 100644 --- a/kystudio/src/service/monitor.js +++ b/kystudio/src/service/monitor.js @@ -50,15 +50,6 @@ export default { loadJobBulidChartData: (para) => { return Vue.resource(apiUrl + 'jobs/statistics/duration_per_byte').get(para) }, - loadStreamingJobsList: (para) => { - return Vue.resource(apiUrl + 'streaming_jobs{?job_types}{&model_names}').get(para) - }, - getStreamingJobRecords: (para) => { - return Vue.resource(apiUrl + 'streaming_jobs/records').get(para) - }, - updateStreamingJobs: (para) => { - return Vue.resource(apiUrl + 'streaming_jobs/status').update(para) - }, getStreamingChartData: (para) => { return Vue.resource(apiUrl + `streaming_jobs/stats/${para.job_id}`).get(para) }, diff --git a/kystudio/src/store/model.js b/kystudio/src/store/model.js index f4a8219bb4..b8f2f3a54b 100644 --- a/kystudio/src/store/model.js +++ b/kystudio/src/store/model.js @@ -390,15 +390,6 @@ export default { [types.FETCH_SUBMITTER_LIST] (_, params) { return api.model.fetchSubmitterList(params) }, - [types.GET_STREAMING_JOB] (_, params) { - return api.model.getStreamingJobs(params) - }, - [types.CHANGE_STREAMING_JOB_STATUS] (_, params) { - return api.model.changeStreamingJobStatus(params) - }, - [types.UPDATE_STREAMING_CONFIGURATIONS] (_, params) { - return api.model.updateStreamingConfigurations(params) - }, [types.DELETE_SYNC_SEGMENTS] (_, params) { return api.model.deleteSyncSegments(params) }, diff --git a/kystudio/src/store/monitor.js b/kystudio/src/store/monitor.js index ff5568a785..319792c83c 100644 --- a/kystudio/src/store/monitor.js +++ b/kystudio/src/store/monitor.js @@ -44,15 +44,6 @@ export default { [types.LOAD_JOB_BULID_CHART_DATA]: function ({ commit }, para) { return api.monitor.loadJobBulidChartData(para) }, - [types.LOAD_STREAMING_JOBS_LIST]: function ({ commit }, para) { - return api.monitor.loadStreamingJobsList(para) - }, - [types.GET_STREAMING_JOB_RECORDS]: function ({ commit }, para) { - return api.monitor.getStreamingJobRecords(para) - }, - [types.UPDATE_STREAMING_JOBS]: function ({ commit }, para) { - return api.monitor.updateStreamingJobs(para) - }, [types.GET_STREAMING_CHART_DATA]: function ({ commit }, para) { return api.monitor.getStreamingChartData(para) },