From 9ec277ce656164fe165f82f110938b9bf45d7bcf Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Thu, 19 Jun 2025 20:23:10 +0000 Subject: [PATCH] implement ssr dialog for config --- web/html/config-volumes.go.tmpl | 2 +- web/html/config.html | 26 ++- web/scripts/config.js | 163 ++++++------------- web/templates/config.go.tmpl | 269 +++++++++++++++++++++++++++++++- 4 files changed, 317 insertions(+), 143 deletions(-) diff --git a/web/html/config-volumes.go.tmpl b/web/html/config-volumes.go.tmpl index 8c2ff0d..d86a22b 100644 --- a/web/html/config-volumes.go.tmpl +++ b/web/html/config-volumes.go.tmpl @@ -1 +1 @@ -{{template "volumes" .config.Volumes}} \ No newline at end of file +{{template "volumes" Map "Volumes" .config.Volumes "InstanceType" .config.Type}} \ No newline at end of file diff --git a/web/html/config.html b/web/html/config.html index c641957..a47e223 100644 --- a/web/html/config.html +++ b/web/html/config.html @@ -43,18 +43,14 @@
Volumes
- {{template "volumes" .config.Volumes}} + {{template "volumes" Map "Volumes" .config.Volumes "InstanceType" .config.Type}}
- + + {{template "volumes-add-disk" .}} + {{if eq .config.Type "VM"}} - + {{template "volumes-add-cd"}} {{end}}
@@ -64,10 +60,8 @@ {{template "nets" .config.Nets}}
- + + {{template "nets-add-net"}}
{{if eq .config.Type "VM"}} @@ -77,10 +71,8 @@ {{template "devices" .config.Devices}}
- + + {{template "devices-add-device"}}
diff --git a/web/scripts/config.js b/web/scripts/config.js index 6b12add..a5b17b5 100644 --- a/web/scripts/config.js +++ b/web/scripts/config.js @@ -29,6 +29,7 @@ class VolumeAction extends HTMLElement { super(); const internals = this.attachInternals(); this.shadowRoot = internals.shadowRoot; + this.template = this.shadowRoot.querySelector("#dialog-template"); if (this.dataset.type === "move") { this.addEventListener("click", this.handleDiskMove); } @@ -53,9 +54,7 @@ class VolumeAction extends HTMLElement { async handleDiskDetach () { const disk = this.dataset.volume; - const header = `Detach ${disk}`; - const body = `

Are you sure you want to detach disk ${disk}

`; - dialog(header, body, async (result, form) => { + dialog(this.template, async (result, form) => { if (result === "confirm") { this.setStatusLoading(); const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/disk/${disk}/detach`, "POST"); @@ -69,15 +68,7 @@ class VolumeAction extends HTMLElement { } async handleDiskAttach () { - const header = `Attach ${this.dataset.volume}`; - const body = ` -
- - -
- `; - - dialog(header, body, async (result, form) => { + dialog(this.template, async (result, form) => { if (result === "confirm") { const device = form.get("device"); this.setStatusLoading(); @@ -97,15 +88,7 @@ class VolumeAction extends HTMLElement { } async handleDiskResize () { - const header = `Resize ${this.dataset.volume}`; - const body = ` -
- - -
- `; - - dialog(header, body, async (result, form) => { + dialog(this.template, async (result, form) => { if (result === "confirm") { const disk = this.dataset.volume; this.setStatusLoading(); @@ -123,25 +106,7 @@ class VolumeAction extends HTMLElement { } async handleDiskMove () { - const content = type === "qemu" ? "images" : "rootdir"; - const storage = await requestPVE(`/nodes/${node}/storage`, "GET"); - const header = `Move ${this.dataset.volume}`; - let options = ""; - storage.data.forEach((element) => { - if (element.content.includes(content)) { - options += `"`; - } - }); - const select = ``; - - const body = ` -
- ${select} - -
- `; - - dialog(header, body, async (result, form) => { + const d = dialog(this.template, async (result, form) => { if (result === "confirm") { const disk = this.dataset.volume; this.setStatusLoading(); @@ -157,13 +122,20 @@ class VolumeAction extends HTMLElement { refreshBoot(); } }); + const content = type === "qemu" ? "images" : "rootdir"; + const storage = await requestPVE(`/nodes/${node}/storage`, "GET"); + const select = d.querySelector("#storage-select"); + storage.data.forEach((element) => { + if (element.content.includes(content)) { + select.add(new Option(element.storage)); + } + select.selectedIndex = -1; + }); } async handleDiskDelete () { const disk = this.dataset.volume; - const header = `Delete ${disk}`; - const body = `

Are you sure you want to delete disk ${disk}

`; - dialog(header, body, async (result, form) => { + dialog(this.template, async (result, form) => { if (result === "confirm") { this.setStatusLoading(); const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/disk/${disk}/delete`, "DELETE"); @@ -201,26 +173,8 @@ async function refreshVolumes () { } async function handleDiskAdd () { - const content = type === "qemu" ? "images" : "rootdir"; - const storage = await requestPVE(`/nodes/${node}/storage`, "GET"); - const header = "Create New Disk"; - let options = ""; - storage.data.forEach((element) => { - if (element.content.includes(content)) { - options += `"`; - } - }); - const select = ``; - - const body = ` -
- - ${select} - -
- `; - - dialog(header, body, async (result, form) => { + const template = document.querySelector("#add-disk-dialog"); + const d = dialog(template, async (result, form) => { if (result === "confirm") { const body = { storage: form.get("storage-select"), @@ -237,19 +191,21 @@ async function handleDiskAdd () { refreshBoot(); } }); + + const content = type === "qemu" ? "images" : "rootdir"; + const storage = await requestPVE(`/nodes/${node}/storage`, "GET"); + const select = d.querySelector("#storage-select"); + storage.data.forEach((element) => { + if (element.content.includes(content)) { + select.add(new Option(element.storage)); + } + select.selectedIndex = -1; + }); } async function handleCDAdd () { - const isos = await requestAPI("/user/vm-isos", "GET"); - const header = "Mount a CDROM"; - const body = ` -
- - -
- `; - - const d = dialog(header, body, async (result, form) => { + const template = document.querySelector("#add-cd-dialog"); + const d = dialog(template, async (result, form) => { if (result === "confirm") { const body = { iso: form.get("iso-select") @@ -264,12 +220,13 @@ async function handleCDAdd () { } }); - const isoSelect = d.querySelector("#iso-select"); + const isos = await requestAPI("/user/vm-isos", "GET"); + const select = d.querySelector("#iso-select"); for (const iso of isos) { - isoSelect.append(new Option(iso.name, iso.volid)); + select.add(new Option(iso.name, iso.volid)); } - isoSelect.selectedIndex = -1; + select.selectedIndex = -1; } class NetworkAction extends HTMLElement { @@ -279,6 +236,7 @@ class NetworkAction extends HTMLElement { super(); const internals = this.attachInternals(); this.shadowRoot = internals.shadowRoot; + this.template = this.shadowRoot.querySelector("#dialog-template"); if (this.dataset.type === "config") { this.addEventListener("click", this.handleNetworkConfig); } @@ -293,16 +251,9 @@ class NetworkAction extends HTMLElement { } async handleNetworkConfig () { - const netID = this.dataset.network; const netDetails = this.dataset.value; - const header = `Edit ${netID}`; - const body = ` -
- -
- `; - - const d = dialog(header, body, async (result, form) => { + const netID = this.dataset.network; + const d = dialog(this.template, async (result, form) => { if (result === "confirm") { this.setStatusLoading(); const body = { @@ -323,9 +274,7 @@ class NetworkAction extends HTMLElement { async handleNetworkDelete () { const netID = this.dataset.network; - const header = `Delete ${netID}`; - const body = ""; - dialog(header, body, async (result, form) => { + dialog(this.template, async (result, form) => { if (result === "confirm") { setSVGSrc(document.querySelector(`svg[data-network="${netID}"]`), "images/status/loading.svg"); const net = `${netID}`; @@ -361,17 +310,8 @@ async function refreshNetworks () { } async function handleNetworkAdd () { - const header = "Create Network Interface"; - let body = ` -
- - - `; - if (type === "lxc") { - body += ""; - } - body += "
"; - dialog(header, body, async (result, form) => { + const template = document.querySelector("#add-net-dialog"); + dialog(template, async (result, form) => { if (result === "confirm") { const body = { rate: form.get("rate") @@ -398,6 +338,7 @@ class DeviceAction extends HTMLElement { super(); const internals = this.attachInternals(); this.shadowRoot = internals.shadowRoot; + this.template = this.shadowRoot.querySelector("#dialog-template"); if (this.dataset.type === "config") { this.addEventListener("click", this.handleDeviceConfig); } @@ -415,14 +356,7 @@ class DeviceAction extends HTMLElement { const deviceID = this.dataset.device; const deviceDetails = this.dataset.value; const deviceName = this.dataset.name; - const header = `Edit Expansion Card ${deviceID}`; - const body = ` -
- -
- `; - - const d = dialog(header, body, async (result, form) => { + const d = dialog(this.template, async (result, form) => { if (result === "confirm") { this.setStatusLoading(); const body = { @@ -448,9 +382,7 @@ class DeviceAction extends HTMLElement { async handleDeviceDelete () { const deviceID = this.dataset.device; - const header = `Remove Expansion Card ${deviceID}`; - const body = ""; - dialog(header, body, async (result, form) => { + dialog(this.template, async (result, form) => { if (result === "confirm") { this.setStatusLoading(); const device = `${deviceID}`; @@ -487,15 +419,8 @@ async function refreshDevices () { } async function handleDeviceAdd () { - const header = "Add Expansion Card"; - const body = ` -
- - - -
- `; - const d = dialog(header, body, async (result, form) => { + const template = document.querySelector("#add-device-dialog"); + const d = dialog(template, async (result, form) => { if (result === "confirm") { const hostpci = form.get("hostpci"); const body = { diff --git a/web/templates/config.go.tmpl b/web/templates/config.go.tmpl index 654cc76..76f9f68 100644 --- a/web/templates/config.go.tmpl +++ b/web/templates/config.go.tmpl @@ -27,22 +27,75 @@ {{end}} {{define "volumes"}} - {{range $k,$v := .}} + {{range $k,$v := .Volumes}} {{if eq $v.Type "rootfs"}} - {{ template "volume-rootfs" Map "Name" $k "Volume" $v}} + {{ template "volume-rootfs" Map "Name" $k "Volume" $v "InstanceType" $.InstanceType}} {{else if eq $v.Type "mp"}} - {{ template "volume-mp" Map "Name" $k "Volume" $v}} + {{ template "volume-mp" Map "Name" $k "Volume" $v "InstanceType" $.InstanceType}} {{else if eq $v.Type "ide"}} - {{ template "volume-ide" Map "Name" $k "Volume" $v}} + {{ template "volume-ide" Map "Name" $k "Volume" $v "InstanceType" $.InstanceType}} {{else if or (eq $v.Type "scsi") (eq $v.Type "sata")}} - {{ template "volume-scsi" Map "Name" $k "Volume" $v}} + {{ template "volume-scsi" Map "Name" $k "Volume" $v "InstanceType" $.InstanceType}} {{else if eq $v.Type "unused"}} - {{ template "volume-unused" Map "Name" $k "Volume" $v}} + {{ template "volume-unused" Map "Name" $k "Volume" $v "InstanceType" $.InstanceType}} {{else}} {{end}} {{end}} {{end}} +{{define "volumes-add-disk"}} + + +{{end}} + +{{define "volumes-add-cd"}} + + +{{end}} + {{define "volume-rootfs"}}

{{.Name}}

@@ -108,6 +161,23 @@ {{end}} @@ -126,6 +196,23 @@ {{end}} @@ -144,6 +231,22 @@ {{end}} @@ -162,6 +265,28 @@ {{end}} @@ -171,6 +296,22 @@ {{end}} @@ -190,6 +331,33 @@ {{end}} {{end}} +{{define "nets-add-net"}} + + +{{end}} + {{define "net"}}

{{.Net_ID}}

@@ -199,12 +367,44 @@ @@ -216,6 +416,31 @@ {{end}} {{end}} +{{define "devices-add-device"}} + + +{{end}} + {{define "device"}}

{{.Device_ID}}

@@ -225,12 +450,44 @@