AppInfo: integrate config panel with fake "operations" tab

This commit is contained in:
axolotle 2022-11-24 15:44:58 +01:00
parent 359c248233
commit 5f10cb5115
2 changed files with 179 additions and 117 deletions

View file

@ -202,14 +202,22 @@ const routes = [
}
},
{
name: 'app-info',
path: '/apps/:id',
component: () => import(/* webpackChunkName: "views/apps/info" */ '@/views/app/AppInfo'),
props: true,
meta: {
args: { param: 'id' },
breadcrumb: ['app-list', 'app-info']
}
children: [
{
name: 'app-info',
path: ':tabId?',
component: () => import(/* webpackChunkName: "components/configPanel" */ '@/components/ConfigPanel'),
props: true,
meta: {
routerParams: ['id'], // Override router key params to avoid view recreation at tab change.
args: { param: 'id' },
breadcrumb: ['app-list', 'app-info']
}
}
]
},
{
// no need for name here, only children are visited

View file

@ -20,119 +20,121 @@
</description-row>
</card>
<!-- OPERATIONS -->
<card v-if="app" :title="$t('operations')" icon="wrench">
<!-- CHANGE PERMISSIONS LABEL -->
<b-form-group :label="$t('app_manage_label_and_tiles')" label-class="font-weight-bold">
<form-field
v-for="(perm, i) in app.permissions" :key="i"
:label="perm.title" :label-for="'perm-' + i"
label-cols="0" label-class="" class="m-0"
:validation="$v.form.labels.$each[i] "
>
<template #default="{ self }">
<b-input-group>
<input-item
:state="self.state" v-model="form.labels[i].label"
:id="'perm' + i" :aria-describedby="'perm-' + i + '_group__BV_description_'"
/>
<b-input-group-append v-if="perm.tileAvailable" is-text>
<checkbox-item v-model="form.labels[i].show_tile" :label="$t('permission_show_tile_enabled')" />
</b-input-group-append>
<b-input-group-append>
<b-button
variant="info" v-t="'save'"
@click="changeLabel(perm.name, form.labels[i])"
<config-panels v-bind="config" @submit="onConfigSubmit">
<!-- OPERATIONS TAB -->
<template v-if="currentTab === 'operations'" #tab-top>
<!-- CHANGE PERMISSIONS LABEL -->
<b-form-group :label="$t('app_manage_label_and_tiles')" label-class="font-weight-bold">
<form-field
v-for="(perm, i) in app.permissions" :key="i"
:label="perm.title" :label-for="'perm-' + i"
label-cols="0" label-class="" class="m-0"
:validation="$v.form.labels.$each[i] "
>
<template #default="{ self }">
<b-input-group>
<input-item
:state="self.state" v-model="form.labels[i].label"
:id="'perm' + i" :aria-describedby="'perm-' + i + '_group__BV_description_'"
/>
</b-input-group-append>
</b-input-group>
</template>
<b-input-group-append v-if="perm.tileAvailable" is-text>
<checkbox-item v-model="form.labels[i].show_tile" :label="$t('permission_show_tile_enabled')" />
</b-input-group-append>
<b-input-group-append>
<b-button
variant="info" v-t="'save'"
@click="changeLabel(perm.name, form.labels[i])"
/>
</b-input-group-append>
</b-input-group>
</template>
<template v-if="perm.url" #description>
{{ $t('permission_corresponding_url') }}:
<b-link :href="'https://' + perm.url">
https://{{ perm.url }}
</b-link>
</template>
</form-field>
</b-form-group>
<hr>
<!-- CHANGE URL -->
<b-form-group
:label="$t('app_info_changeurl_desc')" label-for="input-url"
:label-cols-lg="app.supports_change_url ? 0 : 0" label-class="font-weight-bold"
v-if="app.is_webapp"
>
<b-input-group v-if="app.supports_change_url">
<b-input-group-prepend is-text>
https://
</b-input-group-prepend>
<b-input-group-prepend class="flex-grow-1">
<b-select v-model="form.url.domain" :options="domains" />
</b-input-group-prepend>
<b-input-group-prepend is-text>
/
</b-input-group-prepend>
<b-input id="input-url" v-model="form.url.path" class="flex-grow-3" />
<b-input-group-append>
<b-button @click="changeUrl" variant="info" v-t="'save'" />
</b-input-group-append>
</b-input-group>
<div v-else class="alert alert-warning">
<icon iname="exclamation" /> {{ $t('app_info_change_url_disabled_tooltip') }}
</div>
</b-form-group>
<hr v-if="app.is_webapp">
<!-- MAKE DEFAULT -->
<b-form-group
:label="$t('app_info_default_desc', { domain: app.domain })" label-for="main-domain"
label-class="font-weight-bold" label-cols-md="4"
v-if="app.is_webapp"
>
<template v-if="!app.is_default">
<b-button @click="setAsDefaultDomain($event, false)" id="main-domain" variant="success">
<icon iname="star" /> {{ $t('app_make_default') }}
</b-button>
</template>
<template v-else>
<b-button @click="setAsDefaultDomain($event, true)" id="main-domain" variant="warning">
<icon iname="star" /> {{ $t('app_make_not_default') }}
</b-button>
</template>
</b-form-group>
<hr v-if="app.is_webapp">
<!-- APP CONFIG PANEL -->
<template v-if="app.supports_config_panel">
<b-form-group
:label="$t('app_config_panel_label')" label-for="config"
label-cols-md="4" label-class="font-weight-bold"
>
<b-button id="config" variant="warning" :to="{ name: 'app-config-panel', params: { id } }">
<icon iname="cog" /> {{ $t('app_config_panel') }}
</b-button>
<template v-if="perm.url" #description>
{{ $t('permission_corresponding_url') }}:
<b-link :href="'https://' + perm.url">
https://{{ perm.url }}
</b-link>
</template>
</form-field>
</b-form-group>
<hr>
</template>
<!-- UNINSTALL -->
<b-form-group
:label="$t('app_info_uninstall_desc')" label-for="uninstall"
label-class="font-weight-bold" label-cols-md="4"
>
<b-button @click="uninstall" id="uninstall" variant="danger">
<icon iname="trash-o" /> {{ $t('uninstall') }}
</b-button>
</b-form-group>
</card>
<!-- CHANGE URL -->
<b-form-group
:label="$t('app_info_changeurl_desc')" label-for="input-url"
:label-cols-lg="app.supports_change_url ? 0 : 0" label-class="font-weight-bold"
v-if="app.is_webapp"
>
<b-input-group v-if="app.supports_change_url">
<b-input-group-prepend is-text>
https://
</b-input-group-prepend>
<b-input-group-prepend class="flex-grow-1">
<b-select v-model="form.url.domain" :options="domains" />
</b-input-group-prepend>
<b-input-group-prepend is-text>
/
</b-input-group-prepend>
<b-input id="input-url" v-model="form.url.path" class="flex-grow-3" />
<b-input-group-append>
<b-button @click="changeUrl" variant="info" v-t="'save'" />
</b-input-group-append>
</b-input-group>
<div v-else class="alert alert-warning">
<icon iname="exclamation" /> {{ $t('app_info_change_url_disabled_tooltip') }}
</div>
</b-form-group>
<hr v-if="app.is_webapp">
<!-- MAKE DEFAULT -->
<b-form-group
:label="$t('app_info_default_desc', { domain: app.domain })" label-for="main-domain"
label-class="font-weight-bold" label-cols-md="4"
v-if="app.is_webapp"
>
<template v-if="!app.is_default">
<b-button @click="setAsDefaultDomain($event, false)" id="main-domain" variant="success">
<icon iname="star" /> {{ $t('app_make_default') }}
</b-button>
</template>
<template v-else>
<b-button @click="setAsDefaultDomain($event, true)" id="main-domain" variant="warning">
<icon iname="star" /> {{ $t('app_make_not_default') }}
</b-button>
</template>
</b-form-group>
<hr v-if="app.is_webapp">
<!-- APP CONFIG PANEL -->
<template v-if="app.supports_config_panel">
<b-form-group
:label="$t('app_config_panel_label')" label-for="config"
label-cols-md="4" label-class="font-weight-bold"
>
<b-button id="config" variant="warning" :to="{ name: 'app-config-panel', params: { id } }">
<icon iname="cog" /> {{ $t('app_config_panel') }}
</b-button>
</b-form-group>
<hr>
</template>
<!-- UNINSTALL -->
<b-form-group
:label="$t('app_info_uninstall_desc')" label-for="uninstall"
label-class="font-weight-bold" label-cols-md="4"
>
<b-button @click="uninstall" id="uninstall" variant="danger">
<icon iname="trash-o" /> {{ $t('uninstall') }}
</b-button>
</b-form-group>
</template>
</config-panels>
<template #skeleton>
<card-info-skeleton :item-count="8" />
@ -145,14 +147,23 @@
import { mapGetters } from 'vuex'
import { validationMixin } from 'vuelidate'
import api from '@/api'
import api, { objectToParams } from '@/api'
import { readableDate } from '@/helpers/filters/date'
import { humanPermissionName } from '@/helpers/filters/human'
import { required } from '@/helpers/validators'
import {
formatFormData,
formatYunoHostConfigPanels
} from '@/helpers/yunohostArguments'
import ConfigPanels from '@/components/ConfigPanels'
export default {
name: 'AppInfo',
components: {
ConfigPanels
},
props: {
id: { type: String, required: true }
},
@ -162,17 +173,33 @@ export default {
queries: [
['GET', `apps/${this.id}?full`],
['GET', { uri: 'users/permissions?full', storeKey: 'permissions' }],
['GET', { uri: 'domains' }]
['GET', { uri: 'domains' }],
['GET', `apps/${this.id}/config?full`]
],
infos: undefined,
app: undefined,
form: undefined
form: undefined,
config: {
panels: [
// Fake integration of operations in config panels
{
hasApplyButton: false,
id: 'operations',
name: this.$i18n.t('operations')
}
],
validations: {}
}
}
},
computed: {
...mapGetters(['domains']),
currentTab () {
return this.$route.params.tabId
},
allowedGroups () {
if (!this.app) return
return this.app.permissions[0].allowed
@ -191,7 +218,14 @@ export default {
},
methods: {
onQueriesResponse (app) {
onQueriesResponse (app, _, __, config) {
if (app.supports_config_panel) {
const config_ = formatYunoHostConfigPanels(config)
// reinject 'operations' fake config tab
config_.panels.unshift(this.config.panels[0])
this.config = config_
}
const form = { labels: [] }
const mainPermission = app.permissions[this.id + '.main']
@ -244,6 +278,26 @@ export default {
}
},
async onConfigSubmit ({ id, form, action, name }) {
const args = await formatFormData(form, { removeEmpty: false, removeNull: true })
api.put(
action
? `apps/${this.id}/actions/${action}`
: `apps/${this.id}/config/${id}`,
{ args: objectToParams(args) },
{ key: `apps.${action ? 'action' : 'update'}_config`, id, name: this.id }
).then(() => {
this.$refs.view.fetchQueries({ triggerLoading: true })
}).catch(err => {
if (err.name !== 'APIBadRequestError') throw err
const panel = this.config.panels.find(panel => panel.id === id)
if (err.data.name) {
this.config.errors[id][err.data.name].message = err.message
} else this.$set(panel, 'serverError', err.message)
})
},
changeLabel (permName, data) {
data.show_tile = data.show_tile ? 'True' : 'False'
api.put(