mirror of
https://github.com/YunoHost/yunohost-admin.git
synced 2024-09-03 20:06:15 +02:00
refactor: turn infos store to global state
This commit is contained in:
parent
deae1324e1
commit
60b5134dcf
13 changed files with 227 additions and 264 deletions
|
@ -1,23 +1,16 @@
|
|||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
|
||||
import { useInfos } from '@/composables/useInfos'
|
||||
import { useRequests } from '@/composables/useRequests'
|
||||
import { useSettings } from '@/composables/useSettings'
|
||||
import { useStoreGetters } from '@/store/utils'
|
||||
import { HistoryConsole } from '@/views/_partials'
|
||||
|
||||
const store = useStore()
|
||||
|
||||
const { connected, yunohost, ssoLink } = useStoreGetters()
|
||||
const { ssoLink, connected, yunohost, logout, onAppCreated } = useInfos()
|
||||
const { locked } = useRequests()
|
||||
const { spinner, dark } = useSettings()
|
||||
|
||||
async function logout() {
|
||||
store.dispatch('LOGOUT')
|
||||
}
|
||||
|
||||
store.dispatch('ON_APP_CREATED')
|
||||
onAppCreated()
|
||||
|
||||
onMounted(() => {
|
||||
const copypastaCode = ['ArrowDown', 'ArrowDown', 'ArrowUp', 'ArrowUp']
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { useInfos } from '@/composables/useInfos'
|
||||
import {
|
||||
useRequests,
|
||||
type APIRequestAction,
|
||||
|
@ -242,10 +243,10 @@ export default {
|
|||
delay = 2000,
|
||||
initialDelay = 0,
|
||||
}: ReconnectingArgs = {}) {
|
||||
const { getYunoHostVersion } = useInfos()
|
||||
return new Promise((resolve, reject) => {
|
||||
function reconnect(n: number) {
|
||||
store
|
||||
.dispatch('GET_YUNOHOST_INFOS')
|
||||
getYunoHostVersion()
|
||||
.then(resolve)
|
||||
.catch((err: APIError) => {
|
||||
if (err instanceof APIUnauthorizedError) {
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
|
||||
import errors from '@/api/errors'
|
||||
import { useInfos } from '@/composables/useInfos'
|
||||
import {
|
||||
STATUS_VARIANT,
|
||||
type APIRequest,
|
||||
|
@ -39,10 +40,9 @@ export async function getResponseData(response: Response) {
|
|||
* @returns Promise that resolve on websocket 'open' or 'error' event.
|
||||
*/
|
||||
export function openWebSocket(request: APIRequestAction): Promise<Event> {
|
||||
const { host } = useInfos()
|
||||
return new Promise((resolve) => {
|
||||
const ws = new WebSocket(
|
||||
`wss://${store.getters.host}/yunohost/api/messages`,
|
||||
)
|
||||
const ws = new WebSocket(`wss://${host.value}/yunohost/api/messages`)
|
||||
ws.onmessage = ({ data }) => {
|
||||
const messages: Record<'info' | 'success' | 'warning' | 'error', string> =
|
||||
JSON.parse(data)
|
||||
|
|
|
@ -1,16 +1,9 @@
|
|||
<script setup lang="ts">
|
||||
import { useStoreGetters } from '@/store/utils'
|
||||
import { useInfos } from '@/composables/useInfos'
|
||||
|
||||
const { breadcrumb } = useStoreGetters()
|
||||
const { breadcrumb } = useInfos()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.breadcrumb {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
</style>
|
||||
|
||||
<template>
|
||||
<BBreadcrumb v-if="breadcrumb.length">
|
||||
<BBreadcrumbItem to="/">
|
||||
|
@ -19,12 +12,19 @@ const { breadcrumb } = useStoreGetters()
|
|||
</BBreadcrumbItem>
|
||||
|
||||
<BBreadcrumbItem
|
||||
v-for="({ name, text }, i) in breadcrumb"
|
||||
:key="name"
|
||||
:to="{ name }"
|
||||
v-for="({ to, text }, i) in breadcrumb"
|
||||
:key="i"
|
||||
:to="to"
|
||||
:active="i === breadcrumb.length - 1"
|
||||
>
|
||||
{{ text }}
|
||||
</BBreadcrumbItem>
|
||||
</BBreadcrumb>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.breadcrumb {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -10,13 +10,13 @@ import {
|
|||
ModalWaiting,
|
||||
ModalWarning,
|
||||
} from '@/components/modals'
|
||||
import { useInfos } from '@/composables/useInfos'
|
||||
import { useRequests } from '@/composables/useRequests'
|
||||
import { useSettings } from '@/composables/useSettings'
|
||||
import { useStoreGetters } from '@/store/utils'
|
||||
import type { VueClass } from '@/types/commons'
|
||||
|
||||
const router = useRouter()
|
||||
const { routerKey } = useStoreGetters()
|
||||
const { routerKey } = useInfos()
|
||||
const { reconnecting, currentRequest, dismissModal } = useRequests()
|
||||
const { transitions, transitionName, dark } = useSettings()
|
||||
|
||||
|
|
|
@ -1,212 +1,189 @@
|
|||
import { createGlobalState, useLocalStorage } from '@vueuse/core'
|
||||
import { computed, ref } from 'vue'
|
||||
import type {
|
||||
RouteLocationNormalized,
|
||||
RouteLocationNormalizedLoaded,
|
||||
RouteRecordNormalized,
|
||||
} from 'vue-router'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
import api from '@/api'
|
||||
import { useRequests, type ReconnectingArgs } from '@/composables/useRequests'
|
||||
import { isEmptyValue, timeout } from '@/helpers/commons'
|
||||
import i18n from '@/i18n'
|
||||
import router from '@/router'
|
||||
import { useStoreGetters } from '@/store/utils'
|
||||
import type { CustomRoute, RouteFromTo } from '@/types/commons'
|
||||
import { useRequests, type ReconnectingArgs } from './useRequests'
|
||||
|
||||
export default {
|
||||
state: {
|
||||
host: window.location.host, // String
|
||||
installed: null,
|
||||
connected: localStorage.getItem('connected') === 'true', // Boolean
|
||||
yunohost: null, // Object { version, repo }
|
||||
routerKey: undefined, // String if current route has params
|
||||
breadcrumb: [], // Array of routes
|
||||
transitionName: null, // String of CSS class if transitions are enabled
|
||||
},
|
||||
export const useInfos = createGlobalState(() => {
|
||||
const router = useRouter()
|
||||
|
||||
mutations: {
|
||||
SET_INSTALLED(state, boolean) {
|
||||
state.installed = boolean
|
||||
},
|
||||
const host = ref(window.location.host)
|
||||
const installed = ref<boolean | undefined>()
|
||||
const connected = useLocalStorage('connected', false)
|
||||
const yunohost = ref<{ version: string; repo: string } | undefined>()
|
||||
const routerKey = ref<string | undefined>()
|
||||
const breadcrumb = ref<CustomRoute[]>([])
|
||||
|
||||
SET_CONNECTED(state, boolean) {
|
||||
localStorage.setItem('connected', boolean)
|
||||
state.connected = boolean
|
||||
},
|
||||
const { mainDomain } = useStoreGetters()
|
||||
const ssoLink = computed(() => {
|
||||
return `//${mainDomain.value ?? host.value}/yunohost/sso`
|
||||
})
|
||||
|
||||
SET_YUNOHOST_INFOS(state, yunohost) {
|
||||
state.yunohost = yunohost
|
||||
},
|
||||
// INIT
|
||||
|
||||
SET_ROUTER_KEY(state, key) {
|
||||
state.routerKey = key
|
||||
},
|
||||
|
||||
SET_BREADCRUMB(state, breadcrumb) {
|
||||
state.breadcrumb = breadcrumb
|
||||
},
|
||||
|
||||
SET_TRANSITION_NAME(state, transitionName) {
|
||||
state.transitionName = transitionName
|
||||
},
|
||||
},
|
||||
|
||||
actions: {
|
||||
async ON_APP_CREATED({ dispatch, state }) {
|
||||
await dispatch('CHECK_INSTALL')
|
||||
|
||||
if (!state.installed) {
|
||||
router.push({ name: 'post-install' })
|
||||
} else {
|
||||
dispatch('CONNECT')
|
||||
}
|
||||
},
|
||||
|
||||
async CHECK_INSTALL({ dispatch, commit }, retry = 2) {
|
||||
// this action will try to query the `/installed` route 3 times every 5 s with
|
||||
// a timeout of the same delay.
|
||||
// FIXME need testing with api not responding
|
||||
try {
|
||||
const { installed } = await timeout(api.get('installed'), 5000)
|
||||
commit('SET_INSTALLED', installed)
|
||||
return installed
|
||||
} catch (err) {
|
||||
if (retry > 0) {
|
||||
return dispatch('CHECK_INSTALL', --retry)
|
||||
}
|
||||
throw err
|
||||
}
|
||||
},
|
||||
|
||||
async CONNECT({ commit, dispatch }) {
|
||||
// If the user is not connected, the first action will throw
|
||||
// and login prompt will be shown automaticly
|
||||
await dispatch('GET_YUNOHOST_INFOS')
|
||||
commit('SET_CONNECTED', true)
|
||||
await api.get({ uri: 'domains', storeKey: 'domains' })
|
||||
},
|
||||
|
||||
RESET_CONNECTED({ commit }) {
|
||||
commit('SET_CONNECTED', false)
|
||||
commit('SET_YUNOHOST_INFOS', null)
|
||||
},
|
||||
|
||||
DISCONNECT({ dispatch }, route) {
|
||||
// FIXME vue3 currentRoute is now a ref (currentRoute.value)
|
||||
dispatch('RESET_CONNECTED')
|
||||
if (router.currentRoute.value.name === 'login') return
|
||||
const previousRoute = route ?? router.currentRoute.value
|
||||
router.push({
|
||||
name: 'login',
|
||||
// Add a redirect query if next route is not unknown (like `logout`) or `login`
|
||||
query:
|
||||
previousRoute && !['login', null].includes(previousRoute.name)
|
||||
? { redirect: previousRoute.path }
|
||||
: {},
|
||||
})
|
||||
},
|
||||
|
||||
LOGIN({ dispatch }, credentials) {
|
||||
return api
|
||||
.post('login', { credentials }, null, { websocket: false })
|
||||
.then(() => {
|
||||
return dispatch('CONNECT')
|
||||
})
|
||||
},
|
||||
|
||||
LOGOUT({ dispatch }) {
|
||||
dispatch('DISCONNECT')
|
||||
return api.get('logout')
|
||||
},
|
||||
|
||||
TRY_TO_RECONNECT({ commit }, args?: ReconnectingArgs) {
|
||||
// FIXME This is very ugly arguments forwarding, will use proper component way of doing this when switching to Vue 3 (teleport)
|
||||
useRequests().reconnecting.value = args
|
||||
},
|
||||
|
||||
GET_YUNOHOST_INFOS({ commit }) {
|
||||
return api.get('versions').then((versions) => {
|
||||
commit('SET_YUNOHOST_INFOS', versions.yunohost)
|
||||
})
|
||||
},
|
||||
|
||||
UPDATE_ROUTER_KEY({ commit }, { to, from }) {
|
||||
if (isEmptyValue(to.params)) {
|
||||
commit('SET_ROUTER_KEY', undefined)
|
||||
return
|
||||
}
|
||||
// If the next route uses the same component as the previous one, Vue will not
|
||||
// recreate an instance of that component, so hooks like `created()` will not be
|
||||
// triggered and data will not be fetched.
|
||||
// For routes with params, we create a unique key to force the recreation of a view.
|
||||
// Params can be declared in route `meta` to stricly define which params should be
|
||||
// taken into account.
|
||||
const params = to.meta.routerParams
|
||||
? to.meta.routerParams.map((key) => to.params[key])
|
||||
: Object.values(to.params)
|
||||
|
||||
commit('SET_ROUTER_KEY', `${to.name}-${params.join('-')}`)
|
||||
},
|
||||
|
||||
UPDATE_BREADCRUMB({ commit }, { to, from }) {
|
||||
function getRouteNames(route) {
|
||||
if (route.meta.breadcrumb) return route.meta.breadcrumb
|
||||
const parentRoute = route.matched
|
||||
.slice()
|
||||
.reverse()
|
||||
.find((route) => route.meta.breadcrumb)
|
||||
if (parentRoute) return parentRoute.meta.breadcrumb
|
||||
return []
|
||||
}
|
||||
|
||||
function formatRoute(route) {
|
||||
const { trad, param } = route.meta.args || {}
|
||||
let text = ''
|
||||
// if a traduction key string has been given and we also need to pass
|
||||
// the route param as a variable.
|
||||
if (trad && param) {
|
||||
text = i18n.global.t(trad, { [param]: to.params[param] })
|
||||
} else if (trad) {
|
||||
text = i18n.global.t(trad)
|
||||
} else {
|
||||
text = to.params[param]
|
||||
}
|
||||
return { name: route.name, text }
|
||||
}
|
||||
|
||||
const routeNames = getRouteNames(to)
|
||||
const allRoutes = router.getRoutes()
|
||||
const breadcrumb = routeNames.map((name) => {
|
||||
const route = allRoutes.find((route) => route.name === name)
|
||||
return formatRoute(route)
|
||||
})
|
||||
|
||||
commit('SET_BREADCRUMB', breadcrumb)
|
||||
|
||||
function getTitle(breadcrumb) {
|
||||
if (breadcrumb.length === 0) return formatRoute(to).text
|
||||
return (breadcrumb.length > 2 ? breadcrumb.slice(-2) : breadcrumb)
|
||||
.map((route) => route.text)
|
||||
.reverse()
|
||||
.join(' / ')
|
||||
}
|
||||
|
||||
// Display a simplified breadcrumb as the document title.
|
||||
document.title = `${getTitle(breadcrumb)} | ${i18n.global.t('yunohost_admin')}`
|
||||
},
|
||||
|
||||
UPDATE_TRANSITION_NAME({ state, commit }, { to, from }) {
|
||||
// Use the breadcrumb array length as a direction indicator
|
||||
const toDepth = (to.meta.breadcrumb || []).length
|
||||
const fromDepth = (from.meta.breadcrumb || []).length
|
||||
commit(
|
||||
'SET_TRANSITION_NAME',
|
||||
toDepth < fromDepth ? 'slide-right' : 'slide-left',
|
||||
async function _checkInstall(retry = 2) {
|
||||
// this action will try to query the `/installed` route 3 times every 5 s with
|
||||
// a timeout of the same delay.
|
||||
// FIXME need testing with api not responding
|
||||
try {
|
||||
const data = await timeout(
|
||||
api.get<{ installed: boolean }>('installed'),
|
||||
5000,
|
||||
)
|
||||
},
|
||||
},
|
||||
installed.value = data.installed
|
||||
} catch (err) {
|
||||
if (retry > 0) {
|
||||
return _checkInstall(--retry)
|
||||
}
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
getters: {
|
||||
host: (state) => state.host,
|
||||
installed: (state) => state.installed,
|
||||
connected: (state) => state.connected,
|
||||
yunohost: (state) => state.yunohost,
|
||||
routerKey: (state) => state.routerKey,
|
||||
breadcrumb: (state) => state.breadcrumb,
|
||||
transitionName: (state) => state.transitionName,
|
||||
ssoLink: (state, getters) => {
|
||||
return `//${getters.mainDomain ?? state.host}/yunohost/sso`
|
||||
},
|
||||
},
|
||||
}
|
||||
async function onAppCreated() {
|
||||
await _checkInstall()
|
||||
|
||||
if (!installed.value) {
|
||||
router.push({ name: 'post-install' })
|
||||
} else {
|
||||
_onLogin()
|
||||
}
|
||||
}
|
||||
|
||||
function getYunoHostVersion() {
|
||||
return api.get('versions').then((versions) => {
|
||||
yunohost.value = versions.yunohost
|
||||
})
|
||||
}
|
||||
|
||||
// CONNECTION
|
||||
|
||||
async function _onLogin() {
|
||||
// If the user is not connected, the first action will throw
|
||||
// and login prompt will be shown automaticly
|
||||
await getYunoHostVersion()
|
||||
connected.value = true
|
||||
await api.get({ uri: 'domains', cachePath: 'domainList' })
|
||||
}
|
||||
|
||||
function onLogout(route?: RouteLocationNormalizedLoaded) {
|
||||
connected.value = false
|
||||
yunohost.value = undefined
|
||||
const previousRoute = route ?? router.currentRoute.value
|
||||
if (previousRoute.name === 'login') return
|
||||
router.push({
|
||||
name: 'login',
|
||||
// Add a redirect query if next route is not unknown (like `logout`) or `login`
|
||||
query:
|
||||
previousRoute && !['login', null].includes(previousRoute.name as any)
|
||||
? { redirect: previousRoute.path }
|
||||
: {},
|
||||
})
|
||||
}
|
||||
|
||||
function login(credentials: string) {
|
||||
return api
|
||||
.post({ uri: 'login', data: { credentials }, websocket: false })
|
||||
.then(() => _onLogin())
|
||||
}
|
||||
|
||||
function logout() {
|
||||
onLogout()
|
||||
return api.get('logout')
|
||||
}
|
||||
|
||||
function tryToReconnect(args?: ReconnectingArgs) {
|
||||
useRequests().reconnecting.value = args
|
||||
}
|
||||
|
||||
function updateRouterKey({ to }: RouteFromTo) {
|
||||
if (isEmptyValue(to.params)) {
|
||||
routerKey.value = undefined
|
||||
return
|
||||
}
|
||||
// If the next route uses the same component as the previous one, Vue will not
|
||||
// recreate an instance of that component, so hooks like `created()` will not be
|
||||
// triggered and data will not be fetched.
|
||||
// For routes with params, we create a unique key to force the recreation of a view.
|
||||
// Params can be declared in route `meta` to stricly define which params should be
|
||||
// taken into account.
|
||||
const params = to.meta.routerParams
|
||||
? to.meta.routerParams.map((key) => to.params[key])
|
||||
: Object.values(to.params)
|
||||
|
||||
routerKey.value = `${to.name?.toString()}-${params.join('-')}`
|
||||
}
|
||||
|
||||
function updateBreadcrumb({ to }: RouteFromTo) {
|
||||
function getRouteNames(route: RouteLocationNormalized): string[] {
|
||||
if (route.meta.breadcrumb) return route.meta.breadcrumb
|
||||
const parentRoute = route.matched
|
||||
.slice()
|
||||
.reverse()
|
||||
.find((route) => route.meta.breadcrumb)
|
||||
return parentRoute?.meta.breadcrumb || []
|
||||
}
|
||||
|
||||
function formatRoute(
|
||||
route: RouteRecordNormalized | RouteLocationNormalized,
|
||||
) {
|
||||
const { trad, param } = route.meta.args || {}
|
||||
let text = ''
|
||||
// if a traduction key string has been given and we also need to pass
|
||||
// the route param as a variable.
|
||||
if (trad && param) {
|
||||
text = i18n.global.t(trad, { [param]: to.params[param] })
|
||||
} else if (trad) {
|
||||
text = i18n.global.t(trad)
|
||||
} else if (param) {
|
||||
text = to.params[param] as string
|
||||
}
|
||||
return { to: { name: route.name! }, text }
|
||||
}
|
||||
|
||||
const routeNames = getRouteNames(to)
|
||||
const allRoutes = router.getRoutes()
|
||||
breadcrumb.value = routeNames.map((name) => {
|
||||
const route = allRoutes.find((route) => route.name === name)!
|
||||
return formatRoute(route)
|
||||
})
|
||||
|
||||
function getTitle(breadcrumb: CustomRoute[]) {
|
||||
if (breadcrumb.length === 0) return formatRoute(to).text
|
||||
return (breadcrumb.length > 2 ? breadcrumb.slice(-2) : breadcrumb)
|
||||
.map((route) => route.text)
|
||||
.reverse()
|
||||
.join(' / ')
|
||||
}
|
||||
|
||||
// Display a simplified breadcrumb as the document title.
|
||||
document.title = `${getTitle(breadcrumb.value)} | ${i18n.global.t('yunohost_admin')}`
|
||||
}
|
||||
|
||||
return {
|
||||
host,
|
||||
installed,
|
||||
connected,
|
||||
yunohost,
|
||||
routerKey,
|
||||
breadcrumb,
|
||||
ssoLink,
|
||||
onAppCreated,
|
||||
getYunoHostVersion,
|
||||
onLogout,
|
||||
login,
|
||||
logout,
|
||||
tryToReconnect,
|
||||
updateRouterKey,
|
||||
updateBreadcrumb,
|
||||
}
|
||||
})
|
||||
|
|
|
@ -7,8 +7,8 @@ import type { APIQuery, RequestMethod } from '@/api/api'
|
|||
import { APIErrorLog, type APIError } from '@/api/errors'
|
||||
import { isObjectLiteral } from '@/helpers/commons'
|
||||
import i18n from '@/i18n'
|
||||
import store from '@/store'
|
||||
import type { StateVariant } from '@/types/commons'
|
||||
import { useInfos } from './useInfos'
|
||||
|
||||
export type RequestStatus = 'pending' | 'success' | 'warning' | 'error'
|
||||
|
||||
|
@ -162,7 +162,7 @@ export const useRequests = createGlobalState(() => {
|
|||
err.log()
|
||||
if (err.code === 401) {
|
||||
// Unauthorized
|
||||
store.dispatch('DISCONNECT')
|
||||
useInfos().onLogout()
|
||||
} else if (err instanceof APIErrorLog) {
|
||||
// Errors that have produced logs
|
||||
router.push({ name: 'tool-log', params: { name: err.logRef } })
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { createRouter, createWebHashHistory } from 'vue-router'
|
||||
|
||||
import { useInfos } from '@/composables/useInfos'
|
||||
import { useRequests } from '@/composables/useRequests'
|
||||
import { useSettings } from '@/composables/useSettings'
|
||||
import store from '@/store'
|
||||
import routes from './routes'
|
||||
|
||||
const router = createRouter({
|
||||
|
@ -39,20 +39,22 @@ router.beforeEach((to, from, next) => {
|
|||
dismissModal(currentRequest.value.id)
|
||||
}
|
||||
|
||||
if (to.name === 'post-install' && store.getters.installed) {
|
||||
const { installed, connected, onLogout } = useInfos()
|
||||
if (to.name === 'post-install' && installed.value) {
|
||||
return next('/')
|
||||
}
|
||||
// Allow if connected or route is not protected
|
||||
if (store.getters.connected || to.meta.noAuth) {
|
||||
if (connected.value || to.meta.noAuth) {
|
||||
next()
|
||||
} else {
|
||||
store.dispatch('DISCONNECT', to)
|
||||
onLogout(to)
|
||||
}
|
||||
})
|
||||
|
||||
router.afterEach((to, from) => {
|
||||
store.dispatch('UPDATE_ROUTER_KEY', { to, from })
|
||||
store.dispatch('UPDATE_BREADCRUMB', { to, from })
|
||||
const { updateRouterKey, updateBreadcrumb } = useInfos()
|
||||
updateRouterKey({ to, from })
|
||||
updateBreadcrumb({ to, from })
|
||||
})
|
||||
|
||||
export default router
|
||||
|
|
|
@ -2,11 +2,10 @@
|
|||
import { reactive, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRouter, type LocationQueryValue } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
|
||||
import { useForm } from '@/composables/form'
|
||||
import { useInfos } from '@/composables/useInfos'
|
||||
import { alphalownumdot_, minLength, required } from '@/helpers/validators'
|
||||
import { useStoreGetters } from '@/store/utils'
|
||||
import type { FieldProps, FormFieldDict } from '@/types/form'
|
||||
|
||||
const props = withDefaults(
|
||||
|
@ -19,10 +18,8 @@ const props = withDefaults(
|
|||
)
|
||||
|
||||
const { t } = useI18n()
|
||||
const store = useStore()
|
||||
const router = useRouter()
|
||||
|
||||
const { installed } = useStoreGetters()
|
||||
const { login, installed } = useInfos()
|
||||
|
||||
type Form = typeof form.value
|
||||
const form = ref({
|
||||
|
@ -57,8 +54,7 @@ const { v, onSubmit } = useForm(form, fields)
|
|||
const onLogin = onSubmit((onError) => {
|
||||
const { username, password } = form.value
|
||||
const credentials = [username, password].join(':')
|
||||
store
|
||||
.dispatch('LOGIN', credentials)
|
||||
login(credentials)
|
||||
.then(() => {
|
||||
if (props.forceReload) {
|
||||
window.location.href = '/yunohost/admin/'
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
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 { useInfos } from '@/composables/useInfos'
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
import { isEmptyValue } from '@/helpers/commons'
|
||||
import { readableDate } from '@/helpers/filters/date'
|
||||
|
@ -19,7 +19,6 @@ const props = defineProps<{
|
|||
|
||||
const { t } = useI18n()
|
||||
const router = useRouter()
|
||||
const store = useStore()
|
||||
const modalConfirm = useAutoModal()
|
||||
const { loading } = useInitialQueries(
|
||||
[{ uri: `backups/${props.name}?with_details` }],
|
||||
|
@ -128,9 +127,9 @@ async function deleteBackup() {
|
|||
}
|
||||
|
||||
function downloadBackup() {
|
||||
const host = store.getters.host
|
||||
const { host } = useInfos()
|
||||
window.open(
|
||||
`https://${host}/yunohost/api/backups/${props.name}/download`,
|
||||
`https://${host.value}/yunohost/api/backups/${props.name}/download`,
|
||||
'_blank',
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<script setup lang="ts">
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useStore } from 'vuex'
|
||||
|
||||
import api from '@/api'
|
||||
import { useAutoModal } from '@/composables/useAutoModal'
|
||||
import { useInfos } from '@/composables/useInfos'
|
||||
|
||||
const { t } = useI18n()
|
||||
const store = useStore()
|
||||
const modalConfirm = useAutoModal()
|
||||
const { tryToReconnect } = useInfos()
|
||||
|
||||
async function triggerAction(action) {
|
||||
const confirmed = await modalConfirm(t('confirm_reboot_action_' + action))
|
||||
|
@ -15,11 +15,7 @@ async function triggerAction(action) {
|
|||
|
||||
api.put({ uri: action + '?force', humanKey: action }).then(() => {
|
||||
const delay = action === 'reboot' ? 4000 : 10000
|
||||
store.dispatch('TRY_TO_RECONNECT', {
|
||||
attemps: Infinity,
|
||||
origin: action,
|
||||
delay,
|
||||
})
|
||||
tryToReconnect({ attemps: Infinity, origin: action, delay })
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useStore } from 'vuex'
|
||||
|
||||
import api from '@/api'
|
||||
import CardCollapse from '@/components/CardCollapse.vue'
|
||||
import { useAutoModal } from '@/composables/useAutoModal'
|
||||
import { useInfos } from '@/composables/useInfos'
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
|
||||
const { t } = useI18n()
|
||||
const store = useStore()
|
||||
const { tryToReconnect } = useInfos()
|
||||
const modalConfirm = useAutoModal()
|
||||
const { loading } = useInitialQueries(
|
||||
[{ method: 'PUT', uri: 'update/all', humanKey: 'update' }],
|
||||
|
@ -105,7 +105,7 @@ async function performSystemUpgrade() {
|
|||
|
||||
api.put({ uri: 'upgrade/system', humanKey: 'upgrade.system' }).then(() => {
|
||||
if (system.value.some(({ name }) => name.includes('yunohost'))) {
|
||||
store.dispatch('TRY_TO_RECONNECT', {
|
||||
tryToReconnect({
|
||||
attemps: 1,
|
||||
origin: 'upgrade_system',
|
||||
initialDelay: 2000,
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
<script setup lang="ts">
|
||||
import { type ComputedRef } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
|
||||
import { useInfos } from '@/composables/useInfos'
|
||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
||||
import { useSearch } from '@/composables/useSearch'
|
||||
import { useStoreGetters } from '@/store/utils'
|
||||
import type { Obj } from '@/types/commons'
|
||||
|
||||
const store = useStore()
|
||||
const { loading } = useInitialQueries([
|
||||
{
|
||||
uri: 'users?fields=username&fields=fullname&fields=mail&fields=mailbox-quota&fields=groups',
|
||||
|
@ -23,8 +22,8 @@ const [search, filteredUsers] = useSearch(
|
|||
)
|
||||
|
||||
function downloadExport() {
|
||||
const host = store.getters.host
|
||||
window.open(`https://${host}/yunohost/api/users/export`, '_blank')
|
||||
const { host } = useInfos()
|
||||
window.open(`https://${host.value}/yunohost/api/users/export`, '_blank')
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
Loading…
Reference in a new issue