From 1f266c33535f72b69c65985bf2eff27cd2c5a104 Mon Sep 17 00:00:00 2001 From: undergroundwires Date: Sun, 6 Sep 2020 15:26:19 +0100 Subject: [PATCH] fix indeterminate state being lost --- .../SelectableTree/LiquorTree/LiquorTree.d.ts | 1 + .../LiquorTree/LiquorTreeOptions.ts | 3 +- .../NodeWrapper/NodeStateUpdater.ts | 35 ++- .../LiquorTree/NodeWrapper/NodeTranslator.ts | 1 + .../SelectableTree/SelectableTree.vue | 22 +- .../NodeWrapper/NodeStateUpdater.spec.ts | 264 ++++++++++++------ .../NodeWrapper/NodeTranslator.spec.ts | 1 + 7 files changed, 227 insertions(+), 100 deletions(-) diff --git a/src/presentation/Scripts/ScriptsTree/SelectableTree/LiquorTree/LiquorTree.d.ts b/src/presentation/Scripts/ScriptsTree/SelectableTree/LiquorTree/LiquorTree.d.ts index 4af1ff73..b3ed101c 100644 --- a/src/presentation/Scripts/ScriptsTree/SelectableTree/LiquorTree/LiquorTree.d.ts +++ b/src/presentation/Scripts/ScriptsTree/SelectableTree/LiquorTree/LiquorTree.d.ts @@ -20,6 +20,7 @@ declare module 'liquor-tree' { // https://github.com/amsik/liquor-tree/blob/master/src/lib/Node.js export interface ILiquorTreeNodeState { checked: boolean; + indeterminate: boolean; } export interface ILiquorTreeNode { diff --git a/src/presentation/Scripts/ScriptsTree/SelectableTree/LiquorTree/LiquorTreeOptions.ts b/src/presentation/Scripts/ScriptsTree/SelectableTree/LiquorTree/LiquorTreeOptions.ts index e7cff70f..9b6e4a2d 100644 --- a/src/presentation/Scripts/ScriptsTree/SelectableTree/LiquorTree/LiquorTreeOptions.ts +++ b/src/presentation/Scripts/ScriptsTree/SelectableTree/LiquorTree/LiquorTreeOptions.ts @@ -5,9 +5,10 @@ export class LiquorTreeOptions implements ILiquorTreeOptions { public readonly checkbox = true; public readonly checkOnSelect = true; /* For checkbox mode only. Children will have the same checked state as their parent. + ⚠️ Setting this false, does not update indeterminate state of nodes. This is false as it's handled manually to be able to batch select for performance + highlighting */ public readonly autoCheckChildren = false; - public readonly parentSelect = false; + public readonly parentSelect = true; public readonly keyboardNavigation = true; public readonly filter = { // Wrap this in an arrow function as setting filter directly does not work JS APIs emptyText: this.liquorTreeFilter.emptyText, diff --git a/src/presentation/Scripts/ScriptsTree/SelectableTree/LiquorTree/NodeWrapper/NodeStateUpdater.ts b/src/presentation/Scripts/ScriptsTree/SelectableTree/LiquorTree/NodeWrapper/NodeStateUpdater.ts index 1e2a1c9f..d859b879 100644 --- a/src/presentation/Scripts/ScriptsTree/SelectableTree/LiquorTree/NodeWrapper/NodeStateUpdater.ts +++ b/src/presentation/Scripts/ScriptsTree/SelectableTree/LiquorTree/NodeWrapper/NodeStateUpdater.ts @@ -1,14 +1,37 @@ -import { ILiquorTreeNode } from 'liquor-tree'; +import { ILiquorTreeNode, ILiquorTreeNodeState } from 'liquor-tree'; import { NodeType } from './../../Node/INode'; -export function getNewCheckedState( - oldNode: ILiquorTreeNode, +export function getNewState( + node: ILiquorTreeNode, + selectedNodeIds: ReadonlyArray): ILiquorTreeNodeState { + const checked = getNewCheckedState(node, selectedNodeIds); + const indeterminate = !checked && getNewIndeterminateState(node, selectedNodeIds); + return { + checked, indeterminate, + }; +} + +function getNewIndeterminateState( + node: ILiquorTreeNode, selectedNodeIds: ReadonlyArray): boolean { - switch (oldNode.data.type) { + switch (node.data.type) { case NodeType.Script: - return selectedNodeIds.some((id) => id === oldNode.id); + return false; case NodeType.Category: - return parseAllSubScriptIds(oldNode).every((id) => selectedNodeIds.includes(id)); + return parseAllSubScriptIds(node).some((id) => selectedNodeIds.includes(id)); + default: + throw new Error('Unknown node type'); + } +} + +function getNewCheckedState( + node: ILiquorTreeNode, + selectedNodeIds: ReadonlyArray): boolean { + switch (node.data.type) { + case NodeType.Script: + return selectedNodeIds.some((id) => id === node.id); + case NodeType.Category: + return parseAllSubScriptIds(node).every((id) => selectedNodeIds.includes(id)); default: throw new Error('Unknown node type'); } diff --git a/src/presentation/Scripts/ScriptsTree/SelectableTree/LiquorTree/NodeWrapper/NodeTranslator.ts b/src/presentation/Scripts/ScriptsTree/SelectableTree/LiquorTree/NodeWrapper/NodeTranslator.ts index 7e947c6d..f5c5bbe0 100644 --- a/src/presentation/Scripts/ScriptsTree/SelectableTree/LiquorTree/NodeWrapper/NodeTranslator.ts +++ b/src/presentation/Scripts/ScriptsTree/SelectableTree/LiquorTree/NodeWrapper/NodeTranslator.ts @@ -23,6 +23,7 @@ export function toNewLiquorTreeNode(node: INode): ILiquorTreeNewNode { text: node.text, state: { checked: false, + indeterminate: false, }, children: convertChildren(node.children, toNewLiquorTreeNode), data: { diff --git a/src/presentation/Scripts/ScriptsTree/SelectableTree/SelectableTree.vue b/src/presentation/Scripts/ScriptsTree/SelectableTree/SelectableTree.vue index 078eb3b8..74d330a9 100644 --- a/src/presentation/Scripts/ScriptsTree/SelectableTree/SelectableTree.vue +++ b/src/presentation/Scripts/ScriptsTree/SelectableTree/SelectableTree.vue @@ -18,14 +18,15 @@