feat(devtools): pass each datasource through to it's own material tree component

This commit is contained in:
AleksanderBodurri 2020-03-21 23:07:48 -04:00 committed by Minko Gechev
parent 2d34a209a6
commit 6d0c4093c2
11 changed files with 70 additions and 188 deletions

View file

@ -12,6 +12,11 @@ export enum PropertyViewFilterOptions {
STATE,
}
export interface DirectiveTreeData {
dataSource: PropertyDataSource;
treeControl: FlatTreeControl<FlatNode>;
}
const expandable = (prop: Descriptor) => {
if (!prop) {
return false;
@ -61,9 +66,9 @@ export class DirectivePropertyResolver {
this._onReceivedNestedProperties
);
_inputsDataSource: PropertyDataSource;
_outputsDataSource: PropertyDataSource;
_stateDataSource: PropertyDataSource;
private _inputsDataSource: PropertyDataSource;
private _outputsDataSource: PropertyDataSource;
private _stateDataSource: PropertyDataSource;
constructor(
private _messageBus: MessageBus<Events>,
@ -82,15 +87,15 @@ export class DirectivePropertyResolver {
};
}
get directiveInputControls(): { dataSource: PropertyDataSource; treeControl: FlatTreeControl<FlatNode> } {
get directiveInputControls(): DirectiveTreeData {
return getDirectiveControls(this._inputsDataSource);
}
get directiveOutputControls(): { dataSource: PropertyDataSource; treeControl: FlatTreeControl<FlatNode> } {
get directiveOutputControls(): DirectiveTreeData {
return getDirectiveControls(this._outputsDataSource);
}
get directiveStateControls(): { dataSource: PropertyDataSource; treeControl: FlatTreeControl<FlatNode> } {
get directiveStateControls(): DirectiveTreeData {
return getDirectiveControls(this._stateDataSource);
}

View file

@ -7,7 +7,6 @@ import { map } from 'rxjs/operators';
import { DefaultIterableDiffer } from '@angular/core';
import { diff } from '../../diffing';
import { FlatNode, Property } from './element-property-resolver';
import { PropertyViewFilterOptions } from './directive-property-resolver';
const expandable = (prop: Descriptor, messageBus?: MessageBus<Events>) => {
if (!prop) {
@ -32,8 +31,6 @@ export class PropertyDataSource extends DataSource<FlatNode> {
private _expandedData = new BehaviorSubject<FlatNode[]>([]);
private _differ = new DefaultIterableDiffer(trackBy);
private readonly _originalData: FlatNode[];
constructor(
props: { [prop: string]: Descriptor },
private _treeFlattener: MatTreeFlattener<Property, FlatNode>,
@ -44,8 +41,7 @@ export class PropertyDataSource extends DataSource<FlatNode> {
private _onReceivedNestedProperties: () => void
) {
super();
this._originalData = this._treeFlattener.flattenNodes(this._arrayify(props));
this._data.next(this._originalData);
this._data.next(this._treeFlattener.flattenNodes(this._arrayify(props)));
}
get data(): FlatNode[] {
@ -130,24 +126,4 @@ export class PropertyDataSource extends DataSource<FlatNode> {
this._onReceivedNestedProperties();
});
}
filterDataSource(filter: string[] | null): void {
if (filter === null) {
return;
}
let pushFlag = false;
const filteredData: FlatNode[] = [];
// tslint:disable-next-line:prefer-for-of
for (let i = 0; i < this._originalData.length; i++) {
const node = this._originalData[i];
if (node.level === 0) {
pushFlag = filter.includes(node.prop.name);
}
if (pushFlag) {
filteredData.push(node);
}
}
this._data.next(filteredData);
}
}

View file

@ -1,31 +1,26 @@
<mat-tree *ngIf="treeControl" class="property-list" [dataSource]="dataSource" [treeControl]="treeControl">
<mat-tree-node matTreeNodePaddingIndent="14" *matTreeNodeDef="let node" matTreeNodePadding>
<span class="name non-expandable"> {{ node.prop.name }} </span>:&nbsp;
<ng-container *ngIf="!node.prop.descriptor.editable; else editable">
<span class="value">
{{ node.prop.descriptor.preview }}
</span>
</ng-container>
<ng-template #editable>
<ng-property-editor
[key]="node.prop.name"
[initialValue]="node.prop.descriptor.value || node.prop.descriptor.preview"
(updateValue)="updateValue(node, $event)"
>
</ng-property-editor>
</ng-template>
</mat-tree-node>
<div *ngIf="directiveInputControls.dataSource.data.length > 0">
Inputs
<ng-property-view-tree
[dataSource]="directiveInputControls.dataSource"
[treeControl]="directiveInputControls.treeControl"
(updateValue)="updateValue($event)"
></ng-property-view-tree>
</div>
<mat-tree-node matTreeNodePaddingIndent="14" *matTreeNodeDef="let node; when: hasChild" matTreeNodePadding>
<div (click)="toggle(node)">
<span class="arrow">
{{ treeControl.isExpanded(node) ? '▼' : '►' }}
</span>
&nbsp;
<span class="name"> {{ node.prop.name }} </span>:&nbsp;
<span class="value">
{{ treeControl.isExpanded(node) ? '' : node.prop.descriptor.preview }}
</span>
</div>
</mat-tree-node>
</mat-tree>
<div *ngIf="directiveOutputControls.dataSource.data.length > 0">
Outputs
<ng-property-view-tree
[dataSource]="directiveOutputControls.dataSource"
[treeControl]="directiveOutputControls.treeControl"
(updateValue)="updateValue($event)"
></ng-property-view-tree>
</div>
<div *ngIf="directiveStateControls.dataSource.data.length > 0">
State
<ng-property-view-tree
[dataSource]="directiveStateControls.dataSource"
[treeControl]="directiveStateControls.treeControl"
(updateValue)="updateValue($event)"
></ng-property-view-tree>
</div>

View file

@ -1,47 +1,22 @@
import { Component, Input, OnChanges, OnInit } from '@angular/core';
import { FlatTreeControl } from '@angular/cdk/tree';
import { PropertyDataSource } from '../../../../property-resolver/property-data-source';
import { Component, Input } from '@angular/core';
import {
DirectivePropertyResolver,
DirectiveTreeData,
} from '../../../../property-resolver/directive-property-resolver';
import { FlatNode } from '../../../../property-resolver/element-property-resolver';
import { DirectivePropertyResolver } from '../../../../property-resolver/directive-property-resolver';
@Component({
selector: 'ng-property-view-body',
templateUrl: './property-view-body.component.html',
styleUrls: ['./property-view-body.component.css'],
})
export class PropertyViewBodyComponent implements OnChanges {
@Input() dataSource: PropertyDataSource;
@Input() treeControl: FlatTreeControl<FlatNode>;
export class PropertyViewBodyComponent {
@Input() controller: DirectivePropertyResolver;
@Input() filterList: string[] | null = null;
@Input() directiveInputControls: DirectiveTreeData;
@Input() directiveOutputControls: DirectiveTreeData;
@Input() directiveStateControls: DirectiveTreeData;
hasChild = (_: number, node: FlatNode): boolean => node.expandable;
ngOnChanges(): void {
this.filterTreeNodes();
}
filterTreeNodes(): void {
this.dataSource.filterDataSource(this.filterList);
}
toggle(node: FlatNode): void {
if (this.treeControl.isExpanded(node)) {
this.treeControl.collapse(node);
return;
}
this.expand(node);
}
expand(node: FlatNode): void {
const { prop } = node;
if (!prop.descriptor.expandable) {
return;
}
this.treeControl.expand(node);
}
updateValue(newValue: any, node: FlatNode): void {
this.controller.updateValue(newValue, node);
updateValue({ node, newValue }: { newValue: any; node: FlatNode }): void {
this.controller.updateValue(node, newValue);
}
}

View file

@ -1,4 +1,4 @@
<mat-tree *ngIf="_treeControl" class="property-list" [dataSource]="_dataSource" [treeControl]="_treeControl">
<mat-tree *ngIf="treeControl" class="property-list" [dataSource]="dataSource" [treeControl]="treeControl">
<mat-tree-node matTreeNodePaddingIndent="14" *matTreeNodeDef="let node" matTreeNodePadding>
<span class="name non-expandable"> {{ node.prop.name }} </span>:&nbsp;
<ng-container *ngIf="!node.prop.descriptor.editable; else editable">
@ -17,15 +17,14 @@
</mat-tree-node>
<mat-tree-node matTreeNodePaddingIndent="14" *matTreeNodeDef="let node; when: hasChild" matTreeNodePadding>
LOL
<div (click)="toggle(node)">
<span class="arrow">
{{ _treeControl.isExpanded(node) ? '▼' : '►' }}
{{ treeControl.isExpanded(node) ? '▼' : '►' }}
</span>
&nbsp;
<span class="name"> {{ node.prop.name }} </span>:&nbsp;
<span class="value">
{{ _treeControl.isExpanded(node) ? '' : node.prop.descriptor.preview }}
{{ treeControl.isExpanded(node) ? '' : node.prop.descriptor.preview }}
</span>
</div>
</mat-tree-node>

View file

@ -9,21 +9,15 @@ import { FlatTreeControl } from '@angular/cdk/tree';
styleUrls: ['./property-view-tree.component.css'],
})
export class PropertyViewTreeComponent {
@Input() set dataSource(dataSource: PropertyDataSource) {
this._dataSource = dataSource;
}
@Input() dataSource: PropertyDataSource;
@Input() treeControl: FlatTreeControl<FlatNode>;
@Output() updateValue = new EventEmitter<any>();
_dataSource: PropertyDataSource;
_treeControl: FlatTreeControl<FlatNode>;
hasChild = (_: number, node: FlatNode): boolean => {
return node.expandable;
};
hasChild = (_: number, node: FlatNode): boolean => node.expandable;
toggle(node: FlatNode): void {
if (this._treeControl.isExpanded(node)) {
this._treeControl.collapse(node);
if (this.treeControl.isExpanded(node)) {
this.treeControl.collapse(node);
return;
}
this.expand(node);
@ -34,13 +28,13 @@ export class PropertyViewTreeComponent {
if (!prop.descriptor.expandable) {
return;
}
this._treeControl.expand(node);
this.treeControl.expand(node);
}
handleUpdate(node: FlatNode, updatedValue: any): void {
handleUpdate(node: FlatNode, newValue: any): void {
this.updateValue.emit({
node,
updatedValue,
newValue,
});
}
}

View file

@ -22,7 +22,3 @@ header {
line-height: 15px;
margin-right: 7px;
}
:host /deep/ .mat-button-toggle-appearance-standard .mat-button-toggle-label-content {
line-height: 25px;
}

View file

@ -1,16 +1,5 @@
<header>
<span> Properties of {{ directive }} </span>
<mat-button-toggle-group [multiple]="true" (change)="filterProperties($event)">
<mat-button-toggle [value]="cmpFilterOptions.INPUTS" [checked]="true">
Inputs
</mat-button-toggle>
<mat-button-toggle [value]="cmpFilterOptions.OUTPUTS" [checked]="true">
Outputs
</mat-button-toggle>
<mat-button-toggle [value]="cmpFilterOptions.STATE" [checked]="true">
State
</mat-button-toggle>
</mat-button-toggle-group>
<button mat-icon-button (click)="copyPropData.emit(directive)">
<svg
xmlns="http://www.w3.org/2000/svg"

View file

@ -1,6 +1,4 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { MatButtonToggleChange } from '@angular/material/button-toggle';
import { PropertyViewFilterOptions } from '../../../../property-resolver/directive-property-resolver';
@Component({
selector: 'ng-property-view-header',
@ -9,12 +7,5 @@ import { PropertyViewFilterOptions } from '../../../../property-resolver/directi
})
export class PropertyViewHeaderComponent {
@Input() directive: string;
@Output() filter = new EventEmitter<PropertyViewFilterOptions[]>();
@Output() copyPropData = new EventEmitter<string>();
cmpFilterOptions = PropertyViewFilterOptions;
filterProperties(event: MatButtonToggleChange): void {
this.filter.emit(event.value);
}
}

View file

@ -1,11 +1,7 @@
<ng-property-view-header
[directive]="directive"
(copyPropData)="copyPropData.emit($event)"
(filter)="filter($event)"
></ng-property-view-header>
<ng-property-view-header [directive]="directive" (copyPropData)="copyPropData.emit($event)"></ng-property-view-header>
<ng-property-view-body
[controller]="controller"
[dataSource]="dataSource"
[filterList]="allowedList"
[treeControl]="treeControl"
[directiveInputControls]="directiveInputControls"
[directiveOutputControls]="directiveOutputControls"
[directiveStateControls]="directiveStateControls"
></ng-property-view-body>

View file

@ -1,6 +1,7 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
import {
DirectivePropertyResolver,
DirectiveTreeData,
PropertyViewFilterOptions,
} from '../../../property-resolver/directive-property-resolver';
import { PropertyDataSource } from '../../../property-resolver/property-data-source';
@ -16,56 +17,21 @@ export class PropertyViewComponent {
@Input() directive: string;
@Output() copyPropData = new EventEmitter<string>();
currentFilter: PropertyViewFilterOptions[] = [
PropertyViewFilterOptions.INPUTS,
PropertyViewFilterOptions.OUTPUTS,
PropertyViewFilterOptions.STATE,
];
allowedList: string[] | null = null;
constructor(private _nestedProps: ElementPropertyResolver) {}
get controller(): DirectivePropertyResolver | undefined {
return this._nestedProps.getDirectiveController(this.directive);
}
get dataSource(): PropertyDataSource | void {
if (!this.controller) {
return;
}
return this.controller.getDirectiveControls1().dataSource;
get directiveInputControls(): DirectiveTreeData | void {
return this.controller?.directiveInputControls;
}
get treeControl(): TreeControl<FlatNode> | void {
if (!this.controller) {
return;
}
return this.controller.getDirectiveControls1().treeControl;
get directiveOutputControls(): DirectiveTreeData | void {
return this.controller?.directiveOutputControls;
}
filter(evt: PropertyViewFilterOptions[]): void {
this.currentFilter = evt;
this.computeAllowedList();
}
computeAllowedList(): void {
if (!this.controller || !this.controller.directiveProperties) {
return;
}
const inputList = this.controller.directiveInputs1;
const outputList = this.controller.directiveOutputs1;
const stateList = Object.keys(this.controller.directiveProperties).filter(
prop => !inputList.includes(prop) && !outputList.includes(prop)
);
const propList = {
[PropertyViewFilterOptions.INPUTS]: inputList,
[PropertyViewFilterOptions.OUTPUTS]: outputList,
[PropertyViewFilterOptions.STATE]: stateList,
};
this.allowedList = [].concat.apply(
[],
this.currentFilter.map(filterOption => propList[filterOption])
);
get directiveStateControls(): DirectiveTreeData | void {
return this.controller?.directiveStateControls;
}
}