@@ -4,18 +4,41 @@ import { TranslatePipe } from '@ngx-translate/core';
44
55import { Button } from 'primeng/button' ;
66import { Menu } from 'primeng/menu' ;
7+ import { TableModule } from 'primeng/table' ;
78import { Tab , TabList , Tabs } from 'primeng/tabs' ;
89
910import { switchMap } from 'rxjs' ;
1011
11- import { ChangeDetectionStrategy , Component , DestroyRef , HostBinding , inject } from '@angular/core' ;
12+ import {
13+ ChangeDetectionStrategy ,
14+ Component ,
15+ computed ,
16+ DestroyRef ,
17+ effect ,
18+ HostBinding ,
19+ inject ,
20+ signal ,
21+ } from '@angular/core' ;
1222import { takeUntilDestroyed } from '@angular/core/rxjs-interop' ;
1323import { DomSanitizer , SafeResourceUrl } from '@angular/platform-browser' ;
1424import { ActivatedRoute , Router , RouterLink } from '@angular/router' ;
1525
16- import { LoadingSpinnerComponent , SubHeaderComponent } from '@osf/shared/components' ;
17- import { OsfFile } from '@shared/models' ;
18- import { CustomConfirmationService , ToastService } from '@shared/services' ;
26+ import {
27+ CedarMetadataDataTemplateJsonApi ,
28+ CedarMetadataRecordData ,
29+ CedarRecordDataBinding ,
30+ } from '@osf/features/metadata/models' ;
31+ import {
32+ CreateCedarMetadataRecord ,
33+ GetCedarMetadataRecords ,
34+ GetCedarMetadataTemplates ,
35+ MetadataSelectors ,
36+ UpdateCedarMetadataRecord ,
37+ } from '@osf/features/metadata/store' ;
38+ import { LoadingSpinnerComponent , MetadataTabsComponent , SubHeaderComponent } from '@osf/shared/components' ;
39+ import { MetadataResourceEnum , ResourceType } from '@osf/shared/enums' ;
40+ import { MetadataTabsModel , OsfFile } from '@osf/shared/models' ;
41+ import { CustomConfirmationService , ToastService } from '@osf/shared/services' ;
1942
2043import {
2144 FileKeywordsComponent ,
@@ -51,6 +74,8 @@ import {
5174 FileRevisionsComponent ,
5275 FileMetadataComponent ,
5376 FileResourceMetadataComponent ,
77+ MetadataTabsComponent ,
78+ TableModule ,
5479 ] ,
5580 templateUrl : './file-detail.component.html' ,
5681 styleUrl : './file-detail.component.scss' ,
@@ -74,19 +99,27 @@ export class FileDetailComponent {
7499 getFileResourceMetadata : GetFileResourceMetadata ,
75100 getFileResourceContributors : GetFileResourceContributors ,
76101 deleteEntry : DeleteEntry ,
102+
103+ getCedarRecords : GetCedarMetadataRecords ,
104+ getCedarTemplates : GetCedarMetadataTemplates ,
105+ createCedarRecord : CreateCedarMetadataRecord ,
106+ updateCedarRecord : UpdateCedarMetadataRecord ,
77107 } ) ;
78108
79109 file = select ( FilesSelectors . getOpenedFile ) ;
80110 isFileLoading = select ( FilesSelectors . isOpenedFileLoading ) ;
111+ cedarRecords = select ( MetadataSelectors . getCedarRecords ) ;
112+ cedarTemplates = select ( MetadataSelectors . getCedarTemplates ) ;
113+
81114 safeLink : SafeResourceUrl | null = null ;
82115 resourceId = '' ;
83116 resourceType = '' ;
84117
85118 isIframeLoading = true ;
86119
87- protected readonly FileDetailTab = FileDetailTab ;
120+ readonly FileDetailTab = FileDetailTab ;
88121
89- protected selectedTab : FileDetailTab = FileDetailTab . Details ;
122+ selectedTab : FileDetailTab = FileDetailTab . Details ;
90123
91124 fileGuid = '' ;
92125
@@ -116,6 +149,18 @@ export class FileDetailComponent {
116149 } ,
117150 ] ;
118151
152+ tabs = signal < MetadataTabsModel [ ] > ( [ ] ) ;
153+
154+ isLoading = computed ( ( ) => {
155+ return this . isFileLoading ( ) ;
156+ } ) ;
157+
158+ selectedMetadataTab = signal ( 'osf' ) ;
159+
160+ selectedCedarRecord = signal < CedarMetadataRecordData | null > ( null ) ;
161+ selectedCedarTemplate = signal < CedarMetadataDataTemplateJsonApi | null > ( null ) ;
162+ cedarFormReadonly = signal < boolean > ( true ) ;
163+
119164 constructor ( ) {
120165 this . route . params
121166 . pipe (
@@ -136,14 +181,31 @@ export class FileDetailComponent {
136181 if ( this . resourceId && this . resourceType ) {
137182 this . actions . getFileResourceMetadata ( this . resourceId , this . resourceType ) ;
138183 this . actions . getFileResourceContributors ( this . resourceId , this . resourceType ) ;
139-
140184 if ( fileId ) {
141185 const fileProvider = this . file ( ) ?. provider || '' ;
142186 this . actions . getFileRevisions ( this . resourceId , fileProvider , fileId ) ;
187+ this . actions . getCedarTemplates ( ) ;
188+ this . actions . getCedarRecords ( fileId , ResourceType . File ) ;
143189 }
144190 }
145191 } ) ;
146192
193+ effect ( ( ) => {
194+ const records = this . cedarRecords ( ) ;
195+
196+ const baseTabs = [ { id : 'osf' , label : 'OSF' , type : MetadataResourceEnum . PROJECT } ] ;
197+
198+ const cedarTabs =
199+ records ?. map ( ( record ) => ( {
200+ id : record . id || '' ,
201+ label : record . embeds ?. template ?. data ?. attributes ?. schema_name || `Record ${ record . id } ` ,
202+ type : MetadataResourceEnum . CEDAR ,
203+ } ) ) || [ ] ;
204+
205+ this . tabs . set ( [ ...baseTabs , ...cedarTabs ] ) ;
206+ // this.handleRouteBasedTabSelection();
207+ } ) ;
208+
147209 this . route . params . pipe ( takeUntilDestroyed ( this . destroyRef ) ) . subscribe ( ( params ) => {
148210 this . actions . getFileMetadata ( params [ 'fileGuid' ] ) ;
149211 } ) ;
@@ -189,28 +251,100 @@ export class FileDetailComponent {
189251 this . selectedTab = index ;
190252 }
191253
192- protected handleEmailShare ( ) : void {
254+ handleEmailShare ( ) : void {
193255 const link = `mailto:?subject=${ this . file ( ) ?. name ?? '' } &body=${ this . file ( ) ?. links ?. html ?? '' } ` ;
194256 window . location . href = link ;
195257 }
196258
197- protected handleXShare ( ) : void {
259+ handleXShare ( ) : void {
198260 const link = `https://x.com/intent/tweet?url=${ this . file ( ) ?. links ?. html ?? '' } &text=${ this . file ( ) ?. name ?? '' } &via=OSFramework` ;
199261 window . open ( link , '_blank' , 'noopener,noreferrer' ) ;
200262 }
201263
202- protected handleFacebookShare ( ) : void {
264+ handleFacebookShare ( ) : void {
203265 const link = `https://www.facebook.com/dialog/share?app_id=1022273774556662&display=popup&href=${ this . file ( ) ?. links ?. html ?? '' } &redirect_uri=${ this . file ( ) ?. links ?. html ?? '' } ` ;
204266 window . open ( link , '_blank' , 'noopener,noreferrer' ) ;
205267 }
206268
207- protected handleCopyDynamicEmbed ( ) : void {
269+ handleCopyDynamicEmbed ( ) : void {
208270 const data = embedDynamicJs . replace ( 'ENCODED_URL' , this . file ( ) ?. links ?. render ?? '' ) ;
209271 this . copyToClipboard ( data ) ;
210272 }
211273
212- protected handleCopyStaticEmbed ( ) : void {
274+ handleCopyStaticEmbed ( ) : void {
213275 const data = embedStaticHtml . replace ( 'ENCODED_URL' , this . file ( ) ?. links ?. render ?? '' ) ;
214276 this . copyToClipboard ( data ) ;
215277 }
278+
279+ onMetadataTabChange ( tabId : string | number ) : void {
280+ const tab = this . tabs ( ) . find ( ( x ) => x . id === tabId . toString ( ) ) ;
281+
282+ if ( ! tab ) {
283+ return ;
284+ }
285+
286+ this . selectedMetadataTab . set ( tab . id as MetadataResourceEnum ) ;
287+ if ( tab . type === 'cedar' ) {
288+ this . selectedCedarRecord . set ( null ) ;
289+ this . selectedCedarTemplate . set ( null ) ;
290+ if ( tab . id ) {
291+ this . loadCedarRecord ( tab . id ) ;
292+ }
293+ } else {
294+ this . selectedCedarRecord . set ( null ) ;
295+ this . selectedCedarTemplate . set ( null ) ;
296+ }
297+ }
298+
299+ onCedarFormEdit ( ) : void {
300+ this . cedarFormReadonly . set ( false ) ;
301+ }
302+
303+ onCedarFormSubmit ( data : CedarRecordDataBinding ) : void {
304+ // const selectedRecord = this.selectedCedarRecord();
305+ // if (!this.resourceId || !selectedRecord) return;
306+ // if (selectedRecord.id) {
307+ // this.actions
308+ // .updateCedarRecord(data, selectedRecord.id, this.resourceId, this.resourceType())
309+ // .pipe(takeUntilDestroyed(this.destroyRef))
310+ // .subscribe({
311+ // next: () => {
312+ // this.cedarFormReadonly.set(true);
313+ // this.toastService.showSuccess('CEDAR record updated successfully');
314+ // this.actions.getCedarRecords(this.resourceId, this.resourceType());
315+ // },
316+ // });
317+ // }
318+ }
319+
320+ onCedarFormChangeTemplate ( ) : void {
321+ // this.router.navigate(['add'], { relativeTo: this.activeRoute });
322+ }
323+
324+ private loadCedarRecord ( recordId : string ) : void {
325+ const records = this . cedarRecords ( ) ;
326+ const templates = this . cedarTemplates ( ) ;
327+ if ( ! records ) {
328+ return ;
329+ }
330+ const record = records . find ( ( r ) => r . id === recordId ) ;
331+ if ( ! record ) {
332+ return ;
333+ }
334+ this . selectedCedarRecord . set ( record ) ;
335+ this . cedarFormReadonly . set ( true ) ;
336+ const templateId = record . relationships ?. template ?. data ?. id ;
337+ if ( templateId && templates ?. data ) {
338+ const template = templates . data . find ( ( t ) => t . id === templateId ) ;
339+ if ( template ) {
340+ this . selectedCedarTemplate . set ( template ) ;
341+ } else {
342+ this . selectedCedarTemplate . set ( null ) ;
343+ this . actions . getCedarTemplates ( ) ;
344+ }
345+ } else {
346+ this . selectedCedarTemplate . set ( null ) ;
347+ this . actions . getCedarTemplates ( ) ;
348+ }
349+ }
216350}
0 commit comments