• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

atinc / ngx-tethys / 68ef226c-f83e-44c1-b8ed-e420a83c5d84

28 May 2025 10:31AM UTC coverage: 10.352% (-80.0%) from 90.316%
68ef226c-f83e-44c1-b8ed-e420a83c5d84

Pull #3460

circleci

pubuzhixing8
chore: xxx
Pull Request #3460: refactor(icon): migrate signal input #TINFR-1476

132 of 6823 branches covered (1.93%)

Branch coverage included in aggregate %.

10 of 14 new or added lines in 1 file covered. (71.43%)

11648 existing lines in 344 files now uncovered.

2078 of 14525 relevant lines covered (14.31%)

6.69 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

1.85
/src/tree/tree.service.ts
1
import { coerceArray, isFunction } from 'ngx-tethys/util';
2
import { BehaviorSubject, Subject } from 'rxjs';
3
import { Injectable, OnDestroy } from '@angular/core';
4
import { ThyTreeNodeCheckState, ThyTreeNodeData, ThyTreeNode, IThyTreeService, ThyTreeFormatEmitEvent } from './tree.class';
5

6
function checkStateResolve(node: ThyTreeNode) {
UNCOV
7
    const checkedNodes = node.children.filter(n => n.isChecked === ThyTreeNodeCheckState.checked);
×
UNCOV
8
    const unCheckedNodes = node.children.filter(n => n.isChecked === ThyTreeNodeCheckState.unchecked);
×
UNCOV
9
    if (checkedNodes.length === node.children.length) {
×
10
        return ThyTreeNodeCheckState.checked;
×
11
    } else if (unCheckedNodes.length === node.children.length) {
UNCOV
12
        return ThyTreeNodeCheckState.unchecked;
×
UNCOV
13
    } else {
×
14
        return ThyTreeNodeCheckState.indeterminate;
15
    }
UNCOV
16
}
×
17

18
type FlattenAllNodesCb = (treeNode: ThyTreeNode) => boolean;
19

20
/**
21
 * @internal
22
 */
