ui: Refactor ZoneList component

This commit is contained in:
nemunaire 2021-10-20 17:56:40 +02:00
parent 918ae2c4d5
commit 2748d20098
5 changed files with 216 additions and 48 deletions

View File

@ -32,28 +32,34 @@
-->
<template>
<b-list-group>
<b-list-group-item v-if="isLoading" class="d-flex justify-content-center align-items-center">
<b-spinner variant="primary" :label="$t('common.spinning')" class="mr-3" /> <i18n :path="loadingStr" />
</b-list-group-item>
<div>
<div v-if="isLoading" class="d-flex justify-content-center align-items-center">
<b-spinner variant="primary" :label="$t('common.spinning')" class="my-2 mr-3" /> <i18n :path="loadingStr" />
</div>
<slot v-else-if="domains.length === 0" name="no-domain" />
<b-list-group-item
v-for="(domain, index) in domains"
v-else
:key="index"
:button="button"
class="d-flex justify-content-between align-items-center"
@click="$emit('click', domain)"
>
<div class="text-monospace">
<div class="d-inline-block text-center" style="width: 50px;">
<img v-if="providers_getAll[domain.id_provider]" :src="'/api/providers/_specs/' + providers_getAll[domain.id_provider]._srctype + '/icon.png'" :alt="providers_getAll[domain.id_provider]._srctype" :title="providers_getAll[domain.id_provider]._srctype" style="max-width: 100%; max-height: 2.5em; margin: -.6em .4em -.6em -.6em">
</div>
{{ domain.domain }}
<div v-else v-for="(domains, group) in groups" :key="group" :class="Object.keys(groups).length != 1?'border-top':''">
<div v-if="Object.keys(groups).length != 1" class="text-center" style="height: 1em">
<h3 class="d-inline-block px-1" style="background: white; position: relative; top: -.65em">{{ group }}</h3>
</div>
<slot name="badges" :domain="domain" />
</b-list-group-item>
</b-list-group>
<h-list
:items="domains"
:button="button"
@click="$emit('click', $event)"
>
<template #default="{ item }">
<div class="text-monospace">
<div class="d-inline-block text-center" style="width: 50px;">
<img v-if="providers_getAll[item.id_provider]" :src="'/api/providers/_specs/' + providers_getAll[item.id_provider]._srctype + '/icon.png'" :alt="providers_getAll[item.id_provider]._srctype" :title="providers_getAll[item.id_provider]._srctype" style="max-width: 100%; max-height: 2.5em; margin: -.6em .4em -.6em -.6em">
</div>
{{ item.domain }}
</div>
</template>
<template #badges="{ item }">
<slot name="badges" :domain="item" />
</template>
</h-list>
</div>
</div>
</template>
<script>
@ -62,11 +68,19 @@ import { mapGetters } from 'vuex'
export default {
name: 'ZoneList',
components: {
hList: () => import('@/components/hList')
},
props: {
button: {
type: Boolean,
default: false
},
displayByGroups: {
type: Boolean,
default: false
},
domains: {
type: Array,
default: null
@ -82,6 +96,24 @@ export default {
},
computed: {
groups () {
if (!this.displayByGroups) {
return { null: this.domains }
}
const groups = { }
this.domains.forEach((domain, index) => {
if (groups[domain.group] === undefined) {
groups[domain.group] = []
}
groups[domain.group].push(domain)
})
return groups
},
isLoading () {
return this.parentIsLoading || this.domains == null || this.providers_getAll == null
},

View File

@ -0,0 +1,80 @@
<!--
Copyright or © or Copr. happyDNS (2021)
contact@happydns.org
This software is a computer program whose purpose is to provide a modern
interface to interact with DNS systems.
This software is governed by the CeCILL license under French law and abiding
by the rules of distribution of free software. You can use, modify and/or
redistribute the software under the terms of the CeCILL license as
circulated by CEA, CNRS and INRIA at the following URL
"http://www.cecill.info".
As a counterpart to the access to the source code and rights to copy, modify
and redistribute granted by the license, users are provided only with a
limited warranty and the software's author, the holder of the economic
rights, and the successive licensors have only limited liability.
In this respect, the user's attention is drawn to the risks associated with
loading, using, modifying and/or developing or reproducing the software by
the user in light of its specific status of free software, that may mean
that it is complicated to manipulate, and that also therefore means that it
is reserved for developers and experienced professionals having in-depth
computer knowledge. Users are therefore encouraged to load and test the
software's suitability as regards their requirements in conditions enabling
the security of their systems and/or data to be ensured and, more generally,
to use and operate it in the same conditions as regards security.
The fact that you are presently reading this means that you have had
knowledge of the CeCILL license and that you accept its terms.
-->
<template>
<b-list-group>
<b-list-group-item v-if="isLoading" class="d-flex justify-content-center align-items-center">
<slot name="loading" />
</b-list-group-item>
<b-list-group-item v-if="!isLoading && items.length == 0" class="text-center">
<slot name="empty" />
</b-list-group-item>
<b-list-group-item
v-else
v-for="(item, index) in items"
:key="index"
:active="isActive(item)"
:button="button"
class="d-flex justify-content-between align-items-center"
@click="$emit('click', item)"
>
<slot name="default" :item="item" />
<slot name="badges" :item="item" />
</b-list-group-item>
</b-list-group>
</template>
<script>
export default {
name: 'hList',
props: {
button: {
type: Boolean,
default: false
},
isLoading: {
type: Boolean,
default: false
},
isActive: {
type: Function,
default: () => false
},
items: {
type: Array,
default: null
}
}
}
</script>

View File

@ -32,7 +32,11 @@
-->
<template>
<h-zone-list :domains="listImportableDomains" loading-str="wait.asking-domains" :parent-is-loading="isLoading">
<h-zone-list
:domains="listImportableDomains"
loading-str="wait.asking-domains"
:parent-is-loading="isLoading"
>
<template #badges="{ domain }">
<b-badge v-if="domain.state" class="ml-1" :variant="domain.state">
<b-icon v-if="domain.state === 'success'" icon="check" />

View File

@ -32,46 +32,53 @@
-->
<template>
<b-list-group>
<b-list-group-item v-if="isLoading" class="d-flex justify-content-center align-items-center">
<h-list
button
:is-active="(provider) => mySelectedProvider && mySelectedProvider._id === provider._id"
:is-loading="isLoading"
:items="sortedProviders"
@click="selectProvider($event)"
>
<template #loading>
<b-spinner variant="primary" label="Spinning" class="mr-3" /> Retrieving your providers...
</b-list-group-item>
<b-list-group-item v-if="!isLoading && providers_getAll.length == 0" class="text-center">
</template>
<template #empty>
You have no provider defined currently. Try <a href="#" @click.prevent="$emit('new-provider')">adding one</a>!
</b-list-group-item>
<b-list-group-item v-for="(provider, index) in sortedProviders" :key="index" :active="mySelectedProvider && mySelectedProvider._id === provider._id" button class="d-flex justify-content-between align-items-center" @click="selectProvider(provider)">
</template>
<template #default="{ item }">
<div class="d-flex">
<div class="text-center" style="width: 50px;">
<img v-if="providerSpecs_getAll && providerSpecs_getAll[provider._srctype]" :src="'/api/providers/_specs/' + provider._srctype + '/icon.png'" :alt="providerSpecs_getAll[provider._srctype].name" :title="providerSpecs_getAll[provider._srctype].name" style="max-width: 100%; max-height: 2.5em; margin: -.6em .4em -.6em -.6em">
<img v-if="providerSpecs_getAll && providerSpecs_getAll[item._srctype]" :src="'/api/providers/_specs/' + item._srctype + '/icon.png'" :alt="providerSpecs_getAll[item._srctype].name" :title="providerSpecs_getAll[item._srctype].name" style="max-width: 100%; max-height: 2.5em; margin: -.6em .4em -.6em -.6em">
</div>
<div v-if="provider._comment" style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
{{ provider._comment }}
<div v-if="item._comment" style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
{{ item._comment }}
</div>
<em v-else>No name</em>
</div>
<div v-if="!(noLabel && noDropdown)" class="d-flex">
<div v-if="!noLabel">
<b-badge class="ml-1" :variant="domain_in_providers[provider._id] > 0 ? 'success' : 'danger'">
{{ domain_in_providers[provider._id] }} domain(s) associated
<b-badge class="ml-1" :variant="domain_in_providers[item._id] > 0 ? 'success' : 'danger'">
{{ domain_in_providers[item._id] }} domain(s) associated
</b-badge>
<b-badge v-if="providerSpecs_getAll && providerSpecs_getAll[provider._srctype]" class="ml-1" variant="secondary" :title="provider._srctype">
{{ providerSpecs_getAll[provider._srctype].name }}
<b-badge v-if="providerSpecs_getAll && providerSpecs_getAll[item._srctype]" class="ml-1" variant="secondary" :title="item._srctype">
{{ providerSpecs_getAll[item._srctype].name }}
</b-badge>
</div>
<b-dropdown v-if="!noDropdown" no-caret size="sm" style="margin-right: -10px" variant="link">
<template #button-content>
<b-icon icon="three-dots" />
</template>
<b-dropdown-item @click="updateProvider($event, provider)">
<b-dropdown-item @click="updateProvider($event, item)">
{{ $t('provider.update') }}
</b-dropdown-item>
<b-dropdown-item @click="deleteProvider($event, provider)">
<b-dropdown-item @click="deleteProvider($event, item)">
{{ $t('provider.delete') }}
</b-dropdown-item>
</b-dropdown>
</div>
</b-list-group-item>
</b-list-group>
</template>
</h-list>
</template>
<script>
@ -82,6 +89,10 @@ import ProviderApi from '@/api/providers'
export default {
name: 'ProviderList',
components: {
hList: () => import('@/components/hList')
},
props: {
emitNewIfEmpty: {
type: Boolean,

View File

@ -36,41 +36,81 @@
<i18n path="common.welcome" tag="h1" class="text-center mb-4">
<h-logo height="40" />
</i18n>
<b-row>
<b-col md="8">
<h-zone-list ref="zlist" button :domains="filteredDomains" @click="showDomain($event)">
<b-col md="8" class="order-1 order-md-0">
<h-zone-list
ref="zlist"
button
:domains="filteredDomains"
@click="showDomain($event)"
>
<template #badges>
<b-badge variant="success">
OK
</b-badge>
</template>
</h-zone-list>
<b-card v-if="filteredProvider && $refs.zlist && !$refs.zlist.isLoading" no-body :class="filteredDomains.length > 0 ? 'mt-4' : ''">
<b-card
v-if="filteredProvider && $refs.zlist && !$refs.zlist.isLoading"
no-body
:class="filteredDomains.length > 0 ? 'mt-4' : ''"
>
<template v-if="!noDomainsList" slot="header">
<div class="d-flex justify-content-between">
<i18n path="provider.provider">
<em>{{ filteredProvider._comment }}</em>
</i18n>
<b-button v-if="$refs.newDomains && $refs.newDomains.listImportableDomains.length > 0" type="button" variant="secondary" size="sm" @click="$refs.newDomains.importAllDomains()">
<b-button
v-if="$refs.newDomains && $refs.newDomains.listImportableDomains.length > 0"
type="button"
variant="secondary"
size="sm"
@click="$refs.newDomains.importAllDomains()"
>
{{ $t('provider.import-domains') }}
</b-button>
</div>
</template>
<h-provider-list-domains ref="newDomains" :provider="filteredProvider" show-domains-with-actions @no-domains-list-change="noDomainsList = $event" />
<h-provider-list-domains
ref="newDomains"
:provider="filteredProvider"
show-domains-with-actions
@no-domains-list-change="noDomainsList = $event"
/>
</b-card>
<h-list-group-input-new-domain v-if="$refs.zlist && !$refs.zlist.isLoading && (!filteredProvider || noDomainsList)" autofocus class="mt-2" :my-provider="filteredProvider" />
<h-list-group-input-new-domain
v-if="$refs.zlist && !$refs.zlist.isLoading && (!filteredProvider || noDomainsList)"
autofocus
class="mt-2"
:my-provider="filteredProvider"
/>
</b-col>
<b-col md="4">
<b-card no-body class="mt-3 mt-md-0">
<b-col md="4" class="order-0 order-md-1">
<b-card
no-body
class="mb-3"
>
<template slot="header">
<div class="d-flex justify-content-between">
<i18n path="provider.title" />
<b-button size="sm" variant="light" @click="newProvider">
<b-button
size="sm"
variant="light"
@click="newProvider"
>
<b-icon icon="plus" />
</b-button>
</div>
</template>
<h-provider-list ref="providerList" no-label flush :selected-provider="filteredProvider" @provider-selected="filteredProvider = $event" />
<h-provider-list
ref="providerList"
no-label
flush
:selected-provider="filteredProvider"
@provider-selected="filteredProvider = $event"
/>
</b-card>
</b-col>
</b-row>
@ -92,6 +132,7 @@ export default {
data: function () {
return {
noDomainsList: true,
filteredGroup: null,
filteredProvider: null
}
},