diff --git a/Dockerfile b/Dockerfile
index e8ec915ec..b54bf8999 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,23 +1,23 @@
-FROM node:10 as stage-build
+FROM node:14.16 as stage-build
+ARG TARGETARCH
+ARG VERSION
+ENV VERSION=$VERSION
ARG NPM_REGISTRY="https://registry.npmmirror.com"
ENV NPM_REGISTY=$NPM_REGISTRY
-ARG SASS_BINARY_SITE="https://npmmirror.com/mirrors/node-sass"
-ENV SASS_BINARY_SITE=$SASS_BINARY_SITE
WORKDIR /data
-RUN npm config set sass_binary_site=${SASS_BINARY_SITE}
-RUN npm config set registry ${NPM_REGISTRY}
-RUN yarn config set registry ${NPM_REGISTRY}
-COPY package.json yarn.lock /data/
-RUN yarn install
-RUN npm rebuild node-sass
+RUN set -ex \
+ && npm config set registry ${NPM_REGISTRY} \
+ && yarn config set registry ${NPM_REGISTRY} \
+ && yarn config set cache-folder /root/.cache/yarn/lina
-ARG VERSION
-ENV VERSION=$VERSION
ADD . /data
-RUN cd utils && bash -xieu build.sh build
+RUN --mount=type=cache,target=/root/.cache/yarn \
+ sed -i "s@Version .*@Version ${VERSION}@g" src/layout/components/Footer/index.vue \
+ && yarn install \
+ && yarn build
FROM nginx:alpine
-COPY --from=stage-build /data/release/lina /opt/lina
+COPY --from=stage-build /data/lina /opt/lina
COPY nginx.conf /etc/nginx/conf.d/default.conf
diff --git a/package.json b/package.json
index 7552d82bb..015471211 100644
--- a/package.json
+++ b/package.json
@@ -7,6 +7,7 @@
"scripts": {
"dev": "vue-cli-service serve",
"serve": "vue-cli-service serve",
+ "build": "vue-cli-service build --mode staging",
"build:prod": "vue-cli-service build",
"build:stage": "vue-cli-service build --mode staging",
"preview": "node build/index.js --preview",
@@ -32,7 +33,7 @@
"element-ui": "2.13.2",
"eslint-plugin-html": "^6.0.0",
"install": "^0.13.0",
- "jquery": "^3.5.0",
+ "jquery": "^3.6.1",
"js-cookie": "2.2.0",
"jsencrypt": "^3.2.1",
"krry-transfer": "^1.7.3",
diff --git a/src/App.vue b/src/App.vue
index fed5caa5f..8de84169c 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,12 +1,19 @@
-
+
diff --git a/src/router/common.js b/src/router/common.js
index 208bc277d..14d815a4d 100644
--- a/src/router/common.js
+++ b/src/router/common.js
@@ -15,6 +15,16 @@ export default [
permissions: []
}
},
+ {
+ path: '/ops/ansible/task/:id/log/',
+ component: () => import('@/views/ops/CeleryTaskLog'),
+ name: 'AnsibleTaskLog',
+ hidden: true,
+ meta: {
+ title: i18n.t('route.CeleryTaskLog'),
+ permissions: []
+ }
+ },
{
path: '/ops/task/task/:id/log/',
component: () => import('@/views/ops/CeleryTaskLog'),
diff --git a/src/router/console/xpack.js b/src/router/console/xpack.js
index 0018a9bda..14fe9191d 100644
--- a/src/router/console/xpack.js
+++ b/src/router/console/xpack.js
@@ -1,6 +1,8 @@
import empty from '@/layout/empty'
import i18n from '@/i18n/i18n'
+const activateMenu = '/console/assets/assets'
+
export default [
{
path: 'cloud',
@@ -20,7 +22,7 @@ export default [
hidden: true,
meta: {
title: i18n.t('xpack.Cloud.CloudSync'),
- activeMenu: '/console/assets/assets'
+ activeMenu: activateMenu
}
},
{
@@ -71,6 +73,7 @@ export default [
hidden: true,
meta: {
title: i18n.t('xpack.Cloud.AccountDetail'),
+ activeMenu: activateMenu,
permissions: ['xpack.view_account']
}
}
@@ -121,7 +124,8 @@ export default [
name: 'SyncInstanceTaskDetail',
hidden: true,
meta: {
- title: i18n.t('xpack.Cloud.SyncInstanceTaskDetail')
+ title: i18n.t('xpack.Cloud.SyncInstanceTaskDetail'),
+ activeMenu: activateMenu
}
}
]
diff --git a/src/store/modules/common.js b/src/store/modules/common.js
index e26944216..f3ac0e80e 100644
--- a/src/store/modules/common.js
+++ b/src/store/modules/common.js
@@ -2,7 +2,8 @@ import { optionUrlMeta } from '@/api/common'
const getDefaultState = () => {
return {
- metaMap: {}
+ metaMap: {},
+ isRouterAlive: true
}
}
@@ -11,6 +12,12 @@ const state = getDefaultState()
const mutations = {
SET_URL_META: (state, { url, meta }) => {
state.metaMap[url] = meta
+ },
+ reload: (state) => {
+ state.isRouterAlive = false
+ setTimeout(() => {
+ state.isRouterAlive = true
+ }, 0)
}
}
diff --git a/src/utils/common.js b/src/utils/common.js
index 4c260272c..68b321fab 100644
--- a/src/utils/common.js
+++ b/src/utils/common.js
@@ -302,3 +302,8 @@ export function groupedDropdownToCascader(group) {
export { BASE_URL }
+export function openWindow(url, name = '', iWidth = 900, iHeight = 600) {
+ var iTop = (window.screen.height - 30 - iHeight) / 2
+ var iLeft = (window.screen.width - 10 - iWidth) / 2
+ window.open(url, name, 'height=' + iHeight + ',width=' + iWidth + ',top=' + iTop + ',left=' + iLeft)
+}
diff --git a/src/utils/jms.js b/src/utils/jms.js
index 05472ea32..588f7a107 100644
--- a/src/utils/jms.js
+++ b/src/utils/jms.js
@@ -1,8 +1,10 @@
import store from '@/store'
import { constantRoutes } from '@/router'
+import { openWindow } from './common'
-export function openTaskPage(taskId) {
- window.open(`/#/ops/celery/task/${taskId}/log/`, '', 'width=900,height=600')
+export function openTaskPage(taskId, taskType) {
+ taskType = taskType || 'celery'
+ openWindow(`/#/ops/${taskType}/task/${taskId}/log/?type=${taskType}`)
}
export function checkPermission(permsRequired, permsAll) {
diff --git a/src/utils/jquery-vendor.js b/src/utils/jquery-vendor.js
index 97b3464ae..40ec6ad4d 100644
--- a/src/utils/jquery-vendor.js
+++ b/src/utils/jquery-vendor.js
@@ -1,4 +1,2 @@
-import $ from 'jquery'
-window.$ = $
-window.jQuery = $
+import $ from 'jquery/dist/jquery.min.js'
export default $
diff --git a/src/utils/org.js b/src/utils/org.js
index 6cd0a5d3d..ea18b8f77 100644
--- a/src/utils/org.js
+++ b/src/utils/org.js
@@ -30,7 +30,7 @@ async function changeOrg(org) {
if (index !== -1) {
location.href = path.substring(0, index)
}
- setTimeout(() => location.reload(), 400)
+ setTimeout(() => store.commit('common/reload'), 400)
}
}
diff --git a/src/views/accounts/ChangeAuthPlan/AppChangeAuthPlan/ChangeAuthPlanDetail/ChangeAuthPlanApp/index.vue b/src/views/accounts/ChangeAuthPlan/AppChangeAuthPlan/ChangeAuthPlanDetail/ChangeAuthPlanApp/index.vue
index 74ae7e95e..4d8ef9037 100644
--- a/src/views/accounts/ChangeAuthPlan/AppChangeAuthPlan/ChangeAuthPlanDetail/ChangeAuthPlanApp/index.vue
+++ b/src/views/accounts/ChangeAuthPlan/AppChangeAuthPlan/ChangeAuthPlanDetail/ChangeAuthPlanApp/index.vue
@@ -98,7 +98,7 @@ export default {
that.iHasObjects = [...that.iHasObjects, ...objects]
that.$refs.select2.clearSelected()
this.$message.success(this.$t('common.updateSuccessMsg'))
- window.location.reload()
+ this.$store.commit('common/reload')
this.$refs.listTable.$refs.ListTable.reloadTable()
}
}
diff --git a/src/views/accounts/ChangeAuthPlan/AssetChangeAuthPlan/ChangeAuthPlanDetail/ChangeAuthPlanAsset/index.vue b/src/views/accounts/ChangeAuthPlan/AssetChangeAuthPlan/ChangeAuthPlanDetail/ChangeAuthPlanAsset/index.vue
index ecca8a67e..e420c086a 100644
--- a/src/views/accounts/ChangeAuthPlan/AssetChangeAuthPlan/ChangeAuthPlanDetail/ChangeAuthPlanAsset/index.vue
+++ b/src/views/accounts/ChangeAuthPlan/AssetChangeAuthPlan/ChangeAuthPlanDetail/ChangeAuthPlanAsset/index.vue
@@ -93,7 +93,7 @@ export default {
onAddSuccess: (items, that) => {
this.$log.debug('AssetSelect value', that.assets)
this.$message.success(this.$t('common.updateSuccessMsg'))
- window.location.reload()
+ this.$store.commit('common/reload')
}
},
nodeRelationConfig: {
@@ -120,7 +120,7 @@ export default {
that.iHasObjects = [...that.iHasObjects, ...objects]
that.$refs.select2.clearSelected()
this.$message.success(this.$t('common.updateSuccessMsg'))
- window.location.reload()
+ this.$store.commit('common/reload')
},
performDelete: (item) => {
const data = {
diff --git a/src/views/applications/DatabaseApp/const.js b/src/views/applications/DatabaseApp/const.js
index f9dbd99b0..f482d12fa 100644
--- a/src/views/applications/DatabaseApp/const.js
+++ b/src/views/applications/DatabaseApp/const.js
@@ -1,11 +1,9 @@
-import { ORACLE, MONGODB, REDIS } from '../const'
+import { MONGODB, REDIS } from '../const'
export function getDatabaseTypeFieldsMap(type) {
const baseParams = ['host', 'port', 'database']
const tlsParams = ['use_ssl', 'ca_cert']
switch (type) {
- case ORACLE:
- return baseParams.concat(['version'])
case REDIS:
return baseParams.concat(tlsParams.concat(['client_cert', 'cert_key']))
case MONGODB:
diff --git a/src/views/assets/Cloud/SyncInstanceTask/SyncInstanceTaskDetail/AssetList.vue b/src/views/assets/Cloud/SyncInstanceTask/SyncInstanceTaskDetail/AssetList.vue
index 4d0f9407c..4a47bc984 100644
--- a/src/views/assets/Cloud/SyncInstanceTask/SyncInstanceTaskDetail/AssetList.vue
+++ b/src/views/assets/Cloud/SyncInstanceTask/SyncInstanceTaskDetail/AssetList.vue
@@ -38,6 +38,7 @@ export default {
},
tableConfig: {
url: `/api/v1/xpack/cloud/sync-instance-tasks/${this.object.id}/instances/`,
+ hasSelection: false,
columns: [
'instance_id',
{
diff --git a/src/views/assets/Cloud/SyncInstanceTask/SyncInstanceTaskList.vue b/src/views/assets/Cloud/SyncInstanceTask/SyncInstanceTaskList.vue
index 107377a20..9f0597653 100644
--- a/src/views/assets/Cloud/SyncInstanceTask/SyncInstanceTaskList.vue
+++ b/src/views/assets/Cloud/SyncInstanceTask/SyncInstanceTaskList.vue
@@ -58,10 +58,7 @@ export default {
formatter: DetailFormatter,
formatterArgs: {
permissions: 'xpack.view_syncinstancedetail',
- route: 'SyncInstanceTaskDetail',
- routeQuery: {
- activeTab: 'detail'
- }
+ route: 'SyncInstanceTaskDetail'
}
},
history_count: {
diff --git a/src/views/assets/CommandFilter/CommandFilterCreateUpdate.vue b/src/views/assets/CommandFilter/CommandFilterCreateUpdate.vue
index 1716905c1..2844954f6 100644
--- a/src/views/assets/CommandFilter/CommandFilterCreateUpdate.vue
+++ b/src/views/assets/CommandFilter/CommandFilterCreateUpdate.vue
@@ -15,7 +15,7 @@ export default {
},
fields: [
[this.$t('common.Basic'), ['name']],
- [this.$t('common.Correlation'), ['users', 'user_groups', 'assets', 'applications', 'system_users']],
+ [this.$t('common.Correlation'), ['users', 'user_groups', 'nodes', 'assets', 'applications', 'system_users']],
[this.$t('common.Other'), ['is_active', 'comment']]
],
fieldsMeta: {
@@ -36,6 +36,17 @@ export default {
url: '/api/v1/users/groups/'
}
},
+ nodes: {
+ el: {
+ value: [],
+ ajax: {
+ url: '/api/v1/assets/nodes/',
+ transformOption: (item) => {
+ return { label: item.full_value, value: item.id }
+ }
+ }
+ }
+ },
assets: {
type: 'assetSelect',
component: AssetSelect,
diff --git a/src/views/ops/TaskDetail/AdhocDetail/AdhocExecutionHistory.vue b/src/views/ops/TaskDetail/AdhocDetail/AdhocExecutionHistory.vue
index 46413b8c0..bfaf1a090 100644
--- a/src/views/ops/TaskDetail/AdhocDetail/AdhocExecutionHistory.vue
+++ b/src/views/ops/TaskDetail/AdhocDetail/AdhocExecutionHistory.vue
@@ -6,6 +6,7 @@
import ListTable from '@/components/ListTable'
import { ActionsFormatter } from '@/components/TableFormatters'
import { toSafeLocalDateStr } from '@/utils/common'
+import { openTaskPage } from '@/utils/jms'
export default {
name: 'AdhocExecutionHistory',
@@ -86,6 +87,14 @@ export default {
callback: function({ row, tableData }) {
return this.$router.push({ name: 'HistoryExecutionDetail', params: { id: row.id }})
}
+ },
+ {
+ name: 'log',
+ title: this.$t('ops.output'),
+ type: 'info',
+ callback: function({ row }) {
+ openTaskPage(row.id, 'ansible')
+ }
}
]
}
diff --git a/src/views/ops/TaskDetail/HistoryExecutionDetail/HistoryExecutionDetail.vue b/src/views/ops/TaskDetail/HistoryExecutionDetail/HistoryExecutionDetail.vue
index 80345f564..7d9901561 100644
--- a/src/views/ops/TaskDetail/HistoryExecutionDetail/HistoryExecutionDetail.vue
+++ b/src/views/ops/TaskDetail/HistoryExecutionDetail/HistoryExecutionDetail.vue
@@ -15,7 +15,6 @@ import DetailCard from '@/components/DetailCard'
import { toSafeLocalDateStr } from '@/utils/common'
import RunInfoCard from '../../RunInfoCard'
import { toLastFailureDisplay, toLastSucessDisplay } from '../business'
-import { openTaskPage } from '@/utils/jms'
export default {
name: 'HistoryExecutionDetail',
@@ -72,17 +71,6 @@ export default {
{
key: this.$t('ops.isSuccess'),
value: this.object.is_success
- },
- {
- key: this.$t('ops.output'),
- value: this.object.id,
- formatter: function(row, value) {
- const onClick = function() {
- openTaskPage(value, 'ansible')
- }
- const title = this.$t('common.View')
- return { title }
- }
}
]
}
diff --git a/src/views/ops/TaskDetail/TaskDetail.vue b/src/views/ops/TaskDetail/TaskDetail.vue
index c60d2d8c6..51ce796e1 100644
--- a/src/views/ops/TaskDetail/TaskDetail.vue
+++ b/src/views/ops/TaskDetail/TaskDetail.vue
@@ -108,7 +108,7 @@ export default {
openTaskPage(value, 'ansible')
}
const title = this.$t('common.View')
- return { title }
+ return { title }
}
}
]
diff --git a/src/views/ops/TaskDetail/TaskHistory.vue b/src/views/ops/TaskDetail/TaskHistory.vue
index 401568565..160b57846 100644
--- a/src/views/ops/TaskDetail/TaskHistory.vue
+++ b/src/views/ops/TaskDetail/TaskHistory.vue
@@ -6,6 +6,7 @@
import ListTable from '@/components/ListTable'
import { DetailFormatter } from '@/components/TableFormatters'
import { toSafeLocalDateStr } from '@/utils/common'
+import { openTaskPage } from '@/utils/jms'
export default {
name: 'TaskHistory',
@@ -95,6 +96,14 @@ export default {
callback: function({ row, tableData }) {
return this.$router.push({ name: 'HistoryExecutionDetail', params: { id: row.id }})
}
+ },
+ {
+ name: 'log',
+ title: this.$t('ops.output'),
+ type: 'info',
+ callback: function({ row }) {
+ openTaskPage(row.id, 'ansible')
+ }
}
]
}
diff --git a/src/views/perms/AssetPermission/AssetPermissionDetail/AssetPermissionAsset.vue b/src/views/perms/AssetPermission/AssetPermissionDetail/AssetPermissionAsset.vue
index 2e4fa30e8..526e73bc4 100644
--- a/src/views/perms/AssetPermission/AssetPermissionDetail/AssetPermissionAsset.vue
+++ b/src/views/perms/AssetPermission/AssetPermissionDetail/AssetPermissionAsset.vue
@@ -93,7 +93,7 @@ export default {
this.$message.success(this.$t('common.updateSuccessMsg'))
this.$refs.ListTable.reloadTable()
that.$refs.assetSelect.$refs.select2.clearSelected()
- window.location.reload()
+ this.$store.commit('common/reload')
}
},
nodeRelationConfig: {
diff --git a/src/views/profile/ProfileInfo.vue b/src/views/profile/ProfileInfo.vue
index e1c3e8491..46c81cad4 100644
--- a/src/views/profile/ProfileInfo.vue
+++ b/src/views/profile/ProfileInfo.vue
@@ -37,7 +37,8 @@ import DetailCard from '@/components/DetailCard'
import QuickActions from '@/components/QuickActions'
import UserConfirmDialog from '@/components/UserConfirmDialog'
import { toSafeLocalDateStr } from '@/utils/common'
-import store from '@/store'
+import { getProfile } from '@/api/users'
+import { mapState } from 'vuex'
export default {
name: 'ProfileInfo',
@@ -47,14 +48,9 @@ export default {
QuickActions,
UserConfirmDialog
},
- props: {
- object: {
- type: Object,
- default: () => store.state.users.profile
- }
- },
data() {
return {
+ object: this.userProfile || {},
url: `/api/v1/users/profile/`,
showPasswordDialog: false,
currentEdit: '',
@@ -160,7 +156,7 @@ export default {
attrs: {
disabled: true,
name: 'site_msg',
- model: this.object.receive_backends.indexOf('site_msg') !== -1
+ model: this.object?.receive_backends.indexOf('site_msg') !== -1
},
callbacks: {
change: this.updateUserReceiveBackends
@@ -171,7 +167,7 @@ export default {
type: 'switcher',
attrs: {
name: 'email',
- model: this.object.receive_backends.indexOf('email') !== -1
+ model: this.object?.receive_backends.indexOf('email') !== -1
},
callbacks: {
change: this.updateUserReceiveBackends
@@ -182,7 +178,7 @@ export default {
type: 'switcher',
attrs: {
name: 'wecom',
- model: this.object.receive_backends.indexOf('wecom') !== -1
+ model: this.object?.receive_backends.indexOf('wecom') !== -1
},
has: this.$store.getters.publicSettings.AUTH_WECOM,
callbacks: {
@@ -194,7 +190,7 @@ export default {
type: 'switcher',
attrs: {
name: 'dingtalk',
- model: this.object.receive_backends.indexOf('dingtalk') !== -1
+ model: this.object?.receive_backends.indexOf('dingtalk') !== -1
},
has: this.$store.getters.publicSettings.AUTH_DINGTALK,
callbacks: {
@@ -206,7 +202,7 @@ export default {
type: 'switcher',
attrs: {
name: 'feishu',
- model: this.object.receive_backends.indexOf('feishu') !== -1
+ model: this.object?.receive_backends.indexOf('feishu') !== -1
},
has: this.$store.getters.publicSettings.AUTH_FEISHU,
callbacks: {
@@ -217,6 +213,9 @@ export default {
}
},
computed: {
+ ...mapState({
+ userProfile: state => state.users.profile
+ }),
detailCardItems() {
return [
{
@@ -299,6 +298,12 @@ export default {
return url
}
},
+ created() {
+ getProfile().then(res => {
+ this.object = res
+ this.$store.commit('users/SET_PROFILE', res)
+ })
+ },
methods: {
updateUserReceiveBackends(val) {
this.$axios.patch(
diff --git a/src/views/sessions/SessionDetail/SessionDetailInfo.vue b/src/views/sessions/SessionDetail/SessionDetailInfo.vue
index 1bb503e75..4dc3315b8 100644
--- a/src/views/sessions/SessionDetail/SessionDetailInfo.vue
+++ b/src/views/sessions/SessionDetail/SessionDetailInfo.vue
@@ -49,7 +49,7 @@ export default {
const msg = vm.$t('sessions.TerminateTaskSendSuccessMsg')
vm.$message.success(msg)
window.setTimeout(function() {
- window.location.reload()
+ this.$store.commit('common/reload')
}, 50000)
})
}
diff --git a/src/views/settings/Interface.vue b/src/views/settings/Interface.vue
index b5b7b8800..2b1e7aeac 100644
--- a/src/views/settings/Interface.vue
+++ b/src/views/settings/Interface.vue
@@ -175,7 +175,7 @@ export default {
}).then(() => {
restoreInterface().then(res => {
this.$message.success(res.success)
- location.reload()
+ this.$store.commit('common/reload')
})
})
}.bind(this)
@@ -221,7 +221,7 @@ export default {
}
}
updateInterface(form).then(res => {
- location.reload()
+ this.$store.commit('common/reload')
})
}
}
diff --git a/src/views/settings/License.vue b/src/views/settings/License.vue
index d3d9c19a5..c485534a4 100644
--- a/src/views/settings/License.vue
+++ b/src/views/settings/License.vue
@@ -140,6 +140,7 @@ export default {
window.open(url, '_blank')
},
importLicense() {
+ const vm = this
if (this.licenseFile['file'] === undefined) {
return
}
@@ -148,7 +149,7 @@ export default {
importLicense(formData).then(res => {
if (res.status) {
this.$message.success(res.msg)
- setTimeout(() => location.reload(), 500)
+ setTimeout(() => vm.$store.commit('common/reload'), 500)
} else {
this.$message.error(res.msg)
}
diff --git a/src/views/settings/Org/OrganizationList.vue b/src/views/settings/Org/OrganizationList.vue
index 376a566d8..08139ce0c 100644
--- a/src/views/settings/Org/OrganizationList.vue
+++ b/src/views/settings/Org/OrganizationList.vue
@@ -60,6 +60,7 @@ export default {
actions: {
prop: 'id',
formatterArgs: {
+ canUpdate: this.$hasPerm('orgs.change_organization'),
canDelete: function({ row }) {
return !row.is_default && vm.$hasPerm('orgs.delete_organization')
},
diff --git a/src/views/settings/SMS/Base.vue b/src/views/settings/SMS/Base.vue
index 2694bf21e..9f7651d59 100644
--- a/src/views/settings/SMS/Base.vue
+++ b/src/views/settings/SMS/Base.vue
@@ -12,7 +12,7 @@
v-on="$listeners"
@confirm="onConfirm()"
>
-
+
@@ -52,6 +52,16 @@ export default {
submitSuccess(res) {
this.$emit('input', !!res[this.enableField])
this.visible = false
+ },
+ testPerformError(error) {
+ const data = error.response.data
+ for (const key of Object.keys(data)) {
+ let value = data[key]
+ if (value instanceof Array) {
+ value = value.join(';')
+ }
+ this.$refs.form.$refs.form.setFieldError(key, value)
+ }
}
}
}
diff --git a/src/views/settings/SMS/CMPP2.vue b/src/views/settings/SMS/CMPP2.vue
index d43f226e0..78f4f56a8 100644
--- a/src/views/settings/SMS/CMPP2.vue
+++ b/src/views/settings/SMS/CMPP2.vue
@@ -1,5 +1,5 @@
-
+