diff --git a/src/App.vue b/src/App.vue
index c63dedff..72e9da75 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -4,11 +4,7 @@
-
-
-
-
-
+
@@ -24,9 +20,7 @@ import TheFooter from './presentation/TheFooter.vue';
import TheCodeArea from './presentation/TheCodeArea.vue';
import TheCodeButtons from './presentation/TheCodeButtons.vue';
import TheSearchBar from './presentation/TheSearchBar.vue';
-import TheSelector from './presentation/Scripts/Selector/TheSelector.vue';
-import TheGrouper from './presentation/Scripts/TheGrouper.vue';
-import CardList from './presentation/Scripts/Cards/CardList.vue';
+import TheScripts from './presentation/Scripts/TheScripts.vue';
@Component({
components: {
@@ -34,9 +28,7 @@ import CardList from './presentation/Scripts/Cards/CardList.vue';
TheCodeArea,
TheCodeButtons,
TheSearchBar,
- TheGrouper,
- CardList,
- TheSelector,
+ TheScripts,
TheFooter,
},
})
diff --git a/src/presentation/Scripts/Cards/CardList.vue b/src/presentation/Scripts/Cards/CardList.vue
index 33f2da28..a828af77 100644
--- a/src/presentation/Scripts/Cards/CardList.vue
+++ b/src/presentation/Scripts/Cards/CardList.vue
@@ -50,9 +50,6 @@ export default class CardList extends StatefulVue {
display: flex;
flex-flow: row wrap;
font-family: $main-font;
- .card {
-
- }
}
.error {
width: 100%;
diff --git a/src/presentation/Scripts/Cards/CardListItem.vue b/src/presentation/Scripts/Cards/CardListItem.vue
index 1cb46187..44050f14 100644
--- a/src/presentation/Scripts/Cards/CardListItem.vue
+++ b/src/presentation/Scripts/Cards/CardListItem.vue
@@ -12,19 +12,19 @@
-
+
\ No newline at end of file
diff --git a/src/presentation/Scripts/Grouping/Grouping.ts b/src/presentation/Scripts/Grouping/Grouping.ts
new file mode 100644
index 00000000..ccaf200f
--- /dev/null
+++ b/src/presentation/Scripts/Grouping/Grouping.ts
@@ -0,0 +1,4 @@
+export enum Grouping {
+ Cards = 1,
+ None = 0,
+}
diff --git a/src/presentation/Scripts/Grouping/TheGrouper.vue b/src/presentation/Scripts/Grouping/TheGrouper.vue
new file mode 100644
index 00000000..8f6d30bb
--- /dev/null
+++ b/src/presentation/Scripts/Grouping/TheGrouper.vue
@@ -0,0 +1,62 @@
+
+
+ Group by:
+
+ Cards
+ |
+ None
+
+
+
+
+
+
+
diff --git a/src/presentation/Scripts/ScriptsTree/ScriptNodeParser.ts b/src/presentation/Scripts/ScriptsTree/ScriptNodeParser.ts
new file mode 100644
index 00000000..bf25782f
--- /dev/null
+++ b/src/presentation/Scripts/ScriptsTree/ScriptNodeParser.ts
@@ -0,0 +1,63 @@
+import { IApplicationState, IUserSelection } from '@/application/State/IApplicationState';
+import { ICategory, IScript } from '@/domain/ICategory';
+import { INode } from './SelectableTree/INode';
+
+export function parseAllCategories(state: IApplicationState): INode[] | undefined {
+ const nodes = new Array();
+ for (const category of state.app.categories) {
+ const children = parseCategoryRecursively(category, state.selection);
+ nodes.push(convertCategoryToNode(category, children));
+ }
+ return nodes;
+}
+
+export function parseSingleCategory(categoryId: number, state: IApplicationState): INode[] | undefined {
+ const category = state.app.findCategory(categoryId);
+ if (!category) {
+ throw new Error(`Category with id ${categoryId} does not exist`);
+ }
+ const tree = parseCategoryRecursively(category, state.selection);
+ return tree;
+}
+
+function parseCategoryRecursively(
+ parentCategory: ICategory,
+ selection: IUserSelection): INode[] {
+ if (!parentCategory) { throw new Error('parentCategory is undefined'); }
+ if (!selection) { throw new Error('selection is undefined'); }
+
+ const nodes = new Array();
+ if (parentCategory.subCategories && parentCategory.subCategories.length > 0) {
+ for (const subCategory of parentCategory.subCategories) {
+ const subCategoryNodes = parseCategoryRecursively(subCategory, selection);
+ nodes.push(convertCategoryToNode(subCategory, subCategoryNodes));
+ }
+ }
+ if (parentCategory.scripts && parentCategory.scripts.length > 0) {
+ for (const script of parentCategory.scripts) {
+ nodes.push(convertScriptToNode(script, selection));
+ }
+ }
+ return nodes;
+}
+
+function convertCategoryToNode(
+ category: ICategory, children: readonly INode[]): INode {
+ return {
+ id: `${category.id}`,
+ text: category.name,
+ selected: false,
+ children,
+ documentationUrls: category.documentationUrls,
+ };
+}
+
+function convertScriptToNode(script: IScript, selection: IUserSelection): INode {
+ return {
+ id: `${script.id}`,
+ text: script.name,
+ selected: selection.isSelected(script),
+ children: undefined,
+ documentationUrls: script.documentationUrls,
+ };
+}
diff --git a/src/presentation/Scripts/Cards/CardListItemScripts.vue b/src/presentation/Scripts/ScriptsTree/ScriptsTree.vue
similarity index 54%
rename from src/presentation/Scripts/Cards/CardListItemScripts.vue
rename to src/presentation/Scripts/ScriptsTree/ScriptsTree.vue
index f1f3fb05..03e1db70 100644
--- a/src/presentation/Scripts/Cards/CardListItemScripts.vue
+++ b/src/presentation/Scripts/ScriptsTree/ScriptsTree.vue
@@ -1,5 +1,5 @@
-
+
0) {
return; // only interested in script nodes
- }
+ }
const state = await this.getCurrentStateAsync();
if (node.selected) {
state.selection.addSelectedScript(node.id);
@@ -60,40 +62,43 @@
}
@Watch('categoryId')
- public async updateNodesAsync(categoryId: |number) {
- this.nodes = categoryId ?
- await ScriptNodeParser.parseNodes(categoryId, await this.getCurrentStateAsync())
- : undefined;
+ public async initializeNodesAsync(categoryId?: number) {
+ const state = await this.getCurrentStateAsync();
+ if (categoryId) {
+ this.nodes = parseSingleCategory(categoryId, state);
+ } else {
+ this.nodes = parseAllCategories(state);
+ }
}
public filterPredicate(node: INode): boolean {
return this.matches.scriptMatches.some((script: IScript) => script.id === node.id);
}
- private reactToChanges(state: IApplicationState) {
- // Update selection data
- const updateNodeSelection = (node: INode, selectedScripts: ReadonlyArray): INode => {
- return {
- id: node.id,
- text: node.text,
- selected: selectedScripts.some((script) => script.id === node.id),
- children: node.children ? node.children.map((child) => updateNodeSelection(child, selectedScripts)) : [],
- documentationUrls: node.documentationUrls,
- };
- };
- state.selection.changed.on(
- (selectedScripts: ReadonlyArray) =>
- this.nodes = this.nodes.map((node: INode) => updateNodeSelection(node, selectedScripts)),
- );
- // Update search / filter data
- state.filter.filterRemoved.on(() =>
- this.filterText = '');
- state.filter.filtered.on((matches: IFilterMatches) => {
- this.filterText = matches.query;
- this.matches = matches;
- });
+ private handleSelectionChanged(selectedScripts: ReadonlyArray) {
+ this.nodes = this.nodes.map((node: INode) => updateNodeSelection(node, selectedScripts));
+ }
+
+ private handleFilterRemoved() {
+ this.filterText = '';
+ }
+
+ private handleFiltered(matches: IFilterMatches) {
+ this.filterText = matches.query;
+ this.matches = matches;
}
}
+
+ function updateNodeSelection(node: INode, selectedScripts: ReadonlyArray): INode {
+ return {
+ id: node.id,
+ text: node.text,
+ selected: selectedScripts.some((script) => script.id === node.id),
+ children: node.children ? node.children.map((child) => updateNodeSelection(child, selectedScripts)) : [],
+ documentationUrls: node.documentationUrls,
+ };
+ }
+
diff --git a/src/presentation/Scripts/TheScripts.vue b/src/presentation/Scripts/TheScripts.vue
new file mode 100644
index 00000000..13e7b770
--- /dev/null
+++ b/src/presentation/Scripts/TheScripts.vue
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
diff --git a/src/presentation/styles/tree.scss b/src/presentation/styles/tree.scss
index cfa54ae2..d8c16858 100644
--- a/src/presentation/styles/tree.scss
+++ b/src/presentation/styles/tree.scss
@@ -1,8 +1,15 @@
// Overrides base styling for LiquorTree
@import "@/presentation/styles/colors.scss";
+.tree {
+ background-color: $slate;
+}
+
.tree-node > .tree-content > .tree-anchor > span {
color: $white !important;
+ text-transform: uppercase;
+ color: $light-gray;
+ font-size: 1.5em;
}
.tree-node {