1+ import { createDispatchMap , select } from '@ngxs/store' ;
2+
13import { TranslatePipe } from '@ngx-translate/core' ;
24
35import { Button } from 'primeng/button' ;
46import { Checkbox } from 'primeng/checkbox' ;
57import { DynamicDialogConfig , DynamicDialogRef } from 'primeng/dynamicdialog' ;
68
7- import { ChangeDetectionStrategy , Component , inject , OnInit , signal } from '@angular/core' ;
9+ import { ChangeDetectionStrategy , Component , effect , inject , OnInit , signal } from '@angular/core' ;
810import { FormControl , FormsModule , ReactiveFormsModule } from '@angular/forms' ;
911
10- import { TextInputComponent } from '@osf/shared/components' ;
12+ import { GetComponents , ProjectOverviewSelectors } from '@osf/features/project/overview/store' ;
13+ import { LoadingSpinnerComponent , TextInputComponent } from '@osf/shared/components' ;
1114import { InputLimits } from '@osf/shared/constants' ;
1215import { CustomValidators } from '@osf/shared/helpers' ;
13- import { ViewOnlyLinkNodeModel } from '@osf/ shared/models' ;
16+ import { ViewOnlyLinkComponent } from '@shared/models' ;
1417
1518@Component ( {
1619 selector : 'osf-create-view-link-dialog' ,
17- imports : [ Button , TranslatePipe , ReactiveFormsModule , FormsModule , Checkbox , TextInputComponent ] ,
20+ imports : [
21+ Button ,
22+ TranslatePipe ,
23+ ReactiveFormsModule ,
24+ FormsModule ,
25+ Checkbox ,
26+ TextInputComponent ,
27+ LoadingSpinnerComponent ,
28+ ] ,
1829 templateUrl : './create-view-link-dialog.component.html' ,
1930 styleUrl : './create-view-link-dialog.component.scss' ,
2031 changeDetection : ChangeDetectionStrategy . OnPush ,
@@ -28,54 +39,129 @@ export class CreateViewLinkDialogComponent implements OnInit {
2839
2940 anonymous = signal ( true ) ;
3041 protected selectedComponents = signal < Record < string , boolean > > ( { } ) ;
31- readonly projectId = signal ( '' ) ;
42+ protected components = select ( ProjectOverviewSelectors . getComponents ) ;
43+ protected isLoading = select ( ProjectOverviewSelectors . getComponentsLoading ) ;
44+
45+ protected actions = createDispatchMap ( {
46+ getComponents : GetComponents ,
47+ } ) ;
48+
49+ get currentProjectId ( ) : string {
50+ return this . config . data ?. [ 'projectId' ] || '' ;
51+ }
52+
53+ get allComponents ( ) : ViewOnlyLinkComponent [ ] {
54+ const currentProjectData = this . config . data ?. [ 'currentProject' ] ;
55+ const components = this . components ( ) ;
56+
57+ const result : ViewOnlyLinkComponent [ ] = [ ] ;
58+
59+ if ( currentProjectData ) {
60+ result . push ( {
61+ id : currentProjectData . id ,
62+ title : currentProjectData . title ,
63+ isCurrentProject : true ,
64+ } ) ;
65+ }
66+
67+ components . forEach ( ( comp ) => {
68+ result . push ( {
69+ id : comp . id ,
70+ title : comp . title ,
71+ isCurrentProject : false ,
72+ } ) ;
73+ } ) ;
74+
75+ return result ;
76+ }
77+
78+ constructor ( ) {
79+ effect ( ( ) => {
80+ const components = this . allComponents ;
81+ if ( components . length ) {
82+ this . initializeSelection ( ) ;
83+ }
84+ } ) ;
85+ }
3286
3387 ngOnInit ( ) : void {
34- const data = ( this . config . data ?. [ 'sharedComponents' ] as ViewOnlyLinkNodeModel [ ] ) || [ ] ;
35- this . projectId . set ( this . config . data ?. projectId ) ;
36- const initialState = data . reduce (
37- ( acc , curr ) => {
38- if ( curr . id ) {
39- acc [ curr . id ] = true ;
40- }
41- return acc ;
42- } ,
43- { } as Record < string , boolean >
44- ) ;
88+ const projectId = this . currentProjectId ;
89+
90+ if ( projectId ) {
91+ this . actions . getComponents ( projectId ) ;
92+ } else {
93+ this . initializeSelection ( ) ;
94+ }
95+ }
96+
97+ private initializeSelection ( ) : void {
98+ const initialState : Record < string , boolean > = { } ;
99+
100+ this . allComponents . forEach ( ( component ) => {
101+ initialState [ component . id ] = component . isCurrentProject ;
102+ } ) ;
103+
45104 this . selectedComponents . set ( initialState ) ;
46105 }
47106
48- isCurrentProject ( item : ViewOnlyLinkNodeModel ) : boolean {
49- return item . category === 'project' && item . id === this . projectId ( ) ;
107+ isCurrentProject ( item : ViewOnlyLinkComponent ) : boolean {
108+ return item . isCurrentProject ;
109+ }
110+
111+ get isFormValid ( ) : boolean {
112+ return this . linkName . valid && ! ! this . linkName . value . trim ( ) . length ;
50113 }
51114
52115 addLink ( ) : void {
53- if ( ! this . linkName . value ) return ;
116+ if ( ! this . isFormValid ) return ;
54117
55- const components = ( this . config . data ?. [ 'sharedComponents' ] as ViewOnlyLinkNodeModel [ ] ) || [ ] ;
56- const selectedIds = Object . entries ( this . selectedComponents ( ) ) . filter ( ( [ component , checked ] ) => checked ) ;
118+ const selectedIds = Object . entries ( this . selectedComponents ( ) )
119+ . filter ( ( [ , checked ] ) => checked )
120+ . map ( ( [ id ] ) => id ) ;
57121
58- const selected = components
59- . filter ( ( comp : ViewOnlyLinkNodeModel ) =>
60- selectedIds . find ( ( [ id , checked ] : [ string , boolean ] ) => id === comp . id && checked )
61- )
62- . map ( ( comp ) => ( {
63- id : comp . id ,
64- type : 'nodes' ,
65- } ) ) ;
122+ const rootProjectId = this . currentProjectId ;
123+ const rootProject = selectedIds . includes ( rootProjectId ) ? [ { id : rootProjectId , type : 'nodes' } ] : [ ] ;
124+
125+ const relationshipComponents = selectedIds
126+ . filter ( ( id ) => id !== rootProjectId )
127+ . map ( ( id ) => ( { id, type : 'nodes' } ) ) ;
66128
67- const data = {
129+ const data : Record < string , unknown > = {
68130 attributes : {
69131 name : this . linkName . value ,
70132 anonymous : this . anonymous ( ) ,
71133 } ,
72- nodes : selected ,
134+ nodes : rootProject ,
73135 } ;
74136
137+ if ( relationshipComponents . length ) {
138+ data [ 'relationships' ] = {
139+ nodes : {
140+ data : relationshipComponents ,
141+ } ,
142+ } ;
143+ }
144+
75145 this . dialogRef . close ( data ) ;
76146 }
77147
78148 onCheckboxToggle ( id : string , checked : boolean ) : void {
79149 this . selectedComponents . update ( ( prev ) => ( { ...prev , [ id ] : checked } ) ) ;
80150 }
151+
152+ selectAllComponents ( ) : void {
153+ const allIds : Record < string , boolean > = { } ;
154+ this . allComponents . forEach ( ( component ) => {
155+ allIds [ component . id ] = true ;
156+ } ) ;
157+ this . selectedComponents . set ( allIds ) ;
158+ }
159+
160+ deselectAllComponents ( ) : void {
161+ const allIds : Record < string , boolean > = { } ;
162+ this . allComponents . forEach ( ( component ) => {
163+ allIds [ component . id ] = component . isCurrentProject ;
164+ } ) ;
165+ this . selectedComponents . set ( allIds ) ;
166+ }
81167}
0 commit comments