Compare commits

..

6 Commits

Author SHA1 Message Date
ibuler
1e777ea67d perf: remove check 2024-12-10 17:28:58 +08:00
ibuler
a290e15b90 perf: 修改抽屉,传递动作 2023-11-08 19:18:49 +08:00
“huailei000”
b47f396cd4 perf: 详情暂时不显示更新按钮 2023-11-08 18:22:35 +08:00
“huailei000”
085554ef7f perf: 优化资产授权报错 2023-11-08 17:15:05 +08:00
feng
a62884564c perf: 在线用户根据websocket添加用户是否活跃状态 2023-11-08 17:03:01 +08:00
fit2bot
a9c0d0677c feat: 右侧抽屉创建 (#3436)
* stash

* perf: 验证用户和网域

* perf: 优化 drawer

* perf: 优化创建后 list reload

* perf: 优化创建

* perf: 替换账号管理相关页面创建、更新组件

* perf: 替换权限管理相关页面组件

* perf: 优化资产这里

* perf: 修改 reload

* perf: 替换权限管理-用户登录页面组件

* perf: 修改资产这里

* perf: 优化一点

* perf: 优化平台列表创建、更新抽屉组件不能正常显示问题

* perf: 优化平台列表创建时表单初始化数据不准确问题

* perf: 优化创建、更新平台表单报错问题

* perf: 优化列表克隆问题

* perf: 优化创建资产时抽屉组件偶尔不显示问题

* perf: 优化工作台创建、更新组件

* perf: GenericCreateUpdateDrawer 组件增加参数visible控制显示隐藏

* perf: 优化visible判断

* perf: 优化资产创建、更新

* perf: 增加el-drawer组件补丁,防止在抽屉里复制拖拽至遮罩层会使抽屉关闭问题

* perf: 优化角色列表创建、更新报错问题;优化关闭抽屉控制台报错问题

* perf: 优化作业管理创建、更新

* perf: 优化工单创建

* perf: 优化远程应用创建、更新

---------

Co-authored-by: ibuler <ibuler@qq.com>
Co-authored-by: “huailei000” <2280131253@qq.com>
Co-authored-by: wangruidong <940853815@qq.com>
Co-authored-by: huailei <31801270+huailei000@users.noreply.github.com>
2023-11-08 11:21:39 +08:00
147 changed files with 2908 additions and 2511 deletions

View File

@@ -19,7 +19,9 @@ jobs:
id: get_version
run: |
TAG=$(basename ${GITHUB_REF})
VERSION=${TAG/v/}
echo "::set-output name=TAG::$TAG"
echo "::set-output name=VERSION::$VERSION"
- name: Create Release
id: create_release
uses: release-drafter/release-drafter@v5
@@ -41,10 +43,10 @@ jobs:
- name: Create Upload Assets
run: |
rm -rf build/*
mv lina lina-${{ steps.get_version.outputs.TAG }}
tar -czf lina-${{ steps.get_version.outputs.TAG }}.tar.gz lina-${{ steps.get_version.outputs.TAG }}
echo $(md5sum lina-${{ steps.get_version.outputs.TAG }}.tar.gz | awk '{print $1}') > build/lina-${{ steps.get_version.outputs.TAG }}.tar.gz.md5
mv lina-${{ steps.get_version.outputs.TAG }}.tar.gz build/
mv lina lina-${{ steps.get_version.outputs.VERSION }}
tar -czf lina-${{ steps.get_version.outputs.VERSION }}.tar.gz lina-${{ steps.get_version.outputs.VERSION }}
echo $(md5sum lina-${{ steps.get_version.outputs.VERSION }}.tar.gz | awk '{print $1}') > build/lina-${{ steps.get_version.outputs.VERSION }}.tar.gz.md5
mv lina-${{ steps.get_version.outputs.VERSION }}.tar.gz build/
- name: Release Upload Assets
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/')

1
GITSHA
View File

@@ -1 +0,0 @@
4b93cf298ceb337dd3082cf408c1b70c6e0d79b9

View File

@@ -5,11 +5,10 @@
"author": "Pan <panfree23@gmail.com>",
"license": "MIT",
"scripts": {
"dev": "vue-cli-service serve",
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"dev": "NODE_OPTIONS=--openssl-legacy-provider vue-cli-service serve",
"serve": "NODE_OPTIONS=--openssl-legacy-provider vue-cli-service serve",
"build": "NODE_OPTIONS=--openssl-legacy-provider vue-cli-service build",
"build:prod": "vue-cli-service build",
"build:stage": "vue-cli-service build --mode staging",
"preview": "node build/index.js --preview",
"lint": "eslint --ext .js,.vue src",
"fix": "eslint --ext .js,.vue --fix src",

View File

@@ -1,16 +1,5 @@
<template>
<Dialog
v-if="iVisible"
:close-on-click-modal="false"
:destroy-on-close="true"
:show-cancel="false"
:show-confirm="false"
:title="title"
:visible.sync="iVisible"
v-bind="$attrs"
width="70%"
v-on="$listeners"
>
<GenericCreateUpdateDrawer v-bind="$attrs">
<AccountCreateUpdateForm
v-if="!loading"
ref="form"
@@ -20,18 +9,18 @@
@add="addAccount"
@edit="editAccount"
/>
</Dialog>
</GenericCreateUpdateDrawer>
</template>
<script>
import Dialog from '@/components/Dialog/index.vue'
import GenericCreateUpdateDrawer from '@/layout/components/GenericCreateUpdateDrawer/index.vue'
import AccountCreateUpdateForm from '@/components/Apps/AccountCreateUpdateForm/index.vue'
export default {
name: 'CreateAccountDialog',
components: {
Dialog,
AccountCreateUpdateForm
AccountCreateUpdateForm,
GenericCreateUpdateDrawer
},
props: {
visible: {

View File

@@ -14,21 +14,11 @@
@updateAuthDone="onUpdateAuthDone"
/>
<AccountCreateUpdate
v-if="showAddDialog"
:account="account"
:url="url"
:asset="iAsset"
:title="accountCreateUpdateTitle"
:visible.sync="showAddDialog"
@add="addAccountSuccess"
@bulk-create-done="showBulkCreateResult($event)"
/>
<AccountCreateUpdate
v-if="showAddTemplateDialog"
:account="account"
:add-template="true"
:asset="iAsset"
:add-template="addTemplate"
:title="accountCreateUpdateTitle"
:visible.sync="showAddTemplateDialog"
@add="addAccountSuccess"
@bulk-create-done="showBulkCreateResult($event)"
/>
@@ -128,6 +118,7 @@ export default {
showAddDialog: false,
showAddTemplateDialog: false,
createAccountResults: [],
addTemplate: false,
accountCreateUpdateTitle: this.$t('assets.AddAccount'),
iAsset: this.asset,
account: {},
@@ -258,7 +249,7 @@ export default {
name: 'Update',
title: this.$t('common.Update'),
can: this.$hasPerm('accounts.change_account') && !this.$store.getters.currentOrgIsRoot,
callback: ({ row }) => {
callback: ({ row, col }) => {
const data = {
...this.asset,
...row.asset
@@ -266,9 +257,10 @@ export default {
vm.account = row
vm.iAsset = data
vm.showAddDialog = false
vm.addTemplate = false
vm.accountCreateUpdateTitle = this.$t('assets.UpdateAccount')
setTimeout(() => {
vm.showAddDialog = true
vm.$eventBus.$emit('showCreateUpdateDrawer', 'update', { url: this.url, row, col })
})
}
}
@@ -313,8 +305,9 @@ export default {
setTimeout(() => {
vm.iAsset = this.asset
vm.account = {}
vm.addTemplate = false
vm.accountCreateUpdateTitle = this.$t('assets.AddAccount')
vm.showAddDialog = true
vm.$eventBus.$emit('showCreateUpdateDrawer', 'create', { url: vm.url })
})
}
},
@@ -330,8 +323,9 @@ export default {
setTimeout(() => {
vm.iAsset = this.asset
vm.account = {}
vm.addTemplate = true
vm.accountCreateUpdateTitle = this.$t('assets.AddAccount')
vm.showAddTemplateDialog = true
vm.$eventBus.$emit('showCreateUpdateDrawer', 'create', { url: vm.url })
})
}
},

View File

@@ -83,6 +83,16 @@ export default {
return row.platform.name
}
},
{
prop: 'protocols',
formatter: function(row) {
const data = row.protocols?.map(p => {
return <el-tag size='mini'>{p.name}/{p.port} </el-tag>
})
return <span> {data} </span>
},
label: this.$t('assets.Protocols')
},
{
prop: 'actions',
has: false

View File

@@ -51,12 +51,7 @@
</el-row>
<el-row :gutter="24" style="margin: 0 auto;">
<el-col :md="24" :sm="24" style="display: flex; margin-bottom: 20px;">
<el-input
v-model="secretValue"
:placeholder="inputPlaceholder"
:show-password="showPassword"
@keyup.enter.native="handleConfirm"
/>
<el-input v-model="secretValue" :placeholder="inputPlaceholder" :show-password="showPassword" />
<span v-if="subTypeSelected === 'sms'" style="margin: -1px 0 0 20px;">
<el-button
:disabled="smsBtnDisabled"
@@ -121,6 +116,7 @@ export default {
}
},
mounted() {
// const onRecvCallback = _.debounce(this.performConfirm, 500)
this.$eventBus.$on('showConfirmDialog', this.performConfirm)
},
methods: {
@@ -149,7 +145,6 @@ export default {
this.title = this.$t('auth.NeedReLogin')
this.visible = true
})
return
}
this.subTypeChoices = data.content
const defaultSubType = this.subTypeChoices.filter(item => !item.disabled)[0]
@@ -200,7 +195,6 @@ export default {
}
this.$axios.post(`/api/v1/authentication/confirm/`, data).then(res => {
this.callback()
this.secretValue = ''
this.visible = false
})
}

View File

@@ -18,7 +18,9 @@ export default {
}
},
data() {
return {}
return {
formatterData: ''
}
},
computed: {
displayValue() {
@@ -67,18 +69,17 @@ export default {
}
},
render(h) {
let formatterData = ''
if (typeof this.formatter === 'function') {
const data = this.formatter(this.item, this.value)
if (data instanceof Promise) {
data.then(res => {
formatterData = res
this.formatterData = res
})
} else {
formatterData = data
this.formatterData = data
}
return (
<span>{formatterData}</span>
<span>{this.formatterData}</span>
)
}
if (this.value instanceof Array) {

View File

@@ -1,19 +1,22 @@
<template>
<ElFormRender
ref="form"
:class="mobile? 'mobile' : 'desktop'"
:content="fields"
:form="basicForm"
:label-position="labelPosition"
label-width="20%"
v-bind="$attrs"
v-on="$listeners"
>
<!-- slot 透传 -->
<slot v-for="item in fields" :slot="`id:${item.id}`" :name="`id:${item.id}`" />
<slot v-for="item in fields" :slot="`$id:${item.id}`" :name="`$id:${item.id}`" />
<div>
<ElFormRender
ref="form"
:class="mobile? 'mobile' : 'desktop'"
:content="fields"
:form="basicForm"
:label-position="labelPosition"
class="form-fields"
label-width="22%"
v-bind="$attrs"
v-on="$listeners"
>
<!-- slot 透传 -->
<slot v-for="item in fields" :slot="`id:${item.id}`" :name="`id:${item.id}`" />
<slot v-for="item in fields" :slot="`$id:${item.id}`" :name="`$id:${item.id}`" />
<el-form-item v-if="hasButtons" class="form-buttons">
</ElFormRender>
<div v-if="hasButtons" class="form-buttons">
<el-button
v-for="button in moreButtons"
:key="button.title"
@@ -44,8 +47,8 @@
>
{{ submitBtnText }}
</el-button>
</el-form-item>
</ElFormRender>
</div>
</div>
</template>
<script>
@@ -160,7 +163,7 @@ export default {
}
.el-form ::v-deep .el-form-item__content {
width: 75%;
width: 73%;
}
.mobile.el-form ::v-deep .el-form-item__content {
@@ -198,5 +201,7 @@ export default {
.form-buttons {
margin-top: 20px;
margin-left: 22%;
margin-bottom: 20px;
}
</style>

View File

@@ -83,14 +83,6 @@ export default {
hidden: (formValue) => formValue['autofill'] !== 'script'
}
}
},
public: {
disabled: this.protocol.name === 'winrm',
hidden: (formValue) => {
if (this.protocol.name === 'winrm') {
formValue['public'] = false
}
}
}
}
}

View File

@@ -21,8 +21,8 @@
:type="inputType"
class="search-input"
@blur="focus = false"
@change="handleConfirm"
@focus="focus = true"
@change="handleChange"
@select="handleSelect"
@keyup.enter.native="handleConfirm"
/>
@@ -99,9 +99,6 @@ export default {
this.filterValue = item.value
this.handleConfirm()
},
handleChange: _.debounce(function(item) {
this.handleConfirm()
}, 240),
handleConfirm() {
if (this.filterValue === '') return

View File

@@ -1,5 +1,5 @@
<template>
<div :class="bolder ? 'bolder' : ''" class="input-text">
<div class="input-text">
{{ value.toString() || text }}
</div>
</template>
@@ -9,15 +9,11 @@ export default {
props: {
value: {
type: [String, Boolean],
default: ''
default: () => ''
},
text: {
type: String,
default: ''
},
bolder: {
type: Boolean,
default: true
default: () => ''
}
},
data() {

View File

@@ -75,6 +75,9 @@ export default {
}
})
},
beforeDestroy() {
this.$eventBus.$off('showColumnSettingPopover')
},
methods: {
handleColumnConfirm() {
this.showColumnSettingPopover = false

View File

@@ -103,9 +103,7 @@ class StrategyPersistSelection extends StrategyAbstract {
*/
updateElTableSelection() {
const { data, id, selected } = this.elDataTable
// 历史勾选的行已经不在当前页了所以要将当前页的行数据和selected合并
const mergeData = _.uniqWith([...data, ...selected], _.isEqual)
mergeData.forEach(r => {
data.forEach(r => {
const isSelected = !!selected.find(r2 => r[id] === r2[id])
if (!this.elTable) {
return

View File

@@ -124,8 +124,8 @@ export default {
watch: {},
methods: {
getList() {
this.$refs.table.clearSelection()
return this.$refs.table.getList()
this.$refs.table?.clearSelection()
return this.$refs.table?.getList()
},
getData() {
return this.$refs.table.data

View File

@@ -174,6 +174,9 @@ export default {
}
})
},
beforeDestroy() {
this.$eventBus.$off('showExportDialog')
},
methods: {
showExportDialog() {
if (!this.mfaVerifyRequired) {

View File

@@ -147,6 +147,9 @@ export default {
}
})
},
beforeDestroy() {
this.$eventBus.$off('showImportDialog')
},
methods: {
closeDialog() {
this.showImportDialog = false

View File

@@ -38,6 +38,10 @@ export default {
type: Boolean,
default: false
},
createInDrawer: {
type: Boolean,
default: true
},
hasBulkDelete: defaultTrue,
canBulkDelete: defaultTrue,
hasBulkUpdate: defaultFalse,
@@ -187,6 +191,10 @@ export default {
},
methods: {
handleCreate() {
if (this.createInDrawer) {
this.$eventBus.$emit('showCreateUpdateDrawer', 'create', { url: this.tableUrl })
return
}
let route
if (typeof this.createRoute === 'string') {
route = { name: this.createRoute }

View File

@@ -79,11 +79,11 @@ export default {
computed: {
...mapGetters(['currentOrgIsRoot']),
dataTable() {
return this.$refs.dataTable.$refs.dataTable
return this.$refs.dataTable?.$refs?.dataTable
},
iHeaderActions() {
// 如果路由中锁定了 root 组织,就不在检查 root 组织下是否可以创建等
const checkRoot = !(this.$route.meta?.disableOrgsChange === true)
const checkRoot = this.$route.meta?.disableOrgsChange !== true
const actions = {
canCreate: { action: 'add', checkRoot: checkRoot },
canBulkDelete: { action: 'delete', checkRoot: false },
@@ -108,7 +108,7 @@ export default {
const config = deepmerge(this.tableConfig, {
extraQuery: this.extraQuery
})
const checkRoot = !(this.$route.meta?.disableOrgsChange === true)
const checkRoot = this.$route.meta?.disableOrgsChange !== true
const formatterArgs = {
'columnsMeta.actions.formatterArgs.canUpdate': () => {
return this.hasActionPerm('change') && (!checkRoot || !this.currentOrgIsRoot)
@@ -165,12 +165,29 @@ export default {
deep: true
}
},
mounted() {
this.$eventBus.$on('closeCreateUpdateDrawer', ({ success }) => {
if (!success) {
return
}
this.extraQuery = {
...this.extraQuery,
order: '-date_updated'
}
setTimeout(() => {
this.reloadTable()
})
})
},
beforeDestroy() {
this.$eventBus.$off('closeCreateUpdateDrawer')
},
methods: {
handleSelectionChange(val) {
this.selectedRows = val
},
reloadTable() {
this.dataTable.getList()
this.dataTable?.getList()
},
search(attrs) {
this.$emit('TagSearch', attrs)

View File

@@ -102,6 +102,9 @@ export default {
this.componentKey += 1
})
},
beforeDestroy() {
this.$eventBus.$off('treeComponentKey')
},
methods: {
hideRMenu() {
this.$refs.AutoDataZTree?.hideRMenu()

View File

@@ -21,34 +21,12 @@ const defaultPerformDelete = function({ row, col }) {
}
const defaultUpdateCallback = function({ row, col }) {
const id = row.id
let route = { params: { id: id }}
const updateRoute = this.colActions.updateRoute
console.log('Update route: ', updateRoute)
if (typeof updateRoute === 'object') {
route = Object.assign(route, updateRoute)
} else if (typeof updateRoute === 'function') {
route = updateRoute({ row, col })
} else {
route.name = updateRoute
}
this.$router.push(route)
this.$eventBus.$emit('showCreateUpdateDrawer', 'update', { url: this.url, row, col })
}
const defaultCloneCallback = function({ row, col }) {
const id = row.id
let route = { query: { clone_from: id }}
const cloneRoute = this.colActions.cloneRoute
if (typeof cloneRoute === 'object') {
route = Object.assign(route, cloneRoute)
} else if (typeof cloneRoute === 'function') {
route = cloneRoute({ row, col })
} else {
route.name = cloneRoute
}
this.$router.push(route)
console.log('Url: ', this.url)
this.$eventBus.$emit('showCreateUpdateDrawer', 'clone', { url: this.url, row, col })
}
const defaultDeleteCallback = function({ row, col, cellValue, reload }) {

View File

@@ -142,9 +142,6 @@ export default {
},
selectNode: function(node) {
return this.$refs.AutoDataZTree.selectNode(node)
},
reloadTable() {
this.$refs.ListTable.reloadTable()
}
}
}

View File

@@ -8,7 +8,7 @@
</span>
</div>
</div>
<el-col :span="span" :style="{'height': height + 'px' }">
<el-col :span="span">
<el-input
v-model="iValue"
autosize
@@ -17,7 +17,7 @@
@change="onChange"
/>
</el-col>
<el-col v-show="isShow" :span="span">
<el-col v-if="isShow" :span="span">
<VueMarkdown class="result-html" :source="iValue" :show="true" :html="true" />
</el-col>
</el-row>
@@ -49,35 +49,11 @@ export default {
},
data() {
return {
height: 0,
resizeObserver: null,
span: 12,
isShow: true,
iValue: this.value
}
},
mounted() {
this.$nextTick(() => {
this.resizeObserver = new ResizeObserver(entries => {
// 监听高度变化
const height = entries[0].target.offsetHeight
if (height) {
this.height = height
}
})
const el = document.querySelector('.result-html')
if (el) {
this.resizeObserver.observe(el)
}
})
},
beforeDestroy() {
const el = document.querySelector('.result-html')
if (el) {
this.resizeObserver.unobserve(el)
}
this.resizeObserver = null
},
methods: {
onChange() {
this.$emit('change', this.iValue)
@@ -100,17 +76,15 @@ export default {
font-size: 13px;
}
>>> .el-textarea {
height: 100% !important;
.el-textarea__inner {
min-height: 210px !important;
height: 100% !important;
}
>>> .el-textarea__inner {
min-height: 210px !important;
}
.source {
padding: 6px;
background-color: #f3f3f3;
}
.result-html {
height: 100%;
min-height: 210px;
margin-left: 4px;
padding: 5px 10px;

View File

@@ -499,7 +499,7 @@
"AddPassKey": "AddPassKey"
},
"common": {
"BelongAll": "Contains all",
"BelongAll": "Include all",
"WordSep": " ",
"Enterprise": "Enterprise",
"SyncTask": "Synchronization task",
@@ -905,7 +905,7 @@
"IsActive": "Is active",
"LessEqualThan": "Less than or equal to",
"OtherRules": "Other rules",
"BelongTo": "Contains any",
"BelongTo": "Belong to",
"GreatEqualThan": "Greater than or equal to",
"PasswordRule": "PasswordRule",
"Uppercase": "Uppercase",
@@ -1767,7 +1767,6 @@
"securityPasswordSpecialChar": "Must contain special characters",
"securityPasswordUpperCase": "Must contain capital letters",
"securityServiceAccountRegistration": "Service account registration",
"Storage": "Storage",
"siteUrl": "Current SITE URL",
"technologyConsult": "Technology Consult",
"terminalAssetListPageSize": "List page size",
@@ -1823,8 +1822,7 @@
"BasicTools": "Basic tool",
"sync": "Sync",
"AccountStorage": "Account Storage",
"Passkey": "Passkey",
"ReplayStorageCreateUpdateHelpMessage": "Note: Currently, SFTP storage only supports account backup and does not support video storage."
"Passkey": "Passkey"
},
"tickets": {
"BatchApproval": "Batch approval",

View File

@@ -499,7 +499,7 @@
"AddPassKey": "パスキー(通行鍵)を追加"
},
"common": {
"BelongAll": "すべてが含まれています",
"BelongAll": "すべて",
"Enterprise": "企業版",
"SyncTask": "同期任務です",
"New": "新筑",
@@ -903,7 +903,7 @@
"IsActive": "アクティブです",
"LessEqualThan": "以下または等しい",
"OtherRules": "他のルール",
"BelongTo": "どれも含まれます",
"BelongTo": "所属する",
"GreatEqualThan": "以上または等しい",
"PasswordRule": "パスワードのルール",
"Uppercase": "大文字",
@@ -1771,7 +1771,6 @@
"securityPasswordSpecialChar": "特殊文字を含む必要があります",
"securityPasswordUpperCase": "大文字を含む必要があります",
"securityServiceAccountRegistration": "端末登録",
"Storage": "設定を保存する",
"siteUrl": "現在のサイトURL",
"technologyConsult": "技術コンサルティング",
"terminalAssetListPageSize": "資産ページングのページ数あたり",
@@ -1814,8 +1813,7 @@
"Applets": "リモート アプリケーション",
"sync": "同期",
"AccountStorage": "アカウントストレージ",
"Passkey": "パスキー",
"ReplayStorageCreateUpdateHelpMessage": "注: 現在、SFTP ストレージはアカウントのバックアップのみをサポートしており、ビデオ ストレージはサポートしていません。"
"Passkey": "パスキー"
},
"tickets": {
"BatchApproval": "大量承認です",

View File

@@ -477,7 +477,7 @@
"ReLoginErr": "登录时长已超过 5 分钟,请重新登录"
},
"common": {
"BelongAll": "同时包含",
"BelongAll": "包含所有",
"WordSep": "",
"PasswordRule": "密码生成规则",
"Length": "长度",
@@ -511,7 +511,7 @@
"MatchResult": "匹配结果",
"GreatEqualThan": "大于等于",
"LessEqualThan": "小于等于",
"BelongTo": "任意包含",
"BelongTo": "所属",
"Email": "邮箱",
"IsActive": "激活",
"All": "所有",
@@ -1790,8 +1790,7 @@
"TestParam": "参数",
"sync": "同步",
"testHelpText": "请输入目的地址进行测试",
"Storage": "存储设置",
"ReplayStorageCreateUpdateHelpMessage": "注意:目前 SFTP 存储仅支持账号备份,暂不支持录像存储。"
"Storage": "存储设置"
},
"tickets": {
"BatchApproval": "批量审批",
@@ -2104,6 +2103,7 @@
"SaveSetting": "同步设置",
"Name": "名称",
"Account": "云账号",
"CreateAccount": "创建云账号",
"Node": "节点",
"WindowsAdminUser": "Windows 特权用户",
"LinuxAdminUser": "Linux 特权用户",

View File

@@ -0,0 +1,187 @@
<template>
<el-drawer
:direction="direction"
:modal="false"
:size="width"
:title="iTitle"
:visible.sync="iVisible"
append-to-body
class="drawer generic-create-update-drawer"
wrapper-closable
v-on="$listeners"
>
<div class="el-drawer__content">
<slot>
<GenericCreateUpdateForm
v-if="iVisible"
:action="iAction"
:action-id="iActionId"
v-bind="$attrs"
@submitSuccess="onSubmitSuccess"
v-on="$listeners"
/>
</slot>
</div>
</el-drawer>
</template>
<script>
import GenericCreateUpdateForm from '../GenericCreateUpdateForm/index.vue'
export default {
name: 'GenericCreateUpdateDrawer',
components: {
GenericCreateUpdateForm
},
props: {
direction: {
type: String,
default: 'rtl'
},
title: {
type: String,
default: ''
},
resource: {
type: String,
default: ''
},
width: {
type: String,
default: '700px'
},
name: {
type: String,
default: ''
},
action: {
type: String,
default: 'create'
},
actionId: {
type: String,
default: ''
},
visible: {
type: Boolean,
default: false
},
actionMeta: {
type: Object,
default: () => ({})
}
},
data() {
return {
iVisible: this.visible,
iAction: this.action,
iActionId: this.actionId,
success: false
}
},
computed: {
iTitle() {
if (this.title) {
return this.title
}
let resource = this.resource
if (!resource) {
const routeName = this.$route.meta.title || this.$route.name
resource = routeName.replace('List', '')
.replace('列表', '')
}
let title
if (this.iAction === 'update') {
title = this.$t('common.Update') + ' ' + resource
} else {
title = this.$t('common.Create') + ' ' + resource
}
return title
}
},
watch: {
visible(val) {
this.setVisible(val)
},
iVisible(val) {
if (!val) {
this.iVisible = false
this.$eventBus.$emit(
'closeCreateUpdateDrawer',
{ action: this.iAction, actionId: this.iActionId, success: this.success }
)
this.$emit('close', { action: this.iAction, actionId: this.iActionId, success: this.success })
}
}
},
mounted() {
this.$eventBus.$on('showCreateUpdateDrawer', (action, { url, row }) => {
const tableUrl = this.$attrs.url
this.$log.debug('Table url: ', tableUrl, ' action url: ', url, 'action: ', action, 'row: ', row)
if (!tableUrl || !url) {
return
}
const tablePath = tableUrl.split('?')[0]
const actionPath = url.split('?')[0]
if (tablePath !== actionPath) {
return
}
this.iAction = action
this.iActionId = row ? row.id : ''
this.$emit('update:actionMeta', { action: action, actionId: this.iActionId, row: row })
this.setVisible(true)
})
},
beforeDestroy() {
this.$eventBus.$off('showCreateUpdateDrawer')
},
methods: {
setVisible: _.debounce(function(val) {
this.iVisible = val
}, 100),
onSubmitSuccess(res, { addContinue }) {
this.success = true
if (!addContinue) {
this.iVisible = false
}
}
}
}
</script>
<style lang='scss' scoped>
.ibox >>> .el-card__body {
padding-top: 30px;
}
.el-drawer__content {
>>> .form-fields {
overflow: auto;
max-height: calc(100vh - 150px);
}
>>> .form-buttons {
//position: absolute;
//bottom: 15px;
width: 100%;
background: white;
}
}
.el-drawer__footer {
text-align: right;
vertical-align: middle;
padding-right: 52px;
border-top: solid 1px #ebeef5;
}
.drawer >>> .el-drawer__header {
font-weight: 500;
font-size: 16px;
}
.el-drawer__footer_buttons {
margin-top: 10px;
}
</style>

View File

@@ -7,6 +7,7 @@
:has-save-continue="iHasSaveContinue"
:is-submitting="isSubmitting"
:method="method"
:submit-btn-text="submitBtnText"
:url="iUrl"
v-bind="$attrs"
@afterRemoteMeta="handleAfterRemoteMeta"
@@ -18,7 +19,6 @@
import AutoDataForm from '@/components/Form/AutoDataForm'
import { getUpdateObjURL } from '@/utils/common'
import { encryptPassword } from '@/utils/crypto'
import deepmerge from 'deepmerge'
export default {
name: 'GenericCreateUpdateForm',
@@ -31,6 +31,14 @@ export default {
type: String,
default: ''
},
action: {
type: String,
default: ''
},
actionId: {
type: [String, Number],
default: ''
},
// 更新的对象
object: {
type: Object,
@@ -116,19 +124,11 @@ export default {
return { name: routeName }
}
},
// 获取下一个路由
getNextRoute: {
type: Function,
default(res, method) {
return method === 'post' ? this.createSuccessNextRoute : this.updateSuccessNextRoute
}
},
// 获取提交的方法
submitMethod: {
type: [Function, String],
default: function() {
const params = this.$route.params
if (params.id) {
if (this.action === 'update') {
return 'put'
} else {
return 'post'
@@ -139,20 +139,20 @@ export default {
getUrl: {
type: Function,
default: function() {
const params = this.$route.params
let url = this.url
if (params.id) {
url = getUpdateObjURL(url, params.id)
if (this.action === 'update') {
url = getUpdateObjURL(url, this.actionId)
}
const clone_from = this.$route.query['clone_from']
const query = clone_from ? `clone_from=${clone_from}` : ''
if (query) {
if (url.indexOf('?') === -1) {
url = `${url}?${query}`
} else {
url = `${url}&${query}`
}
const cloneFrom = this.action === 'clone' ? this.actionId : ''
const query = cloneFrom ? `clone_from=${cloneFrom}` : ''
if (!query) {
return url
}
if (url.indexOf('?') === -1) {
url = `${url}?${query}`
} else {
url = `${url}&${query}`
}
return url
}
@@ -204,18 +204,8 @@ export default {
onPerformSuccess: {
type: Function,
default(res, method, vm, addContinue) {
const route = this.getNextRoute(res, method)
if (!(route.params && route.params.id)) {
route['params'] = deepmerge(route['params'] || {}, { 'id': res.id, order: this.extraQueryOrder })
} else {
route['params'] = deepmerge(route['params'], { order: this.extraQueryOrder })
}
this.$emit('submitSuccess', res)
this.$emit('submitSuccess', res, { method, vm, addContinue })
this.emitPerformSuccessMsg(method, res, addContinue)
if (!addContinue) {
setTimeout(() => this.$router.push(route), 100)
}
}
},
onPerformError: {
@@ -292,6 +282,13 @@ export default {
return this.hasReset
}
return this.isUpdateMethod()
},
submitBtnText() {
if (this.action === 'update') {
return this.$t('common.Update')
} else {
return this.$t('common.Create')
}
}
},
async created() {
@@ -306,6 +303,8 @@ export default {
this.loading = false
}
},
mounted() {
},
methods: {
isUpdateMethod() {
return ['put', 'patch'].indexOf(this.method.toLowerCase()) > -1
@@ -348,25 +347,26 @@ export default {
})
},
async getFormValue() {
const cloneFrom = this.$route.query['clone_from']
if ((!this.isUpdateMethod() && !cloneFrom) || !this.needGetObjectDetail) {
const cloneFrom = this.actionId
if (this.action === 'create' || !this.needGetObjectDetail) {
return Object.assign(this.form, this.initial)
}
let object = this.object
if (!object || Object.keys(object).length === 0) {
if (cloneFrom) {
const [curUrl, query] = this.url.split('?')
const url = `${curUrl}${cloneFrom}/${query ? ('?' + query) : ''}`
object = await this.getObjectDetail(url)
if (object['name']) {
object.name = this.$t('common.cloneFrom') + object.name
} else if (object['hostname']) {
object.hostname = this.$t('common.cloneFrom') + object.hostname
object.name = this.$t('common.cloneFrom') + '' + object.name
}
} else {
object = await this.getObjectDetail(this.iUrl)
if (object && Object.keys(object).length > 0) {
return object
}
if (this.action === 'clone') {
const [curUrl, query] = this.url.split('?')
const url = `${curUrl}${cloneFrom}/${query ? ('?' + query) : ''}`
object = await this.getObjectDetail(url)
if (object['name']) {
object.name = this.$t('common.cloneFrom') + object.name
} else if (object['hostname']) {
object.hostname = this.$t('common.cloneFrom') + object.hostname
object.name = this.$t('common.cloneFrom') + '' + object.name
}
} else {
object = await this.getObjectDetail(this.iUrl)
}
if (object) {
object = _.cloneDeep(object)

View File

@@ -129,13 +129,14 @@ export default {
...mapGetters(['currentOrgIsRoot']),
pageActions() {
return [
{
name: 'update',
title: this.$t('common.Update'),
can: this.validActions.canUpdate,
has: this.validActions.hasUpdate,
callback: this.validActions.updateCallback.bind(this)
},
// 暂时处理,详情中关闭更新操作
// {
// name: 'update',
// title: this.$t('common.Update'),
// can: this.validActions.canUpdate,
// has: this.validActions.hasUpdate,
// callback: this.validActions.updateCallback.bind(this)
// },
{
name: 'delete',
title: this.$t('common.Delete'),

View File

@@ -1,22 +1,17 @@
<template>
<Page v-bind="$attrs">
<GenericListTable ref="ListTable" v-bind="$attrs" />
<ListTable ref="ListTable" v-bind="$attrs" />
</Page>
</template>
<script>
import Page from '@/layout/components/Page'
import GenericListTable from '@/layout/components/GenericListTable'
import ListTable from '@/components/Table/ListTable/index'
export default {
name: 'GenericListPage',
components: {
Page, GenericListTable
},
methods: {
reloadTable() {
this.$refs.ListTable.reloadTable()
}
Page, ListTable
}
}
</script>

View File

@@ -15,9 +15,6 @@ export default {
created() {
},
methods: {
reloadTable() {
this.$refs.ListTable.reloadTable()
}
}
}
</script>

View File

@@ -50,9 +50,6 @@ export default {
},
selectNode: function(node) {
return this.$refs.TreeTable.selectNode(node)
},
reloadTable() {
this.$refs.TreeTable.reloadTable()
}
}
}

View File

@@ -81,7 +81,7 @@ export default {
},
{
label: this.$t('common.Version'),
value: 'v3.9.3'
value: 'version-dev'
},
{
label: this.$t('common.PermissionCompany'),

View File

@@ -43,7 +43,7 @@
import Page from '../Page/'
import merge from 'webpack-merge'
const ACTIVE_TAB_KEY = 'activeTab'
const ACTIVE_TAB_KEY = 'tab'
export default {
name: 'TabPage',
@@ -109,18 +109,21 @@ export default {
},
created() {
this.iActiveMenu = this.getPropActiveTab()
this.setToRoute()
},
methods: {
handleTabClick(tab) {
this.$emit('tab-click', tab)
this.$emit('update:activeMenu', tab.name)
this.$cookie.set(ACTIVE_TAB_KEY, tab.name, 1)
if (this.$router.currentRoute.query[ACTIVE_TAB_KEY]) {
this.setToRoute()
},
setToRoute() {
setTimeout(() => {
this.$router.push({
query: merge(this.$route.query, { [ACTIVE_TAB_KEY]: '' })
query: merge(this.$route.query, { [ACTIVE_TAB_KEY]: this.iActiveMenu })
})
}
})
},
getPropActiveTab() {
let activeTab = ''

View File

@@ -9,6 +9,7 @@ export { default as GenericListPage } from './GenericListPage'
export { default as GenericListTable } from './GenericListTable'
export { default as GenericDetailPage } from './GenericDetailPage'
export { default as GenericCreateUpdatePage } from './GenericCreateUpdatePage'
export { default as GenericCreateUpdateDrawer } from './GenericCreateUpdateDrawer'
export { default as GenericCreateUpdateForm } from './GenericCreateUpdateForm'
export { default as GenericUpdateFormDialog } from './GenericUpdateFormDialog'
export { default as GenericListTableDialog } from './GenericListTableDialog'

View File

@@ -22,6 +22,7 @@ import ECharts from 'vue-echarts'
import service from '@/utils/request'
import { message } from '@/utils/message'
import xss from '@/utils/xss'
import ElDrawerPatch from '@/utils/elDrawerPatch.js'
import ElTableTooltipPatch from '@/utils/elTableTooltipPatch.js'
/**
@@ -42,6 +43,7 @@ Vue.use(ElementUI, { locale })
// 如果想要中文版 element-ui按如下方式声明
// Vue.use(ElementUI)
Vue.use(ElDrawerPatch)
Vue.use(ElTableTooltipPatch)
Vue.config.productionTip = false

View File

@@ -130,14 +130,14 @@ export default [
{
path: 'create',
name: 'CloudCreate',
component: () => import('@/views/assets/Asset/AssetCreateUpdate/CloudsPlatformCreateUpdate.vue'),
component: () => import('@/views/assets/Asset/AssetCreateUpdate/CloudCreateUpdate.vue'),
hidden: true,
meta: { title: i18n.t('route.CloudCreate'), activeMenu: '/console/assets/assets' }
},
{
path: ':id/update',
name: 'CloudUpdate',
component: () => import('@/views/assets/Asset/AssetCreateUpdate/CloudsPlatformCreateUpdate.vue'),
component: () => import('@/views/assets/Asset/AssetCreateUpdate/CloudCreateUpdate.vue'),
hidden: true,
meta: { title: i18n.t('route.CloudUpdate'), activeMenu: '/console/assets/assets' }
}

View File

@@ -24,13 +24,6 @@ export default [
hidden: true,
meta: { title: i18n.t('route.AssetPermissionCreate'), action: 'create' }
},
{
path: ':id/update',
component: () => import('@/views/perms/AssetPermission/AssetPermissionCreateUpdate.vue'),
name: 'AssetPermissionUpdate',
hidden: true,
meta: { title: i18n.t('route.AssetPermissionUpdate'), action: 'update' }
},
{
path: ':id',
component: () => import('@/views/perms/AssetPermission/AssetPermissionDetail'),

View File

@@ -64,22 +64,6 @@ export default [
name: 'UserGroupList',
meta: { title: i18n.t('route.UserGroupList'), permissions: ['users.view_usergroup'] }
},
{
path: 'create',
component: () => import('@/views/users/Group/UserGroupCreateUpdate.vue'), // Parent router-view
name: 'UserGroupCreate',
hidden: true,
meta: {
title: i18n.t('route.UserGroupCreate')
}
},
{
path: ':id/update',
component: () => import('@/views/users/Group/UserGroupCreateUpdate.vue'), // Parent router-view
name: 'UserGroupUpdate',
hidden: true,
meta: { title: i18n.t('route.UserGroupUpdate') }
},
{
path: ':id',
component: () => import('@/views/users/Group/UserGroupDetail'), // Parent router-view

View File

@@ -297,17 +297,6 @@ export default {
activeMenu: '/settings/applets'
}
},
{
path: 'hosts/create',
name: 'AppletHostCreate',
component: () => import('@/views/settings/Applet/AppletHost/AppletHostCreateUpdate'),
hidden: true,
meta: {
title: i18n.t('route.AppletHostCreate'),
permissions: ['terminal.add_applethost'],
activeMenu: '/settings/applets'
}
},
{
path: 'hosts/:id',
name: 'AppletHostDetail',

View File

@@ -51,17 +51,6 @@ export default {
showOrganization: false
},
children: [
{
path: 'request-host-perm/create',
name: 'RequestAssetPermTicketCreateUpdate',
component: () => import('@/views/tickets/RequestAssetPerm/CreateUpdate'),
meta: {
title: i18n.t('tickets.OpenTicket'),
permissions: ['tickets.view_ticket'],
activeMenu: '/tickets/my-tickets'
},
hidden: true
},
{
path: 'request-host-perm/:id',
name: 'AssetsTicketDetail',

View File

@@ -195,17 +195,6 @@ export default {
activeMenu: '/workbench/ops/templates'
}
},
{
path: 'adhoc/create',
name: 'AdhocCreate',
hidden: true,
component: () => import('@/views/ops/Template/Adhoc/AdhocUpdateCreate'),
meta: {
title: i18n.t('ops.createAdhoc'),
permissions: ['ops.add_adhoc'],
activeMenu: '/workbench/ops/templates'
}
},
{
path: 'adhoc/:id',
component: () => import('@/views/ops/Template/Adhoc/AdhocDetail'),
@@ -217,17 +206,6 @@ export default {
activeMenu: '/workbench/ops/templates'
}
},
{
path: 'playbook/create',
name: 'PlaybookCreate',
hidden: true,
component: () => import('@/views/ops/Template/Playbook/PlaybookCreateUpdate'),
meta: {
title: i18n.t('ops.CreatePlaybook'),
permissions: ['ops.add_playbook'],
activeMenu: '/workbench/ops/templates'
}
},
{
path: 'playbook/:id/update',
name: 'PlaybookUpdate',

View File

@@ -30,6 +30,7 @@ const getters = {
currentUserIsAdmin: state => state.users.isAdmin,
hasValidLicense: state => state.settings.hasValidLicense,
isSystemAdmin: state => state.users.profile.system_roles.some(i => (i?.id === '00000000-0000-0000-0000-000000000001')),
sqlQueryCounter: state => state.common.sqlQueryCounter
sqlQueryCounter: state => state.common.sqlQueryCounter,
currentCreateArgs: state => state.common.createArgs
}
export default getters

View File

@@ -6,7 +6,7 @@ const getDefaultState = () => {
metaPromiseMap: {},
isRouterAlive: true,
sqlQueryCounter: [],
confirmDialogVisible: false
createArgs: {}
}
}
@@ -29,8 +29,8 @@ const mutations = {
state.sqlQueryCounter.shift()
}
},
setConfirmDialogVisible: (state, show) => {
state.confirmDialogVisible = show
SET_CREATE_ARGS: (state, args) => {
state.createArgs = args
}
}
@@ -79,8 +79,8 @@ const actions = {
}
commit('addSQLQueryCounter', { url, count: sqlCount })
},
showConfirmDialog({ commit, state }, show) {
commit('setConfirmDialogVisible', show)
setCreateArgs({ commit, state }, args) {
commit('SET_CREATE_ARGS', args)
}
}

View File

@@ -1,5 +1,5 @@
@import './mixin.scss';
//@import './transition.scss';
@import './transition.scss';
@import './sidebar.scss';
@import './menu.scss';
@import './fonts/font-awesome.min.css';

View File

@@ -0,0 +1,28 @@
import { Drawer } from 'element-ui'
const ElDrawer = {
extends: Drawer,
data() {
return {
wrapperMouseDowned: false
}
},
mounted() {
this.$el.onmousedown = (e) => {
this.wrapperMouseDowned = e.target.classList.contains('el-drawer__container')
}
},
methods: {
handleWrapperClick() {
if (this.wrapperClosable && this.wrapperMouseDowned) {
this.closeDrawer()
}
}
}
}
export default {
install(Vue) {
Vue.component(Drawer.name, ElDrawer)
}
}

View File

@@ -2,12 +2,10 @@
import store from '@/store'
import router, { resetRouter } from '@/router'
import Vue from 'vue'
import VueCookie from 'vue-cookie'
import { message } from '@/utils/message'
import orgUtil from '@/utils/org'
import orgs from '@/api/orgs'
import { getPropView, isViewHasOrgs } from '@/utils/jms'
import request from '@/utils/request'
const whiteList = ['/login', process.env.VUE_APP_LOGIN_PATH] // no redirect whitelist
@@ -20,24 +18,24 @@ async function checkLogin({ to, from, next }) {
next()
}
// Determine whether the user has logged in
const sessionExpire = VueCookie.get('jms_session_expire')
if (!sessionExpire) {
request.get(process.env['VUE_APP_LOGOUT_PATH']).finally(() => {
window.location = process.env.VUE_APP_LOGIN_PATH
})
return reject('No session mark found in cookie')
} else if (sessionExpire === 'close') {
let startTime = new Date().getTime()
setInterval(() => {
const endTime = new Date().getTime()
const delta = (endTime - startTime)
startTime = endTime
Vue.$log.debug('Set session expire: ', delta)
VueCookie.set('jms_session_expire', 'close', { expires: '2m' })
}, 10 * 1000)
} else if (sessionExpire === 'age') {
Vue.$log.debug('Session expire on age')
}
// const sessionExpire = VueCookie.get('jms_session_expire')
// if (!sessionExpire) {
// request.get(process.env['VUE_APP_LOGOUT_PATH']).finally(() => {
// window.location = process.env.VUE_APP_LOGIN_PATH
// })
// return reject('No session mark found in cookie')
// } else if (sessionExpire === 'close') {
// let startTime = new Date().getTime()
// setInterval(() => {
// const endTime = new Date().getTime()
// const delta = (endTime - startTime)
// startTime = endTime
// Vue.$log.debug('Set session expire: ', delta)
// VueCookie.set('jms_session_expire', 'close', { expires: '2m' })
// }, 10 * 1000)
// } else if (sessionExpire === 'age') {
// Vue.$log.debug('Session expire on age')
// }
try {
return await store.dispatch('users/getProfile')
} catch (e) {

View File

@@ -1,16 +1,16 @@
<template>
<GenericCreateUpdatePage v-bind="$data" />
<GenericCreateUpdateDrawer v-bind="$data" />
</template>
<script>
import { GenericCreateUpdatePage } from '@/layout/components'
import { GenericCreateUpdateDrawer } from '@/layout/components'
import getChangeSecretFields from '@/views/accounts/AccountBackup/fields'
import { encryptPassword } from '@/utils/crypto'
export default {
name: 'AccountBackupPlanUpdate',
components: {
GenericCreateUpdatePage
GenericCreateUpdateDrawer
},
data() {
const vm = this

View File

@@ -79,20 +79,6 @@ export default {
formatter: (item, val) => {
return <span>{val.map(item => item.name).join(', ')}</span>
}
},
{
key: this.$t('accounts.AccountBackup.RecipientServer') + ' A',
value: this.object.obj_recipients_part_one,
formatter: (item, val) => {
return <span>{val.map(item => item.name).join(', ')}</span>
}
},
{
key: this.$t('accounts.AccountBackup.RecipientServer') + ' B',
value: this.object.obj_recipients_part_two,
formatter: (item, val) => {
return <span>{val.map(item => item.name).join(', ')}</span>
}
}
]
}

View File

@@ -1,16 +1,21 @@
<template>
<GenericListTable :header-actions="headerActions" :table-config="tableConfig" />
<div>
<GenericListTable :header-actions="headerActions" :table-config="tableConfig" />
<AccountBackupCreateUpdate />
</div>
</template>
<script>
import { GenericListTable } from '@/layout/components'
import AccountBackupCreateUpdate from './AccountBackupCreateUpdate.vue'
import { ArrayFormatter, DetailFormatter } from '@/components/Table/TableFormatters'
import { openTaskPage } from '@/utils/jms'
export default {
name: 'AccountBackupPlanList',
components: {
GenericListTable
GenericListTable,
AccountBackupCreateUpdate
},
data() {
const vm = this
@@ -64,7 +69,7 @@ export default {
return {
name: 'AccountBackupList',
query: {
activeTab: 'AccountBackupPlanExecutionList',
tab: 'AccountBackupPlanExecutionList',
plan_id: row.id
}
}
@@ -74,12 +79,8 @@ export default {
actions: {
width: '164px',
formatterArgs: {
onClone: ({ row }) => {
vm.$router.push({ name: 'AccountBackupPlanCreate', query: { clone_from: row.id }})
},
onUpdate: ({ row }) => {
vm.$router.push({ name: 'AccountBackupPlanUpdate', params: { id: row.id }})
},
hasClone: true,
hasUpdate: true,
extraActions: [
{
title: vm.$t('xpack.Execute'),

View File

@@ -1,16 +1,16 @@
<template>
<GenericCreateUpdatePage v-bind="$data" />
<GenericCreateUpdateDrawer v-bind="$data" />
</template>
<script>
import { GenericCreateUpdatePage } from '@/layout/components'
import { GenericCreateUpdateDrawer } from '@/layout/components'
import { getChangeSecretFields } from '@/views/accounts/AccountChangeSecret/fields'
import { AssetSelect, AutomationParams } from '@/components'
export default {
name: 'AccountChangeSecretCreateUpdate',
components: {
GenericCreateUpdatePage
GenericCreateUpdateDrawer
},
data() {
return {

View File

@@ -1,16 +1,21 @@
<template>
<GenericListTable :header-actions="headerActions" :table-config="tableConfig" />
<div>
<GenericListTable :header-actions="headerActions" :table-config="tableConfig" />
<AccountChangeSecretCreateUpdate />
</div>
</template>
<script>
import { GenericListTable } from '@/layout/components'
import AccountChangeSecretCreateUpdate from './AccountChangeSecretCreateUpdate.vue'
import { DetailFormatter } from '@/components/Table/TableFormatters'
import { openTaskPage } from '@/utils/jms'
export default {
name: 'AccountChangeSecretList',
components: {
GenericListTable
GenericListTable,
AccountChangeSecretCreateUpdate
},
data() {
const vm = this
@@ -69,7 +74,7 @@ export default {
return {
name: 'AccountChangeSecretList',
query: {
activeTab: 'AccountChangeSecretExecutionList',
tab: 'AccountChangeSecretExecutionList',
automation_id: row.id
}
}
@@ -82,12 +87,6 @@ export default {
actions: {
width: '164px',
formatterArgs: {
onClone: ({ row }) => {
vm.$router.push({ name: 'AccountChangeSecretCreate', query: { clone_from: row.id }})
},
onUpdate: ({ row }) => {
vm.$router.push({ name: 'AccountChangeSecretUpdate', params: { id: row.id }})
},
extraActions: [
{
title: vm.$t('xpack.Execute'),

View File

@@ -1,16 +1,21 @@
<template>
<GenericListTable :header-actions="headerActions" :table-config="tableConfig" />
<div>
<GenericListTable :header-actions="headerActions" :table-config="tableConfig" />
<TaskCreateUpdate />
</div>
</template>
<script>
import { GenericListTable } from '@/layout/components'
import { DetailFormatter } from '@/components/Table/TableFormatters'
import TaskCreateUpdate from './TaskCreateUpdate.vue'
import { openTaskPage } from '@/utils/jms'
export default {
name: 'AccountGatherTaskList',
components: {
GenericListTable
GenericListTable,
TaskCreateUpdate
},
data() {
const vm = this
@@ -33,7 +38,7 @@ export default {
formatterArgs: {
route: 'AccountGatherTaskDetail',
routeQuery: {
activeTab: 'Detail'
tab: 'Detail'
}
}
},
@@ -62,7 +67,7 @@ export default {
return {
name: 'AccountGatherList',
query: {
activeTab: 'AccountGatherTaskExecutionList',
tab: 'AccountGatherTaskExecutionList',
automation_id: row.id
}
}

View File

@@ -1,15 +1,15 @@
<template>
<GenericCreateUpdatePage v-bind="$data" />
<GenericCreateUpdateDrawer v-bind="$data" />
</template>
<script>
import { GenericCreateUpdatePage } from '@/layout/components'
import { GenericCreateUpdateDrawer } from '@/layout/components'
import { CronTab } from '@/components'
import i18n from '@/i18n/i18n'
export default {
components: {
GenericCreateUpdatePage
GenericCreateUpdateDrawer
},
data() {
return {

View File

@@ -1,17 +1,17 @@
<template>
<GenericCreateUpdatePage v-bind="$data" />
<GenericCreateUpdateDrawer v-bind="$data" />
</template>
<script>
import i18n from '@/i18n/i18n'
import { GenericCreateUpdatePage } from '@/layout/components'
import { GenericCreateUpdateDrawer } from '@/layout/components'
import { getChangeSecretFields } from '@/views/accounts/AccountChangeSecret/fields'
import { AssetSelect, AutomationParams } from '@/components'
export default {
name: 'AccountPushCreateUpdate',
components: {
GenericCreateUpdatePage
GenericCreateUpdateDrawer
},
data() {
return {

View File

@@ -1,16 +1,21 @@
<template>
<GenericListTable :header-actions="headerActions" :table-config="tableConfig" />
<div>
<GenericListTable :header-actions="headerActions" :table-config="tableConfig" />
<AccountPushCreateUpdate />
</div>
</template>
<script>
import { DetailFormatter } from '@/components/Table/TableFormatters'
import { openTaskPage } from '@/utils/jms'
import { GenericListTable } from '@/layout/components'
import AccountPushCreateUpdate from './AccountPushCreateUpdate.vue'
export default {
name: 'AccountPushList',
components: {
GenericListTable
GenericListTable,
AccountPushCreateUpdate
},
data() {
const vm = this
@@ -80,7 +85,7 @@ export default {
return {
name: 'AccountPushList',
query: {
activeTab: 'AccountPushExecutionList',
tab: 'AccountPushExecutionList',
automation_id: row.id
}
}

View File

@@ -1,16 +1,16 @@
<template>
<GenericCreateUpdatePage v-bind="$data" />
<GenericCreateUpdateDrawer v-bind="$data" />
</template>
<script>
import GenericCreateUpdatePage from '@/layout/components/GenericCreateUpdatePage'
import GenericCreateUpdateDrawer from '@/layout/components/GenericCreateUpdateDrawer'
import { templateFields, templateFieldsMeta } from './const.js'
import { encryptPassword } from '@/utils/crypto'
export default {
name: 'GatewayCreateUpdate',
components: {
GenericCreateUpdatePage
GenericCreateUpdateDrawer
},
data() {
const vm = this

View File

@@ -8,11 +8,13 @@
:url="secretUrl"
:visible.sync="showViewSecretDialog"
/>
<AccountTemplateCreateUpdate />
</div>
</template>
<script>
import { GenericListPage } from '@/layout/components'
import AccountTemplateCreateUpdate from './AccountTemplateCreateUpdate.vue'
import { ActionsFormatter } from '@/components/Table/TableFormatters'
import ViewSecret from '@/components/Apps/AccountListTable/ViewSecret'
@@ -20,6 +22,7 @@ export default {
name: 'AccountTemplateList',
components: {
GenericListPage,
AccountTemplateCreateUpdate,
ViewSecret
},
data() {
@@ -86,11 +89,7 @@ export default {
hasExport: false,
hasImport: false,
hasMoreActions: false,
createRoute: () => {
return {
name: 'AccountTemplateCreate'
}
}
createRoute: 'AccountTemplateCreate'
}
}
}

View File

@@ -1,14 +1,19 @@
<template>
<ListTable v-bind="config" />
<div>
<ListTable v-bind="config" />
<VirtualUpdate />
</div>
</template>
<script>
import { ListTable } from '@/components'
import VirtualUpdate from './VirtualUpdate.vue'
export default {
name: 'VirtualAccountList',
components: {
ListTable
ListTable,
VirtualUpdate
},
data() {
return {

View File

@@ -1,14 +1,14 @@
<template>
<GenericCreateUpdatePage v-bind="config" @getObjectDone="handleObjectDone" />
<GenericCreateUpdateDrawer v-bind="config" @getObjectDone="handleObjectDone" />
</template>
<script>
import GenericCreateUpdatePage from '@/layout/components/GenericCreateUpdatePage/index.vue'
import GenericCreateUpdateDrawer from '@/layout/components/GenericCreateUpdateDrawer/index.vue'
import TextReadonly from '@/components/Form/FormFields/TextReadonly.vue'
export default {
name: 'CreateUpdate',
components: { GenericCreateUpdatePage },
components: { GenericCreateUpdateDrawer },
data() {
return {
object: {},

View File

@@ -1,19 +1,19 @@
<template>
<GenericCreateUpdatePage v-bind="$data" />
<GenericCreateUpdateDrawer v-bind="$data" />
</template>
<script>
import GenericCreateUpdatePage from '@/layout/components/GenericCreateUpdatePage'
import rules from '@/components/Form/DataForm/rules'
import { userJSONSelectMeta } from '@/views/users/const'
import { assetJSONSelectMeta } from '@/views/assets/const'
import AccountFormatter from '@/views/perms/AssetPermission/components/AccountFormatter.vue'
import { WeekCronSelect } from '@/components/Form/FormFields'
import GenericCreateUpdateDrawer from '@/layout/components/GenericCreateUpdateDrawer'
export default {
name: 'AclCreateUpdate',
components: {
GenericCreateUpdatePage
GenericCreateUpdateDrawer
},
data() {
return {

View File

@@ -1,13 +1,18 @@
<template>
<GenericListPage :header-actions="headerActions" :help-message="helpMsg" :table-config="tableConfig" />
<div>
<GenericListPage :header-actions="headerActions" :help-message="helpMsg" :table-config="tableConfig" />
<AssetLoginAclCreateUpdate />
</div>
</template>
<script>
import { GenericListPage } from '@/layout/components'
import AssetLoginAclCreateUpdate from './AssetLoginAclCreateUpdate.vue'
export default {
components: {
GenericListPage
GenericListPage,
AssetLoginAclCreateUpdate
},
data() {
return {

View File

@@ -1,5 +1,5 @@
<template>
<GenericCreateUpdatePage
<GenericCreateUpdateDrawer
:fields="fields"
:fields-meta="fieldsMeta"
:initial="initial"
@@ -9,7 +9,7 @@
</template>
<script>
import { GenericCreateUpdatePage } from '@/layout/components'
import GenericCreateUpdateDrawer from '@/layout/components/GenericCreateUpdateDrawer/index.vue'
import AccountFormatter from '@/views/perms/AssetPermission/components/AccountFormatter.vue'
import rules from '@/components/Form/DataForm/rules'
import { userJSONSelectMeta } from '@/views/users/const'
@@ -18,7 +18,7 @@ import { assetJSONSelectMeta } from '@/views/assets/const'
export default {
name: 'CommandFilterAclCreateUpdate',
components: {
GenericCreateUpdatePage
GenericCreateUpdateDrawer
},
data() {
return {

View File

@@ -2,6 +2,7 @@
<div>
<el-alert type="success">{{ helpMsg }}</el-alert>
<ListTable :header-actions="headerActions" :table-config="tableConfig" />
<CommandFilterAclCreateUpdate />
</div>
</template>
@@ -10,10 +11,12 @@
import { ListTable } from '@/components'
import { DetailFormatter } from '@/components/Table/TableFormatters'
import AmountFormatter from '@/components/Table/TableFormatters/AmountFormatter.vue'
import CommandFilterAclCreateUpdate from './CommandFilterAclCreateUpdate.vue'
export default {
components: {
ListTable
ListTable,
CommandFilterAclCreateUpdate
},
data() {
return {
@@ -44,15 +47,8 @@ export default {
width: '160px',
formatter: AmountFormatter,
formatterArgs: {
route: 'AccountGatherList',
getRoute({ row }) {
return {
name: 'CommandFilterAclList',
query: {
activeTab: 'CommandGroup',
command_filters: row.id
}
}
routeQuery: {
tab: 'GroupUser'
}
}
}

View File

@@ -1,5 +1,5 @@
<template>
<GenericCreateUpdatePage
<GenericCreateUpdateDrawer
:fields="fields"
:initial="initial"
:fields-meta="fieldsMeta"
@@ -10,11 +10,11 @@
</template>
<script>
import GenericCreateUpdatePage from '@/layout/components/GenericCreateUpdatePage'
import GenericCreateUpdateDrawer from '@/layout/components/GenericCreateUpdateDrawer/index.vue'
export default {
name: 'CommandGroupCreateUpdate',
components: { GenericCreateUpdatePage },
components: { GenericCreateUpdateDrawer },
data() {
const regexPlaceholder = 'rm.*|reboot|shutdown'
const commandPlaceholder = 'rm\rreboot'

View File

@@ -1,14 +1,19 @@
<template>
<ListTable :header-actions="headerActions" :table-config="tableConfig" />
<div>
<ListTable :header-actions="headerActions" :table-config="tableConfig" />
<CommandGroupCreateUpdate />
</div>
</template>
<script>
import { ListTable } from '@/components'
import { DetailFormatter } from '@/components/Table/TableFormatters'
import CommandGroupCreateUpdate from './CommandGroupCreateUpdate.vue'
export default {
components: {
ListTable
ListTable,
CommandGroupCreateUpdate
},
data() {
const _id = this.$route.query.command_filters

View File

@@ -42,7 +42,7 @@ export default {
const query = _.cloneDeep(this.$route.query)
const newQuery = {
...query,
activeTab: tab.name
tab: tab.name
}
this.$nextTick(() => {
this.$router.replace({ query: newQuery })

View File

@@ -1,9 +1,9 @@
<template>
<GenericCreateUpdatePage v-bind="$data" />
<GenericCreateUpdateDrawer v-bind="$data" />
</template>
<script>
import GenericCreateUpdatePage from '@/layout/components/GenericCreateUpdatePage'
import GenericCreateUpdateDrawer from '@/layout/components/GenericCreateUpdateDrawer'
import rules from '@/components/Form/DataForm/rules'
import { userJSONSelectMeta } from '@/views/users/const'
import { assetJSONSelectMeta } from '@/views/assets/const'
@@ -12,7 +12,7 @@ import { Select2 } from '@/components/Form/FormFields'
export default {
name: 'AclCreateUpdate',
components: {
GenericCreateUpdatePage
GenericCreateUpdateDrawer
},
data() {
return {

View File

@@ -1,13 +1,19 @@
<template>
<GenericListPage :header-actions="headerActions" :help-message="helpText" :table-config="tableConfig" />
<div>
<GenericListPage :header-actions="headerActions" :help-message="helpText" :table-config="tableConfig" />
<ConnectMethodAclCreateUpdate />
</div>
</template>
<script>
import GenericListPage from '@/layout/components/GenericListPage/index.vue'
import ConnectMethodAclCreateUpdate from './ConnectMethodAclCreateUpdate.vue'
export default {
name: 'ConnectMethodListAcl',
components: { GenericListPage },
components: {
GenericListPage,
ConnectMethodAclCreateUpdate
},
data() {
return {
helpText: this.$t('acl.ConnectMethodACLHelpMsg'),

View File

@@ -1,9 +1,9 @@
<template>
<GenericCreateUpdatePage v-bind="$data" />
<GenericCreateUpdateDrawer v-bind="$data" />
</template>
<script>
import GenericCreateUpdatePage from '@/layout/components/GenericCreateUpdatePage'
import GenericCreateUpdateDrawer from '@/layout/components/GenericCreateUpdateDrawer'
import { WeekCronSelect } from '@/components/Form/FormFields'
import { Required } from '@/components/Form/DataForm/rules'
import { userJSONSelectMeta } from '@/views/users/const'
@@ -11,7 +11,7 @@ import { userJSONSelectMeta } from '@/views/users/const'
export default {
name: 'AclCreateUpdate',
components: {
GenericCreateUpdatePage
GenericCreateUpdateDrawer
},
data() {
return {
@@ -70,18 +70,6 @@ export default {
}
}
},
getUrl() {
const query = this.$route.query
const params = this.$route.params
let url = `/api/v1/acls/login-acls/`
if (params.id) {
url = `${url}${params.id}/`
}
if (query.user) {
url = `${url}?user=${query.user}`
}
return url
},
cleanFormValue(value) {
if (!Array.isArray(value.rules.ip_group)) {
value.rules.ip_group = value.rules.ip_group ? value.rules.ip_group.split(',') : []

View File

@@ -1,13 +1,18 @@
<template>
<ListTable :header-actions="headerActions" :table-config="tableConfig" />
<div>
<ListTable :header-actions="headerActions" :table-config="tableConfig" />
<UserLoginACLCreateUpdate />
</div>
</template>
<script>
import ListTable from '@/components/Table/ListTable/index.vue'
import UserLoginACLCreateUpdate from './UserLoginACLCreateUpdate.vue'
export default {
components: {
ListTable
ListTable,
UserLoginACLCreateUpdate
},
props: {
url: {

View File

@@ -1,15 +1,22 @@
<template>
<GenericCreateUpdatePage v-if="!loading" v-bind="iConfig" />
<GenericCreateUpdateDrawer
v-if="!loading"
:visible="visible"
:action="action"
:action-id="actionId"
v-bind="iConfig"
v-on="$listeners"
/>
</template>
<script>
import GenericCreateUpdatePage from '@/layout/components/GenericCreateUpdatePage'
import { assetFieldsMeta } from '@/views/assets/const'
import { encryptPassword } from '@/utils/crypto'
import { getUpdateObjURL, setUrlParam } from '@/utils/common'
import GenericCreateUpdateDrawer from '@/layout/components/GenericCreateUpdateDrawer/index.vue'
export default {
components: { GenericCreateUpdatePage },
components: { GenericCreateUpdateDrawer },
props: {
url: {
type: String,
@@ -28,10 +35,6 @@ export default {
type: [Array, Function],
default: () => []
},
createSuccessNextRoute: {
type: Object,
default: () => ({ name: 'AssetList' })
},
updateSuccessNextRoute: {
type: Object,
default: () => ({ name: 'AssetList' })
@@ -41,11 +44,28 @@ export default {
default: (initial) => {
return initial
}
},
platformId: {
type: Number,
default: 0
},
action: {
type: String,
default: 'create'
},
visible: {
type: Boolean,
default: false
},
row: {
type: Object,
default: () => ({})
}
},
data() {
return {
loading: true,
actionId: this.row?.id,
platform: {},
defaultConfig: {
initial: {},
@@ -62,16 +82,16 @@ export default {
[this.$t('common.Other'), ['domain', 'labels', 'is_active', 'comment']]
],
fieldsMeta: assetFieldsMeta(this),
performSubmit(validValues) {
performSubmit: (validValues) => {
console.log('This row: ', this.row, 'This action: ', this.action)
let url = this.url
const { id = '' } = this.$route.params
const values = _.cloneDeep(validValues)
const submitMethod = id ? 'put' : 'post'
const submitMethod = this.action === 'update' ? 'put' : 'post'
if (values.nodes && values.nodes.length === 0) {
delete values['nodes']
}
if (id) {
url = getUpdateObjURL(url, id)
if (this.action === 'update') {
url = getUpdateObjURL(url, this.row.id)
delete values['accounts']
} else {
const accounts = values?.accounts || []
@@ -89,10 +109,7 @@ export default {
iConfig() {
const { addFields, addFieldsMeta, defaultConfig } = this
let url = this.url
const { id = '' } = this.$route.params
if (this.$route.query.platform && !id) {
url = setUrlParam(url, 'platform', this.$route.query.platform)
}
url = setUrlParam(url, 'platform', this.platformId)
// null, undefined
defaultConfig.fields = defaultConfig.fields.filter(Boolean)
const config = _.merge(defaultConfig, { url })
@@ -105,6 +122,12 @@ export default {
}
}
const tp = this.platform.type?.value
const category = this.platform.category?.value
if (tp && category) {
defaultConfig.fieldsMeta.platform.el.ajax.url = `/api/v1/assets/platforms/?category=${category}&type=${tp}`
}
for (const [name, meta] of Object.entries(addFieldsMeta)) {
if (config.fieldsMeta[name]) {
config.fieldsMeta[name] = Object.assign(config.fieldsMeta[name], meta)
@@ -129,16 +152,16 @@ export default {
},
async setInitial() {
const { defaultConfig } = this
const { node, platform } = this.$route?.query || {}
const { node } = this.$route?.query || {}
const nodesInitial = node ? [node] : []
const platformId = platform || 1
const platformId = this.platformId
const url = `/api/v1/assets/platforms/${platformId}/`
this.platform = await this.$axios.get(url)
const initial = {
labels: [],
is_active: true,
nodes: nodesInitial,
platform: parseInt(platformId),
platform: platformId,
protocols: []
}
if (this.updateInitial) {

View File

@@ -1,9 +1,9 @@
<template>
<BaseAssetCreateUpdate v-bind="$data" />
<BaseAssetCreateUpdate v-bind="Object.assign($data, $attrs)" v-on="$listeners" />
</template>
<script>
import BaseAssetCreateUpdate from './BaseAssetCreateUpdate'
import BaseAssetCreateUpdate from './BaseAssetCreateDrawer.vue'
export default {
name: 'CloudCreateUpdate',

View File

@@ -1,9 +1,9 @@
<template>
<BaseAssetCreateUpdate v-bind="$data" />
<BaseAssetCreateUpdate v-bind="Object.assign($data, $attrs)" v-on="$listeners" />
</template>
<script>
import BaseAssetCreateUpdate from './BaseAssetCreateUpdate'
import BaseAssetCreateUpdate from './BaseAssetCreateDrawer.vue'
export default {
name: 'WebCreateUpdate',

View File

@@ -1,9 +1,9 @@
<template>
<BaseAssetCreateUpdate v-bind="$data" />
<BaseAssetCreateUpdate v-bind="Object.assign($data, $attrs)" v-on="$listeners" />
</template>
<script>
import BaseAssetCreateUpdate from './BaseAssetCreateUpdate'
import BaseAssetCreateUpdate from './BaseAssetCreateDrawer.vue'
import { UploadKey } from '@/components'
import rules from '@/components/Form/DataForm/rules'
@@ -18,7 +18,7 @@ export default {
}
},
mounted() {
this.url = `${this.url}?platform=${this.$route.query.platform}`
console.log('Attrs: ', this.$attrs)
},
methods: {
getAddFields() {

View File

@@ -1,9 +1,9 @@
<template>
<BaseAssetCreateUpdate v-bind="$data" />
<BaseAssetCreateUpdate v-bind="Object.assign($data, $attrs)" v-on="$listeners" />
</template>
<script>
import BaseAssetCreateUpdate from './BaseAssetCreateUpdate'
import BaseAssetCreateUpdate from './BaseAssetCreateDrawer.vue'
export default {
name: 'DeviceCreateUpdate',

View File

@@ -1,9 +1,9 @@
<template>
<BaseAssetCreateUpdate v-bind="$data" />
<BaseAssetCreateUpdate v-bind="Object.assign($data, $attrs)" v-on="$listeners" />
</template>
<script>
import BaseAssetCreateUpdate from './BaseAssetCreateUpdate'
import BaseAssetCreateUpdate from './BaseAssetCreateDrawer.vue'
export default {
name: 'GPTCreateUpdate',

View File

@@ -1,9 +1,9 @@
<template>
<BaseAssetCreateUpdate v-bind="$data" />
<BaseAssetCreateUpdate v-bind="Object.assign($data, $attrs)" v-on="$listeners" />
</template>
<script>
import BaseAssetCreateUpdate from './BaseAssetCreateUpdate'
import BaseAssetCreateUpdate from './BaseAssetCreateDrawer.vue'
export default {
name: 'HostCreateUpdate',

View File

@@ -1,9 +1,9 @@
<template>
<BaseAssetCreateUpdate v-bind="$data" />
<BaseAssetCreateUpdate v-bind="Object.assign($data, $attrs)" />
</template>
<script>
import BaseAssetCreateUpdate from './BaseAssetCreateUpdate'
import BaseAssetCreateUpdate from './BaseAssetCreateDrawer.vue'
export default {
name: 'WebCreateUpdate',

View File

@@ -173,8 +173,7 @@ export default {
removeRowToSelect(row) {
const hasSelectValue = this.hasSelectValue(row)
if (hasSelectValue) {
const index = this.accountsSelected.findIndex(i => i?.id === row.id)
this.accountsSelected.splice(index, 1)
this.accountsSelected.splice(hasSelectValue, 1)
}
}
}

View File

@@ -137,7 +137,7 @@ export default {
name: 'AppletHostDetail',
params: { id: assetId },
query: {
activeTab: 'Accounts'
tab: 'Accounts'
}
})
return
@@ -146,7 +146,7 @@ export default {
name: 'AssetDetail',
params: { id: assetId },
query: {
activeTab: 'Account'
tab: 'Account'
}
})
}

View File

@@ -0,0 +1,73 @@
<template>
<div>
<component
:is="component"
:visible.sync="visible"
:action="action"
:platform-id="platform.id"
:row="row"
@close="onClose"
/>
</div>
</template>
<script>
import HostCreateUpdate from './HostCreateUpdate.vue'
import DatabaseCreateUpdate from './DatabaseCreateUpdate.vue'
import CloudCreateUpdate from './CloudCreateUpdate.vue'
import WebCreateUpdate from './WebCreateUpdate.vue'
import DeviceCreateUpdate from './DeviceCreateUpdate.vue'
import CustomCreateUpdate from './CustomCreateUpdate.vue'
export default {
name: 'WebCreateUpdate',
components: {
HostCreateUpdate,
DatabaseCreateUpdate,
CloudCreateUpdate,
WebCreateUpdate,
DeviceCreateUpdate,
CustomCreateUpdate
},
props: {
},
data() {
return {
visible: false,
category: '',
component: '',
platform: { id: 0 },
row: {},
action: '',
components: {
host: HostCreateUpdate,
database: DatabaseCreateUpdate,
cloud: CloudCreateUpdate,
web: WebCreateUpdate,
device: DeviceCreateUpdate,
custom: CustomCreateUpdate
}
}
},
mounted() {
this.$eventBus.$on('assetCreateUpdate', (platform, action, { url, row }) => {
this.platform = platform
this.category = platform.category.value
this.component = this.components[this.category]
this.row = row
this.action = action
this.visible = true
})
},
beforeDestroy() {
this.$eventBus.$off('assetCreateUpdate')
},
methods: {
onClose() {
console.log('On closed draw')
this.row = {}
this.component = ''
}
}
}
</script>

View File

@@ -5,6 +5,7 @@
<AccountListTable
ref="ListTable"
:asset="object"
:columns="columns"
:has-clone="false"
:has-import="false"
:has-left-actions="true"

View File

@@ -149,7 +149,7 @@ export default {
formatterArgs: {
route: 'AssetPermissionDetail',
routeQuery: {
activeTab: 'AssetPermissionUser'
tab: 'AssetPermissionUser'
}
}
},
@@ -160,7 +160,7 @@ export default {
formatterArgs: {
route: 'AssetPermissionDetail',
routeQuery: {
activeTab: 'AssetPermissionUser'
tab: 'AssetPermissionUser'
}
}
},
@@ -171,7 +171,7 @@ export default {
formatterArgs: {
route: 'AssetPermissionDetail',
routeQuery: {
activeTab: 'AssetPermissionAsset'
tab: 'AssetPermissionAsset'
}
}
}

View File

@@ -15,8 +15,7 @@ export default {
category: 'custom',
url: '/api/v1/assets/customs/',
tableConfig: {
columnsExclude: [
],
columnsExclude: [],
columnsMeta: {
autofill: {
width: '100px'

View File

@@ -1,5 +1,5 @@
<template>
<BaseList v-bind="config" />
<BaseList v-bind="Object.assign(config, $attrs)" />
</template>
<script>

View File

@@ -17,11 +17,13 @@
:port="GatewayPort"
:visible.sync="GatewayVisible"
/>
<AssetCreateUpdate />
</div>
</template>
<script>
import { ListTable } from '@/components'
import AssetCreateUpdate from '../../AssetCreateUpdate'
import {
ActionsFormatter, ArrayFormatter, ChoicesFormatter, DetailFormatter, ProtocolsFormatter, TagsFormatter
} from '@/components/Table/TableFormatters'
@@ -37,7 +39,8 @@ export default {
ListTable,
GatewayDialog,
PlatformDialog,
AssetBulkUpdateDialog
AssetBulkUpdateDialog,
AssetCreateUpdate
},
props: {
url: {
@@ -77,28 +80,13 @@ export default {
data() {
const vm = this
const onAction = (row, action) => {
let routeAction = action
if (action === 'Clone') {
routeAction = 'Create'
const platform = {
...row.platform,
type: row.type,
category: row.category
}
const routeName = _.capitalize(row.category.value) + routeAction
const route = {
name: routeName,
params: {},
query: {}
}
if (action === 'Clone') {
route.query.clone_from = row.id
} else if (action === 'Update') {
route.params.id = row.id
}
if (['Create', 'Update'].includes(routeAction)) {
route.query.platform = row.platform.id
route.query.type = row.type.value
route.query.category = row.type.category
}
const { href } = vm.$router.resolve(route)
window.open(href, '_blank')
console.log('ON action: ', action)
vm.$eventBus.$emit('assetCreateUpdate', platform, action.toLowerCase(), { url: this.url, row })
}
const extraQuery = this.$route.params?.extraQuery || {}
return {

View File

@@ -1,12 +1,13 @@
<template>
<Dialog
<el-drawer
v-if="iVisible"
:show-cancel="false"
:show-confirm="false"
:title="$tc('assets.SelectPlatforms')"
:visible.sync="iVisible"
top="1vh"
width="60%"
class="platform-dialog"
direction="rtl"
size="600px"
>
<div style="margin: 0 10px">
<el-row :gutter="20">
@@ -20,7 +21,7 @@
<el-col
v-for="(platform, index) of ps"
:key="platform.id"
:span="6"
:span="12"
>
<el-card
:style="{ borderLeftColor: randomBorderColor(index) }"
@@ -35,16 +36,13 @@
</el-collapse>
</el-row>
</div>
</Dialog>
</el-drawer>
</template>
<script>
import Dialog from '@/components/Dialog'
export default {
name: 'PlatformDialog',
components: {
Dialog
},
props: {
visible: {
@@ -77,6 +75,7 @@ export default {
computed: {
iVisible: {
set(val) {
console.log('Platform visible changed: ', val)
this.$emit('update:visible', val)
},
get() {
@@ -149,19 +148,12 @@ export default {
localStorage.setItem('RecentPlatforms', JSON.stringify(recentPlatformIds))
},
createAsset(platform) {
const route = _.capitalize(platform.category.value) + 'Create' || 'HostCreate'
this.addToRecentPlatforms(platform)
this.iVisible = false
const query = {
node: this.$route.query?.node || this.$route.query?.node_id || '',
platform: platform.id,
type: platform.type.value,
category: platform.category.value
}
const router = { name: route, query }
const { href } = this.$router.resolve(router)
window.open(href, '_blank')
setTimeout(() => {
this.iVisible = false
})
const url = `/api/v1/assets/${platform.category.value}s/`
this.$eventBus.$emit('assetCreateUpdate', platform, 'create', { url })
}
}
}
@@ -186,8 +178,17 @@ export default {
font-weight: 500;
color: #303133;
}
.platform-dialog {
>>> .el-drawer__header {
margin-bottom: 10px;
}
}
>>> .el-collapse {
border: none;
padding: 0 20px;
.el-collapse-item:last-child {
.el-collapse-item__header {
border: none;

View File

@@ -92,7 +92,7 @@ export default {
const query = _.cloneDeep(this.$route.query)
const newQuery = {
...query,
activeTab: tab.name
tab: tab.name
}
this.$nextTick(() => {
this.$router.replace({ query: newQuery })

View File

@@ -1,25 +1,26 @@
<template>
<GenericCreateUpdatePage
<GenericCreateUpdateDrawer
:initial="initial"
:resource="$tc('xpack.Cloud.Account')"
v-bind="$data"
/>
</template>
<script>
import { GenericCreateUpdatePage } from '@/layout/components'
import { RequiredChange, specialEmojiCheck } from '@/components/Form/DataForm/rules'
import { ACCOUNT_PROVIDER_ATTRS_MAP, aliyun } from '../const'
import { UploadKey } from '@/components'
import { encryptPassword } from '@/utils/crypto'
import GenericCreateUpdateDrawer from '@/layout/components/GenericCreateUpdateDrawer/index.vue'
export default {
components: {
GenericCreateUpdatePage
GenericCreateUpdateDrawer
},
data() {
const vm = this
const accountProvider = this.$route.query.provider || aliyun
const accountProviderAttrs = ACCOUNT_PROVIDER_ATTRS_MAP[accountProvider]
const accountProviderAttrs = ACCOUNT_PROVIDER_ATTRS_MAP[accountProvider] || {}
function setFieldAttrs() {
const fieldsObject = {}
@@ -127,12 +128,6 @@ export default {
values.attrs.ip_group = attrs.ip_group.filter(Boolean)
}
return values
},
afterGetFormValue(formValue) {
if (!formValue.attrs) {
return formValue
}
return formValue
}
}
},

View File

@@ -1,9 +1,13 @@
<template>
<GenericListTable :header-actions="headerActions" :table-config="tableConfig" />
<div>
<GenericListTable :header-actions="headerActions" :table-config="tableConfig" />
<AccountCreateUpdate />
</div>
</template>
<script type="text/jsx">
import GenericListTable from '@/layout/components/GenericListTable'
import AccountCreateUpdate from './AccountCreateUpdate.vue'
import {
ACCOUNT_PROVIDER_ATTRS_MAP, aliyun, aws_china, aws_international, azure, azure_international, baiducloud,
ctyun_private, fc, gcp, huaweicloud, huaweicloud_private, jdcloud, kingsoftcloud, lan, nutanix, openstack, qcloud,
@@ -13,13 +17,15 @@ import {
export default {
name: 'AccountList',
components: {
GenericListTable
GenericListTable,
AccountCreateUpdate
},
data() {
const vm = this
const url = '/api/v1/xpack/cloud/accounts/'
return {
tableConfig: {
url: '/api/v1/xpack/cloud/accounts/',
url: url,
permissions: {
app: 'xpack',
resource: 'account'
@@ -45,7 +51,13 @@ export default {
updateRoute: 'AccountUpdate',
hasClone: false,
onUpdate: ({ row, col }) => {
vm.$router.push({ name: 'AccountUpdate', params: { id: row.id }, query: { provider: row.provider?.value }})
vm.$router.push({
params: { id: row.id },
query: { provider: row.provider?.value }
})
setTimeout(() => {
vm.$eventBus.$emit('showCreateUpdateDrawer', 'update', { row, col })
})
},
extraActions: [
{
@@ -72,7 +84,10 @@ export default {
},
moreCreates: {
callback: (option) => {
vm.$router.push({ name: 'AccountCreate', query: { provider: option.name }})
vm.$router.push({ query: { provider: option.name }})
setTimeout(() => {
vm.$eventBus.$emit('showCreateUpdateDrawer', 'create', { url })
})
},
dropdown: [
{

View File

@@ -1,16 +1,16 @@
<template>
<GenericCreateUpdatePage v-bind="$data" />
<GenericCreateUpdateDrawer :resource="$tc('xpack.Cloud.SyncStrategy')" v-bind="$data" />
</template>
<script>
import { GenericCreateUpdatePage } from '@/layout/components'
import { RequiredChange, specialEmojiCheck } from '@/components/Form/DataForm/rules'
import RuleInput from './components/RuleInput'
import ActionInput from './components/ActionInput'
import GenericCreateUpdateDrawer from '@/layout/components/GenericCreateUpdateDrawer/index.vue'
export default {
components: {
GenericCreateUpdatePage
GenericCreateUpdateDrawer
},
data() {
return {

View File

@@ -1,15 +1,20 @@
<template>
<GenericListTable :header-actions="headerActions" :table-config="tableConfig" />
<div>
<GenericListTable :header-actions="headerActions" :table-config="tableConfig" />
<StrategyCreateUpdate />
</div>
</template>
<script type="text/jsx">
import GenericListTable from '@/layout/components/GenericListTable'
import { DetailFormatter } from '@/components/Table/TableFormatters'
import StrategyCreateUpdate from './StrategyCreateUpdate.vue'
export default {
name: 'StrategyList',
components: {
GenericListTable
GenericListTable,
StrategyCreateUpdate
},
data() {
return {

View File

@@ -1,16 +1,16 @@
<template>
<GenericCreateUpdatePage ref="createUpdatePage" v-bind="$data" />
<GenericCreateUpdateDrawer ref="createUpdatePage" v-bind="$data" />
</template>
<script>
import { GenericCreateUpdatePage } from '@/layout/components'
import { CronTab, Select2 } from '@/components'
import rules from '@/components/Form/DataForm/rules'
import SyncInstanceTaskStrategy from './components/SyncInstanceTaskStrategy/index'
import GenericCreateUpdateDrawer from '@/layout/components/GenericCreateUpdateDrawer/index.vue'
export default {
components: {
GenericCreateUpdatePage
GenericCreateUpdateDrawer
},
data() {
const vm = this

View File

@@ -56,6 +56,14 @@ export default {
)
}.bind(this)
}
},
{
title: this.$t('common.Strategy'),
attrs: {
type: 'primary',
label: this.$t('xpack.Execute'),
disabled: !this.$hasPerm('xpack.add_syncinstancetaskexecution')
}
}
],
strategyRelationConfig: {

View File

@@ -1,22 +1,28 @@
<template>
<GenericListTable :header-actions="headerActions" :table-config="tableConfig" />
<div>
<GenericListTable :header-actions="headerActions" :table-config="tableConfig" />
<SyncInstanceTaskCreateUpdate />
</div>
</template>
<script>
import GenericListTable from '@/layout/components/GenericListTable'
import { DetailFormatter } from '@/components/Table/TableFormatters'
import SyncInstanceTaskCreateUpdate from './SyncInstanceTaskCreateUpdate.vue'
import { openTaskPage } from '@/utils/jms'
export default {
name: 'SyncInstanceTaskList',
components: {
GenericListTable
GenericListTable,
SyncInstanceTaskCreateUpdate
},
data() {
const vm = this
const url = '/api/v1/xpack/cloud/sync-instance-tasks/'
return {
tableConfig: {
url: '/api/v1/xpack/cloud/sync-instance-tasks/',
url: url,
permissions: {
app: 'xpack',
resource: 'syncinstancetask'
@@ -81,7 +87,7 @@ export default {
permissions: 'xpack.view_syncinstancetaskexecution',
route: 'SyncInstanceTaskDetail',
routeQuery: {
activeTab: 'HistoryList'
tab: 'HistoryList'
}
}
},
@@ -91,7 +97,7 @@ export default {
permissions: 'xpack.view_syncinstancetask',
route: 'SyncInstanceTaskDetail',
routeQuery: {
activeTab: 'AssetList'
tab: 'AssetList'
}
}
}
@@ -103,8 +109,7 @@ export default {
headerActions: {
hasMoreActions: false,
hasImport: false,
hasExport: false,
createRoute: 'SyncInstanceTaskCreate'
hasExport: false
}
}
}

View File

@@ -1,21 +1,29 @@
<template>
<GenericCreateUpdatePage :fields="fields" :fields-meta="fieldsMeta" :initial="initial" :url="url" />
<GenericCreateUpdateDrawer
:fields="fields"
:fields-meta="fieldsMeta"
:initial="initial"
:url="url"
v-bind="$attrs"
v-on="$listeners"
/>
</template>
<script>
import GenericCreateUpdatePage from '@/layout/components/GenericCreateUpdatePage'
import GenericCreateUpdateDrawer from '@/layout/components/GenericCreateUpdateDrawer'
import AssetSelect from '@/components/Apps/AssetSelect'
export default {
name: 'GatewayCreateUpdate',
components: {
GenericCreateUpdatePage
GenericCreateUpdateDrawer
},
data() {
return {
initial: {},
fields: [
[this.$t('common.Basic'), ['name', 'assets', 'comment']]
[this.$t('common.Basic'), ['name', 'assets']],
[this.$t('common.Other'), ['comment']]
],
fieldsMeta: {
assets: {

View File

@@ -3,22 +3,32 @@
</template>
<script>
import BaseAssetCreateUpdate from '@/views/assets/Asset/AssetCreateUpdate/BaseAssetCreateUpdate'
import BaseAssetCreateUpdate from '@/views/assets/Asset/AssetCreateUpdate/BaseAssetCreateDrawer.vue'
export default {
name: 'GatewayCreateUpdate',
components: {
BaseAssetCreateUpdate
},
props: {
domain: {
type: String,
default: ''
},
platformType: {
type: String,
default: ''
}
},
data() {
const platformType = this.$route.query.platform_type
const platformType = this.platformType
return {
url: '/api/v1/assets/gateways/',
updateInitial: async(initial) => {
const url = `/api/v1/assets/platforms/?name=Gateway`
const platform = await this.$axios.get(url)
initial.platform = parseInt(platform[0].id)
initial.domain = this.$route.query.domain
initial.domain = this.domain
return initial
},
addFieldsMeta: {
@@ -37,24 +47,6 @@ export default {
}
}
}
},
createSuccessNextRoute: {
name: 'DomainDetail',
params: {
id: this.$route.query.domain
},
query: {
activeTab: 'GatewayList'
}
},
updateSuccessNextRoute: {
name: 'DomainDetail',
params: {
id: this.$route.query.domain
},
query: {
activeTab: 'GatewayList'
}
}
}
},

View File

@@ -10,6 +10,7 @@
:port="port"
:visible.sync="visible"
/>
<GatewayCreateUpdate :domain="domain" :platform-type="platformType" />
</el-col>
</div>
</template>
@@ -17,12 +18,14 @@
<script>
import GenericListTable from '@/layout/components/GenericListTable/index'
import GatewayDialog from '@/components/Apps/GatewayDialog'
import GatewayCreateUpdate from './GatewayCreateUpdate.vue'
import { connectivityMeta } from '@/components/Apps/AccountListTable/const'
import { ArrayFormatter, ChoicesFormatter, DetailFormatter, TagsFormatter } from '@/components/Table/TableFormatters'
export default {
components: {
GenericListTable,
GatewayCreateUpdate,
GatewayDialog
},
props: {
@@ -34,6 +37,8 @@ export default {
},
data() {
return {
domain: '',
platformType: '',
tableConfig: {
url: `/api/v1/assets/gateways/?domain=${this.$route.params.id}`,
columnsExclude: [
@@ -89,7 +94,10 @@ export default {
connectivity: connectivityMeta,
actions: {
formatterArgs: {
updateRoute: { name: 'GatewayUpdate', query: { domain: this.object.id, platform_type: 'linux', 'category': 'host' }},
updateRoute: ({ row }) => {
this.domain = this.object.id
this.platformType = 'linux'
},
performDelete: ({ row }) => {
const id = row.id
const url = `/api/v1/assets/gateways/${id}/`
@@ -130,13 +138,11 @@ export default {
headerActions: {
hasBulkUpdate: false,
hasSearch: true,
createRoute: {
name: 'GatewayCreate',
query: {
domain: this.object.id,
platform_type: 'linux',
category: 'host'
}
onCreate: (item) => {
this.domain = this.object.id
this.platformType = 'linux'
this.category = 'host'
this.$eventBus.$emit('showCreateUpdateDrawer', 'create', { url: this.tableConfig.url })
}
},
port: 0,

View File

@@ -1,18 +1,24 @@
<template>
<GenericListPage :header-actions="headerActions" :help-message="notice" :table-config="tableConfig" />
<div>
<GenericListPage :header-actions="headerActions" :help-message="notice" :table-config="tableConfig" />
<DomainCreateUpdate />
</div>
</template>
<script>
import { GenericListPage } from '@/layout/components'
import { DetailFormatter } from '@/components/Table/TableFormatters'
import DomainCreateUpdate from './DomainCreateUpdate.vue'
import AmountFormatter from '@/components/Table/TableFormatters/AmountFormatter.vue'
export default {
components: {
GenericListPage
GenericListPage,
DomainCreateUpdate
},
data() {
return {
showCreateUpdate: false,
tableConfig: {
url: '/api/v1/assets/domains/',
columnsExclude: ['gateway'],
@@ -28,7 +34,7 @@ export default {
formatter: AmountFormatter,
formatterArgs: {
routeQuery: {
activeTab: 'GroupUser'
tab: 'GroupUser'
}
}
},
@@ -38,7 +44,7 @@ export default {
formatterArgs: {
permissions: 'assets.view_gateway',
routeQuery: {
activeTab: 'GatewayList'
tab: 'GatewayList'
},
getTitle: function({ row }) {
return row.gateways.length
@@ -48,7 +54,6 @@ export default {
}
},
headerActions: {
createRoute: 'DomainCreate'
},
notice: this.$t('assets.DomainHelpMessage')
}

Some files were not shown because too many files have changed in this diff Show More