Skip to content

Commit

Permalink
feat(manager): support better-grained display for isolated services
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Jun 18, 2022
1 parent 54befd0 commit d4712bf
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 97 deletions.
2 changes: 1 addition & 1 deletion plugins/frontend/manager/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default (ctx: Context) => {
icon: 'cog',
order: 630,
authority: 4,
fields: ['config', 'packages', 'services', 'dependencies'],
fields: ['config', 'packages', 'dependencies'],
component: Settings,
})

Expand Down
50 changes: 27 additions & 23 deletions plugins/frontend/manager/client/settings/plugin.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,20 @@
</template>
<template v-if="!current.disabled">
<k-button solid type="error" @click="execute('unload')">停用插件</k-button>
<k-button solid :disabled="env.disabled" @click="execute('reload')">重载配置</k-button>
<k-button solid @click="execute('reload')">重载配置</k-button>
</template>
<template v-else-if="name">
<k-button solid :disabled="env.disabled" :type="env.type" @click="execute('reload')">启用插件</k-button>
<k-button solid :type="type" @click="execute('reload')">启用插件</k-button>
<k-button solid @click="execute('unload')">保存配置</k-button>
</template>
</h1>

<template v-if="name">
<!-- reusability -->
<k-comment v-if="local.id && !local.forkable && current.disabled" type="warning">
此插件已在运行且不可重用,启用可能会导致非预期的问题。
</k-comment>

<!-- latest -->
<k-comment v-if="hasUpdate">
当前的插件版本不是最新,<router-link to="/dependencies">点击前往依赖管理</router-link>。
Expand All @@ -35,21 +40,21 @@

<!-- impl -->
<template v-for="name in env.impl" :key="name">
<k-comment v-if="name in store.services && !local.id" type="warning">
<k-comment v-if="deps[name] && current.disabled" type="warning">
此插件将会提供 {{ name }} 服务,但此服务已被其他插件实现。
</k-comment>
<k-comment v-else :type="local.id ? 'success' : 'primary'">
此插件{{ local.id ? '提供了' : '将会提供' }} {{ name }} 服务。
<k-comment v-else :type="current.disabled ? 'primary' : 'success'">
此插件{{ current.disabled ? '将会提供' : '提供了' }} {{ name }} 服务。
</k-comment>
</template>

<!-- using -->
<k-comment
v-for="({ fulfilled, required, available, name }) in env.using" :key="name"
:type="fulfilled ? 'success' : required ? 'error' : 'primary'">
v-for="({ required, available }, name) in env.using" :key="name"
:type="deps[name] ? 'success' : required ? 'warning' : 'primary'">
{{ required ? '必需' : '可选' }}服务:{{ name }}
{{ fulfilled ? '(已加载)' : '(未加载,启用下列任一插件可实现此服务)' }}
<template v-if="!fulfilled" #body>
{{ deps[name] ? '(已加载)' : '(未加载,启用下列任一插件可实现此服务)' }}
<template v-if="!deps[name]" #body>
<ul>
<li v-for="name in available">
<k-dep-link :name="name"></k-dep-link> (点击{{ name in store.packages ? '配置' : '添加' }})
Expand All @@ -58,19 +63,6 @@
</template>
</k-comment>

<!-- dep -->
<k-comment
v-for="({ fulfilled, required, local, name }) in env.deps" :key="name"
:type="fulfilled ? 'success' : required ? 'error' : 'primary'">
{{ required ? '必需' : '可选' }}依赖:<k-dep-link :name="name"></k-dep-link>
({{ local ? `${fulfilled ? '已' : '未'}启用` : '未安装,点击添加' }})
</k-comment>

<!-- reusability -->
<k-comment v-if="local.id && !local.forkable && current.disabled" type="warning">
此插件已在运行且不可重用,启用可能会导致非预期的问题。
</k-comment>

<!-- schema -->
<k-comment v-if="!local.schema" type="warning">
此插件未声明配置项,这可能并非预期行为{{ hint }}。
Expand All @@ -89,7 +81,6 @@
import { send, store, clone, router } from '@koishijs/client'
import { computed, ref, watch } from 'vue'
import { getMixedMeta } from '../utils'
import { envMap, Tree } from './utils'
import KAlias from './alias.vue'
import KDepLink from './dep-link.vue'
Expand All @@ -104,6 +95,19 @@ watch(() => props.current.config, (value) => {
config.value = clone(value)
}, { immediate: true })
const deps = computed(() => props.current.parent.config.$deps)
const type = computed(() => {
if (env.value.warning && props.current.disabled) return 'warning'
for (const name in env.value.using) {
if (deps.value[name]) {
if (env.value.impl.includes(name)) return 'warning'
} else {
if (env.value.using[name].required) return 'warning'
}
}
})
const name = computed(() => {
const { label, target: temporary } = props.current
const shortname = temporary || label
Expand Down
60 changes: 16 additions & 44 deletions plugins/frontend/manager/client/settings/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,17 @@ import { Dict } from 'koishi'
import { computed } from 'vue'
import { MarketProvider } from '@koishijs/plugin-manager'
import { router, store } from '@koishijs/client'
import { getMixedMeta } from '../utils'
import {} from '@koishijs/cli'

interface DepInfo {
name: string
required: boolean
fulfilled: boolean
}

interface ServiceDepInfo extends DepInfo {
available?: string[]
}

interface PluginDepInfo extends DepInfo {
local?: boolean
available: string[]
}

export interface EnvInfo {
impl: string[]
deps: Dict<PluginDepInfo>
using: Dict<ServiceDepInfo>
disabled?: boolean
type?: 'warning'
using: Dict<DepInfo>
warning?: boolean
console?: boolean
}

Expand All @@ -42,18 +30,14 @@ function getEnvInfo(name: string) {
return
}

const fulfilled = name in store.services
if (required && !fulfilled) result.disabled = true
result.using[name] = { name, required, fulfilled }
if (!fulfilled) {
result.using[name].available = Object.values(store.market || {})
.filter(data => isAvailable(name, data))
.map(data => data.name)
}
const available = Object.values(store.market || {})
.filter(data => isAvailable(name, data))
.map(data => data.name)
result.using[name] = { required, available }
}

const local = store.packages[name]
const result: EnvInfo = { impl: [], using: {}, deps: {} }
const result: EnvInfo = { impl: [], using: {} }

// check implementations
for (const name of local.manifest.service.implements) {
Expand All @@ -69,27 +53,14 @@ function getEnvInfo(name: string) {
setService(name, false)
}

// check dependencies
for (const name in local.peerDependencies) {
if (!name.includes('koishi-plugin-') || !name.startsWith('@koishijs/plugin-')) continue
if (name === '@koishijs/plugin-console') continue
const available = name in store.packages
const fulfilled = !!store.packages[name]?.id
if (!fulfilled) result.disabled = true
result.deps[name] = { name, required: true, fulfilled, local: available }
for (const impl of getMixedMeta(name).manifest.service.implements) {
delete result.using[impl]
}
}

// check reusability
if (local.id && !local.forkable) {
result.type = 'warning'
result.warning = true
}

// check schema
if (!local.schema) {
result.type = 'warning'
result.warning = true
}

return result
Expand All @@ -109,25 +80,26 @@ export interface Tree {
path: string
config?: any
target?: string
parent?: Tree
disabled?: boolean
children?: Tree[]
}

function getTree(prefix: string, plugins: any): Tree[] {
function getTree(parent: Tree, plugins: any): Tree[] {
const trees: Tree[] = []
for (let key in plugins) {
if (key.startsWith('$')) continue
const config = plugins[key]
const node = { config } as Tree
const node = { config, parent } as Tree
if (key.startsWith('~')) {
node.disabled = true
key = key.slice(1)
}
node.label = key.split(':', 1)[0]
node.alias = key.slice(node.label.length + 1)
node.id = node.path = prefix + key
node.id = node.path = parent.path + (parent.path ? '/' : '') + key
if (key.startsWith('group:')) {
node.children = getTree(node.path + '/', config)
node.children = getTree(node, config)
}
trees.push(node)
}
Expand All @@ -141,8 +113,8 @@ export const plugins = computed(() => {
path: '',
alias: '',
config: store.config.plugins,
children: getTree('', store.config.plugins),
}
root.children = getTree(root, store.config.plugins)
const paths: Dict<Tree> = {
'@global': {
label: '全局设置',
Expand Down
5 changes: 0 additions & 5 deletions plugins/frontend/manager/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@ import BotProvider from './bots'
import MarketProvider from './market'
import PackageProvider from './packages'
import AdapterProvider from './protocols'
import ServiceProvider from './services'
import ConfigWriter from './writer'

export * from './bots'
export * from './market'
export * from './packages'
export * from './protocols'
export * from './services'
export * from './writer'

export {
Expand All @@ -21,7 +19,6 @@ export {
MarketProvider,
PackageProvider,
AdapterProvider,
ServiceProvider,
ConfigWriter,
}

Expand All @@ -33,7 +30,6 @@ declare module '@koishijs/plugin-console' {
market: MarketProvider
packages: PackageProvider
protocols: AdapterProvider
services: ServiceProvider
config: ConfigWriter
}
}
Expand All @@ -58,7 +54,6 @@ export function apply(ctx: Context, config: Config) {
ctx.plugin(MarketProvider, config)
ctx.plugin(AdapterProvider)
ctx.plugin(PackageProvider)
ctx.plugin(ServiceProvider)
ctx.plugin(ConfigWriter)

ctx.console.addEntry({
Expand Down
24 changes: 0 additions & 24 deletions plugins/frontend/manager/src/services.ts

This file was deleted.

0 comments on commit d4712bf

Please sign in to comment.