Skip to content

Commit

Permalink
feat(manager): service management
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Jun 13, 2024
1 parent ac2b8c6 commit e2e970b
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 30 deletions.
23 changes: 23 additions & 0 deletions packages/client/app/styles/element.scss
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,29 @@ html.dark .el-popper.is-dark {
}
}

.el-dialog {
.el-dialog__body {
> :first-child {
margin-top: 0;
}

> :last-child {
margin-bottom: 0;
}

p {
margin: 0.5rem 0;
}
}

.el-dialog__footer {
display: flex;
justify-content: flex-end;
align-items: center;
font-size: 0.9em;
}
}

.el-table__body-wrapper,
.el-table__footer-wrapper,
.el-table__header-wrapper {
Expand Down
14 changes: 13 additions & 1 deletion packages/components/client/k-comment.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const icon = computed(() => {
}
.k-comment {
padding: 1px 1.5rem;
padding: 1rem 1.5rem;
margin: 1rem 0;
border-left-width: 4px;
border-left-style: solid;
Expand All @@ -65,6 +65,18 @@ const icon = computed(() => {
@include apply-color(success);
@include apply-color(danger);
> :nth-child(2) { // 1st is icon
margin-top: 0;
}
> :last-child {
margin-bottom: 0;
}
:deep(p) {
margin: 0.5rem 0;
}
:deep(a) {
text-decoration: underline;
Expand Down
4 changes: 2 additions & 2 deletions plugins/manager/client/dialogs/forks.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@
</tr>
</table>
<template #footer>
<div class="left">
<div>
<template v-if="plugins.forks[ctx.manager.dialogFork!]?.length">
此插件目前存在 {{ plugins.forks[ctx.manager.dialogFork!]?.length }} 份配置。
</template>
<template v-else>
此插件尚未被配置。
</template>
</div>
<div class="right">
<div class="grow-1">
<el-button @click.stop="configure()">添加新配置</el-button>
</div>
</template>
Expand Down
55 changes: 36 additions & 19 deletions plugins/manager/client/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { clone, Context, Dict, message, remove, router, Schema, send, Service } from '@cordisjs/client'
import { computed, reactive, ref, Ref, watch } from 'vue'
import type { Data, EntryData } from '../src'
import type { Data, EntryData, InjectInfo, ServiceInfo } from '../src'
import { hasSchema } from './utils'
import Settings from './components/index.vue'
import Forks from './dialogs/forks.vue'
import Select from './dialogs/select.vue'
import Rename from './dialogs/rename.vue'
import Group from './dialogs/group.vue'
import Main from './routes/main.vue'
import Config from './routes/config.vue'
import Remove from './dialogs/remove.vue'
import MainPage from './routes/main.vue'
import ConfigPage from './routes/config.vue'
import ServicePage from './routes/service.vue'

import './index.scss'
import './icons'
Expand All @@ -34,10 +35,7 @@ export interface Node extends EntryData {
children?: Node[]
}

interface DepInfo {
required: boolean
provider?: string[]
}
interface DepInfo extends ServiceInfo, InjectInfo {}

export interface EnvInfo {
impl: string[]
Expand Down Expand Up @@ -215,18 +213,27 @@ export default class Manager extends Service {
this.subroute({
path: '',
name: '概览',
component: Main,
component: MainPage,
})

this.subroute({
path: 'config',
name: '配置',
component: Config,
component: ConfigPage,
hidden: ({ name }) => {
return !hasSchema(this.data.value.packages[name]?.runtime?.schema)
},
})

this.subroute({
path: 'service',
name: '服务',
component: ServicePage,
hidden: ({ name }) => {
return !this.data.value.packages[name]?.runtime
},
})

this.ctx.menu('config.tree', [{
id: 'config.tree.toggle',
type: ({ config }) => config.tree?.disabled ? '' : this.type.value,
Expand Down Expand Up @@ -397,9 +404,8 @@ export default class Manager extends Service {
}

subroute(options: SubRoute) {
const caller = this[Context.current]
options.component = caller.wrapComponent(options.component)
return caller.effect(() => {
options.component = this.ctx.wrapComponent(options.component)
return this.ctx.effect(() => {
this.routes.push(options)
return () => remove(this.routes, options)
})
Expand Down Expand Up @@ -442,13 +448,13 @@ export default class Manager extends Service {

const result: EnvInfo = { impl: [], using: {} }

// check implementations
// FIXME check implementations
for (const name of local.manifest.service?.implements || []) {
result.impl.push(name)
}

// check services
const setService = (name: string, required: boolean) => {
const setService = (name: string, info: InjectInfo) => {
let provider = this.data.value.services[name]?.root
let node = entry
while (node) {
Expand All @@ -463,13 +469,24 @@ export default class Manager extends Service {
}
break
}
result.using[name] = { required, provider }
result.using[name] = { ...info, ...provider }
}
for (const name of local.runtime.required ?? []) {
setService(name, true)

for (const [name, info] of Object.entries(local.runtime.inject ?? {})) {
setService(name, info)
}
for (const name of local.runtime?.optional ?? []) {
setService(name, false)

if (Array.isArray(entry.inject)) {
for (const name of entry.inject) {
setService(name, { required: true })
}
} else if (entry.inject) {
for (const name of entry.inject.required || []) {
setService(name, { required: true })
}
for (const name of entry.inject.optional || []) {
setService(name, { required: false })
}
}

// check reusability
Expand Down
80 changes: 72 additions & 8 deletions plugins/manager/client/routes/service.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,90 @@
<k-comment
v-for="({ required, location }, name) in env.using" :key="name"
:type="location ? 'success' : required ? 'warning' : 'primary'">
<p>
{{ required ? '必需' : '可选' }}服务 {{ name }} {{ location ? '已加载' : '未加载' }}。
</p>
<p>{{ required ? '必需' : '可选' }}服务 {{ name }} {{ location ? '已加载' : '未加载' }}。</p>
</k-comment>
<el-button>添加依赖项</el-button>
<el-button @click="showAddDependency = true">添加依赖项</el-button>
<h2>隔离域</h2>
<k-comment
v-for="(label, name) in currentEntry.isolate" :key="name"
:type="getService(name, label) ? 'success' : 'primary'"
>
<p>该插件为服务 {{ name }} 配置了{{ label ? `名为 ${label} 的共享` : '私有' }}隔离域。</p>
</k-comment>
<p>该插件当前未配置隔离域。</p>
<el-button>创建隔离域</el-button>
<el-button @click="showCreateIsolate = true">创建隔离域</el-button>
</k-content>

<el-dialog
destroy-on-close
v-model="showAddDependency"
title="添加依赖项"
>
<p><el-input ref="inputEl" v-model="input" @keydown.enter.stop.prevent="addDependency"/></p>
<template #footer>
<el-checkbox v-model="isRequired">必需依赖</el-checkbox>
<div class="grow-1">
<el-button @click="showAddDependency = false">取消</el-button>
<el-button type="primary" @click="addDependency">确定</el-button>
</div>
</template>
</el-dialog>

<el-dialog
destroy-on-close
v-model="showCreateIsolate"
title="创建隔离域"
>
<p><el-input ref="inputEl" v-model="input"/></p>
<p><el-input ref="inputEl" v-model="label" placeholder="留空时将创建私有隔离域"/></p>
<template #footer>
<el-button @click="showCreateIsolate = false">取消</el-button>
<el-button type="primary" @click="createIsolate">确定</el-button>
</template>
</el-dialog>
</template>

<script lang="ts" setup>
import { computed } from 'vue'
import { router, useContext } from '@cordisjs/client'
import { computed, ref } from 'vue'
import { router, send, useContext } from '@cordisjs/client'
const ctx = useContext()
const showAddDependency = ref(false)
const showCreateIsolate = ref(false)
const isRequired = ref(false)
const input = ref('')
const label = ref('')
const currentEntry = computed(() => ctx.manager.currentEntry!)
const local = computed(() => ctx.manager.data.value.packages[currentEntry.value.name])
const services = computed(() => ctx.manager.data.value.services)
const env = computed(() => ctx.manager.getEnvInfo(currentEntry.value)!)
function getService(name: string, label: string | true) {
if (!services.value[name]) return
if (label === true) {
return services.value[name].local[currentEntry.value.id]?.location
} else {
return services.value[name].global[label]?.location
}
}
function addDependency() {
send('manager.config.update', {
id: currentEntry.value.id,
// TODO
// inject: [],
})
}
function createIsolate() {
send('manager.config.update', {
id: currentEntry.value.id,
isolate: {
...currentEntry.value.isolate,
[input.value]: label.value || true,
},
})
}
</script>

0 comments on commit e2e970b

Please sign in to comment.