mirror of
https://github.com/YunoHost/yunohost-admin.git
synced 2024-09-03 20:06:15 +02:00
refactor: use useInitialQueries in views
This commit is contained in:
parent
25482b67ca
commit
3054c3ec5c
25 changed files with 245 additions and 262 deletions
|
@ -8,6 +8,7 @@ import CardDeckFeed from '@/components/CardDeckFeed.vue'
|
|||
import { useAutoModal } from '@/composables/useAutoModal'
|
||||
import { randint } from '@/helpers/commons'
|
||||
import { appRepoUrl, required } from '@/helpers/validators'
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
|
@ -28,8 +29,10 @@ const { t } = useI18n()
|
|||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const modalConfirm = useAutoModal()
|
||||
|
||||
const queries = [['GET', 'apps/catalog?full&with_categories&with_antifeatures']]
|
||||
const { loading } = useInitialQueries(
|
||||
[['GET', 'apps/catalog?full&with_categories&with_antifeatures']],
|
||||
{ onQueriesResponse },
|
||||
)
|
||||
|
||||
const apps = ref()
|
||||
const selectedApp = ref()
|
||||
|
@ -96,10 +99,10 @@ const subtags = computed(() => {
|
|||
return null
|
||||
})
|
||||
|
||||
function onQueriesResponse(data) {
|
||||
const apps = []
|
||||
for (const key in data.apps) {
|
||||
const app = data.apps[key]
|
||||
function onQueriesResponse(catalog: any) {
|
||||
const apps_ = []
|
||||
for (const key in catalog.apps) {
|
||||
const app = catalog.apps[key]
|
||||
app.isInstallable =
|
||||
!app.installed || app.manifest.integration.multi_instance
|
||||
app.working = app.state === 'working'
|
||||
|
@ -124,12 +127,12 @@ function onQueriesResponse(data) {
|
|||
]
|
||||
.join(' ')
|
||||
.toLowerCase()
|
||||
apps.push(app)
|
||||
apps_.push(app)
|
||||
}
|
||||
apps.value = apps.sort((a, b) => (a.id > b.id ? 1 : -1))
|
||||
apps.value = apps_.sort((a, b) => (a.id > b.id ? 1 : -1))
|
||||
|
||||
// CATEGORIES
|
||||
data.categories.forEach(({ title, id, icon, subtags, description }) => {
|
||||
catalog.categories.forEach(({ title, id, icon, subtags, description }) => {
|
||||
categories.push({
|
||||
text: title,
|
||||
value: id,
|
||||
|
@ -139,7 +142,7 @@ function onQueriesResponse(data) {
|
|||
})
|
||||
})
|
||||
antifeatures.value = Object.fromEntries(
|
||||
data.antifeatures.map((af) => [af.id, af]),
|
||||
catalog.antifeatures.map((af) => [af.id, af]),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -180,11 +183,10 @@ async function onCustomInstallClick() {
|
|||
|
||||
<template>
|
||||
<ViewSearch
|
||||
:items="apps"
|
||||
:filtered-items="filteredApps"
|
||||
:items="apps"
|
||||
items-name="apps"
|
||||
:queries="queries"
|
||||
@queries-response="onQueriesResponse"
|
||||
:loading="loading"
|
||||
>
|
||||
<template #top-bar>
|
||||
<div id="view-top-bar">
|
||||
|
|
|
@ -7,8 +7,8 @@ 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 ViewBase from '@/components/globals/ViewBase.vue'
|
||||
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'
|
||||
|
@ -18,7 +18,6 @@ import {
|
|||
formatYunoHostConfigPanels,
|
||||
} from '@/helpers/yunohostArguments'
|
||||
import { useStoreGetters } from '@/store/utils'
|
||||
import type { Obj } from '@/types/commons'
|
||||
|
||||
const props = defineProps<{
|
||||
id: string
|
||||
|
@ -30,7 +29,6 @@ const router = useRouter()
|
|||
const modalConfirm = useAutoModal()
|
||||
|
||||
const { domains } = useStoreGetters()
|
||||
const viewElem = ref<InstanceType<typeof ViewBase> | null>(null)
|
||||
|
||||
// FIXME
|
||||
type AppForm = {
|
||||
|
@ -51,13 +49,15 @@ const rules = computed(() => ({
|
|||
}))
|
||||
const externalResults = reactive({})
|
||||
const v$ = useVuelidate(rules, form, { $externalResults: externalResults })
|
||||
const { loading, refetch } = useInitialQueries(
|
||||
[
|
||||
['GET', `apps/${props.id}?full`],
|
||||
['GET', { uri: 'users/permissions?full', storeKey: 'permissions' }],
|
||||
['GET', { uri: 'domains' }],
|
||||
],
|
||||
{ onQueriesResponse },
|
||||
)
|
||||
|
||||
const queries = [
|
||||
['GET', `apps/${props.id}?full`],
|
||||
['GET', { uri: 'users/permissions?full', storeKey: 'permissions' }],
|
||||
['GET', { uri: 'domains' }],
|
||||
]
|
||||
const loading = ref(true)
|
||||
const app = ref()
|
||||
const purge = ref(false)
|
||||
const config_panel_err = ref(null)
|
||||
|
@ -97,7 +97,7 @@ function appLinksIcons(linkType) {
|
|||
return linksIcons[linkType]
|
||||
}
|
||||
|
||||
async function onQueriesResponse(app_: Obj) {
|
||||
async function onQueriesResponse(app_: any) {
|
||||
// const form = { labels: [] }
|
||||
|
||||
const mainPermission = app_.permissions[props.id + '.main']
|
||||
|
@ -224,7 +224,6 @@ async function onQueriesResponse(app_: Obj) {
|
|||
config_panel_err.value = err.message
|
||||
})
|
||||
}
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
async function onConfigSubmit({ id, form, action, name }) {
|
||||
|
@ -245,10 +244,7 @@ async function onConfigSubmit({ id, form, action, name }) {
|
|||
name: props.id,
|
||||
},
|
||||
)
|
||||
.then(() => {
|
||||
loading.value = true
|
||||
viewElem.value!.fetchQueries()
|
||||
})
|
||||
.then(() => refetch())
|
||||
.catch((err: APIError) => {
|
||||
if (!(err instanceof APIBadRequestError)) throw err
|
||||
const panel = config.value.panels.find((panel) => panel.id === id)!
|
||||
|
@ -270,7 +266,7 @@ function changeLabel(permName, data) {
|
|||
prevName: app.value.label,
|
||||
nextName: data.label,
|
||||
})
|
||||
.then(() => viewElem.value!.fetchQueries())
|
||||
.then(() => refetch(false))
|
||||
}
|
||||
|
||||
async function changeUrl() {
|
||||
|
@ -284,7 +280,7 @@ async function changeUrl() {
|
|||
{ domain, path: '/' + path },
|
||||
{ key: 'apps.change_url', name: app.value.label },
|
||||
)
|
||||
.then(() => viewElem.value!.fetchQueries())
|
||||
.then(() => refetch(false))
|
||||
}
|
||||
|
||||
async function setAsDefaultDomain(undo = false) {
|
||||
|
@ -301,7 +297,7 @@ async function setAsDefaultDomain(undo = false) {
|
|||
domain: app.value.domain,
|
||||
},
|
||||
)
|
||||
.then(() => viewElem.value!.fetchQueries())
|
||||
.then(() => refetch(false))
|
||||
}
|
||||
|
||||
async function dismissNotification(name: string) {
|
||||
|
@ -311,7 +307,7 @@ async function dismissNotification(name: string) {
|
|||
{},
|
||||
{ key: 'apps.dismiss_notification', name: app.value.label },
|
||||
)
|
||||
.then(() => viewElem.value!.fetchQueries())
|
||||
.then(() => refetch(false))
|
||||
}
|
||||
|
||||
async function uninstall() {
|
||||
|
@ -328,12 +324,7 @@ async function uninstall() {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<ViewBase
|
||||
:queries="queries"
|
||||
@queries-response="onQueriesResponse"
|
||||
:loading="loading"
|
||||
ref="viewElem"
|
||||
>
|
||||
<ViewBase :loading="loading">
|
||||
<YAlert
|
||||
v-if="
|
||||
app &&
|
||||
|
|
|
@ -7,6 +7,7 @@ import { useRoute, useRouter } from 'vue-router'
|
|||
import api, { objectToParams } from '@/api'
|
||||
import { APIBadRequestError, type APIError } from '@/api/errors'
|
||||
import { useAutoModal } from '@/composables/useAutoModal'
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
import {
|
||||
formatFormData,
|
||||
formatI18nField,
|
||||
|
@ -27,11 +28,13 @@ const validations = ref({})
|
|||
const rules = computed(() => validations)
|
||||
const externalResults = reactive({})
|
||||
const v$ = useVuelidate(rules, form, { $externalResults: externalResults })
|
||||
|
||||
const queries = [
|
||||
['GET', 'apps/catalog?full&with_categories&with_antifeatures'],
|
||||
['GET', `apps/manifest?app=${props.id}&with_screenshot`],
|
||||
]
|
||||
const { loading } = useInitialQueries(
|
||||
[
|
||||
['GET', 'apps/catalog?full&with_categories&with_antifeatures'],
|
||||
['GET', `apps/manifest?app=${props.id}&with_screenshot`],
|
||||
],
|
||||
{ onQueriesResponse },
|
||||
)
|
||||
|
||||
// FIXME
|
||||
const app = ref(undefined)
|
||||
|
@ -54,7 +57,7 @@ function appLinksIcons(linkType) {
|
|||
return linksIcons[linkType]
|
||||
}
|
||||
|
||||
function onQueriesResponse(catalog, _app) {
|
||||
function onQueriesResponse(catalog: any, _app: any) {
|
||||
const antifeaturesList = Object.fromEntries(
|
||||
catalog.antifeatures.map((af) => [af.id, af]),
|
||||
)
|
||||
|
@ -211,7 +214,7 @@ async function performInstall() {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<ViewBase :queries="queries" @queries-response="onQueriesResponse">
|
||||
<ViewBase :loading="loading">
|
||||
<template v-if="app">
|
||||
<section class="border rounded p-3 mb-4">
|
||||
<div class="d-md-flex align-items-center mb-4">
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
const queries = [['GET', 'apps?full']]
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
|
||||
const { loading } = useInitialQueries([['GET', 'apps?full']], {
|
||||
onQueriesResponse,
|
||||
})
|
||||
const search = ref('')
|
||||
const apps = ref()
|
||||
|
||||
|
@ -17,13 +21,13 @@ const filteredApps = computed(() => {
|
|||
return filtered.length ? filtered : null
|
||||
})
|
||||
|
||||
function onQueriesResponse({ apps }) {
|
||||
if (apps.length === 0) {
|
||||
function onQueriesResponse(data: any) {
|
||||
if (data.apps.length === 0) {
|
||||
apps.value = null
|
||||
return
|
||||
}
|
||||
|
||||
apps.value = apps
|
||||
apps.value = data.apps
|
||||
.map(({ id, name, description, manifest }) => {
|
||||
return { id, name: manifest.name, label: name, description }
|
||||
})
|
||||
|
@ -36,11 +40,10 @@ function onQueriesResponse({ apps }) {
|
|||
<template>
|
||||
<ViewSearch
|
||||
v-model:search="search"
|
||||
:filtered-items="filteredApps"
|
||||
items-name="installed_apps"
|
||||
:items="apps"
|
||||
:filtered-items="filteredApps"
|
||||
:queries="queries"
|
||||
@queries-response="onQueriesResponse"
|
||||
:loading="loading"
|
||||
>
|
||||
<template #top-bar-buttons>
|
||||
<BButton variant="success" :to="{ name: 'app-catalog' }">
|
||||
|
|
|
@ -4,6 +4,7 @@ import { useI18n } from 'vue-i18n'
|
|||
import { useRouter } from 'vue-router'
|
||||
|
||||
import api from '@/api'
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
|
||||
const props = defineProps<{
|
||||
id: string
|
||||
|
@ -11,11 +12,14 @@ const props = defineProps<{
|
|||
|
||||
const { t } = useI18n()
|
||||
const router = useRouter()
|
||||
const { loading } = useInitialQueries(
|
||||
[
|
||||
['GET', 'hooks/backup'],
|
||||
['GET', 'apps?with_backup'],
|
||||
],
|
||||
{ onQueriesResponse },
|
||||
)
|
||||
|
||||
const queries = [
|
||||
['GET', 'hooks/backup'],
|
||||
['GET', 'apps?with_backup'],
|
||||
]
|
||||
const selected = ref<string[]>([])
|
||||
const system = ref()
|
||||
const apps = ref()
|
||||
|
@ -40,10 +44,10 @@ function formatHooks(hooks) {
|
|||
return data
|
||||
}
|
||||
|
||||
function onQueriesResponse({ hooks }, { apps }) {
|
||||
function onQueriesResponse({ hooks }: any, { apps: apps_ }: any) {
|
||||
system.value = formatHooks(hooks)
|
||||
// transform app array into literal object to match hooks data structure
|
||||
apps.value = apps.reduce((obj, app) => {
|
||||
apps.value = apps_.reduce((obj, app) => {
|
||||
obj[app.id] = app
|
||||
return obj
|
||||
}, {})
|
||||
|
@ -79,11 +83,7 @@ function createBackup() {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<ViewBase
|
||||
:queries="queries"
|
||||
@queries-response="onQueriesResponse"
|
||||
skeleton="CardListSkeleton"
|
||||
>
|
||||
<ViewBase :loading="loading" skeleton="CardListSkeleton">
|
||||
<!-- FIXME switch to <CardForm> ? -->
|
||||
<YCard :title="$t('backup_create')" icon="archive" no-body>
|
||||
<BFormCheckboxGroup
|
||||
|
|
|
@ -2,10 +2,12 @@
|
|||
import { computed, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
|
||||
import api from '@/api'
|
||||
import { APIBadRequestError, type APIError } from '@/api/errors'
|
||||
import { useAutoModal } from '@/composables/useAutoModal'
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
import { isEmptyValue } from '@/helpers/commons'
|
||||
import { readableDate } from '@/helpers/filters/date'
|
||||
import { humanSize } from '@/helpers/filters/human'
|
||||
|
@ -19,8 +21,11 @@ const { t } = useI18n()
|
|||
const router = useRouter()
|
||||
const store = useStore()
|
||||
const modalConfirm = useAutoModal()
|
||||
const { loading } = useInitialQueries(
|
||||
[['GET', `backups/${props.name}?with_details`]],
|
||||
{ onQueriesResponse },
|
||||
)
|
||||
|
||||
const queries = [['GET', `backups/${props.name}?with_details`]]
|
||||
const selected = ref<string[]>([])
|
||||
const error = ref('')
|
||||
const isValid = ref<boolean | null>(null)
|
||||
|
@ -54,7 +59,7 @@ function formatHooks(hooks) {
|
|||
return data
|
||||
}
|
||||
|
||||
function onQueriesResponse(data) {
|
||||
function onQueriesResponse(data: any) {
|
||||
infos.value = {
|
||||
name: props.name,
|
||||
created_at: data.created_at,
|
||||
|
@ -132,7 +137,7 @@ function downloadBackup() {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<ViewBase :queries="queries" @queries-response="onQueriesResponse">
|
||||
<ViewBase :loading="loading">
|
||||
<!-- BACKUP INFO -->
|
||||
<YCard :title="$t('infos')" icon="info-circle" button-unbreak="sm">
|
||||
<template #header-buttons>
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
import { distanceToNow, readableDate } from '@/helpers/filters/date'
|
||||
import { humanSize } from '@/helpers/filters/human'
|
||||
import type { Obj } from '@/types/commons'
|
||||
|
||||
const props = defineProps<{
|
||||
id: string
|
||||
}>()
|
||||
|
||||
const queries = [['GET', 'backups?with_info']]
|
||||
const archives = ref<Obj[] | null>(null)
|
||||
const { loading } = useInitialQueries([['GET', 'backups?with_info']], {
|
||||
onQueriesResponse,
|
||||
})
|
||||
const archives = ref<any[] | null>(null)
|
||||
|
||||
function onQueriesResponse(data) {
|
||||
function onQueriesResponse(data: any) {
|
||||
const archives_ = Object.entries(data.archives)
|
||||
if (archives_.length) {
|
||||
archives.value = archives_
|
||||
|
@ -28,11 +30,7 @@ function onQueriesResponse(data) {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<ViewBase
|
||||
:queries="queries"
|
||||
@queries-response="onQueriesResponse"
|
||||
skeleton="ListGroupSkeleton"
|
||||
>
|
||||
<ViewBase :loading="loading" skeleton="ListGroupSkeleton">
|
||||
<template #top>
|
||||
<TopBar
|
||||
:button="{
|
||||
|
|
|
@ -2,22 +2,23 @@
|
|||
import { ref } from 'vue'
|
||||
|
||||
import api from '@/api'
|
||||
import type ViewBase from '@/components/globals/ViewBase.vue'
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
import { distanceToNow } from '@/helpers/filters/date'
|
||||
import { DEFAULT_STATUS_ICON } from '@/helpers/yunohostArguments'
|
||||
import { useStoreGetters } from '@/store/utils'
|
||||
|
||||
const viewElem = ref<InstanceType<typeof ViewBase> | null>(null)
|
||||
|
||||
const queries = [
|
||||
['PUT', 'diagnosis/run?except_if_never_ran_yet', {}, 'diagnosis.run'],
|
||||
['GET', 'diagnosis?full'],
|
||||
]
|
||||
const { loading, refetch } = useInitialQueries(
|
||||
[
|
||||
['PUT', 'diagnosis/run?except_if_never_ran_yet', {}, 'diagnosis.run'],
|
||||
['GET', 'diagnosis?full'],
|
||||
],
|
||||
{ wait: true, onQueriesResponse },
|
||||
)
|
||||
const { dark } = useStoreGetters()
|
||||
|
||||
const reports = ref()
|
||||
|
||||
function onQueriesResponse(_, reportsData) {
|
||||
function onQueriesResponse(_: any, reportsData: any) {
|
||||
if (reportsData === null) {
|
||||
reports.value = null
|
||||
return
|
||||
|
@ -65,7 +66,7 @@ function runDiagnosis({ id = null, description } = {}) {
|
|||
key: 'diagnosis.run' + (id !== null ? '_specific' : ''),
|
||||
description,
|
||||
})
|
||||
.then(() => viewElem.value!.fetchQueries())
|
||||
.then(() => refetch(false))
|
||||
}
|
||||
|
||||
function toggleIgnoreIssue(action, report, item) {
|
||||
|
@ -99,12 +100,7 @@ function shareLogs() {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<ViewBase
|
||||
:queries="queries"
|
||||
@queries-response="onQueriesResponse"
|
||||
queries-wait
|
||||
ref="viewElem"
|
||||
>
|
||||
<ViewBase :loading="loading">
|
||||
<template #top-bar-group-right>
|
||||
<BButton @click="shareLogs" variant="success">
|
||||
<YIcon iname="cloud-upload" /> {{ $t('logs_share_with_yunopaste') }}
|
||||
|
|
|
@ -5,12 +5,13 @@ import { useStore } from 'vuex'
|
|||
|
||||
import api from '@/api'
|
||||
import { APIBadRequestError, type APIError } from '@/api/errors'
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
import { DomainForm } from '@/views/_partials'
|
||||
|
||||
const router = useRouter()
|
||||
const store = useStore()
|
||||
|
||||
const queries = [['GET', { uri: 'domains' }]]
|
||||
const { loading } = useInitialQueries([['GET', { uri: 'domains' }]])
|
||||
const serverError = ref('')
|
||||
|
||||
function onSubmit(data) {
|
||||
|
@ -28,7 +29,7 @@ function onSubmit(data) {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<ViewBase :queries="queries" skeleton="CardFormSkeleton">
|
||||
<ViewBase :loading="loading" skeleton="CardFormSkeleton">
|
||||
<DomainForm
|
||||
:title="$t('domain_add')"
|
||||
:server-error="serverError"
|
||||
|
|
|
@ -5,6 +5,7 @@ import { useI18n } from 'vue-i18n'
|
|||
import api from '@/api'
|
||||
import { useAutoModal } from '@/composables/useAutoModal'
|
||||
import { isEmptyValue } from '@/helpers/commons'
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
|
||||
const props = defineProps<{
|
||||
name: string
|
||||
|
@ -12,9 +13,11 @@ const props = defineProps<{
|
|||
|
||||
const { t } = useI18n()
|
||||
const modalConfirm = useAutoModal()
|
||||
const { loading } = useInitialQueries(
|
||||
[['GET', `domains/${props.name}/dns/suggest`]],
|
||||
{ onQueriesResponse },
|
||||
)
|
||||
|
||||
const queries = [['GET', `domains/${props.name}/dns/suggest`]]
|
||||
const loading = ref(true)
|
||||
const showAutoConfigCard = ref(true)
|
||||
const showManualConfigCard = ref(false)
|
||||
const dnsConfig = ref('')
|
||||
|
@ -25,7 +28,7 @@ const force = ref(null)
|
|||
|
||||
getDnsChanges()
|
||||
|
||||
function onQueriesResponse(suggestedConfig) {
|
||||
function onQueriesResponse(suggestedConfig: any) {
|
||||
dnsConfig.value = suggestedConfig
|
||||
}
|
||||
|
||||
|
@ -129,12 +132,7 @@ async function pushDnsChanges() {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<ViewBase
|
||||
:queries="queries"
|
||||
@queries-response="onQueriesResponse"
|
||||
:loading="loading"
|
||||
skeleton="CardInfoSkeleton"
|
||||
>
|
||||
<ViewBase :loading="loading" skeleton="CardInfoSkeleton">
|
||||
<section v-if="showAutoConfigCard" class="panel-section">
|
||||
<BCardTitle title-tag="h3">
|
||||
{{ $t('domain.dns.auto_config') }}
|
||||
|
|
|
@ -6,8 +6,8 @@ import { useStore } from 'vuex'
|
|||
|
||||
import api, { objectToParams } from '@/api'
|
||||
import ConfigPanels from '@/components/ConfigPanels.vue'
|
||||
import type ViewBase from '@/components/globals/ViewBase.vue'
|
||||
import { useAutoModal } from '@/composables/useAutoModal'
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
import {
|
||||
formatFormData,
|
||||
formatYunoHostConfigPanels,
|
||||
|
@ -24,16 +24,16 @@ const router = useRouter()
|
|||
const route = useRoute()
|
||||
const store = useStore()
|
||||
const modalConfirm = useAutoModal()
|
||||
|
||||
const viewElem = ref<InstanceType<typeof ViewBase> | null>(null)
|
||||
const { loading, refetch } = useInitialQueries(
|
||||
[
|
||||
['GET', { uri: 'domains', storeKey: 'domains' }],
|
||||
['GET', { uri: 'domains', storeKey: 'domains_details', param: props.name }],
|
||||
['GET', `domains/${props.name}/config?full`],
|
||||
],
|
||||
{ onQueriesResponse },
|
||||
)
|
||||
|
||||
const { mainDomain } = useStoreGetters()
|
||||
|
||||
const queries = [
|
||||
['GET', { uri: 'domains', storeKey: 'domains' }],
|
||||
['GET', { uri: 'domains', storeKey: 'domains_details', param: props.name }],
|
||||
['GET', `domains/${props.name}/config?full`],
|
||||
]
|
||||
const config = ref({})
|
||||
const externalResults = reactive({})
|
||||
const unsubscribeDomainFromDyndns = ref(false)
|
||||
|
@ -80,7 +80,7 @@ const isMainDynDomain = computed(() => {
|
|||
)
|
||||
})
|
||||
|
||||
function onQueriesResponse(domains, domain, config_) {
|
||||
function onQueriesResponse(domains: any, domain: any, config_: any) {
|
||||
config.value = formatYunoHostConfigPanels(config_)
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ async function onConfigSubmit({ id, form, action, name }) {
|
|||
name: props.name,
|
||||
},
|
||||
)
|
||||
.then(() => viewElem.value!.fetchQueries({ triggerLoading: true }))
|
||||
.then(() => refetch())
|
||||
.catch((err) => {
|
||||
if (err.name !== 'APIBadRequestError') throw err
|
||||
const panel = config.value.panels.find((panel) => panel.id === id)
|
||||
|
@ -150,12 +150,7 @@ async function setAsDefaultDomain() {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<ViewBase
|
||||
:queries="queries"
|
||||
@queries-response="onQueriesResponse"
|
||||
ref="viewElem"
|
||||
skeleton="CardListSkeleton"
|
||||
>
|
||||
<ViewBase :loading="loading" skeleton="CardListSkeleton">
|
||||
<!-- INFO CARD -->
|
||||
<YCard v-if="domain" :title="name" icon="globe">
|
||||
<template v-if="isMainDomain" #header-next>
|
||||
|
|
|
@ -3,11 +3,14 @@ import { useStoreGetters } from '@/store/utils'
|
|||
import { computed, ref } from 'vue'
|
||||
|
||||
import RecursiveListGroup from '@/components/RecursiveListGroup.vue'
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
import type { TreeRootNode } from '@/helpers/data/tree'
|
||||
|
||||
const { domains, mainDomain, domainsTree } = useStoreGetters()
|
||||
const { loading } = useInitialQueries([
|
||||
['GET', { uri: 'domains', storeKey: 'domains' }],
|
||||
])
|
||||
|
||||
const queries = [['GET', { uri: 'domains', storeKey: 'domains' }]]
|
||||
const search = ref('')
|
||||
|
||||
const tree = computed(() => {
|
||||
|
@ -31,10 +34,10 @@ const hasFilteredItems = computed(() => {
|
|||
<ViewSearch
|
||||
id="domain-list"
|
||||
v-model:search="search"
|
||||
:filtered-items="hasFilteredItems"
|
||||
:items="domains"
|
||||
items-name="domains"
|
||||
:queries="queries"
|
||||
:filtered-items="hasFilteredItems"
|
||||
:loading="loading"
|
||||
>
|
||||
<template #top-bar-buttons>
|
||||
<BButton variant="success" :to="{ name: 'domain-add' }">
|
||||
|
|
|
@ -5,6 +5,7 @@ import { useI18n } from 'vue-i18n'
|
|||
import api from '@/api'
|
||||
import TagsSelectizeItem from '@/components/globals/formItems/TagsSelectizeItem.vue'
|
||||
import { useAutoModal } from '@/composables/useAutoModal'
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
import { isEmptyValue } from '@/helpers/commons'
|
||||
|
||||
// TODO add global search with type (search by: group, user, permission)
|
||||
|
@ -12,18 +13,21 @@ import { isEmptyValue } from '@/helpers/commons'
|
|||
|
||||
const { t } = useI18n()
|
||||
const modalConfirm = useAutoModal()
|
||||
|
||||
const queries = [
|
||||
['GET', { uri: 'users' }],
|
||||
const { loading } = useInitialQueries(
|
||||
[
|
||||
'GET',
|
||||
{
|
||||
uri: 'users/groups?full&include_primary_groups',
|
||||
storeKey: 'groups',
|
||||
},
|
||||
['GET', { uri: 'users' }],
|
||||
[
|
||||
'GET',
|
||||
{
|
||||
uri: 'users/groups?full&include_primary_groups',
|
||||
storeKey: 'groups',
|
||||
},
|
||||
],
|
||||
['GET', { uri: 'users/permissions?full', storeKey: 'permissions' }],
|
||||
],
|
||||
['GET', { uri: 'users/permissions?full', storeKey: 'permissions' }],
|
||||
]
|
||||
{ onQueriesResponse },
|
||||
)
|
||||
|
||||
const search = ref('')
|
||||
const permissions = ref()
|
||||
const permissionsOptions = ref()
|
||||
|
@ -45,7 +49,7 @@ const filteredGroups = computed(() => {
|
|||
return isEmptyValue(filtered) ? null : filtered
|
||||
})
|
||||
|
||||
function onQueriesResponse(users, allGroups, permsDict) {
|
||||
function onQueriesResponse(users: any, allGroups: any, permsDict: any) {
|
||||
// Do not use computed properties to get values from the store here to avoid auto
|
||||
// updates while modifying values.
|
||||
const permissions_ = Object.entries(permsDict).map(([id, value]) => ({
|
||||
|
@ -182,12 +186,11 @@ async function deleteGroup(groupName) {
|
|||
|
||||
<template>
|
||||
<ViewSearch
|
||||
items-name="groups"
|
||||
v-model:search="search"
|
||||
:items="primaryGroups"
|
||||
:filtered-items="filteredGroups"
|
||||
:queries="queries"
|
||||
@queries-response="onQueriesResponse"
|
||||
:items="primaryGroups"
|
||||
items-name="groups"
|
||||
:loading="loading"
|
||||
skeleton="CardFormSkeleton"
|
||||
>
|
||||
<template #top-bar-buttons>
|
||||
|
|
|
@ -3,8 +3,8 @@ import { ref } from 'vue'
|
|||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import api from '@/api'
|
||||
import type ViewBase from '@/components/globals/ViewBase.vue'
|
||||
import { useAutoModal } from '@/composables/useAutoModal'
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
import { distanceToNow } from '@/helpers/filters/date'
|
||||
|
||||
const props = defineProps<{
|
||||
|
@ -13,12 +13,14 @@ const props = defineProps<{
|
|||
|
||||
const { t } = useI18n()
|
||||
const modalConfirm = useAutoModal()
|
||||
const viewElem = ref<InstanceType<typeof ViewBase> | null>(null)
|
||||
const { loading, refetch } = useInitialQueries(
|
||||
[
|
||||
['GET', 'services/' + props.name],
|
||||
['GET', `services/${props.name}/log?number=50`],
|
||||
],
|
||||
{ onQueriesResponse },
|
||||
)
|
||||
|
||||
const queries = [
|
||||
['GET', 'services/' + props.name],
|
||||
['GET', `services/${props.name}/log?number=50`],
|
||||
]
|
||||
const infos = ref()
|
||||
const uptime = ref()
|
||||
const isCritical = ref()
|
||||
|
@ -27,8 +29,8 @@ const action = ref()
|
|||
|
||||
function onQueriesResponse(
|
||||
// eslint-disable-next-line
|
||||
{ status, description, start_on_boot, last_state_change, configuration },
|
||||
logs,
|
||||
{ status, description, start_on_boot, last_state_change, configuration }: any,
|
||||
logs_: any,
|
||||
) {
|
||||
isCritical.value = ['nginx', 'ssh', 'slapd', 'yunohost-api'].includes(
|
||||
props.name,
|
||||
|
@ -37,14 +39,14 @@ function onQueriesResponse(
|
|||
uptime.value = last_state_change === 'unknown' ? 0 : last_state_change
|
||||
infos.value = { description, status, start_on_boot, configuration }
|
||||
|
||||
logs.value = Object.keys(logs)
|
||||
logs.value = Object.keys(logs_)
|
||||
.sort((prev, curr) => {
|
||||
if (prev === 'journalctl') return -1
|
||||
else if (curr === 'journalctl') return 1
|
||||
else if (prev < curr) return -1
|
||||
else return 1
|
||||
})
|
||||
.map((filename) => ({ content: logs[filename].join('\n'), filename }))
|
||||
.map((filename) => ({ content: logs_[filename].join('\n'), filename }))
|
||||
}
|
||||
|
||||
async function updateService(action) {
|
||||
|
@ -59,7 +61,7 @@ async function updateService(action) {
|
|||
{},
|
||||
{ key: 'services.' + action, name: props.name },
|
||||
)
|
||||
.then(() => viewElem.value!.fetchQueries())
|
||||
.then(() => refetch(false))
|
||||
}
|
||||
|
||||
function shareLogs() {
|
||||
|
@ -85,12 +87,7 @@ function shareLogs() {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<ViewBase
|
||||
:queries="queries"
|
||||
@queries-response="onQueriesResponse"
|
||||
ref="viewElem"
|
||||
skeleton="CardInfoSkeleton"
|
||||
>
|
||||
<ViewBase :loading="loading" skeleton="CardInfoSkeleton">
|
||||
<!-- INFO CARD -->
|
||||
<YCard :title="name" icon="info-circle" button-unbreak="sm">
|
||||
<template #header-buttons>
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
import { distanceToNow } from '@/helpers/filters/date'
|
||||
|
||||
const queries = [['GET', 'services']]
|
||||
const { loading } = useInitialQueries([['GET', 'services']], {
|
||||
onQueriesResponse,
|
||||
})
|
||||
const search = ref('')
|
||||
const services = ref()
|
||||
|
||||
|
@ -15,11 +18,11 @@ const filteredServices = computed(() => {
|
|||
return services_.length ? services_ : null
|
||||
})
|
||||
|
||||
function onQueriesResponse(services) {
|
||||
services.value = Object.keys(services)
|
||||
function onQueriesResponse(services_: any) {
|
||||
services.value = Object.keys(services_)
|
||||
.sort()
|
||||
.map((name) => {
|
||||
const service = services[name]
|
||||
const service = services_[name]
|
||||
if (service.last_state_change === 'unknown') {
|
||||
service.last_state_change = 0
|
||||
}
|
||||
|
@ -32,11 +35,10 @@ function onQueriesResponse(services) {
|
|||
<ViewSearch
|
||||
id="service-list"
|
||||
v-model:search="search"
|
||||
:items="services"
|
||||
:filtered-items="filteredServices"
|
||||
:items="services"
|
||||
items-name="services"
|
||||
:queries="queries"
|
||||
@queries-response="onQueriesResponse"
|
||||
:loading="loading"
|
||||
>
|
||||
<BListGroup>
|
||||
<BListGroupItem
|
||||
|
|
|
@ -5,16 +5,15 @@ import { useI18n } from 'vue-i18n'
|
|||
|
||||
import api from '@/api'
|
||||
import { APIBadRequestError, type APIError } from '@/api/errors'
|
||||
import type ViewBase from '@/components/globals/ViewBase.vue'
|
||||
import { useAutoModal } from '@/composables/useAutoModal'
|
||||
import { between, integer, required } from '@/helpers/validators'
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
|
||||
const { t } = useI18n()
|
||||
const modalConfirm = useAutoModal()
|
||||
|
||||
const viewElem = ref<InstanceType<typeof ViewBase> | null>(null)
|
||||
|
||||
const queries = [['GET', '/firewall?raw']]
|
||||
const { loading, refetch } = useInitialQueries([['GET', '/firewall?raw']], {
|
||||
onQueriesResponse,
|
||||
})
|
||||
|
||||
const fields = [
|
||||
{ key: 'port', label: t('port') },
|
||||
|
@ -58,7 +57,7 @@ const protocolChoices = [
|
|||
const upnpEnabled = ref()
|
||||
const upnpError = ref('')
|
||||
|
||||
function onQueriesResponse(data) {
|
||||
function onQueriesResponse(data: any) {
|
||||
const ports = Object.values(data).reduce(
|
||||
(ports_, protocols_) => {
|
||||
for (const type of ['TCP', 'UDP']) {
|
||||
|
@ -132,7 +131,7 @@ async function toggleUpnp(value) {
|
|||
)
|
||||
.then(() => {
|
||||
// FIXME Couldn't test when it works.
|
||||
viewElem.value!.fetchQueries()
|
||||
refetch(false)
|
||||
})
|
||||
.catch((err: APIError) => {
|
||||
if (!(err instanceof APIBadRequestError)) throw err
|
||||
|
@ -153,18 +152,13 @@ function onTablePortToggling(port, protocol, connection, index, value) {
|
|||
|
||||
function onFormPortToggling() {
|
||||
togglePort(form).then((toggled) => {
|
||||
if (toggled) viewElem.value!.fetchQueries()
|
||||
if (toggled) refetch(false)
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ViewBase
|
||||
:queries="queries"
|
||||
@queries-response="onQueriesResponse"
|
||||
ref="viewElem"
|
||||
skeleton="CardFormSkeleton"
|
||||
>
|
||||
<ViewBase :loading="loading" skeleton="CardFormSkeleton">
|
||||
<!-- PORTS -->
|
||||
<YCard :title="$t('ports')" icon="shield">
|
||||
<div v-for="(items, protocol) in protocols" :key="protocol">
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
import { computed, ref } from 'vue'
|
||||
|
||||
import api, { objectToParams } from '@/api'
|
||||
import type ViewBase from '@/components/globals/ViewBase.vue'
|
||||
import type { APIQuery } from '@/api/api'
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
import { escapeHtml } from '@/helpers/commons'
|
||||
import { readableDate } from '@/helpers/filters/date'
|
||||
|
||||
|
@ -10,10 +11,8 @@ const props = defineProps<{
|
|||
name: string
|
||||
}>()
|
||||
|
||||
const viewElem = ref<InstanceType<typeof ViewBase> | null>(null)
|
||||
|
||||
const numberOfLines = ref(25)
|
||||
const queries = computed(() => {
|
||||
const queries = computed<APIQuery[]>(() => {
|
||||
const queryString = objectToParams({
|
||||
filter_irrelevant: '',
|
||||
with_suboperations: '',
|
||||
|
@ -21,6 +20,9 @@ const queries = computed(() => {
|
|||
})
|
||||
return [['GET', `logs/${props.name}?${queryString}`]]
|
||||
})
|
||||
const { loading, refetch } = useInitialQueries(queries, {
|
||||
onQueriesResponse,
|
||||
})
|
||||
|
||||
// Log data
|
||||
const description = ref()
|
||||
|
@ -29,7 +31,7 @@ const logs = ref()
|
|||
// Logs line display
|
||||
const moreLogsAvailable = ref(false)
|
||||
|
||||
function onQueriesResponse(log) {
|
||||
function onQueriesResponse(log: any) {
|
||||
if (log.logs.length === numberOfLines.value) {
|
||||
moreLogsAvailable.value = true
|
||||
numberOfLines.value *= 10
|
||||
|
@ -77,12 +79,7 @@ function shareLogs() {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<ViewBase
|
||||
:queries="queries"
|
||||
@queries-response="onQueriesResponse"
|
||||
ref="viewElem"
|
||||
skeleton="CardInfoSkeleton"
|
||||
>
|
||||
<ViewBase :loading="loading" skeleton="CardInfoSkeleton">
|
||||
<!-- INFO CARD -->
|
||||
<YCard :title="description" icon="info-circle">
|
||||
<BRow
|
||||
|
@ -135,7 +132,7 @@ function shareLogs() {
|
|||
v-if="moreLogsAvailable"
|
||||
variant="white"
|
||||
class="w-100 rounded-0"
|
||||
@click="viewElem!.fetchQueries()"
|
||||
@click="refetch(false)"
|
||||
>
|
||||
<YIcon iname="plus" /> {{ $t('logs_more') }}
|
||||
</BButton>
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
import { distanceToNow, readableDate } from '@/helpers/filters/date'
|
||||
|
||||
const queries = [['GET', `logs?limit=${25}&with_details`]]
|
||||
const { loading } = useInitialQueries(
|
||||
[['GET', `logs?limit=${25}&with_details`]],
|
||||
{ onQueriesResponse },
|
||||
)
|
||||
|
||||
const search = ref('')
|
||||
const operations = ref()
|
||||
|
||||
|
@ -16,7 +21,7 @@ const filteredOperations = computed(() => {
|
|||
return operations_.length ? operations_ : null
|
||||
})
|
||||
|
||||
function onQueriesResponse({ operation }) {
|
||||
function onQueriesResponse({ operation }: any) {
|
||||
operation.forEach((log, index) => {
|
||||
if (log.success === '?') {
|
||||
operation[index].icon = 'question'
|
||||
|
@ -36,11 +41,10 @@ function onQueriesResponse({ operation }) {
|
|||
<template>
|
||||
<ViewSearch
|
||||
v-model:search="search"
|
||||
:items="operations"
|
||||
:filtered-items="filteredOperations"
|
||||
:items="operations"
|
||||
items-name="logs"
|
||||
:queries="queries"
|
||||
@queries-response="onQueriesResponse"
|
||||
:loading="loading"
|
||||
skeleton="CardListSkeleton"
|
||||
>
|
||||
<YCard :title="$t('logs_operation')" icon="wrench" no-body>
|
||||
|
|
|
@ -3,24 +3,28 @@ import { reactive, ref } from 'vue'
|
|||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import api from '@/api'
|
||||
import type ViewBase from '@/components/globals/ViewBase.vue'
|
||||
import { useAutoModal } from '@/composables/useAutoModal'
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
|
||||
// FIXME not tested with pending migrations (disclaimer and stuff)
|
||||
const { t } = useI18n()
|
||||
const modalConfirm = useAutoModal()
|
||||
const { loading, refetch } = useInitialQueries(
|
||||
[
|
||||
['GET', 'migrations?pending'],
|
||||
['GET', 'migrations?done'],
|
||||
],
|
||||
{ onQueriesResponse },
|
||||
)
|
||||
|
||||
const viewElem = ref<InstanceType<typeof ViewBase> | null>(null)
|
||||
|
||||
const queries = [
|
||||
['GET', 'migrations?pending'],
|
||||
['GET', 'migrations?done'],
|
||||
]
|
||||
const pending = ref()
|
||||
const done = ref()
|
||||
const checked = reactive({})
|
||||
|
||||
function onQueriesResponse({ migrations: pending_ }, { migrations: done_ }) {
|
||||
function onQueriesResponse(
|
||||
{ migrations: pending_ }: any,
|
||||
{ migrations: done_ }: any,
|
||||
) {
|
||||
done.value = done_.length ? done_.reverse() : null
|
||||
pending_.forEach((migration) => {
|
||||
if (migration.disclaimer) {
|
||||
|
@ -43,7 +47,7 @@ function runMigrations() {
|
|||
if (Object.values(checked).every((value) => value === true)) {
|
||||
api
|
||||
.put('migrations?accept_disclaimer', {}, 'migrations.run')
|
||||
.then(() => viewElem.value!.fetchQueries())
|
||||
.then(() => refetch(false))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,16 +56,12 @@ async function skipMigration(id) {
|
|||
if (!confirmed) return
|
||||
api
|
||||
.put('/migrations/' + id, { skip: '', targets: id }, 'migration.skip')
|
||||
.then(() => viewElem.value!.fetchQueries())
|
||||
.then(() => refetch(false))
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ViewBase
|
||||
:queries="queries"
|
||||
@queries-response="onQueriesResponse"
|
||||
ref="viewElem"
|
||||
>
|
||||
<ViewBase :loading="loading">
|
||||
<!-- PENDING MIGRATIONS -->
|
||||
<YCard :title="$t('migrations_pending')" icon="cogs" no-body>
|
||||
<template #header-buttons v-if="pending">
|
||||
|
|
|
@ -4,20 +4,20 @@ import { reactive, ref } from 'vue'
|
|||
import api, { objectToParams } from '@/api'
|
||||
import { APIBadRequestError, type APIError } from '@/api/errors'
|
||||
import ConfigPanels from '@/components/ConfigPanels.vue'
|
||||
import type ViewBase from '@/components/globals/ViewBase.vue'
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
import {
|
||||
formatFormData,
|
||||
formatYunoHostConfigPanels,
|
||||
} from '@/helpers/yunohostArguments'
|
||||
|
||||
const viewElem = ref<InstanceType<typeof ViewBase> | null>(null)
|
||||
|
||||
const queries = [['GET', 'settings?full']]
|
||||
const { loading, refetch } = useInitialQueries([['GET', 'settings?full']], {
|
||||
onQueriesResponse,
|
||||
})
|
||||
const config = ref({})
|
||||
// FIXME user proper useValidate stuff
|
||||
const externalResults = reactive({})
|
||||
|
||||
function onQueriesResponse(config_) {
|
||||
function onQueriesResponse(config_: any) {
|
||||
config.value = formatYunoHostConfigPanels(config_)
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ async function onConfigSubmit({ id, form }) {
|
|||
{ args: objectToParams(args) },
|
||||
{ key: 'settings.update', panel: id },
|
||||
)
|
||||
.then(() => viewElem.value!.fetchQueries({ triggerLoading: true }))
|
||||
.then(() => refetch())
|
||||
.catch((err: APIError) => {
|
||||
if (!(err instanceof APIBadRequestError)) throw err
|
||||
const panel = config.value.panels.find((panel) => panel.id === id)
|
||||
|
@ -50,12 +50,7 @@ async function onConfigSubmit({ id, form }) {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<ViewBase
|
||||
:queries="queries"
|
||||
@queries-response="onQueriesResponse"
|
||||
ref="viewElem"
|
||||
skeleton="CardFormSkeleton"
|
||||
>
|
||||
<ViewBase :loading="loading" skeleton="CardFormSkeleton">
|
||||
<ConfigPanels
|
||||
v-if="config.panels"
|
||||
v-bind="config"
|
||||
|
|
|
@ -6,13 +6,16 @@ import { useStore } from 'vuex'
|
|||
import api from '@/api'
|
||||
import CardCollapse from '@/components/CardCollapse.vue'
|
||||
import { useAutoModal } from '@/composables/useAutoModal'
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
import { useStoreGetters } from '@/store/utils'
|
||||
|
||||
const { t } = useI18n()
|
||||
const store = useStore()
|
||||
const modalConfirm = useAutoModal()
|
||||
|
||||
const queries = [['PUT', 'update/all', {}, 'update']]
|
||||
const { loading } = useInitialQueries([['PUT', 'update/all', {}, 'update']], {
|
||||
wait: true,
|
||||
onQueriesResponse,
|
||||
})
|
||||
|
||||
const { dark } = useStoreGetters()
|
||||
const system = ref()
|
||||
|
@ -26,13 +29,13 @@ const preUpgrade = ref({
|
|||
})
|
||||
|
||||
function onQueriesResponse({
|
||||
apps,
|
||||
system,
|
||||
apps_,
|
||||
system_,
|
||||
important_yunohost_upgrade,
|
||||
pending_migrations,
|
||||
}) {
|
||||
apps.value = apps.length ? apps : null
|
||||
system.value = system.length ? system : null
|
||||
}: any) {
|
||||
apps.value = apps_.length ? apps_ : null
|
||||
system.value = system_.length ? system_ : null
|
||||
// eslint-disable-next-line camelcase
|
||||
importantYunohostUpgrade.value = important_yunohost_upgrade
|
||||
pendingMigrations.value = pending_migrations.length !== 0
|
||||
|
@ -113,12 +116,7 @@ async function performSystemUpgrade() {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<ViewBase
|
||||
:queries="queries"
|
||||
queries-wait
|
||||
@queries-response="onQueriesResponse"
|
||||
skeleton="CardListSkeleton"
|
||||
>
|
||||
<ViewBase :loading="loading" skeleton="CardListSkeleton">
|
||||
<!-- MIGRATIONS WARN -->
|
||||
<YAlert v-if="pendingMigrations" variant="warning" alert>
|
||||
<span v-html="$t('pending_migrations')" />
|
||||
|
|
|
@ -6,6 +6,7 @@ import { useRouter } from 'vue-router'
|
|||
|
||||
import api from '@/api'
|
||||
import { APIBadRequestError, type APIError } from '@/api/errors'
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
import {
|
||||
alphalownumdot_,
|
||||
minLength,
|
||||
|
@ -19,11 +20,14 @@ import { useStoreGetters } from '@/store/utils'
|
|||
|
||||
const { t } = useI18n()
|
||||
const router = useRouter()
|
||||
const { loading } = useInitialQueries(
|
||||
[
|
||||
['GET', { uri: 'users' }],
|
||||
['GET', { uri: 'domains' }],
|
||||
],
|
||||
{ onQueriesResponse },
|
||||
)
|
||||
|
||||
const queries = [
|
||||
['GET', { uri: 'users' }],
|
||||
['GET', { uri: 'domains' }],
|
||||
]
|
||||
const { userNames, domainsAsChoices, mainDomain } = useStoreGetters()
|
||||
|
||||
const fields = {
|
||||
|
@ -114,11 +118,7 @@ async function onSubmit() {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<ViewBase
|
||||
:queries="queries"
|
||||
@queries-response="onQueriesResponse"
|
||||
skeleton="CardFormSkeleton"
|
||||
>
|
||||
<ViewBase :loading="loading" skeleton="CardFormSkeleton">
|
||||
<CardForm
|
||||
:title="$t('users_new')"
|
||||
icon="user-plus"
|
||||
|
|
|
@ -6,6 +6,7 @@ import { useRouter } from 'vue-router'
|
|||
|
||||
import api from '@/api'
|
||||
import type ViewBase from '@/components/globals/ViewBase.vue'
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
import { arrayDiff } from '@/helpers/commons'
|
||||
import {
|
||||
emailForward,
|
||||
|
@ -31,13 +32,16 @@ const props = defineProps<{
|
|||
|
||||
const { t } = useI18n()
|
||||
const router = useRouter()
|
||||
const { loading } = useInitialQueries(
|
||||
[
|
||||
['GET', { uri: 'users', param: props.name, storeKey: 'users_details' }],
|
||||
['GET', { uri: 'domains' }],
|
||||
],
|
||||
{ onQueriesResponse },
|
||||
)
|
||||
|
||||
const viewElem = ref<InstanceType<typeof ViewBase> | null>(null)
|
||||
|
||||
const queries = [
|
||||
['GET', { uri: 'users', param: props.name, storeKey: 'users_details' }],
|
||||
['GET', { uri: 'domains' }],
|
||||
]
|
||||
const { user, domainsAsChoices, mainDomain } = useStoreGetters()
|
||||
|
||||
const fields = {
|
||||
|
@ -137,7 +141,7 @@ const rules = computed(() => ({
|
|||
const v$ = useVuelidate(rules, form)
|
||||
const serverError = ref('')
|
||||
|
||||
function onQueriesResponse(user_) {
|
||||
function onQueriesResponse(user_: any) {
|
||||
form.fullname = user_.fullname
|
||||
form.mail = adressToFormValue(user_.mail)
|
||||
if (user_['mail-aliases']) {
|
||||
|
@ -226,12 +230,7 @@ function removeEmailField(type: 'aliases' | 'forward', index: number) {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<ViewBase
|
||||
:queries="queries"
|
||||
@queries-response="onQueriesResponse"
|
||||
skeleton="CardFormSkeleton"
|
||||
ref="viewElem"
|
||||
>
|
||||
<ViewBase ref="viewElem" :loading="loading" skeleton="CardFormSkeleton">
|
||||
<CardForm
|
||||
:title="$t('user_username_edit', { name })"
|
||||
icon="user"
|
||||
|
|
|
@ -3,15 +3,15 @@ import { computed, ref } from 'vue'
|
|||
import { useRouter } from 'vue-router'
|
||||
|
||||
import api from '@/api'
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
import { useStoreGetters } from '@/store/utils'
|
||||
|
||||
const props = defineProps<{ name: string }>()
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const queries = [
|
||||
const { loading } = useInitialQueries([
|
||||
['GET', { uri: 'users', param: props.name, storeKey: 'users_details' }],
|
||||
]
|
||||
])
|
||||
|
||||
const { user: userGetter } = useStoreGetters()
|
||||
const purge = ref(false)
|
||||
|
@ -32,7 +32,7 @@ function deleteUser() {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<ViewBase :queries="queries" skeleton="CardInfoSkeleton">
|
||||
<ViewBase :loading="loading" skeleton="CardInfoSkeleton">
|
||||
<YCard v-if="user" :title="user.fullname" icon="user">
|
||||
<div class="d-flex align-items-center flex-column flex-md-row">
|
||||
<YIcon iname="user" class="fa-fw" />
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
import { computed, ref } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
import { useStoreGetters } from '@/store/utils'
|
||||
|
||||
const store = useStore()
|
||||
|
||||
const queries = [
|
||||
const { loading } = useInitialQueries([
|
||||
[
|
||||
'GET',
|
||||
{
|
||||
|
@ -14,8 +14,7 @@ const queries = [
|
|||
storeKey: 'users',
|
||||
},
|
||||
],
|
||||
]
|
||||
|
||||
])
|
||||
const { users } = useStoreGetters()
|
||||
|
||||
const search = ref('')
|
||||
|
@ -40,10 +39,10 @@ function downloadExport() {
|
|||
<template>
|
||||
<ViewSearch
|
||||
v-model:search="search"
|
||||
:items="users"
|
||||
:filtered-items="filteredUsers"
|
||||
:items="users"
|
||||
items-name="users"
|
||||
:queries="queries"
|
||||
:loading="loading"
|
||||
>
|
||||
<template #top-bar-buttons>
|
||||
<BButton variant="info" :to="{ name: 'group-list' }">
|
||||
|
|
Loading…
Reference in a new issue