Skip to content

Commit 1c2e5bd

Browse files
committed
fix(share): updated share social button
1 parent 7f1035b commit 1c2e5bd

27 files changed

+276
-421
lines changed
Lines changed: 22 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,23 @@
1-
<p-card class="card">
2-
<div class="flex flex-column gap-4">
3-
<div class="flex flex-column justify-content-between gap-2 md:flex-row md:align-items-center">
4-
@if (preprint() && preprintProvider()) {
5-
<a pButton severity="secondary" [href]="downloadLink()" (click)="logDownload()">
6-
{{
7-
'preprints.details.share.downloadPreprint' | translate: { documentType: preprintProvider()?.preprintWord }
8-
}}
9-
</a>
10-
}
1+
<div class="flex align-items-center gap-2">
2+
<p-button
3+
class="btn-icon-only"
4+
icon="fas fa-download"
5+
[pTooltip]="
6+
'preprints.details.share.downloadPreprint' | translate: { documentType: preprintProvider()?.preprintWord }
7+
"
8+
tooltipPosition="bottom"
9+
(onClick)="download()"
10+
[attr.aria-label]="
11+
'preprints.details.share.downloadPreprint' | translate: { documentType: preprintProvider()?.preprintWord }
12+
"
13+
/>
1114

12-
@if (metrics()) {
13-
<section class="flex flex-row gap-1 font-bold">
14-
<span>{{ 'preprints.details.share.views' | translate }}: {{ metrics()!.views }}</span>
15-
<span>|</span>
16-
<span>{{ 'preprints.details.share.downloads' | translate }}: {{ metrics()!.downloads }}</span>
17-
</section>
18-
}
19-
20-
@if (isPreprintLoading()) {
21-
<p-skeleton width="10rem" height="2.75rem" />
22-
<p-skeleton width="15rem" height="2.75rem" />
23-
}
24-
</div>
25-
26-
<div class="flex flex-row justify-content-start gap-1">
27-
<a
28-
class="social-link flex align-items-center justify-content-center"
29-
[href]="emailShareLink()"
30-
target="_blank"
31-
rel="noopener noreferrer"
32-
>
33-
<osf-icon [iconClass]="`fas fa-envelope fa-xl`" />
34-
</a>
35-
<a
36-
class="social-link flex align-items-center justify-content-center"
37-
[href]="twitterShareLink()"
38-
target="_blank"
39-
rel="noopener noreferrer"
40-
>
41-
<osf-icon [iconClass]="`fab fa-x-twitter fa-xl`" />
42-
</a>
43-
<a
44-
class="social-link flex align-items-center justify-content-center"
45-
[href]="facebookShareLink()"
46-
target="_blank"
47-
rel="noopener noreferrer"
48-
>
49-
<osf-icon [iconClass]="`fab fa-facebook-f fa-xl`" />
50-
</a>
51-
<a
52-
class="social-link flex align-items-center justify-content-center"
53-
[href]="linkedInShareLink()"
54-
target="_blank"
55-
rel="noopener noreferrer"
56-
>
57-
<osf-icon [iconClass]="`fab fa-linkedin-in fa-xl`" />
58-
</a>
59-
<a
60-
class="social-link flex align-items-center justify-content-center"
61-
[href]="mastodonShareLink()"
62-
target="_blank"
63-
rel="noopener noreferrer"
64-
>
65-
<osf-icon [iconClass]="`fab fa-mastodon fa-xl`" />
66-
</a>
67-
<a
68-
class="social-link flex align-items-center justify-content-center"
69-
[href]="blueskyShareLink()"
70-
target="_blank"
71-
rel="noopener noreferrer"
72-
>
73-
<osf-icon [iconClass]="`fab fa-bluesky fa-xl`" />
74-
</a>
75-
</div>
76-
</div>
77-
</p-card>
15+
@if (preprint() && preprintProvider()) {
16+
<osf-socials-share-button
17+
[resourceId]="preprint()!.id"
18+
[resourceTitle]="preprint()!.title"
19+
[resourceType]="resourceType"
20+
[resourceProvider]="preprintProvider()!.id"
21+
></osf-socials-share-button>
22+
}
23+
</div>
Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +0,0 @@
1-
@use "styles/mixins" as mix;
2-
@use "styles/variables" as var;
3-
4-
.social-link {
5-
background-color: var(--pr-blue-1);
6-
border-radius: mix.rem(8px);
7-
color: var(--white);
8-
padding: mix.rem(7px);
9-
width: mix.rem(36px);
10-
height: mix.rem(36px);
11-
12-
&:hover {
13-
background-color: var(--pr-blue-3);
14-
text-decoration: none;
15-
}
16-
}
17-
18-
.card {
19-
@media (max-width: var.$breakpoint-sm) {
20-
--p-card-body-padding: 0.75rem;
21-
}
22-
}