1✔
23
@Injectable()
UNCOV
24
export class ThyTreeService implements IThyTreeService, OnDestroy {
×
UNCOV
25
    selectedNode!: ThyTreeNode;
×
UNCOV
26

×
UNCOV
27
    flattenNodes$ = new BehaviorSubject<ThyTreeNode[]>([]);
×
UNCOV
28

×
UNCOV
29
    flattenTreeNodes: ThyTreeNode[] = [];
×
UNCOV
30

×
UNCOV
31
    private originTreeNodes: ThyTreeNodeData[] = [];
×
UNCOV
32

×
33
    public treeNodes: ThyTreeNode[] = [];
34

35
    public checkStateResolve: (node: ThyTreeNode) => ThyTreeNodeCheckState = checkStateResolve;
UNCOV
36

×
UNCOV
37
    statusChange$ = new Subject<ThyTreeFormatEmitEvent>();
×
38

39
    constructor() {
UNCOV
40
        this.statusChange$.pipe().subscribe(event => {
×
UNCOV
41
            this.syncFlattenTreeNodes();
×
UNCOV
42
            this.syncNodeCheckState(event.node);
×
43
        });
44
    }
×
UNCOV
45

×
46
    public initializeTreeNodes(rootNodes: ThyTreeNodeData[]) {
UNCOV
47
        this.originTreeNodes = rootNodes || [];
×
UNCOV
48
        this.treeNodes = (rootNodes || []).map(node => new ThyTreeNode(node, null, this));
×
UNCOV
49
    }
×
UNCOV
50

×
UNCOV
51
    public syncFlattenTreeNodes(): ThyTreeNode[] {
×
52
        this.flattenTreeNodes = this.getParallelTreeNodes(this.treeNodes, false);
53
        this.flattenNodes$.next(this.flattenTreeNodes);
54
        return this.flattenTreeNodes;
UNCOV
55
    }
×
UNCOV
56

×
57
    private getParallelTreeNodes(rootTrees: ThyTreeNode[] = this.treeNodes, flattenAllNodes: boolean | FlattenAllNodesCb = true) {
58
        const flattenTreeData: ThyTreeNode[] = [];
×
UNCOV
59
        function _getParallelTreeNodes(list: ThyTreeNode[]) {
×
60
            return list.forEach((treeNode, index) => {
61
                flattenTreeData.push(treeNode);
62
                const flattenAllNodesFlag = isFunction(flattenAllNodes) ? flattenAllNodes(treeNode) : flattenAllNodes;
×
63
                if (flattenAllNodesFlag || treeNode.isExpanded) {
×
64
                    _getParallelTreeNodes(treeNode.children);
×
65
                }
×
66
            });
×
67
        }
68
        _getParallelTreeNodes(rootTrees);
69
        return flattenTreeData;
UNCOV
70
    }
×
UNCOV
71

×
72
    setCheckStateResolve(resolve: (node: ThyTreeNode) => ThyTreeNodeCheckState = checkStateResolve) {
73
        this.checkStateResolve = resolve;
UNCOV
74
    }
×
UNCOV
75

×
76
    public resetSortedTreeNodes(treeNodes: ThyTreeNode[], parent?: ThyTreeNode) {
77
        treeNodes.forEach(node => {
UNCOV
78
            node.level = node.parentNode ? node.parentNode.level + 1 : 0;
×
UNCOV
79
            node.origin.children = node.children.map(n => n.origin);
×
80
            node.parentNode = parent;
81
            this.resetSortedTreeNodes(node.children, node);
UNCOV
82
        });
×
83
    }
×
84

×
85
    public getTreeNode(key: string | number): ThyTreeNode {
×
86
        const allNodes = this.getParallelTreeNodes(this.treeNodes);
×
87
        return allNodes.find(n => n.key === key);
×
88
    }
×
89

90
    public getExpandedNodes(): ThyTreeNode[] {
91
        const allNodes = this.getParallelTreeNodes(this.treeNodes);
UNCOV
92
        return allNodes.filter(n => n.isExpanded);
×
UNCOV
93
    }
×
UNCOV
94

×
UNCOV
95
    public getCheckedNodes(): ThyTreeNode[] {
×
96
        const allNodes = this.getParallelTreeNodes(this.treeNodes);
97
        return allNodes.filter(n => n.isChecked === ThyTreeNodeCheckState.checked);
98
    }
99

×
UNCOV
100
    public deleteTreeNode(node: ThyTreeNode) {
×
UNCOV
101
        if (node.parentNode) {
×
UNCOV
102
            const children = node.parentNode.children;
×
UNCOV
103
            const index = children.findIndex(n => n.key === node.key);
×
104
            if (index > -1) {
105
                children.splice(index, 1);
UNCOV
106
                node.parentNode.origin.children = children.map(item => item.origin);
×
107
                this.syncNodeCheckState(node.parentNode);
UNCOV
108
            }
×
UNCOV
109
        } else {
×
110
            const index = this.treeNodes.findIndex(n => n.key === node.key);
111
            if (index > -1) {
UNCOV
112
                this.treeNodes.splice(index, 1);
×
UNCOV
113
                this.originTreeNodes.splice(index, 1);
×
UNCOV
114
            }
×
115
        }
116
    }
UNCOV
117

×
118
    public addTreeNode(node: ThyTreeNode, parent?: ThyTreeNode, index = -1) {
UNCOV
119
        if (parent) {
×
120
            const insertNode = new ThyTreeNode(node.origin, parent, this);
121
            if (index > -1) {
122
                parent.children.splice(index, 0, insertNode);
123
            } else {
UNCOV
124
                parent.children.push(insertNode);
×
UNCOV
125
            }
×
UNCOV
126
            parent.origin.children = parent.children.map(item => item.origin);
×
127
            this.syncNodeCheckState(parent);
UNCOV
128
        } else {
×
UNCOV
129
            const insertNode = new ThyTreeNode(node.origin, null, this);
×
130
            if (index > -1) {
UNCOV
131
                this.treeNodes.splice(index, 0, insertNode);
×
132
            } else {
133
                this.treeNodes.push(insertNode);
134
            }
×
UNCOV
135
            this.originTreeNodes = this.treeNodes.map(item => item.origin);
×
UNCOV
136
            // this.syncNodeCheckState(insertNode);
×
137
        }
138
    }
×
UNCOV
139

×
UNCOV
140
    public expandTreeNodes(keyOrKeys: string | number | (string | number)[] | true) {
×
UNCOV
141
        const keys = keyOrKeys === true ? [] : coerceArray(keyOrKeys);
×
142
        const needExpandNodes = this.getParallelTreeNodes(this.treeNodes).filter(node => {
143
            return keys.indexOf(node.key) > -1 || keyOrKeys === true;
UNCOV
144
        });
×
UNCOV
145
        needExpandNodes.forEach(node => {
×
UNCOV
146
            node.setExpanded(true);
×
UNCOV
147
        });
×
UNCOV
148
        this.syncFlattenTreeNodes();
×
UNCOV
149
    }
×
150

151
    // 设置节点选中状态
UNCOV
152
    public setNodeChecked(node: ThyTreeNode, checked: boolean, propagateUp = true, propagateDown = true): void {
×
UNCOV
153
        this._setNodeChecked(node, checked, propagateUp, propagateDown);
×
UNCOV
154
        this.syncFlattenTreeNodes();
×
155
    }
156

157
    private _setNodeChecked(node: ThyTreeNode, checked: boolean, propagateUp = true, propagateDown = true) {
UNCOV
158
        if (propagateDown && node.children) {
×
UNCOV
159
            node.children.forEach(subNode => {
×
160
                this._setNodeChecked(subNode, checked, false, true);
161
            });
UNCOV
162
        }
×
UNCOV
163
        if (!node.isDisabled) {
×
164
            if (node.children.length) {
165
                if (checked) {
166
                    const isAllChildrenChecked = node.children.every(item => item.isChecked === ThyTreeNodeCheckState.checked);
UNCOV
167
                    node.isChecked = isAllChildrenChecked ? ThyTreeNodeCheckState.checked : ThyTreeNodeCheckState.indeterminate;
×
UNCOV
168
                    node.origin.checked = isAllChildrenChecked && checked;
×
169
                } else {
170
                    const isAllChildrenUnChecked = node.children.every(item => item.isChecked === ThyTreeNodeCheckState.unchecked);
UNCOV
171
                    node.isChecked = isAllChildrenUnChecked ? ThyTreeNodeCheckState.unchecked : ThyTreeNodeCheckState.indeterminate;
×
UNCOV
172
                    node.origin.checked = isAllChildrenUnChecked && checked;
×
UNCOV
173
                }
×
174
            } else {
175
                node.isChecked = checked ? ThyTreeNodeCheckState.checked : ThyTreeNodeCheckState.unchecked;
176
                node.origin.checked = checked;
UNCOV
177
            }
×
UNCOV
178
        }
×
179
        if (propagateUp) {
180
            this._syncNodeCheckState(node.parentNode);
1✔
181
        }
182
    }
1✔
183

184
    public syncNodeCheckState(node: ThyTreeNode): void {
185
        this._syncNodeCheckState(node);
186
        this.syncFlattenTreeNodes();
187
    }
188

189
    private _syncNodeCheckState(node: ThyTreeNode) {
190
        if (node) {
191
            node.isChecked = this.checkStateResolve(node);
192
            this._syncNodeCheckState(node.parentNode);
193
        }
194
    }
195

196
    ngOnDestroy(): void {
197
        this.statusChange$.complete();
198
        this.statusChange$ = null;
199
    }
200
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc