@@ -11,16 +11,17 @@ import { Tooltip } from 'primeng/tooltip';
1111import { timer } from 'rxjs' ;
1212
1313import { NgClass } from '@angular/common' ;
14- import { ChangeDetectionStrategy , Component , DestroyRef , effect , inject , input , signal } from '@angular/core' ;
14+ import { ChangeDetectionStrategy , Component , computed , DestroyRef , effect , inject , input , signal } from '@angular/core' ;
1515import { takeUntilDestroyed } from '@angular/core/rxjs-interop' ;
1616import { FormsModule } from '@angular/forms' ;
1717import { ActivatedRoute , Router , RouterLink } from '@angular/router' ;
1818
1919import { DuplicateDialogComponent , TogglePublicityDialogComponent } from '@osf/features/project/overview/components' ;
20+ import { SocialsShareActionItem } from '@osf/features/project/overview/models' ;
2021import { IconComponent } from '@osf/shared/components' ;
21- import { ToastService } from '@osf/shared/services' ;
22+ import { SocialShareService , ToastService } from '@osf/shared/services' ;
2223import { ResourceType } from '@shared/enums' ;
23- import { ToolbarResource } from '@shared/models' ;
24+ import { ShareableContent , ToolbarResource } from '@shared/models' ;
2425import { FileSizePipe } from '@shared/pipes' ;
2526import {
2627 AddResourceToBookmarks ,
@@ -30,7 +31,6 @@ import {
3031 RemoveResourceFromBookmarks ,
3132} from '@shared/stores' ;
3233
33- import { SOCIAL_ACTION_ITEMS } from '../../constants' ;
3434import { ForkDialogComponent } from '../fork-dialog/fork-dialog.component' ;
3535
3636@Component ( {
@@ -56,22 +56,28 @@ export class OverviewToolbarComponent {
5656 private dialogService = inject ( DialogService ) ;
5757 private translateService = inject ( TranslateService ) ;
5858 private toastService = inject ( ToastService ) ;
59+ private socialShareService = inject ( SocialShareService ) ;
5960 protected destroyRef = inject ( DestroyRef ) ;
6061 private readonly router = inject ( Router ) ;
6162 private readonly route = inject ( ActivatedRoute ) ;
6263 protected isPublic = signal ( false ) ;
6364 protected isBookmarked = signal ( false ) ;
64-
6565 isCollectionsRoute = input < boolean > ( false ) ;
6666 isAdmin = input . required < boolean > ( ) ;
6767 currentResource = input . required < ToolbarResource | null > ( ) ;
68+ projectTitle = input < string > ( '' ) ;
69+ projectDescription = input < string > ( '' ) ;
6870 showViewOnlyLinks = input < boolean > ( true ) ;
6971
7072 protected isBookmarksLoading = select ( MyResourcesSelectors . getBookmarksLoading ) ;
7173 protected isBookmarksSubmitting = select ( BookmarksSelectors . getBookmarksCollectionIdSubmitting ) ;
7274 protected bookmarksCollectionId = select ( BookmarksSelectors . getBookmarksCollectionId ) ;
7375 protected bookmarkedProjects = select ( MyResourcesSelectors . getBookmarks ) ;
74- protected readonly socialsActionItems = SOCIAL_ACTION_ITEMS ;
76+ protected socialsActionItems = computed ( ( ) => {
77+ const shareableContent = this . createShareableContent ( ) ;
78+ return shareableContent ? this . buildSocialActionItems ( shareableContent ) : [ ] ;
79+ } ) ;
80+
7581 protected readonly forkActionItems = [
7682 {
7783 label : 'project.overview.actions.forkProject' ,
@@ -122,38 +128,6 @@ export class OverviewToolbarComponent {
122128 } ) ;
123129 }
124130
125- private handleForkResource ( ) : void {
126- const resource = this . currentResource ( ) ;
127- const headerTranslation =
128- resource ?. resourceType === ResourceType . Project
129- ? 'project.overview.dialog.fork.headerProject'
130- : resource ?. resourceType === ResourceType . Registration
131- ? 'project.overview.dialog.fork.headerRegistry'
132- : '' ;
133- if ( resource ) {
134- this . dialogService . open ( ForkDialogComponent , {
135- focusOnShow : false ,
136- header : this . translateService . instant ( headerTranslation ) ,
137- closeOnEscape : true ,
138- modal : true ,
139- closable : true ,
140- data : {
141- resource : resource ,
142- } ,
143- } ) ;
144- }
145- }
146-
147- private handleDuplicateProject ( ) : void {
148- this . dialogService . open ( DuplicateDialogComponent , {
149- focusOnShow : false ,
150- header : this . translateService . instant ( 'project.overview.dialog.duplicate.header' ) ,
151- closeOnEscape : true ,
152- modal : true ,
153- closable : true ,
154- } ) ;
155- }
156-
157131 protected handleToggleProjectPublicity ( ) : void {
158132 const resource = this . currentResource ( ) ;
159133 if ( ! resource ) return ;
@@ -212,4 +186,91 @@ export class OverviewToolbarComponent {
212186 } ) ;
213187 }
214188 }
189+
190+ private handleForkResource ( ) : void {
191+ const resource = this . currentResource ( ) ;
192+ const headerTranslation =
193+ resource ?. resourceType === ResourceType . Project
194+ ? 'project.overview.dialog.fork.headerProject'
195+ : resource ?. resourceType === ResourceType . Registration
196+ ? 'project.overview.dialog.fork.headerRegistry'
197+ : '' ;
198+ if ( resource ) {
199+ this . dialogService . open ( ForkDialogComponent , {
200+ focusOnShow : false ,
201+ header : this . translateService . instant ( headerTranslation ) ,
202+ closeOnEscape : true ,
203+ modal : true ,
204+ closable : true ,
205+ data : {
206+ resource : resource ,
207+ } ,
208+ } ) ;
209+ }
210+ }
211+
212+ private handleDuplicateProject ( ) : void {
213+ this . dialogService . open ( DuplicateDialogComponent , {
214+ focusOnShow : false ,
215+ header : this . translateService . instant ( 'project.overview.dialog.duplicate.header' ) ,
216+ closeOnEscape : true ,
217+ modal : true ,
218+ closable : true ,
219+ } ) ;
220+ }
221+
222+ private createShareableContent ( ) : ShareableContent | null {
223+ const resource = this . currentResource ( ) ;
224+ const title = this . projectTitle ( ) ;
225+ const description = this . projectDescription ( ) ;
226+
227+ if ( ! resource ?. isPublic || ! title ) {
228+ return null ;
229+ }
230+
231+ return {
232+ id : resource . id ,
233+ title,
234+ description,
235+ url : this . buildResourceUrl ( resource ) ,
236+ } ;
237+ }
238+
239+ private buildResourceUrl ( resource : ToolbarResource ) : string {
240+ switch ( resource . resourceType ) {
241+ case ResourceType . Project :
242+ return this . socialShareService . createProjectUrl ( resource . id ) ;
243+ case ResourceType . Registration :
244+ return this . socialShareService . createRegistrationUrl ( resource . id ) ;
245+ default :
246+ return `${ window . location . origin } /${ resource . id } ` ;
247+ }
248+ }
249+
250+ private buildSocialActionItems ( shareableContent : ShareableContent ) : SocialsShareActionItem [ ] {
251+ const shareLinks = this . socialShareService . generateAllSharingLinks ( shareableContent ) ;
252+
253+ return [
254+ {
255+ label : 'project.overview.actions.socials.email' ,
256+ icon : 'fas fa-envelope' ,
257+ url : shareLinks . email ,
258+ } ,
259+ {
260+ label : 'project.overview.actions.socials.x' ,
261+ icon : 'fab fa-x-twitter' ,
262+ url : shareLinks . twitter ,
263+ } ,
264+ {
265+ label : 'project.overview.actions.socials.linkedIn' ,
266+ icon : 'fab fa-linkedin' ,
267+ url : shareLinks . linkedIn ,
268+ } ,
269+ {
270+ label : 'project.overview.actions.socials.facebook' ,
271+ icon : 'fab fa-facebook-f' ,
272+ url : shareLinks . facebook ,
273+ } ,
274+ ] ;
275+ }
215276}
0 commit comments