fix draggable list responsiveness,
add event handlers for adding/removing boot options
This commit is contained in:
parent
2b75732e92
commit
8c328dd22c
@ -12,6 +12,7 @@ let node;
|
|||||||
let type;
|
let type;
|
||||||
let vmid;
|
let vmid;
|
||||||
let config;
|
let config;
|
||||||
|
const bootEntries = {};
|
||||||
|
|
||||||
async function init () {
|
async function init () {
|
||||||
setTitleAndHeader();
|
setTitleAndHeader();
|
||||||
@ -230,21 +231,19 @@ function addDiskLine (fieldset, busPrefix, busName, device, diskDetails) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleDiskDetach () {
|
async function handleDiskDetach () {
|
||||||
const header = `Detach ${this.dataset.disk}`;
|
const disk = this.dataset.disk;
|
||||||
const body = `<p>Are you sure you want to detach disk</p><p>${this.dataset.disk}</p>`;
|
const header = `Detach ${disk}`;
|
||||||
|
const body = `<p>Are you sure you want to detach disk</p><p>${disk}</p>`;
|
||||||
dialog(header, body, async (result, form) => {
|
dialog(header, body, async (result, form) => {
|
||||||
if (result === "confirm") {
|
if (result === "confirm") {
|
||||||
document.querySelector(`img[data-disk="${this.dataset.disk}"]`).src = "images/status/loading.svg";
|
document.querySelector(`img[data-disk="${disk}"]`).src = "images/status/loading.svg";
|
||||||
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/disk/${this.dataset.disk}/detach`, "POST");
|
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/disk/${disk}/detach`, "POST");
|
||||||
if (result.status === 200) {
|
if (result.status !== 200) {
|
||||||
await getConfig();
|
|
||||||
populateDisk();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
alert(result.error);
|
alert(result.error);
|
||||||
await getConfig();
|
|
||||||
populateDisk();
|
|
||||||
}
|
}
|
||||||
|
await getConfig();
|
||||||
|
populateDisk();
|
||||||
|
deleteBootLine(`boot-${disk}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -260,17 +259,15 @@ async function handleDiskAttach () {
|
|||||||
const body = {
|
const body = {
|
||||||
source: this.dataset.disk.replace("unused", "")
|
source: this.dataset.disk.replace("unused", "")
|
||||||
};
|
};
|
||||||
const disk = `${type === "qemu" ? "sata" : "mp"}${device}`;
|
const prefix = type === "qemu" ? "sata" : "mp";
|
||||||
|
const disk = `${prefix}${device}`;
|
||||||
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/disk/${disk}/attach`, "POST", body);
|
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/disk/${disk}/attach`, "POST", body);
|
||||||
if (result.status === 200) {
|
if (result.status !== 200) {
|
||||||
await getConfig();
|
|
||||||
populateDisk();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
alert(result.error);
|
alert(result.error);
|
||||||
await getConfig();
|
|
||||||
populateDisk();
|
|
||||||
}
|
}
|
||||||
|
await getConfig();
|
||||||
|
populateDisk();
|
||||||
|
addBootLine("disabled", { id: disk, prefix, value: config.data[disk] });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -281,20 +278,19 @@ async function handleDiskResize () {
|
|||||||
|
|
||||||
dialog(header, body, async (result, form) => {
|
dialog(header, body, async (result, form) => {
|
||||||
if (result === "confirm") {
|
if (result === "confirm") {
|
||||||
document.querySelector(`img[data-disk="${this.dataset.disk}"]`).src = "images/status/loading.svg";
|
const disk = this.dataset.disk;
|
||||||
|
document.querySelector(`img[data-disk="${disk}"]`).src = "images/status/loading.svg";
|
||||||
const body = {
|
const body = {
|
||||||
size: form.get("size-increment")
|
size: form.get("size-increment")
|
||||||
};
|
};
|
||||||
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/disk/${this.dataset.disk}/resize`, "POST", body);
|
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/disk/${disk}/resize`, "POST", body);
|
||||||
if (result.status === 200) {
|
if (result.status !== 200) {
|
||||||
await getConfig();
|
|
||||||
populateDisk();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
alert(result.error);
|
alert(result.error);
|
||||||
await getConfig();
|
|
||||||
populateDisk();
|
|
||||||
}
|
}
|
||||||
|
await getConfig();
|
||||||
|
populateDisk();
|
||||||
|
const prefix = bootMetaData.eligiblePrefixes.find((pref) => disk.startsWith(pref));
|
||||||
|
updateBootLine(`boot-${disk}`, { id: disk, prefix, value: config.data[disk] });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -320,42 +316,38 @@ async function handleDiskMove () {
|
|||||||
|
|
||||||
dialog(header, body, async (result, form) => {
|
dialog(header, body, async (result, form) => {
|
||||||
if (result === "confirm") {
|
if (result === "confirm") {
|
||||||
document.querySelector(`img[data-disk="${this.dataset.disk}"]`).src = "images/status/loading.svg";
|
const disk = this.dataset.disk;
|
||||||
|
document.querySelector(`img[data-disk="${disk}"]`).src = "images/status/loading.svg";
|
||||||
const body = {
|
const body = {
|
||||||
storage: form.get("storage-select"),
|
storage: form.get("storage-select"),
|
||||||
delete: form.get("delete-check") === "on" ? "1" : "0"
|
delete: form.get("delete-check") === "on" ? "1" : "0"
|
||||||
};
|
};
|
||||||
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/disk/${this.dataset.disk}/move`, "POST", body);
|
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/disk/${disk}/move`, "POST", body);
|
||||||
if (result.status === 200) {
|
if (result.status !== 200) {
|
||||||
await getConfig();
|
|
||||||
populateDisk();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
alert(result.error);
|
alert(result.error);
|
||||||
await getConfig();
|
|
||||||
populateDisk();
|
|
||||||
}
|
}
|
||||||
|
await getConfig();
|
||||||
|
populateDisk();
|
||||||
|
const prefix = bootMetaData.eligiblePrefixes.find((pref) => disk.startsWith(pref));
|
||||||
|
updateBootLine(`boot-${disk}`, { id: disk, prefix, value: config.data[disk] });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleDiskDelete () {
|
async function handleDiskDelete () {
|
||||||
const header = `Delete ${this.dataset.disk}`;
|
const disk = this.dataset.disk;
|
||||||
const body = `<p>Are you sure you want to <strong>delete</strong> disk</p><p>${this.dataset.disk}</p>`;
|
const header = `Delete ${disk}`;
|
||||||
|
const body = `<p>Are you sure you want to <strong>delete</strong> disk</p><p>${disk}</p>`;
|
||||||
dialog(header, body, async (result, form) => {
|
dialog(header, body, async (result, form) => {
|
||||||
if (result === "confirm") {
|
if (result === "confirm") {
|
||||||
document.querySelector(`img[data-disk="${this.dataset.disk}"]`).src = "images/status/loading.svg";
|
document.querySelector(`img[data-disk="${disk}"]`).src = "images/status/loading.svg";
|
||||||
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/disk/${this.dataset.disk}/delete`, "DELETE");
|
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/disk/${disk}/delete`, "DELETE");
|
||||||
if (result.status === 200) {
|
if (result.status !== 200) {
|
||||||
await getConfig();
|
|
||||||
populateDisk();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
alert(result.error);
|
alert(result.error);
|
||||||
await getConfig();
|
|
||||||
populateDisk();
|
|
||||||
}
|
}
|
||||||
|
await getConfig();
|
||||||
|
populateDisk();
|
||||||
|
deleteBootLine(`boot-${disk}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -386,17 +378,16 @@ async function handleDiskAdd () {
|
|||||||
storage: form.get("storage-select"),
|
storage: form.get("storage-select"),
|
||||||
size: form.get("size")
|
size: form.get("size")
|
||||||
};
|
};
|
||||||
const disk = `${type === "qemu" ? "sata" : "mp"}${form.get("device")}`;
|
const id = form.get("device");
|
||||||
|
const prefix = type === "qemu" ? "sata" : "mp";
|
||||||
|
const disk = `${prefix}${id}`;
|
||||||
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/disk/${disk}/create`, "POST", body);
|
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/disk/${disk}/create`, "POST", body);
|
||||||
if (result.status === 200) {
|
if (result.status !== 200) {
|
||||||
await getConfig();
|
|
||||||
populateDisk();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
alert(result.error);
|
alert(result.error);
|
||||||
await getConfig();
|
|
||||||
populateDisk();
|
|
||||||
}
|
}
|
||||||
|
await getConfig();
|
||||||
|
populateDisk();
|
||||||
|
addBootLine("disabled", { id: disk, prefix, value: config.data[disk] });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -428,15 +419,12 @@ async function handleCDAdd () {
|
|||||||
};
|
};
|
||||||
const disk = `ide${form.get("device")}`;
|
const disk = `ide${form.get("device")}`;
|
||||||
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/disk/${disk}/create`, "POST", body);
|
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/disk/${disk}/create`, "POST", body);
|
||||||
if (result.status === 200) {
|
if (result.status !== 200) {
|
||||||
await getConfig();
|
|
||||||
populateDisk();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
alert(result.error);
|
alert(result.error);
|
||||||
await getConfig();
|
|
||||||
populateDisk();
|
|
||||||
}
|
}
|
||||||
|
await getConfig();
|
||||||
|
populateDisk();
|
||||||
|
addBootLine("disabled", { id: disk, prefix: "ide", value: config.data[disk] });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -530,15 +518,12 @@ async function handleNetworkConfig () {
|
|||||||
rate: form.get("rate")
|
rate: form.get("rate")
|
||||||
};
|
};
|
||||||
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/net/net${netID}/modify`, "POST", body);
|
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/net/net${netID}/modify`, "POST", body);
|
||||||
if (result.status === 200) {
|
if (result.status !== 200) {
|
||||||
await getConfig();
|
|
||||||
populateNetworks();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
alert(result.error);
|
alert(result.error);
|
||||||
await getConfig();
|
|
||||||
populateNetworks();
|
|
||||||
}
|
}
|
||||||
|
await getConfig();
|
||||||
|
populateNetworks();
|
||||||
|
updateBootLine(`boot-net${netID}`, { id: `net${netID}`, prefix: "net", value: config.data[`net${netID}`] });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -554,15 +539,12 @@ async function handleNetworkDelete () {
|
|||||||
if (result === "confirm") {
|
if (result === "confirm") {
|
||||||
document.querySelector(`img[data-network="${netID}"]`).src = "images/status/loading.svg";
|
document.querySelector(`img[data-network="${netID}"]`).src = "images/status/loading.svg";
|
||||||
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/net/net${netID}/delete`, "DELETE");
|
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/net/net${netID}/delete`, "DELETE");
|
||||||
if (result.status === 200) {
|
if (result.status !== 200) {
|
||||||
await getConfig();
|
|
||||||
populateNetworks();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
alert(result.error);
|
alert(result.error);
|
||||||
await getConfig();
|
|
||||||
populateNetworks();
|
|
||||||
}
|
}
|
||||||
|
await getConfig();
|
||||||
|
populateNetworks();
|
||||||
|
deleteBootLine(`boot-net${netID}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -584,15 +566,12 @@ async function handleNetworkAdd () {
|
|||||||
}
|
}
|
||||||
const netID = form.get("netid");
|
const netID = form.get("netid");
|
||||||
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/net/net${netID}/create`, "POST", body);
|
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/net/net${netID}/create`, "POST", body);
|
||||||
if (result.status === 200) {
|
if (result.status !== 200) {
|
||||||
await getConfig();
|
|
||||||
populateNetworks();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
alert(result.error);
|
alert(result.error);
|
||||||
await getConfig();
|
|
||||||
populateNetworks();
|
|
||||||
}
|
}
|
||||||
|
await getConfig();
|
||||||
|
populateNetworks();
|
||||||
|
addBootLine("disabled", { id: `net${netID}`, prefix: "net", value: config.data[`net${netID}`] });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -679,15 +658,11 @@ async function handleDeviceConfig () {
|
|||||||
pcie: form.get("pcie") ? 1 : 0
|
pcie: form.get("pcie") ? 1 : 0
|
||||||
};
|
};
|
||||||
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/pci/hostpci${deviceID}/modify`, "POST", body);
|
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/pci/hostpci${deviceID}/modify`, "POST", body);
|
||||||
if (result.status === 200) {
|
if (result.status !== 200) {
|
||||||
await getConfig();
|
|
||||||
populateDevices();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
alert(result.error);
|
alert(result.error);
|
||||||
await getConfig();
|
|
||||||
populateDevices();
|
|
||||||
}
|
}
|
||||||
|
await getConfig();
|
||||||
|
populateDevices();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -708,15 +683,11 @@ async function handleDeviceDelete () {
|
|||||||
if (result === "confirm") {
|
if (result === "confirm") {
|
||||||
document.querySelector(`img[data-device="${deviceID}"]`).src = "images/status/loading.svg";
|
document.querySelector(`img[data-device="${deviceID}"]`).src = "images/status/loading.svg";
|
||||||
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/pci/hostpci${deviceID}/delete`, "DELETE");
|
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/pci/hostpci${deviceID}/delete`, "DELETE");
|
||||||
if (result.status === 200) {
|
if (result.status !== 200) {
|
||||||
await getConfig();
|
|
||||||
populateDevices();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
alert(result.error);
|
alert(result.error);
|
||||||
await getConfig();
|
|
||||||
populateDevices();
|
|
||||||
}
|
}
|
||||||
|
await getConfig();
|
||||||
|
populateDevices();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -732,15 +703,11 @@ async function handleDeviceAdd () {
|
|||||||
pcie: form.get("pcie") ? 1 : 0
|
pcie: form.get("pcie") ? 1 : 0
|
||||||
};
|
};
|
||||||
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/pci/create`, "POST", body);
|
const result = await requestAPI(`/cluster/${node}/${type}/${vmid}/pci/create`, "POST", body);
|
||||||
if (result.status === 200) {
|
if (result.status !== 200) {
|
||||||
await getConfig();
|
|
||||||
populateDevices();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
alert(result.error);
|
alert(result.error);
|
||||||
await getConfig();
|
|
||||||
populateDevices();
|
|
||||||
}
|
}
|
||||||
|
await getConfig();
|
||||||
|
populateDevices();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -756,17 +723,23 @@ async function populateBoot () {
|
|||||||
document.querySelector("#boot-card").classList.remove("none");
|
document.querySelector("#boot-card").classList.remove("none");
|
||||||
document.querySelector("#enabled").title = "Enabled";
|
document.querySelector("#enabled").title = "Enabled";
|
||||||
document.querySelector("#disabled").title = "Disabled";
|
document.querySelector("#disabled").title = "Disabled";
|
||||||
const order = config.data.boot.replace("order=", "").split(";");
|
let order = [];
|
||||||
|
if (config.data.boot.startsWith("order=")) {
|
||||||
|
order = config.data.boot.replace("order=", "").split(";");
|
||||||
|
}
|
||||||
const bootable = { disabled: [] };
|
const bootable = { disabled: [] };
|
||||||
const eligible = bootMetaData.eligiblePrefixes;
|
const eligible = bootMetaData.eligiblePrefixes;
|
||||||
for (let i = 0; i < order.length; i++) {
|
for (let i = 0; i < order.length; i++) {
|
||||||
|
const element = order[i];
|
||||||
const prefix = eligible.find((pref) => order[i].startsWith(pref));
|
const prefix = eligible.find((pref) => order[i].startsWith(pref));
|
||||||
bootable[i] = { id: order[i], prefix };
|
const value = config.data[element];
|
||||||
|
bootable[i] = { id: element, prefix, value };
|
||||||
}
|
}
|
||||||
Object.keys(config.data).forEach((element) => {
|
Object.keys(config.data).forEach((element) => {
|
||||||
const prefix = eligible.find((pref) => element.startsWith(pref));
|
const prefix = eligible.find((pref) => element.startsWith(pref));
|
||||||
|
const value = config.data[element];
|
||||||
if (prefix && !order.includes(element)) {
|
if (prefix && !order.includes(element)) {
|
||||||
bootable.disabled.push({ id: element, prefix });
|
bootable.disabled.push({ id: element, prefix, value });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Object.keys(bootable).sort();
|
Object.keys(bootable).sort();
|
||||||
@ -783,20 +756,42 @@ async function populateBoot () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addBootLine (fieldset, bootable, before = null) {
|
function addBootLine (container, data, before = null) {
|
||||||
const item = document.createElement("draggable-item");
|
const item = document.createElement("draggable-item");
|
||||||
item.bootable = bootable;
|
item.data = data;
|
||||||
item.innerHTML = `
|
item.innerHTML = `
|
||||||
<img src="${bootMetaData[bootable.prefix].icon}">
|
<img src="${bootMetaData[data.prefix].icon}">
|
||||||
<p style="margin: 0px;">${bootable.id}</p>
|
<p style="margin: 0px;">${data.id}</p>
|
||||||
|
<p style="margin: 0px; overflow-x: hidden; white-space: nowrap;">${data.value}</p>
|
||||||
`;
|
`;
|
||||||
item.draggable = true;
|
item.draggable = true;
|
||||||
item.classList.add("drop-target");
|
item.classList.add("drop-target");
|
||||||
|
item.id = `boot-${data.id}`;
|
||||||
if (before) {
|
if (before) {
|
||||||
document.querySelector(`#${fieldset}`).insertBefore(item, before);
|
document.querySelector(`#${container}`).insertBefore(item, before);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
document.querySelector(`#${fieldset}`).append(item);
|
document.querySelector(`#${container}`).append(item);
|
||||||
|
}
|
||||||
|
item.container = container;
|
||||||
|
bootEntries[item.id] = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteBootLine (id) {
|
||||||
|
bootEntries[id].parentElement.removeChild(bootEntries[id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateBootLine (id, newData) {
|
||||||
|
const element = bootEntries[id];
|
||||||
|
if (element) {
|
||||||
|
const container = element.container;
|
||||||
|
const before = element.nextSibling;
|
||||||
|
deleteBootLine(id);
|
||||||
|
addBootLine(container, newData, before);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ class DraggableContainer extends HTMLElement {
|
|||||||
super();
|
super();
|
||||||
this.attachShadow({ mode: "open" });
|
this.attachShadow({ mode: "open" });
|
||||||
this.shadowRoot.innerHTML = `
|
this.shadowRoot.innerHTML = `
|
||||||
<link rel="stylesheet" href="css/style.css">
|
|
||||||
<label id="title"></label>
|
<label id="title"></label>
|
||||||
<div id="wrapper">
|
<div id="wrapper">
|
||||||
<draggable-item id="bottom" class="drop-target"></draggable-item>
|
<draggable-item id="bottom" class="drop-target"></draggable-item>
|
||||||
@ -29,20 +28,40 @@ class DraggableContainer extends HTMLElement {
|
|||||||
insertBefore (newNode, referenceNode) {
|
insertBefore (newNode, referenceNode) {
|
||||||
this.content.insertBefore(newNode, referenceNode);
|
this.content.insertBefore(newNode, referenceNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deleteItemByID (nodeid) {
|
||||||
|
const node = this.content.querySelector(`#${nodeid}`);
|
||||||
|
if (node) {
|
||||||
|
this.content.removeChild(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DraggableItem extends HTMLElement {
|
class DraggableItem extends HTMLElement {
|
||||||
constructor () {
|
constructor () {
|
||||||
super();
|
super();
|
||||||
this.attachShadow({ mode: "open" });
|
this.attachShadow({ mode: "open" });
|
||||||
|
// for whatever reason, only grid layout seems to respect the parent's content bounds
|
||||||
this.shadowRoot.innerHTML = `
|
this.shadowRoot.innerHTML = `
|
||||||
<link rel="stylesheet" href="css/style.css">
|
|
||||||
<style>
|
<style>
|
||||||
#wrapper {
|
#wrapper {
|
||||||
min-height: 1.5em;
|
grid-template-columns: auto 8ch 1fr;
|
||||||
|
display: grid;
|
||||||
|
column-gap: 10px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
height: 1em;
|
||||||
|
width: 1em;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<div id="wrapper" class="flex row"></div>
|
<div id="wrapper">
|
||||||
|
<div style="min-height: 1.5em;"></div>
|
||||||
|
</div>
|
||||||
`;
|
`;
|
||||||
this.content = this.shadowRoot.querySelector("#wrapper");
|
this.content = this.shadowRoot.querySelector("#wrapper");
|
||||||
// add drag and drop listeners
|
// add drag and drop listeners
|
||||||
@ -83,13 +102,14 @@ class DraggableItem extends HTMLElement {
|
|||||||
event.target.borderTop = false;
|
event.target.borderTop = false;
|
||||||
}
|
}
|
||||||
if (event.target.classList.contains("drop-target")) {
|
if (event.target.classList.contains("drop-target")) {
|
||||||
const data = event.dataTransfer.getData("application/json");
|
const data = JSON.parse(event.dataTransfer.getData("application/json"));
|
||||||
const content = event.dataTransfer.getData("text/html");
|
const content = event.dataTransfer.getData("text/html");
|
||||||
const item = document.createElement("draggable-item");
|
const item = document.createElement("draggable-item");
|
||||||
item.bootable = data;
|
item.data = data;
|
||||||
item.innerHTML = content;
|
item.innerHTML = content;
|
||||||
item.draggable = true;
|
item.draggable = true;
|
||||||
item.classList.add("drop-target");
|
item.classList.add("drop-target");
|
||||||
|
item.id = `boot-${data.id}`;
|
||||||
event.target.parentElement.insertBefore(item, event.target);
|
event.target.parentElement.insertBefore(item, event.target);
|
||||||
}
|
}
|
||||||
this.content.attributeStyleMap.clear();
|
this.content.attributeStyleMap.clear();
|
||||||
@ -105,14 +125,6 @@ class DraggableItem extends HTMLElement {
|
|||||||
this.content.innerHTML = innerHTML;
|
this.content.innerHTML = innerHTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
get bootable () {
|
|
||||||
return this.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
set bootable (bootable) {
|
|
||||||
this.data = bootable;
|
|
||||||
}
|
|
||||||
|
|
||||||
get borderTop () {
|
get borderTop () {
|
||||||
return this.content.style.borderTop === "";
|
return this.content.style.borderTop === "";
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user