src/app/features/preprints/components/preprint-details/share-and-download/share-and-download.component.spec.ts

Lines changed: 3 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,13 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
66

77
import { PreprintProviderDetails } from '@osf/features/preprints/models';
88
import { PreprintSelectors } from '@osf/features/preprints/store/preprint';
9-
import { IconComponent } from '@shared/components';
10-
import { SocialShareLinks } from '@shared/models';
11-
import { SocialShareService } from '@shared/services';
12-
import { DataciteService } from '@shared/services/datacite/datacite.service';
9+
import { SocialsShareButtonComponent } from '@osf/shared/components';
10+
import { DataciteService } from '@osf/shared/services/datacite/datacite.service';
1311

1412
import { ShareAndDownloadComponent } from './share-and-download.component';
1513

1614
import { PREPRINT_MOCK } from '@testing/mocks/preprint.mock';
1715
import { PREPRINT_PROVIDER_DETAILS_MOCK } from '@testing/mocks/preprint-provider-details';
18-
import { SOCIAL_SHARE_LINKS_MOCK } from '@testing/mocks/social-share-links.mock';
1916
import { TranslationServiceMock } from '@testing/mocks/translation.service.mock';
2017
import { OSFTestingModule } from '@testing/osf.testing.module';
2118
import { provideMockStore } from '@testing/providers/store-provider.mock';
@@ -24,39 +21,26 @@ describe('ShareAndDownloadComponent', () => {
2421
let component: ShareAndDownloadComponent;
2522
let fixture: ComponentFixture<ShareAndDownloadComponent>;
2623
let dataciteService: jest.Mocked<DataciteService>;
27-
let socialShareService: jest.Mocked<SocialShareService>;
2824

2925
const mockPreprint = PREPRINT_MOCK;
3026
const mockProvider: PreprintProviderDetails = PREPRINT_PROVIDER_DETAILS_MOCK;
31-
const mockShareLinks: SocialShareLinks = SOCIAL_SHARE_LINKS_MOCK;
3227

3328
beforeEach(async () => {
3429
dataciteService = {
3530
logIdentifiableDownload: jest.fn().mockReturnValue(of(void 0)),
3631
} as any;
3732

38-
socialShareService = {
39-
createDownloadUrl: jest.fn().mockReturnValue('https://example.com/download/preprint-1'),
40-
createPreprintUrl: jest.fn().mockReturnValue('https://example.com/preprint/preprint-1'),
41-
generateAllSharingLinks: jest.fn().mockReturnValue(mockShareLinks),
42-
} as any;
43-
4433
await TestBed.configureTestingModule({
45-
imports: [ShareAndDownloadComponent, OSFTestingModule, MockComponent(IconComponent)],
34+
imports: [ShareAndDownloadComponent, OSFTestingModule, MockComponent(SocialsShareButtonComponent)],
4635
providers: [
4736
TranslationServiceMock,
4837
MockProvider(DataciteService, dataciteService),
49-
MockProvider(SocialShareService, socialShareService),
5038
provideMockStore({
5139
signals: [
5240
{
5341
selector: PreprintSelectors.getPreprint,
5442
value: mockPreprint,
5543
},
56-
{
57-
selector: PreprintSelectors.isPreprintLoading,
58-
value: false,
59-
},
6044
],
6145
}),
6246
],
@@ -77,85 +61,6 @@ describe('ShareAndDownloadComponent', () => {
7761
expect(preprint).toBe(mockPreprint);
7862
});
7963

80-
it('should return preprint loading state from store', () => {
81-
const loading = component.isPreprintLoading();
82-
expect(loading).toBe(false);
83-
});
84-
85-
it('should compute metrics from preprint', () => {
86-
const metrics = component.metrics();
87-
expect(metrics).toBe(mockPreprint.metrics);
88-
});
89-
90-
it('should return null metrics when no preprint', () => {
91-
jest.spyOn(component, 'preprint').mockReturnValue(null);
92-
const metrics = component.metrics();
93-
expect(metrics).toBeNull();
94-
});
95-
96-
it('should compute download link from preprint', () => {
97-
const downloadLink = component.downloadLink();
98-
expect(downloadLink).toBe('https://example.com/download/preprint-1');
99-
expect(socialShareService.createDownloadUrl).toHaveBeenCalledWith('preprint-1');
100-
});
101-
102-
it('should return default download link when no preprint', () => {
103-
jest.spyOn(component, 'preprint').mockReturnValue(null);
104-
const downloadLink = component.downloadLink();
105-
expect(downloadLink).toBe('#');
106-
});
107-
108-
it('should return null shareable content when no preprint or provider', () => {
109-
jest.spyOn(component, 'preprint').mockReturnValue(null);
110-
const shareableContent = (component as any).shareableContent();
111-
expect(shareableContent).toBeNull();
112-
});
113-
114-
it('should compute share links from shareable content', () => {
115-
const shareLinks = component.shareLinks();
116-
expect(shareLinks).toBe(mockShareLinks);
117-
expect(socialShareService.generateAllSharingLinks).toHaveBeenCalled();
118-
});
119-
120-
it('should return null share links when no shareable content', () => {
121-
jest.spyOn(component as any, 'shareableContent').mockReturnValue(null);
122-
const shareLinks = component.shareLinks();
123-
expect(shareLinks).toBeNull();
124-
});
125-
126-
it('should compute email share link', () => {
127-
const emailLink = component.emailShareLink();
128-
expect(emailLink).toBe(mockShareLinks.email);
129-
});
130-
131-
it('should compute twitter share link', () => {
132-
const twitterLink = component.twitterShareLink();
133-
expect(twitterLink).toBe(mockShareLinks.twitter);
134-
});
135-
136-
it('should compute facebook share link', () => {
137-
const facebookLink = component.facebookShareLink();
138-
expect(facebookLink).toBe(mockShareLinks.facebook);
139-
});
140-
141-
it('should compute linkedIn share link', () => {
142-
const linkedInLink = component.linkedInShareLink();
143-
expect(linkedInLink).toBe(mockShareLinks.linkedIn);
144-
});
145-
146-
it('should return empty string for share links when no share links', () => {
147-
jest.spyOn(component, 'shareLinks').mockReturnValue(null);
148-
expect(component.emailShareLink()).toBe('');
149-
expect(component.twitterShareLink()).toBe('');
150-
expect(component.facebookShareLink()).toBe('');
151-
expect(component.linkedInShareLink()).toBe('');
152-
});
153-
154-
it('should call dataciteService.logIdentifiableDownload when logDownload is called', () => {
155-
component.logDownload();
156-
expect(dataciteService.logIdentifiableDownload).toHaveBeenCalledWith(component.preprint$);
157-
});
158-
15964
it('should handle preprint provider input', () => {
16065
const provider = component.preprintProvider();
16166
expect(provider).toBe(mockProvider);

src/app/features/preprints/components/preprint-details/share-and-download/share-and-download.component.ts

Lines changed: 15 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,22 @@ import { select } from '@ngxs/store';
22

33
import { TranslatePipe } from '@ngx-translate/core';
44

5-
import { ButtonDirective } from 'primeng/button';
6-
import { Card } from 'primeng/card';
7-
import { Skeleton } from 'primeng/skeleton';
5+
import { Button } from 'primeng/button';
6+
import { Tooltip } from 'primeng/tooltip';
87

9-
import { ChangeDetectionStrategy, Component, computed, DestroyRef, inject, input } from '@angular/core';
8+
import { ChangeDetectionStrategy, Component, DestroyRef, inject, input } from '@angular/core';
109
import { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
1110

1211
import { PreprintProviderDetails } from '@osf/features/preprints/models';
1312
import { PreprintSelectors } from '@osf/features/preprints/store/preprint';
14-
import { IconComponent } from '@shared/components';
15-
import { ShareableContent } from '@shared/models';
16-
import { SocialShareService } from '@shared/services';
17-
import { DataciteService } from '@shared/services/datacite/datacite.service';
13+
import { SocialsShareButtonComponent } from '@osf/shared/components';
14+
import { ResourceType } from '@osf/shared/enums';
15+
import { SocialShareService } from '@osf/shared/services';
16+
import { DataciteService } from '@osf/shared/services/datacite/datacite.service';
1817

1918
@Component({
2019
selector: 'osf-preprint-share-and-download',
21-
imports: [Card, IconComponent, Skeleton, ButtonDirective, TranslatePipe],
20+
imports: [Button, SocialsShareButtonComponent, TranslatePipe, Tooltip],
2221
templateUrl: './share-and-download.component.html',
2322
styleUrl: './share-and-download.component.scss',
2423
changeDetection: ChangeDetectionStrategy.OnPush,
@@ -32,54 +31,18 @@ export class ShareAndDownloadComponent {
3231

3332
preprint = select(PreprintSelectors.getPreprint);
3433
preprint$ = toObservable(this.preprint);
35-
isPreprintLoading = select(PreprintSelectors.isPreprintLoading);
34+
resourceType = ResourceType.Preprint;
3635

37-
metrics = computed(() => {
36+
download() {
3837
const preprint = this.preprint();
3938

40-
if (!preprint) return null;
39+
if (!preprint) {
40+
return;
41+
}
4142

42-
return preprint.metrics!;
43-
});
43+
const downloadLink = this.socialShareService.createDownloadUrl(preprint.id);
44+
window.open(downloadLink)?.focus();
4445

45-
downloadLink = computed(() => {
46-
const preprint = this.preprint();
47-
48-
if (!preprint) return '#';
49-
50-
return this.socialShareService.createDownloadUrl(preprint.id);
51-
});
52-
53-
logDownload() {
5446
this.dataciteService.logIdentifiableDownload(this.preprint$).pipe(takeUntilDestroyed(this.destroyRef)).subscribe();
5547
}
56-
57-
private shareableContent = computed((): ShareableContent | null => {
58-
const preprint = this.preprint();
59-
const preprintProvider = this.preprintProvider();
60-
61-
if (!preprint || !preprintProvider) return null;
62-
63-
return {
64-
id: preprint.id,
65-
title: preprint.title,
66-
description: preprint.description,
67-
url: this.socialShareService.createPreprintUrl(preprint.id, preprintProvider.id),
68-
};
69-
});
70-
71-
shareLinks = computed(() => {
72-
const content = this.shareableContent();
73-
74-
if (!content) return null;
75-
76-
return this.socialShareService.generateAllSharingLinks(content);
77-
});
78-
79-
emailShareLink = computed(() => this.shareLinks()?.email || '');
80-
twitterShareLink = computed(() => this.shareLinks()?.twitter || '');
81-
facebookShareLink = computed(() => this.shareLinks()?.facebook || '');
82-
linkedInShareLink = computed(() => this.shareLinks()?.linkedIn || '');
83-
mastodonShareLink = computed(() => this.shareLinks()?.mastodon || '');
84-
blueskyShareLink = computed(() => this.shareLinks()?.bluesky || '');
8548
}

src/app/features/project/overview/components/overview-toolbar/overview-toolbar.component.html

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -97,26 +97,11 @@
9797
}
9898

9999
@if (resource.isPublic && !hasViewOnly()) {
100-
<p-button
101-
class="flex"
102-
(onClick)="socialsActionMenu.toggle($event)"
103-
[pTooltip]="'project.overview.tooltips.share' | translate"
104-
tooltipPosition="bottom"
105-
[ariaLabel]="'project.overview.tooltips.share' | translate"
106-
>
107-
<span class="font-bold">{{ socialsActionItems().length }}</span>
108-
<i class="fas fa-share-nodes text-2xl"></i>
109-
<p-menu appendTo="body" #socialsActionMenu [model]="socialsActionItems()" popup>
110-
<ng-template #item let-item>
111-
<a class="p-menu-item-link" [href]="item.url" target="_blank" rel="noopener noreferrer">
112-
<div class="social-link flex align-items-center justify-content-center">
113-
<osf-icon [iconClass]="`${item.icon} fa-sm`"></osf-icon>
114-
</div>
115-
{{ item.label | translate }}
116-
</a>
117-
</ng-template>
118-
</p-menu>
119-
</p-button>
100+
<osf-socials-share-button
101+
[resourceId]="currentResource().id"
102+
[resourceTitle]="currentResource().title"
103+
[resourceType]="currentResource().resourceType"
104+
></osf-socials-share-button>
120105
}
121106
</div>
122107
</div>

0 commit comments

Comments
 (0)