import { untracked } from 'mobx' ; import { injectable } from '@cloudbeaver/core-di' ; import { NotificationService } from '@cloudbeaver/core-events' ; import { NavTreeResource } from '../NavTreeResource' ; import type { NavNodeTransformView , INavNodeFolderTransform , NavNodeFolderTransformFn } from './IFolderTransform' ; export interface INodeDuplicateList { nodes : string [ ] ; duplicates : string [ ] ; } @ injectable ( ) export class NavNodeViewService { get tabs ( ) : NavNodeTransformView [ ] { return this . transformers . filter ( transform => transform . tab ) . sort ( sortTransformations ) . map ( transform => transform . tab ! ) ; } get panels ( ) : NavNodeTransformView [ ] { return this . transformers . filter ( transform => transform . panel ) . sort ( sortTransformations ) . map ( transform => transform . panel ! ) ; } get transformations ( ) : NavNodeFolderTransformFn [ ] { return this . transformers . sort ( sortTransformations ) . map ( transform => transform . transformer ) ; } private transformers : INavNodeFolderTransform [ ] ; private duplicationNotify : Set < string > ; constructor ( private navTreeResource , private notificationService ) { this . transformers = [ ] ; this . duplicationNotify = new Set ( ) ; this . addTransform ( { order : 0 , transformer : ( nodeId , children ) => { if ( ! children ) { return children ; } const { nodes , duplicates } = this . filterDuplicates ( children ) ; untracked ( ( ) => { this . logDuplicates ( nodeId , duplicates ) ; } ) ; return nodes ; } , } ) ; } getFolders ( nodeId ) { const children = this . navTreeResource . get ( nodeId ) ; return this . transformations . reduce ( ( children , transform ) => transform ( nodeId , children ) , children ) ; } addTransform ( transform ) { this . transformers . push ( transform ) ; } filterDuplicates ( nodes ) { const nextChildren = [ ] ; const duplicates = [ ] ; for ( const child of nodes ) { if ( nextChildren . includes ( child ) ) { if ( ! duplicates . includes ( child ) ) { duplicates . push ( child ) ; nextChildren . splice ( nextChildren . indexOf ( child ) , 1 ) ; } } else { nextChildren . push ( child ) ; } } return { nodes : nextChildren , duplicates , } ; } logDuplicates ( nodeId , duplicates ) { if ( duplicates . length > 0 && ! this . duplicationNotify . has ( nodeId ) ) { this . duplicationNotify . add ( nodeId ) ; this . notificationService . logError ( { title : 'Node key duplication' , message : 'Duplicate elements were hidden.' , details : duplicates . join ( '\n' ) , onClose : ( ) => this . duplicationNotify . delete ( nodeId ) , } ) ; } } } function sortTransformations ( { order : orderA } , { order : orderB } ) { if ( orderA === orderB ) { return 0 ; } if ( orderA === undefined ) { return 1 ; } if ( orderB === undefined ) { return - 1 ; } return orderA - orderB ; }