npm

@smartbit4all/tree
TypeScript icon, indicating that this package has built-in type declarations

2.2.13 • Public • Published

Smart Tree

Please note the all versions from @smartbit4all/tree^2.0.0 are not backward compatible!

Stable versions:

References

These packages must be updated in case of a new version:

  • There are no references yet

How to use

Installation

Go to your project, open the terminal and use the following command:

npm i @smartbit4all/tree

Then import it in the AppModule:

app.module.ts:

import { SmarttreeModule } from '@smartbit4all/tree';
...
@NgModule({
    declarations: [...]
    imports: [
        ...
        SmarttreeModule,
    ],
    providers: [
        ...
        SmarttreeService,
	    TreeService
    ]
    ...
})

Usage

terminal:

>>> cd src/app
>>> mkdir services
>>> cd ./services
>>> ng g s tree

First option: Create a custom inheritance of the SmarttreeService: tree.service.ts:

@Injectable({
    providedIn: 'root'
})
export class MainTreeService extends SmarttreeService<SmartTreeModel> {
    constructor(
        private apiService: BffApiTreeService
    ) {
        super();
    }

    override async downloadTree(): Promise<SmartTreeModel> {
        const treeModel = await this.apiService.getRootNodes().toPromise();
        if (!treeModel) {
            throw new Error('TreeModel is undefined!');
        }
        return treeModel;
    }

    override async downloadChildren(parentNode: SmartTreeNode): Promise<SmartTreeModel> {
        const children = await this.apiService.getChildrenNodes(parentNode).toPromise();
        if (!children) {
            throw new Error(`Node with uri ${parentNode.identifier} does not have children.`);
        }

        return children;
    }

    override onTreeNodeClick(treeNode: SmartTreeNode): void {
        // Handle tree node click
    }

    override onTreeNodeOpen(treeNode: SmartTreeNode): void {
        if (treeNode.expanded && treeNode.childrenNodes && treeNode.childrenNodes.length) {
            treeNode.expanded = false;

            await this.apiService
                .nodeClosed({ identifier: treeNode.identifier! })
                .toPromise()
                .then(() => {
                    this.downloadTree().then((tree) => {
                        this.treeFromBackend = tree;
                        this.syncTree();
                    });
                });
            return;
        }
        await this.downloadChildren(treeNode).then((children: SmartTreeNode[]) => {
            treeNode.expanded = true;
            treeNode.children = children.nodes;

            this.syncTree();
        });
    }

    actionLabelTranslator(code: string): string {
        // Return a readable version of the code
        // Example:
        //  code: addUser
        //  return: Add user
     }

    override syncTree(): void {
        if (!this.treeFromBackend) {
            throw new Error('There is no treeFromBackend available!');
        }
        if (!this.smartTreeModel) {
            this.smartTreeModel = {
                navigationUrlsByNodeType: [],
                rootNodes: []
            };
        }

        let smartTreeNodes: SmartTreeNode[] = this.treeFromBackend.nodes.map((node: SmartTreeNode) => {
            if (node.actions && node.actions.length) {
                // The buttons are customizable
                // Example:
                let button: SmartTreeNodeButton = {
                    type: SmartTreeNodeButtonType.MENU,
                    icon: 'more_vert',
                    menuItemButtons: node.actions.map((action: UiAction) => {
                        type: SmartTreeNodeButtonType.NORMAL,
                        label: this.actionLabelTranslator(action.code),
                        callback: this.doAction.bind(this),
                        args: [action, node.identifier]
                    }),
                }
                node.button = button;
            }
        })

        // Choose from the followings:
        // #1 set up custom buttons
        this.smartTreeModel.rootNodes = this.setButtonsForTreeNodes(this.treeFromBackend.rootNodes);
        // #2 use the tree without custom buttons
        this.smartTreeModel.rootNodes = this.treeFromBackend.rootNodes;

        this.findSelected(this.smartTreeModel.rootNodes);

        this.smartTreeModelChanged.next(this.smartTreeModel);
    }

    // This function is not mandatory and also not defined in the SmarttreeService<T>!
    // The setButtonsForTreeNodes(rootNodes: SmartTreeNode[]) is just a recommendation, place it
    // into your custom TreeService or into a util file.
    setButtonsForTreeNodes(rootNodes: SmartTreeNode[]): SmartTreeNode[] {
        let smartTreeNodes: SmartTreeNode[] = [];

        rootNodes.map((node: SmartTreeNode) => {
            if (node.actions && node.actions.length) {
                // The buttons are customizable
                // Example usage:
                let button: SmartTreeNodeButton = {
                    type: SmartTreeNodeButtonType.MENU,
                    icon: 'more_vert',
                    menuItemButtons: node.actions.map((action: UiAction) => {
                        type: SmartTreeNodeButtonType.NORMAL,
                        label: this.actionLabelTranslator(action.code),
                        callback: this.doAction.bind(this),
                        args: [action, node.identifier]
                    }),
                }
                node.button = button;
            }

            if (node.childrenNodes) {
                node.childrenNodes = this.setButtonsForTreeNodes(node.childrenNodes);
            }

            smartTreeNodes.push(node);
        })

        return smartTreeNodes;
    }

    // Feel free to choose from the followings:
    // First option
    doAction(action: UiAction, identifier: string, args?: any[]): void { ... }
    // Second option
    doAction(args: any[]): void { ... }
}

Second option: Create a custom inheritance of the SmarttreeGenericService:

export class MainTreeService extends SmarttreeGenericService {
    constructor(
        viewContext: SmartViewContextService,
        treeService: TreeService,
    ) {
        super(viewContext, treeService);

        // Example data
        this.configureTree({
            pageName: Pages.Main,
            treeid: `model.tree`,
            viewContextName: Pages.VIEW_CONTEXT
        });
    }

