refactor: update AppInstall with async useForm

This commit is contained in:
axolotle 2024-07-25 14:22:16 +02:00
parent 5408b0553c
commit ea6cf5e3cf

View file

@ -1,18 +1,17 @@
<script setup lang="ts"> <script setup lang="ts">
import { useVuelidate } from '@vuelidate/core' import { ref, shallowRef, type Ref } from 'vue'
import { computed, reactive, ref } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import api, { objectToParams } from '@/api' import api, { objectToParams } from '@/api'
import { APIBadRequestError, type APIError } from '@/api/errors' import { type APIError } from '@/api/errors'
import { formatOptions } from '@/composables/configPanels'
import { useForm, type FormValidation } from '@/composables/form'
import { useAutoModal } from '@/composables/useAutoModal' import { useAutoModal } from '@/composables/useAutoModal'
import { useInitialQueries } from '@/composables/useInitialQueries' import { useInitialQueries } from '@/composables/useInitialQueries'
import { import { formatForm, formatI18nField } from '@/helpers/yunohostArguments'
formatForm, import type { Obj } from '@/types/commons'
formatI18nField, import type { FormFieldDict } from '@/types/form'
formatYunoHostArguments,
} from '@/helpers/yunohostArguments'
const props = defineProps<{ const props = defineProps<{
id: string id: string
@ -23,11 +22,19 @@ const route = useRoute()
const router = useRouter() const router = useRouter()
const modalConfirm = useAutoModal() const modalConfirm = useAutoModal()
const form = reactive({}) // TODO: handling async form is a mess, make a composable or something?
const validations = ref({}) const formData = shallowRef<
const rules = computed(() => validations) | {
const externalResults = reactive({}) form: Ref<Obj>
const v$ = useVuelidate(rules, form, { $externalResults: externalResults }) fields: FormFieldDict<Obj>
v: Ref<FormValidation<Obj>>
onSubmit: (
fn: (onError: (err: APIError) => void) => void,
) => (e: SubmitEvent) => void
}
| undefined
>()
const { loading } = useInitialQueries( const { loading } = useInitialQueries(
[ [
['GET', 'apps/catalog?full&with_categories&with_antifeatures'], ['GET', 'apps/catalog?full&with_categories&with_antifeatures'],
@ -39,8 +46,6 @@ const { loading } = useInitialQueries(
// FIXME // FIXME
const app = ref(undefined) const app = ref(undefined)
const name = ref(undefined) const name = ref(undefined)
const fields = ref(undefined)
const serverError = ref('')
const force = ref(false) const force = ref(false)
function appLinksIcons(linkType) { function appLinksIcons(linkType) {
@ -140,22 +145,19 @@ function onQueriesResponse(catalog: any, _app: any) {
// FIXME yunohost should add the label field by default // FIXME yunohost should add the label field by default
_app.install.unshift({ _app.install.unshift({
type: 'string',
id: 'label',
ask: t('label_for_manifestname', { name }), ask: t('label_for_manifestname', { name }),
default: name, default: name,
name: 'label',
help: t('label_for_manifestname_help'), help: t('label_for_manifestname_help'),
optional: false,
}) })
const { const { form, fields } = formatOptions(_app.install)
form: form_, const { v, onSubmit } = useForm(form, fields)
fields, formData.value = { form, fields, v, onSubmit }
validations,
} = formatYunoHostArguments(_app.install)
app.value = app_ app.value = app_
fieds.value = fields
Object.assign(form, form_)
validations.value = validations
} }
function formatAppNotifs(notifs) { function formatAppNotifs(notifs) {
@ -164,11 +166,13 @@ function formatAppNotifs(notifs) {
}, '') }, '')
} }
async function performInstall() { async function performInstall(onError: (err: APIError) => void) {
if ('path' in form && form.path === '/') { const { form } = formData.value!
const confirmed = await this.modalConfirm(
if ('path' in form.value && form.value.path === '/') {
const confirmed = await modalConfirm(
t('confirm_install_domain_root', { t('confirm_install_domain_root', {
domain: form.domain, domain: form.value.domain,
}), }),
) )
if (!confirmed) return if (!confirmed) return
@ -200,12 +204,7 @@ async function performInstall() {
} }
router.push({ name: 'app-list' }) router.push({ name: 'app-list' })
}) })
.catch((err: APIError) => { .catch(onError)
if (!(err instanceof APIBadRequestError)) throw err
if (err.data.name) {
externalResults[err.data.name] = err.message
} else serverError.value = err.message
})
} }
</script> </script>
@ -382,25 +381,15 @@ async function performInstall() {
<!-- INSTALL FORM --> <!-- INSTALL FORM -->
<CardForm <CardForm
v-if="app.canInstall || force" v-if="formData && (app.canInstall || force)"
v-model="formData.form.value"
:fields="formData.fields"
:title="$t('app_install_parameters')" :title="$t('app_install_parameters')"
icon="cog" icon="cog"
:submit-text="$t('install')" :submit-text="$t('install')"
:validation="v$" :validations="formData.v.value"
:server-error="serverError" @submit="formData.onSubmit(performInstall)($event)"
@submit.prevent="performInstall" />
>
<template v-for="(field, fname) in fields">
<Component
v-if="field.visible"
v-bind="field.props"
:is="field.is"
v-model="form[fname]"
:validation="v$.form[fname]"
:key="fname"
/>
</template>
</CardForm>
</template> </template>
<!-- In case of a custom url with no manifest found --> <!-- In case of a custom url with no manifest found -->