Merge branch 'master' of github.com:jumpserver/lina

This commit is contained in:
ibuler
2020-05-07 16:28:36 +08:00
30 changed files with 722 additions and 460 deletions

View File

@@ -40,12 +40,15 @@
"nprogress": "0.2.0", "nprogress": "0.2.0",
"path-to-regexp": "2.4.0", "path-to-regexp": "2.4.0",
"vue": "2.6.10", "vue": "2.6.10",
"vue-codemirror-lite": "^1.0.4",
"vue-cookie": "^1.1.4", "vue-cookie": "^1.1.4",
"vue-i18n": "^8.15.5", "vue-i18n": "^8.15.5",
"vue-router": "3.0.6", "vue-router": "3.0.6",
"vue-select": "^3.9.5", "vue-select": "^3.9.5",
"vuejs-logger": "^1.5.4", "vuejs-logger": "^1.5.4",
"vuex": "3.1.0", "vuex": "3.1.0",
"xterm": "^4.5.0",
"xterm-addon-fit": "^0.3.0",
"ztree": "^3.5.24" "ztree": "^3.5.24"
}, },
"devDependencies": { "devDependencies": {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

@@ -0,0 +1,20 @@
<template>
<codemirror v-bind="$attrs" v-on="$listeners" />
</template>
<script>
import { codemirror } from 'vue-codemirror-lite'
export default {
components: {
codemirror
},
props: {
...codemirror.props
}
}
</script>
<style>
</style>

View File

@@ -0,0 +1,52 @@
<template>
<div id="terminal" ref="terminal" class="xterm" />
</template>
<script>
import 'xterm/css/xterm.css'
import { Terminal } from 'xterm'
import { FitAddon } from 'xterm-addon-fit'
export default {
name: 'Term',
data() {
return {
xterm: ''
}
},
mounted: function() {
const terminalContainer = this.$refs.terminal
this.xterm = new Terminal(
{
fontFamily: 'monaco, Consolas, "Lucida Console", monospace',
lineHeight: 1.2,
fontSize: 15,
rightClickSelectsWord: true,
theme: {
background: '#1f1b1b'
}
})
const fitAddon = new FitAddon()
this.xterm.loadAddon(fitAddon)
this.xterm.open(terminalContainer)
fitAddon.fit()
this.xterm.scrollToBottom()
},
beforeDestroy() {
this.xterm.dispose()
},
methods: {
reset: function() {
this.xterm.reset()
},
write: function(val) {
this.xterm.write(val)
},
changeSelectedAssets() {
}
}
}
</script>

View File

@@ -0,0 +1,17 @@
<template>
<div />
</template>
<script>
export default {
name: '',
components: {},
data() {
return {}
}
}
</script>
<style lang='less' scoped>
</style>

View File

@@ -2,7 +2,13 @@
<el-collapse-transition> <el-collapse-transition>
<div style="display: flex;justify-items: center; flex-wrap: nowrap;justify-content:space-between;"> <div style="display: flex;justify-items: center; flex-wrap: nowrap;justify-content:space-between;">
<div v-show="iShowTree" :style="iShowTree?('width:250px;'):('width:0;')" class="transition-box"> <div v-show="iShowTree" :style="iShowTree?('width:250px;'):('width:0;')" class="transition-box">
<AutoDataZTree :setting="treeSetting" class="auto-data-ztree" @urlChange="handleUrlChange" /> <!-- <AutoDataZTree :setting="treeSetting" class="auto-data-ztree" @urlChange="handleUrlChange" />-->
<component
:is="component"
:setting="treeSetting"
class="auto-data-ztree"
@urlChange="handleUrlChange"
/>
</div> </div>
<div :style="iShowTree?('display: flex;width: calc(100% - 250px);'):('display: flex;width:100%;')"> <div :style="iShowTree?('display: flex;width: calc(100% - 250px);'):('display: flex;width:100%;')">
<div class="mini"> <div class="mini">
@@ -38,6 +44,11 @@ export default {
showTree: { showTree: {
type: Boolean, type: Boolean,
default: true default: true
},
// 默认引用的Tree组件
component: {
type: String,
default: () => 'AutoDataZTree'
} }
}, },
data() { data() {

View File

@@ -1,39 +1,84 @@
<template> <template>
<Page> <el-collapse-transition>
<el-alert v-if="helpMessage" type="success"> {{ helpMessage }} </el-alert> <div style="display: flex;justify-items: center; flex-wrap: nowrap;justify-content:space-between;">
<el-collapse-transition> <div v-show="iShowTree" :style="iShowTree?('width:250px;'):('width:0;')" class="transition-box">
<el-row> <!-- <AutoDataZTree :setting="treeSetting" class="auto-data-ztree" @urlChange="handleUrlChange" />-->
<el-col v-show="ShowTree" :span="4" class="transition-box"> <component
<!-- <TreeNode :url="treeurl" @urlChanged="handleUrlChange" />--> :is="component"
这里放资产树 :setting="treeSetting"
</el-col> class="auto-data-ztree"
<el-col :span="1" class="mini"><div style="display:block" class="mini-button" @click="ShowTree=!ShowTree"><i v-show="ShowTree" id="toggle-icon" class="fa fa-angle-left fa-x" /><i v-show="!ShowTree" id="toggle-icon" class="fa fa-angle-right fa-x" /></div></el-col> @urlChange="handleUrlChange"
<el-col :span="ShowTree?19:23" class="transition-box"> />
这里其它东西 </div>
</el-col> <div :style="iShowTree?('display: flex;width: calc(100% - 250px);'):('display: flex;width:100%;')">
</el-row> <div class="mini">
</el-collapse-transition> <div style="display:block" class="mini-button" @click="iShowTree=!iShowTree">
</Page> <i v-show="iShowTree" class="fa fa-angle-left fa-x" /><i v-show="!iShowTree" class="fa fa-angle-right fa-x" />
</div>
</div>
<IBox class="transition-box" style="width: calc(100% - 17px);">
<Term />
<div style="display: flex">
<div>
<CodeMirror @change="handleActionChange" />
</div>
<div>
<Select2 />
</div>
</div>
</IBox>
</div>
</div>
</el-collapse-transition>
</template> </template>
<script> <script>
import { Page } from '@/layout/components' import AutoDataZTree from '@/components/AutoDataZTree'
// import TreeNode from '@/components/TreeNode' import Term from '@/components/Term'
import ListTable from '@/components/ListTable'
import IBox from '@/components/IBox'
import Select2 from '@/components/Select2'
import CodeMirror from '@/components/CodeMirror'
export default { export default {
name: 'TreeTable',
components: { components: {
Page ListTable,
// TreeNode Term,
AutoDataZTree,
IBox,
Select2,
CodeMirror
},
props: {
...ListTable.props,
treeSetting: {
type: Object,
default: () => AutoDataZTree.props.setting.default()
},
showTree: {
type: Boolean,
default: true
},
// 默认引用的Tree组件
component: {
type: String,
default: () => 'AutoDataZTree'
}
}, },
data() { data() {
return { return {
helpMessage: '', iTableConfig: this.tableConfig,
ShowTree: true, iShowTree: this.showTree,
treeurl: '/api/v1/assets/nodes/children/tree/' actions: ''
} }
}, },
methods: { methods: {
handleUrlChange(_url) { handleUrlChange(_url) {
console.log(_url) this.$set(this.iTableConfig, 'url', _url)
console.log(this.iTableConfig)
},
handleActionChange(val) {
this.actions = val
} }
} }
} }
@@ -58,4 +103,8 @@ export default {
width: 12px !important; width: 12px !important;
} }
.auto-data-ztree {
overflow: auto;
/*border-right: solid 1px red;*/
}
</style> </style>

View File

@@ -1,140 +0,0 @@
<template>
<GenericDetailPage :object.sync="historyExecutionDetail" v-bind="config">
<div slot="executionDetail">
<el-row :gutter="20">
<el-col :span="14">
<DetailCard v-if="flag" :title="cardTitle" :items="detailCardItems" />
</el-col>
<el-col :span="10">
<RunInfoCard v-bind="RunSuccessConfig" />
<RunInfoCard v-bind="RunFailedConfig" />
</el-col>
</el-row>
</div>
<div slot="outPut">
输出
</div>
</GenericDetailPage>
</template>
<script>
import { GenericDetailPage } from '@/layout/components'
import DetailCard from '@/components/DetailCard/index'
import { getHistoryExecutionDetail } from '@/api/ops'
import { toSafeLocalDateStr } from '@/utils/common'
import RunInfoCard from './runinfocard/RunInfoCard'
export default {
name: 'HistoryExecutionDetail',
components: {
GenericDetailPage,
DetailCard,
RunInfoCard
},
data() {
return {
flag: false,
historyExecutionDetail: { name: '' },
config: {
activeMenu: 'executionDetail',
title: this.$t('jobcenter.ExecutionDetail'),
submenu: [
{
title: this.$t('jobcenter.ExecutionDetail'),
name: 'executionDetail'
},
{
title: this.$t('jobcenter.Output'),
name: 'outPut'
}
],
hasRightSide: false,
actions: {
detailApiUrl: `/api/v1/ops/adhoc-executions/${this.$route.params.id}/`
}
},
RunSuccessConfig: {
icon: 'fa-info',
title: this.$t('jobcenter.Last run success hosts'),
content: [
{
hostname: 'linux',
result: 'api没有该数据==api没有该数据api没有该数据api没有该数据api没有该数据'
}
]
},
RunFailedConfig: {
icon: 'fa-info',
title: this.$t('jobcenter.Last run failed hosts'),
headerColor: 'danger',
content: [
{
hostname: 'window',
result: 'api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据'
}
]
},
defaultValue: '',
historyExecutionDetailData: {}
}
},
computed: {
cardTitle() {
return `${this.historyExecutionDetailData.task_display}:${this.historyExecutionDetailData.adhoc_short_id}`
},
detailCardItems() {
return [
{
key: this.$t('jobcenter.ID'),
value: this.historyExecutionDetailData.id
},
{
key: this.$t('jobcenter.TaskName'),
value: this.historyExecutionDetailData.task_display
},
{
key: this.$t('jobcenter.Version'),
value: this.historyExecutionDetailData.adhoc_short_id
},
{
key: this.$t('jobcenter.DateStart'),
value: toSafeLocalDateStr(this.historyExecutionDetailData.date_start)
},
{
key: this.$t('jobcenter.TimeDelta'),
value: this.historyExecutionDetailData.timedelta.toFixed(2) + 's'
},
{
key: this.$t('jobcenter.IsFinished'),
value: this.toChoicesDisplay(this.historyExecutionDetailData.is_finished)
},
{
key: this.$t('jobcenter.IsSuccess'),
value: this.toChoicesDisplay(this.historyExecutionDetailData.is_success)
}
]
}
},
mounted() {
this.getHistoryExecutionDetailData()
},
methods: {
getHistoryExecutionDetailData() {
getHistoryExecutionDetail(this.$route.params.id).then(data => {
this.historyExecutionDetailData = data
this.flag = true
})
},
toChoicesDisplay(c) {
if (!c) {
return this.$t('jobcenter.No')
}
return this.$t('jobcenter.Yes')
}
}
}
</script>
<style lang="less" scoped>
</style>

View File

@@ -1,165 +0,0 @@
<template>
<GenericDetailPage :object.sync="taskDetail" v-bind="config">
<div slot="detail">
<el-row :gutter="20">
<el-col :span="14">
<DetailCard v-if="flag" :title="cardTitle" :items="detailCardItems" />
</el-col>
<el-col :span="10">
<RunInfoCard v-bind="RunSuccessConfig" />
<RunInfoCard v-bind="RunFailedConfig" />
</el-col>
</el-row>
</div>
<div slot="taskVersions">
<TaskAdhoc />
</div>
<div slot="execution">
<TaskHistory />
</div>
<div slot="laskExecutionOutput">
最后执行输出
</div>
</GenericDetailPage>
</template>
<script>
import { GenericDetailPage } from '@/layout/components'
import DetailCard from '@/components/DetailCard/index'
import { toSafeLocalDateStr } from '@/utils/common'
import { getTaskDetail } from '@/api/ops'
import TaskHistory from './TaskHistory'
import TaskAdhoc from './TaskAdhoc'
import RunInfoCard from './runinfocard/RunInfoCard'
export default {
name: 'TaskDetail',
components: {
GenericDetailPage,
DetailCard,
TaskAdhoc,
TaskHistory,
RunInfoCard
},
data() {
return {
flag: false,
taskDetail: { name: '' },
config: {
activeMenu: 'detail',
submenu: [
{
title: this.$t('jobcenter.TaskDetail'),
name: 'detail'
},
{
title: this.$t('jobcenter.TaskVersions'),
name: 'taskVersions'
},
{
title: this.$t('jobcenter.Execution'),
name: 'execution'
},
{
title: this.$t('jobcenter.LaskExecutionOutput'),
name: 'laskExecutionOutput'
}
],
hasRightSide: false
},
RunSuccessConfig: {
icon: 'fa-info',
title: this.$t('jobcenter.Last run success hosts'),
content: [
{
hostname: 'linux',
result: 'api没有该数据==api没有该数据api没有该数据api没有该数据api没有该数据'
}
]
},
RunFailedConfig: {
icon: 'fa-info',
title: this.$t('jobcenter.Last run failed hosts'),
headerColor: 'danger',
content: [
{
hostname: 'window',
result: 'api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据'
}
]
},
taskData: {}
}
},
computed: {
cardTitle() {
return this.taskData.name
},
detailCardItems() {
return [
{
key: this.$t('jobcenter.ID'),
value: this.taskData.id
},
{
key: this.$t('common.Name'),
value: this.taskData.name
},
{
key: this.$t('jobcenter.DateCreated'),
value: toSafeLocalDateStr(this.taskData.date_created)
},
{
key: this.$t('jobcenter.TotalVersions'),
value: this.taskData.summary.total
},
{
key: this.$t('jobcenter.LatestVersion'),
value: this.taskData.latest_execution.adhoc_short_id
},
{
key: this.$t('jobcenter.LastRun'),
value: toSafeLocalDateStr(this.taskData.latest_execution.date_finished)
},
{
key: this.$t('jobcenter.TimeDelta'),
value: this.taskData.latest_execution.timedelta.toFixed(2) + 's'
},
{
key: this.$t('jobcenter.IsFinished'),
value: this.toChoicesDisplay(this.taskData.latest_execution.is_finished)
},
{
key: this.$t('jobcenter.IsSuccess'),
value: this.toChoicesDisplay(this.taskData.latest_execution.is_success)
},
{
key: this.$t('jobcenter.Contents'),
value: 'api 没有该数据'
}
]
}
},
mounted() {
this.getTaskDetailData()
},
methods: {
getTaskDetailData() {
getTaskDetail(this.$route.params.id).then(data => {
this.taskData = data
this.flag = true
})
},
toChoicesDisplay(c) {
if (!c) {
return this.$t('jobcenter.No')
}
return this.$t('jobcenter.Yes')
}
}
}
</script>
<style lang="less" scoped>
</style>

View File

@@ -1,57 +1,34 @@
<template> <template>
<GenericDetailPage :object.sync="adhocDetail" v-bind="config"> <el-row :gutter="20">
<div slot="adhocDetail"> <el-col :span="14">
<el-row :gutter="20"> <DetailCard :title="cardTitle" :items="detailCardItems" />
<el-col :span="14"> </el-col>
<DetailCard v-if="flag" :title="cardTitle" :items="detailCardItems" /> <el-col :span="10">
</el-col> <RunInfoCard v-bind="RunSuccessConfig" />
<el-col :span="10"> <RunInfoCard v-bind="RunFailedConfig" />
<RunInfoCard v-bind="RunSuccessConfig" /> </el-col>
<RunInfoCard v-bind="RunFailedConfig" /> </el-row>
</el-col>
</el-row>
</div>
<div slot="versionRunExecution">
<AdhocExecutionHistory />
</div>
</GenericDetailPage>
</template> </template>
<script> <script>
import { GenericDetailPage } from '@/layout/components'
import DetailCard from '@/components/DetailCard/index' import DetailCard from '@/components/DetailCard/index'
import { getAdhocDetail } from '@/api/ops'
import AdhocExecutionHistory from './AdhocExecutionHistory'
import { toSafeLocalDateStr } from '@/utils/common' import { toSafeLocalDateStr } from '@/utils/common'
import RunInfoCard from './runinfocard/RunInfoCard' import RunInfoCard from '../../runinfocard/RunInfoCard'
export default { export default {
name: 'AdhocDetail', name: 'AdhocDetail',
components: { components: {
GenericDetailPage,
DetailCard, DetailCard,
AdhocExecutionHistory,
RunInfoCard RunInfoCard
}, },
props: {
object: {
type: Object,
default: () => ({})
}
},
data() { data() {
return { return {
flag: false,
adhocDetail: { name: '' },
config: {
activeMenu: 'adhocDetail',
title: this.$t('jobcenter.TaskDetail'),
submenu: [
{
title: this.$t('jobcenter.versionDetail'),
name: 'adhocDetail'
},
{
title: this.$t('jobcenter.VersionRunExecution'),
name: 'versionRunExecution'
}
],
hasRightSide: false
},
RunSuccessConfig: { RunSuccessConfig: {
icon: 'fa-info', icon: 'fa-info',
title: this.$t('jobcenter.Last run success hosts'), title: this.$t('jobcenter.Last run success hosts'),
@@ -72,40 +49,39 @@ export default {
result: 'api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据' result: 'api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据'
} }
] ]
}, }
adhocData: '',
versionDetailData: {}
} }
}, },
computed: { computed: {
cardTitle() { cardTitle() {
console.log('this.object===', this.object)
return 'api 没有该数据' return 'api 没有该数据'
}, },
detailCardItems() { detailCardItems() {
return [ return [
{ {
key: this.$t('jobcenter.ID'), key: this.$t('jobcenter.ID'),
value: this.adhocData.id value: this.object.id
}, },
{ {
key: this.$t('jobcenter.Hosts'), key: this.$t('jobcenter.Hosts'),
value: this.adhocData.hosts.length value: this.object.hosts.length
}, },
{ {
key: this.$t('jobcenter.Pattern'), key: this.$t('jobcenter.Pattern'),
value: this.adhocData.pattern value: this.object.pattern
}, },
{ {
key: this.$t('jobcenter.Options'), key: this.$t('jobcenter.Options'),
value: this.adhocData.options value: this.object.options
}, },
{ {
key: this.$t('jobcenter.RunAs'), key: this.$t('jobcenter.RunAs'),
value: this.disPlayRunAs(this.adhocData.run_as_admin, this.adhocData.run_as) value: this.disPlayRunAs(this.object.run_as_admin, this.object.run_as)
}, },
{ {
key: this.$t('jobcenter.Become'), key: this.$t('jobcenter.Become'),
value: this.adhocData.become_display value: this.object.become_display
}, },
{ {
key: this.$t('jobcenter.CreatedBy'), key: this.$t('jobcenter.CreatedBy'),
@@ -113,7 +89,7 @@ export default {
}, },
{ {
key: this.$t('jobcenter.DateCreated'), key: this.$t('jobcenter.DateCreated'),
value: toSafeLocalDateStr(this.adhocData.date_created) value: toSafeLocalDateStr(this.object.date_created)
}, },
{ {
key: this.$t('jobcenter.RunTimes'), key: this.$t('jobcenter.RunTimes'),
@@ -142,18 +118,7 @@ export default {
] ]
} }
}, },
mounted() {
this.getAdhocDetailData()
},
methods: { methods: {
getAdhocDetailData() {
getAdhocDetail(this.$route.params.id).then(data => {
console.log(this.$route.params.id)
console.log(data)
this.adhocData = data
this.flag = true
})
},
disPlayRunAs(run_as_admin, run_as) { disPlayRunAs(run_as_admin, run_as) {
if (run_as_admin) { if (run_as_admin) {
return 'Admin' return 'Admin'

View File

@@ -0,0 +1,45 @@
<template>
<GenericDetailPage :object.sync="AdhocDetail" :active-menu.sync="config.activeMenu" v-bind="config" v-on="$listeners">
<keep-alive>
<component :is="config.activeMenu" :object="AdhocDetail" />
</keep-alive>
</GenericDetailPage>
</template>
<script>
import { GenericDetailPage, TabPage } from '@/layout/components'
import AdhocExecutionHistory from './AdhocExecutionHistory'
import AdhocDetail from './AdhocDetail'
export default {
components: {
GenericDetailPage,
AdhocExecutionHistory,
AdhocDetail,
TabPage
},
data() {
return {
AdhocDetail: {},
config: {
activeMenu: 'AdhocDetail',
title: this.$t('jobcenter.TaskDetail'),
submenu: [
{
title: this.$t('jobcenter.versionDetail'),
name: 'AdhocDetail'
},
{
title: this.$t('jobcenter.VersionRunExecution'),
name: 'AdhocExecutionHistory'
}
]
}
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,111 @@
<template>
<el-row :gutter="20">
<el-col :span="14">
<DetailCard :title="cardTitle" :items="detailCardItems" />
</el-col>
<el-col :span="10">
<RunInfoCard v-bind="RunSuccessConfig" />
<RunInfoCard v-bind="RunFailedConfig" />
</el-col>
</el-row>
</template>
<script>
import DetailCard from '@/components/DetailCard/index'
import { toSafeLocalDateStr } from '@/utils/common'
import RunInfoCard from '../../runinfocard/RunInfoCard'
export default {
name: 'HistoryExecutionDetail',
components: {
DetailCard,
RunInfoCard
},
props: {
object: {
type: Object,
default: () => ({})
}
},
data() {
return {
RunSuccessConfig: {
icon: 'fa-info',
title: this.$t('jobcenter.Last run success hosts'),
content: [
{
hostname: 'linux',
result: 'api没有该数据==api没有该数据api没有该数据api没有该数据api没有该数据'
}
]
},
RunFailedConfig: {
icon: 'fa-info',
title: this.$t('jobcenter.Last run failed hosts'),
headerColor: 'danger',
content: [
{
hostname: 'window',
result: 'api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据'
}
]
}
}
},
computed: {
cardTitle() {
return `${this.object.task_display}:${this.object.adhoc_short_id}`
},
detailCardItems() {
return [
{
key: this.$t('jobcenter.ID'),
value: this.object.id
},
{
key: this.$t('jobcenter.TaskName'),
value: this.object.task_display
},
{
key: this.$t('jobcenter.Version'),
value: this.object.adhoc_short_id
},
{
key: this.$t('jobcenter.DateStart'),
value: toSafeLocalDateStr(this.object.date_start)
},
{
key: this.$t('jobcenter.TimeDelta'),
value: this.object.timedelta.toFixed(2) + 's'
},
{
key: this.$t('jobcenter.IsFinished'),
value: this.toChoicesDisplay(this.object.is_finished)
},
{
key: this.$t('jobcenter.IsSuccess'),
value: this.toChoicesDisplay(this.object.is_success)
}
]
}
},
watch: {
object(iNew, iOld) {
console.log('iNew====', iNew)
console.log('iOld====', iOld)
}
},
methods: {
toChoicesDisplay(c) {
if (!c) {
return this.$t('jobcenter.No')
}
return this.$t('jobcenter.Yes')
}
}
}
</script>
<style lang="less" scoped>
</style>

View File

@@ -0,0 +1,46 @@
<template>
<GenericDetailPage :object.sync="HistoryExecutionDetail" :active-menu.sync="config.activeMenu" v-bind="config" v-on="$listeners">
<keep-alive>
<component :is="config.activeMenu" :object="HistoryExecutionDetail" />
</keep-alive>
</GenericDetailPage>
</template>
<script>
import { GenericDetailPage, TabPage } from '@/layout/components'
import HistoryExecutionDetail from './HistoryExecutionDetail'
export default {
components: {
HistoryExecutionDetail,
GenericDetailPage,
TabPage
},
data() {
return {
HistoryExecutionDetail: {},
config: {
activeMenu: 'HistoryExecutionDetail',
title: this.$t('jobcenter.ExecutionDetail'),
submenu: [
{
title: this.$t('jobcenter.ExecutionDetail'),
name: 'HistoryExecutionDetail'
},
{
title: this.$t('jobcenter.Output'),
name: 'OutPut'
}
],
actions: {
detailApiUrl: `/api/v1/ops/adhoc-executions/${this.$route.params.id}/`
}
}
}
}
}
</script>
<style scoped>
</style>

View File

@@ -11,10 +11,16 @@ export default {
components: { components: {
ListTable ListTable
}, },
props: {
object: {
type: Object,
default: () => ({})
}
},
data() { data() {
return { return {
tableConfig: { tableConfig: {
url: `/api/v1/ops/adhoc/?task=${this.$route.params.id}`, url: `/api/v1/ops/adhoc/?task=${this.object.id}`,
columns: [ columns: [
'short_id', 'hosts', 'pattern', 'run_as', 'become_display', 'date_created', 'actions' 'short_id', 'hosts', 'pattern', 'run_as', 'become_display', 'date_created', 'actions'
], ],
@@ -52,7 +58,7 @@ export default {
}, },
actions: { actions: {
prop: 'id', prop: 'id',
abel: this.$tc('Action'), label: this.$tc('Action'),
formatter: ActionsFormatter, formatter: ActionsFormatter,
actions: { actions: {
hasEdit: false, hasEdit: false,

View File

@@ -0,0 +1,127 @@
<template>
<el-row :gutter="20">
<el-col :span="14">
<DetailCard :title="cardTitle" :items="detailCardItems" />
</el-col>
<el-col :span="10">
<RunInfoCard v-bind="RunSuccessConfig" />
<RunInfoCard v-bind="RunFailedConfig" />
</el-col>
</el-row>
</template>
<script>
import DetailCard from '@/components/DetailCard/index'
import { toSafeLocalDateStr } from '@/utils/common'
import RunInfoCard from '../runinfocard/RunInfoCard'
export default {
name: 'TaskDetail',
components: {
DetailCard,
RunInfoCard
},
props: {
object: {
type: Object,
default: () => ({})
}
},
data() {
return {
RunSuccessConfig: {
icon: 'fa-info',
title: this.$t('jobcenter.Last run success hosts'),
content: [
{
hostname: 'linux',
result: 'api没有该数据==api没有该数据api没有该数据api没有该数据api没有该数据'
}
]
},
RunFailedConfig: {
icon: 'fa-info',
title: this.$t('jobcenter.Last run failed hosts'),
headerColor: 'danger',
content: [
{
hostname: 'window',
result: 'api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据'
}
]
},
taskData: {}
}
},
computed: {
cardTitle() {
return this.object.name
},
detailCardItems() {
return [
{
key: this.$t('jobcenter.ID'),
value: this.object.id
},
{
key: this.$t('common.Name'),
value: this.object.name
},
{
key: this.$t('jobcenter.DateCreated'),
value: toSafeLocalDateStr(this.object.date_created)
},
{
key: this.$t('jobcenter.TotalVersions'),
value: this.object.summary.total
},
{
key: this.$t('jobcenter.LatestVersion'),
value: this.object.latest_execution.adhoc_short_id
},
{
key: this.$t('jobcenter.LastRun'),
value: toSafeLocalDateStr(this.object.latest_execution.date_finished)
},
{
key: this.$t('jobcenter.TimeDelta'),
value: this.object.latest_execution.timedelta.toFixed(2) + 's'
},
{
key: this.$t('jobcenter.IsFinished'),
value: this.toChoicesDisplay(this.object.latest_execution.is_finished)
},
{
key: this.$t('jobcenter.IsSuccess'),
value: this.toChoicesDisplay(this.object.latest_execution.is_success)
},
{
key: this.$t('jobcenter.Contents'),
value: 'api 没有该数据'
}
]
}
},
mounted() {
// this.getTaskDetailData()
},
methods: {
// getTaskDetailData() {
// getTaskDetail(this.$route.params.id).then(data => {
// this.taskData = data
// this.flag = true
// })
// },
toChoicesDisplay(c) {
if (!c) {
return this.$t('jobcenter.No')
}
return this.$t('jobcenter.Yes')
}
}
}
</script>
<style lang="less" scoped>
</style>

View File

@@ -12,10 +12,16 @@ export default {
components: { components: {
ListTable ListTable
}, },
props: {
object: {
type: Object,
default: () => ({})
}
},
data() { data() {
return { return {
tableConfig: { tableConfig: {
url: `/api/v1/ops/adhoc-executions/?task=${this.$route.params.id}`, url: `/api/v1/ops/adhoc-executions/?task=${this.object.id}`,
columns: [ columns: [
'date_start', 'stat', 'ratio', 'is_finished', 'is_success', 'timedelta', 'adhoc_short_id', 'actions' 'date_start', 'stat', 'ratio', 'is_finished', 'is_success', 'timedelta', 'adhoc_short_id', 'actions'
], ],

View File

@@ -0,0 +1,54 @@
<template>
<GenericDetailPage :object.sync="TaskDetail" :active-menu.sync="config.activeMenu" v-bind="config" v-on="$listeners">
<keep-alive>
<component :is="config.activeMenu" :object="TaskDetail" />
</keep-alive>
</GenericDetailPage>
</template>
<script>
import { GenericDetailPage, TabPage } from '@/layout/components'
import TaskDetail from './TaskDetail'
import TaskHistory from './TaskHistory'
import TaskAdhoc from './TaskAdhoc'
export default {
components: {
GenericDetailPage,
TaskHistory,
TaskDetail,
TaskAdhoc,
TabPage
},
data() {
return {
TaskDetail: {},
config: {
activeMenu: 'TaskDetail',
submenu: [
{
title: this.$t('jobcenter.TaskDetail'),
name: 'TaskDetail'
},
{
title: this.$t('jobcenter.TaskVersions'),
name: 'TaskAdhoc'
},
{
title: this.$t('jobcenter.Execution'),
name: 'TaskHistory'
},
{
title: this.$t('jobcenter.LaskExecutionOutput'),
name: 'laskExecutionOutput'
}
],
hasRightSide: false
}
}
}
}
</script>
<style scoped>
</style>

View File

@@ -83,7 +83,12 @@ export default {
}, },
headerActions: { headerActions: {
hasCreate: false, hasCreate: false,
hasBulkDelete: false hasBulkDelete: false,
hasBulkUpdate: false,
hasExport: false,
hasImport: false,
hasRefresh: false
} }
} }
} }

View File

@@ -7,21 +7,21 @@ export default [
}, },
{ {
path: 'tasks/:id', path: 'tasks/:id',
component: () => import('@/views/jobcenter/TaskDetail'), component: () => import('@/views/jobcenter/TaskDetail/index'),
name: 'TaskDetail', name: 'TaskDetail',
hidden: true, hidden: true,
meta: { title: 'TaskDetail', activeMenu: '/ops/task' } meta: { title: 'TaskDetail', activeMenu: '/ops/task' }
}, },
{ {
path: 'adhoc/:id', path: 'adhoc/:id',
component: () => import('@/views/jobcenter/AdhocDetail'), component: () => import('@/views/jobcenter/TaskDetail/AdhocDetail/index'),
name: 'AdhocDetail', name: 'AdhocDetail',
hidden: true, hidden: true,
meta: { title: 'TaskDetail', activeMenu: '/ops/task' } meta: { title: 'TaskDetail', activeMenu: '/ops/task' }
}, },
{ {
path: 'executions/:id', path: 'executions/:id',
component: () => import('@/views/jobcenter/HistoryExecutionDetail'), component: () => import('@/views/jobcenter/TaskDetail/HistoryExecutionDetail/index'),
name: 'HistoryExecutionDetail', name: 'HistoryExecutionDetail',
hidden: true, hidden: true,
meta: { title: 'TaskDetail', activeMenu: '/ops/task' } meta: { title: 'TaskDetail', activeMenu: '/ops/task' }

View File

@@ -4,9 +4,9 @@
<ListTable :table-config="tableConfig" :header-actions="headerActions" /> <ListTable :table-config="tableConfig" :header-actions="headerActions" />
</el-col> </el-col>
<el-col :md="10" :sm="24"> <el-col :md="10" :sm="24">
<RelationCard v-bind="assetReletionConfig" /> <RelationCard type="primary" v-bind="assetReletionConfig" />
<RelationCard v-bind="nodeReletionConfig" /> <RelationCard type="info" style="margin-top: 15px" v-bind="nodeReletionConfig" />
<RelationCard v-bind="systemUserReletionConfig" /> <RelationCard type="warning" style="margin-top: 15px" v-bind="systemUserReletionConfig" />
</el-col> </el-col>
</el-row> </el-row>
</template> </template>

View File

@@ -4,8 +4,8 @@
<ListTable :table-config="tableConfig" :header-actions="headerActions" /> <ListTable :table-config="tableConfig" :header-actions="headerActions" />
</el-col> </el-col>
<el-col :md="10" :sm="24"> <el-col :md="10" :sm="24">
<RelationCard v-bind="userReletionConfig" /> <RelationCard type="primary" v-bind="userReletionConfig" />
<RelationCard v-bind="groupReletionConfig" /> <RelationCard type="info" style="margin-top: 15px" v-bind="groupReletionConfig" />
</el-col> </el-col>
</el-row> </el-row>
</template> </template>
@@ -78,10 +78,8 @@ export default {
} }
}, },
performAdd: (items) => { performAdd: (items) => {
console.log('item=====', items)
const relationUrl = `/api/v1/perms/asset-permissions-users-relations/` const relationUrl = `/api/v1/perms/asset-permissions-users-relations/`
const objectId = this.object.id const objectId = this.object.id
console.log('objectId====', objectId)
const data = items.map(v => { const data = items.map(v => {
return { return {
user: v.value, user: v.value,
@@ -110,7 +108,6 @@ export default {
return this.$axios.post(relationUrl, data) return this.$axios.post(relationUrl, data)
}, },
performDelete: (item) => { performDelete: (item) => {
console.log('item-group-==', item)
// const itemId = item.value // const itemId = item.value
const objectId = this.object.id const objectId = this.object.id
const relationUrl = `/api/v1/perms/asset-permissions-user-groups-relations/?assetpermission=${objectId}` const relationUrl = `/api/v1/perms/asset-permissions-user-groups-relations/?assetpermission=${objectId}`

View File

@@ -4,8 +4,8 @@
<ListTable :table-config="tableConfig" :header-actions="headerActions" /> <ListTable :table-config="tableConfig" :header-actions="headerActions" />
</el-col> </el-col>
<el-col :md="10" :sm="24"> <el-col :md="10" :sm="24">
<RelationCard v-bind="databaseAppReletionConfig" /> <RelationCard type="primary" v-bind="databaseAppReletionConfig" />
<RelationCard v-bind="systemUserReletionConfig" /> <RelationCard type="info" style="margin-top: 15px" v-bind="systemUserReletionConfig" />
</el-col> </el-col>
</el-row> </el-row>
</template> </template>
@@ -63,13 +63,24 @@ export default {
hasSearch: false, hasSearch: false,
hasRightActions: false hasRightActions: false
}, },
databaseAppPermissionDatabaseApp: [],
databaseAppPermissionSystemUser: [],
databaseAppReletionConfig: { databaseAppReletionConfig: {
icon: 'fa-info', icon: 'fa-info',
title: this.$t('perms.Add DatabaseApp to this permission'), title: this.$t('perms.Add DatabaseApp to this permission'),
objectsAjax: { objectsAjax: {
url: '/api/v1/applications/database-apps/' url: '/api/v1/applications/database-apps/'
},
hasObjectsId: this.object.databaseapp,
performAdd: (items) => {
console.log('this.object===', this.object)
const relationUrl = `/api/v1/perms/database-app-permissions-database-apps-relations/`
const objectId = this.object.id
const data = items.map(v => {
return {
databaseapppermission: objectId,
databaseapp: v.value
}
})
return this.$axios.post(relationUrl, data)
} }
}, },
hasObjectsId: this.object.system_users, hasObjectsId: this.object.system_users,
@@ -79,7 +90,6 @@ export default {
objectsAjax: { objectsAjax: {
url: '/api/v1/assets/system-users/', url: '/api/v1/assets/system-users/',
processResults(data) { processResults(data) {
console.log('data====', data)
let results = data.results let results = data.results
results = results.filter((item) => item.protocol === 'mysql').map((item) => { results = results.filter((item) => item.protocol === 'mysql').map((item) => {
return { label: item.name + '(' + item.username + ')', value: item.id } return { label: item.name + '(' + item.username + ')', value: item.id }

View File

@@ -36,7 +36,7 @@ export default {
is_active: this.object.is_active is_active: this.object.is_active
} }
], ],
url: `/api/v1/perms/database-app-permissions/${this.$route.params.id}/` url: `/api/v1/perms/database-app-permissions/${this.object.id}/`
} }
} }
}, },

View File

@@ -4,8 +4,8 @@
<ListTable :table-config="tableConfig" :header-actions="headerActions" /> <ListTable :table-config="tableConfig" :header-actions="headerActions" />
</el-col> </el-col>
<el-col :md="10" :sm="24"> <el-col :md="10" :sm="24">
<RelationCard v-bind="userReletionConfig" /> <RelationCard type="primary" v-bind="userReletionConfig" />
<RelationCard v-bind="groupReletionConfig" /> <RelationCard type="info" style="margin-top: 15px" v-bind="groupReletionConfig" />
</el-col> </el-col>
</el-row> </el-row>
@@ -114,6 +114,7 @@ export default {
// const itemId = item.value // const itemId = item.value
const objectId = this.object.id const objectId = this.object.id
const relationUrl = `/api/v1/perms/database-app-permissions-user-groups-relations/?databaseapppermission=${objectId}` const relationUrl = `/api/v1/perms/database-app-permissions-user-groups-relations/?databaseapppermission=${objectId}`
// const relationUrl = `/api/v1/perms/database-app-permissions-user-groups-relations/?databaseapppermission=${objectId}&usergroups=${itemId}`
return this.$axios.delete(relationUrl) return this.$axios.delete(relationUrl)
} }
} }

View File

@@ -27,24 +27,6 @@ export default {
}, },
data() { data() {
return { return {
flag: false,
config: {
activeMenu: 'detail',
submenu: [
{
title: this.$t('perms.RemoteAppPermissionDetail'),
name: 'detail'
},
{
title: this.$t('perms.UsersAndUserGroups'),
name: 'userAndUserGroups'
},
{
title: this.$t('perms.RemoteApp'),
name: 'remoteApp'
}
]
},
activeConfig: { activeConfig: {
icon: 'fa-info', icon: 'fa-info',
title: this.$t('perms.QuickModify'), title: this.$t('perms.QuickModify'),
@@ -54,7 +36,7 @@ export default {
is_active: true is_active: true
} }
], ],
url: `/api/v1/perms/remote-app-permissions/${this.$route.params.id}/` url: `/api/v1/perms/remote-app-permissions/${this.object.id}/`
} }
} }
}, },

View File

@@ -4,8 +4,8 @@
<ListTable :table-config="tableConfig" :header-actions="headerActions" /> <ListTable :table-config="tableConfig" :header-actions="headerActions" />
</el-col> </el-col>
<el-col :md="10" :sm="24"> <el-col :md="10" :sm="24">
<RelationCard v-bind="remoteAppReletionConfig" /> <RelationCard type="primary" v-bind="remoteAppReletionConfig" />
<RelationCard v-bind="systemUserReletionConfig" /> <RelationCard type="info" style="margin-top: 15px" v-bind="systemUserReletionConfig" />
</el-col> </el-col>
</el-row> </el-row>
</template> </template>
@@ -58,6 +58,21 @@ export default {
title: this.$t('perms.Add RemoteApp to this permission'), title: this.$t('perms.Add RemoteApp to this permission'),
objectsAjax: { objectsAjax: {
url: '/api/v1/applications/remote-apps/' url: '/api/v1/applications/remote-apps/'
},
hasObjectsId: this.object.remote_apps,
performAdd: (items) => {
const objectId = this.object.id
console.log('this.object===', this.object)
const relationUrl = `/api/v1/perms/remote-app-permissions/${objectId}/remote-apps/add/`
const remoteAppId = items.map(v => v.value)
const data = { remote_apps: remoteAppId }
return this.$axios.patch(relationUrl, data)
},
performDelete: (item) => {
const objectId = this.object.id
const relationUrl = `/api/v1/perms/remote-app-permissions/${objectId}/remote-apps/remove/`
const data = { remote_apps: [item.value] }
return this.$axios.patch(relationUrl, data)
} }
}, },
systemUserReletionConfig: { systemUserReletionConfig: {
@@ -76,21 +91,20 @@ export default {
}, },
hasObjectsId: this.object.system_users, hasObjectsId: this.object.system_users,
performAdd: (items) => { performAdd: (items) => {
const relationUrl = `/api/v1/perms/remote-app-permissions-system-users-relations/`
const objectId = this.object.id const objectId = this.object.id
const data = items.map(v => { const relationUrl = `/api/v1/perms/remote-app-permissions/${objectId}/`
return { const objectRelationSystemUsers = this.object.system_users
remoteapppermission: objectId, items.map(v => objectRelationSystemUsers.push(v.value))
systemuser: v.value const data = { system_users: objectRelationSystemUsers }
} return this.$axios.patch(relationUrl, data)
})
return this.$axios.post(relationUrl, data)
}, },
performDelete: (item) => { performDelete: (item) => {
const itemId = item.value
const objectId = this.object.id const objectId = this.object.id
const relationUrl = `/api/v1/perms/remote-app-permissions-system-users-relations/?remoteapppermission=${objectId}&systemuser=${itemId}` const relationUrl = `/api/v1/perms/remote-app-permissions/${objectId}/`
return this.$axios.delete(relationUrl) const objectOldRelationSystemUsers = this.object.system_users
const objectNewRelationSystemUsers = objectOldRelationSystemUsers.filter(v => v !== item.value)
const data = { system_users: objectNewRelationSystemUsers }
return this.$axios.patch(relationUrl, data)
} }
} }
} }

View File

@@ -4,8 +4,8 @@
<ListTable :table-config="tableConfig" :header-actions="headerActions" /> <ListTable :table-config="tableConfig" :header-actions="headerActions" />
</el-col> </el-col>
<el-col :md="10" :sm="24"> <el-col :md="10" :sm="24">
<RelationCard v-bind="userReletionConfig" /> <RelationCard type="primary" v-bind="userReletionConfig" />
<RelationCard v-bind="groupReletionConfig" /> <RelationCard type="info" style="margin-top: 15px" v-bind="groupReletionConfig" />
</el-col> </el-col>
</el-row> </el-row>
</template> </template>
@@ -20,10 +20,16 @@ export default {
ListTable, ListTable,
RelationCard RelationCard
}, },
props: {
object: {
type: Object,
default: () => ({})
}
},
data() { data() {
return { return {
tableConfig: { tableConfig: {
url: `/api/v1/perms/remote-app-permissions/${this.$route.params.id}/users/all/`, url: `/api/v1/perms/remote-app-permissions/${this.object.id}/users/all/`,
columns: [ columns: [
// 'user_display' // 'user_display'
], ],
@@ -47,8 +53,6 @@ export default {
hasSearch: false, hasSearch: false,
hasRightActions: false hasRightActions: false
}, },
remoteAppPermissionUser: [],
remoteAppPermissionUserGroup: [],
userReletionConfig: { userReletionConfig: {
icon: 'fa-user', icon: 'fa-user',
title: this.$t('perms.Add user to this permission'), title: this.$t('perms.Add user to this permission'),
@@ -62,6 +66,20 @@ export default {
const more = !!data.next const more = !!data.next
return { results: results, pagination: more, total: data.count } return { results: results, pagination: more, total: data.count }
} }
},
hasObjectsId: this.object.users,
performAdd: (items) => {
const objectId = this.object.id
const relationUrl = `/api/v1/perms/remote-app-permissions/${objectId}/users/add/`
const usersId = items.map(v => v.value)
const data = { users: usersId }
return this.$axios.patch(relationUrl, data)
},
performDelete: (item) => {
const objectId = this.object.id
const relationUrl = `/api/v1/perms/remote-app-permissions/${objectId}/users/remove/`
const data = { users: [item.value] }
return this.$axios.patch(relationUrl, data)
} }
}, },
groupReletionConfig: { groupReletionConfig: {
@@ -69,6 +87,23 @@ export default {
title: this.$t('perms.Add user group to this permission'), title: this.$t('perms.Add user group to this permission'),
objectsAjax: { objectsAjax: {
url: '/api/v1/users/groups/' url: '/api/v1/users/groups/'
},
hasObjectsId: this.object.user_groups,
performAdd: (items) => {
const objectId = this.object.id
const relationUrl = `/api/v1/perms/remote-app-permissions/${objectId}/`
const objectRelationUserGroups = this.object.user_groups
items.map(v => objectRelationUserGroups.push(v.value))
const data = { user_groups: objectRelationUserGroups }
return this.$axios.patch(relationUrl, data)
},
performDelete: (item) => {
const objectId = this.object.id
const relationUrl = `/api/v1/perms/remote-app-permissions/${objectId}/`
const objectOldRelationUserGroups = this.object.user_groups
const objectNewRelationUserGroups = objectOldRelationUserGroups.filter(v => v !== item.value)
const data = { user_groups: objectNewRelationUserGroups }
return this.$axios.patch(relationUrl, data)
} }
} }
} }

View File

@@ -39,17 +39,6 @@ export default {
name: 'RemoteAppPermissionRemoteApp' name: 'RemoteAppPermissionRemoteApp'
} }
] ]
},
activeConfig: {
icon: 'fa-info',
title: this.$t('perms.QuickModify'),
content: [
{
name: this.$t('perms.Active'),
is_active: true
}
],
url: `/api/v1/perms/remote-app-permissions/${this.$route.params.id}/`
} }
} }
}, },

View File

@@ -2462,6 +2462,11 @@ code-point-at@^1.0.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
codemirror@^5.22.0:
version "5.53.2"
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.53.2.tgz#9799121cf8c50809cca487304e9de3a74d33f428"
integrity sha512-wvSQKS4E+P8Fxn/AQ+tQtJnF1qH5UOlxtugFLpubEZ5jcdH2iXTVinb+Xc/4QjshuOxRm4fUsU2QPF1JJKiyXA==
collection-visit@^1.0.0: collection-visit@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0"
@@ -9469,6 +9474,13 @@ vm-browserify@^1.0.1:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
vue-codemirror-lite@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/vue-codemirror-lite/-/vue-codemirror-lite-1.0.4.tgz#48a5cd7d17c0914503c8cd9d9b56b438e49c3410"
integrity sha1-SKXNfRfAkUUDyM2dm1a0OOScNBA=
dependencies:
codemirror "^5.22.0"
vue-cookie@^1.1.4: vue-cookie@^1.1.4:
version "1.1.4" version "1.1.4"
resolved "https://registry.npm.taobao.org/vue-cookie/download/vue-cookie-1.1.4.tgz#b8b46d112bda9f93a2f47017c2ed5282d2064fda" resolved "https://registry.npm.taobao.org/vue-cookie/download/vue-cookie-1.1.4.tgz#b8b46d112bda9f93a2f47017c2ed5282d2064fda"
@@ -9918,6 +9930,16 @@ xtend@^4.0.0, xtend@~4.0.1:
version "4.0.2" version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
xterm-addon-fit@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/xterm-addon-fit/-/xterm-addon-fit-0.3.0.tgz#341710741027de9d648a9f84415a01ddfdbbe715"
integrity sha512-kvkiqHVrnMXgyCH9Xn0BOBJ7XaWC/4BgpSWQy3SueqximgW630t/QOankgqkvk11iTOCwWdAY9DTyQBXUMN3lw==
xterm@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.5.0.tgz#c7fd145c6cf91c9f2ef07011a9b35026cf4bfecc"
integrity sha512-4t12tsvtYnv13FBJwewddxdI/j4kSonmbQQv50j34R/rPIFbUNGtptbprmuUlTDAKvHLMDZ/Np2XcpNimga/HQ==
y18n@^3.2.1: y18n@^3.2.1:
version "3.2.1" version "3.2.1"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"