Editing & saving changes & fixes
This commit is contained in:
parent
f451b1fbc3
commit
7e1416a721
5 changed files with 75 additions and 30 deletions
|
@ -1,5 +1,5 @@
|
||||||
import { AddInstanceDialog } from "./add_an_instance.mjs";
|
import { AddInstanceDialog } from "./add_an_instance.mjs";
|
||||||
import { InstanceDetailsDialog, InstanceDetailsDialogData } from "./confirm_instance_details.mjs";
|
import { dialogDetailsToInstance, InstanceDetailsDialog, InstanceDetailsDialogData } from "./confirm_instance_details.mjs";
|
||||||
import { Dialog } from "./dialog.mjs";
|
import { Dialog } from "./dialog.mjs";
|
||||||
import storageManager, { Instance } from "./storage_manager.mjs";
|
import storageManager, { Instance } from "./storage_manager.mjs";
|
||||||
|
|
||||||
|
@ -26,14 +26,14 @@ export class AddInstanceFlow {
|
||||||
this.detailsDialog = new InstanceDetailsDialog(detailsDialog, true);
|
this.detailsDialog = new InstanceDetailsDialog(detailsDialog, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
async start() {
|
async start(autoSave: boolean) {
|
||||||
const {
|
const {
|
||||||
autoQueryMetadata,
|
autoQueryMetadata,
|
||||||
host,
|
host,
|
||||||
secure,
|
secure,
|
||||||
} = await this.addDialog.present();
|
} = await this.addDialog.present();
|
||||||
|
|
||||||
let detailsDialogData: InstanceDetailsDialogData = {
|
const detailsDialogData: InstanceDetailsDialogData = {
|
||||||
name: host,
|
name: host,
|
||||||
host,
|
host,
|
||||||
hostSecure: secure,
|
hostSecure: secure,
|
||||||
|
@ -62,17 +62,11 @@ export class AddInstanceFlow {
|
||||||
} catch { }
|
} catch { }
|
||||||
this.spinnerDialog.close();
|
this.spinnerDialog.close();
|
||||||
|
|
||||||
detailsDialogData = await this.detailsDialog.present(detailsDialogData);
|
const finalData = await this.detailsDialog.present(detailsDialogData);
|
||||||
|
const instance = dialogDetailsToInstance(finalData, {});
|
||||||
const instance: Instance = {
|
|
||||||
name: detailsDialogData.name,
|
|
||||||
origin: `http${detailsDialogData.hostSecure ? "s" : ""}://${detailsDialogData.host}`,
|
|
||||||
software: detailsDialogData.software,
|
|
||||||
iconURL: detailsDialogData.iconURL ?? undefined
|
|
||||||
};
|
|
||||||
|
|
||||||
storageManager.storage.instances.push(instance);
|
storageManager.storage.instances.push(instance);
|
||||||
storageManager.save();
|
if (autoSave) storageManager.save();
|
||||||
console.log("Successfully added new instance:", instance);
|
console.log("Successfully added new instance:", instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import { parseHost } from "./add_an_instance.mjs";
|
import { parseHost } from "./add_an_instance.mjs";
|
||||||
import { AddInstanceFlow } from "./add_instance_flow.mjs";
|
import { AddInstanceFlow } from "./add_instance_flow.mjs";
|
||||||
import { InstanceDetailsDialog } from "./confirm_instance_details.mjs";
|
import { dialogDetailsFromInstance, dialogDetailsToInstance, InstanceDetailsDialog, InstanceDetailsDialogData } from "./confirm_instance_details.mjs";
|
||||||
import { findButtonOrFail, findDialogOrFail, findOlOrFail } from "./dom.mjs";
|
import { findButtonOrFail, findDialogOrFail, findOlOrFail } from "./dom.mjs";
|
||||||
import storageManager from "./storage_manager.mjs";
|
import storageManager, { Instance } from "./storage_manager.mjs";
|
||||||
|
|
||||||
let reordering = false;
|
let reordering = false;
|
||||||
|
let unsaved = false;
|
||||||
// Dragging code is a heavily modified version of https://stackoverflow.com/a/28962290
|
// Dragging code is a heavily modified version of https://stackoverflow.com/a/28962290
|
||||||
let elementBeingDragged: HTMLLIElement | undefined;
|
let elementBeingDragged: HTMLLIElement | undefined;
|
||||||
|
|
||||||
|
@ -20,12 +21,12 @@ const reorderButton = findButtonOrFail(document.body, "#reorder");
|
||||||
let instanceDetailsDialog = new InstanceDetailsDialog(detailsDialog, true);
|
let instanceDetailsDialog = new InstanceDetailsDialog(detailsDialog, true);
|
||||||
let addInstanceFlow = new AddInstanceFlow(addDialog, spinnerDialog, instanceDetailsDialog);
|
let addInstanceFlow = new AddInstanceFlow(addDialog, spinnerDialog, instanceDetailsDialog);
|
||||||
|
|
||||||
startAddInstanceFlowButton.addEventListener("click", e => addInstanceFlow.start());
|
startAddInstanceFlowButton.addEventListener("click", e => {
|
||||||
|
addInstanceFlow.start(false).then(_ => unsavedChanges());
|
||||||
saveButton.addEventListener("click", e => {
|
|
||||||
storageManager.save();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
saveButton.addEventListener("click", e => saveChanges());
|
||||||
|
|
||||||
reorderButton.addEventListener("click", () => {
|
reorderButton.addEventListener("click", () => {
|
||||||
reordering = !reordering;
|
reordering = !reordering;
|
||||||
if (!reordering) applyReordering();
|
if (!reordering) applyReordering();
|
||||||
|
@ -38,6 +39,26 @@ storageManager.addSaveCallback(updateInstanceList);
|
||||||
|
|
||||||
mainDialog.show();
|
mainDialog.show();
|
||||||
|
|
||||||
|
function saveChanges() {
|
||||||
|
storageManager.save();
|
||||||
|
unsaved = false;
|
||||||
|
saveButton.classList.remove("pulse-red");
|
||||||
|
}
|
||||||
|
|
||||||
|
function unsavedChanges() {
|
||||||
|
if (!unsaved) {
|
||||||
|
unsaved = true;
|
||||||
|
saveButton.classList.add("pulse-red");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function editInstance(instance: Instance) {
|
||||||
|
const data = dialogDetailsFromInstance(instance);
|
||||||
|
const newData = await instanceDetailsDialog.present(data);
|
||||||
|
dialogDetailsToInstance(newData, instance);
|
||||||
|
unsavedChanges();
|
||||||
|
}
|
||||||
|
|
||||||
function updateInstanceList() {
|
function updateInstanceList() {
|
||||||
instanceList.replaceChildren(); // Erase all child nodes
|
instanceList.replaceChildren(); // Erase all child nodes
|
||||||
instanceList.style.listStyleType = reordering ? "\"≡ \"" : "disc";
|
instanceList.style.listStyleType = reordering ? "\"≡ \"" : "disc";
|
||||||
|
@ -83,17 +104,7 @@ function updateInstanceList() {
|
||||||
const editLink = document.createElement("a");
|
const editLink = document.createElement("a");
|
||||||
editLink.innerText = `Edit`;
|
editLink.innerText = `Edit`;
|
||||||
editLink.href = "#";
|
editLink.href = "#";
|
||||||
editLink.addEventListener("click", e => {
|
editLink.addEventListener("click", e => editInstance(instance));
|
||||||
const host = parseHost(instance.origin)!;
|
|
||||||
populateInstanceDetailsDialog(
|
|
||||||
instance.name,
|
|
||||||
host.host,
|
|
||||||
host.secure,
|
|
||||||
instance.software,
|
|
||||||
instance.iconURL ?? null
|
|
||||||
);
|
|
||||||
showInstanceDetailsDialog();
|
|
||||||
});
|
|
||||||
const deleteLink = document.createElement("a");
|
const deleteLink = document.createElement("a");
|
||||||
deleteLink.innerText = `Delete`;
|
deleteLink.innerText = `Delete`;
|
||||||
deleteLink.href = "#";
|
deleteLink.href = "#";
|
||||||
|
@ -127,4 +138,5 @@ function applyReordering() {
|
||||||
indices.push(parseInt(option));
|
indices.push(parseInt(option));
|
||||||
}
|
}
|
||||||
storageManager.storage.instances = indices.map(i => storageManager.storage.instances[i]);
|
storageManager.storage.instances = indices.map(i => storageManager.storage.instances[i]);
|
||||||
|
unsavedChanges();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,17 @@
|
||||||
// This file handles the "Confirm instance details" dialog
|
// This file handles the "Confirm instance details" dialog
|
||||||
|
|
||||||
|
import { parseHost } from "./add_an_instance.mjs";
|
||||||
import { FormDialog, ONCE } from "./dialog.mjs";
|
import { FormDialog, ONCE } from "./dialog.mjs";
|
||||||
import { findButtonOrFail, findFormOrFail, findImageOrFail, findInputOrFail, findSelectOrFail } from "./dom.mjs";
|
import { findButtonOrFail, findFormOrFail, findImageOrFail, findInputOrFail, findSelectOrFail } from "./dom.mjs";
|
||||||
import knownSoftware from "./known_software.mjs";
|
import knownSoftware from "./known_software.mjs";
|
||||||
|
import { Instance } from "./storage_manager.mjs";
|
||||||
|
|
||||||
const blankImage = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
|
const blankImage = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
|
||||||
|
|
||||||
|
export function mergeHost(host: string, secure: boolean): string {
|
||||||
|
return `http${secure ? "s" : ""}://${host}`;
|
||||||
|
}
|
||||||
|
|
||||||
export type InstanceDetailsDialogData = {
|
export type InstanceDetailsDialogData = {
|
||||||
name: string,
|
name: string,
|
||||||
host: string,
|
host: string,
|
||||||
|
@ -14,6 +20,25 @@ export type InstanceDetailsDialogData = {
|
||||||
iconURL: string | null
|
iconURL: string | null
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function dialogDetailsFromInstance(instance: Instance): InstanceDetailsDialogData {
|
||||||
|
const host = parseHost(instance.origin)!;
|
||||||
|
return {
|
||||||
|
name: instance.name,
|
||||||
|
host: host.host,
|
||||||
|
hostSecure: host.secure,
|
||||||
|
software: instance.software,
|
||||||
|
iconURL: instance.iconURL ?? null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function dialogDetailsToInstance(data: InstanceDetailsDialogData, instance: Partial<Instance>): Instance {
|
||||||
|
instance.name = data.name;
|
||||||
|
instance.origin = mergeHost(data.host, data.hostSecure);
|
||||||
|
instance.software = data.software;
|
||||||
|
instance.iconURL = data.iconURL ?? undefined;
|
||||||
|
return instance as Instance;
|
||||||
|
}
|
||||||
|
|
||||||
export class InstanceDetailsDialog extends FormDialog {
|
export class InstanceDetailsDialog extends FormDialog {
|
||||||
protected instanceName: HTMLInputElement;
|
protected instanceName: HTMLInputElement;
|
||||||
protected instanceHost: HTMLInputElement;
|
protected instanceHost: HTMLInputElement;
|
||||||
|
|
|
@ -31,7 +31,7 @@ if (!autoRedirect()) {
|
||||||
mainDialog.show();
|
mainDialog.show();
|
||||||
};
|
};
|
||||||
|
|
||||||
startAddInstanceFlowButton.addEventListener("click", e => addInstanceFlow?.start());
|
startAddInstanceFlowButton.addEventListener("click", e => addInstanceFlow?.start(true));
|
||||||
|
|
||||||
redirectButton.addEventListener("click", e => {
|
redirectButton.addEventListener("click", e => {
|
||||||
// Can be assumed to not fail because the button is disabled if there are no options and the first one is selected by default
|
// Can be assumed to not fail because the button is disabled if there are no options and the first one is selected by default
|
||||||
|
|
|
@ -185,3 +185,17 @@ abbr[title] {
|
||||||
.buttonPanel>* {
|
.buttonPanel>* {
|
||||||
margin-top: min(var(--xl), 6vh);
|
margin-top: min(var(--xl), 6vh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pulse-red {
|
||||||
|
animation: 1s ease-in-out 0s infinite alternate both running pulse-red-anim;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse-red-anim {
|
||||||
|
0% {
|
||||||
|
box-shadow: 0px 0px 0px var(--red);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
box-shadow: 0px 0px 20px var(--red);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue