Skip to content

Commit

Permalink
fix: common tree implementation aas-tree, aas-table
Browse files Browse the repository at this point in the history
  • Loading branch information
raronpxcsw committed Feb 15, 2024
1 parent 8a66e61 commit 271a41f
Show file tree
Hide file tree
Showing 37 changed files with 1,024 additions and 1,025 deletions.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"CONTENT_ROOT": "projects/aas-server/build",
"WEB_ROOT": "projects/aas-portal/dist",
"ASSETS": "projects/aas-server/src/assets",
"USER_STORAGE": "mongodb://localhost:27017/aasportal-users",
// "USER_STORAGE": "mongodb://localhost:27017/aasportal-users",
// "TEMPLATE_STORAGE": "http://localhost:8080/templates",
// "AAS_INDEX": "mysql://localhost:3306",
"ENDPOINTS": "[\"file:///endpoints/samples?name=Samples\"]",
Expand Down
6 changes: 4 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

113 changes: 57 additions & 56 deletions projects/aas-lib/src/lib/aas-table/aas-table.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -72,70 +72,71 @@
}
</tbody>
</table>
} @else {
<table class="table table-sm table-borderless table-hover table-striped">
} @else {
<table class="table table-sm table-borderless table-hover table-striped">
<thead>
<tr>
<th class="th-w-checkbox">
<input type="checkbox" class="form-check-input" [indeterminate]="someSelected | async"
[checked]="everySelected | async" (change)="toggleSelections()">
</th>
<th scope="col">
<div class="text-center" translate>COLUMN_NAME</div>
</th>
<th scope="col">
<div class="text-center" translate>COLUMN_ID</div>
</th>
</tr>
</thead>
<tbody>
@for (row of rows | async; track row) {
<tr class="align-middle">
<tr>
<th class="th-w-checkbox">
<input type="checkbox" class="form-check-input" [indeterminate]="someSelected | async"
[checked]="everySelected | async" (change)="toggleSelections()">
</th>
<th scope="col">
<div class="text-center" translate>COLUMN_NAME</div>
</th>
<th scope="col">
<div class="text-center" translate>COLUMN_ID</div>
</th>
</tr>
</thead>
<tbody>
@for (row of rows | async; track row) {
<tr class="align-middle">
<td>
<input type="checkbox" class="form-check-input" (change)="toggleSelected(row)"
<input type="checkbox" class="form-check-input" (change)="toggleSelected(row)"
[checked]="row.selected" [name]="row.name" />
</td>
<td>
</td>
<td>
<div class="d-flex" style="overflow-x: hidden">
<div [ngStyle]="{'width': (row.level * 16) + 'px'}"></div>
@if (!row.isLeaf && !row.expanded && row.hasChildren) {
<a href="javascript:void(0);"
(click)="expand(row)">
<div class="text-dark">
<i class="bi bi-plus-square"></i>
</div>
</a>
}
@if (!row.isLeaf && !row.expanded && !row.hasChildren) {
<div class="text-muted">
<i class="bi bi-square"></i>
</div>
}
@if (!row.isLeaf && row.expanded) {
<a href="javascript:void(0);" (click)="collapse(row)">
<div class="text-dark">
<i class="bi bi-dash-square"></i>
</div>
</a>
}
@if (row.isLeaf) {
<div [ngStyle]="{'width': (row.level * 16) + 'px'}"></div>
@if (row.isLeaf) {
<div class="text-muted wh-4"></div>
}
<div class="ms-2">
}@else {
@if (row.expanded) {
<a href="javascript:void(0);" (click)="collapse(row)">
<div class="text-dark">
<i class="bi bi-dash-square"></i>
</div>
</a>
}@else {
@if (row.hasChildren) {
<a href="javascript:void(0);"
(click)="expand(row)">
<div class="text-dark">
<i class="bi bi-plus-square"></i>
</div>
</a>
}@else {
<div class="text-muted">
<i class="bi bi-square"></i>
</div>
}
}
}
<div class="ms-2">
<img class="img-fluid" width="40" height="40" [src]="row.thumbnail" alt="" />
</div>
<div class="ms-2 flex-grow-1">
</div>
<div class="ms-2 flex-grow-1">
<a class="text-nowrap" href="javascript:void(0);" (click)="open(row)">{{row.name |
max:60}}</a>
</div>
</div>
</div>
</td>
<td>
</td>
<td>
<div>{{row.endpoint}}</div>
<div class="text-nowrap" placement="top" [ngbTooltip]="getToolTip(row)">{{row.id | max:80}}</div>
</td>
</tr>
}
</tbody>
</table>
}
</td>
</tr>
}
</tbody>
</table>
}
26 changes: 21 additions & 5 deletions projects/aas-lib/src/lib/aas-table/aas-table.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ export class AASTableEffects {
const rows = documents.map(document => {
const row = map.get(`${document.endpoint}:${document.id}`);
if (row) {
return row.document === document ? row : this.cloneD(row, document);
return row.document === document ? row : this.cloneWithNewDocument(row, document);
}

return new AASTableRow(document, false, false, false, -1, -1, -1);
return new AASTableRow(document, -1, false, false, false, false, -1, -1, -1);
});

return rows;
Expand All @@ -69,7 +69,7 @@ export class AASTableEffects {
documents.forEach(document => {
const row = map.get(`${document.endpoint}:${document.id}`);
if (row) {
rows.push(row.document === document ? row : this.cloneD(row, document));
rows.push(row.document === document ? row : this.cloneWithNewDocument(row, document));
} else {
nodes.push(document);
}
Expand All @@ -89,6 +89,8 @@ export class AASTableEffects {
const children = nodes.filter(node => this.isChild(root, node));
const rootRow = new AASTableRow(
root,
-1,
false,
false,
false,
children.length === 0,
Expand All @@ -115,7 +117,17 @@ export class AASTableEffects {
let previous: AASTableRow | null = null;
const children = nodes.filter(node => this.isChild(parent, node));
for (const child of children) {
const row = new AASTableRow(child, false, false, children.length === 0, level, -1, -1);
const row = new AASTableRow(
child,
rows.length - 1,
false,
false,
false,
children.length === 0,
level,
-1,
-1,
);

rows.push(row);
if (previous) {
Expand All @@ -142,20 +154,24 @@ export class AASTableEffects {
private clone(row: AASTableRow): AASTableRow {
return new AASTableRow(
row.document,
row.parent,
row.selected,
row.expanded,
row.highlighted,
row.isLeaf,
row.level,
row.firstChild,
row.nextSibling,
);
}

private cloneD(row: AASTableRow, document: AASDocument): AASTableRow {
private cloneWithNewDocument(row: AASTableRow, document: AASDocument): AASTableRow {
return new AASTableRow(
document,
row.parent,
row.selected,
row.expanded,
row.highlighted,
row.isLeaf,
row.level,
row.firstChild,
Expand Down
105 changes: 17 additions & 88 deletions projects/aas-lib/src/lib/aas-table/aas-table.reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import { createReducer, on } from '@ngrx/store';
import { AASDocument } from 'common';
import * as AASTableActions from './aas-table.actions';
import { AASTableRow, AASTableState } from './aas-table.state';
import { AASTableRow, AASTableState, AASTableTree } from './aas-table.state';
import { ViewMode } from '../types/view-mode';

const initialState: AASTableState = {
Expand All @@ -34,110 +34,39 @@ export const aasTableReducer = createReducer(
function setViewMode(state: AASTableState, viewMode: ViewMode): AASTableState {
return state.viewMode !== viewMode ? { ...state, rows: [], viewMode } : state;
}

function setRows(state: AASTableState, rows: AASTableRow[]): AASTableState {
return { ...state, rows };
}

function setSelections(state: AASTableState, documents: AASDocument[]): AASTableState {
const rows = [...state.rows];
const set = new Set(documents);
for (let i = 0, n = rows.length; i < n; i++) {
const row = rows[i];
if (!row.selected && set.has(row.document)) {
rows[i] = clone(row, true);
} else if (row.selected) {
rows[i] = clone(row, false);
}
}

return { ...state, rows };
const tree = new AASTableTree(state.rows);
tree.selectedElements = documents;
return { ...state, rows: tree.nodes };
}

function toggleSelected(state: AASTableState, row: AASTableRow, altKey: boolean, shiftKey: boolean): AASTableState {
let rows: AASTableRow[];
if (altKey) {
rows = state.rows.map(item =>
item === row ? clone(row, !row.selected) : item.selected ? clone(item, false) : item,
);
} else if (shiftKey) {
const index = state.rows.indexOf(row);
let begin = index;
let end = index;
const selection = state.rows.map(row => row.selected);
const last = selection.lastIndexOf(true);
if (last >= 0) {
if (last > index) {
begin = index;
end = selection.indexOf(true);
} else if (last < index) {
begin = last;
end = index;
}
}

rows = [];
for (let i = 0, n = state.rows.length; i < n; i++) {
const row = state.rows[i];
if (i < begin || i > end) {
rows.push(row.selected ? clone(row, false) : row);
} else {
rows.push(row.selected ? row : clone(row, true));
}
}
} else {
const i = state.rows.indexOf(row);
rows = [...state.rows];
rows[i] = clone(row, !row.selected);
}

return { ...state, rows };
const tree = new AASTableTree(state.rows);
tree.toggleSelected(row, altKey, shiftKey);
return { ...state, rows: tree.nodes };
}

function toggleSelections(state: AASTableState): AASTableState {
const rows = [...state.rows];
if (rows.length > 0) {
const value = !rows.every(row => row.selected);
for (let index = 0, n = rows.length; index < n; ++index) {
const row = rows[index];
if (row.selected !== value) {
rows[index] = clone(row, value);
}
}
}

return { ...state, rows };
}

function clone(row: AASTableRow, selected?: boolean): AASTableRow {
if (selected === undefined) {
selected = row.selected;
}

return new AASTableRow(
row.document,
selected,
row.expanded,
row.isLeaf,
row.level,
row.firstChild,
row.nextSibling,
);
const tree = new AASTableTree(state.rows);
tree.toggleSelections();
return { ...state, rows: tree.nodes };
}

function expandRow(state: AASTableState, row: AASTableRow): AASTableState {
const rows = [...state.rows];
const index = rows.indexOf(row);
rows[index] = new AASTableRow(row.document, false, true, row.isLeaf, row.level, row.firstChild, row.nextSibling);

return { ...state, rows };
const tree = new AASTableTree(state.rows);
tree.expand(row);
return { ...state, rows: tree.nodes };
}

function collapseRow(state: AASTableState, row: AASTableRow): AASTableState {
const rows = [...state.rows];
const index = rows.indexOf(row);
rows[index] = new AASTableRow(row.document, false, false, row.isLeaf, row.level, row.firstChild, row.nextSibling);

return { ...state, rows };
const tree = new AASTableTree(state.rows);
tree.collapse(row);
return { ...state, rows: tree.nodes };
}

function setFilter(state: AASTableState, filter?: string): AASTableState {
Expand Down
Loading

0 comments on commit 271a41f

Please sign in to comment.