-
Notifications
You must be signed in to change notification settings - Fork 269
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* [ACS-4364] Add tree component and categories service * [ACS-4364] Add tree component to public api * [ACS-4364] Refine tree unit tests * [ACS-4364] Intergrate adding and deleting category * [ACS-4364] Restyle load more button in tree component * [ACS-4364] Missing semicolon * [ACS-4364] Fix code styling * [ACS-4364] Add docs for tree component and category service * [ACS-4364] CR fixes * [ACS-4364] Hide header row when displayName is not provided * [ACS-4364] Docs fixes * [ACS-4364] Add helper methods, code cleanup, unit tests for new methods * [ACS-4364] Add missing semicolon
- Loading branch information
1 parent
afb22bb
commit 52520bb
Showing
29 changed files
with
1,964 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,7 @@ | |
"CSRF", | ||
"datacolumn", | ||
"datarow", | ||
"Datasource", | ||
"datatable", | ||
"dateitem", | ||
"datepicker", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
--- | ||
Title: Tree component | ||
Added: v6.0.0.0 | ||
Status: Active | ||
Last reviewed: 2023-01-25 | ||
--- | ||
|
||
# [Tree component](../../../lib/content-services/src/lib/tree/components/tree.component.ts "Defined in tree.component.ts") | ||
|
||
Shows the nodes in tree structure, each node containing children is collapsible/expandable. Can be integrated with any datasource extending [Tree service](../../../lib/content-services//src/lib/tree/services/tree.service.ts). | ||
|
||
![Tree component screenshot](../../docassets/images/tree.png) | ||
|
||
## Basic Usage | ||
|
||
```html | ||
<adf-tree | ||
[displayName]="'Tree display name'" | ||
[loadMoreSuffix]="'subnodes'" | ||
[emptyContentTemplate]="emptyContentTemplate" | ||
[nodeActionsMenuTemplate]="nodeActionsMenuTemplate" | ||
(paginationChanged)="onPaginationChanged($event)"> | ||
</adf-tree> | ||
``` | ||
|
||
## Class members | ||
|
||
### Properties | ||
|
||
| Name | Type | Default value | Description | | ||
| ---- | ---- | ------------- | ----------- | | ||
| emptyContentTemplate | `TemplateRef` | | Template that will be rendered when no nodes are loaded. | | ||
| nodeActionsMenuTemplate | `TemplateRef` | | Template that will be rendered when context menu for given node is opened. | | ||
| stickyHeader | `boolean` | false | If set to true header will be sticky. | | ||
| selectableNodes | `boolean` | false | If set to true nodes will be selectable. | | ||
| displayName | `string` | | Display name for tree title. | | ||
| loadMoreSuffix | `string` | | Suffix added to `Load more` string inside load more node. | | ||
| expandIcon | `string` | `chevron_right` | Icon shown when node is collapsed. | | ||
| collapseIcon | `string` | `expand_more` | Icon showed when node is expanded. | | ||
|
||
|
||
### Events | ||
|
||
| Name | Type | Description | | ||
| ---- | ---- | ----------- | | ||
| paginationChanged | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<PaginationModel>` | Emitted when during loading additional nodes pagination changes. | | ||
|
||
## Details | ||
|
||
### Defining your own custom datasource | ||
|
||
First of all create custom node interface extending [`TreeNode`](../../../lib/content-services/src/lib/tree/models/tree-node.interface.ts) interface or use [`TreeNode`](../../../lib/content-services/src/lib/tree/models/tree-node.interface.ts) when none extra properties are required. | ||
|
||
```ts | ||
export interface CustomNode extends TreeNode | ||
``` | ||
Next create custom datasource service extending [`TreeService`](../../../lib/content-services/src/lib/tree/services/tree.service.ts). Datasource service must implement `getSubNodes` method. It has to be able to provide both root level nodes as well as subnodes. If there are more subnodes to load for a given node it should add node with `LoadMoreNode` node type. Example of custom datasource service can be found in [`Category tree datasource service`](../services/category-tree-datasource.service.md). | ||
```ts | ||
@Injectable({...}) | ||
export class CustomTreeDatasourceService extends TreeService<TreeNode> { | ||
... | ||
public getSubNodes(parentNodeId: string, skipCount?: number, maxItems?: number): Observable<TreeResponse<TreeNode>> { | ||
... | ||
} | ||
``` | ||
Final step is to provide your custom datasource service as tree service in component using `TreeComponent`. | ||
```ts | ||
providers: [ | ||
{ | ||
provide: TreeService, | ||
useClass: CustomTreeDatasourceService, | ||
}, | ||
] | ||
``` | ||
### Enabling nodes selection and listening to selection changes | ||
First step is to provide necessary input value. | ||
```html | ||
<adf-tree | ||
[displayName]="'Tree display name'" | ||
[loadMoreSuffix]="'subnodes'" | ||
[selectableNodes]="true" | ||
[emptyContentTemplate]="emptyContentTemplate" | ||
[nodeActionsMenuTemplate]="nodeActionsMenuTemplate" | ||
(paginationChanged)="onPaginationChanged($event)"> | ||
</adf-tree> | ||
``` | ||
Next inside your component get the `TreeComponent` | ||
```ts | ||
@ViewChild(TreeComponent) | ||
public treeComponent: TreeComponent<TreeNode>; | ||
``` | ||
and listen to selection changes. | ||
```ts | ||
this.treeComponent.treeNodesSelection.changed.subscribe( | ||
(selectionChange: SelectionChange<TreeNode>) => { | ||
this.onTreeSelectionChange(selectionChange); | ||
} | ||
); | ||
``` |
26 changes: 26 additions & 0 deletions
26
docs/content-services/services/category-tree-datasource.service.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
--- | ||
Title: Category tree datasource service | ||
Added: v6.0.0.0 | ||
Status: Active | ||
Last reviewed: 2023-01-25 | ||
--- | ||
|
||
# [Category tree datasource service](../../../lib/content-services/src/lib/category/services/category-tree-datasource.service.ts "Defined in category-tree-datasource.service.ts") | ||
|
||
Datasource service for category tree. | ||
|
||
## Class members | ||
|
||
### Methods | ||
|
||
- **getSubNodes**(parentNodeId: `string`, skipCount?: `number`, maxItems?: `number`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`TreeResponse<CategoryNode>`](../../../lib/content-services/src/lib/tree/models/tree-response.interface.ts)`>`<br/> | ||
Gets categories as nodes for category tree. | ||
- _parentNodeId:_ `string` - Identifier of a parent category | ||
- _skipCount:_ `number` - Number of top categories to skip | ||
- _maxItems:_ `number` - Maximum number of subcategories returned from Observable | ||
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`TreeResponse<CategoryNode>`](../../../lib/content-services/src/lib/tree/models/tree-response.interface.ts)`>` - TreeResponse object containing pagination object and list on nodes | ||
|
||
## Details | ||
|
||
Category tree datasource service acts as datasource for tree component utilizing category service. See the | ||
[Tree component](../../../lib/content-services/src/lib/tree/components/tree.component.ts) and [Tree service](../../../lib/content-services/src/lib/tree/services/tree.service.ts) to get more details on how datasource is used. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
--- | ||
Title: Category service | ||
Added: v6.0.0.0 | ||
Status: Active | ||
Last reviewed: 2023-01-25 | ||
--- | ||
|
||
# [Category service](../../../lib/content-services/src/lib/category/services/category.service.ts "Defined in category.service.ts") | ||
|
||
Manages categories in Content Services. | ||
|
||
## Class members | ||
|
||
### Methods | ||
|
||
- **getSubcategories**(parentCategoryId: `string`, skipCount?: `number`, maxItems?: `number`): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`CategoryPaging`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/api/content-rest-api/docs/CategoryPaging.md)`>`<br/> | ||
Gets subcategories of a given parent category. | ||
- _parentCategoryId:_ `string` - Identifier of a parent category | ||
- _skipCount:_ `number` - Number of top categories to skip | ||
- _maxItems:_ `number` - Maximum number of subcategories returned from Observable | ||
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`CategoryPaging`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/api/content-rest-api/docs/CategoryPaging.md)`>` - CategoryPaging object (defined in JS-API) with category paging list | ||
- **createSubcategory**(parentCategoryId: `string`, payload: [`CategoryBody`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/api/content-rest-api/docs/CategoryBody.md)): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`CategoryEntry`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/api/content-rest-api/docs/CategoryEntry.md)`>`<br/> | ||
Creates subcategory under category with provided categoryId. | ||
- _parentCategoryId:_ `string` - Identifier of a parent category | ||
- _payload:_ [`CategoryBody`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/api/content-rest-api/docs/CategoryBody.md) - Created category body | ||
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`CategoryEntry`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/api/content-rest-api/docs/CategoryEntry.md)`>` - CategoryEntry object (defined in JS-API) containing the category | ||
- **updateCategory**(categoryId: `string`, payload: [`CategoryBody`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/api/content-rest-api/docs/CategoryBody.md)): [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`CategoryEntry`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/api/content-rest-api/docs/CategoryEntry.md)`>`<br/> | ||
Updates category. | ||
- _categoryId:_ `string` - Identifier of a category | ||
- _payload:_ [`CategoryBody`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/api/content-rest-api/docs/CategoryBody.md) - Created category body | ||
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`CategoryEntry`](https://github.com/Alfresco/alfresco-js-api/blob/master/src/api/content-rest-api/docs/CategoryEntry.md)`>` - CategoryEntry object (defined in JS-API) containing the category | ||
- **deleteCategory**(categoryId: `string`): [`Observable`](http://reactivex.io/documentation/observable.html)`<void>`<br/> | ||
Deletes category. | ||
- _categoryId:_ `string` - Identifier of a category | ||
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<void>` - Null object when the operation completes | ||
|
||
## Details | ||
|
||
See the | ||
[Categories API](https://github.com/Alfresco/alfresco-js-api/blob/master/src/api/content-rest-api/docs/CategoriesApi.md) | ||
in the Alfresco JS API for more information about the types returned by [Category | ||
service](category.service.md) methods and for the implementation of the REST API the service is | ||
based on. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/*! | ||
* @license | ||
* Copyright 2019 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'; |
38 changes: 38 additions & 0 deletions
38
lib/content-services/src/lib/category/mock/category-mock.service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/*! | ||
* @license | ||
* Copyright 2019 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 { CategoryEntry, CategoryPaging } from '@alfresco/js-api'; | ||
import { Observable, of } from 'rxjs'; | ||
|
||
@Injectable({ providedIn: 'root' }) | ||
export class CategoryServiceMock { | ||
|
||
public getSubcategories(parentNodeId: string, skipCount?: number, maxItems?: number): Observable<CategoryPaging> { | ||
return parentNodeId ? of(this.getChildrenLevelResponse(skipCount, maxItems)) : of(this.getRootLevelResponse(skipCount, maxItems)); | ||
} | ||
|
||
private getRootLevelResponse(skipCount?: number, maxItems?: number): CategoryPaging { | ||
const rootCategoryEntry: CategoryEntry = {entry: {id: 'testId', name: 'testNode', parentId: '-root-', hasChildren: true}}; | ||
return {list: {pagination: {skipCount, maxItems, hasMoreItems: false}, entries: [rootCategoryEntry]}}; | ||
} | ||
|
||
private getChildrenLevelResponse(skipCount?: number, maxItems?: number): CategoryPaging { | ||
const childCategoryEntry: CategoryEntry = {entry: {id: 'childId', name: 'childNode', parentId: 'testId', hasChildren: false}}; | ||
return {list: {pagination: {skipCount, maxItems, hasMoreItems: true}, entries: [childCategoryEntry]}}; | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
lib/content-services/src/lib/category/models/category-node.interface.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/*! | ||
* @license | ||
* Copyright 2019 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 { TreeNode } from '../../tree/models/tree-node.interface'; | ||
|
||
export interface CategoryNode extends TreeNode { | ||
description?: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/*! | ||
* @license | ||
* Copyright 2019 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 './services/category.service'; | ||
export * from './services/category-tree-datasource.service'; | ||
export * from './models/category-node.interface'; |
72 changes: 72 additions & 0 deletions
72
lib/content-services/src/lib/category/services/category-tree-datasource.service.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/*! | ||
* @license | ||
* Copyright 2019 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 { CoreTestingModule } from '@alfresco/adf-core'; | ||
import { fakeAsync, TestBed } from '@angular/core/testing'; | ||
import { CategoryService } from '../services/category.service'; | ||
import { CategoryTreeDatasourceService } from './category-tree-datasource.service'; | ||
import { CategoryServiceMock } from '../mock/category-mock.service'; | ||
import { TreeNodeType, TreeResponse } from '../../tree'; | ||
import { CategoryNode } from '../models/category-node.interface'; | ||
|
||
describe('CategoryTreeDatasourceService', () => { | ||
let categoryTreeDatasourceService: CategoryTreeDatasourceService; | ||
|
||
beforeEach(() => { | ||
TestBed.configureTestingModule({ | ||
imports: [ | ||
CoreTestingModule | ||
], | ||
providers: [ | ||
{ provide: CategoryService, useClass: CategoryServiceMock } | ||
] | ||
}); | ||
|
||
categoryTreeDatasourceService = TestBed.inject(CategoryTreeDatasourceService); | ||
}); | ||
|
||
it('should get root level categories', fakeAsync(() => { | ||
spyOn(categoryTreeDatasourceService, 'getParentNode').and.returnValue(undefined); | ||
categoryTreeDatasourceService.getSubNodes(null, 0 , 100).subscribe((treeResponse: TreeResponse<CategoryNode>) => { | ||
expect(treeResponse.entries.length).toBe(1); | ||
expect(treeResponse.entries[0].level).toBe(0); | ||
expect(treeResponse.entries[0].nodeType).toBe(TreeNodeType.RegularNode); | ||
}); | ||
})); | ||
|
||
it('should get child level categories and add loadMore node when there are more children to load', fakeAsync(() => { | ||
const parentNode: CategoryNode = { | ||
id: 'testId', | ||
nodeName: 'testNode', | ||
parentId: '-root-', | ||
hasChildren: true, | ||
level: 0, | ||
isLoading: false, | ||
nodeType: TreeNodeType.RegularNode | ||
}; | ||
spyOn(categoryTreeDatasourceService, 'getParentNode').and.returnValue(parentNode); | ||
categoryTreeDatasourceService.getSubNodes(parentNode.id, 0 , 100).subscribe((treeResponse: TreeResponse<CategoryNode>) => { | ||
expect(treeResponse.entries.length).toBe(2); | ||
expect(treeResponse.entries[0].parentId).toBe(parentNode.id); | ||
expect(treeResponse.entries[0].level).toBe(1); | ||
expect(treeResponse.entries[0].nodeType).toBe(TreeNodeType.RegularNode); | ||
expect(treeResponse.entries[1].id).toBe('loadMore'); | ||
expect(treeResponse.entries[1].parentId).toBe(parentNode.id); | ||
expect(treeResponse.entries[1].nodeType).toBe(TreeNodeType.LoadMoreNode); | ||
}); | ||
})); | ||
}); |
Oops, something went wrong.