This commit is contained in:
parent
bc7e388f04
commit
027faf8371
4 changed files with 138 additions and 29 deletions
|
@ -30,7 +30,17 @@
|
|||
instance.<br>
|
||||
<img src="/static/down_arrow.svg" alt="" class="medium-height" />
|
||||
<p id="noInstance">You currently don't have any instances. You should add one!</p>
|
||||
<form id="instanceSelectForm" class="align-start wfit-content"></form>
|
||||
<form id="instanceSelectForm" class="align-start wfit-content">
|
||||
<ol id="preferredList" class="margin-none" hidden></ol>
|
||||
<div id="forks" hidden>
|
||||
<p class="align-center margin-none-bottom">Other <span id="forkOf"></span> forks</p>
|
||||
<ol id="forksList" class="margin-none"></ol>
|
||||
</div>
|
||||
<div id="others" hidden>
|
||||
<p class="align-center margin-none-bottom">Other instances</p>
|
||||
<ol id="othersList" class="margin-none"></ol>
|
||||
</div>
|
||||
</form>
|
||||
<br>
|
||||
<button id="startAddInstanceFlow">Add an instance</button>
|
||||
</center>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { AddInstanceFlow } from "./add_instance_flow.mjs";
|
||||
import { findButtonOrFail, findDialogOrFail, findFormOrFail, findInputOrFail, findParagraphOrFail, findPreOrFail, findSpanOrFail } from "./dom.mjs";
|
||||
import { findButtonOrFail, findDialogOrFail, findDivOrFail, findFormOrFail, findInputOrFail, findOlOrFail, findParagraphOrFail, findPreOrFail, findSpanOrFail } from "./dom.mjs";
|
||||
import knownSoftware, { getName } from "./known_software.mjs";
|
||||
import storageManager from "./storage_manager.mjs";
|
||||
import storageManager, { Instance } from "./storage_manager.mjs";
|
||||
|
||||
const RADIO_BUTTON_NAME = "instanceSelect";
|
||||
|
||||
|
@ -13,6 +13,12 @@ const addDialog = findDialogOrFail(document.body, "#addInstance");
|
|||
const spinnerDialog = findDialogOrFail(document.body, "#spinner");
|
||||
const detailsDialog = findDialogOrFail(document.body, "#instanceDetails");
|
||||
const instanceSelectForm = findFormOrFail(document.body, "#instanceSelectForm");
|
||||
const preferredList = findOlOrFail(document.body, "#preferredList");
|
||||
const forksDiv = findDivOrFail(document.body, "#forks");
|
||||
const forkOfSpan = findSpanOrFail(document.body, "#forkOf");
|
||||
const forksList = findOlOrFail(document.body, "#forksList");
|
||||
const othersDiv = findDivOrFail(document.body, "#others");
|
||||
const othersList = findOlOrFail(document.body, "#othersList");
|
||||
const redirectButton = findButtonOrFail(document.body, "#redirect");
|
||||
const redirectAlwaysButton = findButtonOrFail(document.body, "#redirectAlways");
|
||||
const noInstanceParagraph = findParagraphOrFail(document.body, "#noInstance");
|
||||
|
@ -58,9 +64,60 @@ function updateNoInstanceHint() {
|
|||
storageManager.storage.instances.length > 0;
|
||||
}
|
||||
|
||||
function createInstanceSelectOptions() {
|
||||
instanceSelectForm.replaceChildren(); // Erase all child nodes
|
||||
type PreferenceGroups = {
|
||||
preferred: Instance[],
|
||||
forks?: {
|
||||
list: Instance[],
|
||||
of: string,
|
||||
},
|
||||
others: Instance[],
|
||||
};
|
||||
|
||||
function sortInstancesIntoPreferenceGroups(): PreferenceGroups {
|
||||
const targetID = getTargetSoftwareOrGroup();
|
||||
const pGroups: PreferenceGroups = {
|
||||
preferred: [],
|
||||
others: [],
|
||||
};
|
||||
// If targetID is a group
|
||||
if (knownSoftware.groups[targetID]) {
|
||||
for (const instance of storageManager.storage.instances) {
|
||||
const software = knownSoftware.software[instance.software];
|
||||
// If the instance's software is in the target group
|
||||
if (software.groups.includes(targetID)) {
|
||||
pGroups.preferred.push(instance);
|
||||
} else {
|
||||
pGroups.others.push(instance);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const isFork = knownSoftware.software[targetID].forkOf !== undefined;
|
||||
const forkOf = knownSoftware.software[targetID].forkOf ?? targetID;
|
||||
const hasForks = isFork || Object.values(knownSoftware.software).some(s => s.forkOf === forkOf);
|
||||
if (hasForks) {
|
||||
pGroups.forks = {
|
||||
list: [],
|
||||
of: forkOf,
|
||||
};
|
||||
}
|
||||
for (const instance of storageManager.storage.instances) {
|
||||
if (instance.software === targetID) {
|
||||
pGroups.preferred.push(instance);
|
||||
continue;
|
||||
}
|
||||
const software = knownSoftware.software[instance.software];
|
||||
// Checking pGroups.forks is the TypeScript safe way of checking hasForks
|
||||
if (pGroups.forks && (instance.software === forkOf || software.forkOf === forkOf)) {
|
||||
pGroups.forks.list.push(instance);
|
||||
continue;
|
||||
}
|
||||
pGroups.others.push(instance);
|
||||
}
|
||||
}
|
||||
return pGroups;
|
||||
}
|
||||
|
||||
function constructOptionFromInstance(instance: Instance): HTMLDivElement {
|
||||
const div = document.createElement("div");
|
||||
div.setAttribute("x-option", instance.origin);
|
||||
const radio = document.createElement("input");
|
||||
|
@ -84,8 +141,35 @@ function createInstanceSelectOptions() {
|
|||
label.appendChild(small);
|
||||
div.appendChild(radio);
|
||||
div.appendChild(label);
|
||||
instanceSelectForm.appendChild(div);
|
||||
return div;
|
||||
}
|
||||
|
||||
function createInstanceSelectOptions() {
|
||||
// Erase all child nodes
|
||||
preferredList.replaceChildren();
|
||||
forksList.replaceChildren();
|
||||
othersList.replaceChildren();
|
||||
|
||||
const { preferred, forks, others } = sortInstancesIntoPreferenceGroups();
|
||||
|
||||
preferredList.hidden = preferred.length === 0;
|
||||
for (const instance of preferred) {
|
||||
preferredList.appendChild(constructOptionFromInstance(instance));
|
||||
}
|
||||
|
||||
forksDiv.hidden = forks === undefined;
|
||||
if (forks) {
|
||||
forkOfSpan.innerText = getName(knownSoftware, forks.of) ?? forks.of;
|
||||
for (const instance of forks.list) {
|
||||
forksList.appendChild(constructOptionFromInstance(instance));
|
||||
}
|
||||
}
|
||||
|
||||
othersDiv.hidden = others.length === 0;
|
||||
for (const instance of others) {
|
||||
othersList.appendChild(constructOptionFromInstance(instance));
|
||||
}
|
||||
|
||||
const firstInput = instanceSelectForm.querySelector("input");
|
||||
if (firstInput) firstInput.checked = true;
|
||||
setRedirectButtonState(firstInput !== null);
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
// I would've LOVED to use generics for this but unfortunately that's not possible.
|
||||
// Type safety, but at what cost... >~< thanks TypeScript
|
||||
|
||||
export function findDivOrFail(on: Element, selector: string): HTMLDivElement {
|
||||
const element = on.querySelector(selector);
|
||||
if (!(element instanceof HTMLDivElement))
|
||||
throw new Error(`${selector} isn't a div`);
|
||||
return element;
|
||||
}
|
||||
|
||||
export function findSpanOrFail(on: Element, selector: string): HTMLSpanElement {
|
||||
const element = on.querySelector(selector);
|
||||
if (!(element instanceof HTMLSpanElement))
|
||||
|
|
|
@ -61,6 +61,10 @@ abbr[title] {
|
|||
text-align: start;
|
||||
}
|
||||
|
||||
.align-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.inline-block {
|
||||
display: inline-block;
|
||||
}
|
||||
|
@ -157,6 +161,10 @@ abbr[title] {
|
|||
margin-bottom: var(--large);
|
||||
}
|
||||
|
||||
.margin-none-bottom {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.square {
|
||||
aspect-ratio: 1;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue