Propagate services values through components
This commit is contained in:
parent
d41a073fc3
commit
23311495ce
@ -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)
|
||||
)
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -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
|
||||
|
43
htdocs/src/services/ServiceSpecsApi.js
Normal file
43
htdocs/src/services/ServiceSpecsApi.js
Normal 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')
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
38
htdocs/src/services/ZoneApi.js
Normal file
38
htdocs/src/services/ZoneApi.js
Normal 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))
|
||||
}
|
||||
}
|
@ -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 …</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 {
|
||||
|
@ -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/')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user