Propagate services values through components

This commit is contained in:
nemunaire 2020-06-11 00:09:33 +02:00
parent d41a073fc3
commit 23311495ce
14 changed files with 240 additions and 66 deletions

View File

@ -50,7 +50,7 @@
</template>
<script>
import ServicesApi from '@/services/ServicesApi'
import ServiceSpecsApi from '@/services/ServiceSpecsApi'
export default {
name: 'HDomainService',
@ -60,9 +60,17 @@ export default {
},
props: {
origin: {
type: String,
required: true
},
service: {
type: Object,
required: true
},
zoneMeta: {
type: Object,
required: true
}
},
@ -80,7 +88,7 @@ export default {
},
created () {
ServicesApi.getServices()
ServiceSpecsApi.getServiceSpecs()
.then(
(response) => (this.services = response.data)
)

View File

@ -32,7 +32,7 @@
-->
<template>
<component :is="itemComponent" v-model="value" :edit="edit" :edit-toolbar="editToolbar" :index="index" :services="services" :specs="specs" :type="type" />
<component :is="itemComponent" :value="value" @input="$emit('input', $event)" :edit="edit" :edit-toolbar="editToolbar" :index="index" :services="services" :specs="specs" :type="type" @saveService="$emit('saveService')" />
</template>
<script>

View File

@ -38,7 +38,7 @@
<label v-if="specs.label" :for="'spec-' + index" :title="specs.label" class="col-md-4 col-form-label text-truncate text-md-right text-primary">{{ specs.label }}</label>
<label v-else :for="'spec-' + index" :title="specs.label" class="col-md-4 col-form-label text-truncate text-md-right text-primary">{{ specs.id }}</label>
<b-col md="8">
<h-resource-value-input-raw v-model="value" :edit="edit" :index="index" :specs="specs" />
<h-resource-value-input-raw v-model="val" :edit="edit" :index="index" :specs="specs" />
<p v-if="specs.description" class="text-justify" style="line-height: 1.1">
<small class="text-muted">{{ specs.description }}</small>
</p>
@ -71,6 +71,17 @@ export default {
value: {
required: true
}
},
computed: {
val: {
get () {
return this.value
},
set (val) {
this.$emit('input', val)
}
}
}
}
</script>

View File

@ -33,36 +33,50 @@
<template>
<div ng-if="!isLoading()">
<div class="text-right">
<b-button v-if="!edit" type="button" size="sm" variant="outline-primary" class="mx-1" @click="toogleServiceEdit()">
<b-icon icon="pencil" />
Edit
</b-button>
<b-button v-else type="button" size="sm" variant="primary" class="mx-1" @click="submitService(index, idx)">
<b-icon icon="check" />
Save those modifications
</b-button>
<b-button type="button" size="sm" variant="outline-danger" class="mx-1">
<b-icon icon="trash" />
Delete
</b-button>
</div>
<div v-for="(val,key) in value" :key="key">
<h3>{{ key }}</h3>
<b-row>
<b-col>
<h3>
<span v-if="!editKeys[key]">{{ key }}</span>
<b-input-group v-else>
<b-form-input v-model="newKeys[key]" />
<template v-slot:append>
<b-button v-if="editKeys[key]" type="button" size="sm" variant="primary" @click="rename(key)">
<b-icon icon="check" />
Rename
</b-button>
</template>
</b-input-group>
<b-button v-if="!editKeys[key]" type="button" size="sm" variant="link" @click="toogleKeyEdit(key)">
<b-icon icon="pencil" />
</b-button>
</h3>
</b-col>
<b-col sm="auto">
<b-button type="button" size="sm" variant="outline-danger" class="mx-1 float-right">
<b-icon icon="trash" />
Delete
</b-button>
</b-col>
</b-row>
<h-resource-value
v-model="value[key]"
:edit="edit"
:services="services"
:specs="service_specs"
:type="main_type"
@saveService="$emit('saveService')"
/>
<hr>
</div>
<b-button>
Add new {{ specs.id }}
</b-button>
</div>
</template>
<script>
import ServicesApi from '@/services/ServicesApi'
import ServiceSpecsApi from '@/services/ServiceSpecsApi'
import Vue from 'vue'
export default {
name: 'HResourceValueMap',
@ -72,10 +86,6 @@ export default {
},
props: {
edit: {
type: Boolean,
default: false
},
services: {
type: Object,
required: true
@ -96,6 +106,8 @@ export default {
data: function () {
return {
editKeys: {},
newKeys: {},
key_type: '',
main_type: '',
service_specs: null
@ -136,7 +148,7 @@ export default {
methods: {
pullServiceSpecs () {
ServicesApi.getServiceSpecs(this.main_type)
ServiceSpecsApi.getServiceSpecs(this.main_type)
.then(
(response) => {
this.service_specs = response.data
@ -144,8 +156,17 @@ export default {
)
},
toogleServiceEdit () {
this.edit = !this.edit
rename (key) {
if (key !== this.newKeys[key]) {
Vue.set(this.value, this.newKeys[key], this.value[key])
Vue.delete(this.value, key)
}
Vue.delete(this.editKeys, key)
},
toogleKeyEdit (key) {
Vue.set(this.newKeys, key, key)
Vue.set(this.editKeys, key, !this.editKeys[key])
}
}
}

View File

@ -52,6 +52,7 @@
:services="services"
:specs="spec"
:type="spec.type"
@saveService="$emit('saveService')"
/>
<b-button v-else>
Create {{ spec.id }}
@ -64,7 +65,7 @@
<b-icon icon="pencil" />
Edit
</b-button>
<b-button v-else type="button" size="sm" variant="primary" class="mx-1" @click="submitService(index, idx)">
<b-button v-else type="button" size="sm" variant="primary" class="mx-1" @click="$emit('saveService')">
<b-icon icon="check" />
Save those modifications
</b-button>
@ -81,13 +82,14 @@
:services="services"
:specs="spec"
:type="spec.type"
@saveService="$emit('saveService')"
/>
</div>
</div>
</template>
<script>
import ServicesApi from '@/services/ServicesApi'
import ServiceSpecsApi from '@/services/ServiceSpecsApi'
export default {
name: 'HResourceValueObject',
@ -150,7 +152,7 @@ export default {
methods: {
pullServiceSpecs () {
ServicesApi.getServiceSpecs(this.type)
ServiceSpecsApi.getServiceSpecs(this.type)
.then(
(response) => {
this.service_specs = response.data

View File

@ -40,14 +40,14 @@
</b-button>
</template>
<template v-slot:cell()="row">
<h-resource-value v-if="service_specs.fields" v-model="row.item[row.field.key]" :edit="edit_row.indexOf(row.index) >= 0" :index="row.index" :services="services" :specs="service_specs.fields[row.field.index]" :type="service_specs.fields[row.field.index].type" no-decorate />
<h-resource-value v-else v-model="row.item" :edit="edit_row.indexOf(row.index) >= 0" :index="row.index" :services="services" :specs="specs" :type="row_type" no-decorate />
<h-resource-value v-if="service_specs.fields" v-model="row.item[row.field.key]" :edit="edit_row.indexOf(row.index) >= 0" :index="row.index" :services="services" :specs="service_specs.fields[row.field.index]" :type="service_specs.fields[row.field.index].type" no-decorate @saveService="$emit('saveService')" />
<h-resource-value v-else v-model="row.item" :edit="edit_row.indexOf(row.index) >= 0" :index="row.index" :services="services" :specs="specs" :type="row_type" no-decorate @saveService="$emit('saveService')" />
</template>
<template v-slot:cell(_actions)="row">
<b-button v-if="edit_row.indexOf(row.index) < 0" size="sm" title="Edit" variant="outline-primary" class="mx-1" @click="editService(row)">
<b-icon icon="pencil" />
</b-button>
<b-button v-else type="button" title="Save the modifications" size="sm" variant="primary" class="mx-1" @click="submitService(row.item)">
<b-button v-else type="button" title="Save the modifications" size="sm" variant="primary" class="mx-1" @click="$emit('saveService')">
<b-icon icon="check" />
</b-button>
<b-button type="button" title="Delete" size="sm" variant="outline-danger" class="mx-1" @click="deleteService(row.item)">
@ -59,7 +59,7 @@
</template>
<script>
import ServicesApi from '@/services/ServicesApi'
import ServiceSpecsApi from '@/services/ServiceSpecsApi'
export default {
name: 'HResourceValueTable',
@ -147,7 +147,7 @@ export default {
if (this.row_type === 'string') {
this.service_specs = {}
} else {
ServicesApi.getServiceSpecs(this.row_type)
ServiceSpecsApi.getServiceSpecs(this.row_type)
.then(
(response) => {
this.service_specs = response.data

View File

@ -69,7 +69,7 @@
</b-button>
</h2>
<div v-show="showResources">
<h-domain-service v-for="(svc, idx) in services" :key="idx" :service="svc" />
<h-domain-service v-for="(svc, idx) in services" :key="idx" :origin="origin" :service="svc" :zone-meta="zoneMeta" />
</div>
</div>
</div>
@ -92,9 +92,17 @@ export default {
type: String,
required: true
},
origin: {
type: String,
required: true
},
services: {
type: Array,
required: true
},
zoneMeta: {
type: Object,
required: true
}
},

View File

@ -33,12 +33,12 @@
<template>
<div v-if="!isLoading" class="pt-3">
<h-subdomain-item v-for="(dn, index) in sortedDomains" :key="index" :dn="dn" :services="myServices.services[dn]===undefined?[]:myServices.services[dn]" :aliases="myServices.aliases[dn]===undefined?[]:myServices.aliases[dn]" />
<h-subdomain-item v-for="(dn, index) in sortedDomains" :key="index" :dn="dn" :origin="domain.domain" :services="myServices.services[dn]===undefined?[]:myServices.services[dn]" :aliases="myServices.aliases[dn]===undefined?[]:myServices.aliases[dn]" :zone-meta="zoneMeta" />
</div>
</template>
<script>
import axios from 'axios'
import ZoneApi from '@/services/ZoneApi'
export default {
name: 'HSubdomainList',
@ -67,7 +67,7 @@ export default {
computed: {
isLoading () {
return this.myServices == null
return this.myServices == null && this.zoneMeta === undefined
},
sortedDomains () {
@ -105,9 +105,7 @@ export default {
},
created () {
if (this.domain !== undefined && this.domain.domain !== undefined && this.zoneMeta !== undefined) {
this.pullZone()
}
this.pullZone()
},
methods: {
@ -121,8 +119,12 @@ export default {
},
pullZone () {
axios
.get('/api/domains/' + encodeURIComponent(this.domain.domain) + '/zone/' + encodeURIComponent(this.zoneMeta.id))
if (this.domain === undefined || this.domain.domain === undefined || this.zoneMeta === undefined || this.zoneMeta.id === undefined) {
return
}
ZoneApi
.getZone(this.domain.domain, this.zoneMeta.id)
.then(
(response) => {
this.myServices = response.data

View File

@ -0,0 +1,43 @@
// Copyright or © or Copr. happyDNS (2020)
//
// 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.
import Api from '@/services/Api'
export default {
getServiceSpecs (serviceType) {
if (serviceType != null) {
serviceType = serviceType[0] === '*' ? serviceType.substr(1) : serviceType
return Api().get('/api/service_specs/' + serviceType)
} else {
return Api().get('/api/service_specs')
}
}
}

View File

@ -32,11 +32,11 @@
import Api from '@/services/Api'
export default {
getServices () {
getServices (domain) {
return Api().get('/api/service_specs')
},
getServiceSpecs (serviceType) {
serviceType = serviceType[0] === '*' ? serviceType.substr(1) : serviceType
updateService (service) {
var serviceType = serviceType[0] === '*' ? serviceType.substr(1) : serviceType
return Api().get('/api/service_specs/' + serviceType)
}
}

View File

@ -0,0 +1,38 @@
// Copyright or © or Copr. happyDNS (2020)
//
// 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.
import Api from '@/services/Api'
export default {
getZone (domain, id) {
return Api().get('/api/domains/' + encodeURIComponent(domain) + '/zone/' + encodeURIComponent(id))
}
}

View File

@ -32,7 +32,13 @@
-->
<template>
<h-subdomain-list v-if="selectedHistory" :domain="domain" :zone-meta="selectedHistory" />
<div>
<div v-if="importInProgress" class="mt-4 text-center">
<b-spinner label="Spinning" />
<p>Please wait while we are importing your domain&nbsp;&hellip;</p>
</div>
<h-subdomain-list v-if="!importInProgress && selectedHistory" :domain="domain" :zone-meta="selectedHistory" />
</div>
</template>
<script>
@ -52,6 +58,7 @@ export default {
data: function () {
return {
importInProgress: false,
selectedHistory: null
}
},
@ -71,12 +78,14 @@ export default {
methods: {
pullDomain () {
if (this.domain.zone_history === null || this.domain.zone_history.length === 0) {
this.importInProgress = true
axios
.post('/api/domains/' + encodeURIComponent(this.domain.domain) + '/import_zone')
.then(
(response) => {
this.importInProgress = false
this.selectedHistory = response.data
this.$parent.$emit('updateDomainInfo')
// this.selectedHistory = response.data
}
)
} else {

View File

@ -86,22 +86,8 @@ export default {
},
mounted () {
var mydomain = this.$route.params.domain
axios
.get('/api/domains/' + mydomain)
.then(
response => (this.domain = response.data),
error => {
this.$root.$bvToast.toast(
'Unfortunately, we were unable to retrieve information for the domain ' + this.$route.params.domain + ': ' + error.response.data.errmsg, {
title: 'Unable to retrieve domain information',
autoHideDelay: 5000,
variant: 'danger',
toaster: 'b-toaster-content-right'
}
)
this.$router.push('/domains/')
})
this.updateDomainInfo()
this.$on('updateDomainInfo', this.updateDomainInfo)
},
methods: {
@ -111,6 +97,25 @@ export default {
.then(response => (
this.$router.push('/domains/')
))
},
updateDomainInfo () {
var mydomain = this.$route.params.domain
axios
.get('/api/domains/' + encodeURIComponent(mydomain))
.then(
response => (this.domain = response.data),
error => {
this.$root.$bvToast.toast(
'Unfortunately, we were unable to retrieve information for the domain ' + this.$route.params.domain + ': ' + error.response.data.errmsg, {
title: 'Unable to retrieve domain information',
autoHideDelay: 5000,
variant: 'danger',
toaster: 'b-toaster-content-right'
}
)
this.$router.push('/domains/')
})
}
}
}

View File

@ -32,6 +32,8 @@
package happydns
import (
"bytes"
"errors"
"time"
)
@ -50,3 +52,28 @@ type Zone struct {
Aliases map[string][]string `json:"aliases"`
Services map[string][]*ServiceCombined `json:"services"`
}
func (z *Zone) FindService(id []byte) *ServiceCombined {
for _, services := range z.Services {
for _, svc := range services {
if bytes.Equal(svc.Id, id) {
return svc
}
}
}
return nil
}
func (z *Zone) EraseService(domain string, id []byte, s *ServiceCombined) error {
if services, ok := z.Services[domain]; ok {
for k, svc := range services {
if bytes.Equal(svc.Id, id) {
z.Services[domain][k] = s
return nil
}
}
}
return errors.New("Service not found")
}