mirror of
https://github.com/YunoHost/yunohost-admin.git
synced 2024-09-03 20:06:15 +02:00
refactor: update ConfigPanels component to receive useConfigPanels data
This commit is contained in:
parent
d3f843b1b1
commit
8af40dd04a
1 changed files with 67 additions and 68 deletions
|
@ -1,88 +1,87 @@
|
||||||
<script setup lang="ts">
|
<script
|
||||||
import { useVuelidate, type BaseValidation } from '@vuelidate/core'
|
setup
|
||||||
import { computed, defineAsyncComponent, toRef } from 'vue'
|
lang="ts"
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
generic="NestedMV extends Obj, MV extends Obj<NestedMV>"
|
||||||
|
>
|
||||||
import type { CustomRoute, Obj } from '@/types/commons'
|
import type { FormValidation } from '@/composables/form'
|
||||||
|
import type { KeyOfStr, Obj } from '@/types/commons'
|
||||||
|
import type { ConfigPanel, ConfigPanels } from '@/types/configPanels'
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
const RoutableTabs = defineAsyncComponent(
|
const props = defineProps<{
|
||||||
() => import('@/components/RoutableTabs.vue'),
|
// modelValue: MV[keyof MV]
|
||||||
)
|
panel: ConfigPanel<NestedMV, MV>
|
||||||
|
routes: ConfigPanels<NestedMV, MV>['routes']
|
||||||
const props = withDefaults(
|
validations: FormValidation<NestedMV>
|
||||||
defineProps<{
|
|
||||||
panels: Obj[]
|
|
||||||
forms: Obj<Obj>
|
|
||||||
validations: BaseValidation
|
|
||||||
externalResults: Obj
|
|
||||||
errors?: Obj // never used
|
|
||||||
noRedirect?: boolean
|
|
||||||
routes?: CustomRoute[]
|
|
||||||
}>(),
|
|
||||||
{
|
|
||||||
errors: undefined,
|
|
||||||
routes: undefined,
|
|
||||||
noRedirect: false,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
const slots = defineSlots<{
|
|
||||||
'tab-top': any
|
|
||||||
'tab-before': any
|
|
||||||
'tab-after': any
|
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const externalResults = toRef(props, 'externalResults')
|
const emit = defineEmits<{
|
||||||
const rules = computed(() => ({ forms: props.validations }))
|
apply: [action?: KeyOfStr<typeof props.panel.fields>]
|
||||||
const v$ = useVuelidate(rules, props.forms, {
|
'update:modelValue': [modelValue: MV[keyof MV]]
|
||||||
$externalResults: externalResults,
|
}>()
|
||||||
})
|
|
||||||
|
|
||||||
const router = useRouter()
|
const slots = defineSlots<{
|
||||||
const route = useRoute()
|
'tab-top'?: any
|
||||||
const routes = computed(() => {
|
'tab-before'?: any
|
||||||
return (
|
default?: any
|
||||||
props.routes ||
|
'tab-after'?: any
|
||||||
props.panels.map((panel) => ({
|
}>()
|
||||||
to: { params: { tabId: panel.id } },
|
|
||||||
text: panel.name,
|
|
||||||
icon: panel.icon || 'wrench',
|
|
||||||
}))
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!props.noRedirect && !route.params.tabId) {
|
const modelValue = defineModel<NestedMV>({ required: true })
|
||||||
router.replace({ params: { tabId: props.panels[0].id } })
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="config-panel">
|
<BCard v-if="routes.length > 1" no-body class="config-panel">
|
||||||
<!-- FIXME vue3 - weird stuff with event binding, need to propagate by hand for now -->
|
<BCardHeader header-tag="nav">
|
||||||
<RoutableTabs
|
<BNav card-header fill pills>
|
||||||
v-if="routes.length > 1"
|
<BNavItem
|
||||||
v-bind="{ panels, forms, v: v$, ...$attrs }"
|
v-for="route in routes"
|
||||||
:routes="routes"
|
:key="route.text"
|
||||||
|
:to="route.to"
|
||||||
|
:active="$route.params.tabId === route.to.params?.tabId"
|
||||||
|
>
|
||||||
|
<!-- FIXME added :active="" because `exact-active-class` not working https://github.com/bootstrap-vue-next/bootstrap-vue-next/issues/1754 -->
|
||||||
|
<!-- exact-active-class="active" -->
|
||||||
|
<YIcon v-if="route.icon" :iname="route.icon" />
|
||||||
|
{{ route.text }}
|
||||||
|
</BNavItem>
|
||||||
|
</BNav>
|
||||||
|
</BCardHeader>
|
||||||
|
|
||||||
|
<CardForm
|
||||||
|
v-model="modelValue"
|
||||||
|
:fields="panel.fields"
|
||||||
|
:no-footer="!panel.hasApplyButton"
|
||||||
|
:sections="panel.sections"
|
||||||
|
:validations="validations"
|
||||||
|
as-tab
|
||||||
|
@submit="emit('apply')"
|
||||||
|
@action="emit('apply', $event)"
|
||||||
>
|
>
|
||||||
<template #tab-top>
|
<template #top>
|
||||||
<slot name="tab-top" />
|
<slot name="tab-top" />
|
||||||
</template>
|
</template>
|
||||||
<template #tab-before>
|
<template v-if="panel.help" #disclaimer>
|
||||||
|
<div class="alert alert-info" v-html="panel.help" />
|
||||||
|
</template>
|
||||||
|
<template #before-form>
|
||||||
<slot name="tab-before" />
|
<slot name="tab-before" />
|
||||||
</template>
|
</template>
|
||||||
<template #tab-after>
|
<template v-if="slots.default" #default>
|
||||||
|
<slot name="default" />
|
||||||
|
</template>
|
||||||
|
<template #after-form>
|
||||||
<slot name="tab-after" />
|
<slot name="tab-after" />
|
||||||
</template>
|
</template>
|
||||||
</RoutableTabs>
|
</CardForm>
|
||||||
|
</BCard>
|
||||||
<YCard v-else :title="routes[0].text" :icon="routes[0].icon">
|
<YCard v-else :title="routes[0].text" :icon="routes[0].icon">
|
||||||
<slot name="tab-top" />
|
<slot name="tab-top" />
|
||||||
<slot name="tab-before" />
|
<slot name="tab-before" />
|
||||||
<slot name="tab-after" />
|
<slot name="default" />
|
||||||
</YCard>
|
<slot name="tab-after" />
|
||||||
</div>
|
</YCard>
|
||||||
</template>
|
</template>
|
||||||
|
|
Loading…
Add table
Reference in a new issue