Skip to content

Commit

Permalink
feat(manager): support multiple installer
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Feb 2, 2022
1 parent ae51131 commit 45112c6
Show file tree
Hide file tree
Showing 14 changed files with 303 additions and 217 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<form class="schema-form">
<slot name="header"></slot>
<k-schema :schema="schema" :disabled="disabled" v-model="config"></k-schema>
<k-schema v-if="schema" :schema="schema" :disabled="disabled" v-model="config"></k-schema>
<slot name="footer"></slot>
</form>
</template>
Expand Down
1 change: 1 addition & 0 deletions plugins/frontend/console/client/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ declare module '~/client' {
order?: number
fields?: readonly (keyof Console.Services)[]
position?: 'top' | 'bottom' | 'hidden'
badge?: () => string | number
}

export interface PageOptions extends RouteMetaExtension {
Expand Down
17 changes: 17 additions & 0 deletions plugins/frontend/console/client/layout/sidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<router-link class="k-menu-item" :to="{ path, query: queries[path] }">
<k-icon :name="meta.icon"/>
{{ name }}
<span class="badge" v-if="meta.badge?.()">{{ meta.badge?.() }}</span>
</router-link>
</template>
</div>
Expand All @@ -18,6 +19,7 @@
<router-link class="k-menu-item" :to="{ path, query: queries[path] }">
<k-icon :name="meta.icon"/>
{{ name }}
<span class="badge" v-if="meta.badge?.()">{{ meta.badge?.() }}</span>
</router-link>
</template>
</div>
Expand Down Expand Up @@ -102,6 +104,21 @@ aside.layout-aside {
vertical-align: -4px;
}
.k-menu-item .badge {
position: absolute;
border-radius: 1rem;
background-color: var(--error);
top: 50%;
right: 1.5rem;
transform: translateY(-50%);
line-height: 1;
padding: 4px 8px;
font-size: 0.875rem;
font-weight: normal;
color: var(--bg0);
transition: 0.3s ease;
}
.top {
margin-top: 0.5rem;
}
Expand Down
88 changes: 35 additions & 53 deletions plugins/frontend/manager/client/dependencies/index.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<template>
<nav>
<k-button solid>下载全部</k-button>
</nav>
<k-card class="frameless">
<table class="table-header">
<k-card class="page-deps">
<div class="operation">
<k-button solid @click="install" :disabled="!overrideCount">更新依赖</k-button>
</div>
<table class="table-body">
<colgroup>
<col width="auto">
<col width="160px">
<col width="200px">
<col width="200px">
</colgroup>
<thead>
Expand All @@ -16,79 +16,61 @@
<th>目标版本</th>
</tr>
</thead>
<tbody>
<package-view v-for="name in names" :key="name" :name="name"></package-view>
</tbody>
</table>
<el-scrollbar>
<table class="table-body">
<colgroup>
<col width="auto">
<col width="160px">
<col width="200px">
</colgroup>
<tbody>
<template v-for="name in names" :key="name">
<tr>
<td>{{ name }}</td>
<td>{{ store.packages[name]?.version || '-' }}</td>
<td>
<el-select v-model="config.override[name]">
<el-option
v-for="({ version }, index) in store.market[name].versions"
:key="version" :label="version + (index ? '' : ' (最新)')" :value="version"
></el-option>
</el-select>
</td>
</tr>
</template>
</tbody>
</table>
</el-scrollbar>
{{ config.override }}
</k-card>
</template>

<script lang="ts" setup>
import { computed } from 'vue'
import { store } from '~/client'
import { config } from '../utils'
import { store, send } from '~/client'
import { config, state, overrideCount } from '../utils'
import { ElMessage } from 'element-plus'
import PackageView from './package.vue'
const names = computed(() => {
const data = Object.values(store.packages).filter(item => !item.workspace && store.market[item.name]).map(item => item.name)
for (const key in config.override) {
if (!data.includes(key) && store.market[key]) data.push(key)
if (!data.includes(key) && store.market[key] && config.override[key]) data.push(key)
}
return data.sort((a, b) => a > b ? 1 : -1)
})
async function install() {
state.downloading = true
try {
const code = await send('install', config.override)
if (code === 0) {
ElMessage.success('安装成功!')
} else {
ElMessage.error('安装失败!')
}
} catch (err) {
ElMessage.error('安装超时!')
} finally {
state.downloading = false
}
}
</script>

<style lang="scss">
.route-versions nav {
margin-top: 2rem;
padding: 0 2rem;
.right {
float: right;
}
}
.route-versions .k-card {
position: absolute;
bottom: 0;
height: calc(100vh - 8rem);
left: var(--aside-width);
right: 0;
.page-deps {
height: calc(100vh - 4rem);
.k-card-body {
height: 100%;
display: flex;
flex-direction: column;
}
table {
tr:first-child {
border-top: none;
}
.operation {
margin-bottom: 1.5rem;
}
tbody {
Expand Down
63 changes: 63 additions & 0 deletions plugins/frontend/manager/client/dependencies/overlay.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<template>
<transition name="fade">
<div class="loading-overlay" v-if="!state.downloading">
<div class="spinner">
<svg class="circular" viewBox="25 25 50 50">
<circle class="path" cx="50" cy="50" r="20" fill="none"></circle>
</svg>
<p>正在更新依赖……</p>
</div>
</div>
</transition>
</template>

<script lang="ts" setup>
import { state } from '../utils'
</script>

<style lang="scss">
.loading-overlay {
position: fixed;
left: 0;
bottom: 0;
top: 0;
right: 0;
z-index: 1000;
transition: 0.4s opacity ease;
user-select: none;
background-color: #0009;
.spinner {
top: 50%;
width: 100%;
text-align: center;
position: absolute;
transform: translateY(-50%);
p {
color: var(--bg0);
margin-bottom: 0;
}
svg {
display: inline;
height: 2.5rem;
width: 2.5rem;
animation: loading-rotate 2s linear infinite;
circle {
animation: loading-dash 1.5s ease-in-out infinite;
stroke-dasharray: 90, 150;
stroke-dashoffset: 0;
stroke-width: 3;
stroke: var(--el-color-primary);
stroke-linecap: round;
}
}
}
}
</style>
49 changes: 49 additions & 0 deletions plugins/frontend/manager/client/dependencies/package.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<template>
<tr>
<td>{{ name }}</td>
<td>{{ current || '-' }}{{ current === remote[0].version ? ' (最新)' : '' }}</td>
<td>
<el-select v-model="value">
<el-option value="">移除插件</el-option>
<el-option
v-for="({ version }) in remote"
:key="version" :value="version"
>{{ version }}{{ version === current ? ' (当前)' : '' }}</el-option>
</el-select>
</td>
</tr>
</template>

<script lang="ts" setup>
import { computed } from 'vue'
import { store } from '~/client'
import { config } from '../utils'
const props = defineProps({
name: String,
})
const value = computed({
get() {
const target = config.override[props.name]
return target === '' ? '移除插件' : target
},
set(target: string) {
if (target === '' && !current.value || target === current.value) {
delete config.override[props.name]
} else {
config.override[props.name] = target
}
},
})
const current = computed(() => {
return store.packages[props.name]?.version
})
const remote = computed(() => {
return store.market[props.name].versions
})
</script>
8 changes: 8 additions & 0 deletions plugins/frontend/manager/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,17 @@ import Bots from './bots/index.vue'
import Settings from './settings/index.vue'
import Dependencies from './dependencies/index.vue'
import Market from './market/index.vue'
import Overlay from './dependencies/overlay.vue'
import { overrideCount } from './utils'

import './style.scss'

export default (ctx: Context) => {
ctx.addView({
type: 'global',
component: Overlay,
})

ctx.addView({
type: 'numeric',
order: 100,
Expand Down Expand Up @@ -44,6 +51,7 @@ export default (ctx: Context) => {
order: 620,
fields: ['market', 'packages'],
component: Dependencies,
badge: () => overrideCount.value,
})

ctx.addPage({
Expand Down
20 changes: 0 additions & 20 deletions plugins/frontend/manager/client/settings/select.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,6 @@
:filter="data => !data.id && data.name && (!filtered || !isReadonly(data))" #="data">
<span :class="{ readonly: isReadonly(data) }">{{ data.shortname }}</span>
</k-tab-group>
<template v-if="store.market">
<div class="k-tab-group-title">
待下载的插件
</div>
<k-tab-group :data="favorites" v-model="model" #="data">
<span :class="{ readonly: isReadonly(data) }">{{ data.shortname }}</span>
<k-icon class="remove" name="times-full" @click="removeFavorite(data.name)"/>
</k-tab-group>
</template>
</div>
</el-scrollbar>
</template>
Expand All @@ -45,7 +36,6 @@
import { ref, computed, onActivated, nextTick } from 'vue'
import { store } from '~/client'
import { config, removeFavorite } from '../utils'
const props = defineProps<{
modelValue: string
Expand All @@ -65,16 +55,6 @@ function isReadonly(data: any) {
return !data.root && data.id
}
const favorites = computed(() => {
const result = {}
// config.favorites = config.override.filter((name) => {
// if (!store.market[name]) return false
// result[name] = store.market[name]
// return true
// })
return result
})
onActivated(async () => {
const container = root.value.$el
await nextTick()
Expand Down
Loading

0 comments on commit 45112c6

Please sign in to comment.