mirror of
https://github.com/YunoHost/yunohost-admin.git
synced 2024-09-03 20:06:15 +02:00
add AppActions view/route
This commit is contained in:
parent
b1b9e65b7b
commit
a12dc45229
5 changed files with 174 additions and 20 deletions
|
@ -1,7 +1,7 @@
|
|||
import i18n from '@/i18n'
|
||||
import store from '@/store'
|
||||
|
||||
function formatI18nField (field) {
|
||||
export function formatI18nField (field) {
|
||||
if (typeof field === 'string') return field
|
||||
const { locale, fallbackLocale } = store.state
|
||||
return field[locale] || field[fallbackLocale] || field.en
|
||||
|
|
|
@ -165,18 +165,6 @@ const routes = [
|
|||
component: () => import(/* webpackChunkName: "views/apps" */ '@/views/app/AppList'),
|
||||
meta: { breadcrumb: [{ name: 'app-list', trad: 'applications' }] }
|
||||
},
|
||||
{
|
||||
name: 'app-info',
|
||||
path: '/apps/info/:id',
|
||||
component: () => import(/* webpackChunkName: "views/apps" */ '@/views/app/AppInfo'),
|
||||
props: true,
|
||||
meta: {
|
||||
breadcrumb: [
|
||||
{ name: 'app-list', trad: 'applications' },
|
||||
{ name: 'app-info', param: 'id' }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'app-catalog',
|
||||
path: '/apps/catalog',
|
||||
|
@ -214,6 +202,31 @@ const routes = [
|
|||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'app-info',
|
||||
path: '/apps/:id',
|
||||
component: () => import(/* webpackChunkName: "views/apps" */ '@/views/app/AppInfo'),
|
||||
props: true,
|
||||
meta: {
|
||||
breadcrumb: [
|
||||
{ name: 'app-list', trad: 'applications' },
|
||||
{ name: 'app-info', param: 'id' }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'app-actions',
|
||||
path: '/apps/:id/actions',
|
||||
component: () => import(/* webpackChunkName: "views/apps" */ '@/views/app/AppActions'),
|
||||
props: true,
|
||||
meta: {
|
||||
breadcrumb: [
|
||||
{ name: 'app-list', trad: 'applications' },
|
||||
{ name: 'app-info', param: 'id' },
|
||||
{ name: 'app-actions', trad: 'action' }
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
/* ────────────────╮
|
||||
│ SYSTEM UPDATE │
|
||||
|
|
|
@ -76,15 +76,24 @@ body {
|
|||
.card + .card {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
.card-header h2 {
|
||||
margin: 0;
|
||||
font-size: 1.75rem;
|
||||
.card-header {
|
||||
h2, h4 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
.card-body {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.card-footer {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
// collapse icon
|
||||
.not-collapsed > .icon {
|
||||
transform: rotate(-90deg);
|
||||
|
|
131
app/src/views/app/AppActions.vue
Normal file
131
app/src/views/app/AppActions.vue
Normal file
|
@ -0,0 +1,131 @@
|
|||
<template>
|
||||
<div class="app-actions">
|
||||
<div v-if="actions">
|
||||
<b-alert variant="warning" show class="mb-4">
|
||||
<icon iname="exclamation-triangle" /> {{ $t('experimental_warning') }}
|
||||
</b-alert>
|
||||
|
||||
<!-- BASIC INFOS -->
|
||||
<b-card v-for="(action, i) in actions" :key="i">
|
||||
<template v-slot:header>
|
||||
<h4>{{ action.name }}</h4>
|
||||
</template>
|
||||
|
||||
<b-card-text v-if="action.description" v-html="action.description" />
|
||||
|
||||
<b-form v-if="action.args" :id="action.id + '-form'" @submit.prevent="performAction(action)">
|
||||
<form-item-helper v-for="arg in action.args" :key="arg.name" v-bind="arg" />
|
||||
|
||||
<b-form-invalid-feedback :id="action.id + '-feedback'" :state="action.isValid">
|
||||
{{ action.error }}
|
||||
</b-form-invalid-feedback>
|
||||
</b-form>
|
||||
|
||||
<template v-slot:footer>
|
||||
<b-button
|
||||
v-if="action.args" type="submit" :form="action.id + '-form'"
|
||||
variant="success" class="ml-auto" v-t="'perform'"
|
||||
/>
|
||||
<b-button
|
||||
v-else @click="performAction(action)"
|
||||
variant="success" class="ml-auto" v-t="'perform'"
|
||||
/>
|
||||
</template>
|
||||
</b-card>
|
||||
</div>
|
||||
|
||||
<!-- In case of a custom url with no manifest found -->
|
||||
<b-alert v-else-if="actions === null" variant="warning" show>
|
||||
<icon iname="exclamation-triangle" /> {{ $t('app_no_actions') }}
|
||||
</b-alert>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import api, { objectToParams } from '@/helpers/api'
|
||||
import { formatI18nField, formatYunoHostArgument } from '@/helpers/yunohostArguments'
|
||||
|
||||
export default {
|
||||
name: 'AppActions',
|
||||
|
||||
props: {
|
||||
id: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
actions: undefined
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
fetchData () {
|
||||
Promise.all([
|
||||
api.get(`apps/${this.id}/actions`),
|
||||
this.$store.dispatch('FETCH_ALL', [
|
||||
{ uri: 'domains' },
|
||||
{ uri: 'domains/main', storeKey: 'main_domain' },
|
||||
{ uri: 'users' }
|
||||
])
|
||||
]).then((responses) => this.setupForm(responses[0]))
|
||||
},
|
||||
|
||||
setupForm (data) {
|
||||
if (!data.actions) {
|
||||
this.actions = null
|
||||
return
|
||||
}
|
||||
|
||||
const actions = []
|
||||
for (const { name, id, description, arguments: arguments_ } of data.actions) {
|
||||
const action = { name, id, isValid: null, error: '' }
|
||||
if (description) {
|
||||
action.description = formatI18nField(description)
|
||||
}
|
||||
if (arguments_ && arguments_.length) {
|
||||
action.args = arguments_.map(arg => formatYunoHostArgument(arg))
|
||||
}
|
||||
actions.push(action)
|
||||
}
|
||||
this.actions = actions
|
||||
},
|
||||
|
||||
performAction (action) {
|
||||
const data = {}
|
||||
|
||||
if (action.args) {
|
||||
const args = {}
|
||||
for (const arg of action.args) {
|
||||
if (arg.component === 'CheckboxItem') {
|
||||
args[arg.props.id] = arg.props.value ? 1 : 0
|
||||
} else {
|
||||
args[arg.props.id] = arg.props.value
|
||||
}
|
||||
}
|
||||
data.args = objectToParams(args)
|
||||
// FIXME api expect at least one argument ?!
|
||||
} else {
|
||||
data.args = objectToParams({ wut: undefined })
|
||||
}
|
||||
|
||||
api.put(`apps/${this.id}/actions/${action.id}`, data).then(response => {
|
||||
this.fetchData()
|
||||
}).catch(err => {
|
||||
action.isValid = false
|
||||
action.error = err.message
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
created () {
|
||||
this.fetchData()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
|
@ -32,12 +32,13 @@
|
|||
<form-item-helper v-for="arg in form.args" :key="arg.name" v-bind="arg" />
|
||||
|
||||
<b-form-invalid-feedback id="global-feedback" :state="server.isValid">
|
||||
{{ this.server.error }}
|
||||
{{ server.error }}
|
||||
</b-form-invalid-feedback>
|
||||
</b-form>
|
||||
|
||||
<template v-slot:footer>
|
||||
<b-button
|
||||
class="ml-auto"
|
||||
type="submit" form="install-form"
|
||||
variant="success" v-t="'install'"
|
||||
/>
|
||||
|
@ -48,7 +49,7 @@
|
|||
<b-modal
|
||||
id="confirm-domain-root-modal" ref="confirm-domain-root-modal" centered
|
||||
body-bg-variant="danger" body-text-variant="light"
|
||||
@ok="runInstall" hide-header
|
||||
@ok="performInstall" hide-header
|
||||
:ok-title="$t('install')"
|
||||
>
|
||||
{{ $t('confirm_install_domain_root', { domain: confirmDomain }) }}
|
||||
|
@ -152,11 +153,11 @@ export default {
|
|||
this.confirmDomain = this.form.args.find(arg => arg.props.id === 'domain').props.value
|
||||
this.$refs['confirm-domain-root-modal'].show()
|
||||
} else {
|
||||
this.runInstall()
|
||||
this.performInstall()
|
||||
}
|
||||
},
|
||||
|
||||
runInstall () {
|
||||
performInstall () {
|
||||
const args = {}
|
||||
for (const arg of this.form.args) {
|
||||
if (arg.component === 'CheckboxItem') {
|
||||
|
|
Loading…
Add table
Reference in a new issue