chore: component names to PascalCase

This commit is contained in:
axolotle 2024-02-24 14:33:11 +01:00
parent e5a3f5df2b
commit 159f1b5a1a
79 changed files with 1184 additions and 1184 deletions

View file

@ -2,8 +2,8 @@
<div id="app" class="container">
<!-- HEADER -->
<header>
<b-navbar>
<b-navbar-brand
<BNavbar>
<BNavbarBrand
:to="{ name: 'home' }" :disabled="waiting"
exact exact-active-class="active"
>
@ -13,67 +13,67 @@
<span v-else>
<img alt="YunoHost logo" src="./assets/logo_dark.png" width="40">
</span>
</b-navbar-brand>
</BNavbarBrand>
<b-navbar-nav class="ml-auto">
<BNavbarNav class="ml-auto">
<li class="nav-item">
<b-button
<BButton
:href="ssoLink"
variant="primary" size="sm" block
>
{{ $t('user_interface_link') }} <icon iname="user" />
</b-button>
{{ $t('user_interface_link') }} <Icon iname="user" />
</BButton>
</li>
<li class="nav-item" v-show="connected">
<b-button
<BButton
@click.prevent="logout"
variant="outline-dark" block size="sm"
>
{{ $t('logout') }} <icon iname="sign-out" />
</b-button>
{{ $t('logout') }} <Icon iname="sign-out" />
</BButton>
</li>
</b-navbar-nav>
</b-navbar>
</BNavbarNav>
</BNavbar>
</header>
<!-- MAIN -->
<view-lock-overlay>
<breadcrumb />
<ViewLockOverlay>
<Breadcrumb />
<main id="main">
<!-- The `key` on router-view make sure that if a link points to a page that
<!-- The `key` on RouterView make sure that if a link points to a page that
use the same component as the previous one, it will be refreshed -->
<transition v-if="transitions" :name="transitionName">
<router-view class="animated" :key="routerKey" />
</transition>
<router-view v-else class="static" :key="routerKey" />
<Transition v-if="transitions" :name="transitionName">
<RouterView class="animated" :key="routerKey" />
</Transition>
<RouterView v-else class="static" :key="routerKey" />
</main>
</view-lock-overlay>
</ViewLockOverlay>
<!-- HISTORY CONSOLE -->
<history-console />
<HistoryConsole />
<!-- FOOTER -->
<footer class="py-3 mt-auto">
<nav>
<b-nav class="justify-content-center">
<b-nav-item href="https://yunohost.org/docs" target="_blank" link-classes="text-secondary">
<icon iname="book" /> {{ $t('footer.documentation') }}
</b-nav-item>
<b-nav-item href="https://yunohost.org/help" target="_blank" link-classes="text-secondary">
<icon iname="life-ring" /> {{ $t('footer.help') }}
</b-nav-item>
<b-nav-item href="https://donate.yunohost.org/" target="_blank" link-classes="text-secondary">
<icon iname="heart" /> {{ $t('footer.donate') }}
</b-nav-item>
<BNav class="justify-content-center">
<BNavItem href="https://yunohost.org/docs" target="_blank" link-classes="text-secondary">
<Icon iname="book" /> {{ $t('footer.documentation') }}
</BNavItem>
<BNavItem href="https://yunohost.org/help" target="_blank" link-classes="text-secondary">
<Icon iname="life-ring" /> {{ $t('footer.help') }}
</BNavItem>
<BNavItem href="https://donate.yunohost.org/" target="_blank" link-classes="text-secondary">
<Icon iname="heart" /> {{ $t('footer.donate') }}
</BNavItem>
<b-nav-text
<BNavText
v-if="yunohost" id="yunohost-version" class="ml-md-auto text-center"
>
<span v-html="$t('footer_version', yunohost)" />
</b-nav-text>
</b-nav>
</BNavText>
</BNav>
</nav>
</footer>
</div>
@ -209,7 +209,7 @@ main {
top: 0;
transform: translate(-100vw, 0);
}
// hack to hide last transition provoqued by the <router-view> element change
// hack to hide last transition provoqued by the <RouterView> element change
// while disabling the transitions in ToolWebAdmin
.static ~ .animated {
display: none;

View file

@ -1,6 +1,6 @@
<template>
<b-input-group v-bind="$attrs">
<input-item
<BInputGroup v-bind="$attrs">
<InputItem
:id="id"
:value="value.localPart"
:placeholder="placeholder"
@ -10,23 +10,23 @@
@blur="$parent.$emit('touch')"
/>
<b-input-group-append>
<b-input-group-text>{{ value.separator }}</b-input-group-text>
</b-input-group-append>
<BInputGroupAppend>
<BInputGroupText>{{ value.separator }}</BInputGroupText>
</BInputGroupAppend>
<b-input-group-append>
<select-item
<BInputGroupAppend>
<SelectItem
:value="value.domain"
:choices="choices"
:aria-describedby="id + 'domain-desc'"
@input="onInput('domain', $event)"
@blur="$parent.$emit('touch')"
/>
</b-input-group-append>
</BInputGroupAppend>
<span class="sr-only" :id="id + 'local-part-desc'" v-t="'address.local_part_description.' + type" />
<span class="sr-only" :id="id + 'domain-desc'" v-t="'address.domain_description.' + type" />
</b-input-group>
</BInputGroup>
</template>
<script>

View file

@ -1,26 +1,26 @@
<template>
<b-card
<BCard
v-bind="$attrs"
no-body :class="_class"
>
<slot name="header" slot="header">
<h2>
<b-button v-b-toggle="id" :variant="variant" class="card-collapse-button">
<BButton v-b-toggle="id" :variant="variant" class="card-collapse-button">
{{ title }}
<icon class="ml-auto" iname="chevron-right" />
</b-button>
<Icon class="ml-auto" iname="chevron-right" />
</BButton>
</h2>
</slot>
<b-collapse :id="id" :visible="visible" role="region">
<BCollapse :id="id" :visible="visible" role="region">
<slot name="default" />
</b-collapse>
</b-card>
</BCollapse>
</BCard>
</template>
<script>
export default {
name: 'CollapseCard',
name: 'CardCollapse',
props: {
id: { type: String, required: true },

View file

@ -63,7 +63,7 @@ export default {
render (h) {
return h(
'b-card-group',
'BCardGroup',
{
attrs: { role: 'feed', 'aria-busy': this.busy.toString() },
props: { deck: true },

View file

@ -1,5 +1,5 @@
<template>
<abstract-form
<AbstractForm
v-bind="{ id: panel.id + '-form', validation, serverError: panel.serverError }"
@submit.prevent.stop="onApply"
:no-footer="!panel.hasApplyButton"
@ -13,31 +13,31 @@
<slot name="tab-before" />
<template v-for="section in panel.sections">
<component
<Component
v-if="section.visible"
:is="section.name ? 'section' : 'div'"
:key="section.id"
class="panel-section"
>
<b-card-title v-if="section.name" title-tag="h3">
<BCardTitle v-if="section.name" title-tag="h3">
{{ section.name }} <small v-if="section.help">{{ section.help }}</small>
</b-card-title>
</BCardTitle>
<template v-for="(field, fname) in section.fields">
<!-- FIXME rework the whole component chain to avoid direct mutation of the `forms` props -->
<!-- eslint-disable -->
<component
<Component
v-if="field.visible" :is="field.is" v-bind="field.props"
v-model="forms[panel.id][fname]" :validation="validation[fname]" :key="fname"
@action.stop="onAction(section.id, fname, section.fields)"
/>
<!-- eslint-enable -->
</template>
</component>
</Component>
</template>
<slot name="tab-after" />
</abstract-form>
</AbstractForm>
</template>
<script>

View file

@ -1,6 +1,6 @@
<template>
<div class="config-panel">
<routable-tabs
<RoutableTabs
v-if="routes_.length > 1"
:routes="routes_"
v-bind="{ panels, forms, v: $v, ...$attrs }"
@ -15,13 +15,13 @@
<template #tab-after>
<slot name="tab-after" />
</template>
</routable-tabs>
</RoutableTabs>
<card v-else :title="routes_[0].text" :icon="routes_[0].icon">
<Card v-else :title="routes_[0].text" :icon="routes_[0].icon">
<slot name="tab-top" />
<slot name="tab-before" />
<slot name="tab-after" />
</card>
</Card>
</div>
</template>

View file

@ -1,21 +1,21 @@
<template>
<b-list-group
<BListGroup
v-bind="$attrs" flush
:class="{ 'fixed-height': fixedHeight, 'bordered': bordered }"
@scroll="onScroll"
>
<yuno-list-group-item
<YunoListGroupItem
v-if="limit && messages.length > limit"
variant="info" v-t="'api.partial_logs'"
/>
<yuno-list-group-item
<YunoListGroupItem
v-for="({ color, text }, i) in reducedMessages" :key="i"
:variant="color" size="xs"
>
<span v-html="text" />
</yuno-list-group-item>
</b-list-group>
</YunoListGroupItem>
</BListGroup>
</template>
<script>

View file

@ -11,16 +11,16 @@
<div v-if="request.errors || request.warnings">
<!-- WEBSOCKET ERRORS COUNT -->
<span class="count" v-if="request.errors">
{{ request.errors }}<icon iname="bug" class="text-danger ml-1" />
{{ request.errors }}<Icon iname="bug" class="text-danger ml-1" />
</span>
<!-- WEBSOCKET WARNINGS COUNT -->
<span class="count" v-if="request.warnings">
{{ request.warnings }}<icon iname="warning" class="text-warning ml-1" />
{{ request.warnings }}<Icon iname="warning" class="text-warning ml-1" />
</span>
</div>
<!-- VIEW ERROR BUTTON -->
<b-button
<BButton
v-if="showError && request.error"
size="sm" pill
class="error-btn ml-auto py-0"
@ -28,7 +28,7 @@
@click="reviewError"
>
<small v-t="'api_error.view_error'" />
</b-button>
</BButton>
<!-- TIME DISPLAY -->
<time v-if="showTime" :datetime="request.date | hour" :class="request.error ? 'ml-2' : 'ml-auto'">

View file

@ -1,14 +1,14 @@
<template>
<b-list-group :flush="flush" :style="{ '--depth': tree.depth }">
<BListGroup :flush="flush" :style="{ '--depth': tree.depth }">
<template v-for="(node, i) in tree.children">
<b-list-group-item
<BListGroupItem
:key="node.id"
class="list-group-item-action" :class="getClasses(node, i)"
@click="$router.push(node.data.to)"
>
<slot name="default" v-bind="node" />
<b-button
<BButton
v-if="node.children"
size="xs" variant="outline-secondary"
:aria-expanded="node.data.opened ? 'true' : 'false'" :aria-controls="'collapse-' + node.id"
@ -16,15 +16,15 @@
@click.stop="node.data.opened = !node.data.opened"
>
<span class="sr-only">{{ toggleText }}</span>
<icon iname="chevron-right" />
</b-button>
</b-list-group-item>
<Icon iname="chevron-right" />
</BButton>
</BListGroupItem>
<b-collapse
<BCollapse
v-if="node.children" :key="'collapse-' + node.id"
v-model="node.data.opened" :id="'collapse-' + node.id"
>
<recursive-list-group
<RecursiveListGroup
:tree="node"
:last="last !== undefined ? last : i === tree.children.length - 1" flush
>
@ -32,10 +32,10 @@
<template slot="default" slot-scope="scope">
<slot name="default" v-bind="scope" />
</template>
</recursive-list-group>
</b-collapse>
</RecursiveListGroup>
</BCollapse>
</template>
</b-list-group>
</BListGroup>
</template>
<script>

View file

@ -1,19 +1,19 @@
<template>
<b-card no-body>
<b-card-header header-tag="nav">
<b-nav card-header fill pills>
<b-nav-item
<BCard no-body>
<BCardHeader header-tag="nav">
<BNav card-header fill pills>
<BNavItem
v-for="route in routes" :key="route.text"
:to="route.to" exact exact-active-class="active"
>
<icon v-if="route.icon" :iname="route.icon" />
<Icon v-if="route.icon" :iname="route.icon" />
{{ route.text }}
</b-nav-item>
</b-nav>
</b-card-header>
</BNavItem>
</BNav>
</BCardHeader>
<!-- Bind extra props to the child view and forward child events to parent -->
<router-view v-bind="$attrs" v-on="$listeners">
<RouterView v-bind="$attrs" v-on="$listeners">
<template #tab-top>
<slot name="tab-top" />
</template>
@ -23,8 +23,8 @@
<template #tab-after>
<slot name="tab-after" />
</template>
</router-view>
</b-card>
</RouterView>
</BCard>
</template>
<script>

View file

@ -1,32 +1,32 @@
<template>
<div>
<b-card-body>
<BCardBody>
<slot name="disclaimer" />
<b-form
<BForm
:id="id" :inline="inline" :class="formClasses"
@submit.prevent="onSubmit" novalidate
>
<slot name="default" />
<slot name="server-error" v-bind="{ errorFeedback }">
<b-alert
<BAlert
v-if="errorFeedback"
variant="danger" class="my-3" icon="ban"
>
<div v-html="errorFeedback" />
</b-alert>
</BAlert>
</slot>
</b-form>
</b-card-body>
</BForm>
</BCardBody>
<b-card-footer v-if="!noFooter">
<BCardFooter v-if="!noFooter">
<slot name="footer">
<b-button type="submit" variant="success" :form="id">
<BButton type="submit" variant="success" :form="id">
{{ submitText || $t('save') }}
</b-button>
</BButton>
</slot>
</b-card-footer>
</BCardFooter>
</div>
</template>

View file

@ -1,17 +1,17 @@
<template>
<b-breadcrumb v-if="breadcrumb.length">
<b-breadcrumb-item to="/">
<BBreadcrumb v-if="breadcrumb.length">
<BBreadcrumbItem to="/">
<span class="sr-only">{{ $t('home') }}</span>
<icon iname="home" />
</b-breadcrumb-item>
<Icon iname="home" />
</BBreadcrumbItem>
<b-breadcrumb-item
<BBreadcrumbItem
v-for="({ name, text }, i) in breadcrumb" :key="name"
:to="{ name }" :active="i === breadcrumb.length - 1"
>
{{ text }}
</b-breadcrumb-item>
</b-breadcrumb>
</BBreadcrumbItem>
</BBreadcrumb>
</template>
<script>

View file

@ -1,11 +1,11 @@
<template>
<b-card v-bind="$attrs" :no-body="collapsable ? true : $attrs['no-body']">
<BCard v-bind="$attrs" :no-body="collapsable ? true : $attrs['no-body']">
<template #header>
<div class="w-100 d-flex align-items-center flex-wrap custom-header">
<slot name="header">
<component :is="titleTag" class="custom-header-title">
<icon v-if="icon" :iname="icon" class="mr-2" />{{ title }}
</component>
<Component :is="titleTag" class="custom-header-title">
<Icon v-if="icon" :iname="icon" class="mr-2" />{{ title }}
</Component>
<slot name="header-next" />
</slot>
@ -14,22 +14,22 @@
</div>
</div>
<b-button
<BButton
v-if="collapsable" @click="visible = !visible"
size="sm" variant="outline-secondary"
class="align-self-center ml-auto" :class="{ 'not-collapsed': visible, 'collapsed': !visible, [`ml-${buttonUnbreak}-2`]: buttonUnbreak }"
>
<icon iname="chevron-right" />
<Icon iname="chevron-right" />
<span class="sr-only">{{ $t('words.collapse') }}</span>
</b-button>
</BButton>
</template>
<b-collapse v-if="collapsable" :visible="visible">
<BCollapse v-if="collapsable" :visible="visible">
<slot v-if="('no-body' in $attrs)" name="default" />
<b-card-body v-else>
<BCardBody v-else>
<slot name="default" />
</b-card-body>
</b-collapse>
</BCardBody>
</BCollapse>
<template v-else>
<slot name="default" />
</template>
@ -37,7 +37,7 @@
<template #footer v-if="'buttons' in $slots">
<slot name="buttons" />
</template>
</b-card>
</BCard>
</template>
<script>

View file

@ -1,33 +1,33 @@
<template>
<card v-bind="$attrs" class="card-form">
<Card v-bind="$attrs" class="card-form">
<template #default>
<slot name="disclaimer" />
<b-form
<BForm
:id="id" :inline="inline" :class="formClasses"
@submit.prevent="onSubmit" novalidate
>
<slot name="default" />
<slot name="server-error">
<b-alert
<BAlert
variant="danger" class="my-3" icon="ban"
:show="errorFeedback !== ''"
>
<div v-html="errorFeedback" />
</b-alert>
</BAlert>
</slot>
</b-form>
</BForm>
</template>
<template v-if="!noFooter" #buttons>
<slot name="buttons">
<b-button type="submit" variant="success" :form="id">
<BButton type="submit" variant="success" :form="id">
{{ submitText ? submitText : $t('save') }}
</b-button>
</BButton>
</slot>
</template>
</card>
</Card>
</template>
<script>

View file

@ -1,17 +1,17 @@
<template>
<b-row no-gutters class="description-row">
<b-col v-bind="cols_">
<BRow no-gutters class="description-row">
<BCol v-bind="cols_">
<slot name="term">
<strong>{{ term }}</strong>
</slot>
</b-col>
</BCol>
<b-col>
<BCol>
<slot name="default">
{{ details }}
</slot>
</b-col>
</b-row>
</BCol>
</BRow>
</template>
<script>

View file

@ -2,20 +2,20 @@
<span class="explain-what">
<slot name="default" />
<span class="explain-what-popover-container">
<b-button
<BButton
:id="id" href="#"
variant="light"
>
<icon iname="question" />
<Icon iname="question" />
<span class="sr-only">{{ $t('details_about', { subject: title }) }}</span>
</b-button>
<b-popover
</BButton>
<BPopover
placement="auto"
:target="id" triggers="focus" custom-class="explain-what-popover"
:variant="variant" :title="title"
>
<span v-html="content" />
</b-popover>
</BPopover>
</span>
</span>
</template>

View file

@ -1,6 +1,6 @@
<template>
<!-- v-bind="$attrs" allow to pass default attrs not specified in this component slots -->
<b-form-group
<BFormGroup
v-bind="attrs"
:id="_id"
:label-for="$attrs['label-for'] || props.id"
@ -10,7 +10,7 @@
<!-- Make field props and state available as scoped slot data -->
<slot v-bind="{ self: { ...props, state }, touch }">
<!-- if no component was passed as slot, render a component from the props -->
<component
<Component
:is="component"
v-bind="props"
v-on="$listeners"
@ -28,15 +28,15 @@
<!-- Render description -->
<template v-if="description || link">
<div class="d-flex">
<b-link
<BLink
v-if="link"
:to="link" :href="link.href" class="ml-auto"
>
{{ link.text }}
</b-link>
</BLink>
</div>
<vue-showdown
<VueShowdown
v-if="description"
:markdown="description" flavor="github"
:class="{ ['alert p-1 px-2 alert-' + descriptionVariant]: descriptionVariant }"
@ -45,7 +45,7 @@
<!-- Slot available to overwrite the one above -->
<slot name="description" />
</template>
</b-form-group>
</BFormGroup>
</template>
<script>

View file

@ -1,14 +1,14 @@
<template>
<b-row no-gutters class="description-row">
<b-col v-bind="cols_" class="font-weight-bold">
<BRow no-gutters class="description-row">
<BCol v-bind="cols_" class="font-weight-bold">
{{ label }}
</b-col>
</BCol>
<b-col>
<BCol>
<!-- FIXME not sure about rendering html -->
<div v-html="text" />
</b-col>
</b-row>
</BCol>
</BRow>
</template>
<script>

View file

@ -1,5 +1,5 @@
<template>
<b-button-toolbar :aria-label="label" id="top-bar">
<BButtonToolbar :aria-label="label" id="top-bar">
<div id="top-bar-left" class="top-bar-group" v-if="hasLeftSlot">
<slot name="group-left" />
</div>
@ -7,11 +7,11 @@
<div id="top-bar-right" class="top-bar-group" v-if="hasRightSlot || button">
<slot v-if="hasRightSlot" name="group-right" />
<b-button v-else variant="success" :to="button.to">
<icon v-if="button.icon" :iname="button.icon" /> {{ button.text }}
</b-button>
<BButton v-else variant="success" :to="button.to">
<Icon v-if="button.icon" :iname="button.icon" /> {{ button.text }}
</BButton>
</div>
</b-button-toolbar>
</BButtonToolbar>
</template>
<script>

View file

@ -1,21 +1,21 @@
<template>
<div>
<top-bar v-if="hasTopBar">
<TopBar v-if="hasTopBar">
<template #group-left>
<slot name="top-bar-group-left" />
</template>
<template #group-right>
<slot name="top-bar-group-right" />
</template>
</top-bar>
</TopBar>
<slot v-else name="top-bar" />
<slot name="top" v-bind="{ loading: isLoading }" />
<b-skeleton-wrapper :loading="isLoading">
<BSkeletonWrapper :loading="isLoading">
<template #loading>
<slot name="skeleton">
<component :is="skeleton" />
<Component :is="skeleton" />
</slot>
</template>
@ -23,7 +23,7 @@
<div>
<slot name="default" v-bind="{ loading: isLoading }" />
</div>
</b-skeleton-wrapper>
</BSkeletonWrapper>
<slot name="bot" v-bind="{ loading: isLoading }" />
</div>

View file

@ -1,21 +1,21 @@
<template>
<view-base v-bind="$attrs" v-on="$listeners" :skeleton="skeleton">
<ViewBase v-bind="$attrs" v-on="$listeners" :skeleton="skeleton">
<template v-if="hasCustomTopBar" #top-bar>
<slot name="top-bar" />
</template>
<template v-if="!hasCustomTopBar" #top-bar-group-left>
<b-input-group class="w-100">
<b-input-group-prepend is-text>
<icon iname="search" />
</b-input-group-prepend>
<BInputGroup class="w-100">
<BInputGroupPrepend is-text>
<Icon iname="search" />
</BInputGroupPrepend>
<b-form-input
<BFormInput
id="top-bar-search"
:value="search" @input="$emit('update:search', $event)"
:placeholder="$t('search.for', { items: $tc('items.' + itemsName, 2) })"
:disabled="!items"
/>
</b-input-group>
</BInputGroup>
</template>
<template v-if="!hasCustomTopBar" #top-bar-group-right>
<slot name="top-bar-buttons" />
@ -26,12 +26,12 @@
</template>
<template #default>
<b-alert v-if="items === null || filteredItems === null" variant="warning">
<BAlert v-if="items === null || filteredItems === null" variant="warning">
<slot name="alert-message">
<icon iname="exclamation-triangle" />
<Icon iname="exclamation-triangle" />
{{ $tc(items === null ? 'items_verbose_count': 'search.not_found', 0, { items: $tc('items.' + itemsName, 0) }) }}
</slot>
</b-alert>
</BAlert>
<slot v-else name="default" />
</template>
@ -43,7 +43,7 @@
<template #skeleton>
<slot name="skeleton" />
</template>
</view-base>
</ViewBase>
</template>
<script>
@ -55,7 +55,7 @@ export default {
itemsName: { type: String, required: true },
filteredItems: { type: null, required: true },
search: { type: String, default: null },
skeleton: { type: String, default: 'list-group-skeleton' }
skeleton: { type: String, default: 'ListGroupSkeleton' }
},
computed: {

View file

@ -1,17 +1,17 @@
<template>
<component
<Component
v-bind="$attrs"
:is="alert ? 'b-alert' : 'div'"
:is="alert ? 'BAlert' : 'div'"
:variant="alert ? variant : null"
:class="{ ['alert alert-' + variant]: !alert }"
class="yuno-alert d-flex flex-column flex-md-row align-items-center"
>
<icon :iname="_icon" class="mr-md-3 mb-md-0 mb-2 md" />
<Icon :iname="_icon" class="mr-md-3 mb-md-0 mb-2 md" />
<div class="w-100">
<slot name="default" />
</div>
</component>
</Component>
</template>
<script>

View file

@ -1,10 +1,10 @@
<template>
<b-list-group-item
<BListGroupItem
class="yuno-list-group-item" :class="_class"
v-bind="$attrs"
>
<div v-if="!noStatus" class="yuno-list-group-item-status">
<icon
<Icon
v-if="_icon" :iname="_icon"
:class="['icon-' + variant]"
/>
@ -13,7 +13,7 @@
<div class="yuno-list-group-item-content">
<slot name="default" />
</div>
</b-list-group-item>
</BListGroupItem>
</template>
<script>

View file

@ -1,14 +1,14 @@
<template>
<b-button
<BButton
:id="id"
:variant="type"
@click="$emit('action', $event)"
:disabled="!enabled"
class="d-block mb-3"
>
<icon :iname="icon_" class="mr-2" />
<Icon :iname="icon_" class="mr-2" />
<span v-html="label" />
</b-button>
</BButton>
</template>
<script>

View file

@ -1,5 +1,5 @@
<template>
<b-checkbox
<BFormCheckbox
v-model="checked"
v-on="$listeners"
:id="id"
@ -7,7 +7,7 @@
switch
>
{{ label || $t(labels[checked]) }}
</b-checkbox>
</BFormCheckbox>
</template>
<script>

View file

@ -1,14 +1,14 @@
<template>
<b-button-group class="w-100">
<b-button
<BButtonGroup class="w-100">
<BButton
v-if="!this.required && this.value.file !== null"
@click="clearFiles" variant="danger"
>
<span class="sr-only">{{ $t('delete') }}</span>
<icon iname="trash" />
</b-button>
<Icon iname="trash" />
</BButton>
<b-form-file
<BFormFile
:value="value.file"
ref="input-file"
:id="id"
@ -22,7 +22,7 @@
@blur="$parent.$emit('touch', name)"
@focusout.native="$parent.$emit('touch', name)"
/>
</b-button-group>
</BButtonGroup>
</template>
<script>

View file

@ -1,5 +1,5 @@
<template>
<b-input
<BFormInput
:value="value"
:id="id"
:placeholder="placeholder"

View file

@ -1,5 +1,5 @@
<template>
<vue-showdown :markdown="label" flavor="github" />
<VueShowdown :markdown="label" flavor="github" />
</template>
<script>

View file

@ -1,12 +1,12 @@
<template>
<b-alert class="d-flex flex-column flex-md-row align-items-center" :variant="type" show>
<icon :iname="icon_" class="mr-md-3 mb-md-0 mb-2" :variant="type" />
<BAlert class="d-flex flex-column flex-md-row align-items-center" :variant="type" show>
<Icon :iname="icon_" class="mr-md-3 mb-md-0 mb-2" :variant="type" />
<vue-showdown
<VueShowdown
:markdown="label" flavor="github"
tag="span" class="markdown"
/>
</b-alert>
</BAlert>
</template>
<script>

View file

@ -1,5 +1,5 @@
<template>
<b-select
<BFormSelect
:value="value"
:id="id"
:options="choices"

View file

@ -1,5 +1,5 @@
<template>
<b-form-tags
<BFormTags
v-model="tags"
:id="id"
:placeholder="placeholder"

View file

@ -1,6 +1,6 @@
<template>
<div class="tags-selectize">
<b-form-tags
<BFormTags
v-bind="$attrs" v-on="$listeners"
:value="value" :id="id"
size="lg" class="p-0 border-0" no-outer-focus
@ -8,59 +8,59 @@
<template #default="{ tags, disabled, addTag, removeTag }">
<ul v-if="!noTags && tags.length > 0" class="list-inline d-inline-block mb-2">
<li v-for="tag in tags" :key="id + '-' + tag" class="list-inline-item">
<b-form-tag
<BFormTag
@remove="onRemoveTag({ option: tag, removeTag })"
:title="tag"
:disabled="disabled || disabledItems.includes(tag)"
class="border border-dark mb-2"
>
<icon v-if="tagIcon" :iname="tagIcon" /> {{ tag }}
</b-form-tag>
<Icon v-if="tagIcon" :iname="tagIcon" /> {{ tag }}
</BFormTag>
</li>
</ul>
<b-dropdown
<BDropdown
ref="dropdown"
variant="outline-dark" block menu-class="w-100"
@keydown.native="onDropdownKeydown"
>
<template #button-content>
<icon iname="search-plus" /> {{ label }}
<Icon iname="search-plus" /> {{ label }}
</template>
<b-dropdown-group class="search-group">
<b-dropdown-form @submit.stop.prevent="() => {}">
<b-form-group
<BDropdownGroup class="search-group">
<BDropdownForm @submit.stop.prevent="() => {}">
<BFormGroup
:label="$t('search.for', { items: itemsName })"
label-cols-md="auto" label-size="sm" :label-for="id + '-search-input'"
:invalid-feedback="$tc('search.not_found', 0, { items: $tc('items.' + itemsName, 0) })"
:state="searchState" :disabled="disabled"
class="mb-0"
>
<b-form-input
<BFormInput
ref="search-input" v-model="search"
:id="id + '-search-input'"
type="search" size="sm" autocomplete="off"
/>
</b-form-group>
</b-dropdown-form>
<b-dropdown-divider />
</b-dropdown-group>
</BFormGroup>
</BDropdownForm>
<BDropdownDivider />
</BDropdownGroup>
<b-dropdown-item-button
<BDropdownItemButton
v-for="option in availableOptions"
:key="option"
@click="onAddTag({ option, addTag })"
>
{{ option }}
</b-dropdown-item-button>
<b-dropdown-text v-if="!criteria && availableOptions.length === 0">
<icon iname="exclamation-triangle" />
</BDropdownItemButton>
<BDropdownText v-if="!criteria && availableOptions.length === 0">
<Icon iname="exclamation-triangle" />
{{ $tc('items_verbose_items_left', 0, { items: $tc('items.' + itemsName, 0) }) }}
</b-dropdown-text>
</b-dropdown>
</BDropdownText>
</BDropdown>
</template>
</b-form-tags>
</BFormTags>
</div>
</template>

View file

@ -1,5 +1,5 @@
<template>
<b-form-textarea
<BFormTextarea
:value="value"
:id="id"
:placeholder="placeholder"

View file

@ -1,20 +1,20 @@
<template>
<b-card>
<BCard>
<template #header>
<b-skeleton width="30%" height="36px" class="m-0" />
<BSkeleton width="30%" height="36px" class="m-0" />
</template>
<div v-for="count in itemCount" :key="count">
<template v-if="randint(0, 1)">
<b-skeleton width="100%" height="24px" />
<b-skeleton :width="randint(15, 60) + '%'" height="24px" />
<BSkeleton width="100%" height="24px" />
<BSkeleton :width="randint(15, 60) + '%'" height="24px" />
</template>
<b-skeleton v-else :width="randint(45, 100) + '%'" height="24px" />
<BSkeleton v-else :width="randint(45, 100) + '%'" height="24px" />
<b-skeleton :width="randint(20, 30) + '%'" height="38px" class="mt-3" />
<BSkeleton :width="randint(20, 30) + '%'" height="38px" class="mt-3" />
<hr>
</div>
</b-card>
</BCard>
</template>
<script>

View file

@ -1,39 +1,39 @@
<template>
<b-card>
<BCard>
<template #header>
<b-skeleton width="30%" height="36px" class="m-0" />
<BSkeleton width="30%" height="36px" class="m-0" />
</template>
<template v-for="count in itemCount">
<b-row :key="count" :class="{ 'd-block': cols === null }">
<b-col v-bind="cols">
<BRow :key="count" :class="{ 'd-block': cols === null }">
<BCol v-bind="cols">
<div style="height: 38px" class="d-flex align-items-center">
<b-skeleton class="m-0" :width="randint(45, 100) + '%'" height="24px" />
<BSkeleton class="m-0" :width="randint(45, 100) + '%'" height="24px" />
</div>
</b-col>
</BCol>
<b-col>
<BCol>
<div class="w100 d-flex justify-content-between" v-if="count % 2 === 0">
<b-skeleton width="100%" height="38px" />
<BSkeleton width="100%" height="38px" />
<b-skeleton width="38px" height="38px" class="ml-2" />
<BSkeleton width="38px" height="38px" class="ml-2" />
</div>
<b-skeleton v-else width="100%" height="38px" />
<BSkeleton v-else width="100%" height="38px" />
<b-skeleton :width="randint(15, 35) + '%'" height="19px" />
</b-col>
</b-row>
<BSkeleton :width="randint(15, 35) + '%'" height="19px" />
</BCol>
</BRow>
<hr :key="count + '-hr'">
</template>
<template #footer>
<div class="d-flex justify-content-end w-100">
<b-skeleton width="100px" height="38px" />
<BSkeleton width="100px" height="38px" />
</div>
</template>
</b-card>
</BCard>
</template>
<script>

View file

@ -1,18 +1,18 @@
<template>
<b-card>
<BCard>
<template #header>
<b-skeleton width="30%" height="36px" class="m-0" />
<BSkeleton width="30%" height="36px" class="m-0" />
</template>
<b-row v-for="i in itemCount" :key="i" no-gutters>
<b-col cols="5" md="3" xl="3">
<b-skeleton :width="randint(45, 95) + '%'" height="19px" />
</b-col>
<b-col>
<b-skeleton :width="randint(10, 60) + '%'" height="19px" />
</b-col>
</b-row>
</b-card>
<BRow v-for="i in itemCount" :key="i" no-gutters>
<BCol cols="5" md="3" xl="3">
<BSkeleton :width="randint(45, 95) + '%'" height="19px" />
</BCol>
<BCol>
<BSkeleton :width="randint(10, 60) + '%'" height="19px" />
</BCol>
</BRow>
</BCard>
</template>
<script>

View file

@ -1,18 +1,18 @@
<template>
<b-card no-body>
<BCard no-body>
<template #header>
<b-skeleton width="30%" height="36px" class="m-0" />
<BSkeleton width="30%" height="36px" class="m-0" />
</template>
<b-list-group flush>
<b-list-group-item v-for="count in itemCount" :key="count" class="d-flex">
<BListGroup flush>
<BListGroupItem v-for="count in itemCount" :key="count" class="d-flex">
<div style="width: 20%;">
<b-skeleton :width="randint(50, 100) + '%'" height="24px" class="mr-3" />
<BSkeleton :width="randint(50, 100) + '%'" height="24px" class="mr-3" />
</div>
<b-skeleton :width="randint(30, 80) + '%'" height="24px" class="m-0" />
</b-list-group-item>
</b-list-group>
</b-card>
<BSkeleton :width="randint(30, 80) + '%'" height="24px" class="m-0" />
</BListGroupItem>
</BListGroup>
</BCard>
</template>
<script>

View file

@ -1,10 +1,10 @@
<template>
<b-list-group>
<b-list-group-item v-for="count in itemCount" :key="count">
<b-skeleton :width="randint(15, 25) + '%'" height="24px" class="mb-2" />
<b-skeleton :width="randint(25, 50) + '%'" height="24px" class="m-0" />
</b-list-group-item>
</b-list-group>
<BListGroup>
<BListGroupItem v-for="count in itemCount" :key="count">
<BSkeleton :width="randint(15, 25) + '%'" height="24px" class="mb-2" />
<BSkeleton :width="randint(25, 50) + '%'" height="24px" class="m-0" />
</BListGroupItem>
</BListGroup>
</template>
<script>

View file

@ -1,16 +1,16 @@
<template>
<div class="home">
<b-list-group class="menu-list">
<b-list-group-item
<BListGroup class="menu-list">
<BListGroupItem
v-for="item in menu"
:key="item.routeName"
:to="{ name: item.routeName }"
>
<icon :iname="item.icon" class="lg ml-1" />
<Icon :iname="item.icon" class="lg ml-1" />
<h4>{{ $t(item.translation) }}</h4>
<icon iname="chevron-right" class="lg fs-sm ml-auto" />
</b-list-group-item>
</b-list-group>
<Icon iname="chevron-right" class="lg fs-sm ml-auto" />
</BListGroupItem>
</BListGroup>
</div>
</template>

View file

@ -1,24 +1,24 @@
<template>
<card-form
<CardForm
:title="$t('login')" icon="lock"
:validation="$v" :server-error="serverError"
@submit.prevent="login"
>
<!-- ADMIN USERNAME -->
<form-field v-bind="fields.username" v-model="form.username" :validation="$v.form.username" />
<FormField v-bind="fields.username" v-model="form.username" :validation="$v.form.username" />
<!-- ADMIN PASSWORD -->
<form-field v-bind="fields.password" v-model="form.password" :validation="$v.form.password" />
<FormField v-bind="fields.password" v-model="form.password" :validation="$v.form.password" />
<template #buttons>
<b-button
<BButton
type="submit" variant="success"
:disabled="!installed" form="ynh-form"
>
{{ $t('login') }}
</b-button>
</BButton>
</template>
</card-form>
</CardForm>
</template>
<script>

View file

@ -3,7 +3,7 @@
<!-- START STEP -->
<template v-if="step === 'start'">
<p class="alert alert-success">
<icon iname="thumbs-up" /> {{ $t('postinstall_intro_1') }}
<Icon iname="thumbs-up" /> {{ $t('postinstall_intro_1') }}
</p>
<p class="alert alert-info">
@ -12,70 +12,70 @@
<span v-html="$t('postinstall_intro_3')" />
</p>
<b-button size="lg" variant="success" @click="goToStep('domain')">
<BButton size="lg" variant="success" @click="goToStep('domain')">
{{ $t('begin') }}
</b-button>
</BButton>
</template>
<!-- DOMAIN SETUP STEP -->
<template v-else-if="step === 'domain'">
<domain-form
<DomainForm
:title="$t('postinstall_set_domain')" :submit-text="$t('next')" :server-error="serverError"
@submit="setDomain"
>
<template #disclaimer>
<p class="alert alert-info" v-t="'postinstall_domain'" />
</template>
</domain-form>
</DomainForm>
<b-button variant="primary" @click="goToStep('start')" class="mt-3">
<icon iname="chevron-left" /> {{ $t('previous') }}
</b-button>
<BButton variant="primary" @click="goToStep('start')" class="mt-3">
<Icon iname="chevron-left" /> {{ $t('previous') }}
</BButton>
</template>
<!-- FIRST USER SETUP STEP -->
<template v-else-if="step === 'user'">
<card-form
<CardForm
:title="$t('postinstall.user.title')" icon="user-plus"
:validation="$v" :server-error="serverError"
:submit-text="$t('next')" @submit.prevent="setUser"
>
<read-only-alert-item
<ReadOnlyAlertItem
:label="$t('postinstall.user.first_user_help')"
type="info"
/>
<form-field
<FormField
v-for="(field, name) in fields" :key="name"
v-bind="field" v-model="user[name]" :validation="$v.user[name]"
/>
</card-form>
</CardForm>
<b-button variant="primary" @click="goToStep('domain')" class="mt-3">
<icon iname="chevron-left" /> {{ $t('previous') }}
</b-button>
<BButton variant="primary" @click="goToStep('domain')" class="mt-3">
<Icon iname="chevron-left" /> {{ $t('previous') }}
</BButton>
</template>
<template v-else-if="step === 'rootfsspace-error'">
<card no-body header-class="d-none" footer-bg-variant="danger">
<b-card-body class="alert alert-danger m-0">
<Card no-body header-class="d-none" footer-bg-variant="danger">
<BCardBody class="alert alert-danger m-0">
{{ serverError }}
</b-card-body>
</BCardBody>
<template #buttons>
<b-button variant="light" size="sm" @click="performPostInstall(true)">
<icon iname="warning" /> {{ $t('postinstall.force') }}
</b-button>
<BButton variant="light" size="sm" @click="performPostInstall(true)">
<Icon iname="warning" /> {{ $t('postinstall.force') }}
</BButton>
</template>
</card>
</Card>
</template>
<!-- POST-INSTALL SUCCESS STEP -->
<template v-else-if="step === 'login'">
<p class="alert alert-success">
<icon iname="thumbs-up" /> {{ $t('installation_complete') }}
<Icon iname="thumbs-up" /> {{ $t('installation_complete') }}
</p>
<login />
<Login />
</template>
</div>
</template>

View file

@ -1,5 +1,5 @@
<template>
<card-form
<CardForm
:title="title" icon="globe" :submit-text="submitText"
:validation="$v" :server-error="serverError"
@submit.prevent="onSubmit"
@ -8,7 +8,7 @@
<slot name="disclaimer" />
</template>
<b-form-radio
<BFormRadio
v-model="selected" name="domain-type" value="domain"
:class="domainIsVisible ? null : 'collapsed'"
:aria-expanded="domainIsVisible ? 'true' : 'false'"
@ -16,21 +16,21 @@
class="mb-2"
>
{{ $t('domain.add.from_registrar') }}
</b-form-radio>
</BFormRadio>
<b-collapse id="collapse-domain" :visible.sync="domainIsVisible">
<BCollapse id="collapse-domain" :visible.sync="domainIsVisible">
<p class="mt-2 alert alert-info">
<icon iname='info-circle' />
<Icon iname='info-circle' />
<span class='pl-1' v-html="$t('domain.add.from_registrar_desc')" />
</p>
<form-field
<FormField
v-bind="fields.domain" v-model="form.domain"
:validation="$v.form.domain" class="mt-3"
/>
</b-collapse>
</BCollapse>
<b-form-radio
<BFormRadio
v-model="selected" name="domain-type" value="dynDomain"
:disabled="dynDnsForbiden"
:class="dynDomainIsVisible ? null : 'collapsed'"
@ -39,56 +39,56 @@
class="mb-2"
>
{{ $t('domain.add.from_yunohost') }}
</b-form-radio>
</BFormRadio>
<b-collapse id="collapse-dynDomain" :visible.sync="dynDomainIsVisible">
<BCollapse id="collapse-dynDomain" :visible.sync="dynDomainIsVisible">
<p class="mt-2 alert alert-info">
<icon iname="info-circle" />
<Icon iname="info-circle" />
<span class='pl-1' v-html="$t('domain.add.from_yunohost_desc')" />
</p>
<form-field v-bind="fields.dynDomain" :validation="$v.form.dynDomain" class="mt-3">
<FormField v-bind="fields.dynDomain" :validation="$v.form.dynDomain" class="mt-3">
<template #default="{ self }">
<adress-input-select v-bind="self" v-model="form.dynDomain" />
<AdressInputSelect v-bind="self" v-model="form.dynDomain" />
</template>
</form-field>
</FormField>
<form-field
<FormField
v-bind="fields.dynDomainPassword"
:validation="$v.form.dynDomainPassword"
v-model="form.dynDomainPassword"
/>
<form-field
<FormField
v-bind="fields.dynDomainPasswordConfirmation"
:validation="$v.form.dynDomainPasswordConfirmation"
v-model="form.dynDomainPasswordConfirmation"
/>
</b-collapse>
</BCollapse>
<div v-if="dynDnsForbiden" class="alert alert-warning mt-2" v-html="$t('domain_add_dyndns_forbidden')" />
<b-form-radio
<BFormRadio
v-model="selected" name="domain-type" value="localDomain"
:class="localDomainIsVisible ? null : 'collapsed'"
:aria-expanded="localDomainIsVisible ? 'true' : 'false'"
aria-controls="collapse-localDomain"
>
{{ $t('domain.add.from_local') }}
</b-form-radio>
</BFormRadio>
<b-collapse id="collapse-localDomain" :visible.sync="localDomainIsVisible">
<BCollapse id="collapse-localDomain" :visible.sync="localDomainIsVisible">
<p class="mt-2 alert alert-info">
<icon iname='info-circle' />
<Icon iname='info-circle' />
<span class='pl-1' v-html="$t('domain.add.from_local_desc')" />
</p>
<form-field v-bind="fields.localDomain" :validation="$v.form.localDomain" class="mt-3">
<FormField v-bind="fields.localDomain" :validation="$v.form.localDomain" class="mt-3">
<template #default="{ self }">
<adress-input-select v-bind="self" v-model="form.localDomain" />
<AdressInputSelect v-bind="self" v-model="form.localDomain" />
</template>
</form-field>
</b-collapse>
</card-form>
</FormField>
</BCollapse>
</CardForm>
</template>
<script>

View file

@ -1,8 +1,8 @@
<template>
<!-- This card receives style from `ViewLockOverlay` if used inside it -->
<div>
<b-card-body>
<b-card-title v-t="'api_errors_titles.' + error.name" />
<BCardBody>
<BCardTitle v-t="'api_errors_titles.' + error.name" />
<em v-t="'api_error.sorry'" />
@ -21,9 +21,9 @@
<p>
<strong v-t="'api_error.error_message'" />
<b-alert class="mt-2" variant="danger">
<BAlert class="mt-2" variant="danger">
<div v-html="error.message" />
</b-alert>
</BAlert>
</p>
<template v-if="error.traceback">
@ -37,17 +37,17 @@
<p class="my-2">
<strong v-t="'api_error.server_said'" />
</p>
<message-list-group :messages="messages" bordered />
<MessageListGroup :messages="messages" bordered />
</template>
</b-card-body>
</BCardBody>
<b-card-footer footer-bg-variant="danger">
<BCardFooter footer-bg-variant="danger">
<!-- TODO add copy error ? -->
<b-button
<BButton
variant="light" size="sm"
v-t="'ok'" @click="dismiss"
/>
</b-card-footer>
</BCardFooter>
</div>
</template>

View file

@ -1,7 +1,7 @@
<template>
<b-card no-body id="console">
<BCard no-body id="console">
<!-- HISTORY BAR -->
<b-card-header
<BCardHeader
role="button" tabindex="0"
:aria-expanded="open ? 'true' : 'false'" aria-controls="console-collapse"
header-tag="header" :header-bg-variant="open ? 'best' : 'white'"
@ -11,11 +11,11 @@
@keyup.space.enter.prevent="onHistoryBarKey"
>
<h5 class="m-0">
<icon iname="history" /> <span class="d-none d-sm-inline font-weight-bold">{{ $t('history.title') }}</span>
<Icon iname="history" /> <span class="d-none d-sm-inline font-weight-bold">{{ $t('history.title') }}</span>
</h5>
<!-- CURRENT/LAST ACTION -->
<b-button
<BButton
v-if="lastAction"
size="sm" pill
class="ml-auto py-0"
@ -24,11 +24,11 @@
@keyup.enter.space.prevent="onLastActionClick"
>
<small>{{ $t('history.last_action') }}</small>
</b-button>
<query-header v-if="lastAction" :request="lastAction" class="w-auto ml-2 xs-hide" />
</b-card-header>
</BButton>
<QueryHeader v-if="lastAction" :request="lastAction" class="w-auto ml-2 xs-hide" />
</BCardHeader>
<b-collapse id="console-collapse" v-model="open">
<BCollapse id="console-collapse" v-model="open">
<div
class="accordion" role="tablist"
id="history" ref="history"
@ -38,33 +38,33 @@
</p>
<!-- ACTION LIST -->
<b-card
<BCard
v-for="(action, i) in history" :key="i"
no-body class="rounded-0 rounded-top border-left-0 border-right-0"
>
<!-- ACTION -->
<b-card-header header-tag="header" header-bg-variant="white" class="sticky-top d-flex">
<BCardHeader header-tag="header" header-bg-variant="white" class="sticky-top d-flex">
<!-- ACTION DESC -->
<query-header
<QueryHeader
role="tab" v-b-toggle="action.messages.length ? 'messages-collapse-' + i : false"
:request="action" show-time show-error
/>
</b-card-header>
</BCardHeader>
<!-- ACTION MESSAGES -->
<b-collapse
<BCollapse
v-if="action.messages.length"
:id="'messages-collapse-' + i" accordion="my-accordion"
role="tabpanel"
@shown="scrollToAction(i)"
@hide="scrollToAction(i)"
>
<message-list-group :messages="action.messages" />
</b-collapse>
</b-card>
<MessageListGroup :messages="action.messages" />
</BCollapse>
</BCard>
</div>
</b-collapse>
</b-card>
</BCollapse>
</BCard>
</template>
<script>

View file

@ -1,12 +1,12 @@
<template>
<!-- This card receives style from `ViewLockOverlay` if used inside it -->
<b-card-body>
<b-card-title class="text-center my-4" v-t="'api.reconnecting.title'" />
<BCardBody>
<BCardTitle class="text-center my-4" v-t="'api.reconnecting.title'" />
<template v-if="status === 'reconnecting'">
<spinner class="mb-4" />
<Spinner class="mb-4" />
<b-alert
<BAlert
v-if="origin"
v-t="'api.reconnecting.reason.' + origin"
:variant="origin === 'unknow' ? 'warning' : 'info'"
@ -14,12 +14,12 @@
</template>
<template v-if="status === 'failed'">
<b-alert variant="danger">
<markdown-item :label="$t('api.reconnecting.failed')" />
</b-alert>
<BAlert variant="danger">
<MarkdownItem :label="$t('api.reconnecting.failed')" />
</BAlert>
<div class="d-flex justify-content-end">
<b-button
<BButton
variant="success" v-t="'retry'" class="ml-auto"
@click="tryToReconnect()"
/>
@ -27,11 +27,11 @@
</template>
<template v-if="status === 'success'">
<b-alert variant="success" v-t="'api.reconnecting.success'" />
<BAlert variant="success" v-t="'api.reconnecting.success'" />
<login-view force-reload />
<LoginView force-reload />
</template>
</b-card-body>
</BCardBody>
</template>
<script>

View file

@ -1,5 +1,5 @@
<template>
<b-overlay
<BOverlay
variant="white" opacity="0.75"
no-center
:show="waiting || reconnecting || error !== null"
@ -7,15 +7,15 @@
<slot name="default" />
<template #overlay>
<b-card no-body class="card-overlay">
<b-card-header header-bg-variant="white">
<query-header :request="error || currentRequest" status-size="lg" />
</b-card-header>
<BCard no-body class="card-overlay">
<BCardHeader header-bg-variant="white">
<QueryHeader :request="error || currentRequest" status-size="lg" />
</BCardHeader>
<component :is="component.name" :request="component.request" />
</b-card>
<Component :is="component.name" :request="component.request" />
</BCard>
</template>
</b-overlay>
</BOverlay>
</template>
<script>

View file

@ -1,26 +1,26 @@
<template>
<!-- This card receives style from `ViewLockOverlay` if used inside it -->
<b-card-body>
<b-card-title class="text-center mt-4" v-t="hasMessages ? 'api.processing' : 'api_waiting'" />
<BCardBody>
<BCardTitle class="text-center mt-4" v-t="hasMessages ? 'api.processing' : 'api_waiting'" />
<!-- PROGRESS BAR -->
<b-progress
<BProgress
v-if="progress" class="my-4"
:max="progress.max" height=".5rem"
>
<b-progress-bar variant="success" :value="progress.values[0]" />
<b-progress-bar variant="warning" :value="progress.values[1]" animated />
<b-progress-bar variant="secondary" :value="progress.values[2]" striped />
</b-progress>
<BProgressBar variant="success" :value="progress.values[0]" />
<BProgressBar variant="warning" :value="progress.values[1]" animated />
<BProgressBar variant="secondary" :value="progress.values[2]" striped />
</BProgress>
<!-- OR SPINNER -->
<spinner v-else class="my-4" />
<Spinner v-else class="my-4" />
<message-list-group
<MessageListGroup
v-if="hasMessages" :messages="request.messages"
bordered fixed-height auto-scroll
:limit="100"
/>
</b-card-body>
</BCardBody>
</template>
<script>

View file

@ -1,16 +1,16 @@
<template>
<!-- This card receives style from `ViewLockOverlay` if used inside it -->
<div>
<b-card-body body-class="alert alert-warning">
<BCardBody body-class="alert alert-warning">
<div v-html="warning.text" />
</b-card-body>
</BCardBody>
<b-card-footer footer-bg-variant="warning">
<b-button
<BCardFooter footer-bg-variant="warning">
<BButton
variant="light" size="sm"
v-t="'ok'" @click="dismiss"
/>
</b-card-footer>
</BCardFooter>
</div>
</template>

View file

@ -1,117 +1,117 @@
<template>
<view-search
<ViewSearch
:items="apps" :filtered-items="filteredApps" items-name="apps"
:queries="queries" @queries-response="onQueriesResponse"
>
<template #top-bar>
<div id="view-top-bar">
<!-- APP SEARCH -->
<b-input-group>
<b-input-group-prepend is-text>
<icon iname="search" />
</b-input-group-prepend>
<b-form-input
<BInputGroup>
<BInputGroupPrepend is-text>
<Icon iname="search" />
</BInputGroupPrepend>
<BFormInput
id="search-input" :placeholder="$t('search.for', { items: $tc('items.apps', 2) })"
:value="search" @input="updateQuery('search', $event)"
/>
<b-input-group-append>
<b-select :value="quality" :options="qualityOptions" @change="updateQuery('quality', $event)" />
</b-input-group-append>
</b-input-group>
<BInputGroupAppend>
<BFormSelect :value="quality" :options="qualityOptions" @change="updateQuery('quality', $event)" />
</BInputGroupAppend>
</BInputGroup>
<!-- CATEGORY SELECT -->
<b-input-group class="mt-3">
<b-input-group-prepend is-text>
<icon iname="filter" />
</b-input-group-prepend>
<b-select :value="category" :options="categories" @change="updateQuery('category', $event)" />
<b-input-group-append>
<b-button variant="primary" :disabled="category === null" @click="updateQuery('category', null)">
<BInputGroup class="mt-3">
<BInputGroupPrepend is-text>
<Icon iname="filter" />
</BInputGroupPrepend>
<BFormSelect :value="category" :options="categories" @change="updateQuery('category', $event)" />
<BInputGroupAppend>
<BButton variant="primary" :disabled="category === null" @click="updateQuery('category', null)">
{{ $t('app_show_categories') }}
</b-button>
</b-input-group-append>
</b-input-group>
</BButton>
</BInputGroupAppend>
</BInputGroup>
<!-- CATEGORIES SUBTAGS -->
<b-input-group v-if="subtags" class="mt-3 subtags">
<b-input-group-prepend is-text>
<BInputGroup v-if="subtags" class="mt-3 subtags">
<BInputGroupPrepend is-text>
Subtags
</b-input-group-prepend>
<b-form-radio-group
</BInputGroupPrepend>
<BFormRadioGroup
id="subtags-radio" name="subtags"
:checked="subtag" :options="subtags" @change="updateQuery('subtag', $event)"
buttons button-variant="outline-secondary"
/>
<b-select
<BFormSelect
id="subtags-select" :value="subtag" :options="subtags"
@change="updateQuery('subtag', $event)"
/>
</b-input-group>
</BInputGroup>
</div>
</template>
<!-- CATEGORIES CARDS -->
<b-card-group v-if="category === null" deck tag="ul">
<b-card
<BCardGroup v-if="category === null" deck tag="ul">
<BCard
v-for="cat in categories.slice(1)" :key="cat.value"
tag="li" class="category-card"
>
<b-card-title>
<b-link @click="updateQuery('category', cat.value)" class="card-link">
<icon :iname="cat.icon" /> {{ cat.text }}
</b-link>
</b-card-title>
<b-card-text>{{ cat.description }}</b-card-text>
</b-card>
</b-card-group>
<BCardTitle>
<BLink @click="updateQuery('category', cat.value)" class="card-link">
<Icon :iname="cat.icon" /> {{ cat.text }}
</BLink>
</BCardTitle>
<BCardText>{{ cat.description }}</BCardText>
</BCard>
</BCardGroup>
<!-- APPS CARDS -->
<card-deck-feed v-else>
<b-card
<CardDeckFeed v-else>
<BCard
v-for="(app, i) in filteredApps" :key="app.id"
tag="article" :aria-labelledby="`${app.id}-title`" :aria-describedby="`${app.id}-desc`"
tabindex="0" :aria-posinset="i + 1" :aria-setsize="filteredApps.length"
no-body class="app-card"
>
<b-card-body class="d-flex">
<b-img v-if="app.logo_hash" class="app-logo rounded" :src="`./applogos/${app.logo_hash}.png`" />
<BCardBody class="d-flex">
<BImg v-if="app.logo_hash" class="app-logo rounded" :src="`./applogos/${app.logo_hash}.png`" />
<div>
<b-card-title :id="`${app.id}-title`" class="d-flex mb-2">
<b-link :to="{ name: 'app-install', params: { id: app.id }}" class="card-link">
<BCardTitle :id="`${app.id}-title`" class="d-flex mb-2">
<BLink :to="{ name: 'app-install', params: { id: app.id }}" class="card-link">
{{ app.manifest.name }}
</b-link>
</BLink>
<small v-if="app.state !== 'working' || app.high_quality" class="d-flex align-items-center ml-2 position-relative">
<b-badge
<BBadge
v-if="app.state !== 'working'"
:variant="app.color"
v-b-popover.hover.bottom="$t(`app_state_${app.state}_explanation`)"
>
<!-- app.state can be 'lowquality' or 'inprogress' -->
{{ $t('app_state_' + app.state) }}
</b-badge>
</BBadge>
<icon
<Icon
v-if="app.high_quality" iname="star" class="star"
v-b-popover.hover.bottom="$t(`app_state_highquality_explanation`)"
/>
</small>
</b-card-title>
</BCardTitle>
<b-card-text :id="`${app.id}-desc`">
<BCardText :id="`${app.id}-desc`">
{{ app.manifest.description }}
</b-card-text>
</BCardText>
<b-card-text v-if="!app.maintained" class="align-self-end position-relative mt-auto">
<BCardText v-if="!app.maintained" class="align-self-end position-relative mt-auto">
<span class="alert-warning p-1" v-b-popover.hover.top="$t('orphaned_details')">
<icon iname="warning" /> {{ $t('orphaned') }}
<Icon iname="warning" /> {{ $t('orphaned') }}
</span>
</b-card-text>
</BCardText>
</div>
</b-card-body>
</b-card>
</card-deck-feed>
</BCardBody>
</BCard>
</CardDeckFeed>
<app-catalog-details
v-if="selectedApp"
@ -124,42 +124,42 @@
<template #bot>
<!-- INSTALL CUSTOM APP -->
<card-form
<CardForm
:title="$t('custom_app_install')" icon="download"
@submit.prevent="onCustomInstallClick" :submit-text="$t('install')"
:validation="$v" class="mt-5"
>
<template #disclaimer>
<div class="alert alert-warning">
<icon iname="exclamation-triangle" /> {{ $t('confirm_install_custom_app') }}
<Icon iname="exclamation-triangle" /> {{ $t('confirm_install_custom_app') }}
</div>
</template>
<!-- URL -->
<form-field v-bind="customInstall.field" v-model="customInstall.url" :validation="$v.customInstall.url" />
</card-form>
<FormField v-bind="customInstall.field" v-model="customInstall.url" :validation="$v.customInstall.url" />
</CardForm>
</template>
<!-- CUSTOM SKELETON -->
<template #skeleton>
<b-card-group deck>
<b-card
<BCardGroup deck>
<BCard
v-for="i in 15" :key="i"
no-body style="min-height: 10rem;"
>
<div class="d-flex w-100 mt-auto">
<b-skeleton width="30px" height="30px" class="mr-2 ml-auto" />
<b-skeleton :width="randint(30, 70) + '%'" height="30px" class="mr-auto" />
<BSkeleton width="30px" height="30px" class="mr-2 ml-auto" />
<BSkeleton :width="randint(30, 70) + '%'" height="30px" class="mr-auto" />
</div>
<b-skeleton
<BSkeleton
v-if="randint(0, 1)"
:width="randint(30, 85) + '%'" height="24px" class="mx-auto"
/>
<b-skeleton :width="randint(30, 85) + '%'" height="24px" class="mx-auto mb-auto" />
</b-card>
</b-card-group>
<BSkeleton :width="randint(30, 85) + '%'" height="24px" class="mx-auto mb-auto" />
</BCard>
</BCardGroup>
</template>
</view-search>
</ViewSearch>
</template>
<script>
@ -397,8 +397,8 @@ export default {
}
.card {
@include hover() {
color: color-yiq($dark);
&:hover {
color: color-contrast($dark);
background-color: $dark;
border-color: $dark;
}

View file

@ -1,52 +1,52 @@
<template>
<view-base
<ViewBase
:queries="queries" @queries-response="onQueriesResponse" :loading="loading"
ref="view"
>
<yuno-alert v-if="app && app.doc && app.doc.notifications && app.doc.notifications.postInstall.length" variant="info" class="my-4">
<YunoAlert v-if="app && app.doc && app.doc.notifications && app.doc.notifications.postInstall.length" variant="info" class="my-4">
<div class="d-md-flex align-items-center mb-3">
<h2 v-t="'app.doc.notifications.post_install'" class="md-m-0" />
<b-button
<BButton
variant="primary"
size="sm"
class="ml-auto mr-2"
@click="dismissNotification('post_install')"
>
<icon iname="check" />
<Icon iname="check" />
{{ $t('app.doc.notifications.understood') }}
</b-button>
</BButton>
</div>
<vue-showdown
<VueShowdown
v-for="[name, notif] in app.doc.notifications.postInstall" :key="name"
:markdown="notif" flavor="github" :options="{ headerLevelStart: 4 }"
/>
</yuno-alert>
</YunoAlert>
<yuno-alert v-if="app && app.doc && app.doc.notifications && app.doc.notifications.postUpgrade.length" variant="info" class="my-4">
<YunoAlert v-if="app && app.doc && app.doc.notifications && app.doc.notifications.postUpgrade.length" variant="info" class="my-4">
<div class="d-md-flex align-items-center mb-3">
<h2 v-t="'app.doc.notifications.post_upgrade'" class="md-m-0" />
<b-button
<BButton
variant="primary"
size="sm"
class="ml-auto mr-2"
@click="dismissNotification('post_upgrade')"
>
<icon iname="check" />
<Icon iname="check" />
{{ $t('app.doc.notifications.understood') }}
</b-button>
</BButton>
</div>
<vue-showdown
<VueShowdown
v-for="[name, notif] in app.doc.notifications.postUpgrade" :key="name"
:markdown="notif" flavor="github" :options="{ headerLevelStart: 4 }"
/>
</yuno-alert>
</YunoAlert>
<section v-if="app" class="border rounded p-3 mb-4">
<div class="d-md-flex align-items-center mb-4">
<h1 class="mb-3 mb-md-0">
<icon iname="cube" />
<Icon iname="cube" />
{{ app.label }}
<span class="text-secondary tiny">
@ -54,24 +54,24 @@
</span>
</h1>
<b-button
<BButton
v-if="app.url"
:href="app.url" target="_blank"
variant="success" class="ml-auto mr-2"
>
<icon iname="external-link" />
<Icon iname="external-link" />
{{ $t('app.open_this_app') }}
</b-button>
</BButton>
<b-button
<BButton
v-b-modal.uninstall-modal
id="uninstall"
variant="danger"
:class="{ 'ml-auto': !app.url }"
>
<icon iname="trash-o" />
<Icon iname="trash-o" />
{{ $t('uninstall') }}
</b-button>
</BButton>
</div>
<p class="text-secondary">
@ -83,203 +83,203 @@
</p>
<p>
<icon iname="comments" /> {{ $t('app.info.problem') }}
<Icon iname="comments" /> {{ $t('app.info.problem') }}
<a :href="`https://forum.yunohost.org/tag/${id}`" target="_blank">
{{ $t('app.info.forum') }}
</a>
</p>
<vue-showdown :markdown="app.description" flavor="github" />
<VueShowdown :markdown="app.description" flavor="github" />
</section>
<yuno-alert
<YunoAlert
v-if="config_panel_err"
class="mb-4" variant="danger" icon="bug"
>
<p>{{ $t('app.info.config_panel_error') }}</p>
<p>{{ config_panel_err }}</p>
<p>{{ $t('app.info.config_panel_error_please_report') }}</p>
</yuno-alert>
</YunoAlert>
<!-- BASIC INFOS -->
<config-panels v-bind="config" @submit="onConfigSubmit">
<ConfigPanels 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
<BFormGroup :label="$t('app_manage_label_and_tiles')" label-class="font-weight-bold">
<FormField
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
<BInputGroup>
<InputItem
: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
<BInputGroupAppend v-if="perm.tileAvailable" is-text>
<CheckboxItem v-model="form.labels[i].show_tile" :label="$t('permission_show_tile_enabled')" />
</BInputGroupAppend>
<BInputGroupAppend>
<BButton
variant="info" v-t="'save'"
@click="changeLabel(perm.name, form.labels[i])"
/>
</b-input-group-append>
</b-input-group>
</BInputGroupAppend>
</BInputGroup>
</template>
<template v-if="perm.url" #description>
{{ $t('permission_corresponding_url') }}:
<b-link :href="'https://' + perm.url">
<BLink :href="'https://' + perm.url">
https://{{ perm.url }}
</b-link>
</BLink>
</template>
</form-field>
</b-form-group>
</FormField>
</BFormGroup>
<hr>
<!-- PERMISSIONS -->
<b-form-group
<BFormGroup
:label="$t('app_info_access_desc')" label-for="permissions"
label-class="font-weight-bold" label-cols-lg="0"
>
{{ allowedGroups.length > 0 ? allowedGroups.join(', ') : $t('nobody') }}
<b-button
<BButton
size="sm" :to="{ name: 'group-list'}" variant="info"
class="ml-2"
>
<icon iname="key-modern" /> {{ $t('groups_and_permissions_manage') }}
</b-button>
</b-form-group>
<Icon iname="key-modern" /> {{ $t('groups_and_permissions_manage') }}
</BButton>
</BFormGroup>
<hr>
<!-- CHANGE URL -->
<b-form-group
<BFormGroup
: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>
<BInputGroup v-if="app.supports_change_url">
<BInputGroupPrepend is-text>
https://
</b-input-group-prepend>
</BInputGroupPrepend>
<b-input-group-prepend class="flex-grow-1">
<b-select v-model="form.url.domain" :options="domains" />
</b-input-group-prepend>
<BInputGroupPrepend class="flex-grow-1">
<BFormSelect v-model="form.url.domain" :options="domains" />
</BInputGroupPrepend>
<b-input-group-prepend is-text>
<BInputGroupPrepend is-text>
/
</b-input-group-prepend>
</BInputGroupPrepend>
<b-input id="input-url" v-model="form.url.path" class="flex-grow-3" />
<BFormInput 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>
<BInputGroupAppend>
<BButton @click="changeUrl" variant="info" v-t="'save'" />
</BInputGroupAppend>
</BInputGroup>
<div v-else class="alert alert-warning">
<icon iname="exclamation" /> {{ $t('app_info_change_url_disabled_tooltip') }}
<Icon iname="exclamation" /> {{ $t('app_info_change_url_disabled_tooltip') }}
</div>
</b-form-group>
</BFormGroup>
<hr v-if="app.is_webapp">
<!-- MAKE DEFAULT -->
<b-form-group
<BFormGroup
: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(false)" id="main-domain" variant="success">
<icon iname="star" /> {{ $t('app_make_default') }}
</b-button>
<BButton @click="setAsDefaultDomain(false)" id="main-domain" variant="success">
<Icon iname="star" /> {{ $t('app_make_default') }}
</BButton>
</template>
<template v-else>
<b-button @click="setAsDefaultDomain(true)" id="main-domain" variant="warning">
<icon iname="star" /> {{ $t('app_make_not_default') }}
</b-button>
<BButton @click="setAsDefaultDomain(true)" id="main-domain" variant="warning">
<Icon iname="star" /> {{ $t('app_make_not_default') }}
</BButton>
</template>
</b-form-group>
</BFormGroup>
</template>
</config-panels>
</ConfigPanels>
<b-card v-if="app && app.doc.admin.length" no-body>
<b-tabs card fill pills>
<b-tab
<BCard v-if="app && app.doc.admin.length" no-body>
<BTabs card fill pills>
<BTab
v-for="[name, content] in app.doc.admin" :key="name"
>
<template #title>
<icon iname="book" class="mr-2" />
<Icon iname="book" class="mr-2" />
{{ name === "admin" ? $t('app.doc.admin.title') : name }}
</template>
<vue-showdown :markdown="content" flavor="github" />
</b-tab>
</b-tabs>
</b-card>
<VueShowdown :markdown="content" flavor="github" />
</BTab>
</BTabs>
</BCard>
<card
<Card
v-if="app && app.integration"
id="app-integration" :title="$t('app.integration.title')"
collapsable collapsed no-body
>
<b-list-group flush>
<yuno-list-group-item variant="info">
<BListGroup flush>
<YunoListGroupItem variant="info">
{{ $t('app.integration.archs') }} {{ app.integration.archs }}
</yuno-list-group-item>
<yuno-list-group-item v-if="app.integration.ldap" :variant="app.integration.ldap === true ? 'success' : 'warning'">
</YunoListGroupItem>
<YunoListGroupItem v-if="app.integration.ldap" :variant="app.integration.ldap === true ? 'success' : 'warning'">
{{ $t(`app.integration.ldap.${app.integration.ldap}`) }}
</yuno-list-group-item>
<yuno-list-group-item v-if="app.integration.sso" :variant="app.integration.sso === true ? 'success' : 'warning'">
</YunoListGroupItem>
<YunoListGroupItem v-if="app.integration.sso" :variant="app.integration.sso === true ? 'success' : 'warning'">
{{ $t(`app.integration.sso.${app.integration.sso}`) }}
</yuno-list-group-item>
<yuno-list-group-item variant="info">
</YunoListGroupItem>
<YunoListGroupItem variant="info">
{{ $t(`app.integration.multi_instance.${app.integration.multi_instance}`) }}
</yuno-list-group-item>
<yuno-list-group-item variant="info">
</YunoListGroupItem>
<YunoListGroupItem variant="info">
{{ $t('app.integration.resources', app.integration.resources) }}
</yuno-list-group-item>
</b-list-group>
</card>
</YunoListGroupItem>
</BListGroup>
</Card>
<card
<Card
v-if="app"
id="app-links" icon="link" :title="$t('app.links.title')"
collapsable collapsed no-body
>
<b-list-group flush>
<yuno-list-group-item v-for="[key, link] in app.links" :key="key" no-status>
<b-link :href="link" target="_blank">
<icon :iname="appLinksIcons(key)" class="mr-1" />
<BListGroup flush>
<YunoListGroupItem v-for="[key, link] in app.links" :key="key" no-status>
<BLink :href="link" target="_blank">
<Icon :iname="appLinksIcons(key)" class="mr-1" />
{{ $t('app.links.' + key) }}
</b-link>
</yuno-list-group-item>
</b-list-group>
</card>
</BLink>
</YunoListGroupItem>
</BListGroup>
</Card>
<b-modal
<BModal
v-if="app"
id="uninstall-modal" :title="$t('confirm_uninstall', { name: id })"
header-bg-variant="warning" :body-class="{ 'd-none': !app.supports_purge }" body-bg-variant=""
@ok="uninstall"
>
<b-form-group v-if="app.supports_purge">
<b-form-checkbox v-model="purge">
<BFormGroup v-if="app.supports_purge">
<BFormCheckbox v-model="purge">
{{ $t('app.uninstall.purge_desc', { name: id }) }}
</b-form-checkbox>
</b-form-group>
</b-modal>
</BFormCheckbox>
</BFormGroup>
</BModal>
<template #skeleton>
<card-info-skeleton :item-count="8" />
<card-form-skeleton />
<CardInfoSkeleton :item-count="8" />
<CardFormSkeleton />
</template>
</view-base>
</ViewBase>
</template>
<script>

View file

@ -1,5 +1,5 @@
<template>
<view-base :queries="queries" @queries-response="onQueriesResponse">
<ViewBase :queries="queries" @queries-response="onQueriesResponse">
<template v-if="app">
<section class="border rounded p-3 mb-4">
<div class="d-md-flex align-items-center mb-4">
@ -7,14 +7,14 @@
{{ app.name }}
</h1>
<b-button
<BButton
v-if="app.demo"
:href="app.demo" target="_blank"
variant="primary" class="ml-auto"
>
<icon iname="external-link" />
<Icon iname="external-link" />
{{ $t('app.install.try_demo') }}
</b-button>
</BButton>
</div>
<p class="text-secondary">
@ -25,58 +25,58 @@
</template>
</p>
<vue-showdown :markdown="app.description" flavor="github" />
<VueShowdown :markdown="app.description" flavor="github" />
<b-img
<BImg
v-if="app.screenshot"
:src="app.screenshot"
aria-hidden="true" class="d-block" fluid
/>
</section>
<card
<Card
v-if="app.integration"
id="app-integration" :title="$t('app.integration.title')"
collapsable collapsed no-body
>
<b-list-group flush>
<yuno-list-group-item variant="info">
<BListGroup flush>
<YunoListGroupItem variant="info">
{{ $t('app.integration.archs') }} {{ app.integration.archs }}
</yuno-list-group-item>
<yuno-list-group-item v-if="app.integration.ldap" :variant="app.integration.ldap === true ? 'success' : 'warning'">
</YunoListGroupItem>
<YunoListGroupItem v-if="app.integration.ldap" :variant="app.integration.ldap === true ? 'success' : 'warning'">
{{ $t(`app.integration.ldap.${app.integration.ldap}`) }}
</yuno-list-group-item>
<yuno-list-group-item v-if="app.integration.sso" :variant="app.integration.sso === true ? 'success' : 'warning'">
</YunoListGroupItem>
<YunoListGroupItem v-if="app.integration.sso" :variant="app.integration.sso === true ? 'success' : 'warning'">
{{ $t(`app.integration.sso.${app.integration.sso}`) }}
</yuno-list-group-item>
<yuno-list-group-item variant="info">
</YunoListGroupItem>
<YunoListGroupItem variant="info">
{{ $t(`app.integration.multi_instance.${app.integration.multi_instance}`) }}
</yuno-list-group-item>
<yuno-list-group-item variant="info">
</YunoListGroupItem>
<YunoListGroupItem variant="info">
{{ $t('app.integration.resources', app.integration.resources) }}
</yuno-list-group-item>
</b-list-group>
</card>
</YunoListGroupItem>
</BListGroup>
</Card>
<card
<Card
id="app-links" icon="link" :title="$t('app.links.title')"
collapsable collapsed no-body
>
<template #header>
<h2><icon iname="link" /> {{ $t('app.links.title') }}</h2>
<h2><Icon iname="link" /> {{ $t('app.links.title') }}</h2>
</template>
<b-list-group flush>
<yuno-list-group-item v-for="[key, link] in app.links" :key="key" no-status>
<b-link :href="link" target="_blank">
<icon :iname="appLinksIcons(key)" class="mr-1" />
<BListGroup flush>
<YunoListGroupItem v-for="[key, link] in app.links" :key="key" no-status>
<BLink :href="link" target="_blank">
<Icon :iname="appLinksIcons(key)" class="mr-1" />
{{ $t('app.links.' + key) }}
</b-link>
</yuno-list-group-item>
</b-list-group>
</card>
</BLink>
</YunoListGroupItem>
</BListGroup>
</Card>
<yuno-alert v-if="app.hasWarning" variant="warning" class="my-4">
<YunoAlert v-if="app.hasWarning" variant="warning" class="my-4">
<h2>{{ $t('app.install.notifs.pre.warning') }}</h2>
<template v-if="app.antifeatures">
@ -84,7 +84,7 @@
<dl class="antifeatures">
<div v-for="antifeature in app.antifeatures" :key="antifeature.id">
<dt class="d-inline">
<icon :iname="antifeature.icon" class="md mr-1" />
<Icon :iname="antifeature.icon" class="md mr-1" />
{{ antifeature.title }}:
</dt>
<dd class="d-inline">
@ -96,10 +96,10 @@
<p v-if="app.quality.state === 'lowquality'" v-t="'app.install.problems.lowquality'" />
<vue-showdown v-if="app.preInstall" :markdown="app.preInstall" flavor="github" />
</yuno-alert>
<VueShowdown v-if="app.preInstall" :markdown="app.preInstall" flavor="github" />
</YunoAlert>
<yuno-alert
<YunoAlert
v-if="!app.hasSupport"
variant="danger" icon="warning" class="my-4"
>
@ -114,9 +114,9 @@
<p v-if="!app.requirements.required_yunohost_version.pass">
{{ $t('app.install.problems.version', app.requirements.required_yunohost_version.values) }}
</p>
</yuno-alert>
</YunoAlert>
<yuno-alert v-else-if="app.hasDanger" variant="danger" class="my-4">
<YunoAlert v-else-if="app.hasDanger" variant="danger" class="my-4">
<h2>{{ $t('app.install.notifs.pre.danger') }}</h2>
<p v-if="['inprogress', 'broken', 'thirdparty'].includes(app.quality.state)" v-t="'app.install.problems.' + app.quality.state" />
@ -124,35 +124,35 @@
{{ $t('app.install.problems.ram', app.requirements.ram.values) }}
</p>
<checkbox-item v-model="force" id="force-install" :label="$t('app.install.problems.ignore')" />
</yuno-alert>
<CheckboxItem v-model="force" id="force-install" :label="$t('app.install.problems.ignore')" />
</YunoAlert>
<!-- INSTALL FORM -->
<card-form
<CardForm
v-if="app.canInstall || force"
:title="$t('app_install_parameters')" icon="cog" :submit-text="$t('install')"
:validation="$v" :server-error="serverError"
@submit.prevent="performInstall"
>
<template v-for="(field, fname) in fields">
<component
<Component
v-if="field.visible" :is="field.is" v-bind="field.props"
v-model="form[fname]" :validation="$v.form[fname]" :key="fname"
/>
</template>
</card-form>
</CardForm>
</template>
<!-- In case of a custom url with no manifest found -->
<b-alert v-else-if="app === null" variant="warning">
<icon iname="exclamation-triangle" /> {{ $t('app_install_custom_no_manifest') }}
</b-alert>
<BAlert v-else-if="app === null" variant="warning">
<Icon iname="exclamation-triangle" /> {{ $t('app_install_custom_no_manifest') }}
</BAlert>
<template #skeleton>
<card-info-skeleton />
<card-form-skeleton :cols="null" />
<CardInfoSkeleton />
<CardFormSkeleton :cols="null" />
</template>
</view-base>
</ViewBase>
</template>
<script>

View file

@ -1,5 +1,5 @@
<template>
<view-search
<ViewSearch
:search.sync="search"
items-name="installed_apps"
:items="apps"
@ -8,14 +8,14 @@
@queries-response="onQueriesResponse"
>
<template #top-bar-buttons>
<b-button variant="success" :to="{ name: 'app-catalog' }">
<icon iname="plus" />
<BButton variant="success" :to="{ name: 'app-catalog' }">
<Icon iname="plus" />
{{ $t('install') }}
</b-button>
</BButton>
</template>
<b-list-group>
<b-list-group-item
<BListGroup>
<BListGroupItem
v-for="{ id, description, label } in filteredApps" :key="id"
:to="{ name: 'app-info', params: { id }}"
class="d-flex justify-content-between align-items-center pr-0"
@ -30,10 +30,10 @@
</p>
</div>
<icon iname="chevron-right" class="lg fs-sm ml-auto" />
</b-list-group-item>
</b-list-group>
</view-search>
<Icon iname="chevron-right" class="lg fs-sm ml-auto" />
</BListGroupItem>
</BListGroup>
</ViewSearch>
</template>
<script>

View file

@ -1,7 +1,7 @@
<template>
<div>
<b-list-group>
<b-list-group-item
<BListGroup>
<BListGroupItem
v-for="{ id, name, uri } in storages" :key="id"
:to="{ name: 'backup-list', params: { id }}"
class="d-flex justify-content-between align-items-center pr-0"
@ -15,9 +15,9 @@
{{ uri }}
</p>
</div>
<icon iname="chevron-right" class="lg fs-sm ml-auto" />
</b-list-group-item>
</b-list-group>
<Icon iname="chevron-right" class="lg fs-sm ml-auto" />
</BListGroupItem>
</BListGroup>
</div>
</template>

View file

@ -1,33 +1,33 @@
<template>
<view-base :queries="queries" @queries-response="onQueriesResponse" skeleton="card-list-skeleton">
<!-- FIXME switch to <card-form> ? -->
<card :title="$t('backup_create')" icon="archive" no-body>
<b-form-checkbox-group
<ViewBase :queries="queries" @queries-response="onQueriesResponse" skeleton="CardListSkeleton">
<!-- FIXME switch to <CardForm> ? -->
<Card :title="$t('backup_create')" icon="archive" no-body>
<BFormCheckboxGroup
v-model="selected"
id="backup-select" name="backup-select" size="lg"
>
<b-list-group flush>
<BListGroup flush>
<!-- SYSTEM HEADER -->
<b-list-group-item class="d-flex align-items-sm-center flex-column flex-sm-row text-primary">
<BListGroupItem class="d-flex align-items-sm-center flex-column flex-sm-row text-primary">
<h4 class="m-0">
<icon iname="cube" /> {{ $t('system') }}
<Icon iname="cube" /> {{ $t('system') }}
</h4>
<div class="ml-sm-auto mt-2 mt-sm-0">
<b-button
<BButton
@click="toggleSelected(true, 'system')" v-t="'select_all'"
size="sm" variant="outline-dark"
/>
<b-button
<BButton
@click="toggleSelected(false, 'system')" v-t="'select_none'"
size="sm" variant="outline-dark" class="ml-2"
/>
</div>
</b-list-group-item>
</BListGroupItem>
<!-- SYSTEM ITEMS -->
<b-list-group-item
<BListGroupItem
v-for="(item, partName) in system" :key="partName"
class="d-flex justify-content-between align-items-center pr-0"
>
@ -40,30 +40,30 @@
</p>
</div>
<b-form-checkbox :value="partName" :aria-label="$t('check')" class="d-inline" />
</b-list-group-item>
<BFormCheckbox :value="partName" :aria-label="$t('check')" class="d-inline" />
</BListGroupItem>
<!-- APPS HEADER -->
<b-list-group-item class="d-flex align-items-sm-center flex-column flex-sm-row text-primary">
<BListGroupItem class="d-flex align-items-sm-center flex-column flex-sm-row text-primary">
<h4 class="m-0">
<icon iname="cubes" /> {{ $t('applications') }}
<Icon iname="cubes" /> {{ $t('applications') }}
</h4>
<div class="ml-sm-auto mt-2 mt-sm-0">
<b-button
<BButton
@click="toggleSelected(true, 'apps')" v-t="'select_all'"
size="sm" variant="outline-dark"
/>
<b-button
<BButton
@click="toggleSelected(false, 'apps')" v-t="'select_none'"
size="sm" variant="outline-dark" class="ml-2"
/>
</div>
</b-list-group-item>
</BListGroupItem>
<!-- APPS ITEMS -->
<b-list-group-item
<BListGroupItem
v-for="(item, appName) in apps" :key="appName"
class="d-flex justify-content-between align-items-center pr-0"
>
@ -76,20 +76,20 @@
</p>
</div>
<b-form-checkbox :value="appName" :aria-label="$t('check')" class="d-inline" />
</b-list-group-item>
</b-list-group>
</b-form-checkbox-group>
<BFormCheckbox :value="appName" :aria-label="$t('check')" class="d-inline" />
</BListGroupItem>
</BListGroup>
</BFormCheckboxGroup>
<!-- SUBMIT -->
<template #buttons>
<b-button
<BButton
@click="createBackup" v-t="'backup_action'"
variant="success" :disabled="selected.length === 0"
/>
</template>
</card>
</view-base>
</Card>
</ViewBase>
</template>
<script>

View file

@ -1,60 +1,60 @@
<template>
<view-base :queries="queries" @queries-response="onQueriesResponse">
<ViewBase :queries="queries" @queries-response="onQueriesResponse">
<!-- BACKUP INFO -->
<card :title="$t('infos')" icon="info-circle" button-unbreak="sm">
<Card :title="$t('infos')" icon="info-circle" button-unbreak="sm">
<template #header-buttons>
<!-- DOWNLOAD ARCHIVE -->
<b-button @click="downloadBackup" size="sm" variant="success">
<icon iname="download" /> {{ $t('download') }}
</b-button>
<BButton @click="downloadBackup" size="sm" variant="success">
<Icon iname="download" /> {{ $t('download') }}
</BButton>
<!-- DELETE ARCHIVE -->
<b-button @click="deleteBackup" size="sm" variant="danger">
<icon iname="trash-o" /> {{ $t('delete') }}
</b-button>
<BButton @click="deleteBackup" size="sm" variant="danger">
<Icon iname="trash-o" /> {{ $t('delete') }}
</BButton>
</template>
<b-row
<BRow
v-for="(value, prop) in infos" :key="prop"
no-gutters class="row-line"
>
<b-col md="3" xl="2">
<BCol md="3" xl="2">
<strong>{{ $t(prop === 'name' ? 'id' : prop) }}</strong>
</b-col>
<b-col>
</BCol>
<BCol>
<span v-if="prop === 'created_at'">{{ value | readableDate }}</span>
<span v-else-if="prop === 'size'">{{ value | humanSize }}</span>
<span v-else>{{ value }}</span>
</b-col>
</b-row>
</card>
</BCol>
</BRow>
</Card>
<!-- BACKUP CONTENT -->
<!-- FIXME switch to <card-form> ? -->
<card
<!-- FIXME switch to <CardForm> ? -->
<Card
:title="$t('backup_content')" icon="archive"
no-body button-unbreak="sm"
>
<template #header-buttons>
<b-button
<BButton
size="sm" variant="outline-secondary"
@click="toggleSelected()" v-t="'select_all'"
/>
<b-button
<BButton
size="sm" variant="outline-secondary"
@click="toggleSelected(false)" v-t="'select_none'"
/>
</template>
<b-form-checkbox-group
<BFormCheckboxGroup
v-if="hasBackupData" v-model="selected"
id="backup-select" name="backup-select" size="lg"
aria-describedby="backup-restore-feedback"
>
<b-list-group flush>
<BListGroup flush>
<!-- SYSTEM PARTS -->
<b-list-group-item
<BListGroupItem
v-for="(item, partName) in system" :key="partName"
class="d-flex justify-content-between align-items-center pr-0"
>
@ -67,11 +67,11 @@
</p>
</div>
<b-form-checkbox :value="partName" :aria-label="$t('check')" />
</b-list-group-item>
<BFormCheckbox :value="partName" :aria-label="$t('check')" />
</BListGroupItem>
<!-- APPS -->
<b-list-group-item
<BListGroupItem
v-for="(item, appName) in apps" :key="appName"
class="d-flex justify-content-between align-items-center pr-0"
>
@ -84,35 +84,35 @@
</p>
</div>
<b-form-checkbox :value="appName" :aria-label="$t('check')" />
</b-list-group-item>
</b-list-group>
<BFormCheckbox :value="appName" :aria-label="$t('check')" />
</BListGroupItem>
</BListGroup>
<b-form-invalid-feedback id="backup-restore-feedback" :state="isValid">
<b-alert variant="danger" class="mb-0">
<BFormInvalidFeedback id="backup-restore-feedback" :state="isValid">
<BAlert variant="danger" class="mb-0">
{{ error }}
</b-alert>
</b-form-invalid-feedback>
</b-form-checkbox-group>
</BAlert>
</BFormInvalidFeedback>
</BFormCheckboxGroup>
<div v-else class="alert alert-warning mb-0">
<icon iname="exclamation-triangle" /> {{ $t('archive_empty') }}
<Icon iname="exclamation-triangle" /> {{ $t('archive_empty') }}
</div>
<!-- SUBMIT -->
<template v-if="hasBackupData" #buttons>
<b-button
<BButton
@click="restoreBackup" form="backup-restore" variant="success"
v-t="'restore'" :disabled="selected.length === 0"
/>
</template>
</card>
</Card>
<template #skeleton>
<card-info-skeleton :item-count="4" />
<card-list-skeleton />
<CardInfoSkeleton :item-count="4" />
<CardListSkeleton />
</template>
</view-base>
</ViewBase>
</template>
<script>

View file

@ -1,16 +1,16 @@
<template>
<view-base :queries="queries" @queries-response="onQueriesResponse" skeleton="list-group-skeleton">
<ViewBase :queries="queries" @queries-response="onQueriesResponse" skeleton="ListGroupSkeleton">
<template #top>
<top-bar :button="{ text: $t('backup_new'), icon: 'plus', to: { name: 'backup-create' } }" />
<TopBar :button="{ text: $t('backup_new'), icon: 'plus', to: { name: 'backup-create' } }" />
</template>
<b-alert v-if="!archives" variant="warning">
<icon iname="exclamation-triangle" />
<BAlert v-if="!archives" variant="warning">
<Icon iname="exclamation-triangle" />
{{ $tc('items_verbose_count', 0, { items: $tc('items.backups', 0) }) }}
</b-alert>
</BAlert>
<b-list-group v-else>
<b-list-group-item
<BListGroup v-else>
<BListGroupItem
v-for="{ name, created_at, path, size } in archives" :key="name"
:to="{ name: 'backup-info', params: { name, id }}"
:title="created_at | readableDate"
@ -25,10 +25,10 @@
{{ path }}
</p>
</div>
<icon iname="chevron-right" class="lg fs-sm ml-auto" />
</b-list-group-item>
</b-list-group>
</view-base>
<Icon iname="chevron-right" class="lg fs-sm ml-auto" />
</BListGroupItem>
</BListGroup>
</ViewBase>
</template>
<script>

View file

@ -1,28 +1,28 @@
<template>
<view-base
<ViewBase
:queries="queries" @queries-response="onQueriesResponse" queries-wait
ref="view"
>
<template #top-bar-group-right>
<b-button @click="shareLogs" variant="success">
<icon iname="cloud-upload" /> {{ $t('logs_share_with_yunopaste') }}
</b-button>
<BButton @click="shareLogs" variant="success">
<Icon iname="cloud-upload" /> {{ $t('logs_share_with_yunopaste') }}
</BButton>
</template>
<template #top>
<div class="alert alert-info">
{{ $t(reports ? 'diagnosis_explanation' : 'diagnosis_first_run') }}
<b-button
<BButton
v-if="reports === null" class="d-block mt-2" variant="info"
@click="runDiagnosis()"
>
<icon iname="stethoscope" /> {{ $t('run_first_diagnosis') }}
</b-button>
<Icon iname="stethoscope" /> {{ $t('run_first_diagnosis') }}
</BButton>
</div>
</template>
<!-- REPORT CARD -->
<card
<Card
v-for="report in reports" :key="report.id"
collapsable :collapsed="report.noIssues"
no-body button-unbreak="lg"
@ -32,17 +32,17 @@
<h2>{{ report.description }}</h2>
<div class="">
<b-badge v-if="report.noIssues" variant="success" v-t="'everything_good'" />
<b-badge v-if="report.errors" variant="danger" v-t="{ path: 'issues', args: { count: report.errors } }" />
<b-badge v-if="report.warnings" variant="warning" v-t="{ path: 'warnings', args: { count: report.warnings } }" />
<b-badge v-if="report.ignoreds" v-t="{ path: 'ignored', args: { count: report.ignoreds } }" />
<BBadge v-if="report.noIssues" variant="success" v-t="'everything_good'" />
<BBadge v-if="report.errors" variant="danger" v-t="{ path: 'issues', args: { count: report.errors } }" />
<BBadge v-if="report.warnings" variant="warning" v-t="{ path: 'warnings', args: { count: report.warnings } }" />
<BBadge v-if="report.ignoreds" v-t="{ path: 'ignored', args: { count: report.ignoreds } }" />
</div>
</template>
<template #header-buttons>
<b-button size="sm" :variant="report.items ? 'info' : 'success'" @click="runDiagnosis(report)">
<icon iname="refresh" /> {{ $t('rerun_diagnosis') }}
</b-button>
<BButton size="sm" :variant="report.items ? 'info' : 'success'" @click="runDiagnosis(report)">
<Icon iname="refresh" /> {{ $t('rerun_diagnosis') }}
</BButton>
</template>
<!-- REPORT BODY -->
@ -50,58 +50,58 @@
{{ $t('last_ran') }} {{ report.timestamp | distanceToNow(true, true) }}
</p>
<b-list-group flush>
<BListGroup flush>
<!-- REPORT ITEM -->
<yuno-list-group-item
<YunoListGroupItem
v-for="(item, i) in report.items" :key="i"
:variant="item.variant" :icon="item.icon" :faded="item.ignored"
:variant="item.variant" :Icon="item.Icon" :faded="item.ignored"
>
<div class="item-button d-flex align-items-center">
<p class="mb-0 mr-2" v-html="item.summary" />
<div class="d-flex flex-column flex-lg-row ml-auto">
<b-button
<BButton
v-if="item.ignored" size="sm"
@click="toggleIgnoreIssue('unignore', report, item)"
>
<icon iname="bell" /> {{ $t('unignore') }}
</b-button>
<b-button
<Icon iname="bell" /> {{ $t('unignore') }}
</BButton>
<BButton
v-else-if="item.issue" variant="warning" size="sm"
@click="toggleIgnoreIssue('ignore', report, item)"
>
<icon iname="bell-slash" /> {{ $t('ignore') }}
</b-button>
<Icon iname="bell-slash" /> {{ $t('ignore') }}
</BButton>
<b-button
<BButton
v-if="item.details"
size="sm" variant="outline-dark" class="ml-lg-2 mt-2 mt-lg-0"
v-b-toggle="`collapse-${report.id}-item-${i}`"
>
<icon iname="level-down" /> {{ $t('details') }}
</b-button>
<Icon iname="level-down" /> {{ $t('details') }}
</BButton>
</div>
</div>
<b-collapse v-if="item.details" :id="`collapse-${report.id}-item-${i}`">
<BCollapse v-if="item.details" :id="`collapse-${report.id}-item-${i}`">
<ul class="mt-2 pl-4">
<li v-for="(detail, index) in item.details" :key="index" v-html="detail" />
</ul>
</b-collapse>
</yuno-list-group-item>
</b-list-group>
</card>
</BCollapse>
</YunoListGroupItem>
</BListGroup>
</Card>
<template #skeleton>
<card-list-skeleton />
<b-card no-body>
<CardListSkeleton />
<BCard no-body>
<template #header>
<b-skeleton width="30%" height="36px" class="m-0" />
<BSkeleton width="30%" height="36px" class="m-0" />
</template>
</b-card>
<card-list-skeleton />
</BCard>
<CardListSkeleton />
</template>
</view-base>
</ViewBase>
</template>
<script>

View file

@ -1,10 +1,10 @@
<template>
<view-base :queries="queries" skeleton="card-form-skeleton">
<domain-form
<ViewBase :queries="queries" skeleton="CardFormSkeleton">
<DomainForm
:title="$t('domain_add')" :server-error="serverError"
@submit="onSubmit" :submit-text="$t('add')"
/>
</view-base>
</ViewBase>
</template>
<script>

View file

@ -1,14 +1,14 @@
<template>
<view-base
<ViewBase
:queries="queries" @queries-response="onQueriesResponse" :loading="loading"
skeleton="card-info-skeleton"
skeleton="CardInfoSkeleton"
>
<section v-if="showAutoConfigCard" class="panel-section">
<b-card-title title-tag="h3">
<BCardTitle title-tag="h3">
{{ $t('domain.dns.auto_config') }}
</b-card-title>
</BCardTitle>
<read-only-alert-item
<ReadOnlyAlertItem
:label="$t('domain.dns.info')"
type="warning"
icon="flask"
@ -27,7 +27,7 @@
class="records px-2" :class="{ 'ignored': managed_by_yunohost === false && force !== true }"
:title="managed_by_yunohost === false && force !== true ? $t('domain.dns.auto_config_ignored') : null"
>
<icon :iname="icon" :class="'text-' + variant" />
<Icon :iname="icon" :class="'text-' + variant" />
{{ record }}
<span class="bg-dark text-light px-1 rounded">{{ type }}</span>{{ spaces }}
<span v-if="old_content"><span class="text-danger">{{ old_content }}</span> --> </span>
@ -38,7 +38,7 @@
</template>
<!-- CONFIG OK ALERT -->
<read-only-alert-item
<ReadOnlyAlertItem
v-else-if="dnsChanges === null"
:label="$t('domain.dns.auto_config_ok')"
type="success"
@ -47,7 +47,7 @@
<!-- CONFIG ERROR ALERT -->
<template v-if="dnsErrors && dnsErrors.length">
<read-only-alert-item
<ReadOnlyAlertItem
v-for="({ variant, icon, message }, i) in dnsErrors" :key="i"
:label="message"
:type="variant"
@ -56,7 +56,7 @@
</template>
<!-- CONFIG OVERWRITE DISCLAIMER -->
<read-only-alert-item
<ReadOnlyAlertItem
v-if="force !== null"
:label="$t('domain.dns.push_force_warning')"
type="warning"
@ -64,21 +64,21 @@
<!-- CONFIG PUSH SUBMIT -->
<template v-if="dnsChanges">
<b-form-checkbox v-if="force !== null" v-model="force">
<BFormCheckbox v-if="force !== null" v-model="force">
{{ $t('domain.dns.push_force') }}
</b-form-checkbox>
</BFormCheckbox>
<b-button variant="success" @click="pushDnsChanges">
<BButton variant="success" @click="pushDnsChanges">
{{ $t('domain.dns.push') }}
</b-button>
</BButton>
</template>
</section>
<!-- CURRENT DNS ZONE -->
<section v-if="showAutoConfigCard && dnsZone && dnsZone.length" class="panel-section">
<b-card-title title-tag="h3">
<BCardTitle title-tag="h3">
{{ $t('domain.dns.auto_config_zone') }}
</b-card-title>
</BCardTitle>
<div class="log">
<div v-for="({ name: record, spaces, content, type }, i) in dnsZone" :key="'zone-' + i" class="records">
@ -91,18 +91,18 @@
<!-- MANUAL CONFIG CARD -->
<section v-if="showManualConfigCard" class="panel-section">
<b-card-title title-tag="h3">
<BCardTitle title-tag="h3">
{{ $t('domain.dns.manual_config') }}
</b-card-title>
</BCardTitle>
<read-only-alert-item
<ReadOnlyAlertItem
:label="$t('domain_dns_conf_is_just_a_recommendation')"
type="warning"
/>
<pre class="log">{{ dnsConfig }}</pre>
</section>
</view-base>
</ViewBase>
</template>
<script>

View file

@ -1,102 +1,102 @@
<template>
<view-base
<ViewBase
:queries="queries" @queries-response="onQueriesResponse"
ref="view" skeleton="card-list-skeleton"
ref="view" skeleton="CardListSkeleton"
>
<!-- INFO CARD -->
<card v-if="domain" :title="name" icon="globe">
<Card v-if="domain" :title="name" icon="globe">
<template v-if="isMainDomain" #header-next>
<b-badge variant="info" class="main-domain-badge">
<explain-what
<BBadge variant="info" class="main-domain-badge">
<ExplainWhat
id="explain-main-domain"
:title="$t('domain.types.main_domain')"
:content="$t('domain.explain.main_domain', { domain: name })"
>
<icon iname="star" /> {{ $t('domain.types.main_domain') }}
</explain-what>
</b-badge>
<Icon iname="star" /> {{ $t('domain.types.main_domain') }}
</ExplainWhat>
</BBadge>
</template>
<template #header-buttons>
<!-- DEFAULT DOMAIN -->
<b-button v-if="!isMainDomain" @click="setAsDefaultDomain" variant="info">
<icon iname="star" /> {{ $t('set_default') }}
</b-button>
<BButton v-if="!isMainDomain" @click="setAsDefaultDomain" variant="info">
<Icon iname="star" /> {{ $t('set_default') }}
</BButton>
<!-- DELETE DOMAIN -->
<b-button v-b-modal.delete-modal :disabled="isMainDomain" variant="danger">
<icon iname="trash-o" /> {{ $t('delete') }}
</b-button>
<BButton v-b-modal.delete-modal :disabled="isMainDomain" variant="danger">
<Icon iname="trash-o" /> {{ $t('delete') }}
</BButton>
</template>
<!-- DOMAIN LINK -->
<description-row :term="$t('words.link')">
<b-link :href="'https://' + name" target="_blank">
<DescriptionRow :term="$t('words.link')">
<BLink :href="'https://' + name" target="_blank">
https://{{ name }}
</b-link>
</description-row>
</BLink>
</DescriptionRow>
<!-- DOMAIN CERT AUTHORITY -->
<description-row :term="$t('domain.info.certificate_authority')">
<icon :iname="cert.icon" :variant="cert.variant" class="mr-1" />
<DescriptionRow :term="$t('domain.info.certificate_authority')">
<Icon :iname="cert.icon" :variant="cert.variant" class="mr-1" />
{{ $t('domain.cert.types.' + cert.authority) }}
<span class="text-secondary px-2">({{ $t('domain.cert.valid_for', { days: $tc('day_validity', cert.validity) }) }})</span>
</description-row>
</DescriptionRow>
<!-- DOMAIN REGISTRAR -->
<description-row v-if="domain.registrar" :term="$t('domain.info.registrar')">
<DescriptionRow v-if="domain.registrar" :term="$t('domain.info.registrar')">
<template v-if="domain.registrar === 'parent_domain'">
{{ $t('domain.see_parent_domain') }}&nbsp;<b-link :href="`#/domains/${domain.topest_parent}/dns`">
{{ $t('domain.see_parent_domain') }}&nbsp;<BLink :href="`#/domains/${domain.topest_parent}/dns`">
{{ domain.topest_parent }}
</b-link>
</BLink>
</template>
<template v-else>
{{ domain.registrar }}
</template>
</description-row>
</DescriptionRow>
<!-- DOMAIN APPS -->
<description-row :term="$t('domain.info.apps_on_domain')">
<DescriptionRow :term="$t('domain.info.apps_on_domain')">
<div>
<b-button-group
<BButton-group
v-for="app in domain.apps" :key="app.id"
size="sm" class="mr-2 mb-2"
>
<b-button class="py-0 font-weight-bold" variant="outline-dark" :to="{ name: 'app-info', params: { id: app.id }}">
<BButton class="py-0 font-weight-bold" variant="outline-dark" :to="{ name: 'app-info', params: { id: app.id }}">
{{ app.name }}
</b-button>
<b-button
</BButton>
<BButton
variant="outline-dark" class="py-0 px-1"
:href="'https://' + name + app.path" target="_blank"
>
<span class="sr-only">{{ $t('app.visit_app') }}</span>
<icon iname="external-link" />
</b-button>
</b-button-group>
<Icon iname="external-link" />
</BButton>
</BButton-group>
{{ domain.apps.length ? '' : $t('words.none') }}
</div>
</description-row>
</card>
</DescriptionRow>
</Card>
<config-panels v-if="config.panels" v-bind="config" @submit="onConfigSubmit">
<ConfigPanels v-if="config.panels" v-bind="config" @submit="onConfigSubmit">
<template v-if="currentTab === 'dns'" #tab-after>
<domain-dns :name="name" />
<DomainDns :name="name" />
</template>
</config-panels>
</ConfigPanels>
<b-modal
<BModal
v-if="domain"
id="delete-modal" :title="$t('confirm_delete', { name: this.name })" @ok="deleteDomain"
header-bg-variant="warning" body-class="" body-bg-variant=""
>
<b-form-group v-if="isMainDynDomain">
<b-form-checkbox v-model="unsubscribeDomainFromDyndns">
<BFormGroup v-if="isMainDynDomain">
<BFormCheckbox v-model="unsubscribeDomainFromDyndns">
{{ $t('domain.info.dyn_dns_remove_and_unsubscribe') }}
</b-form-checkbox>
</b-form-group>
</b-modal>
</view-base>
</BFormCheckbox>
</BFormGroup>
</BModal>
</ViewBase>
</template>
<script>

View file

@ -1,5 +1,5 @@
<template>
<view-search
<ViewSearch
id="domain-list"
:search.sync="search"
:items="domains"
@ -9,33 +9,33 @@
@queries-response="onQueriesResponse"
>
<template #top-bar-buttons>
<b-button variant="success" :to="{ name: 'domain-add' }">
<icon iname="plus" />
<BButton variant="success" :to="{ name: 'domain-add' }">
<Icon iname="plus" />
{{ $t('domain_add') }}
</b-button>
</BButton>
</template>
<recursive-list-group :tree="tree" :toggle-text="$t('domain.toggle_subdomains')" class="mb-5">
<RecursiveListGroup :tree="tree" :toggle-text="$t('domain.toggle_subdomains')" class="mb-5">
<template #default="{ data, parent }">
<div class="w-100 d-flex justify-content-between align-items-center">
<h5 class="mr-3">
<b-link :to="data.to" class="text-body text-decoration-none">
<BLink :to="data.to" class="text-body text-decoration-none">
<span class="font-weight-bold">{{ data.name.replace(parent ? parent.data.name : null, '') }}</span>
<span v-if="parent" class="text-secondary">{{ parent.data.name }}</span>
</b-link>
</BLink>
<small
v-if="data.name === mainDomain"
:title="$t('domain.types.main_domain')" class="ml-1"
v-b-tooltip.hover
>
<icon iname="star" />
<Icon iname="star" />
</small>
</h5>
</div>
</template>
</recursive-list-group>
</view-search>
</RecursiveListGroup>
</ViewSearch>
</template>
<script>

View file

@ -1,12 +1,12 @@
<template>
<card-form
<CardForm
:title="$t('group_new')" icon="users"
:validation="$v" :server-error="serverError"
@submit.prevent="onSubmit"
>
<!-- GROUP NAME -->
<form-field v-bind="groupname" v-model="form.groupname" :validation="$v.form.groupname" />
</card-form>
<FormField v-bind="groupname" v-model="form.groupname" :validation="$v.form.groupname" />
</CardForm>
</template>
<script>

View file

@ -1,107 +1,107 @@
<template>
<view-search
<ViewSearch
items-name="groups"
:search.sync="search"
:items="primaryGroups"
:filtered-items="filteredGroups"
:queries="queries"
@queries-response="onQueriesResponse"
skeleton="card-form-skeleton"
skeleton="CardFormSkeleton"
>
<template #top-bar-buttons>
<b-button variant="success" :to="{ name: 'group-create' }">
<icon iname="plus" /> {{ $t('group_new') }}
</b-button>
<BButton variant="success" :to="{ name: 'group-create' }">
<Icon iname="plus" /> {{ $t('group_new') }}
</BButton>
</template>
<!-- PRIMARY GROUPS CARDS -->
<card
<Card
v-for="(group, groupName) in filteredGroups" :key="groupName" collapsable
:title="group.isSpecial ? $t('group_' + groupName) : `${$t('group')} '${groupName}'`" icon="group"
>
<template #header-buttons>
<!-- DELETE GROUP -->
<b-button
<BButton
v-if="!group.isSpecial" @click="deleteGroup(groupName)"
size="sm" variant="danger"
>
<icon iname="trash-o" /> {{ $t('delete') }}
</b-button>
<Icon iname="trash-o" /> {{ $t('delete') }}
</BButton>
</template>
<b-row>
<b-col md="3" lg="2">
<BRow>
<BCol md="3" lg="2">
<strong>{{ $t('users') }}</strong>
</b-col>
</BCol>
<b-col>
<BCol>
<template v-if="group.isSpecial">
<p class="text-primary">
<icon iname="info-circle" /> {{ $t('group_explain_' + groupName) }}
<Icon iname="info-circle" /> {{ $t('group_explain_' + groupName) }}
</p>
<p class="text-primary" v-if="groupName === 'visitors'">
<em>{{ $t('group_explain_visitors_needed_for_external_client') }}</em>
</p>
</template>
<template v-if="groupName == 'admins' || !group.isSpecial">
<tags-selectize-item
<TagsSelectizeItem
v-model="group.members" :options="usersOptions"
:id="groupName + '-users'" :label="$t('group_add_member')"
tag-icon="user" items-name="users"
@tag-update="onUserChanged({ ...$event, groupName })"
/>
</template>
</b-col>
</b-row>
</BCol>
</BRow>
<hr>
<b-row>
<b-col md="3" lg="2">
<BRow>
<BCol md="3" lg="2">
<strong>{{ $t('permissions') }}</strong>
</b-col>
<b-col>
<tags-selectize-item
</BCol>
<BCol>
<TagsSelectizeItem
v-model="group.permissions" :options="permissionsOptions"
:id="groupName + '-perms'" :label="$t('group_add_permission')"
tag-icon="key-modern" items-name="permissions"
@tag-update="onPermissionChanged({ ...$event, groupName })"
:disabled-items="group.disabledItems"
/>
</b-col>
</b-row>
</card>
</BCol>
</BRow>
</Card>
<!-- USER GROUPS CARD -->
<card
<Card
v-if="userGroups" collapsable
:title="$t('group_specific_permissions')" icon="group"
>
<template v-for="(userName, index) in activeUserGroups">
<b-row :key="userName">
<b-col md="3" lg="2">
<BRow :key="userName">
<BCol md="3" lg="2">
<icon iname="user" /> <strong>{{ userName }}</strong>
</b-col>
</BCol>
<b-col>
<tags-selectize-item
<BCol>
<TagsSelectizeItem
v-model="userGroups[userName].permissions" :options="permissionsOptions"
:id="userName + '-perms'" :label="$t('group_add_permission')"
tag-icon="key-modern" items-name="permissions"
@tag-update="onPermissionChanged({ ...$event, groupName: userName })"
/>
</b-col>
</b-row>
</BCol>
</BRow>
<hr :key="index">
</template>
<tags-selectize-item
<TagsSelectizeItem
v-model="activeUserGroups" :options="usersOptions"
id="user-groups" :label="$t('group_add_member')"
no-tags items-name="users"
@tag-update="onSpecificUserAdded"
/>
</card>
</view-search>
</Card>
</ViewSearch>
</template>
<script>

View file

@ -1,40 +1,40 @@
<template>
<view-base
<ViewBase
:queries="queries" @queries-response="onQueriesResponse"
ref="view" skeleton="card-info-skeleton"
ref="view" skeleton="CardInfoSkeleton"
>
<!-- INFO CARD -->
<card :title="name" icon="info-circle" button-unbreak="sm">
<Card :title="name" icon="info-circle" button-unbreak="sm">
<template #header-buttons>
<template v-if="infos.status === 'running'">
<!-- RESTART SERVICE -->
<b-button @click="updateService('restart')" variant="warning">
<icon iname="refresh" /> {{ $t('restart') }}
</b-button>
<BButton @click="updateService('restart')" variant="warning">
<Icon iname="refresh" /> {{ $t('restart') }}
</BButton>
<!-- STOP SERVICE -->
<b-button v-if="!isCritical" @click="updateService('stop')" variant="danger">
<icon iname="warning" /> {{ $t('stop') }}
</b-button>
<BButton v-if="!isCritical" @click="updateService('stop')" variant="danger">
<Icon iname="warning" /> {{ $t('stop') }}
</BButton>
</template>
<!-- START SERVICE -->
<b-button v-else @click="updateService('start')" variant="success">
<icon iname="play" /> {{ $t('start') }}
</b-button>
<BButton v-else @click="updateService('start')" variant="success">
<Icon iname="play" /> {{ $t('start') }}
</BButton>
</template>
<b-row
<BRow
v-for="(value, key) in infos" :key="key"
no-gutters class="row-line"
>
<b-col md="3" xl="2">
<BCol md="3" xl="2">
<strong>{{ $t(key === 'start_on_boot' ? 'service_' + key : key) }}</strong>
</b-col>
<b-col>
</BCol>
<BCol>
<template v-if="key === 'status'">
<span :class="value === 'running' ? 'text-success' : 'text-danger'">
<icon :iname="value === 'running' ? 'check-circle' : 'times'" />
<Icon :iname="value === 'running' ? 'check-circle' : 'times'" />
{{ $t(value) }}
</span>
{{ $t('since') }} {{ uptime | distanceToNow }}
@ -45,16 +45,16 @@
</span>
<span v-else v-t="value" />
</b-col>
</b-row>
</card>
</BCol>
</BRow>
</Card>
<!-- LOGS CARD -->
<card :title="$t('logs')" icon="book" button-unbreak="sm">
<Card :title="$t('logs')" icon="book" button-unbreak="sm">
<template #header-buttons>
<b-button variant="success" @click="shareLogs">
<icon iname="cloud-upload" /> {{ $t('logs_share_with_yunopaste') }}
</b-button>
<BButton variant="success" @click="shareLogs">
<Icon iname="cloud-upload" /> {{ $t('logs_share_with_yunopaste') }}
</BButton>
</template>
<template v-for="({ filename, content }, i) in logs">
@ -64,8 +64,8 @@
<pre :key="i + '-content'" class="log"><code>{{ content }}</code></pre>
</template>
</card>
</view-base>
</Card>
</ViewBase>
</template>
<script>

View file

@ -1,5 +1,5 @@
<template>
<view-search
<ViewSearch
id="service-list"
:search.sync="search"
:items="services"
@ -8,8 +8,8 @@
:queries="queries"
@queries-response="onQueriesResponse"
>
<b-list-group>
<b-list-group-item
<BListGroup>
<BListGroupItem
v-for="{ name, description, status, last_state_change } in filteredServices" :key="name"
:to="{ name: 'service-info', params: { name }}"
class="d-flex justify-content-between align-items-center pr-0"
@ -21,17 +21,17 @@
</h5>
<p class="m-0">
<span :class="status === 'running' ? 'text-success' : 'text-danger'">
<icon :iname="status === 'running' ? 'check-circle' : 'times'" />
<Icon :iname="status === 'running' ? 'check-circle' : 'times'" />
{{ $t(status) }}
</span>
{{ $t('since') }} {{ last_state_change | distanceToNow }}
</p>
</div>
<icon iname="chevron-right" class="lg fs-sm ml-auto" />
</b-list-group-item>
</b-list-group>
</view-search>
<Icon iname="chevron-right" class="lg fs-sm ml-auto" />
</BListGroupItem>
</BListGroup>
</ViewSearch>
</template>
<script>

View file

@ -1,14 +1,14 @@
<template>
<view-base
<ViewBase
:queries="queries" @queries-response="onQueriesResponse"
ref="view" skeleton="card-form-skeleton"
ref="view" skeleton="CardFormSkeleton"
>
<!-- PORTS -->
<card :title="$t('ports')" icon="shield">
<Card :title="$t('ports')" icon="shield">
<div v-for="(items, protocol) in protocols" :key="protocol">
<h5>{{ $t(protocol) }}</h5>
<b-table
<BTable
:fields="fields" :items="items"
small striped responsive
>
@ -19,7 +19,7 @@
<!-- CONNECTIONS CELL -->
<template #cell()="data">
<b-checkbox
<BFormCheckbox
v-if="data.field.key !== 'uPnP'"
class="on-off-switch"
v-model="data.value"
@ -29,62 +29,62 @@
<span :class="'btn btn-sm py-0 btn-' + (data.value ? 'danger' : 'success')">
{{ $t(data.value ? 'close' : 'open') }}
</span>
</b-checkbox>
</BFormCheckbox>
<icon
<Icon
v-else
:iname="data.value ? 'check' : 'times'"
:class="data.value ? 'text-success' : 'text-danger'"
/>
</template>
</b-table>
</BTable>
</div>
</card>
</Card>
<!-- OPERATIONS -->
<card-form
<CardForm
:title="$t('operations')" icon="cogs"
:validation="$v" :server-error="serverError"
@submit.prevent="onFormPortToggling"
inline form-classes="d-flex justify-content-between align-items-start"
>
<b-input-group :prepend="$t('action')">
<b-select v-model="form.action" :options="actionChoices" />
</b-input-group>
<BInputGroup :prepend="$t('action')">
<BFormSelect v-model="form.action" :options="actionChoices" />
</BInputGroup>
<form-field :validation="$v.form.port">
<b-input-group :prepend="$t('port')">
<input-item
<FormField :validation="$v.form.port">
<BInputGroup :prepend="$t('port')">
<InputItem
id="input-port" placeholder="0" type="number"
v-model="form.port"
/>
</b-input-group>
</form-field>
</BInputGroup>
</FormField>
<b-input-group :prepend="$t('connection')">
<b-select v-model="form.connection" :options="connectionChoices" id="input-connection" />
</b-input-group>
<BInputGroup :prepend="$t('connection')">
<BFormSelect v-model="form.connection" :options="connectionChoices" id="input-connection" />
</BInputGroup>
<b-input-group :prepend="$t('protocol')">
<b-select v-model="form.protocol" :options="protocolChoices" id="input-protocol" />
</b-input-group>
</card-form>
<BInputGroup :prepend="$t('protocol')">
<BFormSelect v-model="form.protocol" :options="protocolChoices" id="input-protocol" />
</BInputGroup>
</CardForm>
<!-- UPnP -->
<card :title="$t('upnp')" icon="exchange" :body-text-variant="upnpEnabled ? 'success' : 'danger'">
<Card :title="$t('upnp')" icon="exchange" :body-text-variant="upnpEnabled ? 'success' : 'danger'">
{{ $t(upnpEnabled ? 'upnp_enabled' : 'upnp_disabled' ) }}
<b-form-invalid-feedback :state="upnpError !== '' ? false : null">
<BFormInvalidFeedback :state="upnpError !== '' ? false : null">
{{ upnpError }}
</b-form-invalid-feedback>
</BFormInvalidFeedback>
<template #buttons>
<b-button @click="toggleUpnp" :variant="!upnpEnabled ? 'success' : 'danger'">
<BButton @click="toggleUpnp" :variant="!upnpEnabled ? 'success' : 'danger'">
{{ $t(!upnpEnabled ? 'enable' : 'disable' ) }}
</b-button>
</BButton>
</template>
</card>
</view-base>
</Card>
</ViewBase>
</template>
<script>

View file

@ -1,16 +1,16 @@
<!-- FIXME make a component shared with Home.vue ? -->
<template>
<b-list-group class="menu-list">
<b-list-group-item
<BListGroup class="menu-list">
<BListGroupItem
v-for="item in menu"
:key="item.routeName"
:to="{name: item.routeName}"
>
<icon :iname="item.icon" class="lg ml-1" />
<Icon :iname="item.icon" class="lg ml-1" />
<h4>{{ $t(item.translation) }}</h4>
<icon iname="chevron-right" class="lg fs-sm ml-auto" />
</b-list-group-item>
</b-list-group>
<Icon iname="chevron-right" class="lg fs-sm ml-auto" />
</BListGroupItem>
</BListGroup>
</template>
<script>

View file

@ -1,64 +1,64 @@
<template>
<view-base
<ViewBase
:queries="queries" @queries-response="onQueriesResponse"
ref="view" skeleton="card-info-skeleton"
ref="view" skeleton="CardInfoSkeleton"
>
<!-- INFO CARD -->
<card :title="description" icon="info-circle">
<b-row
<Card :title="description" icon="info-circle">
<BRow
v-for="(value, prop) in info" :key="prop"
no-gutters class="row-line"
>
<b-col md="3" xl="2">
<BCol md="3" xl="2">
<strong>{{ $t('logs_' + prop) }}</strong>
</b-col>
</BCol>
<b-col>
<BCol>
<span v-if="prop.endsWith('_at')">{{ value | readableDate }}</span>
<div v-else-if="prop === 'suboperations'">
<div v-for="operation in value" :key="operation.name">
<icon v-if="operation.success !== true" iname="times" class="text-danger" />
<b-link :to="{ name: 'tool-log', params: { name: operation.name } }">
<Icon v-if="operation.success !== true" iname="times" class="text-danger" />
<BLink :to="{ name: 'tool-log', params: { name: operation.name } }">
{{ operation.description }}
</b-link>
</BLink>
</div>
</div>
<span v-else>{{ value }}</span>
</b-col>
</b-row>
</card>
</BCol>
</BRow>
</Card>
<div v-if="info.error" class="alert alert-danger my-5">
<icon iname="exclamation-circle" /> <span v-html="$t('operation_failed_explanation')" />
<Icon iname="exclamation-circle" /> <span v-html="$t('operation_failed_explanation')" />
</div>
<!-- LOGS CARD -->
<card :title="$t('logs')" icon="file-text" no-body>
<Card :title="$t('logs')" icon="file-text" no-body>
<template #header-buttons>
<b-button @click="shareLogs" variant="success">
<icon iname="cloud-upload" /> {{ $t('logs_share_with_yunopaste') }}
</b-button>
<BButton @click="shareLogs" variant="success">
<Icon iname="cloud-upload" /> {{ $t('logs_share_with_yunopaste') }}
</BButton>
</template>
<b-button
<BButton
v-if="moreLogsAvailable"
variant="white" class="w-100 rounded-0"
@click="$refs.view.fetchQueries()"
>
<icon iname="plus" /> {{ $t('logs_more') }}
</b-button>
<Icon iname="plus" /> {{ $t('logs_more') }}
</BButton>
<pre class="log unselectable"><code v-html="logs" /></pre>
<b-button @click="shareLogs" variant="success" class="w-100 rounded-0">
<icon iname="cloud-upload" /> {{ $t('logs_share_with_yunopaste') }}
</b-button>
</card>
<BButton @click="shareLogs" variant="success" class="w-100 rounded-0">
<Icon iname="cloud-upload" /> {{ $t('logs_share_with_yunopaste') }}
</BButton>
</Card>
<p class="w-100 px-5 py-2 mb-0" v-html="$t('text_selection_is_disabled')" />
</view-base>
</ViewBase>
</template>
<script>

View file

@ -1,27 +1,27 @@
<template>
<view-search
<ViewSearch
:search.sync="search"
:items="operations"
:filtered-items="filteredOperations"
items-name="logs"
:queries="queries"
@queries-response="onQueriesResponse"
skeleton="card-list-skeleton"
skeleton="CardListSkeleton"
>
<card :title="$t('logs_operation')" icon="wrench" no-body>
<b-list-group flush>
<b-list-group-item
<Card :title="$t('logs_operation')" icon="wrench" no-body>
<BListGroup flush>
<BListGroupItem
v-for="log in filteredOperations" :key="log.name"
:to="{ name: 'tool-log', params: { name: log.name || log.log_path } }"
:title="log.started_at | readableDate"
>
<small class="mr-3">{{ log.started_at | distanceToNow }} </small>
<icon :iname="log.icon" :class="'text-' + log.class" />
<Icon :iname="log.icon" :class="'text-' + log.class" />
{{ log.description }}
</b-list-group-item>
</b-list-group>
</card>
</view-search>
</BListGroupItem>
</BListGroup>
</Card>
</ViewSearch>
</template>
<script>

View file

@ -1,30 +1,30 @@
<template>
<view-base :queries="queries" @queries-response="onQueriesResponse" ref="view">
<ViewBase :queries="queries" @queries-response="onQueriesResponse" ref="view">
<!-- PENDING MIGRATIONS -->
<card :title="$t('migrations_pending')" icon="cogs" no-body>
<Card :title="$t('migrations_pending')" icon="cogs" no-body>
<template #header-buttons v-if="pending">
<b-button size="sm" variant="success" @click="runMigrations">
<icon iname="play" /> {{ $t('run') }}
</b-button>
<BButton size="sm" variant="success" @click="runMigrations">
<Icon iname="play" /> {{ $t('run') }}
</BButton>
</template>
<b-card-body v-if="pending === null">
<BCardBody v-if="pending === null">
<span class="text-success">
<icon iname="check-circle" /> {{ $t('migrations_no_pending') }}
<Icon iname="check-circle" /> {{ $t('migrations_no_pending') }}
</span>
</b-card-body>
</BCardBody>
<b-list-group v-else-if="pending" flush>
<b-list-group-item
<BListGroup v-else-if="pending" flush>
<BListGroupItem
v-for="{ number, description, id, disclaimer } in pending" :key="number"
>
<div class="d-flex align-items-center">
{{ number }}. {{ description }}
<div class="ml-auto">
<b-button @click="skipMigration(id)" size="sm" variant="warning">
<icon iname="close" /> {{ $t('skip') }}
</b-button>
<BButton @click="skipMigration(id)" size="sm" variant="warning">
<Icon iname="close" /> {{ $t('skip') }}
</BButton>
</div>
</div>
@ -32,52 +32,52 @@
<hr>
<p v-html="disclaimer" />
<b-form-checkbox
<BFormCheckbox
:id="'checkbox-' + number" :name="'checkbox-' + number"
:aria-describedby="'checkbox-feedback-' + number"
v-model="checked[id]"
>
{{ $t('migrations_disclaimer_check_message') }}
</b-form-checkbox>
</BFormCheckbox>
<b-form-invalid-feedback
<BFormInvalidFeedback
v-if="checked[id] === false" :state="false"
:id="'checkbox-feedback-' + number"
>
{{ $t('migrations_disclaimer_not_checked') }}
</b-form-invalid-feedback>
</BFormInvalidFeedback>
</template>
</b-list-group-item>
</b-list-group>
</card>
</BListGroupItem>
</BListGroup>
</Card>
<!-- DONE MIGRATIONS -->
<card
<Card
:title="$t('migrations_done')" icon="cogs"
collapsable collapsed no-body
>
<b-card-body v-if="done === null">
<BCardBody v-if="done === null">
<span class="text-success">
<icon iname="check-circle" /> {{ $t('migrations_no_done') }}
<Icon iname="check-circle" /> {{ $t('migrations_no_done') }}
</span>
</b-card-body>
</BCardBody>
<b-list-group flush v-else-if="done">
<b-list-group-item v-for="{ number, description } in done" :key="number">
<BListGroup flush v-else-if="done">
<BListGroupItem v-for="{ number, description } in done" :key="number">
{{ number }}. {{ description }}
</b-list-group-item>
</b-list-group>
</card>
</BListGroupItem>
</BListGroup>
</Card>
<template #skeleton>
<card-list-skeleton :item-count="3" />
<b-card no-body>
<CardListSkeleton :item-count="3" />
<BCard no-body>
<template #header>
<b-skeleton width="30%" height="36px" class="m-0" />
<BSkeleton width="30%" height="36px" class="m-0" />
</template>
</b-card>
</BCard>
</template>
</view-base>
</ViewBase>
</template>
<script>

View file

@ -1,26 +1,26 @@
<template>
<card :title="$t('operations')" icon="wrench">
<Card :title="$t('operations')" icon="wrench">
<!-- REBOOT -->
<b-form-group
<BFormGroup
label-cols="5" label-cols-md="4" label-cols-lg="3"
:label="$t('tools_reboot')" label-for="reboot"
>
<b-button @click="triggerAction('reboot')" variant="danger" id="reboot">
<icon iname="refresh" /> {{ $t('tools_reboot_btn') }}
</b-button>
</b-form-group>
<BButton @click="triggerAction('reboot')" variant="danger" id="reboot">
<Icon iname="refresh" /> {{ $t('tools_reboot_btn') }}
</BButton>
</BFormGroup>
<hr>
<!-- SHUTDOWN -->
<b-form-group
<BFormGroup
label-cols="5" label-cols-md="4" label-cols-lg="3"
:label="$t('tools_shutdown')" label-for="shutdown"
>
<b-button @click="triggerAction('shutdown')" variant="danger" id="shutdown">
<icon iname="power-off" /> {{ $t('tools_shutdown_btn') }}
</b-button>
</b-form-group>
</card>
<BButton @click="triggerAction('shutdown')" variant="danger" id="shutdown">
<Icon iname="power-off" /> {{ $t('tools_shutdown_btn') }}
</BButton>
</BFormGroup>
</Card>
</template>
<script>

View file

@ -1,10 +1,10 @@
<template>
<view-base
<ViewBase
:queries="queries" @queries-response="onQueriesResponse"
ref="view" skeleton="card-form-skeleton"
ref="view" skeleton="CardFormSkeleton"
>
<config-panels v-if="config.panels" v-bind="config" @submit="onConfigSubmit" />
</view-base>
<ConfigPanels v-if="config.panels" v-bind="config" @submit="onConfigSubmit" />
</ViewBase>
</template>
<script>

View file

@ -1,10 +1,10 @@
<template>
<card-form :title="$t('tools_webadmin_settings')" icon="cog" no-footer>
<CardForm :title="$t('tools_webadmin_settings')" icon="cog" no-footer>
<template v-for="(field, fname) in fields">
<form-field v-bind="field" v-model="self[fname]" :key="fname" />
<FormField v-bind="field" v-model="self[fname]" :key="fname" />
<hr :key="fname + 'hr'">
</template>
</card-form>
</CardForm>
</template>
<script>

View file

@ -1,45 +1,45 @@
<template>
<view-base
<ViewBase
:queries="queries" queries-wait @queries-response="onQueriesResponse"
skeleton="card-list-skeleton"
skeleton="CardListSkeleton"
>
<!-- MIGRATIONS WARN -->
<yuno-alert v-if="pendingMigrations" variant="warning" alert>
<YunoAlert v-if="pendingMigrations" variant="warning" alert>
<span v-html="$t('pending_migrations')" />
</yuno-alert>
</YunoAlert>
<!-- MAJOR YUNOHOST UPGRADE WARN -->
<yuno-alert v-if="importantYunohostUpgrade" variant="warning" alert>
<YunoAlert v-if="importantYunohostUpgrade" variant="warning" alert>
<span v-html="$t('important_yunohost_upgrade')" />
</yuno-alert>
</YunoAlert>
<!-- SYSTEM UPGRADE -->
<card :title="$t('system')" icon="server" no-body>
<b-list-group v-if="system" flush>
<b-list-group-item v-for="{ name, current_version, new_version } in system" :key="name">
<Card :title="$t('system')" icon="server" no-body>
<BListGroup v-if="system" flush>
<BListGroupItem v-for="{ name, current_version, new_version } in system" :key="name">
<h5 class="m-0">
{{ name }}
<small class="text-secondary">({{ $t('from_to', [current_version, new_version]) }})</small>
</h5>
</b-list-group-item>
</b-list-group>
</BListGroupItem>
</BListGroup>
<b-card-body v-else-if="system === null">
<span class="text-success"><icon iname="check-circle" /> {{ $t('system_packages_nothing') }}</span>
</b-card-body>
<BCardBody v-else-if="system === null">
<span class="text-success"><Icon iname="check-circle" /> {{ $t('system_packages_nothing') }}</span>
</BCardBody>
<template #buttons v-if="system">
<b-button
<BButton
variant="success" v-t="'system_upgrade_all_packages_btn'"
@click="performSystemUpgrade()"
/>
</template>
</card>
</Card>
<!-- APPS UPGRADE -->
<card :title="$t('applications')" icon="cubes" no-body>
<b-list-group v-if="apps" flush>
<b-list-group-item
<Card :title="$t('applications')" icon="cubes" no-body>
<BListGroup v-if="apps" flush>
<BListGroupItem
v-for="{ name, id, current_version, new_version } in apps" :key="id"
class="d-flex justify-content-between align-items-center"
>
@ -48,26 +48,26 @@
<small>({{ id }}) {{ $t('from_to', [current_version, new_version]) }}</small>
</h5>
<b-button
<BButton
variant="success" size="sm" v-t="'system_upgrade_btn'"
@click="confirmAppsUpgrade(id)"
/>
</b-list-group-item>
</b-list-group>
</BListGroupItem>
</BListGroup>
<b-card-body v-else-if="apps === null">
<span class="text-success"><icon iname="check-circle" /> {{ $t('system_apps_nothing') }}</span>
</b-card-body>
<BCardBody v-else-if="apps === null">
<span class="text-success"><Icon iname="check-circle" /> {{ $t('system_apps_nothing') }}</span>
</BCardBody>
<template #buttons v-if="apps">
<b-button
<BButton
variant="success" v-t="'system_upgrade_all_applications_btn'"
@click="confirmAppsUpgrade()"
/>
</template>
</card>
</Card>
<b-modal
<BModal
id="apps-pre-upgrade"
:title="$t('app.upgrade.confirm.title')"
header-bg-variant="warning"
@ -90,24 +90,24 @@
{{ $t('app.upgrade.notifs.pre.title') }}
</h3>
<yuno-alert variant="warning">
<YunoAlert variant="warning">
{{ $t('app.upgrade.notifs.pre.alert' ) }}
</yuno-alert>
</YunoAlert>
<div class="card-collapse-wrapper">
<card-collapse
<CardCollapse
v-for="{ id, name, notif } in preUpgrade.apps" :key="`${id}-notifs`"
:title="name" :id="`${id}-notifs`"
visible flush
>
<b-card-body>
<vue-showdown :markdown="notif" flavor="github" :options="{ headerLevelStart: 6 }" />
</b-card-body>
</card-collapse>
<BCardBody>
<VueShowdown :markdown="notif" flavor="github" :options="{ headerLevelStart: 6 }" />
</BCardBody>
</CardCollapse>
</div>
</div>
</b-modal>
</view-base>
</BModal>
</ViewBase>
</template>
<script>

View file

@ -1,43 +1,43 @@
<template>
<view-base :queries="queries" @queries-response="onQueriesResponse" skeleton="card-form-skeleton">
<card-form
<ViewBase :queries="queries" @queries-response="onQueriesResponse" skeleton="CardFormSkeleton">
<CardForm
:title="$t('users_new')" icon="user-plus"
:validation="$v" :server-error="serverError"
@submit.prevent="onSubmit"
>
<!-- USER NAME -->
<form-field v-bind="fields.username" v-model="form.username" :validation="$v.form.username" />
<FormField v-bind="fields.username" v-model="form.username" :validation="$v.form.username" />
<!-- USER FULLNAME -->
<form-field v-bind="fields.fullname" :validation="$v.form.fullname" v-model="form.fullname" />
<FormField v-bind="fields.fullname" :validation="$v.form.fullname" v-model="form.fullname" />
<hr>
<!-- USER MAIL DOMAIN -->
<form-field v-bind="fields.domain" :validation="$v.form.domain">
<FormField v-bind="fields.domain" :validation="$v.form.domain">
<template #default="{ self }">
<b-input-group>
<b-input-group-append>
<b-input-group-text id="local-part" tag="label" class="border-right-0">
<BInputGroup>
<BInputGroupAppend>
<BInputGroupText id="local-part" tag="label" class="border-right-0">
{{ form.username }}@
</b-input-group-text>
</b-input-group-append>
</BInputGroupText>
</BInputGroupAppend>
<select-item
<SelectItem
aria-labelledby="local-part" aria-describedby="mail__BV_description_"
v-model="form.domain" v-bind="self"
/>
</b-input-group>
</BInputGroup>
</template>
</form-field>
</FormField>
<hr>
<!-- USER PASSWORD -->
<form-field v-bind="fields.password" v-model="form.password" :validation="$v.form.password" />
<FormField v-bind="fields.password" v-model="form.password" :validation="$v.form.password" />
<!-- USER PASSWORD CONFIRMATION -->
<form-field v-bind="fields.confirmation" v-model="form.confirmation" :validation="$v.form.confirmation" />
</card-form>
</view-base>
<FormField v-bind="fields.confirmation" v-model="form.confirmation" :validation="$v.form.confirmation" />
</CardForm>
</ViewBase>
</template>
<script>

View file

@ -1,93 +1,93 @@
<template>
<view-base :queries="queries" @queries-response="onQueriesResponse" skeleton="card-form-skeleton">
<card-form
<ViewBase :queries="queries" @queries-response="onQueriesResponse" skeleton="CardFormSkeleton">
<CardForm
:title="$t('user_username_edit', { name })" icon="user"
:validation="$v" :server-error="serverError"
@submit.prevent="onSubmit"
>
<!-- USERNAME (disabled) -->
<form-field v-bind="fields.username" />
<FormField v-bind="fields.username" />
<!-- USER FULLNAME -->
<form-field v-bind="fields.fullname" v-model="form.fullname" :validation="$v.form.fullname" />
<FormField v-bind="fields.fullname" v-model="form.fullname" :validation="$v.form.fullname" />
<hr>
<!-- USER EMAIL -->
<form-field v-bind="fields.mail" :validation="$v.form.mail">
<FormField v-bind="fields.mail" :validation="$v.form.mail">
<template #default="{ self }">
<adress-input-select v-bind="self" v-model="form.mail" />
<AdressInputSelect v-bind="self" v-model="form.mail" />
</template>
</form-field>
</FormField>
<!-- MAILBOX QUOTA -->
<form-field v-bind="fields.mailbox_quota" :validation="$v.form.mailbox_quota">
<FormField v-bind="fields.mailbox_quota" :validation="$v.form.mailbox_quota">
<template #default="{ self }">
<b-input-group append="M">
<input-item v-bind="self" v-model="form.mailbox_quota" />
</b-input-group>
<BInputGroup append="M">
<InputItem v-bind="self" v-model="form.mailbox_quota" />
</BInputGroup>
</template>
</form-field>
</FormField>
<hr>
<!-- MAIL ALIASES -->
<form-field :label="$t('user_emailaliases')" id="mail-aliases">
<FormField :label="$t('user_emailaliases')" id="mail-aliases">
<div
v-for="(mail, i) in form.mail_aliases" :key="i"
class="mail-list"
>
<form-field
<FormField
v-bind="fields.mail_aliases"
:id="'mail_aliases' + i"
:validation="$v.form.mail_aliases.$each[i]"
>
<template #default="{ self }">
<adress-input-select v-bind="self" v-model="form.mail_aliases[i]" />
<AdressInputSelect v-bind="self" v-model="form.mail_aliases[i]" />
</template>
</form-field>
</FormField>
<b-button variant="danger" @click="removeEmailField('aliases', i)">
<icon :title="$t('delete')" iname="trash-o" />
<BButton variant="danger" @click="removeEmailField('aliases', i)">
<Icon :title="$t('delete')" iname="trash-o" />
<span class="sr-only">{{ $t('delete') }}</span>
</b-button>
</BButton>
</div>
<b-button variant="success" @click="addEmailField('aliases')">
<icon iname="plus" /> {{ $t('user_emailaliases_add') }}
</b-button>
</form-field>
<BButton variant="success" @click="addEmailField('aliases')">
<Icon iname="plus" /> {{ $t('user_emailaliases_add') }}
</BButton>
</FormField>
<!-- MAIL FORWARD -->
<form-field :label="$t('user_emailforward')" id="mail-forward">
<FormField :label="$t('user_emailforward')" id="mail-forward">
<div
v-for="(mail, i) in form.mail_forward" :key="i"
class="mail-list"
>
<form-field
<FormField
v-bind="fields.mail_forward" v-model="form.mail_forward[i]"
:id="'mail-forward' + i"
:validation="$v.form.mail_forward.$each[i]"
/>
<b-button variant="danger" @click="removeEmailField('forward', i)">
<icon :title="$t('delete')" iname="trash-o" />
<BButton variant="danger" @click="removeEmailField('forward', i)">
<Icon :title="$t('delete')" iname="trash-o" />
<span class="sr-only">{{ $t('delete') }}</span>
</b-button>
</BButton>
</div>
<b-button variant="success" @click="addEmailField('forward')">
<icon iname="plus" /> {{ $t('user_emailforward_add') }}
</b-button>
</form-field>
<BButton variant="success" @click="addEmailField('forward')">
<Icon iname="plus" /> {{ $t('user_emailforward_add') }}
</BButton>
</FormField>
<hr>
<!-- USER PASSWORD -->
<form-field v-bind="fields.change_password" v-model="form.change_password" :validation="$v.form.change_password" />
<FormField v-bind="fields.change_password" v-model="form.change_password" :validation="$v.form.change_password" />
<!-- USER PASSWORD CONFIRMATION -->
<form-field v-bind="fields.confirmation" v-model="form.confirmation" :validation="$v.form.confirmation" />
</card-form>
</view-base>
<FormField v-bind="fields.confirmation" v-model="form.confirmation" :validation="$v.form.confirmation" />
</CardForm>
</ViewBase>
</template>
<script>

View file

@ -1,18 +1,18 @@
<template>
<card-form
<CardForm
:title="$t('users_import')" icon="user-plus"
:validation="$v" :server-error="serverError"
@submit.prevent="onSubmit"
>
<!-- CSV FILE -->
<form-field v-bind="fields.csvfile" v-model="form.csvfile" :validation="$v.form.csvfile" />
<FormField v-bind="fields.csvfile" v-model="form.csvfile" :validation="$v.form.csvfile" />
<!-- UPDATE -->
<form-field v-bind="fields.update" v-model="form.update" />
<FormField v-bind="fields.update" v-model="form.update" />
<!-- DELETE -->
<form-field v-bind="fields.delete" v-model="form.delete" />
</card-form>
<FormField v-bind="fields.delete" v-model="form.delete" />
</CardForm>
</template>
<script>

View file

@ -1,36 +1,36 @@
<template>
<view-base :queries="queries" skeleton="card-info-skeleton">
<card v-if="user" :title="user.fullname" icon="user">
<ViewBase :queries="queries" skeleton="CardInfoSkeleton">
<Card v-if="user" :title="user.fullname" icon="user">
<div class="d-flex align-items-center flex-column flex-md-row">
<icon iname="user" class="fa-fw" />
<Icon iname="user" class="fa-fw" />
<div class="w-100">
<b-row>
<b-col><strong>{{ $t('user_username') }}</strong></b-col>
<b-col>{{ user.username }}</b-col>
</b-row>
<BRow>
<BCol><strong>{{ $t('user_username') }}</strong></BCol>
<BCol>{{ user.username }}</BCol>
</BRow>
<b-row>
<b-col><strong>{{ $t('user_email') }}</strong></b-col>
<b-col class="font-italic">
<BRow>
<BCol><strong>{{ $t('user_email') }}</strong></BCol>
<BCol class="font-italic">
{{ user.mail }}
</b-col>
</b-row>
</BCol>
</BRow>
<b-row>
<b-col><strong>{{ $t('user_mailbox_quota') }}</strong></b-col>
<b-col>{{ user['mailbox-quota'].limit }}</b-col>
</b-row>
<BRow>
<BCol><strong>{{ $t('user_mailbox_quota') }}</strong></BCol>
<BCol>{{ user['mailbox-quota'].limit }}</BCol>
</BRow>
<b-row>
<b-col><strong>{{ $t('user_mailbox_use') }}</strong></b-col>
<b-col>{{ user['mailbox-quota'].use }}</b-col>
</b-row>
<BRow>
<BCol><strong>{{ $t('user_mailbox_use') }}</strong></BCol>
<BCol>{{ user['mailbox-quota'].use }}</BCol>
</BRow>
<b-row v-for="(trad, mailType) in {'mail-aliases': 'user_emailaliases', 'mail-forward': 'user_emailforward'}" :key="mailType">
<b-col><strong>{{ $t(trad) }}</strong></b-col>
<BRow v-for="(trad, mailType) in {'mail-aliases': 'user_emailaliases', 'mail-forward': 'user_emailforward'}" :key="mailType">
<BCol><strong>{{ $t(trad) }}</strong></BCol>
<b-col v-if="user[mailType]">
<BCol v-if="user[mailType]">
<ul v-if="user[mailType].length > 1">
<li v-for="(alias, index) in user[mailType]" :key="index">
{{ alias }}
@ -40,42 +40,42 @@
<template v-else-if="user[mailType][0]">
{{ user[mailType][0] }}
</template>
</b-col>
</b-row>
</BCol>
</BRow>
</div>
</div>
<template #buttons>
<b-button :to="{ name: 'user-edit', params: { user } }" :variant="user ? 'info' : 'dark'">
<icon iname="edit" />
<BButton :to="{ name: 'user-edit', params: { user } }" :variant="user ? 'info' : 'dark'">
<Icon iname="edit" />
{{ user ? $t('user_username_edit', {name: user.username}) : '' }}
</b-button>
</BButton>
<b-button v-b-modal.delete-modal :variant="user ? 'danger' : 'dark'">
<icon iname="trash-o" />
<BButton v-b-modal.delete-modal :variant="user ? 'danger' : 'dark'">
<Icon iname="trash-o" />
{{ user ? $t('delete') : '' }}
</b-button>
</BButton>
</template>
</card>
</Card>
<b-modal
<BModal
v-if="user"
id="delete-modal" :title="$t('confirm_delete', { name: user.username })" @ok="deleteUser"
header-bg-variant="warning" body-class="" body-bg-variant=""
>
<b-form-group>
<b-form-checkbox v-model="purge">
<BFormGroup>
<BFormCheckbox v-model="purge">
{{ $t('purge_user_data_checkbox', { name: user.username }) }}
</b-form-checkbox>
</BFormCheckbox>
<template #description>
<div class="alert alert-warning">
<icon iname="exclamation-triangle" /> {{ $t('purge_user_data_warning') }}
<Icon iname="exclamation-triangle" /> {{ $t('purge_user_data_warning') }}
</div>
</template>
</b-form-group>
</b-modal>
</view-base>
</BFormGroup>
</BModal>
</ViewBase>
</template>
<script>

View file

@ -1,5 +1,5 @@
<template>
<view-search
<ViewSearch
:search.sync="search"
:items="users"
:filtered-items="filteredUsers"
@ -7,29 +7,29 @@
:queries="queries"
>
<template #top-bar-buttons>
<b-button variant="info" :to="{ name: 'group-list' }">
<icon iname="key-modern" /> {{ $t('groups_and_permissions_manage') }}
</b-button>
<BButton variant="info" :to="{ name: 'group-list' }">
<Icon iname="key-modern" /> {{ $t('groups_and_permissions_manage') }}
</BButton>
<b-dropdown
<BDropdown
:split-to="{ name: 'user-create' }"
split variant="outline-success" right
split-variant="success"
>
<template #button-content>
<icon iname="plus" /> {{ $t('users_new') }}
<Icon iname="plus" /> {{ $t('users_new') }}
</template>
<b-dropdown-item :to="{ name: 'user-import' }">
<icon iname="plus" /> {{ $t('users_import') }}
</b-dropdown-item>
<b-dropdown-item @click="downloadExport">
<icon iname="download" /> {{ $t('users_export') }}
</b-dropdown-item>
</b-dropdown>
<BDropdownItem :to="{ name: 'user-import' }">
<Icon iname="plus" /> {{ $t('users_import') }}
</BDropdownItem>
<BDropdownItem @click="downloadExport">
<Icon iname="download" /> {{ $t('users_export') }}
</BDropdownItem>
</BDropdown>
</template>
<b-list-group>
<b-list-group-item
<BListGroup>
<BListGroupItem
v-for="user in filteredUsers" :key="user.username"
:to="{ name: 'user-info', params: { name: user.username }}"
class="d-flex justify-content-between align-items-center pr-0"
@ -43,10 +43,10 @@
{{ user.mail }}
</p>
</div>
<icon iname="chevron-right" class="lg fs-sm ml-auto" />
</b-list-group-item>
</b-list-group>
</view-search>
<Icon iname="chevron-right" class="lg fs-sm ml-auto" />
</BListGroupItem>
</BListGroup>
</ViewSearch>
</template>
<script>