Merge pull request #3693 from jumpserver/dev

v3.10.2
This commit is contained in:
Bryan
2024-01-17 07:24:50 -04:00
committed by GitHub
38 changed files with 234 additions and 118 deletions

View File

@@ -17,6 +17,7 @@
:table-config="tableConfig"
:tree-url="`${baseNodeUrl}children/tree/`"
:url="baseUrl"
:tree-setting="treeSetting"
class="tree-table"
v-bind="$attrs"
/>
@@ -52,6 +53,10 @@ export default {
disabled: {
type: [Boolean, Function],
default: false
},
treeSetting: {
type: Object,
default: () => ({})
}
},
data() {

View File

@@ -13,6 +13,7 @@
ref="dialog"
:base-node-url="baseNodeUrl"
:base-url="baseUrl"
:tree-setting="treeSetting"
:tree-url-query="treeUrlQuery"
:value="value"
:visible.sync="dialogVisible"
@@ -48,6 +49,10 @@ export default {
value: {
type: Array,
default: () => []
},
treeSetting: {
type: Object,
default: () => ({})
}
},
data() {

View File

@@ -60,6 +60,7 @@ export default {
const showAssets = this.treeSetting?.showAssets || this.showAssets
const treeUrlQuery = this.setTreeUrlQuery()
const assetTreeUrl = `${this.treeUrl}?assets=${showAssets ? '1' : '0'}&${treeUrlQuery}`
const vm = this
return {
treeTabConfig: {
@@ -81,7 +82,13 @@ export default {
nodeUrl: this.nodeUrl,
treeUrl: assetTreeUrl,
callback: {
onSelected: (event, treeNode) => this.getAssetsUrl(treeNode)
onSelected: (event, treeNode) => this.getAssetsUrl(treeNode),
beforeRefresh: () => {
const query = { ...this.$route.query, node_id: '', asset_id: '' }
setTimeout(() => {
vm.$router.replace({ query: query })
}, 100)
}
},
...this.treeSetting
}

View File

@@ -5,9 +5,9 @@ import Switcher from '@/components/Form/FormFields/Switcher.vue'
import rules from '@/components/Form/DataForm/rules'
import BasicTree from '@/components/Form/FormFields/BasicTree.vue'
import JsonEditor from '@/components/Form/FormFields/JsonEditor.vue'
import TransferSelect from '@/components/Form/FormFields/TransferSelect.vue'
import { assignIfNot } from '@/utils/common'
import TagInput from '@/components/Form/FormFields/TagInput.vue'
import TransferSelect from '@/components/Form/FormFields/TransferSelect.vue'
export class FormFieldGenerator {
constructor(emit) {
@@ -45,7 +45,7 @@ export class FormFieldGenerator {
break
case 'field':
type = ''
field.component = TransferSelect
field.component = ObjectSelect2
if (fieldRemoteMeta.required) {
field.el.clearable = false
}
@@ -76,7 +76,7 @@ export class FormFieldGenerator {
field.component = ObjectSelect2
break
case 'm2m_related_field':
field.component = TransferSelect
field.component = ObjectSelect2
field.el.label = field.label
break
case 'nested object':
@@ -134,6 +134,9 @@ export class FormFieldGenerator {
case 'comment':
field.el.type = 'textarea'
break
case 'users':
field.component = TransferSelect
field.el.label = field.label
}
return field
}

View File

@@ -204,7 +204,12 @@ export default {
},
formatWeektime(col) {
const timeStamp = 1542384000000 // '2018-11-17 00:00:00'
const beginStamp = timeStamp + col * 1800000 // col * 30 * 60 * 1000
const timezone = 8
const offsetGMT = new Date().getTimezoneOffset() // 本地时间和格林威治的时间差,单位为分钟
const nowDate = new Date(timeStamp).getTime()
const targetStamp = new Date(nowDate + offsetGMT * 60 * 1000 + timezone * 60 * 60 * 1000).getTime()
const beginStamp = targetStamp + col * 1800000 // col * 30 * 60 * 1000
const endStamp = beginStamp + 1800000
const begin = this.formatDate(new Date(beginStamp), 'hh:mm')

View File

@@ -3,7 +3,7 @@
<el-button v-if="shouldFold" circle class="search-btn" size="mini" @click="handleManualSearch">
<svg-icon icon-class="search" />
</el-button>
<TagSearch v-else :options="iOption" v-bind="$attrs" @tagSearch="handleTagSearch" v-on="$listeners" />
<TagSearch v-else :options="iOption" v-bind="$attrs" v-on="$listeners" @tag-search="handleTagSearch" />
</span>
</template>
@@ -68,6 +68,9 @@ export default {
},
methods: {
handleTagSearch(tags) {
if (_.isEqual(tags, this.tags)) {
return
}
this.tags = tags
if (tags.length === 0) {
this.manualSearch = false

View File

@@ -104,7 +104,7 @@ export default {
title: this.$t('common.BatchUpdate'),
name: 'actionUpdateSelected',
has: this.hasBulkUpdate,
icon: 'fa fa-refresh',
fa: 'batch-update',
can: function({ selectedRows }) {
let canBulkUpdate = vm.canBulkUpdate
if (typeof canBulkUpdate === 'function') {

View File

@@ -173,12 +173,14 @@ export default {
this.dataTable.getList()
},
search(attrs) {
this.$log.debug('ListTable: search table', attrs)
this.$emit('TagSearch', attrs)
return this.dataTable?.search(attrs, true)
this.$refs.dataTable?.$refs.dataTable?.search(attrs, true)
},
filter(attrs) {
this.$emit('TagFilter', attrs)
this.$refs.dataTable.$refs.dataTable.search(attrs, true)
this.$log.debug('ListTable: found filter change', attrs)
this.search(attrs)
},
hasActionPerm(action) {
const permRequired = this.permissions[action]

View File

@@ -10,14 +10,14 @@
<el-tag
v-for="(v, k) in filterTags"
:key="k"
:disable-transitions="true"
:name="k"
class="filter-tag"
closable
size="small"
class="filter-tag"
type="info"
:disable-transitions="true"
@close="handleTagClose(k)"
@click="handleTagClick(v,k)"
@close="handleTagClose(k)"
>
<strong v-if="v.label">{{ v.label + ':' }}</strong>
<span v-if="v.valueLabel">{{ v.valueLabel }}</span>
@@ -27,14 +27,14 @@
<el-input
ref="SearchInput"
v-model="filterValue"
:placeholder="placeholder"
class="search-input"
:class="options.length < 1 ? 'search-input2': ''"
:placeholder="placeholder"
:validate-event="false"
class="search-input"
suffix-icon="el-icon-search"
@blur="focus = false"
@focus="focus = true"
@change="handleConfirm"
@focus="focus = true"
@keyup.enter.native="handleConfirm"
@keyup.delete.native="handleDelete"
/>
@@ -122,6 +122,12 @@ export default {
},
deep: true
},
filterTags: {
handler() {
this.$emit('tag-search', this.filterMaps)
},
deep: true
},
filterValue(newValue, oldValue) {
if (newValue === '' && oldValue !== '') {
this.emptyCount = 1
@@ -210,11 +216,6 @@ export default {
...asFilterTags,
...routeFilter
}
if (Object.keys(this.filterTags).length > 0) {
setTimeout(() => {
return this.$emit('tagSearch', this.filterMaps)
}, 400)
}
},
getValueLabel(key, value) {
for (const field of this.options) {
@@ -252,7 +253,7 @@ export default {
if (this.getUrlQuery) {
this.checkUrlFields(evt)
}
this.$emit('tagSearch', this.filterMaps)
// this.$emit('tagSearch', this.filterMaps)
return true
},
handleDelete() {
@@ -284,7 +285,7 @@ export default {
valueLabel: this.valueLabel
}
this.$set(this.filterTags, this.filterKey, tag)
this.$emit('tagSearch', this.filterMaps)
// this.$emit('tagSearch', this.filterMaps)
// 修改查询参数时改变url中保存的参数
if (this.getUrlQuery) {

View File

@@ -167,6 +167,9 @@ export default {
},
async refresh() {
this.treeSearchValue = ''
if (this.treeSetting?.callback?.beforeRefresh) {
this.treeSetting.callback.beforeRefresh()
}
if (this.treeSetting?.callback?.refresh) {
await this.treeSetting.callback.refresh()
}

View File

@@ -969,29 +969,30 @@
"LoginCount": "Login count",
"LoginOverview": "Sessions overview",
"LoginTo": "Login to",
"LoginUsers": "Active accounts",
"ActiveUsers": "Active users",
"Monthly": "Monthly",
"CurrentConnections": "Current connections",
"TodayFailedConnections": "Connections failed today",
"CurrentConnectionUsers": "Current connection users",
"TodayFailedConnections": "Number of failed sessions today",
"OnlineSessions": "Online sessions",
"OnlineUserDevices": "Online user devices",
"RealTimeData": "Real-time data",
"UserAssetActivity": "Account/Asset activity",
"UserData": "Account data",
"UserAssetActivity": "User/asset activity status",
"UserData": "User data",
"LoginUserToday": "Login account today",
"AssetData": "Asset data",
"LoginAssetToday": "Active assets today",
"LoginAssetToday": "Active asset today",
"WeekAdd": "New this week",
"ProportionOfAssetTypes": "Proportion of asset types",
"Proportion": "Proportion",
"LoginUserRanking": "Login account ranking",
"ActiveAssetRanking": "Login asset ranking",
"LoginUserRanking": "Session user ranking",
"ActiveAssetRanking": "Session asset Ranking",
"AssetName": "Asset name",
"NumberOfVisits": "Number of visits",
"ranking": "Ranking",
"Today": "Today",
"Last7Days": "Last 7 days",
"Last30Days": "Last30 days",
"Last7Days": "Last 7d",
"Last30Days": "Last 30d",
"OnlineUsers": "Online accounts",
"ConnectUsers": "Connect accounts",
"Num": "Num",
@@ -1009,13 +1010,14 @@
"BatchCommandNotExecuted": "Batch command not executed",
"ExecuteFailedCommand": "Execute failed command",
"SessionTrend": "Session trend",
"SessionConnectTrend": "Session connection trends",
"UserLoginTrend": "Account login trend",
"TimesWeekUnit": "times/week",
"TopAssetsOfWeek": "Top assets of week",
"TopUsersOfWeek": "Top user of week",
"User": "User",
"UserRatio": "User Ratio",
"UsersTotal": "Accounts total",
"UsersTotal": "User total",
"Weekly": "Weekly",
"TotalJobFailed": "Total job failed",
"TotalJobRunning": "Total job running",
@@ -2002,7 +2004,7 @@
"Account": "Account",
"Existing": "Existing",
"UserInformation": "User information",
"Authentication": "Account",
"Authentication": "Authentication",
"Comment": "Comment",
"ConfirmPassword": "Confirm password",
"DateExpired": "Date expired",

View File

@@ -971,22 +971,23 @@
"LoginCount": "ログイン回数",
"LoginOverview": "セッション統計",
"LoginTo": "ログインしました",
"LoginUsers": "アクティブなアカウント",
"ActiveUsers": "アクティブユーザー",
"Monthly": "月ごと",
"CurrentConnections": "現在の接続数",
"TodayFailedConnections": "今日の接続に失敗しました",
"CurrentConnectionUsers": "現在のセッションユーザーの数",
"TodayFailedConnections": "今日の失敗したセッションの数",
"OnlineSessions": "オンラインセッション",
"RealTimeData": "リアルタイムデータ",
"UserAssetActivity": "アカウント/資産のアクティブ化",
"UserData": "アカウントデータ",
"LoginUserToday": "今日のログインアカウント数",
"UserAssetActivity": "ユーザー/アセットのアクティビティステータス",
"UserData": "ユーザーデータ",
"LoginUserToday": "今日のログインユーザー数",
"AssetData": "資産データ",
"LoginAssetToday": "今日のアクティブ資産数",
"WeekAdd": "今週の追加",
"ProportionOfAssetTypes": "資産タイプの割合",
"Proportion": "占有率",
"LoginUserRanking": "ログインアカウントランキング",
"ActiveAssetRanking": "ログイン資産ランキング",
"LoginUserRanking": "セッションユーザーランキング",
"ActiveAssetRanking": "セッションアセットランキング",
"AssetName": "資産名",
"NumberOfVisits": "アクセス回数",
"ranking": "ランキング",
@@ -1010,13 +1011,14 @@
"BatchCommandNotExecuted": "未実行コマンド",
"ExecuteFailedCommand": "失敗コマンドの実行",
"SessionTrend": "セッショントレンド",
"SessionConnectTrend": "セッション接続の傾向",
"UserLoginTrend": "アカウントログイントレンド",
"TimesWeekUnit": "回/週",
"TopAssetsOfWeek": "週間資産TOP10",
"TopUsersOfWeek": "週ユーザーTOP10",
"User": "ユーザー",
"UserRatio": "ユーザー比率統計",
"UsersTotal": "アカウント総数",
"UsersTotal": "総ユーザー数",
"Weekly": "週ごと"
},
"ops": {

View File

@@ -960,22 +960,23 @@
"LoginCount": "登录次数",
"LoginOverview": "会话统计",
"LoginTo": "登录了",
"LoginUsers": "活跃账号",
"ActiveUsers": "活跃用户",
"Monthly": "按月",
"CurrentConnections": "当前连接数",
"TodayFailedConnections": "今日连接失败数",
"CurrentConnectionUsers": "当前会话用户数",
"TodayFailedConnections": "今日会话失败数",
"OnlineSessions": "在线会话数",
"RealTimeData": "实时数据",
"UserAssetActivity": "账号/资产活跃情况",
"UserData": "账号数据",
"LoginUserToday": "今日登录账号数",
"UserAssetActivity": "用户/资产活跃情况",
"UserData": "用户数据",
"LoginUserToday": "今日登录用户数",
"AssetData": "资产数据",
"LoginAssetToday": "今日活跃资产数",
"WeekAdd": "本周新增",
"ProportionOfAssetTypes": "资产类型占比",
"Proportion": "占比",
"LoginUserRanking": "登录账号排名",
"ActiveAssetRanking": "登录资产排名",
"LoginUserRanking": "会话用户排名",
"ActiveAssetRanking": "会话资产排名",
"AssetName": "资产名称",
"NumberOfVisits": "访问次数",
"ranking": "排名",
@@ -999,13 +1000,13 @@
"BatchCommandNotExecuted": "未执行批量命令",
"ExecuteFailedCommand": "执行失败命令",
"SessionTrend": "会话趋势",
"UserLoginTrend": "账号登录趋势",
"SessionConnectTrend": "会话连接趋势",
"TimesWeekUnit": "次/周",
"TopAssetsOfWeek": "周资产 TOP10",
"TopUsersOfWeek": "周用户 TOP10",
"User": "用户",
"UserRatio": "用户占比统计",
"UsersTotal": "账号总数",
"UsersTotal": "用户总数",
"Weekly": "按周"
},
"ops": {

View File

@@ -1 +1 @@
<svg t="1687315588323" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3119" width="11" height="11"><path d="M302.545455 116.363636h409.6a27.927273 27.927273 0 0 0 0-55.854545h-409.6a27.927273 27.927273 0 1 0 0 55.854545z m-93.09091 102.4h595.781819a27.927273 27.927273 0 0 0 0-55.854545h-595.781819a27.927273 27.927273 0 1 0 0 55.854545z m670.254546 55.854546h-735.418182c-51.414109 0-93.090909 41.686109-93.090909 93.090909v512c0 51.414109 41.6768 93.090909 93.090909 93.090909h735.418182c51.414109 0 93.090909-41.6768 93.090909-93.090909v-512c0-51.4048-41.6768-93.090909-93.090909-93.090909z m37.236364 594.3296a46.545455 46.545455 0 0 1-46.545455 46.545454h-716.8a46.545455 46.545455 0 0 1-46.545455-46.545454V386.327273a46.545455 46.545455 0 0 1 46.545455-46.545455h716.8a46.545455 46.545455 0 0 1 46.545455 46.545455v482.620509zM602.177164 522.621673l-68.9152-64.474764a4.747636 4.747636 0 0 0-1.405673-1.349818 9.234618 9.234618 0 0 0-1.396364-1.163636 11.776 11.776 0 0 0-3.006836-1.7408c-0.996073-0.577164-1.796655-0.772655-2.802036-1.163637-0.605091-0.195491-1.200873-0.390982-2.010764-0.577163-0.390982 0-0.586473-0.195491-0.996073-0.195491-2.196945-0.577164-4.012218-0.577164-5.008291-0.577164h-0.400291c-0.996073 0-3.006836 0-5.408581 0.577164-0.400291 0-0.595782 0.195491-0.996073 0.195491-0.400291 0.195491-1.005382 0.195491-1.405673 0.390981a15.555491 15.555491 0 0 0-3.006836 1.163637c-0.195491 0-0.195491 0.195491-0.400291 0.195491 0 0.195491-0.195491 0.195491-0.195491 0.195491-1.200873 0.577164-2.606545 1.349818-3.611927 2.122472l-0.195491 0.195491a7.000436 7.000436 0 0 0-2.401746 1.7408l-67.314036 64.660946c-4.803491 4.449745-7.614836 10.426182-7.614836 16.7936-0.195491 6.376727 2.606545 12.744145 7.214545 17.370763s10.826473 7.335564 17.435927 7.335564 13.218909-2.513455 18.031709-7.149382l24.641164-23.738182v266.267928c0 13.312 11.226764 24.129164 25.041455 24.129163s25.041455-10.817164 25.041454-24.129163V532.452073l26.046836 24.520145c4.608 4.626618 10.817164 6.953891 17.640728 6.953891 6.795636 0 13.014109-2.513455 17.836218-7.149382l0.186182-0.195491c9.616291-9.644218 9.4208-24.510836-0.400291-33.773381l-0.223418-0.186182z" fill="#2c2c2c" p-id="3120"></path></svg>
<svg t="1704873961556" viewBox="0 0 1124 1224" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8913" width="14" height="14"><path stroke-width="150" d="M302.545455 116.363636h409.6a27.927273 27.927273 0 0 0 0-55.854545h-409.6a27.927273 27.927273 0 1 0 0 55.854545z m-93.09091 102.4h595.781819a27.927273 27.927273 0 0 0 0-55.854545h-595.781819a27.927273 27.927273 0 1 0 0 55.854545z m670.254546 55.854546h-735.418182c-51.414109 0-93.090909 41.686109-93.090909 93.090909v512c0 51.414109 41.6768 93.090909 93.090909 93.090909h735.418182c51.414109 0 93.090909-41.6768 93.090909-93.090909v-512c0-51.4048-41.6768-93.090909-93.090909-93.090909z m37.236364 594.3296a46.545455 46.545455 0 0 1-46.545455 46.545454h-716.8a46.545455 46.545455 0 0 1-46.545455-46.545454V386.327273a46.545455 46.545455 0 0 1 46.545455-46.545455h716.8a46.545455 46.545455 0 0 1 46.545455 46.545455v482.620509zM602.177164 522.621673l-68.9152-64.474764a4.747636 4.747636 0 0 0-1.405673-1.349818 9.234618 9.234618 0 0 0-1.396364-1.163636 11.776 11.776 0 0 0-3.006836-1.7408c-0.996073-0.577164-1.796655-0.772655-2.802036-1.163637-0.605091-0.195491-1.200873-0.390982-2.010764-0.577163-0.390982 0-0.586473-0.195491-0.996073-0.195491-2.196945-0.577164-4.012218-0.577164-5.008291-0.577164h-0.400291c-0.996073 0-3.006836 0-5.408581 0.577164-0.400291 0-0.595782 0.195491-0.996073 0.195491-0.400291 0.195491-1.005382 0.195491-1.405673 0.390981a15.555491 15.555491 0 0 0-3.006836 1.163637c-0.195491 0-0.195491 0.195491-0.400291 0.195491 0 0.195491-0.195491 0.195491-0.195491 0.195491-1.200873 0.577164-2.606545 1.349818-3.611927 2.122472l-0.195491 0.195491a7.000436 7.000436 0 0 0-2.401746 1.7408l-67.314036 64.660946c-4.803491 4.449745-7.614836 10.426182-7.614836 16.7936-0.195491 6.376727 2.606545 12.744145 7.214545 17.370763s10.826473 7.335564 17.435927 7.335564 13.218909-2.513455 18.031709-7.149382l24.641164-23.738182v266.267928c0 13.312 11.226764 24.129164 25.041455 24.129163s25.041455-10.817164 25.041454-24.129163V532.452073l26.046836 24.520145c4.608 4.626618 10.817164 6.953891 17.640728 6.953891 6.795636 0 13.014109-2.513455 17.836218-7.149382l0.186182-0.195491c9.616291-9.644218 9.4208-24.510836-0.400291-33.773381l-0.223418-0.186182z" fill="#2c2c2c" p-id="8914"></path></svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -71,6 +71,11 @@ export default {
height: calc(100vh - 50px);
overflow-y: auto;
overflow-x: hidden;
.el-alert {
margin-top: -10px;
margin-bottom: 10px;
}
}
.go-back {

View File

@@ -8,6 +8,8 @@ import orgUtil from '@/utils/org'
import orgs from '@/api/orgs'
import { getPropView, isViewHasOrgs } from '@/utils/jms'
import request from '@/utils/request'
import i18n from '@/i18n/i18n'
import { MessageBox } from 'element-ui'
const whiteList = ['/login', process.env.VUE_APP_LOGIN_PATH] // no redirect whitelist
@@ -39,12 +41,30 @@ async function checkLogin({ to, from, next }) {
return reject('No session mark found in cookie')
} else if (sessionExpire === 'close') {
let startTime = new Date().getTime()
this.newLoginHasOpen = false
const intervalId = setInterval(() => {
const endTime = new Date().getTime()
const delta = (endTime - startTime)
startTime = endTime
Vue.$log.debug('Set session expire: ', delta)
if (!isRenewalExpired(120)) {
const currentTimeStamp = Math.floor(endTime / 1000)
const sessionExpireTimestamp = VueCookie.get('jms_session_expire_timestamp')
if (currentTimeStamp >= parseInt(sessionExpireTimestamp, 10)) {
if (!this.newLoginHasOpen) {
this.newLoginHasOpen = true
MessageBox.confirm(
i18n.t('auth.LoginRequiredMsg'),
i18n.t('common.Info'),
{
confirmButtonText: i18n.t('auth.ReLogin'),
cancelButtonText: i18n.t('common.Cancel'),
type: 'warning'
}).finally(() => {
window.location = '/core/auth/logout/'
clearInterval(intervalId)
})
}
} else if (!isRenewalExpired(120)) {
VueCookie.set('jms_session_expire', 'close', { expires: '2m' })
} else {
clearInterval(intervalId)

View File

@@ -1,5 +1,5 @@
<template>
<GenericListTable :table-config="tableConfig" :header-actions="headerActions" />
<GenericListTable :header-actions="headerActions" :table-config="tableConfig" />
</template>
<script>
@@ -110,7 +110,7 @@ export default {
hasSearch: true,
hasRefresh: true,
hasRightActions: true,
hasLeftActions: true,
hasLeftActions: false,
hasMoreActions: false,
hasExport: false,
hasImport: false,

View File

@@ -59,7 +59,7 @@ export default {
[this.$t('common.Basic'), ['name', 'address', 'platform', 'nodes']],
[this.$t('assets.Protocol'), ['protocols']],
[this.$t('assets.Account'), ['accounts']],
[this.$t('common.Other'), ['domain', 'is_active', 'comment']]
[this.$t('common.Other'), ['domain', 'labels', 'is_active', 'comment']]
],
fieldsMeta: assetFieldsMeta(this),
performSubmit(validValues) {

View File

@@ -97,8 +97,13 @@ export default {
route.query.type = row.type.value
route.query.category = row.type.category
}
const { href } = vm.$router.resolve(route)
window.open(href, '_blank')
const createInNewPage = this.$route.query.node_id && routeAction === 'Create'
if (createInNewPage) {
const { href } = vm.$router.resolve(route)
window.open(href, '_blank')
} else {
this.$router.push(route)
}
}
const extraQuery = this.$route.params?.extraQuery || {}
return {

View File

@@ -160,8 +160,12 @@ export default {
}
const router = { name: route, query }
const { href } = this.$router.resolve(router)
window.open(href, '_blank')
if (this.$route.query.node_id) {
const { href } = this.$router.resolve(router)
window.open(href, '_blank')
} else {
this.$router.push(router)
}
}
}
}

View File

@@ -5,7 +5,6 @@
<script>
import { GenericListPage } from '@/layout/components'
import { DetailFormatter } from '@/components/Table/TableFormatters'
import AmountFormatter from '@/components/Table/TableFormatters/AmountFormatter.vue'
export default {
components: {
@@ -17,20 +16,16 @@ export default {
url: '/api/v1/assets/domains/',
columnsExclude: ['gateway'],
columnsExtra: ['gateway_count'],
columns: ['name', 'assets_amount', 'gateway_count', 'comment', 'actions'],
columnsShow: {
min: ['name', 'actions'],
default: ['name', 'assets', 'gateway_count', 'comment', 'actions']
default: ['name', 'assets_amount', 'gateway_count', 'comment', 'actions']
},
columnsMeta: {
assets: {
assets_amount: {
label: this.$t('assets.Assets'),
width: '160px',
formatter: AmountFormatter,
formatterArgs: {
routeQuery: {
activeTab: 'GroupUser'
}
}
formatter: DetailFormatter
},
gateway_count: {
label: this.$t('assets.Gateway'),

View File

@@ -123,6 +123,7 @@ export const assetFieldsMeta = (vm) => {
name: 'labels',
label: vm.$t('assets.Label'),
type: 'm2m',
component: Select2,
el: {
multiple: true,
url: '/api/v1/labels/labels/',

View File

@@ -19,8 +19,8 @@ export default {
data() {
return {
config: {
title: this.$t('dashboard.UserLoginTrend'),
tip: this.$t('dashboard.UserLoginTrend')
title: this.$t('dashboard.SessionConnectTrend'),
tip: this.$t('dashboard.SessionConnectTrend')
},
columnChartConfig: {
datesMetrics: [],

View File

@@ -33,7 +33,7 @@ export default {
{
prop: 'total',
label: this.$t('dashboard.LoginCount'),
width: '80px'
width: '120px'
}
]
},
@@ -50,7 +50,7 @@ export default {
{
prop: 'total',
label: this.$t('dashboard.NumberOfVisits'),
width: '80px'
width: '140px'
}
]
}

View File

@@ -28,7 +28,7 @@ export default {
lineChartConfig: {
datesMetrics: [],
primaryData: [0],
primaryName: this.$t('dashboard.LoginUsers'),
primaryName: this.$t('dashboard.ActiveUsers'),
secondaryData: [0],
secondaryName: this.$t('dashboard.LoginAssets')
}

View File

@@ -9,7 +9,7 @@
class="table"
style="width: 100%"
>
<el-table-column :label="$tc('dashboard.ranking')" width="60px">
<el-table-column :label="$tc('dashboard.ranking')" width="90px">
<template v-slot="scope">
<span>{{ scope.$index + 1 }}</span>
</template>

View File

@@ -44,7 +44,7 @@ export default {
}
},
{
title: this.$t('dashboard.CurrentConnections'),
title: this.$t('dashboard.CurrentConnectionUsers'),
body: {
route: { name: `SessionList`, params: { activeMenu: 'OnlineList' }},
count: this.counter.total_count_online_users,

View File

@@ -51,7 +51,7 @@ export default {
fontSize: 24,
color: '#646A73'
},
subtext: this.$t('dashboard.Proportion') + percentage + '%',
subtext: this.$t('dashboard.Proportion') + ' ' + percentage + '%',
subtextStyle: {
fontSize: 12,
color: '#646A73'

View File

@@ -121,8 +121,10 @@ export default {
}
const url = `/api/v1/labels/labels/${this.label.id}/resource-types/${this.select2.value}/resources/`
this.$axios.put(url, data).then(res => {
this.$message.success(this.$t('common.BindSuccess'))
this.$emit('confirm')
setTimeout(() => {
this.$message.success(this.$tc('common.BindSuccess'))
this.$emit('bind-success')
}, 100)
})
},
async getResourceTypes() {

View File

@@ -1,7 +1,7 @@
<template>
<div>
<GenericListPage ref="GenericListPage" :header-actions="headerActions" :table-config="tableConfig" />
<BindDialog v-if="bindVisible" :label="label" :visible.sync="bindVisible" @confirm="handleDialogConfirm" />
<BindDialog v-if="bindVisible" :label="label" :visible.sync="bindVisible" @bind-success="handleDialogConfirm" />
<LabelResourcesDialog
v-if="resDialogVisible"
:label="label"

View File

@@ -40,8 +40,12 @@ export default {
}
},
headerActions: {
hasImport: false,
onCreate: () => {
this.$emit('addResource')
},
searchConfig: {
getUrlQuery: false
}
}
}

View File

@@ -76,7 +76,11 @@ export default {
required: false
}],
el: {
value: []
value: [],
treeSetting: {
showSearch: false,
showRefresh: false
}
}
},
nodes: {

View File

@@ -21,6 +21,7 @@ import PermBulkUpdateDialog from './components/PermBulkUpdateDialog'
import AmountFormatter from '@/components/Table/TableFormatters/AmountFormatter'
import { mapGetters } from 'vuex'
import { AccountLabelMapper, AssetPermissionListPageSearchConfigOptions } from '../const'
import { DetailFormatter } from '@/components/Table/TableFormatters'
export default {
components: {
@@ -44,11 +45,15 @@ export default {
url: '/api/v1/perms/asset-permissions/',
hasTree: true,
columnsExtra: ['action'],
columns: [
'name', 'users_amount', 'user_groups_amount', 'assets_amount', 'nodes_amount',
'accounts', 'is_expired', 'from_ticket', 'actions'
],
columnsShow: {
min: ['name', 'actions'],
default: [
'name', 'users', 'user_groups', 'assets',
'nodes', 'accounts', 'is_valid', 'actions'
'name', 'users_amount', 'user_groups_amount', 'assets_amount',
'nodes_amount', 'accounts', 'is_valid', 'actions'
]
},
columnsMeta: {
@@ -82,40 +87,40 @@ export default {
showFalse: false
}
},
users: {
users_amount: {
label: this.$t('perms.User'),
width: '60px',
formatter: AmountFormatter,
formatter: DetailFormatter,
formatterArgs: {
routeQuery: {
activeTab: 'AssetPermissionUser'
}
}
},
user_groups: {
user_groups_amount: {
label: this.$t('perms.UserGroups'),
width: '100px',
formatter: AmountFormatter,
formatter: DetailFormatter,
formatterArgs: {
routeQuery: {
activeTab: 'AssetPermissionUser'
}
}
},
assets: {
assets_amount: {
label: this.$t('perms.Asset'),
width: '60px',
formatter: AmountFormatter,
formatter: DetailFormatter,
formatterArgs: {
routeQuery: {
activeTab: 'AssetPermissionAsset'
}
}
},
nodes: {
nodes_amount: {
label: this.$t('perms.Node'),
width: '60px',
formatter: AmountFormatter,
formatter: DetailFormatter,
formatterArgs: {
routeQuery: {
activeTab: 'AssetPermissionAsset'
@@ -152,11 +157,17 @@ export default {
headerActions: {
hasLabelSearch: true,
hasBulkDelete: true,
createRoute() {
return {
onCreate: () => {
const route = {
name: 'AssetPermissionCreate',
query: this.$route.query
}
if (vm.$route.query.node_id) {
const { href } = this.$router.resolve(route)
window.open(href, '_blank')
} else {
this.$router.push(route)
}
},
handleImportClick: ({ selectedRows }) => {
this.$eventBus.$emit('showImportDialog', {
@@ -164,7 +175,6 @@ export default {
url: '/api/v1/perms/asset-permissions/'
})
},
createInNewPage: true,
searchConfig: {
url: '',
options: AssetPermissionListPageSearchConfigOptions

View File

@@ -34,7 +34,7 @@ export default {
settings: {
visible: false,
url: '/api/v1/settings/setting/?category=ldap',
fields: ['AUTH_LDAP_SYNC_ORG_IDS', 'AUTH_LDAP_SYNC_IS_PERIODIC', 'AUTH_LDAP_SYNC_CRONTAB', 'AUTH_LDAP_SYNC_INTERVAL'],
fields: ['AUTH_LDAP_SYNC_ORG_IDS', 'AUTH_LDAP_SYNC_IS_PERIODIC', 'AUTH_LDAP_SYNC_CRONTAB', 'AUTH_LDAP_SYNC_INTERVAL', 'AUTH_LDAP_SYNC_RECEIVERS'],
fieldsMeta: {
AUTH_LDAP_SYNC_ORG_IDS: {
component: Select2,
@@ -63,6 +63,20 @@ export default {
AUTH_LDAP_SYNC_INTERVAL: {
rules: [Required],
helpText: this.$t('xpack.HelpText.IntervalOfCreateUpdatePage')
},
AUTH_LDAP_SYNC_RECEIVERS: {
component: Select2,
label: this.$t('accounts.AccountChangeSecret.Addressee'),
el: {
value: [],
multiple: true,
ajax: {
url: '/api/v1/users/users/?fields_size=mini&oid=ROOT',
transformOption: (item) => {
return { label: item.name + '(' + item.username + ')', value: item.id }
}
}
}
}
},
submitMethod: () => 'patch'

View File

@@ -60,8 +60,8 @@ export default {
],
encryptedFields: ['VAULT_HCP_TOKEN'],
fields: [
[
this.$t('setting.AccountStorage'),
[this.$t('common.Basic'), ['HISTORY_ACCOUNT_CLEAN_LIMIT']],
[this.$t('setting.AccountStorage'),
[
'VAULT_ENABLED',
'VAULT_HCP_HOST',
@@ -71,6 +71,11 @@ export default {
]
],
fieldsMeta: {
HISTORY_ACCOUNT_CLEAN_LIMIT: {
el: {
autocomplete: 'new-password'
}
},
VAULT_ENABLED: {
disabled: true,
label: this.$t('setting.EnableVaultStorage')

View File

@@ -38,7 +38,7 @@ export default {
{
title: this.$t('setting.AccountStorage'),
name: 'Vault',
hidden: !this.$hasPerm('settings.change_vault') || !this.$store.getters.hasValidLicense
hidden: !this.$store.getters.hasValidLicense
},
{
title: this.$t('setting.ChatAI'),

View File

@@ -36,19 +36,16 @@ export default {
[
this.$t('common.BasicInfo'),
[
'EMAIL_HOST', 'EMAIL_PORT', 'EMAIL_HOST_USER',
'EMAIL_HOST_PASSWORD'
]
],
[
this.$t('setting.Security'),
[
'EMAIL_USE_SSL', 'EMAIL_USE_TLS'
'EMAIL_PROTOCOL', 'EMAIL_HOST', 'EMAIL_PORT', 'EMAIL_HOST_USER',
'EMAIL_HOST_PASSWORD', 'EMAIL_USE_SSL', 'EMAIL_USE_TLS'
]
]
],
successUrl: { name: 'Settings', params: { activeMenu: 'EmailContent' }},
fieldsMeta: {
EMAIL_PORT: {
hidden: (formValue) => formValue.EMAIL_PROTOCOL !== 'smtp'
},
EMAIL_HOST_PASSWORD: {
component: UpdateToken
},
@@ -57,6 +54,12 @@ export default {
type: 'textarea',
rows: 3
}
},
EMAIL_USE_SSL: {
hidden: (formValue) => formValue.EMAIL_PROTOCOL !== 'smtp'
},
EMAIL_USE_TLS: {
hidden: (formValue) => formValue.EMAIL_PROTOCOL !== 'smtp'
}
},
url: '/api/v1/settings/setting/?category=email',
@@ -75,6 +78,9 @@ export default {
if (data['EMAIL_USE_TLS'] === null) {
delete data['EMAIL_USE_TLS']
}
if (data['EMAIL_PORT'] === null) {
delete data['EMAIL_PORT']
}
return data
}
}

View File

@@ -4,7 +4,7 @@
<script>
import { GenericListPage } from '@/layout/components'
import AmountFormatter from '@/components/Table/TableFormatters/AmountFormatter.vue'
import { DetailFormatter } from '@/components/Table/TableFormatters'
export default {
components: {
@@ -14,25 +14,27 @@ export default {
return {
tableConfig: {
url: '/api/v1/users/groups/',
columns: ['name', 'users_amount', 'comment', 'actions'],
columnsShow: {
default: ['name', 'users', 'comment', 'actions'],
default: ['name', 'users_amount', 'comment', 'actions'],
min: ['name', 'action']
},
columnsMeta: {
users_amount: {
label: this.$t('users.Users'),
width: '120px'
},
users: {
label: this.$t('perms.User'),
width: '160px',
formatter: AmountFormatter,
width: '120px',
formatter: DetailFormatter,
formatterArgs: {
getItem(item) {
return item.is_service_account ? null : item.name
},
routeQuery: {
activeTab: 'GroupUser'
getRoute({ row }) {
return {
name: 'UserGroupDetail',
params: {
id: row.id
},
query: {
activeTab: 'GroupUser'
}
}
}
}
}