mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ADF-3723] Tree view component (#3939)
* [ADF-3723] added first step to adf tree view component * [ADF-3723] start adding tests for the new component * [ADF-3723] fixed style and start adding tests * [ADF-3723] working on unit test * [ADF-3723] added test for the new tree view component * [ADF-3723] added event when clicked on a tree node * [ADF-3723] refactored code * [ADF-3723 added peer review changes * [ADF-3723] fixed extra space * [ADF-3723] fixed unit test * [ADF-3723] fixed failing unit test
This commit is contained in:
@@ -85,7 +85,8 @@
|
|||||||
"WORD_TO_SEARCH": "Search Word",
|
"WORD_TO_SEARCH": "Search Word",
|
||||||
"SEARCH_CREATED_BY": "Created By",
|
"SEARCH_CREATED_BY": "Created By",
|
||||||
"SEARCH_SERVICE_APPROACH": "Check this to disable the input property and configure using the service",
|
"SEARCH_SERVICE_APPROACH": "Check this to disable the input property and configure using the service",
|
||||||
"HEADER_DATA": "Header Data"
|
"HEADER_DATA": "Header Data",
|
||||||
|
"TREE_VIEW": "Tree View"
|
||||||
},
|
},
|
||||||
"TRASHCAN": {
|
"TRASHCAN": {
|
||||||
"ACTIONS": {
|
"ACTIONS": {
|
||||||
|
@@ -12,8 +12,8 @@
|
|||||||
"clientId": "activiti",
|
"clientId": "activiti",
|
||||||
"scope": "openid",
|
"scope": "openid",
|
||||||
"secret": "",
|
"secret": "",
|
||||||
"implicitFlow": true,
|
"implicitFlow": false,
|
||||||
"silentLogin": true,
|
"silentLogin": false,
|
||||||
"redirectUri": "/",
|
"redirectUri": "/",
|
||||||
"redirectUriLogout": "/logout"
|
"redirectUriLogout": "/logout"
|
||||||
},
|
},
|
||||||
|
@@ -67,6 +67,7 @@ import { ProcessServicesCloudModule } from '@alfresco/adf-process-services-cloud
|
|||||||
import { CloudComponent } from './components/cloud/cloud.component';
|
import { CloudComponent } from './components/cloud/cloud.component';
|
||||||
import { TaskListCloudDemoComponent } from './components/task-list-cloud-demo/task-list-cloud-demo.component';
|
import { TaskListCloudDemoComponent } from './components/task-list-cloud-demo/task-list-cloud-demo.component';
|
||||||
import { ProcessListCloudExampleComponent } from './components/cloud/process-list-cloud-example.component';
|
import { ProcessListCloudExampleComponent } from './components/cloud/process-list-cloud-example.component';
|
||||||
|
import { TreeViewSampleComponent } from './components/tree-view/tree-view-sample.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -117,7 +118,8 @@ import { ProcessListCloudExampleComponent } from './components/cloud/process-lis
|
|||||||
FormLoadingComponent,
|
FormLoadingComponent,
|
||||||
ReportIssueComponent,
|
ReportIssueComponent,
|
||||||
TaskListCloudDemoComponent,
|
TaskListCloudDemoComponent,
|
||||||
ProcessListCloudExampleComponent
|
ProcessListCloudExampleComponent,
|
||||||
|
TreeViewSampleComponent
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
|
@@ -43,6 +43,7 @@ import { AppComponent } from './app.component';
|
|||||||
import { CloudComponent } from './components/cloud/cloud.component';
|
import { CloudComponent } from './components/cloud/cloud.component';
|
||||||
import { TaskListCloudDemoComponent } from './components/task-list-cloud-demo/task-list-cloud-demo.component';
|
import { TaskListCloudDemoComponent } from './components/task-list-cloud-demo/task-list-cloud-demo.component';
|
||||||
import { ProcessListCloudExampleComponent } from './components/cloud/process-list-cloud-example.component';
|
import { ProcessListCloudExampleComponent } from './components/cloud/process-list-cloud-example.component';
|
||||||
|
import { TreeViewSampleComponent } from './components/tree-view/tree-view-sample.component';
|
||||||
|
|
||||||
export const appRoutes: Routes = [
|
export const appRoutes: Routes = [
|
||||||
{ path: 'login', component: LoginComponent },
|
{ path: 'login', component: LoginComponent },
|
||||||
@@ -279,6 +280,11 @@ export const appRoutes: Routes = [
|
|||||||
component: DemoPermissionComponent,
|
component: DemoPermissionComponent,
|
||||||
canActivate: [AuthGuardEcm]
|
canActivate: [AuthGuardEcm]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'treeview',
|
||||||
|
component: TreeViewSampleComponent,
|
||||||
|
canActivate: [AuthGuardEcm]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'about',
|
path: 'about',
|
||||||
loadChildren: 'app/components/about/about.module#AppAboutModule'
|
loadChildren: 'app/components/about/about.module#AppAboutModule'
|
||||||
|
@@ -58,6 +58,7 @@ export class AppLayoutComponent implements OnInit {
|
|||||||
{ href: '/extendedSearch', icon: 'search', title: 'APP_LAYOUT.SEARCH' },
|
{ href: '/extendedSearch', icon: 'search', title: 'APP_LAYOUT.SEARCH' },
|
||||||
/* cspell:disable-next-line */
|
/* cspell:disable-next-line */
|
||||||
{ href: '/overlay-viewer', icon: 'pageview', title: 'APP_LAYOUT.OVERLAY_VIEWER' },
|
{ href: '/overlay-viewer', icon: 'pageview', title: 'APP_LAYOUT.OVERLAY_VIEWER' },
|
||||||
|
{ href: '/treeview', icon: 'nature', title: 'APP_LAYOUT.TREE_VIEW' },
|
||||||
{ href: '/about', icon: 'info_outline', title: 'APP_LAYOUT.ABOUT' }
|
{ href: '/about', icon: 'info_outline', title: 'APP_LAYOUT.ABOUT' }
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@@ -0,0 +1,10 @@
|
|||||||
|
<div>TREE VIEW TEST</div>
|
||||||
|
<mat-form-field class="example-full-width">
|
||||||
|
<input matInput placeholder="Node Id" [(ngModel)]="nodeIdSample">
|
||||||
|
</mat-form-field>
|
||||||
|
<span>
|
||||||
|
CLICKED NODE: {{clickedNodeName}}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<adf-tree-view-list [nodeId]="nodeIdSample" (nodeClicked)="onClick($event)">
|
||||||
|
</adf-tree-view-list>
|
@@ -0,0 +1,3 @@
|
|||||||
|
.example-full-width {
|
||||||
|
width: 100%;
|
||||||
|
}
|
@@ -0,0 +1,34 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-tree-view',
|
||||||
|
templateUrl: 'tree-view-sample.component.html',
|
||||||
|
styleUrls: ['tree-view-sample.component.scss']
|
||||||
|
})
|
||||||
|
export class TreeViewSampleComponent {
|
||||||
|
|
||||||
|
clickedNodeName: string = '';
|
||||||
|
|
||||||
|
nodeIdSample: string = '-my-';
|
||||||
|
|
||||||
|
onClick(node) {
|
||||||
|
this.clickedNodeName = node.entry.name;
|
||||||
|
}
|
||||||
|
}
|
32
docs/content-services/tree-view.component.md
Normal file
32
docs/content-services/tree-view.component.md
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
Added: v2.6.1
|
||||||
|
Status: Active
|
||||||
|
---
|
||||||
|
|
||||||
|
# Rating component
|
||||||
|
|
||||||
|
Allow a user to show the folder and subfolders of a node in a tree view
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Basic Usage
|
||||||
|
|
||||||
|
```html
|
||||||
|
<adf-tree-view-list [nodeId]="'74cd8a96-8a21-47e5-9b3b-a1b3e296787d'"
|
||||||
|
(nodeClicked)="onClick($event)">
|
||||||
|
</adf-tree-view-list>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Class members
|
||||||
|
|
||||||
|
### Properties
|
||||||
|
|
||||||
|
| Name | Type | Default value | Description |
|
||||||
|
| ---- | ---- | ------------- | ----------- |
|
||||||
|
| nodeId | `string` | | Identifier of the node to apply the rating to. |
|
||||||
|
|
||||||
|
### Events
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | ---- | ----------- |
|
||||||
|
| nodeClicked | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<NodeEntry>` | Emitted when a node on the tree view is clicked |
|
BIN
docs/docassets/images/tree-view.png
Normal file
BIN
docs/docassets/images/tree-view.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
@@ -38,6 +38,7 @@ import { DialogModule } from './dialogs/dialog.module';
|
|||||||
import { FolderDirectiveModule } from './folder-directive/folder-directive.module';
|
import { FolderDirectiveModule } from './folder-directive/folder-directive.module';
|
||||||
import { ContentMetadataModule } from './content-metadata/content-metadata.module';
|
import { ContentMetadataModule } from './content-metadata/content-metadata.module';
|
||||||
import { PermissionManagerModule } from './permission-manager/permission-manager.module';
|
import { PermissionManagerModule } from './permission-manager/permission-manager.module';
|
||||||
|
import { TreeViewModule } from './tree-view/tree-view.module';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -61,7 +62,8 @@ import { PermissionManagerModule } from './permission-manager/permission-manager
|
|||||||
FolderDirectiveModule,
|
FolderDirectiveModule,
|
||||||
ContentDirectiveModule,
|
ContentDirectiveModule,
|
||||||
PermissionManagerModule,
|
PermissionManagerModule,
|
||||||
VersionManagerModule
|
VersionManagerModule,
|
||||||
|
TreeViewModule
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
SocialModule,
|
SocialModule,
|
||||||
@@ -79,7 +81,8 @@ import { PermissionManagerModule } from './permission-manager/permission-manager
|
|||||||
FolderDirectiveModule,
|
FolderDirectiveModule,
|
||||||
ContentDirectiveModule,
|
ContentDirectiveModule,
|
||||||
PermissionManagerModule,
|
PermissionManagerModule,
|
||||||
VersionManagerModule
|
VersionManagerModule,
|
||||||
|
TreeViewModule
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class ContentModuleLazy {}
|
export class ContentModuleLazy {}
|
||||||
@@ -106,7 +109,8 @@ export class ContentModuleLazy {}
|
|||||||
FolderDirectiveModule,
|
FolderDirectiveModule,
|
||||||
ContentDirectiveModule,
|
ContentDirectiveModule,
|
||||||
PermissionManagerModule,
|
PermissionManagerModule,
|
||||||
VersionManagerModule
|
VersionManagerModule,
|
||||||
|
TreeViewModule
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
@@ -134,7 +138,8 @@ export class ContentModuleLazy {}
|
|||||||
FolderDirectiveModule,
|
FolderDirectiveModule,
|
||||||
ContentDirectiveModule,
|
ContentDirectiveModule,
|
||||||
PermissionManagerModule,
|
PermissionManagerModule,
|
||||||
VersionManagerModule
|
VersionManagerModule,
|
||||||
|
TreeViewModule
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class ContentModule {
|
export class ContentModule {
|
||||||
|
@@ -289,5 +289,8 @@
|
|||||||
"DUPLICATE-PERMISSION": "One or more of the permissions you have set is already present : {{list}}",
|
"DUPLICATE-PERMISSION": "One or more of the permissions you have set is already present : {{list}}",
|
||||||
"NOT-ALLOWED": "You are not allowed to change permissions"
|
"NOT-ALLOWED": "You are not allowed to change permissions"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"ADF-TREE-VIEW": {
|
||||||
|
"MISSING-ID": "No nodeId provided!"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -35,7 +35,8 @@ import {
|
|||||||
MatDatepickerModule,
|
MatDatepickerModule,
|
||||||
MatSlideToggleModule,
|
MatSlideToggleModule,
|
||||||
MatRadioModule,
|
MatRadioModule,
|
||||||
MatSliderModule
|
MatSliderModule,
|
||||||
|
MatTreeModule
|
||||||
} from '@angular/material';
|
} from '@angular/material';
|
||||||
|
|
||||||
export function modules() {
|
export function modules() {
|
||||||
@@ -58,7 +59,8 @@ export function modules() {
|
|||||||
MatDatepickerModule,
|
MatDatepickerModule,
|
||||||
MatSlideToggleModule,
|
MatSlideToggleModule,
|
||||||
MatRadioModule,
|
MatRadioModule,
|
||||||
MatSliderModule
|
MatSliderModule,
|
||||||
|
MatTreeModule
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
@import '../permission-manager/components/add-permission/add-permission.component';
|
@import '../permission-manager/components/add-permission/add-permission.component';
|
||||||
@import '../permission-manager/components/add-permission/add-permission-dialog.component';
|
@import '../permission-manager/components/add-permission/add-permission-dialog.component';
|
||||||
@import '../permission-manager/components/add-permission/add-permission-panel.component';
|
@import '../permission-manager/components/add-permission/add-permission-panel.component';
|
||||||
|
@import '../tree-view/components/tree-view.component';
|
||||||
|
|
||||||
@mixin adf-content-services-theme($theme) {
|
@mixin adf-content-services-theme($theme) {
|
||||||
@include adf-breadcrumb-theme($theme);
|
@include adf-breadcrumb-theme($theme);
|
||||||
@@ -36,4 +37,5 @@
|
|||||||
@include adf-add-permission-theme($theme);
|
@include adf-add-permission-theme($theme);
|
||||||
@include adf-add-permission-dialog-theme($theme);
|
@include adf-add-permission-dialog-theme($theme);
|
||||||
@include adf-add-permission-panel-theme($theme);
|
@include adf-add-permission-panel-theme($theme);
|
||||||
|
@include adf-tree-view-theme($theme);
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,21 @@
|
|||||||
|
<mat-tree class="adf-tree-view-main" [dataSource]="dataSource" [treeControl]="treeControl" *ngIf="nodeId; else missingNodeId">
|
||||||
|
<mat-tree-node class="adf-tree-view-node" *matTreeNodeDef="let treeNode" id="{{treeNode.name + '-tree-node'}}"
|
||||||
|
matTreeNodePadding [matTreeNodePaddingIndent]="15">
|
||||||
|
{{treeNode.name}}
|
||||||
|
</mat-tree-node>
|
||||||
|
<mat-tree-node class="adf-tree-view-node" id="{{treeNode.name + '-tree-child-node'}}" *matTreeNodeDef="let treeNode; when: hasChild"
|
||||||
|
matTreeNodePadding [matTreeNodePaddingIndent]="15">
|
||||||
|
<button id="{{'button-'+treeNode.name}}" (click)="onNodeClicked(treeNode.node)"
|
||||||
|
mat-icon-button [attr.aria-label]="'toggle ' + treeNode.filename" matTreeNodeToggle>
|
||||||
|
<mat-icon class="adf-tree-view-icon">
|
||||||
|
{{treeControl.isExpanded(treeNode) ? 'folder_open' : 'folder'}}
|
||||||
|
</mat-icon>
|
||||||
|
</button>
|
||||||
|
{{treeNode.name}}
|
||||||
|
</mat-tree-node>
|
||||||
|
</mat-tree>
|
||||||
|
<ng-template #missingNodeId>
|
||||||
|
<div id="adf-tree-view-missing-node">
|
||||||
|
{{'ADF-TREE-VIEW.MISSING-ID' | translate}}
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
@@ -0,0 +1,17 @@
|
|||||||
|
@mixin adf-tree-view-theme($theme) {
|
||||||
|
$primary: map-get($theme, primary);
|
||||||
|
$foreground: map-get($theme, foreground);
|
||||||
|
$background: map-get($theme, background);
|
||||||
|
|
||||||
|
.adf {
|
||||||
|
&-tree-view-icon {
|
||||||
|
color: #D9E022;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-tree-view-node.mat-tree-node {
|
||||||
|
min-height: 40px;
|
||||||
|
font-size: 12px;
|
||||||
|
align-items: baseline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,181 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { setupTestBed } from '@alfresco/adf-core';
|
||||||
|
import { TreeViewComponent } from './tree-view.component';
|
||||||
|
import { ContentTestingModule } from '../../testing/content.testing.module';
|
||||||
|
import { TreeViewService } from '../services/tree-view.service';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
import { TreeBaseNode } from '../models/tree-view.model';
|
||||||
|
import { NodeEntry } from 'alfresco-js-api';
|
||||||
|
|
||||||
|
describe('TreeViewComponent', () => {
|
||||||
|
|
||||||
|
let fixture: ComponentFixture<TreeViewComponent>;
|
||||||
|
let element: HTMLElement;
|
||||||
|
let treeService: TreeViewService;
|
||||||
|
let component: any;
|
||||||
|
|
||||||
|
let fakeNodeList: TreeBaseNode[] = [
|
||||||
|
{ nodeId: 'fake-node-id', name: 'fake-node-name', level: 0, expandable: true,
|
||||||
|
node: { entry: { name: 'fake-node-name', id: 'fake-node-id' } } }
|
||||||
|
];
|
||||||
|
|
||||||
|
let fakeChildrenList: TreeBaseNode[] = [
|
||||||
|
{ nodeId: 'fake-child-id', name: 'fake-child-name', level: 0, expandable: true, node : {} },
|
||||||
|
{ nodeId: 'fake-second-id', name: 'fake-second-name', level: 0, expandable: true, node : {} }
|
||||||
|
];
|
||||||
|
|
||||||
|
let fakeNextChildrenList: TreeBaseNode[] = [
|
||||||
|
{ nodeId: 'fake-next-child-id', name: 'fake-next-child-name', level: 0, expandable: true, node : {} },
|
||||||
|
{ nodeId: 'fake-next-second-id', name: 'fake-next-second-name', level: 0, expandable: true, node : {} }
|
||||||
|
];
|
||||||
|
|
||||||
|
let returnRootOrChildrenNode = function (nodeId: string) {
|
||||||
|
if (nodeId === '9999999') {
|
||||||
|
return of(fakeNodeList);
|
||||||
|
} else if (nodeId === 'fake-second-id') {
|
||||||
|
return of(fakeNextChildrenList);
|
||||||
|
} else {
|
||||||
|
return of(fakeChildrenList);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
setupTestBed({
|
||||||
|
imports: [
|
||||||
|
ContentTestingModule
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('When there is a nodeId', () => {
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
treeService = TestBed.get(TreeViewService);
|
||||||
|
fixture = TestBed.createComponent(TreeViewComponent);
|
||||||
|
element = fixture.nativeElement;
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
spyOn(treeService, 'getTreeNodes').and.callFake((nodeId) => returnRootOrChildrenNode(nodeId));
|
||||||
|
component.nodeId = '9999999';
|
||||||
|
fixture.detectChanges();
|
||||||
|
}));
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
fixture.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show the folder', async(() => {
|
||||||
|
expect(element.querySelector('#fake-node-name-tree-child-node')).not.toBeNull();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should show the subfolders when the folder is clicked', async(() => {
|
||||||
|
let rootFolderButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#button-fake-node-name');
|
||||||
|
expect(rootFolderButton).not.toBeNull();
|
||||||
|
rootFolderButton.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect(element.querySelector('#fake-child-name-tree-child-node')).not.toBeNull();
|
||||||
|
expect(element.querySelector('#fake-second-name-tree-child-node')).not.toBeNull();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should throw a nodeClicked event when a node is clicked', (done) => {
|
||||||
|
component.nodeClicked.subscribe((nodeClicked: NodeEntry) => {
|
||||||
|
expect(nodeClicked).toBeDefined();
|
||||||
|
expect(nodeClicked).not.toBeNull();
|
||||||
|
expect(nodeClicked.entry.name).toBe('fake-node-name');
|
||||||
|
expect(nodeClicked.entry.id).toBe('fake-node-id');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
let rootFolderButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#button-fake-node-name');
|
||||||
|
expect(rootFolderButton).not.toBeNull();
|
||||||
|
rootFolderButton.click();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should change the icon of the opened folders', async(() => {
|
||||||
|
let rootFolderButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#button-fake-node-name');
|
||||||
|
expect(rootFolderButton).not.toBeNull();
|
||||||
|
expect(element.querySelector('#button-fake-node-name .mat-icon').textContent.trim()).toBe('folder');
|
||||||
|
rootFolderButton.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect(element.querySelector('#button-fake-node-name .mat-icon').textContent.trim()).toBe('folder_open');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should show the subfolders of a subfolder if there are any', async(() => {
|
||||||
|
let rootFolderButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#button-fake-node-name');
|
||||||
|
expect(rootFolderButton).not.toBeNull();
|
||||||
|
rootFolderButton.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect(element.querySelector('#fake-second-name-tree-child-node')).not.toBeNull();
|
||||||
|
let childButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#button-fake-second-name');
|
||||||
|
expect(childButton).not.toBeNull();
|
||||||
|
childButton.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect(element.querySelector('#fake-next-child-name-tree-child-node')).not.toBeNull();
|
||||||
|
expect(element.querySelector('#fake-next-second-name-tree-child-node')).not.toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should hide the subfolders when clicked again', async(() => {
|
||||||
|
let rootFolderButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#button-fake-node-name');
|
||||||
|
expect(rootFolderButton).not.toBeNull();
|
||||||
|
rootFolderButton.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect(element.querySelector('#fake-child-name-tree-child-node')).not.toBeNull();
|
||||||
|
expect(element.querySelector('#fake-second-name-tree-child-node')).not.toBeNull();
|
||||||
|
rootFolderButton.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect(element.querySelector('#button-fake-node-name .mat-icon').textContent.trim()).toBe('folder');
|
||||||
|
expect(element.querySelector('#fake-child-name-tree-child-node')).toBeNull();
|
||||||
|
expect(element.querySelector('#fake-second-name-tree-child-node')).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('When no nodeId is given', () => {
|
||||||
|
|
||||||
|
let emptyElement: HTMLElement;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
fixture = TestBed.createComponent(TreeViewComponent);
|
||||||
|
emptyElement = fixture.nativeElement;
|
||||||
|
}));
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
fixture.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show an error message when no nodeId is provided', async(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(emptyElement.querySelector('#adf-tree-view-missing-node')).toBeDefined();
|
||||||
|
expect(emptyElement.querySelector('#adf-tree-view-missing-node')).not.toBeNull();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
});
|
@@ -0,0 +1,77 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { FlatTreeControl } from '@angular/cdk/tree';
|
||||||
|
import { Component, Input, OnInit, OnChanges, SimpleChanges, Output, EventEmitter } from '@angular/core';
|
||||||
|
import { TreeBaseNode } from '../models/tree-view.model';
|
||||||
|
import { TreeViewDataSource } from '../data/tree-view-datasource';
|
||||||
|
import { TreeViewService } from '../services/tree-view.service';
|
||||||
|
import { NodeEntry } from 'alfresco-js-api';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'adf-tree-view-list',
|
||||||
|
templateUrl: 'tree-view.component.html',
|
||||||
|
styleUrls: ['tree-view.component.scss']
|
||||||
|
})
|
||||||
|
|
||||||
|
export class TreeViewComponent implements OnInit, OnChanges {
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
nodeId: string;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
nodeClicked: EventEmitter<NodeEntry> = new EventEmitter();
|
||||||
|
|
||||||
|
treeControl: FlatTreeControl<TreeBaseNode>;
|
||||||
|
dataSource: TreeViewDataSource;
|
||||||
|
|
||||||
|
constructor(private treeViewService: TreeViewService) {
|
||||||
|
this.treeControl = new FlatTreeControl<TreeBaseNode>(this.getLevel, this.isExpandable);
|
||||||
|
this.dataSource = new TreeViewDataSource(this.treeControl, this.treeViewService);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
if (this.nodeId) {
|
||||||
|
this.loadTreeNode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
|
if (changes['nodeId'].currentValue &&
|
||||||
|
changes['nodeId'].currentValue !== changes['nodeId'].previousValue) {
|
||||||
|
this.loadTreeNode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onNodeClicked(node: NodeEntry) {
|
||||||
|
this.nodeClicked.emit(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
getLevel = (node: TreeBaseNode) => node.level;
|
||||||
|
|
||||||
|
isExpandable = (node: TreeBaseNode) => node.expandable;
|
||||||
|
|
||||||
|
hasChild = (level: number, nodeData: TreeBaseNode) => nodeData.expandable;
|
||||||
|
|
||||||
|
private loadTreeNode() {
|
||||||
|
this.treeViewService.getTreeNodes(this.nodeId)
|
||||||
|
.subscribe(
|
||||||
|
(treeNode: TreeBaseNode[]) => {
|
||||||
|
this.dataSource.data = treeNode;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
91
lib/content-services/tree-view/data/tree-view-datasource.ts
Normal file
91
lib/content-services/tree-view/data/tree-view-datasource.ts
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { CollectionViewer, SelectionChange } from '@angular/cdk/collections';
|
||||||
|
import { BehaviorSubject, merge, Observable } from 'rxjs';
|
||||||
|
import { map } from 'rxjs/operators';
|
||||||
|
import { FlatTreeControl } from '@angular/cdk/tree';
|
||||||
|
import { TreeBaseNode } from '../models/tree-view.model';
|
||||||
|
import { TreeViewService } from '../services/tree-view.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class TreeViewDataSource {
|
||||||
|
|
||||||
|
treeNodes: TreeBaseNode[];
|
||||||
|
dataChange = new BehaviorSubject<TreeBaseNode[]>([]);
|
||||||
|
|
||||||
|
get data(): TreeBaseNode[] {
|
||||||
|
return this.treeNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
set data(value: TreeBaseNode[]) {
|
||||||
|
this.treeControl.dataNodes = value;
|
||||||
|
this.dataChange.next(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(private treeControl: FlatTreeControl<TreeBaseNode>,
|
||||||
|
private treeViewService: TreeViewService) {
|
||||||
|
this.dataChange.subscribe((treeNodes) => this.treeNodes = treeNodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(collectionViewer: CollectionViewer): Observable<TreeBaseNode[]> {
|
||||||
|
this.treeControl.expansionModel.onChange!.subscribe(change => {
|
||||||
|
if ((change as SelectionChange<TreeBaseNode>).added &&
|
||||||
|
(change as SelectionChange<TreeBaseNode>).added.length > 0) {
|
||||||
|
this.expandTreeNodes(change as SelectionChange<TreeBaseNode>);
|
||||||
|
} else if ((change as SelectionChange<TreeBaseNode>).removed) {
|
||||||
|
this.reduceTreeNodes(change as SelectionChange<TreeBaseNode>);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return merge(collectionViewer.viewChange, this.dataChange).pipe(map(() => this.data));
|
||||||
|
}
|
||||||
|
|
||||||
|
private expandTreeNodes(change: SelectionChange<TreeBaseNode>) {
|
||||||
|
change.added.forEach(node => this.expandNode(node));
|
||||||
|
}
|
||||||
|
|
||||||
|
private reduceTreeNodes(change: SelectionChange<TreeBaseNode>) {
|
||||||
|
change.removed.slice().reverse().forEach(node => this.toggleNode(node));
|
||||||
|
}
|
||||||
|
|
||||||
|
private expandNode(node: TreeBaseNode) {
|
||||||
|
this.treeViewService.getTreeNodes(node.nodeId).subscribe((children) => {
|
||||||
|
const index = this.data.indexOf(node);
|
||||||
|
if (!children || index < 0) {
|
||||||
|
node.expandable = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const nodes = children.map(actualNode => {
|
||||||
|
actualNode.level = node.level + 1;
|
||||||
|
return actualNode;
|
||||||
|
});
|
||||||
|
this.data.splice(index + 1, 0, ...nodes);
|
||||||
|
this.dataChange.next(this.data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleNode(node: TreeBaseNode) {
|
||||||
|
const index = this.data.indexOf(node);
|
||||||
|
let count = 0;
|
||||||
|
for (let i = index + 1; i < this.data.length
|
||||||
|
&& this.data[i].level > node.level; i++ , count++) { }
|
||||||
|
this.data.splice(index + 1, count);
|
||||||
|
this.dataChange.next(this.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
18
lib/content-services/tree-view/index.ts
Normal file
18
lib/content-services/tree-view/index.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export * from './public-api';
|
34
lib/content-services/tree-view/models/tree-view.model.ts
Normal file
34
lib/content-services/tree-view/models/tree-view.model.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { NodeEntry } from 'alfresco-js-api';
|
||||||
|
|
||||||
|
export class TreeBaseNode {
|
||||||
|
|
||||||
|
name: string;
|
||||||
|
nodeId: string;
|
||||||
|
level: number;
|
||||||
|
expandable = true;
|
||||||
|
node: NodeEntry;
|
||||||
|
|
||||||
|
constructor(nodeEntry: NodeEntry, level?: number) {
|
||||||
|
this.name = nodeEntry.entry.name;
|
||||||
|
this.level = level ? level : 0;
|
||||||
|
this.nodeId = nodeEntry.entry.id;
|
||||||
|
this.node = nodeEntry;
|
||||||
|
}
|
||||||
|
}
|
21
lib/content-services/tree-view/public-api.ts
Normal file
21
lib/content-services/tree-view/public-api.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export * from './tree-view.module';
|
||||||
|
export * from './components/tree-view.component';
|
||||||
|
export * from './data/tree-view-datasource';
|
||||||
|
export * from './models/tree-view.model';
|
@@ -0,0 +1,68 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { setupTestBed, NodesApiService } from '@alfresco/adf-core';
|
||||||
|
import { TreeViewService } from './tree-view.service';
|
||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
import { ContentTestingModule } from '../../testing/content.testing.module';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
import { TreeBaseNode } from 'tree-view/models/tree-view.model';
|
||||||
|
|
||||||
|
describe('TreeViewService', () => {
|
||||||
|
|
||||||
|
let service: TreeViewService;
|
||||||
|
let nodeService: NodesApiService;
|
||||||
|
|
||||||
|
let fakeNodeList = { list: { entries: [
|
||||||
|
{ entry: { id: 'fake-node-id', name: 'fake-node-name', isFolder: true } }
|
||||||
|
] } };
|
||||||
|
|
||||||
|
let fakeMixedNodeList = { list: { entries: [
|
||||||
|
{ entry: { id: 'fake-node-id', name: 'fake-node-name', isFolder: true } },
|
||||||
|
{ entry: { id: 'fake-file-id', name: 'fake-file-name', isFolder: false } }
|
||||||
|
] } };
|
||||||
|
|
||||||
|
setupTestBed({
|
||||||
|
imports: [ContentTestingModule]
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
service = TestBed.get(TreeViewService);
|
||||||
|
nodeService = TestBed.get(NodesApiService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should returns TreeBaseNode elements', (done) => {
|
||||||
|
spyOn(nodeService, 'getNodeChildren').and.returnValue(of(fakeNodeList));
|
||||||
|
service.getTreeNodes('fake-node-id').subscribe((nodes: TreeBaseNode[]) => {
|
||||||
|
expect(nodes.length).toBe(1);
|
||||||
|
expect(nodes[0].nodeId).toBe('fake-node-id');
|
||||||
|
expect(nodes[0].name).toBe('fake-node-name');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should returns only folders elements', (done) => {
|
||||||
|
spyOn(nodeService, 'getNodeChildren').and.returnValue(of(fakeMixedNodeList));
|
||||||
|
service.getTreeNodes('fake-node-id').subscribe((nodes: TreeBaseNode[]) => {
|
||||||
|
expect(nodes.length).toBe(1);
|
||||||
|
expect(nodes[0].nodeId).toBe('fake-node-id');
|
||||||
|
expect(nodes[0].name).toBe('fake-node-name');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
43
lib/content-services/tree-view/services/tree-view.service.ts
Normal file
43
lib/content-services/tree-view/services/tree-view.service.ts
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { NodesApiService } from '@alfresco/adf-core';
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { TreeBaseNode } from '../models/tree-view.model';
|
||||||
|
import { NodePaging, NodeEntry } from 'alfresco-js-api';
|
||||||
|
import { map } from 'rxjs/operators';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class TreeViewService {
|
||||||
|
|
||||||
|
constructor(private nodeApi: NodesApiService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
getTreeNodes(nodeId): Observable<TreeBaseNode[]> {
|
||||||
|
return this.nodeApi.getNodeChildren(nodeId)
|
||||||
|
.pipe(
|
||||||
|
map((nodePage: NodePaging) => {
|
||||||
|
return nodePage.list.entries.filter((node) => node.entry.isFolder ? node : null);
|
||||||
|
}),
|
||||||
|
map((nodes: NodeEntry[]) => nodes.map(node => new TreeBaseNode(node)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
38
lib/content-services/tree-view/tree-view.module.ts
Normal file
38
lib/content-services/tree-view/tree-view.module.ts
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright 2016 Alfresco Software, Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { MaterialModule } from '../material.module';
|
||||||
|
import { TreeViewComponent } from './components/tree-view.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
MaterialModule,
|
||||||
|
TranslateModule.forChild()
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
TreeViewComponent
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
TreeViewComponent
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class TreeViewModule {
|
||||||
|
}
|
Reference in New Issue
Block a user