diff --git a/.dockerignore b/.dockerignore index 7c3b4c0b7..ec513dc87 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,4 @@ lina dist node_modules +.git diff --git a/src/components/AccountListTable/const.js b/src/components/AccountListTable/const.js index 3bb920009..07f7f1d04 100644 --- a/src/components/AccountListTable/const.js +++ b/src/components/AccountListTable/const.js @@ -1,5 +1,5 @@ -import { ChoicesFormatter } from '@/components/TableFormatters' import { toSafeLocalDateStr } from '@/utils/common' +import ChoicesFormatter from '@/components/TableFormatters/ChoicesFormatter' import i18n from '@/i18n/i18n' export const connectivityMeta = { @@ -7,9 +7,14 @@ export const connectivityMeta = { formatter: ChoicesFormatter, formatterArgs: { iconChoices: { - ok: 'fa-check text-primary', - failed: 'fa-times text-danger', - unknown: 'fa-circle text-warning' + ok: 'fa-check', + failed: 'fa-times', + unknown: 'fa-circle-o' + }, + classChoices: { + ok: 'text-primary', + failed: 'text-danger', + unknown: 'text-warning' }, hasTips: true, getTips: ({ row, cellValue }) => { diff --git a/src/components/AutoDataTable/index.vue b/src/components/AutoDataTable/index.vue index bd814f022..88b4eb475 100644 --- a/src/components/AutoDataTable/index.vue +++ b/src/components/AutoDataTable/index.vue @@ -1,6 +1,14 @@ <template> <div> - <DataTable v-if="!loading" ref="dataTable" v-loading="loading" :config="iConfig" v-bind="$attrs" v-on="$listeners" @filter-change="filterChange" /> + <DataTable + v-if="!loading" + ref="dataTable" + v-loading="loading" + :config="iConfig" + v-bind="$attrs" + v-on="$listeners" + @filter-change="filterChange" + /> <ColumnSettingPopover :current-columns="popoverColumns.currentCols" :total-columns-list="popoverColumns.totalColumnsList" @@ -13,7 +21,13 @@ <script type="text/jsx"> import DataTable from '../DataTable' -import { DateFormatter, DetailFormatter, DisplayFormatter, BooleanFormatter, ActionsFormatter } from '@/components/TableFormatters' +import { + DateFormatter, + DetailFormatter, + DisplayFormatter, + ActionsFormatter, + ChoicesFormatter +} from '@/components/TableFormatters' import i18n from '@/i18n/i18n' import ColumnSettingPopover from './components/ColumnSettingPopover' import { newURL } from '@/utils/common' @@ -103,7 +117,7 @@ export default { break case 'is_valid': col.label = i18n.t('common.Validity') - col.formatter = BooleanFormatter + col.formatter = ChoicesFormatter col.align = 'center' col.width = '80px' break @@ -123,7 +137,7 @@ export default { col.formatter = DisplayFormatter break case 'boolean': - col.formatter = BooleanFormatter + col.formatter = ChoicesFormatter col.align = 'center' col.width = '80px' break diff --git a/src/components/TableFormatters/BooleanFormatter.vue b/src/components/TableFormatters/BooleanFormatter.vue index c2261ff46..983cdd0f1 100644 --- a/src/components/TableFormatters/BooleanFormatter.vue +++ b/src/components/TableFormatters/BooleanFormatter.vue @@ -5,7 +5,7 @@ <script> import BaseFormatter from './base' export default { - name: 'ChoicesFormatter', + name: 'BooleanFormatter', extends: BaseFormatter, props: { formatterArgsDefault: { @@ -16,6 +16,7 @@ export default { true: 'fa-check text-primary', false: 'fa-times text-danger' }, + showFalse: true, typeChange(val) { return !!val } @@ -31,6 +32,9 @@ export default { computed: { iconClass() { const key = this.formatterArgs.typeChange(this.cellValue) + if (!key && !this.formatterArgs.showFalse) { + return '' + } return this.formatterArgs.iconChoices[key] } } diff --git a/src/components/TableFormatters/ChoicesFormatter.vue b/src/components/TableFormatters/ChoicesFormatter.vue index 634274010..92a9463f4 100644 --- a/src/components/TableFormatters/ChoicesFormatter.vue +++ b/src/components/TableFormatters/ChoicesFormatter.vue @@ -1,11 +1,11 @@ <template> - <div> - <el-tooltip v-if="formatterArgs.hasTips" placement="bottom" effect="dark"> - <div slot="content" v-html="tips" /> - <i :class="'fa ' + iconClass" /> - </el-tooltip> - <i v-else :class="'fa ' + iconClass" /> - </div> + <el-tooltip v-if="shown" :disabled="!formatterArgs.hasTips" placement="bottom" effect="dark"> + <div slot="content" v-html="tips" /> + <span :class="classes"> + <i v-if="formatterArgs.useIcon" :class="'fa ' + icon" /> + <span v-if="formatterArgs.useText">{{ text }}</span> + </span> + </el-tooltip> </template> <script> @@ -19,13 +19,24 @@ export default { default() { return { iconChoices: { - true: 'fa-check text-primary', - false: 'fa-times text-danger' + true: 'fa-check', + false: 'fa-times' }, - getIconKey({ row, cellValue }) { + classChoices: { + true: 'text-primary', + false: 'text-danger' + }, + textChoices: { + true: this.$t('common.Yes'), + false: this.$t('common.No') + }, + getKey({ row, cellValue }) { return cellValue }, hasTips: false, + useIcon: true, + useText: false, + showFalse: true, getTips: ({ row, cellValue }) => { return cellValue } @@ -39,12 +50,28 @@ export default { } }, computed: { - iconClass() { - const key = this.formatterArgs.getIconKey({ row: this.row, cellValue: this.cellValue }) - return this.formatterArgs.iconChoices[key] + key() { + return this.formatterArgs.getKey( + { row: this.row, cellValue: this.cellValue } + ) + }, + icon() { + return this.formatterArgs.iconChoices[this.key] + }, + classes() { + return this.formatterArgs.classChoices[this.key] + }, + text() { + return this.formatterArgs.textChoices[this.key] }, tips() { return this.formatterArgs.getTips({ cellValue: this.cellValue, row: this.row }) + }, + shown() { + if (!this.formatterArgs.showFalse && !this.key) { + return false + } + return true } } } diff --git a/src/components/TableFormatters/DisplayFormatter.vue b/src/components/TableFormatters/DisplayFormatter.vue index 4c0485c48..612144a5c 100644 --- a/src/components/TableFormatters/DisplayFormatter.vue +++ b/src/components/TableFormatters/DisplayFormatter.vue @@ -1,5 +1,5 @@ <template> - <span>{{ display }}</span> + <span :class="cls"> {{ value }}</span> </template> <script> @@ -19,19 +19,27 @@ export default { }, data() { return { - display: this.getValue() + formatterArgs: Object.assign(this.formatterArgsDefault, this.col.formatterArgs) } }, - methods: { - getValue() { - const formatterArgs = Object.assign(this.formatterArgsDefault, this.col.formatterArgs) - const displayKey = formatterArgs.displayKey + computed: { + value() { + const displayKey = this.formatterArgs.displayKey let value = this.row[displayKey] if (value === undefined) { value = this.row[this.col.prop] } return value + }, + cls() { + const classChoices = this.formatterArgs?.classChoices + if (!classChoices) { + return '' + } + return classChoices[this.cellValue] } + }, + methods: { } } </script> diff --git a/src/components/TableFormatters/index.js b/src/components/TableFormatters/index.js index 67de651a5..178ff07a3 100644 --- a/src/components/TableFormatters/index.js +++ b/src/components/TableFormatters/index.js @@ -1,7 +1,6 @@ import DetailFormatter from './DetailFormatter' import ArrayFormatter from './ArrayFormatter' import DisplayFormatter from './DisplayFormatter' -import BooleanFormatter from './BooleanFormatter' import ChoicesFormatter from './ChoicesFormatter' import ActionsFormatter from './ActionsFormatter' import DeleteActionFormatter from './DeleteActionFormatter' @@ -15,7 +14,6 @@ import StatusFormatter from './StatusFormatter' export default { DetailFormatter, DisplayFormatter, - BooleanFormatter, ChoicesFormatter, ActionsFormatter, DeleteActionFormatter, @@ -31,7 +29,6 @@ export default { export { DetailFormatter, DisplayFormatter, - BooleanFormatter, ChoicesFormatter, ActionsFormatter, DeleteActionFormatter, diff --git a/src/views/accounts/GatheredUser/TaskDetail/TaskExecutionList.vue b/src/views/accounts/GatheredUser/TaskDetail/TaskExecutionList.vue index 0c97fa8b6..368da7053 100644 --- a/src/views/accounts/GatheredUser/TaskDetail/TaskExecutionList.vue +++ b/src/views/accounts/GatheredUser/TaskDetail/TaskExecutionList.vue @@ -4,7 +4,6 @@ <script> import GenericListTable from '@/layout/components/GenericListTable/index' -import { BooleanFormatter, DateFormatter } from '@/components/TableFormatters' export default { name: 'TaskExecutionList', @@ -26,33 +25,24 @@ export default { }, tableConfig: { url: `/api/v1/xpack/gathered-user/task-executions/?task=${this.object.id}`, - columns: [ - { - prop: 'timedelta', + columns: ['timedelta', 'date_start', 'success'], + columnsMeta: { + timedelta: { label: this.$t('ops.timeDelta'), formatter: function(row) { return row.timedelta.toFixed(2) + 's' - } + }, + width: null }, - { - prop: 'date_start', - label: this.$t('common.DateStart'), - formatter: DateFormatter + date_start: { + width: null }, - { - prop: 'success', - label: this.$t('common.Success'), - width: '90px', - align: 'center', - formatter: BooleanFormatter, - formatterArgs: { - iconChoices: { - false: 'fa-times text-danger', - true: 'fa-check text-primary' - } - } + success: { + width: null, + label: this.$t('common.Success') } - ] + } + } } } diff --git a/src/views/assets/SystemUser/SystemUserList/CommonUserList.vue b/src/views/assets/SystemUser/SystemUserList/CommonUserList.vue index ec643115f..4c61c3adb 100644 --- a/src/views/assets/SystemUser/SystemUserList/CommonUserList.vue +++ b/src/views/assets/SystemUser/SystemUserList/CommonUserList.vue @@ -36,7 +36,10 @@ export default { width: '100px' }, username_same_with_user: { - width: '150px' + width: '150px', + formatterArgs: { + showFalse: false + } }, login_mode: { width: '120px' diff --git a/src/views/audits/LoginLogList.vue b/src/views/audits/LoginLogList.vue index e3e19514b..55164615d 100644 --- a/src/views/audits/LoginLogList.vue +++ b/src/views/audits/LoginLogList.vue @@ -17,7 +17,10 @@ export default { return { tableConfig: { url: '/api/v1/audits/login-logs/', - columns: ['username', 'type', 'backend', 'ip', 'city', 'user_agent', 'mfa', 'reason', 'status', 'datetime'], + columns: [ + 'username', 'type', 'backend', 'ip', 'city', + 'user_agent', 'mfa', 'reason', 'status', 'datetime' + ], columnsMeta: { username: { showOverflowTooltip: true @@ -33,7 +36,13 @@ export default { width: '90px' }, status: { - width: '85px' + width: '85px', + formatterArgs: { + classChoices: { + true: 'text-primary', + false: 'text-danger' + } + } }, mfa: { label: 'MFA', diff --git a/src/views/sessions/Storage/CommandStorage.vue b/src/views/sessions/Storage/CommandStorage.vue index 6440f2d7e..e9e37f674 100644 --- a/src/views/sessions/Storage/CommandStorage.vue +++ b/src/views/sessions/Storage/CommandStorage.vue @@ -5,7 +5,6 @@ <script> import ListTable from '@/components/ListTable' import { SetToDefaultCommandStorage, TestCommandStorage } from '@/api/sessions' -import { BooleanFormatter } from '@/components/TableFormatters' export default { name: 'CommandStorage', components: { @@ -56,12 +55,8 @@ export default { } }, is_default: { - formatter: BooleanFormatter, formatterArgs: { - iconChoices: { - true: 'fa-check text-primary', - false: '' - } + showFalse: false }, align: 'center', width: '100px' diff --git a/src/views/sessions/Storage/ReplayStorage.vue b/src/views/sessions/Storage/ReplayStorage.vue index bb3467b88..c80f66623 100644 --- a/src/views/sessions/Storage/ReplayStorage.vue +++ b/src/views/sessions/Storage/ReplayStorage.vue @@ -4,7 +4,6 @@ <script> import ListTable from '@/components/ListTable' import { TestReplayStorage, SetToDefaultReplayStorage } from '@/api/sessions' -import { BooleanFormatter } from '@/components/TableFormatters' export default { name: 'ReplayStorage', components: { @@ -61,12 +60,8 @@ export default { } }, is_default: { - formatter: BooleanFormatter, formatterArgs: { - iconChoices: { - true: 'fa-check text-primary', - false: '' - } + showFalse: false }, align: 'center', width: '100px' diff --git a/src/views/sessions/TerminalList.vue b/src/views/sessions/TerminalList.vue index a6a79a88b..0db3ec3c5 100644 --- a/src/views/sessions/TerminalList.vue +++ b/src/views/sessions/TerminalList.vue @@ -17,7 +17,6 @@ import { GenericListPage, GenericCreateUpdateForm } from '@/layout/components' import Dialog from '@/components/Dialog' import Select2 from '@/components/FormFields/Select2' -import { BooleanFormatter } from '@/components/TableFormatters' export default { components: { GenericListPage, @@ -94,7 +93,7 @@ export default { 'name', 'remote_addr', 'session_online', 'stat.cpu_load', 'stat.disk_used', 'stat.memory_used', - 'status_display', + 'status', 'is_active', 'is_alive', 'actions' ], columnsMeta: { @@ -113,16 +112,25 @@ export default { label: this.$t('sessions.systemMemoryUsedPercent'), width: '120px' }, - 'status_display': { + status: { label: this.$t('xpack.LoadStatus'), - width: '120px' + width: '120px', + // formatter: DisplayFormatter, + filterable: 'custom', + formatterArgs: { + classChoices: { + offline: 'fa fa-chain-broken text-danger', + critical: 'fa fa-bolt text-warning', + high: 'fa fa-exclamation-triangle text-info', + normal: 'fa fa-check text-primary' + } + } }, remote_addr: { sortable: 'custom' }, is_active: { label: this.$t('sessions.active'), - formatter: BooleanFormatter, width: '80px', align: 'center' }, diff --git a/src/views/users/User/UserList.vue b/src/views/users/User/UserList.vue index 3d145426d..f7eb8a96a 100644 --- a/src/views/users/User/UserList.vue +++ b/src/views/users/User/UserList.vue @@ -46,8 +46,8 @@ export default { columns: [ 'name', 'username', 'email', 'phone', 'wechat', 'groups_display', 'total_role_display', 'source', - 'is_valid', 'login_blocked', 'mfa_enabled', 'is_expired', - 'mfa_force_enabled', + 'is_valid', 'login_blocked', 'mfa_enabled', + 'mfa_force_enabled', 'is_expired', 'last_login', 'date_joined', 'date_password_last_updated', 'comment', 'created_by', 'actions' ], @@ -72,6 +72,22 @@ export default { label: this.$t('users.Role'), showOverflowTooltip: true }, + mfa_enabled: { + label: 'MFA', + formatterArgs: { + showFalse: false + } + }, + mfa_force_enabled: { + formatterArgs: { + showFalse: false + } + }, + is_expired: { + formatterArgs: { + showFalse: false + } + }, groups_display: { width: '200px', showOverflowTooltip: true @@ -81,10 +97,10 @@ export default { canClone: true, hasDelete: hasDelete, canUpdate: function({ row }) { - return row.can_update + return row['can_update'] }, canDelete: function({ row }) { - return row.can_delete + return row['can_delete'] }, extraActions: [ { diff --git a/src/views/xpack/Cloud/Account/AccountList.vue b/src/views/xpack/Cloud/Account/AccountList.vue index 5755f0773..192f0f765 100644 --- a/src/views/xpack/Cloud/Account/AccountList.vue +++ b/src/views/xpack/Cloud/Account/AccountList.vue @@ -5,7 +5,6 @@ <script type="text/jsx"> import GenericListTable from '@/layout/components/GenericListTable' import { ACCOUNT_PROVIDER_ATTRS_MAP, aliyun, aws_china, aws_international, huaweicloud, qcloud, azure, azure_international, vmware, nutanix, qingcloud_private, huaweicloud_private, gcp } from '../const' -import { BooleanFormatter, DetailFormatter } from '@/components/TableFormatters' export default { components: { @@ -21,10 +20,8 @@ export default { ], columnsMeta: { name: { - prop: 'name', sortable: true, showOverflowTooltip: true, - formatter: DetailFormatter, formatterArgs: { route: 'AccountDetail' } @@ -51,17 +48,6 @@ export default { } ] } - }, - validity: { - width: '90px', - align: 'center', - formatter: BooleanFormatter, - formatterArgs: { - iconChoices: { - false: 'fa-times text-danger', - true: 'fa-check text-primary' - } - } } } },