    override getLabelByAction(action: UiAction): string {
        return getActionTranslator(action.code!).title;
    }

    override async doAction(args: any[]): Promise<void> {
        let uiAction: UiAction = args[0];
        let nodeUuid: string = args[1];
        // Do action...
    }
}

app.component.html:

<smart-tree [treeStyle]="treeStyle!" [treeService]="treeService"></smart-tree>

app.component.ts:

export class AppComponent {
    treeStyle?: TreeStyle;

    constructor(public treeService: MainTreeService) {
        // set up the BffApiTreeService (headers and url)

        this.treeService.initialize();

        this.treeStyle = {
            levelBackgroundColor: ['rgba(34, 107, 193, 0.3)', 'rgba(0, 0, 0, 0.15)'],
            activeStyle: {
                backgroundColor: '#1A5DBE',
                color: '#FFF'
            }
        };
    }

}

Version logs

@smartbit4all/tree v2.1.12

Type: Update The SmarttreeService<T> got a new property: errorMessage: string.

This error message will appear when the tree is not available.

@smartbit4all/tree v2.1.2

Type: Update

From now on the backend's responsibility to handle clicking on an already selected node.

@smartbit4all/tree v2.1.1

Type: Update

In this update a generic tree service has been added to the package.

@smartbit4all/tree v2.0.1

Type: Update

@smartbit4all/icon support.

@smartbit4all/tree v2.0.0

Type: Major update

The tree requires a new SmartTreeModel from the backend with the changed SmartTreeNodes:

export interface SmartTreeModel {
    identifier?: string;
    rootNodes?: Array<SmartTreeNode>;
}

export interface SmartTreeNode {
    identifier?: string;
    icon?: string;
    caption?: string;
    classes?: Array<string>;
    hasChildren?: boolean;
    childrenNodes?: Array<SmartTreeNode>;
    expanded?: boolean;
    selected?: boolean;
    level?: number;
    shortDescription?: string;
    nodeType?: string;
    button?: object;
    actions?: Array<UiAction>;
}

SmartreeService changes:

  • SmarttreeService<T, N> -> SmarttreeService<T>
  • The convertRootNodesToSmartTreeNodes(rootNodes: Array<N>) function has been removed.

@smartbit4all/tree v1.1.4

Type: Bugfix

Click event on customly defined button was not stopped from propagation.

@smartbit4all/tree v1.1.1

Type: Bugfix

A bug has been fixed which caused that the tree could only expand the root nodes of the tree.

@smartbit4all/tree v1.1.0

Type: Feature

This update contains two changes:

  1. SmartForm treeStyle before this update could not set the styling of the root nodes. From now the root nodes styling can be setted too.
  2. SmartTreeNode interface has been extended with a new SmartTreeNodeButton typed property. With this property you can define and add buttons to every treeNode and define the callback functions.

How to use the features of this update:

  1. TreeStyle: levelBackground is an array contains the colors in string. The index of an element refers to the level of the treeNode

    this.treeStyle = {
        levelBackgroundColor: ['rgba(34, 107, 193, 0.3)', 'rgba(0, 0, 0, 0.15)'],
            activeStyle: {
                backgroundColor: '#1A5DBE',
                color: '#FFF'
            }
        };
    
  2. SmartTreeNodeButton: add button property to the treeNode object. SmartTreeNodeButton has 3 different type:

  • ICON
  • MENU
  • NORMAL

@smartbit4all/tree v1.0.1

Type: Update

The package has been published.

@smartbit4all/tree v0.1.0

Type: Feature

The usage of tree has been redesigned in order to support the BFF APIs.

New things in this update:

  • SmarttreeServiceDescriptor<T, N>
  • export class SmarttreeService<T, N> implements SmarttreeServiceDescriptor<T, N>

Things that have been changed:

  • SmarttreeComponent does not require a SmarttreeModel anymore
  • SmarttreeComponent requires an inheritance of the SmarttreeService
  • Node click events are no longer handled by the component
  • Node click events can be handled manually in the inheritance of the SmarttreeService

@smartbit4all/tree v0.0.8

Type: Feature

This version contains a routing update, which allows you to navigate to a named outlet.

The change:

The navigationUrl property of the SmartTreeNodeType has changed from string to any[].

export interface SmartTreeNodeType {
    nodeType: string;
    navigationUrl: any[];
}

@smartbit4all/tree v0.0.7

Type: Bugfix

A bug has been fixed which caused routing problems while navigating with objectUri.

The change itself: this.router.navigate(['${navigationUrlByNodeType.navigationUrl}'], { queryParams: { uri: node.objectUri }});

@smartbit4all/tree v0.0.6

Type: Bugfix

The last deselected node could not be selected directly.

@smartbit4all/tree v0.0.5

Type: Bugfix

There were no option to deselect an already selected tree node.

@smartbit4all/tree v0.0.4

Type: Bugfix

Navigating on node click was not working properly.

this.router.navigateByUrl has been replaced with this.router.navigate.

@smartbit4all/tree v0.0.3

Type: Feature

The generated TreeModel has been replaced with SmartTreeModel.

The new SmartTreeModel and SmartTreeNode have new features like setting the node type and its navigation target. Also some optional fields have been changed to required ones.

Readme

Keywords

none

Package Sidebar

Install

npm i @smartbit4all/tree

Weekly Downloads

3

Version

2.2.13

License

none

Unpacked Size

781 kB

Total Files

48

Last publish

Collaborators

  • adam.otvos
  • szabolcs_bazil_papp
  • lipcseizs
  • hbalazs11
  • zoltan.suller
  • attila.mate