diff --git a/l3config.js b/l3config.js index 6e73356..522ff88 100644 --- a/l3config.js +++ b/l3config.js @@ -17,9 +17,7 @@ class L3Section { let fs = makeFieldset(this.legend); let sep = undefined; for (const input of this.inputs) { - let div = document.createElement('div'); - div.append(...input.node()); - fs.append(div); + fs.append(input.node()); } return fs; } @@ -28,7 +26,7 @@ class L3Section { } render() { const options = this.inputs - .map(input => input.option()) + .flatMap(input => input.option()) .filter(option => !!option); if (options.length == 0) { @@ -67,23 +65,22 @@ class L3MultiSection { this.legend = legend; this.template = template; this.handleUpdate = handleUpdate; - this.fieldset = undefined; this.sections = []; this.nsections = 0; } node() { - this.fieldset = document.createElement('fieldset'); + let fieldset = document.createElement('fieldset'); let fieldsetlegend = document.createElement('legend'); let fieldsetbutton = document.createElement('button'); fieldsetbutton.setAttribute('type', 'button'); console.log(this.template); - fieldsetbutton.addEventListener('click', () => this.addSection()); + fieldsetbutton.addEventListener('click', () => this.addSection(fieldset)); fieldsetbutton.innerHTML = this.legend; fieldsetlegend.appendChild(fieldsetbutton); - this.fieldset.appendChild(fieldsetlegend); - return this.fieldset; + fieldset.appendChild(fieldsetlegend); + return fieldset; } - addSection() { + addSection(fieldset) { const idsuffix = `-${this.nsections++}`; let newsection = this.template(idsuffix); this.sections.push(newsection); @@ -99,7 +96,7 @@ class L3MultiSection { del.innerHTML = 'Remove'; nodes.append(del); - this.fieldset.before(nodes); + fieldset.before(nodes); this.handleUpdate(); } removeSection(del, nodes) { @@ -134,7 +131,7 @@ class L3Input { this.input.setAttribute(attr, this.attrs[attr]); } - let ret = (this.input.type === 'radio') ? [this.input, newLabel] : [newLabel, this.input]; + let inner = (this.input.type === 'radio') ? [this.input, newLabel] : [newLabel, this.input]; if (this.datalist) { let datalist = document.createElement('datalist'); @@ -148,10 +145,12 @@ class L3Input { datalist.append(option); } - ret.push(datalist); + inner.push(datalist); } - return ret; + let div = document.createElement('div') + div.append(...inner); + return div; } id() { @@ -192,6 +191,56 @@ class L3Input { } } +class L3MultiInput { + constructor(label, handleUpdate, template) { + this.label = label; + this.template = template; + this.handleUpdate = handleUpdate; + this.inputs = []; + this.ninputs = 0; + } + node() { + let inputcontainer = document.createElement('div'); + let inputbutton = document.createElement('button'); + inputbutton.setAttribute('type', 'button'); + console.log(this.template); + inputbutton.addEventListener('click', () => this.addInput(inputcontainer)); + inputbutton.innerHTML = this.label; + inputcontainer.appendChild(inputbutton); + return inputcontainer; + } + addInput(inputcontainer) { + const idsuffix = `-${this.ninputs++}`; + let newinput = this.template(idsuffix); + this.inputs.push(newinput); + let div = newinput.node(); + for (let input of div.getElementsByTagName('input')) { + console.log(input); + input.addEventListener('input', () => this.handleUpdate()) + } + + let del = document.createElement('button'); + del.setAttribute('type', 'button'); + del.addEventListener('click', () => this.removeInput(newinput, div)); + del.innerHTML = 'Remove'; + div.append(del); + + inputcontainer.before(div); + this.handleUpdate(); + } + removeInput(del, div) { + this.inputs = this.inputs.filter(input => input != del); + div.remove(); + this.handleUpdate(); + } + render() { + return this.inputs.map(input => input.render()).filter(input => !!input) + } + option() { + return this.inputs.map(input => input.option()); + } +} + class L3Config { constructor() { this.sections = []; @@ -222,14 +271,16 @@ function initForm() { const l3cfg = new L3Config(); l3cfg.addSection(new L3Section('gateway', new L3Input('Router Name','gatewayName', 'name', {type: 'search', placeholder: 'Router Name'}), - new L3Input('Router IPv4 Address','gatewayRouterIP', 'router_ip', {type: 'text'}), - new L3Input('Router IPv6 Address','gatewayRouterIP6', 'router_ip6', {type: 'text'}), + new L3Input('Router IPv4 Address','gatewayRouterIP', 'router_ip', {type: 'text', maxlength: 15}), + new L3Input('Router IPv6 Address','gatewayRouterIP6', 'router_ip6', {type: 'text', maxlength: 39}), )); l3cfg.addSection(new L3Section('dns', new L3Input('Anycast DNS','dnsAnycast', 'server', {type: 'radio', name: 'anycast', value: 'fd43:5602:29bd:ffff:1:1:1:1', checked: ''}), new L3Input('Anycast DNS64','dnsAnycast64', 'server', {type: 'radio', name: 'anycast', value: 'fd43:5602:29bd:ffff:1:1:1:64'}), new L3Input('Disable','dnsAnycastNone', 'server', {type: 'radio', name: 'anycast', value: undefined}), - new L3Input('Custom DNS Server','dnsOther', 'server', {type: 'text', placeholder: 'Custom DNS Server'}), + new L3MultiInput('+ Custom DNS Server', () => l3cfg.handleUpdate(), function(idsuffix) { + return new L3Input('Custom DNS Server','dnsOther'+idsuffix, 'server', {type: 'text', maxlength: 39, placeholder: 'Custom DNS Server'}); + }), )); l3cfg.addSection(new L3Section('wan', new L3Input('Use VLAN','babelpeerVLAN', 'vlan', {type: 'number', min: 1, max: 4094}), @@ -254,8 +305,8 @@ function initForm() { new L3Input('Endpoint Host', 'wireguardpeerEPHost'+idsuffix, 'endpoint_host', {type: 'text', required: ''}, ['peering.nue3.fff.community','ff1.zbau.f3netze.de','nsvm.f3netze.de','2a0b:f4c0:400::']), new L3Input('Endpoint Port','wireguardpeerEPPort'+idsuffix, 'endpoint_port', {type: 'number', required: '', min:1, max: 65535}), new L3Input('Persistent Keepalive','wireguardpeerPersistentKeepalive', 'persistent_keepalive', {type: 'number', min: 0, max: 65535, placeholder: '1 - 65535 Seconds...'}), - new L3Input('Remote Public Key', 'wireguardpeerRemotePubKey'+idsuffix, 'remote_public_key', {type: 'text', required: '', placeholder: 'base64 encoded public key'}), - new L3Input('Local Private Key', 'wireguardpeerLocalPrivKey'+idsuffix, 'local_private_key', {type: 'text', placeholder: 'base64 encoded private key'}), + new L3Input('Remote Public Key', 'wireguardpeerRemotePubKey'+idsuffix, 'remote_public_key', {type: 'text', minlength: 44, maxlength: 44, required: '', placeholder: 'base64 encoded public key'}), + new L3Input('Local Private Key', 'wireguardpeerLocalPrivKey'+idsuffix, 'local_private_key', {type: 'text', minlength: 44, maxlength: 44, placeholder: 'base64 encoded private key'}), new L3Input('rxcost','wireguardpeerRXCost', 'rxcost', {type: 'number', min: 96, max: 65535, value: 4096, placeholder: '4096'}), new L3Input('mtu','wireguardpeerMTU', 'mtu', {type: 'number', min: 1280, max: 65535, value: 1412, placeholder: '1412'}), );