diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml
new file mode 100644
index 0000000..d7ffab6
--- /dev/null
+++ b/.github/workflows/pages.yml
@@ -0,0 +1,42 @@
+name: Build and deploy Pages
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+ workflow_dispatch:
+
+permissions:
+ contents: read
+
+jobs:
+ build:
+ runs-on: ubuntu-slim
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 22
+ cache: npm
+ - uses: taiki-e/install-action@just
+ - run: npm ci
+ - run: just style
+ - run: just build
+ - uses: actions/upload-pages-artifact@v3
+ if: github.event_name != 'pull_request'
+ with:
+ path: dist
+
+ deploy:
+ if: github.event_name != 'pull_request'
+ needs: build
+ runs-on: ubuntu-slim
+ permissions:
+ pages: write
+ id-token: write
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ steps:
+ - id: deployment
+ uses: actions/deploy-pages@v4
diff --git a/.gitignore b/.gitignore
index 3d72576..f62cc61 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,11 @@
+# System files
.DS_Store
-.idea
\ No newline at end of file
+
+# Editor settings
+.idea/
+
+# Installed dependencies
+node_modules/
+
+# Generated site
+dist/
diff --git a/app/index.html b/app/index.html
new file mode 100644
index 0000000..742ed87
--- /dev/null
+++ b/app/index.html
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+ StartTreeV2 - Home
+
+
diff --git a/app/pages/edit.html b/app/pages/edit.html
new file mode 100644
index 0000000..d26f951
--- /dev/null
+++ b/app/pages/edit.html
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+ StartTreeV3 - Edit
+
+
+
diff --git a/app/pages/view.html b/app/pages/view.html
new file mode 100644
index 0000000..c578345
--- /dev/null
+++ b/app/pages/view.html
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+ StartTreeV3
+
+
diff --git a/js/helper/dragOptions.js b/app/src/helper/dragOptions.ts
similarity index 55%
rename from js/helper/dragOptions.js
rename to app/src/helper/dragOptions.ts
index ec912ee..677372d 100644
--- a/js/helper/dragOptions.js
+++ b/app/src/helper/dragOptions.ts
@@ -1,5 +1,8 @@
export default class DragOptions {
- constructor({ data, validDropzones }) {
+ data: string;
+ validDropzones: string[];
+
+ constructor({ data, validDropzones }: { data?: string; validDropzones?: string[] }) {
this.data = data ?? "";
this.validDropzones = validDropzones ?? []; // classes that this draggable can be dropped on
}
diff --git a/js/helper/jsurl.js b/app/src/helper/jsurl.ts
similarity index 82%
rename from js/helper/jsurl.js
rename to app/src/helper/jsurl.ts
index 37145ed..46957eb 100644
--- a/js/helper/jsurl.js
+++ b/app/src/helper/jsurl.ts
@@ -23,17 +23,17 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
//
-let stringify = function stringify(v) {
- function encode(s) {
+let stringify = function stringify(v: unknown): string | undefined {
+ function encode(s: string): string {
return !/[^\w-.]/.test(s)
? s
- : s.replace(/[^\w-.]/g, function (ch) {
+ : s.replace(/[^\w-.]/g, function (ch: string) {
if (ch === "$") return "!";
- ch = ch.charCodeAt(0);
+ const code = ch.charCodeAt(0);
// thanks to Douglas Crockford for the negative slice trick
- return ch < 0x100
- ? "*" + ("00" + ch.toString(16)).slice(-2)
- : "**" + ("0000" + ch.toString(16)).slice(-4);
+ return code < 0x100
+ ? "*" + ("00" + code.toString(16)).slice(-2)
+ : "**" + ("0000" + code.toString(16)).slice(-4);
});
}
@@ -59,8 +59,8 @@ let stringify = function stringify(v) {
return "~(" + (tmpAry.join("") || "~") + ")";
} else {
for (var key in v) {
- if (v.hasOwnProperty(key)) {
- var val = stringify(v[key]);
+ if (Object.prototype.hasOwnProperty.call(v, key)) {
+ var val = stringify((v as Record)[key]);
// skip undefined and functions
if (val) {
@@ -83,13 +83,13 @@ var reserved = {
null: null,
};
-let parse = function (s) {
- if (!s) return s;
- s = s.replace(/%(25)*27/g, "'");
+let parse = function (input: string | null): unknown {
+ if (!input) return input;
+ let s = input.replace(/%(25)*27/g, "'");
var i = 0,
len = s.length;
- function eat(expected) {
+ function eat(expected: string) {
if (s.charAt(i) !== expected)
throw new Error(
"bad JSURL syntax: expected " + expected + ", got " + (s && s.charAt(i))
@@ -123,7 +123,7 @@ let parse = function (s) {
return r + s.substring(beg, i);
}
- return (function parseOne() {
+ return (function parseOne(): unknown {
var result, ch, beg;
eat("~");
switch ((ch = s.charAt(i))) {
@@ -138,11 +138,11 @@ let parse = function (s) {
} while (s.charAt(i) === "~");
}
} else {
- result = {};
+ result = {} as Record;
if (s.charAt(i) !== ")") {
do {
var key = decode();
- result[key] = parseOne();
+ (result as Record)[key] = parseOne();
} while (s.charAt(i) === "~" && ++i);
}
}
@@ -159,7 +159,7 @@ let parse = function (s) {
if (/[\d\-]/.test(ch)) {
result = parseFloat(sub);
} else {
- result = reserved[sub];
+ result = reserved[sub as keyof typeof reserved];
if (typeof result === "undefined")
throw new Error("bad value keyword: " + sub);
}
diff --git a/js/helper/makeDraggable.js b/app/src/helper/makeDraggable.ts
similarity index 70%
rename from js/helper/makeDraggable.js
rename to app/src/helper/makeDraggable.ts
index 1bc5d2e..e3c774a 100644
--- a/js/helper/makeDraggable.js
+++ b/app/src/helper/makeDraggable.ts
@@ -1,3 +1,5 @@
+import DragOptions from "./dragOptions.js";
+export type DragAction = "dragstart" | "dragend" | "dragover" | "dragenter" | "dragleave" | "drop";
// ====================================================== //
// ==================== makeDraggable =================== //
// ====================================================== //
@@ -5,19 +7,19 @@
// helper method to make an element draggable, configured with DragOptions
let lastDropWasValid = false;
-export default (element, dragOptions, callback) => {
+export default (element: HTMLElement, dragOptions: DragOptions, callback: (type: DragAction, event: DragEvent) => void) => {
element.draggable = true;
element.classList.add("dropzone");
element.addEventListener("dragstart", (event) => {
event.stopPropagation();
- event.dataTransfer.setData("text", dragOptions.data);
+ event.dataTransfer?.setData("text", dragOptions.data);
callback("dragstart", event);
});
element.addEventListener("dragend", (event) => {
event.preventDefault();
- if (event.dataTransfer.dropEffect != "none" && lastDropWasValid) {
+ if (event.dataTransfer?.dropEffect != "none" && lastDropWasValid) {
callback("dragend", event);
event.stopPropagation();
}
@@ -45,7 +47,7 @@ export default (element, dragOptions, callback) => {
element.addEventListener("drop", (event) => {
event.preventDefault();
lastDropWasValid = _isValidDropzone(
- JSON.parse(event.dataTransfer.getData("text"))
+ JSON.parse(event.dataTransfer?.getData("text") ?? "{}")
);
if (lastDropWasValid) {
event.stopPropagation();
@@ -53,14 +55,14 @@ export default (element, dragOptions, callback) => {
}
});
- const _isValidDropzone = (dropZone) => {
+ const _isValidDropzone = (dropZone: { classList: string[] }) => {
// check if an element of dropzone.classlist is in the array dragOptions.classList
return _isValid(dropZone, dragOptions.validDropzones);
};
- const _isValid = (element, classes) => {
+ const _isValid = (element: { classList: string[] }, classes: string[]) => {
for (let i = 0; i < classes.length; i++) {
- if ([...element.classList].indexOf(classes[i]) > -1) {
+ if ([...element.classList].indexOf(classes[i]!) > -1) {
return true;
}
}
diff --git a/app/src/helper/utils.ts b/app/src/helper/utils.ts
new file mode 100644
index 0000000..a7daa8a
--- /dev/null
+++ b/app/src/helper/utils.ts
@@ -0,0 +1,3 @@
+export function insertAfter(newNode: Node, existingNode: Node) {
+ existingNode.parentNode?.insertBefore(newNode, existingNode.nextSibling);
+}
diff --git a/js/html/edit.js b/app/src/pages/edit.ts
similarity index 87%
rename from js/html/edit.js
rename to app/src/pages/edit.ts
index c9b3eec..c593778 100644
--- a/js/html/edit.js
+++ b/app/src/pages/edit.ts
@@ -1,13 +1,14 @@
+import type { TreeConfig } from "../views/tree/components/treeTypes.js";
import EditTree from "../views/tree/editTree/components/editTree.js";
import { parse, stringify } from "../helper/jsurl.js";
import Button from "../views/other/button.js";
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
-const treeConfig = parse(urlParams.get("t")) || {};
+const treeConfig = (parse(urlParams.get("t")) as TreeConfig | null) ?? { bmc: [], s: {}, t: {} };
const REPO_URL = "https://github.com/AlexW00/StartTreeV2";
-const t = new EditTree(treeConfig, true);
+const t = new EditTree(treeConfig);
document.body.appendChild(t.html());
const getExportUrl = () => {
@@ -15,7 +16,7 @@ const getExportUrl = () => {
path = location.pathname,
affix = "?t=",
data = stringify(t.export());
- return host + path.replace("e.html", "v.html") + affix + data;
+ return host + path.replace("edit.html", "view.html") + affix + data;
};
const cancelButtonHtml = () => {
diff --git a/app/src/pages/index.ts b/app/src/pages/index.ts
new file mode 100644
index 0000000..8dd1f2e
--- /dev/null
+++ b/app/src/pages/index.ts
@@ -0,0 +1,9 @@
+import { stringify } from "../helper/jsurl.js";
+
+const exampleData = await fetch("./src/views/tree/exampleConfig.json").then(
+ (response) => response.json()
+);
+
+const jsonStringified = stringify(exampleData);
+
+document.location.replace(`./pages/edit.html?t=${jsonStringified}`);
diff --git a/js/html/view.js b/app/src/pages/view.ts
similarity index 71%
rename from js/html/view.js
rename to app/src/pages/view.ts
index 30f39da..393b94b 100644
--- a/js/html/view.js
+++ b/app/src/pages/view.ts
@@ -1,13 +1,14 @@
+import type { TreeConfig } from "../views/tree/components/treeTypes.js";
import Tree from "../views/tree/components/tree.js";
import { parse } from "../helper/jsurl.js";
import Button from "../views/other/button.js";
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
-const treeConfig = parse(urlParams.get("t")) || {};
-const editModeHref = "./e.html";
+const treeConfig = (parse(urlParams.get("t")) as TreeConfig | null) ?? { bmc: [], s: {}, t: {} };
+const editModeHref = "./edit.html";
-const t = new Tree(treeConfig, false);
+const t = new Tree(treeConfig);
document.body.appendChild(t.html());
const editModeButtonHtml = () => {
diff --git a/js/views/other/button.js b/app/src/views/other/button.ts
similarity index 98%
rename from js/views/other/button.js
rename to app/src/views/other/button.ts
index 7bb3b2e..23a88ce 100644
--- a/js/views/other/button.js
+++ b/app/src/views/other/button.ts
@@ -3,8 +3,11 @@
// ====================================================== //
export default class Button {
+ svg: string;
+ type: string;
+
// possible values for type: "save", "cancel", "add" or "delete"
- constructor(type, width, height) {
+ constructor(type: string, width?: number, height?: number) {
this.type = type;
if (type === "add") {
this.svg = `
diff --git a/js/views/tree/components/searchBar.js b/app/src/views/tree/components/searchBar.ts
similarity index 90%
rename from js/views/tree/components/searchBar.js
rename to app/src/views/tree/components/searchBar.ts
index 774d967..071976b 100644
--- a/js/views/tree/components/searchBar.js
+++ b/app/src/views/tree/components/searchBar.ts
@@ -3,7 +3,15 @@
// ====================================================== //;
export default class SearchBar {
- constructor(config) {
+ form!: HTMLFormElement;
+ formInput!: HTMLInputElement;
+ h1!: HTMLHeadingElement;
+ root!: HTMLDivElement;
+ searchEngineNameShort: string;
+ searchEngineUrl: string;
+ sectionName!: HTMLDivElement;
+
+ constructor(config: { n?: string; u?: string }) {
this.searchEngineUrl = config.u ?? "https://duckduckgo.com/?q=";
this.searchEngineNameShort = config.n ?? "ddg";
}
diff --git a/js/views/tree/components/tree.js b/app/src/views/tree/components/tree.ts
similarity index 82%
rename from js/views/tree/components/tree.js
rename to app/src/views/tree/components/tree.ts
index 781bb3f..9fa6b87 100644
--- a/js/views/tree/components/tree.js
+++ b/app/src/views/tree/components/tree.ts
@@ -1,3 +1,4 @@
+import type { TreeConfig, CategoryConfig } from "./treeTypes.js";
import ThemeChanger from "../themechanger/theme-changer.js";
import SearchBar from "./searchBar.js";
import TreeColumn from "./treeColumn.js";
@@ -7,7 +8,15 @@ import TreeColumn from "./treeColumn.js";
// ====================================================== //
export default class Tree {
- constructor(config) {
+ bookmarkColumns: TreeColumn[];
+ bookmarkRow!: HTMLDivElement;
+ root!: HTMLDivElement;
+ searchBar: SearchBar;
+ themeChanger: ThemeChanger;
+ titlePrompt!: HTMLDivElement;
+ version: string;
+
+ constructor(config: TreeConfig) {
this.version = config.v || "0.0";
this.bookmarkColumns = this.initBookmarkColumns(config.bmc);
@@ -17,15 +26,15 @@ export default class Tree {
// ~~~~~~~~ initialization methods ~~~~~~~ //
- initBookmarkColumns(config) {
+ initBookmarkColumns(config: CategoryConfig[][]) {
return config.map((column) => new TreeColumn(column));
}
- initSearchBar(config) {
+ initSearchBar(config: TreeConfig["s"]) {
return new SearchBar(config);
}
- initThemeChanger(config) {
+ initThemeChanger(config: TreeConfig["t"]) {
return new ThemeChanger(config);
}
diff --git a/js/views/tree/components/treeColumn.js b/app/src/views/tree/components/treeColumn.ts
similarity index 85%
rename from js/views/tree/components/treeColumn.js
rename to app/src/views/tree/components/treeColumn.ts
index a41d6ba..fae0501 100644
--- a/js/views/tree/components/treeColumn.js
+++ b/app/src/views/tree/components/treeColumn.ts
@@ -5,8 +5,15 @@ import TreeColumnCategory from "./treeColumnCategory.js";
// ====================================================== //
export default class TreeColumn {
+ bookmarkCategories: TreeColumnCategory[];
+ categoryList!: HTMLUListElement;
+ columnTitle!: HTMLHeadingElement;
+ id: string;
+ root!: HTMLDivElement;
+ tree!: HTMLDivElement;
+
static count = 0;
- constructor(bookmarkColumn) {
+ constructor(bookmarkColumn: { cn: string; b: { n: string; u: string }[] }[]) {
TreeColumn.count++;
this.id = `column-${TreeColumn.count}`;
this.bookmarkCategories = this.initBookmarkCategories(bookmarkColumn);
@@ -67,7 +74,7 @@ export default class TreeColumn {
// ~~~~~~~~~~~~ class functionality ~~~~~~~~~~~~ //
- initBookmarkCategories(categoryConfig) {
+ initBookmarkCategories(categoryConfig: { cn: string; b: { n: string; u: string }[] }[]) {
return categoryConfig.map((bookmarkCategory) => {
return new TreeColumnCategory(bookmarkCategory);
});
diff --git a/js/views/tree/components/treeColumnCategory.js b/app/src/views/tree/components/treeColumnCategory.ts
similarity index 85%
rename from js/views/tree/components/treeColumnCategory.js
rename to app/src/views/tree/components/treeColumnCategory.ts
index eb9305a..1dbc230 100644
--- a/js/views/tree/components/treeColumnCategory.js
+++ b/app/src/views/tree/components/treeColumnCategory.ts
@@ -5,8 +5,15 @@
import TreeItem from "./treeItem.js";
export default class TreeColumnCategory {
+ bookmarkList!: HTMLUListElement;
+ categoryTitle!: HTMLHeadingElement;
+ id: string;
+ name: string;
+ root!: HTMLLIElement;
+ treeItems: TreeItem[];
+
static count = 0;
- constructor(bookmarkCategory) {
+ constructor(bookmarkCategory: { cn: string; b: { n: string; u: string }[] }) {
TreeColumnCategory.count++;
this.id = `category-${TreeColumnCategory.count}`;
this.name = bookmarkCategory.cn;
@@ -58,7 +65,7 @@ export default class TreeColumnCategory {
// ~~~~~~~~~~~~ class functionality ~~~~~~~~~~~~ //
- initTreeItems(bookmarkConfig) {
+ initTreeItems(bookmarkConfig: { n: string; u: string }[]) {
return bookmarkConfig.map((bookmark) => {
return new TreeItem(bookmark);
});
diff --git a/js/views/tree/components/treeItem.js b/app/src/views/tree/components/treeItem.ts
similarity index 86%
rename from js/views/tree/components/treeItem.js
rename to app/src/views/tree/components/treeItem.ts
index 03b4b79..d318e96 100644
--- a/js/views/tree/components/treeItem.js
+++ b/app/src/views/tree/components/treeItem.ts
@@ -4,8 +4,14 @@
//
export default class TreeItem {
+ a!: HTMLAnchorElement;
+ id: string;
+ name: string;
+ root!: HTMLLIElement;
+ url: string;
+
static count = 0;
- constructor(bookmark) {
+ constructor(bookmark: { n: string; u: string }) {
TreeItem.count++;
this.id = `bookmark-${TreeItem.count}`;
this.name = bookmark.n;
@@ -39,7 +45,7 @@ export default class TreeItem {
return root;
}
- generateLinkText(url) {
+ generateLinkText(url: string) {
// if the url has a protocol, return the url, else append a protocol
if (url.includes("//")) {
return url;
diff --git a/app/src/views/tree/components/treeTypes.ts b/app/src/views/tree/components/treeTypes.ts
new file mode 100644
index 0000000..449e843
--- /dev/null
+++ b/app/src/views/tree/components/treeTypes.ts
@@ -0,0 +1,3 @@
+export type BookmarkConfig = { n: string; u: string };
+export type CategoryConfig = { cn: string; b: BookmarkConfig[] };
+export type TreeConfig = { v?: string; bmc: CategoryConfig[][]; s: { n?: string; u?: string }; t: { nr?: number } };
diff --git a/js/views/tree/editTree/components/editSearchBar.js b/app/src/views/tree/editTree/components/editSearchBar.ts
similarity index 92%
rename from js/views/tree/editTree/components/editSearchBar.js
rename to app/src/views/tree/editTree/components/editSearchBar.ts
index 4a7e8bd..a51706a 100644
--- a/js/views/tree/editTree/components/editSearchBar.js
+++ b/app/src/views/tree/editTree/components/editSearchBar.ts
@@ -9,13 +9,14 @@ import editorTarget from "../editor/helperObjects/editorTarget.js";
import Button from "../../../other/button.js";
export default class EditSearchBar extends SearchBar {
- constructor(config) {
+
+ constructor(config: { n?: string; u?: string }) {
super(config);
}
// ~~~~~~~ override parent methods ~~~~~~~ //
- renderHtml() {
+ override renderHtml() {
this.root = this.rootHtml();
this.sectionName = this.#sectionNameHtml();
@@ -56,8 +57,8 @@ export default class EditSearchBar extends SearchBar {
}),
(editorFinishEvent) => {
if (editorFinishEvent.type === "save") {
- this.searchEngineUrl = editorFinishEvent.editResult.link;
- this.searchEngineNameShort = editorFinishEvent.editResult.text;
+ this.searchEngineUrl = editorFinishEvent.editResult!.link;
+ this.searchEngineNameShort = editorFinishEvent.editResult!.text;
this.root.prepend(this.#sectionNameHtml());
} else {
this.root.prepend(this.#sectionNameHtml());
diff --git a/js/views/tree/editTree/components/editTree.js b/app/src/views/tree/editTree/components/editTree.ts
similarity index 79%
rename from js/views/tree/editTree/components/editTree.js
rename to app/src/views/tree/editTree/components/editTree.ts
index d42ea35..c83929d 100644
--- a/js/views/tree/editTree/components/editTree.js
+++ b/app/src/views/tree/editTree/components/editTree.ts
@@ -2,6 +2,8 @@ import ThemeChanger from "../../themechanger/theme-changer.js";
import EditSearchBar from "./editSearchBar.js";
import EditTreeColumn from "./editTreeColumn.js";
import Button from "../../../other/button.js";
+import type { TreeConfig, CategoryConfig } from "../../components/treeTypes.js";
+import TreeUpdateEvent from "../events/treeUpdateEvent.js";
import Tree from "../../components/tree.js";
// ====================================================== //
@@ -9,27 +11,28 @@ import Tree from "../../components/tree.js";
// ====================================================== //
export default class EditTree extends Tree {
- constructor(config) {
+
+ constructor(config: TreeConfig) {
super(config);
}
// ~~~~~~~~ override parent methods ~~~~~~~ //
- initBookmarkColumns(config) {
+ override initBookmarkColumns(config: CategoryConfig[][]) {
return config.map(
(column) => new EditTreeColumn(column, this.onColumnUpdate.bind(this))
);
}
- initSearchBar(config) {
+ override initSearchBar(config: TreeConfig["s"]) {
return new EditSearchBar(config);
}
- initThemeChanger(config) {
+ override initThemeChanger(config: TreeConfig["t"]) {
return new ThemeChanger(config);
}
- renderHtml() {
+ override renderHtml() {
this.root = super.renderHtml();
this.root.append(this.themeChanger.html());
this.titlePrompt.appendChild(this.#addColumnButtonHtml());
@@ -54,7 +57,7 @@ export default class EditTree extends Tree {
// ~~~~~~~~~~~ callback methods ~~~~~~~~~~ //
- onColumnUpdate(treeUpdateEvent) {
+ onColumnUpdate(treeUpdateEvent: TreeUpdateEvent) {
if (treeUpdateEvent.type === "delete") {
const index = this.bookmarkColumns.indexOf(treeUpdateEvent.updatedObject);
this.bookmarkColumns.splice(index, 1);
diff --git a/js/views/tree/editTree/components/editTreeColumn.js b/app/src/views/tree/editTree/components/editTreeColumn.ts
similarity index 80%
rename from js/views/tree/editTree/components/editTreeColumn.js
rename to app/src/views/tree/editTree/components/editTreeColumn.ts
index ca14029..e3b4906 100644
--- a/js/views/tree/editTree/components/editTreeColumn.js
+++ b/app/src/views/tree/editTree/components/editTreeColumn.ts
@@ -4,6 +4,7 @@ import Editor from "../editor/components/editor.js";
import editorTarget from "../editor/helperObjects/editorTarget.js";
import EditorOptions from "../editor/helperObjects/editorOptions.js";
import TreeUpdateEvent from "../events/treeUpdateEvent.js";
+import type { CategoryConfig } from "../../components/treeTypes.js";
import TreeColumn from "../../components/treeColumn.js";
// ====================================================== //
@@ -11,14 +12,16 @@ import TreeColumn from "../../components/treeColumn.js";
// ====================================================== //
export default class EditTreeColumn extends TreeColumn {
- constructor(bookmarkColumn, onUpdate) {
+ onUpdate: (event: TreeUpdateEvent) => void;
+
+ constructor(bookmarkColumn: CategoryConfig[], onUpdate: (event: TreeUpdateEvent) => void) {
super(bookmarkColumn);
this.onUpdate = onUpdate;
}
// ~~~~~~~~~~~~ override parent methods ~~~~~~~~~~~~ //
- initBookmarkCategories(categoryConfig) {
+ override initBookmarkCategories(categoryConfig: CategoryConfig[]) {
return categoryConfig.map((bookmarkCategory) => {
return new EditTreeColumnCategory(
bookmarkCategory,
@@ -27,17 +30,17 @@ export default class EditTreeColumn extends TreeColumn {
});
}
- renderHtml() {
+ override renderHtml() {
this.root = super.renderHtml();
- this.categoryList.lastElementChild.appendChild(
+ this.categoryList.lastElementChild?.appendChild(
this.#newAddCategoryButton()
);
return this.root;
}
- columnTitleHtml() {
+ override columnTitleHtml() {
const h1 = super.columnTitleHtml();
- h1.addEventListener("click", () => this.#categoryTitleListener);
+ h1.addEventListener("click", this.#categoryTitleListener);
return h1;
}
@@ -46,7 +49,7 @@ export default class EditTreeColumn extends TreeColumn {
#categoryTitleListener = () => {
new Editor(
this.tree,
- new editorTarget(".", null, this.h1.id),
+ new editorTarget(".", null, this.columnTitle.id),
new EditorOptions({
allowTextEdit: false,
buttons: ["cancel", "delete"],
@@ -60,8 +63,8 @@ export default class EditTreeColumn extends TreeColumn {
this.root.remove();
} else {
this.tree.insertBefore(
- this.h1,
- this.tree.querySelectorAll("ul")[editorFinishEvent.index]
+ this.columnTitle,
+ this.tree.querySelectorAll("ul")[editorFinishEvent.index] ?? null
);
}
}
@@ -82,10 +85,10 @@ export default class EditTreeColumn extends TreeColumn {
}
// listener for when the add button is clicked
- #onAddCategoryButtonClick = (addCategoryButton) => {
+ #onAddCategoryButtonClick = (addCategoryButton: HTMLDivElement) => {
// removes add button from last category
const elements = this.categoryList.querySelectorAll("li.category");
- elements[elements.length - 1].removeChild(addCategoryButton);
+ elements[elements.length - 1]?.removeChild(addCategoryButton);
// creates new category and appends it to the end of the node
const newBookmarkCategory = new EditTreeColumnCategory(
@@ -104,7 +107,7 @@ export default class EditTreeColumn extends TreeColumn {
(editorFinishEvent) => {
if (editorFinishEvent.type === "save") {
// append new bookmark category to end of list and push to array
- newBookmarkCategory.name = editorFinishEvent.editResult.text;
+ newBookmarkCategory.name = editorFinishEvent.editResult!.text;
const newBookmarkCategoryHtml = newBookmarkCategory.renderHtml();
this.categoryList.appendChild(newBookmarkCategoryHtml);
newBookmarkCategoryHtml.appendChild(addCategoryButton);
@@ -112,7 +115,7 @@ export default class EditTreeColumn extends TreeColumn {
this.bookmarkCategories.push(newBookmarkCategory);
} else {
// re append the button
- this.categoryList.lastElementChild.appendChild(addCategoryButton);
+ this.categoryList.lastElementChild?.appendChild(addCategoryButton);
}
}
);
@@ -120,7 +123,7 @@ export default class EditTreeColumn extends TreeColumn {
// ~~~~~~~~~~~~ callbacks ~~~~~~~~~~~~ //
- onCategoryUpdate(treeUpdateEvent) {
+ onCategoryUpdate(treeUpdateEvent: TreeUpdateEvent) {
if (treeUpdateEvent.type === "delete") {
const categoryIndex = this.bookmarkCategories.indexOf(
treeUpdateEvent.updatedObject
@@ -136,11 +139,11 @@ export default class EditTreeColumn extends TreeColumn {
}
// else if this was the last category in the list, append the add button to the new last category
else if (categoryIndex === this.bookmarkCategories.length) {
- const lastCategory = this.root.querySelector("ul").lastChild;
- lastCategory.appendChild(this.#newAddCategoryButton(this.root));
+ const lastCategory = this.root.querySelector("ul")?.lastChild;
+ lastCategory?.appendChild(this.#newAddCategoryButton());
}
}
- if (treeUpdateEvent.type === "add") {
+ if (treeUpdateEvent.type === "add" && treeUpdateEvent.newObject) {
// get the index of the category to add
const categoryIndex = this.bookmarkCategories.indexOf(
treeUpdateEvent.updatedObject
diff --git a/js/views/tree/editTree/components/editTreeColumnCategory.js b/app/src/views/tree/editTree/components/editTreeColumnCategory.ts
similarity index 80%
rename from js/views/tree/editTree/components/editTreeColumnCategory.js
rename to app/src/views/tree/editTree/components/editTreeColumnCategory.ts
index e2ea67d..090ae1d 100644
--- a/js/views/tree/editTree/components/editTreeColumnCategory.js
+++ b/app/src/views/tree/editTree/components/editTreeColumnCategory.ts
@@ -6,6 +6,7 @@ import EditorOptions from "../editor/helperObjects/editorOptions.js";
import TreeUpdateEvent from "../events/treeUpdateEvent.js";
import DragOptions from "../../../../helper/dragOptions.js";
import makeDraggable from "../../../../helper/makeDraggable.js";
+import type { CategoryConfig, BookmarkConfig } from "../../components/treeTypes.js";
import TreeColumnCategory from "../../components/treeColumnCategory.js";
// ====================================================== //
@@ -13,28 +14,30 @@ import TreeColumnCategory from "../../components/treeColumnCategory.js";
// ====================================================== //
export default class EditTreeColumnCategory extends TreeColumnCategory {
- static count = 0;
- constructor(bookmarkCategory, onUpdate) {
+ onUpdate: (event: TreeUpdateEvent) => void;
+
+ static override count = 0;
+ constructor(bookmarkCategory: CategoryConfig, onUpdate: (event: TreeUpdateEvent) => void) {
super(bookmarkCategory);
this.onUpdate = onUpdate;
}
// ~~~~~~~ override parent methods ~~~~~~~ //
- initTreeItems(bookmarkConfig) {
+ override initTreeItems(bookmarkConfig: BookmarkConfig[]) {
return bookmarkConfig.map((bookmark) => {
return new EditTreeItem(bookmark, this.onBookmarkUpdate.bind(this));
});
}
- renderHtml() {
+ override renderHtml() {
super.renderHtml();
this.root.appendChild(this.#newAddCategoryButton(this.bookmarkList));
this.#makeDraggable();
return this.root;
}
- categoryTitleHtml() {
+ override categoryTitleHtml() {
const h1 = super.categoryTitleHtml();
h1.addEventListener("click", () => {
this.#categoryTitleClickListener(h1);
@@ -53,8 +56,7 @@ export default class EditTreeColumnCategory extends TreeColumnCategory {
}
#makeDraggable = () => {
- const dragOptionsData = this.export();
- dragOptionsData.classList = ["category"];
+ const dragOptionsData = { ...this.export(), classList: ["category"] };
const dragOptions = new DragOptions({
data: JSON.stringify(dragOptionsData),
validDropzones: ["category", "bookmark"],
@@ -77,8 +79,8 @@ export default class EditTreeColumnCategory extends TreeColumnCategory {
this.onUpdate(new TreeUpdateEvent({ type: "delete", updatedObject: this }));
}
- #onDrop = (event) => {
- const dragItemData = JSON.parse(event.dataTransfer.getData("text"));
+ #onDrop = (event: DragEvent) => {
+ const dragItemData = JSON.parse(event.dataTransfer?.getData("text") ?? "{}");
const dragItemClass = dragItemData.classList[0];
@@ -86,13 +88,13 @@ export default class EditTreeColumnCategory extends TreeColumnCategory {
else if (dragItemClass === "category") this.#onDropCategory(dragItemData);
};
- #onDropCategory(dragItemData) {
+ #onDropCategory(dragItemData: CategoryConfig) {
const draggedItem = new EditTreeColumnCategory(
{ cn: dragItemData.cn, b: dragItemData.b },
this.onUpdate
);
const draggedItemHtml = draggedItem.html();
- this.root.parentNode.insertBefore(draggedItemHtml, this.root);
+ this.root.parentNode?.insertBefore(draggedItemHtml, this.root);
this.onUpdate(
new TreeUpdateEvent({
type: "add",
@@ -102,7 +104,7 @@ export default class EditTreeColumnCategory extends TreeColumnCategory {
);
}
- #onDropBookmark(dragItemData) {
+ #onDropBookmark(dragItemData: BookmarkConfig) {
const draggedItem = new EditTreeItem(
{ n: dragItemData.n, u: dragItemData.u },
this.onBookmarkUpdate.bind(this)
@@ -112,14 +114,14 @@ export default class EditTreeColumnCategory extends TreeColumnCategory {
// prepend this item to the list
const categoryList = this.root.querySelector("ul");
this.treeItems.unshift(draggedItem);
- categoryList.insertBefore(
+ categoryList?.insertBefore(
draggedItemHtml,
- categoryList.querySelector(".bookmark")
+ categoryList?.querySelector(".bookmark")
);
}
// TODO: create extra class for this??
- #newAddCategoryButton = (ul) => {
+ #newAddCategoryButton = (ul: HTMLUListElement) => {
const addBookmarkButton = new Button("add").html();
addBookmarkButton.classList.add("add-bookmark-button");
addBookmarkButton.style.paddingLeft = "1.5rem";
@@ -142,8 +144,8 @@ export default class EditTreeColumnCategory extends TreeColumnCategory {
(editorFinishEvent) => {
if (editorFinishEvent.type === "save") {
// append new bookmark to end of list and push to array
- newBookmark.name = editorFinishEvent.editResult.text;
- newBookmark.url = editorFinishEvent.editResult.link ?? "#";
+ newBookmark.name = editorFinishEvent.editResult!.text;
+ newBookmark.url = editorFinishEvent.editResult!.link ?? "#";
this.treeItems.push(newBookmark);
ul.appendChild(newBookmark.renderHtml());
}
@@ -153,7 +155,7 @@ export default class EditTreeColumnCategory extends TreeColumnCategory {
return addBookmarkButton;
};
- #categoryTitleClickListener = (h1) => {
+ #categoryTitleClickListener = (h1: HTMLHeadingElement) => {
new Editor(
this.root,
new editorTarget(this.name, null, h1.id),
@@ -161,7 +163,7 @@ export default class EditTreeColumnCategory extends TreeColumnCategory {
(editorFinishEvent) => {
if (editorFinishEvent.type === "save") {
// if the editor exits with "save", update the category name
- this.name = editorFinishEvent.editResult.text;
+ this.name = editorFinishEvent.editResult!.text;
h1 = this.categoryTitleHtml();
this.root.insertBefore(h1, this.bookmarkList);
this.onUpdate(
@@ -183,13 +185,13 @@ export default class EditTreeColumnCategory extends TreeColumnCategory {
// ~~~~~~~~~~~~~~ callbacks ~~~~~~~~~~~~~~ //
- onBookmarkUpdate(treeUpdateEvent) {
+ onBookmarkUpdate(treeUpdateEvent: TreeUpdateEvent) {
if (treeUpdateEvent.type === "delete") {
this.treeItems.splice(
this.treeItems.indexOf(treeUpdateEvent.updatedObject),
1
);
- } else if (treeUpdateEvent.type === "add") {
+ } else if (treeUpdateEvent.type === "add" && treeUpdateEvent.newObject) {
// add the bookmark to bookmarks after the updated object, if updated object isn't in listit will be added to the end
const dragTargetIndex =
this.treeItems.indexOf(treeUpdateEvent.updatedObject) ??
diff --git a/js/views/tree/editTree/components/editTreeItem.js b/app/src/views/tree/editTree/components/editTreeItem.ts
similarity index 82%
rename from js/views/tree/editTree/components/editTreeItem.js
rename to app/src/views/tree/editTree/components/editTreeItem.ts
index ed19f2c..4b54910 100644
--- a/js/views/tree/editTree/components/editTreeItem.js
+++ b/app/src/views/tree/editTree/components/editTreeItem.ts
@@ -6,6 +6,7 @@ import DragOptions from "../../../../helper/dragOptions.js";
import makeDraggable from "../../../../helper/makeDraggable.js";
import { insertAfter } from "../../../../helper/utils.js";
import Button from "../../../other/button.js";
+import type { BookmarkConfig } from "../../components/treeTypes.js";
import TreeItem from "../../components/treeItem.js";
import Editor from "../editor/components/editor.js";
import EditorOptions from "../editor/helperObjects/editorOptions.js";
@@ -13,18 +14,21 @@ import editorTarget from "../editor/helperObjects/editorTarget.js";
import TreeUpdateEvent from "../events/treeUpdateEvent.js";
export default class EditTreeItem extends TreeItem {
- constructor(bookmark, onUpdate) {
+ editButton!: HTMLDivElement;
+ onUpdate: (event: TreeUpdateEvent) => void;
+
+ constructor(bookmark: BookmarkConfig, onUpdate: (event: TreeUpdateEvent) => void) {
super(bookmark);
this.onUpdate = onUpdate;
}
// ~~~~~~~ override parent methods ~~~~~~ //
- html() {
+ override html() {
return this.root ?? this.renderHtml();
}
- renderHtml() {
+ override renderHtml() {
this.root = super.renderHtml();
this.editButton = this.editButtonHtml();
this.root.appendChild(this.editButton);
@@ -32,7 +36,7 @@ export default class EditTreeItem extends TreeItem {
return this.root;
}
- linkHtml() {
+ override linkHtml() {
const a = super.linkHtml();
a.addEventListener("click", (event) => {
event.preventDefault();
@@ -51,8 +55,7 @@ export default class EditTreeItem extends TreeItem {
}
#makeDraggable = () => {
- const dragOptionsData = this.export();
- dragOptionsData.classList = ["bookmark"];
+ const dragOptionsData = { ...this.export(), classList: ["bookmark"] };
const dragOptions = new DragOptions({
data: JSON.stringify(dragOptionsData),
validDropzones: ["bookmark"],
@@ -68,8 +71,8 @@ export default class EditTreeItem extends TreeItem {
};
// valid element is dropped on this element
- #onDrop(event) {
- const dragItemData = JSON.parse(event.dataTransfer.getData("text")),
+ #onDrop(event: DragEvent) {
+ const dragItemData = JSON.parse(event.dataTransfer?.getData("text") ?? "{}"),
newEditTreeItem = new EditTreeItem(
{ n: dragItemData.n, u: dragItemData.u },
this.onUpdate
@@ -93,7 +96,7 @@ export default class EditTreeItem extends TreeItem {
// creates a new editor and adds it to the DOM
#onBookmarkClick = () => {
- const parentNode = this.root.parentNode;
+ const parentNode = this.root.parentNode as HTMLElement;
new Editor(
parentNode,
new editorTarget(this.name, this.url, this.id),
@@ -103,16 +106,16 @@ export default class EditTreeItem extends TreeItem {
}),
(editorFinishEvent) => {
if (editorFinishEvent.type === "save") {
- this.name = editorFinishEvent.editResult.text;
- this.url = editorFinishEvent.editResult.link ?? "#";
+ this.name = editorFinishEvent.editResult!.text;
+ this.url = editorFinishEvent.editResult!.link ?? "#";
parentNode.insertBefore(
this.renderHtml(),
- parentNode.querySelectorAll("li")[editorFinishEvent.index]
+ parentNode.querySelectorAll("li")[editorFinishEvent.index] ?? null
);
} else if (editorFinishEvent.type === "cancel") {
parentNode.insertBefore(
this.html(),
- parentNode.querySelectorAll("li")[editorFinishEvent.index]
+ parentNode.querySelectorAll("li")[editorFinishEvent.index] ?? null
);
} else if (editorFinishEvent.type === "delete") {
this.onUpdate(
diff --git a/js/views/tree/editTree/editor/components/editor.js b/app/src/views/tree/editTree/editor/components/editor.ts
similarity index 80%
rename from js/views/tree/editTree/editor/components/editor.js
rename to app/src/views/tree/editTree/editor/components/editor.ts
index 084a877..975bcc3 100644
--- a/js/views/tree/editTree/editor/components/editor.js
+++ b/app/src/views/tree/editTree/editor/components/editor.ts
@@ -3,13 +3,30 @@
// ====================================================== //
import EditorFinishEvent from "../events/editorFinishEvent.js";
+import EditorOptions from "../helperObjects/editorOptions.js";
+import EditorTarget from "../helperObjects/editorTarget.js";
import Toolbar from "./toolbar.js";
export default class Editor {
- static openInstance = null;
+ allowTextEdit: boolean;
+ buttons: string[];
+ cb: (event: EditorFinishEvent) => void;
+ editorTarget: EditorTarget;
+ index = 0;
+ isClosed = false;
+ link: string;
+ linkEditorIsOpen: boolean;
+ nodeType: string;
+ parentNode: HTMLElement;
+ root!: HTMLElement;
+ secondRow?: HTMLDivElement;
+ text: string;
+ toolbar!: Toolbar;
+
+ static openInstance: Editor | null = null;
// ~~~~~~~~~ Initialization functions ~~~~~~~~~ //
- constructor(parentNode, editorTarget, editorOptions, cb) {
+ constructor(parentNode: HTMLElement, editorTarget: EditorTarget, editorOptions: EditorOptions, cb: (event: EditorFinishEvent) => void) {
this.cb = cb; // callback function
this.buttons = editorOptions.buttons; // ["link", "delete", "cancel"];
this.parentNode = parentNode; // the parent node of the edit target
@@ -34,13 +51,13 @@ export default class Editor {
this.root = this.html();
this.parentNode.replaceChild(
this.root,
- this.parentNode.querySelector("#" + this.editorTarget.id)
+ this.parentNode.querySelector("#" + this.editorTarget.id)!
);
const children = this.parentNode.children;
// loop over all
for (let i = 0; i < children.length; i++) {
- if (children[i].classList.contains("editor")) {
+ if (children[i]!.classList.contains("editor")) {
this.index = i;
break;
}
@@ -72,7 +89,7 @@ export default class Editor {
#setMouseDownListener = () => {
document.addEventListener("mousedown", (e) => {
- if (this.root.contains(e.target)) return;
+ if (e.target instanceof Node && this.root.contains(e.target)) return;
this.save();
});
};
@@ -93,7 +110,7 @@ export default class Editor {
this.link = input.value;
if (e.keyCode === 13 && input === document.activeElement) {
e.preventDefault();
- this.save(this.root.parentNode);
+ this.save(this.root.parentNode ?? undefined);
}
});
@@ -102,7 +119,7 @@ export default class Editor {
};
// creates an input field
- #createInputField(li) {
+ #createInputField(li: HTMLElement) {
// create input field
const input = document.createElement("input");
@@ -111,7 +128,7 @@ export default class Editor {
input.addEventListener("keyup", (e) => {
this.text = input.value;
if (e.keyCode === 13 && input === document.activeElement) {
- this.save(li.parentNode);
+ this.save(li.parentNode ?? undefined);
}
});
if (!this.allowTextEdit) input.disabled = true;
@@ -119,7 +136,7 @@ export default class Editor {
}
// creates the toolbar html
- #createToolbar(li) {
+ #createToolbar(li: HTMLElement) {
this.toolbar = new Toolbar(this.buttons, (buttonName) => {
console.log(buttonName);
if (buttonName === "cancel") {
@@ -133,7 +150,7 @@ export default class Editor {
return this.toolbar.html();
}
- #toggleLinkInput(li) {
+ #toggleLinkInput(li: HTMLElement) {
if (this.linkEditorIsOpen) {
this.#closeLinkInput(li);
this.toolbar.linkButton.classList.remove("active");
@@ -143,13 +160,13 @@ export default class Editor {
}
}
- #openLinkInput(li) {
+ #openLinkInput(li: HTMLElement) {
li.appendChild(this.#secondRowHtml());
}
// ~~~~~~~ Toolbar event callbacks ~~~~~~ //
- save() {
+ save(_parentNode?: Node) {
if (this.isClosed) return;
this.#remove();
this.cb(
@@ -182,10 +199,10 @@ export default class Editor {
});
}
- #closeLinkInput() {
+ #closeLinkInput(_li?: Node): Promise {
if (!this.linkEditorIsOpen) return Promise.resolve();
return new Promise((resolve) => {
- const linkInput = this.root.querySelector(".secondRow");
+ const linkInput = this.root.querySelector(".secondRow")!;
linkInput.classList.add("slide-down-animate-out");
linkInput.onanimationend = () => {
this.linkEditorIsOpen = false;
diff --git a/js/views/tree/editTree/editor/components/toolbar.js b/app/src/views/tree/editTree/editor/components/toolbar.ts
similarity index 85%
rename from js/views/tree/editTree/editor/components/toolbar.js
rename to app/src/views/tree/editTree/editor/components/toolbar.ts
index 2243a5b..26709d4 100644
--- a/js/views/tree/editTree/editor/components/toolbar.js
+++ b/app/src/views/tree/editTree/editor/components/toolbar.ts
@@ -4,7 +4,13 @@
import Button from "../../../../other/button.js";
export default class Toolbar {
- constructor(buttons, cb) {
+ buttons: string[];
+ cancelButton?: HTMLDivElement;
+ cb: (button: string) => void;
+ deleteButton?: HTMLDivElement;
+ linkButton!: HTMLDivElement;
+
+ constructor(buttons: string[], cb: (button: string) => void) {
this.cb = cb; // callback function
this.buttons = buttons; // ["link", "delete", "cancel"];
}
diff --git a/js/views/tree/editTree/editor/events/editorFinishEvent.js b/app/src/views/tree/editTree/editor/events/editorFinishEvent.ts
similarity index 69%
rename from js/views/tree/editTree/editor/events/editorFinishEvent.js
rename to app/src/views/tree/editTree/editor/events/editorFinishEvent.ts
index 751ac84..acb63db 100644
--- a/js/views/tree/editTree/editor/events/editorFinishEvent.js
+++ b/app/src/views/tree/editTree/editor/events/editorFinishEvent.ts
@@ -3,7 +3,11 @@
// ====================================================== //
export default class EditorFinishEvent {
- constructor(type, editResult, index) {
+ editResult: { text: string; link: string } | null;
+ index: number;
+ type: string;
+
+ constructor(type: string, editResult: { text: string; link: string } | null, index: number) {
this.type = type; // either "save", "cancel" or "delete"
this.editResult = editResult; // { text, link }
this.index = index; // index of the edited item in the parent node
diff --git a/js/views/tree/editTree/editor/helperObjects/editorOptions.js b/app/src/views/tree/editTree/editor/helperObjects/editorOptions.ts
similarity index 75%
rename from js/views/tree/editTree/editor/helperObjects/editorOptions.js
rename to app/src/views/tree/editTree/editor/helperObjects/editorOptions.ts
index 867f598..3332a18 100644
--- a/js/views/tree/editTree/editor/helperObjects/editorOptions.js
+++ b/app/src/views/tree/editTree/editor/helperObjects/editorOptions.ts
@@ -3,7 +3,17 @@
// ====================================================== //
export default class EditorOptions {
- constructor({ allowTextEdit, openWithLinkInput, buttons, nodeType }) {
+ allowTextEdit: boolean;
+ buttons: string[];
+ nodeType: string;
+ openWithLinkInput: boolean;
+
+ constructor({ allowTextEdit, openWithLinkInput, buttons, nodeType }: {
+ allowTextEdit?: boolean;
+ openWithLinkInput?: boolean;
+ buttons?: string[];
+ nodeType?: string;
+ } = {}) {
this.allowTextEdit = allowTextEdit ?? true; // whether or not to allow the user to edit the text of the editor
this.openWithLinkInput = openWithLinkInput ?? false; // whether or not to open the link input when the editor is opened
this.buttons = buttons ?? ["cancel", "delete"]; // the buttons to show in the editor
diff --git a/js/views/tree/editTree/editor/helperObjects/editorTarget.js b/app/src/views/tree/editTree/editor/helperObjects/editorTarget.ts
similarity index 77%
rename from js/views/tree/editTree/editor/helperObjects/editorTarget.js
rename to app/src/views/tree/editTree/editor/helperObjects/editorTarget.ts
index dfdf9d0..9d867b4 100644
--- a/js/views/tree/editTree/editor/helperObjects/editorTarget.js
+++ b/app/src/views/tree/editTree/editor/helperObjects/editorTarget.ts
@@ -3,7 +3,11 @@
// ====================================================== //
export default class editorTarget {
- constructor(text, url, id) {
+ id: string;
+ text: string;
+ url: string;
+
+ constructor(text: string, url: string | null, id: string) {
this.text = text ?? ""; // text to be edited
this.url = url ?? "#"; // url to be edited
this.id = id; // id of the edited item
diff --git a/js/views/tree/editTree/events/treeUpdateEvent.js b/app/src/views/tree/editTree/events/treeUpdateEvent.ts
similarity index 71%
rename from js/views/tree/editTree/events/treeUpdateEvent.js
rename to app/src/views/tree/editTree/events/treeUpdateEvent.ts
index 4676a5f..6adc878 100644
--- a/js/views/tree/editTree/events/treeUpdateEvent.js
+++ b/app/src/views/tree/editTree/events/treeUpdateEvent.ts
@@ -2,16 +2,24 @@
// =================== TreeUpdateEvent ================== //
// ====================================================== //
-export default class TreeUpdateEvent {
+export default class TreeUpdateEvent {
+ newObject: T | undefined;
+ type: string;
+ updatedObject: T;
+
static legalTypes = ["save", "delete", "add"];
- constructor({ type, updatedObject, newObject }) {
+ constructor({ type, updatedObject, newObject }: {
+ type: string;
+ updatedObject: T;
+ newObject?: T;
+ }) {
this.type = this.checkType(type); // event type, must be one of legalTypes
this.updatedObject = updatedObject; // the updated object
this.newObject = newObject; // the new object (if available)
}
- checkType(type) {
+ checkType(type: string) {
if (!TreeUpdateEvent.legalTypes.includes(type)) {
throw new Error(
"TreeUpdateEvent: type must be 'save', 'cancel', or 'delete'. Found: " +
diff --git a/js/views/tree/exampleConfig.json b/app/src/views/tree/exampleConfig.json
similarity index 100%
rename from js/views/tree/exampleConfig.json
rename to app/src/views/tree/exampleConfig.json
diff --git a/js/views/tree/themechanger/theme-changer.js b/app/src/views/tree/themechanger/theme-changer.ts
similarity index 71%
rename from js/views/tree/themechanger/theme-changer.js
rename to app/src/views/tree/themechanger/theme-changer.ts
index a6f35f8..1ebef7f 100644
--- a/js/views/tree/themechanger/theme-changer.js
+++ b/app/src/views/tree/themechanger/theme-changer.ts
@@ -4,6 +4,8 @@
import ThemeItem from "./themeItem.js";
export default class ThemeChanger {
+ themeNr: number;
+
themeChanger = document.createElement("div");
selectedThemeId = 2;
@@ -39,17 +41,17 @@ export default class ThemeChanger {
"catppuccin"
];
- themeCssLink = document.querySelector("link[href='../styles/colors.css']");
+ themeCssLink = document.querySelector("link[href='../styles/colors.css']");
- constructor(config) {
+ constructor(config: { nr?: number }) {
this.themeNr = config.nr ?? 0;
this.addListener();
this.addListenerMouseLeave();
- this.changeTheme(this.THEMES[this.themeNr]);
+ this.changeTheme(this.THEMES[this.themeNr] ?? this.THEMES[0]!);
}
- changeTheme(nameTheme) {
- this.themeCssLink.href = `../themes/${nameTheme}.css`;
+ changeTheme(nameTheme: string) {
+ this.themeCssLink!.href = `../themes/${nameTheme}.css`;
}
html() {
@@ -70,10 +72,10 @@ export default class ThemeChanger {
themeChangerContainer.appendChild(h1);
themeChangerContainer.appendChild(this.themeChanger);
// Change id for selected theme div
- this.themeChanger.childNodes[this.selectedThemeId].id = "selected";
+ (this.themeChanger.childNodes[this.selectedThemeId] as HTMLElement).id = "selected";
// Insert selected theme on the top
this.themeChanger.insertBefore(
- this.themeChanger.childNodes[this.selectedThemeId],
+ this.themeChanger.childNodes[this.selectedThemeId]!,
this.themeChanger.firstChild
);
@@ -83,14 +85,15 @@ export default class ThemeChanger {
addListener = () => {
document.addEventListener("click", (e) => {
- if (e.target.name === "theme-radio") {
+ const target = e.target as HTMLInputElement;
+ if (target.name === "theme-radio") {
// print index of clicked element
- this.themeNr = this.THEMES.indexOf(e.target.id);
- this.changeTheme(e.target.id);
+ this.themeNr = this.THEMES.indexOf(target.id);
+ this.changeTheme(target.id);
const selectedTheme = document.querySelector("#selected");
- selectedTheme.removeAttribute("id");
- e.target.parentElement.id = "selected";
+ selectedTheme?.removeAttribute("id");
+ target.parentElement!.id = "selected";
}
});
};
@@ -98,9 +101,9 @@ export default class ThemeChanger {
addListenerMouseLeave = () => {
this.themeChanger.addEventListener("mouseleave", function (event) {
const selectedTheme = document.querySelector("#selected");
- const path = event.path || (event.composedPath && event.composedPath());
- path[0].insertBefore(selectedTheme, path[0].firstChild);
- event.target.scrollTop = 0;
+ const target = event.currentTarget as HTMLElement;
+ if (selectedTheme) target.insertBefore(selectedTheme, target.firstChild);
+ target.scrollTop = 0;
});
};
diff --git a/js/views/tree/themechanger/themeItem.js b/app/src/views/tree/themechanger/themeItem.ts
similarity index 93%
rename from js/views/tree/themechanger/themeItem.js
rename to app/src/views/tree/themechanger/themeItem.ts
index 56216c8..47b817d 100644
--- a/js/views/tree/themechanger/themeItem.js
+++ b/app/src/views/tree/themechanger/themeItem.ts
@@ -3,11 +3,13 @@
// ====================================================== //
export default class ThemeItem {
+ name: string;
+
static themeCssLink = document.querySelector(
"link[href='./styles/colors.css']"
);
- constructor(themeName) {
+ constructor(themeName: string) {
this.name = themeName;
}
diff --git a/styles/Hack.ttf b/app/styles/Hack.ttf
similarity index 100%
rename from styles/Hack.ttf
rename to app/styles/Hack.ttf
diff --git a/styles/colors.css b/app/styles/colors.css
similarity index 100%
rename from styles/colors.css
rename to app/styles/colors.css
diff --git a/styles/style.css b/app/styles/style.css
similarity index 100%
rename from styles/style.css
rename to app/styles/style.css
diff --git a/themes/MonokaiPro.css b/app/themes/MonokaiPro.css
similarity index 100%
rename from themes/MonokaiPro.css
rename to app/themes/MonokaiPro.css
diff --git a/themes/Programiz.css b/app/themes/Programiz.css
similarity index 100%
rename from themes/Programiz.css
rename to app/themes/Programiz.css
diff --git a/themes/autumn-mech.css b/app/themes/autumn-mech.css
similarity index 100%
rename from themes/autumn-mech.css
rename to app/themes/autumn-mech.css
diff --git a/themes/bigsur.css b/app/themes/bigsur.css
similarity index 100%
rename from themes/bigsur.css
rename to app/themes/bigsur.css
diff --git a/themes/black-ice.css b/app/themes/black-ice.css
similarity index 100%
rename from themes/black-ice.css
rename to app/themes/black-ice.css
diff --git a/themes/capitane.css b/app/themes/capitane.css
similarity index 100%
rename from themes/capitane.css
rename to app/themes/capitane.css
diff --git a/themes/carnival.css b/app/themes/carnival.css
similarity index 100%
rename from themes/carnival.css
rename to app/themes/carnival.css
diff --git a/themes/catppuccin.css b/app/themes/catppuccin.css
similarity index 100%
rename from themes/catppuccin.css
rename to app/themes/catppuccin.css
diff --git a/themes/cotton-candy.css b/app/themes/cotton-candy.css
similarity index 100%
rename from themes/cotton-candy.css
rename to app/themes/cotton-candy.css
diff --git a/themes/desert-sky.css b/app/themes/desert-sky.css
similarity index 100%
rename from themes/desert-sky.css
rename to app/themes/desert-sky.css
diff --git a/themes/ferns.css b/app/themes/ferns.css
similarity index 100%
rename from themes/ferns.css
rename to app/themes/ferns.css
diff --git a/themes/forest.css b/app/themes/forest.css
similarity index 100%
rename from themes/forest.css
rename to app/themes/forest.css
diff --git a/themes/gold-hunter.css b/app/themes/gold-hunter.css
similarity index 100%
rename from themes/gold-hunter.css
rename to app/themes/gold-hunter.css
diff --git a/themes/gruvbox.css b/app/themes/gruvbox.css
similarity index 100%
rename from themes/gruvbox.css
rename to app/themes/gruvbox.css
diff --git a/themes/intrigue.css b/app/themes/intrigue.css
similarity index 100%
rename from themes/intrigue.css
rename to app/themes/intrigue.css
diff --git a/themes/just-red.css b/app/themes/just-red.css
similarity index 100%
rename from themes/just-red.css
rename to app/themes/just-red.css
diff --git a/themes/monterey.css b/app/themes/monterey.css
similarity index 100%
rename from themes/monterey.css
rename to app/themes/monterey.css
diff --git a/themes/neon-pink-dark.css b/app/themes/neon-pink-dark.css
similarity index 100%
rename from themes/neon-pink-dark.css
rename to app/themes/neon-pink-dark.css
diff --git a/themes/neon.css b/app/themes/neon.css
similarity index 100%
rename from themes/neon.css
rename to app/themes/neon.css
diff --git a/themes/nord.css b/app/themes/nord.css
similarity index 100%
rename from themes/nord.css
rename to app/themes/nord.css
diff --git a/themes/orange-dark.css b/app/themes/orange-dark.css
similarity index 100%
rename from themes/orange-dark.css
rename to app/themes/orange-dark.css
diff --git a/themes/sierra.css b/app/themes/sierra.css
similarity index 100%
rename from themes/sierra.css
rename to app/themes/sierra.css
diff --git a/themes/slick-red.css b/app/themes/slick-red.css
similarity index 100%
rename from themes/slick-red.css
rename to app/themes/slick-red.css
diff --git a/themes/storm.css b/app/themes/storm.css
similarity index 100%
rename from themes/storm.css
rename to app/themes/storm.css
diff --git a/themes/this-ones-good.css b/app/themes/this-ones-good.css
similarity index 100%
rename from themes/this-ones-good.css
rename to app/themes/this-ones-good.css
diff --git a/themes/tomorrow-night-eighties.css b/app/themes/tomorrow-night-eighties.css
similarity index 100%
rename from themes/tomorrow-night-eighties.css
rename to app/themes/tomorrow-night-eighties.css
diff --git a/themes/void.css b/app/themes/void.css
similarity index 100%
rename from themes/void.css
rename to app/themes/void.css
diff --git a/themes/water-fire.css b/app/themes/water-fire.css
similarity index 100%
rename from themes/water-fire.css
rename to app/themes/water-fire.css
diff --git a/html/e.html b/html/e.html
deleted file mode 100644
index 4478452..0000000
--- a/html/e.html
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
- StartTreeV2 - Edit
-
-
-
-
-
-