Skip to content

Commit

Permalink
feat(webui): setup plugin list
Browse files Browse the repository at this point in the history
add element-plus as dep
  • Loading branch information
shigma committed Mar 5, 2021
1 parent 2ec250f commit b338c44
Show file tree
Hide file tree
Showing 7 changed files with 218 additions and 22 deletions.
9 changes: 5 additions & 4 deletions packages/plugin-webui/client/app.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<template>
<h2>All plugins:</h2>
<ul>
<plugin-view :data="data" v-for="(data, index) in plugins" :key="index"/>
</ul>
<el-card header="插件">
<ul class="plugin-list">
<plugin-view :data="data" v-for="(data, index) in plugins" :key="index"/>
</ul>
</el-card>
</template>

<script setup lang="ts">
Expand Down
104 changes: 104 additions & 0 deletions packages/plugin-webui/client/components/collapse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { style, emit, store, restore, Types } from '../../utils/transition'
import {} from 'vue'

interface Props {
direction: Types.Direction
duration: number
timingFunction: string
}

export default {
functional: true,

props: {
direction: {
type: String,
default: 'vertical',
},
duration: {
type: Number,
default: 0.3,
},
timingFunction: {
type: String,
default: 'ease-in-out',
},
},

render(createElement, {
props: {
direction,
duration,
timingFunction,
},
listeners,
children,
}) {
let length: Types.Length
let paddingEnd: Types.PaddingEnd
let paddingStart: Types.PaddingStart
let scrollLength: Types.ScrollLength

if (direction === 'horizontal') {
length = 'width'
scrollLength = 'scrollWidth'
paddingStart = 'paddingLeft'
paddingEnd = 'paddingRight'
} else {
length = 'height'
scrollLength = 'scrollHeight'
paddingStart = 'paddingTop'
paddingEnd = 'paddingBottom'
}

const transition = style([
length, paddingEnd, paddingStart,
], duration, timingFunction)

return createElement('transition', {
attrs: { css: false },
on: {
beforeEnter(el: HTMLElement) {
emit(listeners, 'before-enter', el)
store(el, ['transition', paddingEnd, paddingStart])
el.style.transition = transition
el.style[paddingStart] = '0'
el.style[paddingEnd] = '0'
el.style[length] = '0'
},
enter(el: HTMLElement, done: Function) {
el.dataset.overflow = el.style.overflow
restore(el, [paddingEnd, paddingStart])
el.style[length] = el[scrollLength] ? el[scrollLength] + 'px' : ''
el.style.overflow = 'hidden'
setTimeout(done, 1000 * duration)
},
afterEnter(el: HTMLElement) {
el.style[length] = ''
restore(el, ['overflow', 'transition'])
emit(listeners, 'after-enter', el)
},
beforeLeave(el: HTMLElement) {
emit(listeners, 'before-leave', el)
store(el, ['overflow', 'transition', paddingEnd, paddingStart])
el.style[length] = el[scrollLength] + 'px'
el.style.overflow = 'hidden'
},
leave(el: HTMLElement, done: Function) {
if (el[scrollLength] !== 0) {
el.style.transition = transition
el.style[length] = '0'
el.style[paddingEnd] = '0'
el.style[paddingStart] = '0'
}
setTimeout(done, 1000 * duration)
},
afterLeave(el: HTMLElement) {
el.style[length] = ''
restore(el, [paddingEnd, paddingStart, 'overflow', 'transition'])
emit(listeners, 'after-leave', el)
},
},
}, children)
},
}
66 changes: 55 additions & 11 deletions packages/plugin-webui/client/components/plugin-view.vue
Original file line number Diff line number Diff line change
@@ -1,28 +1,72 @@
<template>
<li>
<span :class="data.sideEffect ? 'indisposable' : 'disposable'">{{ data.name }}</span>
<ul v-if="data.children.length">
<plugin-view :data="data" v-for="(data, index) in data.children" :key="index" />
</ul>
<li class="plugin-view" :class="{ 'has-children': data.children.length }">
<i class="el-icon-caret-right" :class="{ show: data.show }"/>
<span class="plugin-item" @click="data.show = !data.show" :class="state">{{ data.name }}</span>
<el-collapse-transition v-if="data.children.length">
<ul class="plugin-list" v-show="data.show">
<plugin-view :data="data" v-for="(data, index) in data.children" :key="index" />
</ul>
</el-collapse-transition>
</li>
</template>

<script setup lang="ts">
import { defineProps } from 'vue'
import { computed, defineProps } from 'vue'
const { data } = defineProps(['data'])
const state = computed(() => {
return data.sideEffect ? 'side-effect' : 'normal'
})
</script>

<style lang="scss" scoped>
<style lang="scss">
@import '../index.scss';
:not(.has-children) > .el-icon-caret-right {
font-size: 16px !important;
width: 10px;
padding-left: 4px;
&::before {
content: "";
}
}
.el-icon-caret-right {
margin-left: -1rem;
margin-right: 1rem;
transition: 0.3s ease;
font-size: 14px !important;
vertical-align: middle !important;
}
.el-icon-caret-right.show {
transform: rotate(90deg);
}
.plugin-item {
line-height: 1.6;
user-select: none;
.has-children > & {
cursor: pointer;
}
&.normal {
color: $default;
}
.disposable {
color: green;
&.side-effect {
color: $error;
}
}
.indisposable {
color: red;
.plugin-list {
list-style-type: none;
}
</style>
23 changes: 23 additions & 0 deletions packages/plugin-webui/client/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
$text: #303133;
$text2: #606266;
$text3: #909399;
$border1: #dcdfe6;
$border2: #ebe7ed;
$border3: #ebeef5;
$border4: #f2f6fc;
$default: #409eff;
$success: #67c23a;
$error: #F56C6C;
$warning: #E6A23C;

.el-card {
max-width: 960px;
margin: 0 auto;
border-radius: 1rem;

.el-card__header {
font-size: 1.25rem;
font-weight: bolder;
padding: 1rem 1.5rem;
}
}
15 changes: 14 additions & 1 deletion packages/plugin-webui/client/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
import { createApp } from 'vue'
import { ElCard, ElCollapseTransition } from 'element-plus'
import App from './app.vue'

createApp(App).mount('#app')
// for el-collapse-transition
import 'element-plus/lib/theme-chalk/base.css'
import 'element-plus/lib/theme-chalk/el-icon.css'
import 'element-plus/lib/theme-chalk/el-card.css'

import './index.scss'

const app = createApp(App)

app.use(ElCard)
app.use(ElCollapseTransition)

app.mount('#app')
1 change: 1 addition & 0 deletions packages/plugin-webui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"koishi-core": "^3.0.0"
},
"dependencies": {
"element-plus": "^1.0.2-beta.33",
"vue": "^3.0.7"
},
"devDependencies": {
Expand Down
22 changes: 16 additions & 6 deletions packages/plugin-webui/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@ export interface Config {
server?: string
}

export interface PluginData {
name: string
sideEffect: boolean
export interface PluginData extends Plugin.Meta {
children: PluginData[]
dependencies: string[]
}

export const name = 'webui'
Expand All @@ -40,12 +39,23 @@ export function apply(ctx: Context, config: Config = {}) {
ctx.app.vite = vite
})

function* getDeps(state: Plugin.State): Generator<string> {
for (const dep of state.dependencies) {
if (dep.name) {
yield dep.name
} else {
yield* getDeps(dep)
}
}
}

function traverse(plugin: Plugin): PluginData[] {
const state = ctx.app.registry.get(plugin)
const children = state.children.flatMap(traverse, 1)
if (typeof plugin === 'function' || !plugin?.name) return children
const { name } = plugin, { sideEffect } = state
return [{ name, sideEffect, children }]
const { name, sideEffect } = state
if (!name) return children
const dependencies = [...new Set(getDeps(state))]
return [{ name, sideEffect, children, dependencies }]
}

ctx.router.get('/plugins', (ctx) => {
Expand Down

0 comments on commit b338c44

Please sign in to comment.