improve the dev portal
This commit is contained in:
parent
9ae7a9c71f
commit
5abe4c6748
2 changed files with 246 additions and 356 deletions
|
@ -16,7 +16,7 @@ import{
|
||||||
wsjson,
|
wsjson,
|
||||||
}from"./jsontypes.js";
|
}from"./jsontypes.js";
|
||||||
import{ Member }from"./member.js";
|
import{ Member }from"./member.js";
|
||||||
import{ FormError, Settings }from"./settings.js";
|
import{ Form, FormError, Options, Settings }from"./settings.js";
|
||||||
import{ MarkDown }from"./markdown.js";
|
import{ MarkDown }from"./markdown.js";
|
||||||
|
|
||||||
const wsCodesRetry = new Set([4000, 4003, 4005, 4007, 4008, 4009]);
|
const wsCodesRetry = new Set([4000, 4003, 4005, 4007, 4008, 4009]);
|
||||||
|
@ -1286,349 +1286,156 @@ class Localuser{
|
||||||
{
|
{
|
||||||
const devPortal = settings.addButton("Developer Portal");
|
const devPortal = settings.addButton("Developer Portal");
|
||||||
|
|
||||||
const teamsRes = await fetch(this.info.api + "/teams", {
|
fetch(this.info.api + "/teams", {
|
||||||
headers: this.headers,
|
headers: this.headers,
|
||||||
});
|
}).then(async (teamsRes)=>{
|
||||||
const teams = await teamsRes.json();
|
const teams = await teamsRes.json();
|
||||||
|
|
||||||
devPortal.addButtonInput("", "Create application", ()=>{
|
devPortal.addButtonInput("", "Create application", ()=>{
|
||||||
const form = devPortal.addSubForm(
|
const form = devPortal.addSubForm(
|
||||||
"Create application",
|
"Create application",
|
||||||
(json: any)=>{
|
(json: any)=>{
|
||||||
if(json.message) form.error("name", json.message);
|
if(json.message) form.error("name", json.message);
|
||||||
else{
|
else{
|
||||||
devPortal.returnFromSub();
|
devPortal.returnFromSub();
|
||||||
this.manageApplication(json.id);
|
this.manageApplication(json.id);
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fetchURL: this.info.api + "/applications",
|
|
||||||
headers: this.headers,
|
|
||||||
method: "POST",
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
form.addTextInput("Name", "name", { required: true });
|
|
||||||
form.addSelect(
|
|
||||||
"Team",
|
|
||||||
"team_id",
|
|
||||||
["Personal", ...teams.map((team: { name: string })=>team.name)],
|
|
||||||
{
|
|
||||||
defaultIndex: 0,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const appListContainer = document.createElement("div");
|
|
||||||
appListContainer.id = "app-list-container";
|
|
||||||
fetch(this.info.api + "/applications", {
|
|
||||||
headers: this.headers,
|
|
||||||
})
|
|
||||||
.then(r=>r.json())
|
|
||||||
.then(json=>{
|
|
||||||
json.forEach(
|
|
||||||
(application: {
|
|
||||||
cover_image: any;
|
|
||||||
icon: any;
|
|
||||||
id: string | undefined;
|
|
||||||
name: string | number;
|
|
||||||
bot: any;
|
|
||||||
})=>{
|
|
||||||
const container = document.createElement("div");
|
|
||||||
|
|
||||||
if(application.cover_image || application.icon){
|
|
||||||
const cover = document.createElement("img");
|
|
||||||
cover.crossOrigin = "anonymous";
|
|
||||||
cover.src =
|
|
||||||
this.info.cdn +
|
|
||||||
"/app-icons/" +
|
|
||||||
application.id +
|
|
||||||
"/" +
|
|
||||||
(application.cover_image || application.icon) +
|
|
||||||
".png?size=256";
|
|
||||||
cover.alt = "";
|
|
||||||
cover.loading = "lazy";
|
|
||||||
container.appendChild(cover);
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fetchURL: this.info.api + "/applications",
|
||||||
|
headers: this.headers,
|
||||||
|
method: "POST",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const name = document.createElement("h2");
|
form.addTextInput("Name", "name", { required: true });
|
||||||
name.textContent =
|
form.addSelect(
|
||||||
application.name + (application.bot ? " (Bot)" : "");
|
"Team",
|
||||||
container.appendChild(name);
|
"team_id",
|
||||||
|
["Personal", ...teams.map((team: { name: string })=>team.name)],
|
||||||
container.addEventListener("click", async ()=>{
|
{
|
||||||
this.manageApplication(application.id);
|
defaultIndex: 0,
|
||||||
});
|
|
||||||
appListContainer.appendChild(container);
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
devPortal.addHTMLArea(appListContainer);
|
|
||||||
|
const appListContainer = document.createElement("div");
|
||||||
|
appListContainer.id = "app-list-container";
|
||||||
|
fetch(this.info.api + "/applications", {
|
||||||
|
headers: this.headers,
|
||||||
|
})
|
||||||
|
.then(r=>r.json())
|
||||||
|
.then(json=>{
|
||||||
|
json.forEach(
|
||||||
|
(application: {
|
||||||
|
cover_image: any;
|
||||||
|
icon: any;
|
||||||
|
id: string | undefined;
|
||||||
|
name: string | number;
|
||||||
|
bot: any;
|
||||||
|
})=>{
|
||||||
|
const container = document.createElement("div");
|
||||||
|
|
||||||
|
if(application.cover_image || application.icon){
|
||||||
|
const cover = document.createElement("img");
|
||||||
|
cover.crossOrigin = "anonymous";
|
||||||
|
cover.src =
|
||||||
|
this.info.cdn +
|
||||||
|
"/app-icons/" +
|
||||||
|
application.id +
|
||||||
|
"/" +
|
||||||
|
(application.cover_image || application.icon) +
|
||||||
|
".png?size=256";
|
||||||
|
cover.alt = "";
|
||||||
|
cover.loading = "lazy";
|
||||||
|
container.appendChild(cover);
|
||||||
|
}
|
||||||
|
|
||||||
|
const name = document.createElement("h2");
|
||||||
|
name.textContent = application.name + (application.bot ? " (Bot)" : "");
|
||||||
|
container.appendChild(name);
|
||||||
|
|
||||||
|
container.addEventListener("click", async ()=>{
|
||||||
|
this.manageApplication(application.id,devPortal);
|
||||||
|
});
|
||||||
|
appListContainer.appendChild(container);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
devPortal.addHTMLArea(appListContainer);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
settings.show();
|
settings.show();
|
||||||
}
|
}
|
||||||
async manageApplication(appId = ""){
|
readonly botTokens:Map<string,string>=new Map();
|
||||||
|
async manageApplication(appId = "", container:Options){
|
||||||
const res = await fetch(this.info.api + "/applications/" + appId, {
|
const res = await fetch(this.info.api + "/applications/" + appId, {
|
||||||
headers: this.headers,
|
headers: this.headers,
|
||||||
});
|
});
|
||||||
const json = await res.json();
|
const json = await res.json();
|
||||||
|
|
||||||
const fields: any = {};
|
const fields: any = {};
|
||||||
const appDialog = new Dialog([
|
const form=container.addSubForm(json.name,()=>{},{
|
||||||
"vdiv",
|
fetchURL:this.info.api + "/applications/" + appId,
|
||||||
["title", "Editing " + json.name],
|
method:"PATCH",
|
||||||
[
|
headers:this.headers
|
||||||
"vdiv",
|
});
|
||||||
[
|
form.addTextInput("Application name:","name",{initText:json.name});
|
||||||
"textbox",
|
form.addMDInput("Description:","description",{initText:json.description});
|
||||||
"Application name:",
|
form.addFileInput("Icon:","icon");
|
||||||
json.name,
|
form.addTextInput("Privacy policy URL:","privacy_policy_url",{initText:json.privacy_policy_url});
|
||||||
(event: Event)=>{
|
form.addTextInput("Terms of Service URL:","terms_of_service_url",{initText:json.terms_of_service_url});
|
||||||
const target = event.target as HTMLInputElement;
|
form.addCheckboxInput("Make bot publicly inviteable?","bot_public",{initState:json.bot_public});
|
||||||
fields.name = target.value;
|
form.addCheckboxInput("Require code grant to invite the bot?","bot_require_code_grant",{initState:json.bot_require_code_grant});
|
||||||
},
|
form.addButtonInput("",(json.bot ? "Manage" : "Add")+" bot",async ()=>{
|
||||||
],
|
if(!json.bot){
|
||||||
[
|
if(!confirm("Are you sure you want to add a bot to this application? There's no going back.")){
|
||||||
"mdbox",
|
return;
|
||||||
"Description:",
|
}
|
||||||
json.description,
|
const updateRes = await fetch(
|
||||||
(event: Event)=>{
|
this.info.api + "/applications/" + appId + "/bot",
|
||||||
const target = event.target as HTMLInputElement;
|
{
|
||||||
fields.description = target.value;
|
method: "POST",
|
||||||
},
|
headers: this.headers,
|
||||||
],
|
}
|
||||||
[
|
);
|
||||||
"vdiv",
|
const updateJSON = await updateRes.json();
|
||||||
json.icon
|
this.botTokens.set(appId,updateJSON.token);
|
||||||
? [
|
}
|
||||||
"img",
|
this.manageBot(appId,form);
|
||||||
this.info.cdn +
|
})
|
||||||
"/app-icons/" +
|
|
||||||
appId +
|
|
||||||
"/" +
|
|
||||||
json.icon +
|
|
||||||
".png?size=128",
|
|
||||||
[128, 128],
|
|
||||||
]
|
|
||||||
: ["text", "No icon"],
|
|
||||||
[
|
|
||||||
"fileupload",
|
|
||||||
"Application icon:",
|
|
||||||
event=>{
|
|
||||||
const reader = new FileReader();
|
|
||||||
const files = (event.target as HTMLInputElement).files;
|
|
||||||
if(files){
|
|
||||||
reader.readAsDataURL(files[0]);
|
|
||||||
reader.onload = ()=>{
|
|
||||||
fields.icon = reader.result;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
],
|
|
||||||
],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"hdiv",
|
|
||||||
[
|
|
||||||
"textbox",
|
|
||||||
"Privacy policy URL:",
|
|
||||||
json.privacy_policy_url || "",
|
|
||||||
(event: Event)=>{
|
|
||||||
const target = event.target as HTMLInputElement;
|
|
||||||
fields.privacy_policy_url = target.value;
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"textbox",
|
|
||||||
"Terms of Service URL:",
|
|
||||||
json.terms_of_service_url || "",
|
|
||||||
(event: Event)=>{
|
|
||||||
const target = event.target as HTMLInputElement;
|
|
||||||
fields.terms_of_service_url = target.value;
|
|
||||||
},
|
|
||||||
],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"hdiv",
|
|
||||||
[
|
|
||||||
"checkbox",
|
|
||||||
"Make bot publicly inviteable?",
|
|
||||||
json.bot_public,
|
|
||||||
(event: Event)=>{
|
|
||||||
const target = event.target as HTMLInputElement;
|
|
||||||
fields.bot_public = target.checked;
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"checkbox",
|
|
||||||
"Require code grant to invite the bot?",
|
|
||||||
json.bot_require_code_grant,
|
|
||||||
(event: Event)=>{
|
|
||||||
const target = event.target as HTMLInputElement;
|
|
||||||
fields.bot_require_code_grant = target.checked;
|
|
||||||
},
|
|
||||||
],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"hdiv",
|
|
||||||
[
|
|
||||||
"button",
|
|
||||||
"",
|
|
||||||
"Save changes",
|
|
||||||
async ()=>{
|
|
||||||
const updateRes = await fetch(
|
|
||||||
this.info.api + "/applications/" + appId,
|
|
||||||
{
|
|
||||||
method: "PATCH",
|
|
||||||
headers: this.headers,
|
|
||||||
body: JSON.stringify(fields),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if(updateRes.ok) appDialog.hide();
|
|
||||||
else{
|
|
||||||
const updateJSON = await updateRes.json();
|
|
||||||
alert("An error occurred: " + updateJSON.message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"button",
|
|
||||||
"",
|
|
||||||
(json.bot ? "Manage" : "Add") + " bot",
|
|
||||||
async ()=>{
|
|
||||||
if(!json.bot){
|
|
||||||
if(
|
|
||||||
!confirm(
|
|
||||||
"Are you sure you want to add a bot to this application? There's no going back."
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const updateRes = await fetch(
|
|
||||||
this.info.api + "/applications/" + appId + "/bot",
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: this.headers,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const updateJSON = await updateRes.json();
|
|
||||||
alert("Bot token:\n" + updateJSON.token);
|
|
||||||
}
|
|
||||||
|
|
||||||
appDialog.hide();
|
|
||||||
this.manageBot(appId);
|
|
||||||
},
|
|
||||||
],
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
appDialog.show();
|
|
||||||
}
|
}
|
||||||
async manageBot(appId = ""){
|
async manageBot(appId = "",container:Form){
|
||||||
const res = await fetch(this.info.api + "/applications/" + appId, {
|
const res = await fetch(this.info.api + "/applications/" + appId, {
|
||||||
headers: this.headers,
|
headers: this.headers,
|
||||||
});
|
});
|
||||||
const json = await res.json();
|
const json = await res.json();
|
||||||
if(!json.bot)
|
if(!json.bot){
|
||||||
return alert(
|
return alert("For some reason, this application doesn't have a bot (yet).");
|
||||||
"For some reason, this application doesn't have a bot (yet)."
|
}
|
||||||
|
const form=container.addSubForm("Editing bot "+json.bot.username,()=>{},{
|
||||||
|
method:"PATCH",
|
||||||
|
fetchURL:this.info.api + "/applications/" + appId + "/bot",
|
||||||
|
headers:this.headers
|
||||||
|
});
|
||||||
|
form.addTextInput("Bot username:","username",{initText:json.bot.username});
|
||||||
|
form.addFileInput("Bot avatar:","avatar");
|
||||||
|
form.addButtonInput("Reset Token:","Reset",async ()=>{
|
||||||
|
if(!confirm("Are you sure you want to reset the bot token? Your bot will stop working until you update it.")){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const updateRes = await fetch(
|
||||||
|
this.info.api + "/applications/" + appId + "/bot/reset",
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: this.headers,
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
const updateJSON = await updateRes.json();
|
||||||
const fields: any = {
|
text.setText("Token: "+updateJSON.token);
|
||||||
username: json.bot.username,
|
this.botTokens.set(appId,updateJSON.token);
|
||||||
avatar: json.bot.avatar
|
});
|
||||||
? this.info.cdn +
|
const text=form.addText(this.botTokens.has(appId)?"Token: "+this.botTokens.get(appId):"Token: *****************")
|
||||||
"/app-icons/" +
|
|
||||||
appId +
|
|
||||||
"/" +
|
|
||||||
json.bot.avatar +
|
|
||||||
".png?size=256"
|
|
||||||
: "",
|
|
||||||
};
|
|
||||||
const botDialog = new Dialog([
|
|
||||||
"vdiv",
|
|
||||||
["title", "Editing bot: " + json.bot.username],
|
|
||||||
[
|
|
||||||
"hdiv",
|
|
||||||
[
|
|
||||||
"textbox",
|
|
||||||
"Bot username:",
|
|
||||||
json.bot.username,
|
|
||||||
(event: Event)=>{
|
|
||||||
const target = event.target as HTMLInputElement;
|
|
||||||
fields.username = target.value;
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"vdiv",
|
|
||||||
fields.avatar
|
|
||||||
? ["img", fields.avatar, [128, 128]]
|
|
||||||
: ["text", "No avatar"],
|
|
||||||
[
|
|
||||||
"fileupload",
|
|
||||||
"Bot avatar:",
|
|
||||||
event=>{
|
|
||||||
const reader = new FileReader();
|
|
||||||
const files = (event.target as HTMLInputElement).files;
|
|
||||||
if(files){
|
|
||||||
const file = files[0];
|
|
||||||
reader.readAsDataURL(file);
|
|
||||||
reader.onload = ()=>{
|
|
||||||
fields.avatar = reader.result;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
],
|
|
||||||
],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"hdiv",
|
|
||||||
[
|
|
||||||
"button",
|
|
||||||
"",
|
|
||||||
"Save changes",
|
|
||||||
async ()=>{
|
|
||||||
const updateRes = await fetch(
|
|
||||||
this.info.api + "/applications/" + appId + "/bot",
|
|
||||||
{
|
|
||||||
method: "PATCH",
|
|
||||||
headers: this.headers,
|
|
||||||
body: JSON.stringify(fields),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if(updateRes.ok) botDialog.hide();
|
|
||||||
else{
|
|
||||||
const updateJSON = await updateRes.json();
|
|
||||||
alert("An error occurred: " + updateJSON.message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"button",
|
|
||||||
"",
|
|
||||||
"Reset token",
|
|
||||||
async ()=>{
|
|
||||||
if(
|
|
||||||
!confirm(
|
|
||||||
"Are you sure you want to reset the bot token? Your bot will stop working until you update it."
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const updateRes = await fetch(
|
|
||||||
this.info.api + "/applications/" + appId + "/bot/reset",
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: this.headers,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const updateJSON = await updateRes.json();
|
|
||||||
alert("New token:\n" + updateJSON.token);
|
|
||||||
botDialog.hide();
|
|
||||||
},
|
|
||||||
],
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
botDialog.show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------- resolving members code -----------
|
//---------- resolving members code -----------
|
||||||
|
|
|
@ -131,14 +131,24 @@ class SettingsText implements OptionsElement<void>{
|
||||||
readonly onSubmit!: (str: string) => void;
|
readonly onSubmit!: (str: string) => void;
|
||||||
value!: void;
|
value!: void;
|
||||||
readonly text: string;
|
readonly text: string;
|
||||||
|
elm!:WeakRef<HTMLSpanElement>;
|
||||||
constructor(text: string){
|
constructor(text: string){
|
||||||
this.text = text;
|
this.text = text;
|
||||||
}
|
}
|
||||||
generateHTML(): HTMLSpanElement{
|
generateHTML(): HTMLSpanElement{
|
||||||
const span = document.createElement("span");
|
const span = document.createElement("span");
|
||||||
span.innerText = this.text;
|
span.innerText = this.text;
|
||||||
|
this.elm=new WeakRef(span);
|
||||||
return span;
|
return span;
|
||||||
}
|
}
|
||||||
|
setText(text:string){
|
||||||
|
if(this.elm){
|
||||||
|
const span=this.elm.deref();
|
||||||
|
if(span){
|
||||||
|
span.innerText=text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
watchForChange(){}
|
watchForChange(){}
|
||||||
submit(){}
|
submit(){}
|
||||||
}
|
}
|
||||||
|
@ -516,17 +526,26 @@ class Options implements OptionsElement<void>{
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
subOptions: Options | Form | undefined;
|
subOptions: Options | Form | undefined;
|
||||||
|
genTop(){
|
||||||
|
const container = this.container.deref();
|
||||||
|
if(container){
|
||||||
|
if(this.isTop()){
|
||||||
|
this.generateContainter();
|
||||||
|
}else if(this.owner instanceof Options){
|
||||||
|
this.owner.genTop();
|
||||||
|
}else{
|
||||||
|
(this.owner as Form).owner.genTop();
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
throw new Error(
|
||||||
|
"Tried to make a sub menu when the options weren't rendered"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
addSubOptions(name: string, { ltr = false } = {}){
|
addSubOptions(name: string, { ltr = false } = {}){
|
||||||
const options = new Options(name, this, { ltr });
|
const options = new Options(name, this, { ltr });
|
||||||
this.subOptions = options;
|
this.subOptions = options;
|
||||||
const container = this.container.deref();
|
this.genTop();
|
||||||
if(container){
|
|
||||||
this.generateContainter();
|
|
||||||
}else{
|
|
||||||
throw new Error(
|
|
||||||
"Tried to make a subOptions when the options weren't rendered"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
addSubForm(
|
addSubForm(
|
||||||
|
@ -550,19 +569,12 @@ class Options implements OptionsElement<void>{
|
||||||
traditionalSubmit,
|
traditionalSubmit,
|
||||||
});
|
});
|
||||||
this.subOptions = options;
|
this.subOptions = options;
|
||||||
const container = this.container.deref();
|
this.genTop();
|
||||||
if(container){
|
|
||||||
this.generateContainter();
|
|
||||||
}else{
|
|
||||||
throw new Error(
|
|
||||||
"Tried to make a subForm when the options weren't rendered"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
returnFromSub(){
|
returnFromSub(){
|
||||||
this.subOptions = undefined;
|
this.subOptions = undefined;
|
||||||
this.generateContainter();
|
this.genTop();
|
||||||
}
|
}
|
||||||
addSelect(
|
addSelect(
|
||||||
label: string,
|
label: string,
|
||||||
|
@ -710,36 +722,70 @@ class Options implements OptionsElement<void>{
|
||||||
div.append(container);
|
div.append(container);
|
||||||
return div;
|
return div;
|
||||||
}
|
}
|
||||||
|
generateName():(HTMLElement|string)[]{
|
||||||
|
const build:(HTMLElement|string)[]=[];
|
||||||
|
if(this.subOptions){
|
||||||
|
if(this.name!==""){
|
||||||
|
const name = document.createElement("span");
|
||||||
|
name.innerText = this.name;
|
||||||
|
name.classList.add("clickable");
|
||||||
|
name.onclick = ()=>{
|
||||||
|
this.returnFromSub();
|
||||||
|
};
|
||||||
|
build.push(name);
|
||||||
|
build.push(" > ");
|
||||||
|
}
|
||||||
|
if(this.subOptions instanceof Options){
|
||||||
|
build.push(...this.subOptions.generateName());
|
||||||
|
}else{
|
||||||
|
build.push(...this.subOptions.options.generateName());
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
const name = document.createElement("span");
|
||||||
|
name.innerText = this.name;
|
||||||
|
build.push(name);
|
||||||
|
}
|
||||||
|
return build;
|
||||||
|
}
|
||||||
|
isTop(){
|
||||||
|
(this.owner instanceof Form&&this.owner.owner.subOptions!==this.owner),
|
||||||
|
(this.owner instanceof Settings),
|
||||||
|
(this.owner instanceof Buttons));
|
||||||
|
return (this.owner instanceof Options&&this.owner.subOptions!==this)||
|
||||||
|
(this.owner instanceof Form&&this.owner.owner.subOptions!==this.owner)||
|
||||||
|
(this.owner instanceof Settings)||
|
||||||
|
(this.owner instanceof Buttons);
|
||||||
|
}
|
||||||
generateContainter(){
|
generateContainter(){
|
||||||
const container = this.container.deref();
|
const container = this.container.deref();
|
||||||
if(container){
|
if(container){
|
||||||
const title = this.title.deref();
|
const title = this.title.deref();
|
||||||
if(title) title.innerHTML = "";
|
if(title) title.innerHTML = "";
|
||||||
container.innerHTML = "";
|
container.innerHTML = "";
|
||||||
if(this.subOptions){
|
if(this.isTop()){
|
||||||
container.append(this.subOptions.generateHTML()); //more code needed, though this is enough for now
|
|
||||||
if(title){
|
if(title){
|
||||||
const name = document.createElement("span");
|
const elms=this.generateName();
|
||||||
name.innerText = this.name;
|
title.append(...elms);
|
||||||
name.classList.add("clickable");
|
|
||||||
name.onclick = ()=>{
|
|
||||||
this.returnFromSub();
|
|
||||||
};
|
|
||||||
title.append(name, " > ", this.subOptions.name);
|
|
||||||
}
|
}
|
||||||
}else{
|
}
|
||||||
|
if(!this.subOptions){
|
||||||
for(const thing of this.options){
|
for(const thing of this.options){
|
||||||
this.generate(thing);
|
this.generate(thing);
|
||||||
}
|
}
|
||||||
if(title){
|
}else{
|
||||||
title.innerText = this.name;
|
container.append(this.subOptions.generateHTML());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(title && title.innerText !== ""){
|
if(title && title.innerText !== ""){
|
||||||
title.classList.add("settingstitle");
|
title.classList.add("settingstitle");
|
||||||
}else if(title){
|
}else if(title){
|
||||||
title.classList.remove("settingstitle");
|
title.classList.remove("settingstitle");
|
||||||
}
|
}
|
||||||
|
if(this.owner instanceof Form&&this.owner.button){
|
||||||
|
const button=this.owner.button.deref();
|
||||||
|
if(button){
|
||||||
|
button.hidden=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
console.warn("tried to generate container, but it did not exist");
|
console.warn("tried to generate container, but it did not exist");
|
||||||
}
|
}
|
||||||
|
@ -818,7 +864,7 @@ class Form implements OptionsElement<object>{
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.method = method;
|
this.method = method;
|
||||||
this.submitText = submitText;
|
this.submitText = submitText;
|
||||||
this.options = new Options("", this, { ltr });
|
this.options = new Options(name, this, { ltr });
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
this.fetchURL = fetchURL;
|
this.fetchURL = fetchURL;
|
||||||
this.headers = headers;
|
this.headers = headers;
|
||||||
|
@ -829,6 +875,36 @@ class Form implements OptionsElement<object>{
|
||||||
//the value can't really be anything, but I don't care enough to fix this
|
//the value can't really be anything, but I don't care enough to fix this
|
||||||
this.values[key] = value;
|
this.values[key] = value;
|
||||||
}
|
}
|
||||||
|
addSubOptions(name: string, { ltr = false } = {}){
|
||||||
|
if(this.button&&this.button.deref()){
|
||||||
|
(this.button.deref() as HTMLElement).hidden=true;
|
||||||
|
}
|
||||||
|
return this.options.addSubOptions(name,{ltr});
|
||||||
|
}
|
||||||
|
addSubForm(
|
||||||
|
name: string,
|
||||||
|
onSubmit: (arg1: object) => void,
|
||||||
|
{
|
||||||
|
ltr = false,
|
||||||
|
submitText = "Submit",
|
||||||
|
fetchURL = "",
|
||||||
|
headers = {},
|
||||||
|
method = "POST",
|
||||||
|
traditionalSubmit = false,
|
||||||
|
} = {}
|
||||||
|
){
|
||||||
|
if(this.button&&this.button.deref()){
|
||||||
|
console.warn("hidden");
|
||||||
|
(this.button.deref() as HTMLElement).hidden=true;
|
||||||
|
}
|
||||||
|
return this.options.addSubForm(name,onSubmit,{ltr,submitText,fetchURL,headers,method,traditionalSubmit});
|
||||||
|
}
|
||||||
|
generateContainter(){
|
||||||
|
this.options.generateContainter();
|
||||||
|
if((this.options.isTop())&&this.button&&this.button.deref()){
|
||||||
|
(this.button.deref() as HTMLElement).hidden=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
addSelect(
|
addSelect(
|
||||||
label: string,
|
label: string,
|
||||||
formName: string,
|
formName: string,
|
||||||
|
@ -903,7 +979,9 @@ class Form implements OptionsElement<object>{
|
||||||
}
|
}
|
||||||
return mdInput;
|
return mdInput;
|
||||||
}
|
}
|
||||||
|
addButtonInput(label:string,textContent:string,onSubmit:()=>void){
|
||||||
|
return this.options.addButtonInput(label,textContent,onSubmit);
|
||||||
|
}
|
||||||
addCheckboxInput(
|
addCheckboxInput(
|
||||||
label: string,
|
label: string,
|
||||||
formName: string,
|
formName: string,
|
||||||
|
@ -917,11 +995,12 @@ class Form implements OptionsElement<object>{
|
||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
addText(str: string){
|
addText(str: string){
|
||||||
this.options.addText(str);
|
return this.options.addText(str);
|
||||||
}
|
}
|
||||||
addTitle(str: string){
|
addTitle(str: string){
|
||||||
this.options.addTitle(str);
|
this.options.addTitle(str);
|
||||||
}
|
}
|
||||||
|
button!:WeakRef<HTMLButtonElement>;
|
||||||
generateHTML(): HTMLElement{
|
generateHTML(): HTMLElement{
|
||||||
const div = document.createElement("div");
|
const div = document.createElement("div");
|
||||||
div.append(this.options.generateHTML());
|
div.append(this.options.generateHTML());
|
||||||
|
@ -933,6 +1012,10 @@ class Form implements OptionsElement<object>{
|
||||||
};
|
};
|
||||||
button.textContent = this.submitText;
|
button.textContent = this.submitText;
|
||||||
div.append(button);
|
div.append(button);
|
||||||
|
if(this.options.subOptions){
|
||||||
|
button.hidden=true;
|
||||||
|
}
|
||||||
|
this.button=new WeakRef(button);
|
||||||
}
|
}
|
||||||
return div;
|
return div;
|
||||||
}
|
}
|
||||||
|
@ -1110,4 +1193,4 @@ class Settings extends Buttons{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export{ Settings, OptionsElement, Buttons, Options };
|
export{ Settings, OptionsElement, Buttons, Options,Form };
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue