Skip to content

Commit 5db06fd

Browse files
committed
refactor: refactor plugin configuration component
1 parent d01fb3f commit 5db06fd

File tree

5 files changed

+262
-231
lines changed

5 files changed

+262
-231
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<script lang="ts" setup>
2+
import { ref, watch } from 'vue'
3+
4+
import { deepClone, message } from '@/utils'
5+
6+
import type { Plugin } from '@/types/app'
7+
8+
interface Props {
9+
plugin: Plugin
10+
modelValue?: Recordable
11+
}
12+
13+
const props = withDefaults(defineProps<Props>(), {
14+
modelValue: () => ({}),
15+
})
16+
17+
const emit = defineEmits(['change', 'update:modelValue'])
18+
19+
const model = ref(deepClone(props.modelValue ?? {}))
20+
21+
let internalUpdate = false
22+
23+
watch(
24+
() => props.modelValue,
25+
(val) => {
26+
if (!internalUpdate) {
27+
model.value = val
28+
}
29+
internalUpdate = false
30+
},
31+
{ deep: true },
32+
)
33+
34+
const getOptions = (val: string[]) => {
35+
return val.map((v) => {
36+
const arr = v.split(',')
37+
return { label: arr[0], value: arr[1] || arr[0] }
38+
})
39+
}
40+
41+
const emitUpdate = () => {
42+
const val = deepClone(model.value)
43+
emit('update:modelValue', val)
44+
emit('change', val)
45+
internalUpdate = true
46+
}
47+
48+
const onChange = (key: string, originalValue: any, value: any) => {
49+
// TODO: array order
50+
if (JSON.stringify(originalValue) === JSON.stringify(value)) {
51+
delete model.value[key]
52+
} else {
53+
model.value[key] = value
54+
}
55+
emitUpdate()
56+
}
57+
58+
const handleReset = (key: string) => {
59+
delete model.value[key]
60+
emitUpdate()
61+
}
62+
63+
const handleResetAll = () => {
64+
model.value = {}
65+
emitUpdate()
66+
message.success('common.success')
67+
}
68+
69+
defineExpose({ reset: handleResetAll })
70+
</script>
71+
72+
<template>
73+
<div>
74+
<slot name="header" v-bind="{ handleResetAll }"></slot>
75+
<Card
76+
v-for="(conf, index) in plugin.configuration"
77+
:key="conf.id"
78+
:title="`${index + 1}. ${conf.title}`"
79+
:class="{ warn: model[conf.key] !== undefined }"
80+
class="card mb-8"
81+
>
82+
<template v-if="model[conf.key] !== undefined" #extra>
83+
<Button
84+
@click="handleReset(conf.key)"
85+
:icon-size="12"
86+
icon="clear"
87+
type="text"
88+
size="small"
89+
v-tips="'settings.plugin.resetSetting'"
90+
/>
91+
</template>
92+
<div class="mb-8 text-12">{{ conf.description }}</div>
93+
<Component
94+
:modelValue="model[conf.key] ?? conf.value"
95+
@change="(val: any) => onChange(conf.key, conf.value, val)"
96+
:is="conf.component"
97+
:options="getOptions(conf.options)"
98+
:autofocus="false"
99+
editable
100+
lang="yaml"
101+
/>
102+
</Card>
103+
</div>
104+
</template>
105+
106+
<style scoped>
107+
.card {
108+
border-left: 2px solid transparent;
109+
}
110+
.warn {
111+
border-left: 2px solid var(--primary-color);
112+
}
113+
</style>

frontend/src/views/PluginsView/components/PluginConfiguration.vue

Lines changed: 0 additions & 139 deletions
This file was deleted.
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<script setup lang="ts">
2+
import { ref, inject, h, useTemplateRef } from 'vue'
3+
import { useI18n } from 'vue-i18n'
4+
5+
import { PluginTriggerEvent } from '@/enums/app'
6+
import { usePluginsStore, useAppSettingsStore } from '@/stores'
7+
import { message } from '@/utils'
8+
9+
import Button from '@/components/Button/index.vue'
10+
11+
import PluginConfigItem from './PluginConfigItem.vue'
12+
13+
import type { Plugin } from '@/types/app'
14+
15+
interface Props {
16+
plugin: Plugin
17+
}
18+
19+
const props = defineProps<Props>()
20+
21+
const { t } = useI18n()
22+
const pluginsStore = usePluginsStore()
23+
const appSettingsStore = useAppSettingsStore()
24+
const pluginConfigRef = useTemplateRef('pluginConfigRef')
25+
26+
const loading = ref(false)
27+
const settings = ref(appSettingsStore.app.pluginSettings[props.plugin.id] ?? {})
28+
const oldSettings = settings.value
29+
const originalSettings = props.plugin.configuration.reduce((p, { key, value }) => {
30+
p[key] = value
31+
return p
32+
}, {} as Recordable)
33+
34+
const handleCancel = inject('cancel') as any
35+
const handleSubmit = inject('submit') as any
36+
37+
const handleSave = async () => {
38+
loading.value = true
39+
try {
40+
await pluginsStore.manualTrigger(
41+
props.plugin.id,
42+
PluginTriggerEvent.OnConfigure,
43+
Object.assign({}, originalSettings, settings.value),
44+
Object.assign({}, originalSettings, oldSettings),
45+
)
46+
} catch (error: any) {
47+
const errors = [
48+
props.plugin.id + ' Not Found',
49+
'is Missing source code',
50+
'Disabled',
51+
"Can't find variable: " + PluginTriggerEvent.OnConfigure,
52+
PluginTriggerEvent.OnConfigure + ' is not defined',
53+
]
54+
if (errors.every((v) => !error.includes(v))) {
55+
message.error(error)
56+
return
57+
}
58+
} finally {
59+
loading.value = false
60+
}
61+
62+
if (JSON.stringify(settings.value) === '{}') {
63+
delete appSettingsStore.app.pluginSettings[props.plugin.id]
64+
} else {
65+
appSettingsStore.app.pluginSettings[props.plugin.id] = settings.value
66+
}
67+
68+
await handleSubmit()
69+
message.success('common.success')
70+
}
71+
72+
const modalSlots = {
73+
action: () =>
74+
h(
75+
Button,
76+
{
77+
type: 'link',
78+
class: 'mr-auto',
79+
onClick: () => pluginConfigRef.value?.reset(),
80+
},
81+
() => t('plugin.restore'),
82+
),
83+
cancel: () =>
84+
h(
85+
Button,
86+
{
87+
disabled: loading.value,
88+
onClick: handleCancel,
89+
},
90+
() => t('common.cancel'),
91+
),
92+
submit: () =>
93+
h(
94+
Button,
95+
{
96+
type: 'primary',
97+
loading: loading.value,
98+
onClick: handleSave,
99+
},
100+
() => t('common.save'),
101+
),
102+
}
103+
104+
defineExpose({ modalSlots })
105+
</script>
106+
107+
<template>
108+
<PluginConfigItem ref="pluginConfigRef" :plugin="props.plugin" v-model="settings" />
109+
</template>

frontend/src/views/PluginsView/index.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import Button from '@/components/Button/index.vue'
1212
import { useModal } from '@/components/Modal'
1313
1414
import PluginChangelog from './components/PluginChangelog.vue'
15-
import PluginConfiguration from './components/PluginConfiguration.vue'
15+
import PluginConfigurator from './components/PluginConfigurator.vue'
1616
import PluginForm from './components/PluginForm.vue'
1717
import PluginHub from './components/PluginHub.vue'
1818
import PluginView from './components/PluginView.vue'
@@ -174,7 +174,7 @@ const generateMenus = (p: Plugin) => {
174174
label: 'plugins.configuration',
175175
handler: async () => {
176176
modalApi.setProps({ title: 'plugins.configuration' })
177-
modalApi.setContent(PluginConfiguration, { id: p.id }).open()
177+
modalApi.setContent(PluginConfigurator, { plugin: p }).open()
178178
},
179179
})
180180
}

0 commit comments

Comments
 (0)