1- import { Component , OnDestroy , OnInit , ViewChild , inject , AfterViewInit , ViewChildren , QueryList } from '@angular/core' ;
2- import { CdkDragDrop , moveItemInArray , copyArrayItem , transferArrayItem , CdkDragMove , CdkDragRelease , CdkDropList , CdkDrag } from '@angular/cdk/drag-drop ' ;
1+ import { Component , OnDestroy , OnInit , ViewChild , inject } from '@angular/core' ;
2+ import { DragulaService } from 'ng2-dragula ' ;
33import {
44 NavigationMenuItemIndexedModel ,
55 NavigationMenuItemModel ,
@@ -10,7 +10,6 @@ import {
1010import {
1111 NavigationMenuService ,
1212 SecurityGroupsService ,
13- NavigationMenuDragDropService ,
1413} from 'src/app/common/services' ;
1514import { Subscription , take } from 'rxjs' ;
1615import { AutoUnsubscribe } from 'ngx-auto-unsubscribe' ;
@@ -35,21 +34,20 @@ import {loadAppMenu, selectCurrentUserLocale} from 'src/app/state';
3534 styleUrls : [ './navigation-menu-page.component.scss' ] ,
3635 standalone : false
3736} )
38- export class NavigationMenuPageComponent implements OnInit , OnDestroy , AfterViewInit {
37+ export class NavigationMenuPageComponent implements OnInit , OnDestroy {
3938 private authStore = inject ( Store ) ;
39+ private dragulaService = inject ( DragulaService ) ;
4040 private navigationMenuService = inject ( NavigationMenuService ) ;
4141 private securityGroupsService = inject ( SecurityGroupsService ) ;
4242 private authStateService = inject ( AuthStateService ) ;
4343 private appMenuStateService = inject ( AppMenuStateService ) ;
4444 private dialog = inject ( MatDialog ) ;
4545 private overlay = inject ( Overlay ) ;
4646 private store = inject ( Store ) ;
47- private dragDropService = inject ( NavigationMenuDragDropService ) ;
4847
4948
5049 @ViewChild ( 'resetMenuModal' )
5150 resetMenuModal : NavigationMenuResetComponent ;
52- @ViewChildren ( CdkDropList ) dropLists ?: QueryList < CdkDropList > ;
5351 securityGroups : CommonDictionaryModel [ ] = [ ] ;
5452 navigationMenuModel : NavigationMenuModel = new NavigationMenuModel ( ) ;
5553
@@ -66,60 +64,40 @@ export class NavigationMenuPageComponent implements OnInit, OnDestroy, AfterView
6664 return NavigationMenuItemTypeEnum ;
6765 }
6866
69- getDropdownId ( index : number ) : string {
70- return `dropdown-${ index } ` ;
71- }
72-
73- get connectedDropdownIds ( ) : string [ ] {
74- return this . navigationMenuModel . actualMenu
75- . map ( ( item , index ) => item . type === NavigationMenuItemTypeEnum . Dropdown ? this . getDropdownId ( index ) : null )
76- . filter ( id => id !== null ) as string [ ] ;
77- }
78-
79- /**
80- * Predicate function to determine if dropping is allowed
81- */
82- allowDropPredicate = ( drag : CdkDrag , drop : CdkDropList ) : boolean => {
83- return this . dragDropService . isDropAllowed ( drag , drop ) ;
84- } ;
85-
86- /**
87- * Get all connected drop lists from the service
88- */
89- get connectedLists ( ) : CdkDropList [ ] {
90- return this . dragDropService . dropLists ;
91- }
92-
9367 constructor ( ) {
68+ const dragulaService = this . dragulaService ;
69+
70+ dragulaService . createGroup ( 'MENU_ITEMS' , {
71+ moves : ( el , container , handle ) => {
72+ return handle . classList . contains ( 'dragula-handle' ) ;
73+ } ,
74+ copy : ( el , source ) => {
75+ return source . id === 'mainMenu' || source . id === 'pluginMenu' ;
76+ } ,
77+ copyItem : ( data : NavigationMenuItemModel ) => {
78+ return { ...data , type : NavigationMenuItemTypeEnum . Link , isInternalLink : true , } ;
79+ } ,
80+ accepts : ( el , target ) => {
81+ // To avoid dragging from right to left container
82+ return (
83+ ( target . classList . contains ( 'dragula-item' ) ||
84+ ( target . classList . contains ( 'dragula-dropdown' ) &&
85+ ! el . classList . contains ( 'dragula-dropdown' ) ) ) &&
86+ target . id !== 'mainMenu' &&
87+ target . id !== 'pluginMenu'
88+ ) ;
89+ } ,
90+ } ) ;
91+ this . dragulaService . drop ( 'MENU_ITEMS' ) . subscribe ( ( { name } ) => {
92+ this . dragulaService . find ( name ) . drake . cancel ( true ) ;
93+ } ) ;
9494 }
9595
9696 ngOnInit ( ) : void {
9797 this . getNavigationMenu ( ) ;
9898 this . getSecurityGroups ( ) ;
9999 }
100100
101- ngAfterViewInit ( ) : void {
102- // Register all drop lists with the service after view initialization
103- if ( this . dropLists ) {
104- this . dropLists . forEach ( dropList => {
105- this . dragDropService . register ( dropList ) ;
106- } ) ;
107-
108- // Subscribe to changes in drop lists (for dynamically added dropdowns)
109- this . dropLists . changes . subscribe ( ( ) => {
110- // Use setTimeout to defer the update to avoid ExpressionChangedAfterItHasBeenCheckedError
111- // This ensures the update happens after the current change detection cycle
112- setTimeout ( ( ) => {
113- // Clear and re-register all drop lists when the list changes
114- this . dragDropService . dropLists = [ ] ;
115- this . dropLists ?. forEach ( dropList => {
116- this . dragDropService . register ( dropList ) ;
117- } ) ;
118- } ) ;
119- } ) ;
120- }
121- }
122-
123101 getSecurityGroups ( ) {
124102 this . securityGroupsSub$ = this . securityGroupsService
125103 . getSecurityGroupsDictionary ( )
@@ -153,49 +131,10 @@ export class NavigationMenuPageComponent implements OnInit, OnDestroy, AfterView
153131 ...this . navigationMenuModel . actualMenu ,
154132 model ,
155133 ] ;
156- // Trigger change detection and update drop lists after the new item is rendered
157- // This ensures newly added dropdowns are immediately available as drop targets
158- setTimeout ( ( ) => {
159- if ( this . dropLists ) {
160- this . dragDropService . dropLists = [ ] ;
161- this . dropLists . forEach ( dropList => {
162- this . dragDropService . register ( dropList ) ;
163- } ) ;
164- }
165- } ) ;
166- }
167-
168- dropMenuItem ( event : CdkDragDrop < NavigationMenuItemModel [ ] > ) {
169- if ( event . previousContainer === event . container ) {
170- moveItemInArray ( event . container . data , event . previousIndex , event . currentIndex ) ;
171- } else {
172- // Copy from template menu
173- const item = {
174- ...event . previousContainer . data [ event . previousIndex ] ,
175- type : NavigationMenuItemTypeEnum . Link ,
176- isInternalLink : true
177- } ;
178- this . navigationMenuModel . actualMenu . splice ( event . currentIndex , 0 , item ) ;
179- }
180- this . navigationMenuModel . actualMenu = [ ...this . navigationMenuModel . actualMenu ] ;
181- }
182-
183- dropMenuItemChild ( event : CdkDragDrop < NavigationMenuItemModel [ ] > , parentIndex : number ) {
184- if ( event . previousContainer === event . container ) {
185- moveItemInArray ( event . container . data , event . previousIndex , event . currentIndex ) ;
186- } else {
187- // Copy from template menu
188- const item = {
189- ...event . previousContainer . data [ event . previousIndex ] ,
190- type : NavigationMenuItemTypeEnum . Link ,
191- isInternalLink : true
192- } ;
193- this . navigationMenuModel . actualMenu [ parentIndex ] . children . splice ( event . currentIndex , 0 , item ) ;
194- }
195- this . navigationMenuModel . actualMenu = [ ...this . navigationMenuModel . actualMenu ] ;
196134 }
197135
198136 ngOnDestroy ( ) : void {
137+ this . dragulaService . destroy ( 'MENU_ITEMS' ) ;
199138 }
200139
201140 onItemDelete (
@@ -288,25 +227,15 @@ export class NavigationMenuPageComponent implements OnInit, OnDestroy, AfterView
288227 ) . name ;
289228 }
290229
230+ menuItemModelChange ( $event : any [ ] ) {
231+ this . navigationMenuModel . actualMenu = [ ...$event ] ;
232+ }
233+
291234 getSecurityGroupNames ( ids : number [ ] ) : string [ ] {
292235 return ids . map ( id => {
293236 const group = this . securityGroups . find ( g => g . id === id ) ;
294237 return group ? group . name : '' ;
295238 } ) . filter ( name => name !== '' ) ;
296239 }
297240
298- /**
299- * Handle drag move events to track hover state
300- */
301- onDragMoved ( event : CdkDragMove < any > ) {
302- this . dragDropService . dragMoved ( event ) ;
303- }
304-
305- /**
306- * Handle drag release events to clear hover state
307- */
308- onDragReleased ( event : CdkDragRelease ) {
309- this . dragDropService . dragReleased ( event ) ;
310- }
311-
312241}
0 commit comments