webclient: Ethernet settings fully changed to Quasar

This commit is contained in:
MaMe82 2018-09-03 15:39:42 +02:00
parent 75e8db6a7f
commit 847a960db9

View File

@ -8,6 +8,21 @@ import (
"github.com/HuckRidgeSW/hvue"
)
type jsDataTablePagination struct {
*js.Object
RowsPerPage int `js:"rowsPerPage"`
Descending bool `js:"descending"`
Page int `js:"page"`
}
func newPagination(rowsPerPage int, startPage int) (res *jsDataTablePagination) {
res = &jsDataTablePagination{Object: O()}
res.RowsPerPage = rowsPerPage
res.Page = startPage
res.Descending = false
return
}
func InitComponentsNetwork() {
hvue.NewComponent(
@ -65,8 +80,8 @@ func InitComponentsNetwork() {
)
hvue.NewComponent(
"networkinterface2",
hvue.Template(templateNetworkInterface2),
"network-interface-settings",
hvue.Template(templateNetworkInterface),
hvue.Props("interface"),
hvue.Computed("selectOptionsInterfaceModes", func(vm *hvue.VM) interface{} {
modes := js.Global.Get("Array").New()
@ -102,83 +117,7 @@ func InitComponentsNetwork() {
}),
)
hvue.NewComponent("dhcpconfig2",
hvue.Props("interface"),
hvue.Template(templateDHCPConfig2),
hvue.Computed("config", func(vm *hvue.VM) interface{} {
if vm.Get("interface").Get("dhcpServerSettings") == js.Undefined {
// no DHCP server settings present
//cast interface to struct
iface := &jsEthernetInterfaceSettings{Object: vm.Get("interface")}
iface.CreateDhcpSettingsForInterface() //Create proper DHCP server settings for interface
}
return vm.Get("interface").Get("dhcpServerSettings")
}),
hvue.ComputedWithGetSet("authoritative",
func(vm *hvue.VM) interface{} {
return !vm.Get("config").Get("nonAuthoritative").Bool()
},
func(vm *hvue.VM, newValue *js.Object) {
vm.Get("config").Set("nonAuthoritative", !newValue.Bool())
}),
hvue.Method("addRange", func(vm *hvue.VM) {
s := &jsDHCPServerSettings{Object: vm.Get("config")}
r := &jsDHCPServerRange{Object: O()}
r.RangeLower = ""
r.RangeUpper = ""
r.LeaseTime = "1m"
s.AddRange(r)
}),
hvue.Method("removeRange", func(vm *hvue.VM, delRange *jsDHCPServerRange) {
s := &jsDHCPServerSettings{Object: vm.Get("config")}
s.RemoveRange(delRange)
}),
)
hvue.NewComponent(
"networkinterface",
hvue.Template(templateNetworkInterface),
hvue.Props("interface"),
hvue.Computed("modes", func(vm *hvue.VM) interface{} {
modes := js.Global.Get("Array").New()
for val, name := range pb.EthernetInterfaceSettings_Mode_name {
mode := struct {
*js.Object
Val int `js:"val"`
Name string `js:"name"`
}{Object: O()}
mode.Val = val
mode.Name = name
modes.Call("push", mode)
}
return modes
}),
hvue.Computed("withIP", func(vm *hvue.VM) interface{} {
if mode := vm.Get("interface").Get("mode").Int(); mode == pb.EthernetInterfaceSettings_Mode_value["MANUAL"] || mode == pb.EthernetInterfaceSettings_Mode_value["DHCP_SERVER"] {
return true
} else {
return false
}
}),
hvue.Computed("withDhcp", func(vm *hvue.VM) interface{} {
if mode := vm.Get("interface").Get("mode").Int(); mode == pb.EthernetInterfaceSettings_Mode_value["DHCP_SERVER"] {
return true
} else {
return false
}
}),
hvue.Method("deploy", func(vm *hvue.VM) {
vm.Get("$store").Call("dispatch", VUEX_ACTION_DEPLOY_ETHERNET_INTERFACE_SETTINGS, vm.Get("interface"))
}),
)
hvue.NewComponent("dhcpconfig",
hvue.NewComponent("dhcp-config",
hvue.Props("interface"),
hvue.Template(templateDHCPConfig),
hvue.Computed("config", func(vm *hvue.VM) interface{} {
@ -202,11 +141,11 @@ func InitComponentsNetwork() {
}),
)
hvue.NewComponent("dhcpranges",
hvue.Props("serversettings"),
hvue.NewComponent("dhcp-ranges",
hvue.Template(templateDHCPRanges),
hvue.Props("config"),
hvue.Method("addRange", func(vm *hvue.VM) {
s := &jsDHCPServerSettings{Object: vm.Get("serversettings")}
s := &jsDHCPServerSettings{Object: vm.Get("config")}
r := &jsDHCPServerRange{Object: O()}
r.RangeLower = ""
r.RangeUpper = ""
@ -214,45 +153,72 @@ func InitComponentsNetwork() {
s.AddRange(r)
}),
hvue.Method("removeRange", func(vm *hvue.VM, delRange *jsDHCPServerRange) {
s := &jsDHCPServerSettings{Object: vm.Get("serversettings")}
s := &jsDHCPServerSettings{Object: vm.Get("config")}
s.RemoveRange(delRange)
}),
hvue.DataFunc(func(vm *hvue.VM) interface{} {
data := &struct {
*js.Object
Pagination *jsDataTablePagination `js:"pagination"`
}{Object: O()}
data.Pagination = newPagination(3, 1)
return data
}),
)
hvue.NewComponent("dhcpoptions",
hvue.Props("serversettings"),
hvue.NewComponent("dhcp-options",
hvue.Props("config"),
hvue.Template(templateDHCPOptions),
hvue.Method("addOption", func(vm *hvue.VM) {
s := &jsDHCPServerSettings{Object: vm.Get("serversettings")}
s := &jsDHCPServerSettings{Object: vm.Get("config")}
o := &jsDHCPServerOption{Object: O()}
o.Option = 3
o.Value = ""
s.AddOption(o)
}),
hvue.Method("removeOption", func(vm *hvue.VM, delOption *jsDHCPServerOption) {
s := &jsDHCPServerSettings{Object: vm.Get("serversettings")}
s := &jsDHCPServerSettings{Object: vm.Get("config")}
s.RemoveOption(delOption)
}),
hvue.DataFunc(func(vm *hvue.VM) interface{} {
data := &struct {
*js.Object
Pagination *jsDataTablePagination `js:"pagination"`
}{Object: O()}
data.Pagination = newPagination(3, 1)
return data
}),
)
hvue.NewComponent("dhcpstatichosts",
hvue.Props("serversettings"),
hvue.NewComponent("dhcp-static-hosts",
hvue.Props("config"),
hvue.Template(templateDHCPStaticHosts),
hvue.Method("addStaticHost", func(vm *hvue.VM) {
s := &jsDHCPServerSettings{Object: vm.Get("serversettings")}
s := &jsDHCPServerSettings{Object: vm.Get("config")}
sh := &jsDHCPServerStaticHost{Object: O()}
sh.Ip = ""
sh.Mac = ""
s.AddStaticHost(sh)
}),
hvue.Method("removeStaticHost", func(vm *hvue.VM, delStaticHost *jsDHCPServerStaticHost) {
s := &jsDHCPServerSettings{Object: vm.Get("serversettings")}
s := &jsDHCPServerSettings{Object: vm.Get("config")}
s.RemoveStaticHost(delStaticHost)
}),
hvue.DataFunc(func(vm *hvue.VM) interface{} {
data := &struct {
*js.Object
Pagination *jsDataTablePagination `js:"pagination"`
}{Object: O()}
data.Pagination = newPagination(3, 1)
return data
}),
)
}
const templateNetwork = `
<q-page>
<q-card inline class="q-ma-sm">
<q-card class="q-ma-sm" :inline="$q.platform.is.desktop">
<q-card-title>
Network interface settings
</q-card-title>
@ -274,35 +240,24 @@ const templateNetwork = `
</q-item>
</q-list>
<networkinterface2 v-if="current" :interface="current"></networkinterface2>
<network-interface-settings v-if="current" :interface="current"></network-interface-settings>
</q-card>
<dhcpconfig2 :interface="current" v-if="currentWithDhcp"></dhcpconfig2>
<div class="network-master">
Interface selection <select v-model="current">
<option v-for="iface in interfaces" :key="iface.name" :value="iface">{{ iface.name }}</option>
</select>
<networkinterface v-if="current" :interface="current"></networkinterface>
</div>
<dhcp-config :interface="current" v-if="currentWithDhcp"></dhcp-config>
</q-page>
`
const templateDHCPConfig2 = `
<q-card inline class="q-ma-sm">
const templateDHCPConfig = `
<q-card class="q-ma-sm" :inline="$q.platform.is.desktop">
<q-card-title>
DHCP Server settings for {{ interface.name }}
</q-card-title>
<q-list link>
<q-list>
<q-item-separator />
<q-item tag="label">
<q-item tag="label" link>
<q-item-side>
<q-toggle v-model="authoritative"></q-toggle>
</q-item-side>
@ -311,95 +266,350 @@ const templateDHCPConfig2 = `
<q-item-tile sublabel>If disabled, the DHCP Server isn't authoritative</q-item-tile>
</q-item-main>
</q-item>
<q-item tag="label" disabled>
<q-item tag="label" disabled link>
<q-item-main>
<q-item-tile label>Path to lease file</q-item-tile>
<q-item-tile sublabel>{{ config.leaseFile }}</q-item-tile>
</q-item-main>
</q-item>
<q-list-header>DHCP ranges</q-list-header>
<dhcp-ranges :config="config"></dhcp-ranges>
<q-list-header>DHCP options</q-list-header>
<dhcp-options :config="config"></dhcp-options>
<q-list-header>DHCP static hosts</q-list-header>
<dhcp-static-hosts :config="config"></dhcp-static-hosts>
</q-list>
<q-item tag="label">
<q-item-main>
<q-item-tile>
<q-table
title="DHCP ranges"
:data="config.ranges"
:columns="[{name:'lower', field: 'rangeLower', label: 'Lower IP', align: 'left'}, {name:'upper', field: 'rangeUpper', label: 'Upper IP', align: 'left'}, {name:'lease', field: 'leaseTime', label: 'Lease Time', align: 'left'}, {name:'remove', label: 'Delete range', align: 'left'}]"
row-key="name"
>
<q-tr slot="header" slot-scope="props" :props="props">
<q-th :key="props.cols[0].name" :props="props"> {{ props.cols[0].label }} </q-th>
<q-th :key="props.cols[1].name" :props="props"> {{ props.cols[1].label }} </q-th>
<q-th :key="props.cols[2].name" :props="props"> {{ props.cols[2].label }} </q-th>
<q-th :key="props.cols[3].name" :props="props">
<q-btn @click="addRange()">add</q-btn>
</q-th>
</q-tr>
<q-tr slot="body" slot-scope="props" :props="props">
<q-td key="lower" :props="props">
<q-input v-model="props.row.rangeLower" inverted></q-input>
</q-td>
<q-td key="upper" :props="props">
<q-input v-model="props.row.rangeUpper" inverted></q-input>
</q-td>
<q-td key="lease" :props="props">
<q-input v-model="props.row.leaseTime" inverted></q-input>
</q-td>
<q-td key="remove" :props="props">
<q-btn @click="removeRange(props.row)">del</q-btn>
</q-td>
</q-tr>
</q-table>
</q-item-tile>
</q-item-main>
</q-item>
<networkinterface2 v-if="current" :interface="current"></networkinterface2>
</q-card>
`
const templateDHCPConfig = `
<div>
<p><b>DHCP server settings</b></p>
<table>
<tr>
<td>Listen port</td>
<td><input v-model="config.listenPort"></input></td>
<td>Port for DNS server (0 to disable DNS and use DHCP only)</td>
</tr>
<tr>
<td>Lease file</td>
<td>{{ config.leaseFile }}</td>
<td>Path to lease file</td>
</tr>
<tr>
<td>Authoritative</td>
<td><toggle-switch type="checkbox" v-model="authoritative"></toggle-switch></td>
<td></td>
</tr>
<tr>
<td>Bind only to {{ config.listenInterface }}</td>
<td>{{ !config.doNotBindInterface }}</td>
<td></td>
</tr>
</table>
<dhcpranges :serversettings="config"></dhcpranges>
<dhcpoptions :serversettings="config"></dhcpoptions>
<dhcpstatichosts :serversettings="config"></dhcpstatichosts>
<!-- {{ config }} -->
</div>
const templateDHCPRanges = `
<q-item :link="false">
<q-item-main>
<q-item-tile>
<q-table
:data="config.ranges"
:columns="[{name:'lower', field: 'rangeLower', label: 'Lower IP', align: 'left'}, {name:'upper', field: 'rangeUpper', label: 'Upper IP', align: 'left'}, {name:'lease', field: 'leaseTime', label: 'Lease Time', align: 'left'}, {name:'remove', label: 'Delete range', align: 'left'}]"
row-key="name"
:pagination.sync="pagination"
v-if="$q.platform.is.desktop"
>
<q-tr slot="header" slot-scope="props" :props="props">
<q-th :key="props.cols[0].name" :props="props"> {{ props.cols[0].label }} </q-th>
<q-th :key="props.cols[1].name" :props="props"> {{ props.cols[1].label }} </q-th>
<q-th :key="props.cols[2].name" :props="props"> {{ props.cols[2].label }} </q-th>
<q-th :key="props.cols[3].name" :props="props">
<q-btn @click="addRange()">add</q-btn>
</q-th>
</q-tr>
<q-tr slot="body" slot-scope="props" :props="props">
<q-td key="lower" :props="props">
<q-input v-model="props.row.rangeLower" inverted></q-input>
</q-td>
<q-td key="upper" :props="props">
<q-input v-model="props.row.rangeUpper" inverted></q-input>
</q-td>
<q-td key="lease" :props="props">
<q-input v-model="props.row.leaseTime" inverted></q-input>
</q-td>
<q-td key="remove" :props="props">
<q-btn @click="removeRange(props.row)">del</q-btn>
</q-td>
</q-tr>
</q-table>
<!--
<q-table
:data="config.ranges"
:columns="[{name:'lower', field: 'rangeLower', label: 'Lower IP', align: 'left'}, {name:'upper', field: 'rangeUpper', label: 'Upper IP', align: 'left'}, {name:'lease', field: 'leaseTime', label: 'Lease Time', align: 'left'}, {name:'remove', label: 'Delete range', align: 'left'}]"
row-key="name"
:pagination.sync="pagination"
>
<q-tr slot="header" slot-scope="props" :props="props">
<q-th :key="props.cols[0].name" :props="props"> {{ props.cols[0].label }} </q-th>
<q-th :key="props.cols[1].name" :props="props"> {{ props.cols[1].label }} </q-th>
<q-th :key="props.cols[2].name" :props="props"> {{ props.cols[2].label }} </q-th>
<q-th :key="props.cols[3].name" :props="props">
<q-btn @click="addRange()">add</q-btn>
</q-th>
</q-tr>
<q-tr slot="body" slot-scope="props" :props="props">
<q-td key="lower" :props="props">
{{ props.row.rangeLower }}
<q-popup-edit v-model="props.row.rangeLower" title="Set lower IP" persistent buttons>
<q-input v-model="props.row.rangeLower" inverted></q-input>
</q-popup-edit>
</q-td>
<q-td key="upper" :props="props">
{{ props.row.rangeUpper }}
<q-popup-edit v-model="props.row.rangeUpper" title="Set upper IP">
<q-input v-model="props.row.rangeUpper" inverted></q-input>
</q-popup-edit>
</q-td>
<q-td key="lease" :props="props">
{{ props.row.leaseTime }}
<q-popup-edit v-model="props.row.leaseTime" title="Set lease time">
<q-input v-model="props.row.leaseTime" inverted></q-input>
</q-popup-edit>
</q-td>
<q-td key="remove" :props="props">
<q-btn @click="removeRange(props.row)">del</q-btn>
</q-td>
</q-tr>
</q-table>
-->
<q-card v-else>
<q-card-main>
<q-table
:data="config.ranges"
:columns="[{name:'lower', field: 'rangeLower', label: 'Lower IP', align: 'left'}, {name:'upper', field: 'rangeUpper', label: 'Upper IP', align: 'left'}, {name:'lease', field: 'leaseTime', label: 'Lease Time', align: 'left'}, {name:'remove', label: 'Delete range', align: 'left'}]"
row-key="name"
hide-header
:pagination.sync="pagination"
grid
>
<template slot="top-right" slot-scope="props" class="q-mr-sm">
<q-btn @click="addRange()" color="primary">add range</q-btn>
</template>
<div
slot="item"
slot-scope="props"
class="col-lg-6"
>
<q-card-separator />
<q-list link no-border>
<q-item tag="label" :key="remove">
<q-item-main>
<q-btn @click="removeRange(props.row)" color="secondary">delete range {{ props.row.__index + 1 }}</q-btn>
</q-item-main>
</q-item>
<q-item tag="label" :key="props.colsMap.lower.name">
<q-item-main>
<q-item-tile label>
{{ props.colsMap.lower.label }}
</q-item-tile>
<q-item-tile>
<q-input v-model="props.row.rangeLower" inverted></q-input>
</q-item-tile>
</q-item-main>
</q-item>
<q-item tag="label" :key="props.colsMap.upper.name">
<q-item-main>
<q-item-tile label>
{{ props.colsMap.upper.label }}
</q-item-tile>
<q-item-tile>
<q-input v-model="props.row.rangeUpper" inverted></q-input>
</q-item-tile>
</q-item-main>
</q-item>
<q-item tag="label" :key="props.colsMap.lease.name">
<q-item-main>
<q-item-tile label>
{{ props.colsMap.lease.label }}
</q-item-tile>
<q-item-tile>
<q-input v-model="props.row.leaseTime" inverted></q-input>
</q-item-tile>
</q-item-main>
</q-item>
</q-list>
</div>
</q-table>
</q-card-main>
</q-card>
</q-item-tile>
</q-item-main>
</q-item>
`
const templateNetworkInterface2 = `
const templateDHCPOptions = `
<q-item :link="false">
<q-item-main>
<q-item-tile>
<q-table
:data="config.options"
:columns="[{name:'optnumber', field: 'number', label: 'Option number (RFC 2132)', align: 'left'}, {name:'optvalue', field: 'value', label: 'Option string', align: 'left'}, {name:'remove', label: 'Delete option', align: 'left'}]"
row-key="name"
:pagination.sync="pagination"
v-if="$q.platform.is.desktop"
>
<q-tr slot="header" slot-scope="props" :props="props">
<q-th :key="props.cols[0].name" :props="props"> {{ props.cols[0].label }} </q-th>
<q-th :key="props.cols[1].name" :props="props"> {{ props.cols[1].label }} </q-th>
<q-th :key="props.cols[2].name" :props="props">
<q-btn @click="addOption()">add</q-btn>
</q-th>
</q-tr>
<q-tr slot="body" slot-scope="props" :props="props">
<q-td key="optnumber" :props="props">
<q-input v-model="props.row.option" type="number" inverted></q-input>
</q-td>
<q-td key="optvalue" :props="props">
<q-input v-model="props.row.value" inverted></q-input>
</q-td>
<q-td key="remove" :props="props">
<q-btn @click="removeOption(props.row)">del</q-btn>
</q-td>
</q-tr>
</q-table>
<q-card v-else>
<q-card-main>
<q-table
:data="config.options"
:columns="[{name:'optnumber', field: 'number', label: 'Option number (RFC 2132)', align: 'left'}, {name:'optvalue', field: 'value', label: 'Option string', align: 'left'}, {name:'remove', label: 'Delete option', align: 'left'}]"
row-key="name"
hide-header
:pagination.sync="pagination"
grid
>
<template slot="top-right" slot-scope="props" class="q-mr-sm">
<q-btn @click="addOption()" color="primary">add option</q-btn>
</template>
<div
slot="item"
slot-scope="props"
class="col-lg-6"
>
<q-card-separator />
<q-list link no-border>
<q-item tag="label" :key="remove">
<q-item-main>
<q-btn @click="removeOption(props.row)" color="secondary">delete option {{ props.row.__index + 1 }}</q-btn>
</q-item-main>
</q-item>
<q-item tag="label" :key="props.colsMap.optnumber.name">
<q-item-main>
<q-item-tile label>
{{ props.colsMap.optnumber.label }}
</q-item-tile>
<q-item-tile>
<q-input v-model="props.row.option" type="number" inverted></q-input>
</q-item-tile>
</q-item-main>
</q-item>
<q-item tag="label" :key="props.colsMap.optvalue.name">
<q-item-main>
<q-item-tile label>
{{ props.colsMap.optvalue.label }}
</q-item-tile>
<q-item-tile>
<q-input v-model="props.row.value" inverted></q-input>
</q-item-tile>
</q-item-main>
</q-item>
</q-list>
</div>
</q-table>
</q-card-main>
</q-card>
</q-item-tile>
</q-item-main>
</q-item>
`
const templateDHCPStaticHosts = `
<q-item :link="false">
<q-item-main>
<q-item-tile>
<q-table
:data="config.staticHosts"
:columns="[{name:'hostmac', field: 'mac', label: 'Host MAC', align: 'left'}, {name:'hostip', field: 'ip', label: 'Host IP', align: 'left'}, {name:'remove', label: 'Delete static host', align: 'left'}]"
row-key="name"
:pagination.sync="pagination"
v-if="$q.platform.is.desktop"
>
<q-tr slot="header" slot-scope="props" :props="props">
<q-th :key="props.cols[0].name" :props="props"> {{ props.cols[0].label }} </q-th>
<q-th :key="props.cols[1].name" :props="props"> {{ props.cols[1].label }} </q-th>
<q-th :key="props.cols[2].name" :props="props">
<q-btn @click="addStaticHost()">add</q-btn>
</q-th>
</q-tr>
<q-tr slot="body" slot-scope="props" :props="props">
<q-td key="hostmac" :props="props">
<q-input v-model="props.row.mac" inverted></q-input>
</q-td>
<q-td key="hostip" :props="props">
<q-input v-model="props.row.ip" inverted></q-input>
</q-td>
<q-td key="remove" :props="props">
<q-btn @click="removeStaticHost(props.row)">del</q-btn>
</q-td>
</q-tr>
</q-table>
<q-card v-else>
<q-card-main>
<q-table
:data="config.staticHosts"
:columns="[{name:'hostmac', field: 'mac', label: 'Host MAC', align: 'left'}, {name:'hostip', field: 'ip', label: 'Host IP', align: 'left'}, {name:'remove', label: 'Delete static host', align: 'left'}]"
row-key="name"
hide-header
:pagination.sync="pagination"
grid
>
<template slot="top-right" slot-scope="props" class="q-mr-sm">
<q-btn @click="addStaticHost()" color="primary">add static host</q-btn>
</template>
<div
slot="item"
slot-scope="props"
class="col-lg-6"
>
<q-card-separator />
<q-list link no-border>
<q-item tag="label" :key="remove">
<q-item-main>
<q-btn @click="removeStaticHost(props.row)" color="secondary">delete</q-btn>
</q-item-main>
</q-item>
<q-item tag="label" :key="props.colsMap.hostmac.name">
<q-item-main>
<q-item-tile label>
{{ props.colsMap.hostmac.label }}
</q-item-tile>
<q-item-tile>
<q-input v-model="props.row.mac" inverted></q-input>
</q-item-tile>
</q-item-main>
</q-item>
<q-item tag="label" :key="props.colsMap.hostip.name">
<q-item-main>
<q-item-tile label>
{{ props.colsMap.hostip.label }}
</q-item-tile>
<q-item-tile>
<q-input v-model="props.row.ip" inverted></q-input>
</q-item-tile>
</q-item-main>
</q-item>
</q-list>
</div>
</q-table>
</q-card-main>
</q-card>
</q-item-tile>
</q-item-main>
</q-item>
`
const templateNetworkInterface = `
<q-list link>
<q-item-separator />
<q-list-header>Generic settings for {{interface.name}}</q-list-header>
@ -446,80 +656,3 @@ const templateNetworkInterface2 = `
</q-list link>
`
const templateNetworkInterface = `
<div class="network-interface">
<h1>
Interface settings for "{{interface.name}}"
</h1>
Deploy settings <button @click="deploy">DEPLOY</button>
<!-- <p>{{ interface }}</p> -->
<table>
<tr>
<td>Enabled</td>
<td>
<toggle-switch v-model="interface.enabled"></toggle-switch>
</td>
</tr>
<tr>
<td>Mode</td>
<td>
<select v-model="interface.mode">
<option v-for="mode in modes" :value="mode.val">{{mode.name}}</option>
</select>
</td>
</tr>
<tr v-if="withIP">
<td>IP</td>
<td><input v-model="interface.ipAddress4"></input></td>
</tr>
<tr v-if="withIP">
<td>Mask</td>
<td><input v-model="interface.netmask4"></input></td>
</tr>
</table>
<dhcpconfig v-if="withDhcp" :interface="interface"></dhcpconfig>
</div>
`
const templateDHCPRanges = `
<div>
<p><b>DHCP ranges</b></p>
<button @click="addRange">ADD</button>
<table>
<tr v-for="range in serversettings.ranges">
<td>First IP</td> <td><input v-model="range.rangeLower"></input></td>
<td>Last IP</td> <td><input v-model="range.rangeUpper"></input></td>
<td>Lease time</td> <td><input v-model="range.leaseTime"></input></td>
<td><button @click="removeRange(range)">DEL</button></td>
</tr>
</table>
</div>
`
const templateDHCPOptions = `
<div>
<p><b>Options</b></p>
<button @click="addOption">ADD</button>
<table>
<tr v-for="option in serversettings.options">
<td>Option number</td> <td><input v-model.number="option.option"></input></td>
<td>Option string</td> <td><input v-model="option.value"></input></td>
<td><button @click="removeOption(option)">DEL</button></td>
</tr>
</table>
</div>
`
const templateDHCPStaticHosts = `
<div>
<p><b>Static host entries</b></p>
<button @click="addStaticHost">ADD</button>
<table>
<tr v-for="statichost in serversettings.staticHosts">
<td>Host Mac</td> <td><input v-model="statichost.mac"></input></td>
<td>Host IP</td> <td><input v-model="statichost.ip"></input></td>
<td><button @click="removeStaticHost(statichost)">DEL</button></td>
</tr>
</table>
</div>
`