mirror of
https://github.com/YunoHost/yunohost-admin.git
synced 2024-09-03 20:06:15 +02:00
refactor: update config panels views using useConfigPanels
This commit is contained in:
parent
8af40dd04a
commit
678638534b
4 changed files with 126 additions and 173 deletions
|
@ -141,22 +141,15 @@ const routes = [
|
|||
},
|
||||
},
|
||||
{
|
||||
path: '/domains/:name',
|
||||
name: 'domain-info',
|
||||
path: '/domains/:name/:tabId?',
|
||||
component: () => import('@/views/domain/DomainInfo.vue'),
|
||||
props: true,
|
||||
children: [
|
||||
{
|
||||
name: 'domain-info',
|
||||
path: ':tabId?',
|
||||
component: () => import('@/components/ConfigPanel.vue'),
|
||||
props: true,
|
||||
meta: {
|
||||
routerParams: ['name'], // Override router key params to avoid view recreation at tab change.
|
||||
args: { param: 'name' },
|
||||
breadcrumb: ['domain-list', 'domain-info'],
|
||||
},
|
||||
},
|
||||
],
|
||||
meta: {
|
||||
routerParams: ['name'], // Override router key params to avoid view recreation at tab change.
|
||||
args: { param: 'name' },
|
||||
breadcrumb: ['domain-list', 'domain-info'],
|
||||
},
|
||||
},
|
||||
|
||||
/* ───────╮
|
||||
|
@ -202,22 +195,15 @@ const routes = [
|
|||
},
|
||||
},
|
||||
{
|
||||
path: '/apps/:id',
|
||||
name: 'app-info',
|
||||
path: '/apps/:id/:tabId?',
|
||||
component: () => import('@/views/app/AppInfo.vue'),
|
||||
props: true,
|
||||
children: [
|
||||
{
|
||||
name: 'app-info',
|
||||
path: ':tabId?',
|
||||
component: () => import('@/components/ConfigPanel.vue'),
|
||||
props: true,
|
||||
meta: {
|
||||
routerParams: ['id'], // Override router key params to avoid view recreation at tab change.
|
||||
args: { param: 'id' },
|
||||
breadcrumb: ['app-list', 'app-info'],
|
||||
},
|
||||
},
|
||||
],
|
||||
meta: {
|
||||
routerParams: ['id'], // Override router key params to avoid view recreation at tab change.
|
||||
args: { param: 'id' },
|
||||
breadcrumb: ['app-list', 'app-info'],
|
||||
},
|
||||
},
|
||||
|
||||
/* ────────────────╮
|
||||
|
@ -315,21 +301,15 @@ const routes = [
|
|||
},
|
||||
},
|
||||
{
|
||||
path: '/tools/settings',
|
||||
name: 'tool-settings',
|
||||
path: '/tools/settings/:tabId?',
|
||||
component: () => import('@/views/tool/ToolSettings.vue'),
|
||||
children: [
|
||||
{
|
||||
name: 'tool-settings',
|
||||
path: ':tabId?',
|
||||
component: () => import('@/components/ConfigPanel.vue'),
|
||||
props: true,
|
||||
meta: {
|
||||
routerParams: [],
|
||||
args: { trad: 'tools_yunohost_settings' },
|
||||
breadcrumb: ['tool-list', 'tool-settings'],
|
||||
},
|
||||
},
|
||||
],
|
||||
props: true,
|
||||
meta: {
|
||||
routerParams: [],
|
||||
args: { trad: 'tools_yunohost_settings' },
|
||||
breadcrumb: ['tool-list', 'tool-settings'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'tool-power',
|
||||
|
|
|
@ -1,26 +1,29 @@
|
|||
<script setup lang="ts">
|
||||
import { useVuelidate } from '@vuelidate/core'
|
||||
import { computed, reactive, ref } from 'vue'
|
||||
import { computed, reactive, ref, shallowRef } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
import api, { objectToParams } from '@/api'
|
||||
import { APIBadRequestError, type APIError } from '@/api/errors'
|
||||
import ConfigPanels from '@/components/ConfigPanels.vue'
|
||||
import { type APIError } from '@/api/errors'
|
||||
import ConfigPanelsComponent from '@/components/ConfigPanels.vue'
|
||||
import type {
|
||||
ConfigPanelsProps,
|
||||
OnPanelApply,
|
||||
} from '@/composables/configPanels'
|
||||
import { formatConfigPanels, useConfigPanels } from '@/composables/configPanels'
|
||||
import { useAutoModal } from '@/composables/useAutoModal'
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
import { isEmptyValue } from '@/helpers/commons'
|
||||
import { humanPermissionName } from '@/helpers/filters/human'
|
||||
import { helpers, required } from '@/helpers/validators'
|
||||
import {
|
||||
formatFormData,
|
||||
formatI18nField,
|
||||
formatYunoHostConfigPanels,
|
||||
} from '@/helpers/yunohostArguments'
|
||||
import { formatI18nField } from '@/helpers/yunohostArguments'
|
||||
import { useStoreGetters } from '@/store/utils'
|
||||
import type { CoreConfigPanels } from '@/types/core/options'
|
||||
|
||||
const props = defineProps<{
|
||||
id: string
|
||||
tabId?: string
|
||||
}>()
|
||||
|
||||
const { t } = useI18n()
|
||||
|
@ -60,18 +63,8 @@ const { loading, refetch } = useInitialQueries(
|
|||
|
||||
const app = ref()
|
||||
const purge = ref(false)
|
||||
const config_panel_err = ref(null)
|
||||
const config = ref({
|
||||
panels: [
|
||||
// Fake integration of operations in config panels
|
||||
{
|
||||
hasApplyButton: false,
|
||||
id: 'operations',
|
||||
name: t('operations'),
|
||||
},
|
||||
],
|
||||
validations: {},
|
||||
})
|
||||
const configPanelErr = ref('')
|
||||
const config = shallowRef<ConfigPanelsProps | undefined>()
|
||||
const doc = ref()
|
||||
|
||||
const currentTab = computed(() => {
|
||||
|
@ -215,47 +208,39 @@ async function onQueriesResponse(app_: any) {
|
|||
await api
|
||||
.get(`apps/${props.id}/config?full`)
|
||||
.then((cp) => {
|
||||
const config_ = formatYunoHostConfigPanels(cp)
|
||||
// reinject 'operations' fake config tab
|
||||
config_.panels.unshift(config.panels[0])
|
||||
config.value = config_
|
||||
const config_ = cp as CoreConfigPanels
|
||||
// Fake integration of operations in config panels
|
||||
config_.panels.unshift({
|
||||
id: 'operations',
|
||||
name: t('operations'),
|
||||
})
|
||||
config.value = useConfigPanels(
|
||||
formatConfigPanels(config_),
|
||||
() => props.tabId,
|
||||
onPanelApply,
|
||||
)
|
||||
})
|
||||
.catch((err: APIError) => {
|
||||
config_panel_err.value = err.message
|
||||
configPanelErr.value = err.message
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async function onConfigSubmit({ id, form, action, name }) {
|
||||
const args = await formatFormData(form, {
|
||||
removeEmpty: false,
|
||||
removeNull: true,
|
||||
})
|
||||
|
||||
const onPanelApply: OnPanelApply = ({ panelId, data, action }, onError) => {
|
||||
api
|
||||
.put(
|
||||
action
|
||||
? `apps/${props.id}/actions/${action}`
|
||||
: `apps/${props.id}/config/${id}`,
|
||||
isEmptyValue(args) ? {} : { args: objectToParams(args) },
|
||||
: `apps/${props.id}/config/${panelId}`,
|
||||
isEmptyValue(data) ? {} : { args: objectToParams(data) },
|
||||
{
|
||||
key: `apps.${action ? 'action' : 'update'}_config`,
|
||||
id,
|
||||
id: panelId,
|
||||
name: props.id,
|
||||
},
|
||||
)
|
||||
.then(() => refetch())
|
||||
.catch((err: APIError) => {
|
||||
if (!(err instanceof APIBadRequestError)) throw err
|
||||
const panel = config.value.panels.find((panel) => panel.id === id)!
|
||||
if (err.data.name) {
|
||||
Object.assign(externalResults, {
|
||||
forms: { [panel.id]: { [err.data.name]: [err.data.error] } },
|
||||
})
|
||||
} else {
|
||||
panel.serverError = err.message
|
||||
}
|
||||
})
|
||||
.catch(onError)
|
||||
}
|
||||
|
||||
function changeLabel(permName, data) {
|
||||
|
@ -439,20 +424,23 @@ async function uninstall() {
|
|||
<VueShowdown :markdown="app.description" />
|
||||
</section>
|
||||
|
||||
<YAlert v-if="config_panel_err" class="mb-4" variant="danger" icon="bug">
|
||||
<YAlert v-if="configPanelErr" class="mb-4" variant="danger" icon="bug">
|
||||
<p>{{ $t('app.info.config_panel_error') }}</p>
|
||||
<p>{{ config_panel_err }}</p>
|
||||
<p>{{ configPanelErr }}</p>
|
||||
<p>{{ $t('app.info.config_panel_error_please_report') }}</p>
|
||||
</YAlert>
|
||||
|
||||
<!-- BASIC INFOS -->
|
||||
<ConfigPanels
|
||||
v-bind="config"
|
||||
:external-results="externalResults"
|
||||
@apply="onConfigSubmit"
|
||||
<ConfigPanelsComponent
|
||||
v-if="config"
|
||||
v-model="config.form"
|
||||
:panel="config.panel.value"
|
||||
:validations="config.v.value"
|
||||
:routes="config.routes"
|
||||
@apply="config.onPanelApply"
|
||||
>
|
||||
<!-- OPERATIONS TAB -->
|
||||
<template v-if="currentTab === 'operations'" #tab-top>
|
||||
<template v-if="currentTab === 'operations'" #default>
|
||||
<!-- CHANGE PERMISSIONS LABEL -->
|
||||
<BFormGroup
|
||||
:label="$t('app_manage_label_and_tiles')"
|
||||
|
@ -584,7 +572,7 @@ async function uninstall() {
|
|||
</template>
|
||||
</BFormGroup>
|
||||
</template>
|
||||
</ConfigPanels>
|
||||
</ConfigPanelsComponent>
|
||||
|
||||
<BCard v-if="app && app.doc.admin.length" no-body>
|
||||
<BTabs card fill pills>
|
||||
|
|
|
@ -1,22 +1,25 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, reactive, ref } from 'vue'
|
||||
import { computed, ref, shallowRef } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
|
||||
import api, { objectToParams } from '@/api'
|
||||
import ConfigPanels from '@/components/ConfigPanels.vue'
|
||||
import ConfigPanelsComponent from '@/components/ConfigPanels.vue'
|
||||
import type {
|
||||
ConfigPanelsProps,
|
||||
OnPanelApply,
|
||||
} from '@/composables/configPanels'
|
||||
import { formatConfigPanels, useConfigPanels } from '@/composables/configPanels'
|
||||
import { useAutoModal } from '@/composables/useAutoModal'
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
import {
|
||||
formatFormData,
|
||||
formatYunoHostConfigPanels,
|
||||
} from '@/helpers/yunohostArguments'
|
||||
import { useStoreGetters } from '@/store/utils'
|
||||
import type { CoreConfigPanels } from '@/types/core/options'
|
||||
import DomainDns from '@/views/domain/DomainDns.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
name: string
|
||||
tabId?: string
|
||||
}>()
|
||||
|
||||
const { t } = useI18n()
|
||||
|
@ -34,14 +37,9 @@ const { loading, refetch } = useInitialQueries(
|
|||
)
|
||||
|
||||
const { mainDomain } = useStoreGetters()
|
||||
const config = ref({})
|
||||
const externalResults = reactive({})
|
||||
const config = shallowRef<ConfigPanelsProps | undefined>()
|
||||
const unsubscribeDomainFromDyndns = ref(false)
|
||||
|
||||
const currentTab = computed(() => {
|
||||
return route.params.tabId
|
||||
})
|
||||
|
||||
const domain = computed(() => {
|
||||
return store.getters.domain(props.name)
|
||||
})
|
||||
|
@ -80,40 +78,33 @@ const isMainDynDomain = computed(() => {
|
|||
)
|
||||
})
|
||||
|
||||
function onQueriesResponse(domains: any, domain: any, config_: any) {
|
||||
config.value = formatYunoHostConfigPanels(config_)
|
||||
function onQueriesResponse(
|
||||
domains: any,
|
||||
domain: any,
|
||||
config_: CoreConfigPanels,
|
||||
) {
|
||||
config.value = useConfigPanels(
|
||||
formatConfigPanels(config_),
|
||||
() => props.tabId,
|
||||
onPanelApply,
|
||||
)
|
||||
}
|
||||
|
||||
async function onConfigSubmit({ id, form, action, name }) {
|
||||
const args = await formatFormData(form, {
|
||||
removeEmpty: false,
|
||||
removeNull: true,
|
||||
})
|
||||
|
||||
const onPanelApply: OnPanelApply = ({ panelId, data, action }, onError) => {
|
||||
api
|
||||
.put(
|
||||
action
|
||||
? `domain/${props.name}/actions/${action}`
|
||||
: `domains/${props.name}/config/${id}`,
|
||||
{ args: objectToParams(args) },
|
||||
: `domains/${props.name}/config/${panelId}`,
|
||||
{ args: objectToParams(data) },
|
||||
{
|
||||
key: `domains.${action ? 'action' : 'update'}_config`,
|
||||
id,
|
||||
id: panelId,
|
||||
name: props.name,
|
||||
},
|
||||
)
|
||||
.then(() => refetch())
|
||||
.catch((err) => {
|
||||
if (err.name !== 'APIBadRequestError') throw err
|
||||
const panel = config.value.panels.find((panel) => panel.id === id)
|
||||
if (err.data.name) {
|
||||
Object.assign(externalResults, {
|
||||
forms: { [panel.id]: { [err.data.name]: [err.data.error] } },
|
||||
})
|
||||
} else {
|
||||
panel.serverError = err.message
|
||||
}
|
||||
})
|
||||
.catch(onError)
|
||||
}
|
||||
|
||||
async function deleteDomain() {
|
||||
|
@ -254,16 +245,18 @@ async function setAsDefaultDomain() {
|
|||
</DescriptionRow>
|
||||
</YCard>
|
||||
|
||||
<ConfigPanels
|
||||
v-if="config.panels"
|
||||
v-bind="config"
|
||||
:external-results="externalResults"
|
||||
@apply="onConfigSubmit"
|
||||
<ConfigPanelsComponent
|
||||
v-if="config"
|
||||
v-model="config.form"
|
||||
:panel="config.panel.value"
|
||||
:validations="config.v.value"
|
||||
:routes="config.routes"
|
||||
@apply="config.onPanelApply"
|
||||
>
|
||||
<template v-if="currentTab === 'dns'" #tab-after>
|
||||
<template v-if="tabId === 'dns'" #tab-after>
|
||||
<DomainDns :name="name" />
|
||||
</template>
|
||||
</ConfigPanels>
|
||||
</ConfigPanelsComponent>
|
||||
|
||||
<BModal
|
||||
v-if="domain"
|
||||
|
|
|
@ -1,61 +1,53 @@
|
|||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue'
|
||||
import { shallowRef } from 'vue'
|
||||
|
||||
import api, { objectToParams } from '@/api'
|
||||
import { APIBadRequestError, type APIError } from '@/api/errors'
|
||||
import ConfigPanels from '@/components/ConfigPanels.vue'
|
||||
import ConfigPanelsComponent from '@/components/ConfigPanels.vue'
|
||||
import type {
|
||||
ConfigPanelsProps,
|
||||
OnPanelApply,
|
||||
} from '@/composables/configPanels'
|
||||
import { formatConfigPanels, useConfigPanels } from '@/composables/configPanels'
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
import {
|
||||
formatFormData,
|
||||
formatYunoHostConfigPanels,
|
||||
} from '@/helpers/yunohostArguments'
|
||||
import type { CoreConfigPanels } from '@/types/core/options'
|
||||
|
||||
const props = defineProps<{ tabId?: string }>()
|
||||
|
||||
const { loading, refetch } = useInitialQueries([['GET', 'settings?full']], {
|
||||
onQueriesResponse,
|
||||
})
|
||||
const config = ref({})
|
||||
// FIXME user proper useValidate stuff
|
||||
const externalResults = reactive({})
|
||||
const config = shallowRef<ConfigPanelsProps | undefined>()
|
||||
|
||||
function onQueriesResponse(config_: any) {
|
||||
config.value = formatYunoHostConfigPanels(config_)
|
||||
function onQueriesResponse(config_: CoreConfigPanels) {
|
||||
config.value = useConfigPanels(
|
||||
formatConfigPanels(config_),
|
||||
() => props.tabId,
|
||||
onPanelApply,
|
||||
)
|
||||
}
|
||||
|
||||
async function onConfigSubmit({ id, form }) {
|
||||
const args = await formatFormData(form, {
|
||||
removeEmpty: false,
|
||||
removeNull: true,
|
||||
})
|
||||
|
||||
const onPanelApply: OnPanelApply = ({ panelId, data }, onError) => {
|
||||
// FIXME no route for potential action
|
||||
api
|
||||
.put(
|
||||
`settings/${id}`,
|
||||
{ args: objectToParams(args) },
|
||||
{ key: 'settings.update', panel: id },
|
||||
`settings/${panelId}`,
|
||||
{ args: objectToParams(data) },
|
||||
{ key: 'settings.update', panel: panelId },
|
||||
)
|
||||
.then(() => refetch())
|
||||
.catch((err: APIError) => {
|
||||
if (!(err instanceof APIBadRequestError)) throw err
|
||||
const panel = config.value.panels.find((panel) => panel.id === id)
|
||||
if (err.data.name) {
|
||||
Object.assign(externalResults, {
|
||||
forms: { [panel.id]: { [err.data.name]: [err.data.error] } },
|
||||
})
|
||||
} else {
|
||||
panel.serverError = err.message
|
||||
}
|
||||
})
|
||||
.catch(onError)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ViewBase :loading="loading" skeleton="CardFormSkeleton">
|
||||
<ConfigPanels
|
||||
v-if="config.panels"
|
||||
v-bind="config"
|
||||
:external-results="externalResults"
|
||||
@apply="onConfigSubmit"
|
||||
<ConfigPanelsComponent
|
||||
v-if="config"
|
||||
v-model="config.form"
|
||||
:panel="config.panel.value"
|
||||
:validations="config.v.value"
|
||||
:routes="config.routes"
|
||||
@apply="config.onPanelApply"
|
||||
/>
|
||||
</ViewBase>
|
||||
</template>
|
||||
|
|
Loading…
Add table
Reference in a new issue