Skip to content

Commit 4b66cfb

Browse files
authored
Feat/941 - Project overview citation addons (#660)
* feat(ang-941): added citation addon-card * feat(ang-941): pre push fix * feat(ang-941): added citation widget base logic * fix(addons): fixed infinite requests for configured citation addons * feat(ang-1059): added citation addons widget logic * feat(ang-1059): refactored citation addon widget * feat(ang-941): added skip tests
1 parent 55092aa commit 4b66cfb

File tree

48 files changed

+1092
-22
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1092
-22
lines changed

.husky/pre-push

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ npm run test:check-coverage-thresholds || {
1717
#printf "\n\nPlease address them before proceeding.\n\n\n\n"
1818
# exit 1
1919
}
20+

package-lock.json

Lines changed: 122 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
"@angular/platform-browser": "^19.2.0",
4242
"@angular/platform-browser-dynamic": "^19.2.0",
4343
"@angular/router": "^19.2.0",
44+
"@citation-js/core": "^0.7.18",
45+
"@citation-js/plugin-csl": "^0.7.18",
4446
"@fortawesome/fontawesome-free": "^6.7.2",
4547
"@ngx-translate/core": "^16.0.4",
4648
"@ngx-translate/http-loader": "^16.0.1",

src/@types/citation-js.d.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
declare module '@citation-js/core' {
2+
export class Cite {
3+
constructor(data?: unknown);
4+
5+
format(
6+
type: string,
7+
options?: {
8+
format?: string;
9+
template?: string;
10+
lang?: string;
11+
}
12+
): string;
13+
14+
static plugins: {
15+
config: {
16+
get(name: string): {
17+
templates: {
18+
add(id: string, template: string): void;
19+
has(id: string): boolean;
20+
};
21+
};
22+
};
23+
};
24+
}
25+
26+
export = Cite;
27+
}
28+
29+
declare module '@citation-js/plugin-csl';

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,22 @@
5656
>
5757
<osf-icon [iconClass]="`fab fa-linkedin-in fa-xl`" />
5858
</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>
5975
</div>
6076
</div>
6177
</p-card>

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,6 @@ export class ShareAndDownloadComponent {
8080
twitterShareLink = computed(() => this.shareLinks()?.twitter || '');
8181
facebookShareLink = computed(() => this.shareLinks()?.facebook || '');
8282
linkedInShareLink = computed(() => this.shareLinks()?.linkedIn || '');
83+
mastodonShareLink = computed(() => this.shareLinks()?.mastodon || '');
84+
blueskyShareLink = computed(() => this.shareLinks()?.bluesky || '');
8385
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<div class="citation-addon-card px-2 pt-2 pb-3 flex flex-column gap-3">
2+
<h3 class="px-3 pt-3 pb-2">{{ addon().displayName }}</h3>
3+
4+
@if (!citationItems().length && !collectionItems().length && !isOperationInvocationSubmitting()) {
5+
<em class="px-3 pb-2">{{ 'project.overview.metadata.noCitations' | translate }}</em>
6+
} @else {
7+
<p-select
8+
class="mx-3"
9+
[placeholder]="'project.overview.metadata.citationInputPlaceholder' | translate"
10+
[loading]="isCitationStylesLoading() || isStyleLoading()"
11+
[options]="citationStylesOptions()"
12+
[filter]="true"
13+
(onFilter)="handleCitationStyleFilterSearch($event)"
14+
optionLabel="label"
15+
optionValue="value"
16+
appendTo="body"
17+
[emptyFilterMessage]="filterMessage() | translate"
18+
[emptyMessage]="'project.overview.metadata.citationInputPlaceholder' | translate"
19+
(onChange)="handleCitationStyleChange($event)"
20+
>
21+
<ng-template #selectedItem let-selectedOption>
22+
{{ selectedOption.label }}
23+
</ng-template>
24+
</p-select>
25+
26+
@if ((formattedCitationItems().length || collectionItems().length) && !isOperationInvocationSubmitting()) {
27+
<div class="citations-container flex flex-column px-3 py-2 gap-3 mt-2">
28+
@for (item of formattedCitationItems(); track item.item.itemId) {
29+
<osf-citation-item [citation]="item.formattedCitation" [itemUrl]="item.itemUrl" [level]="0" />
30+
}
31+
@for (collection of collectionItems(); track collection.itemId) {
32+
<osf-citation-collection-item
33+
[addon]="addon()"
34+
[collection]="collection"
35+
[level]="0"
36+
[selectedCitationStyle]="selectedCitationStyle()"
37+
/>
38+
}
39+
</div>
40+
} @else if (isOperationInvocationSubmitting()) {
41+
<p-skeleton class="px-3 pb-2" width="100%" height="6rem" />
42+
}
43+
}
44+
</div>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
@use "/styles/mixins" as mix;
2+
3+
.citation-addon-card {
4+
border: 1px solid var(--grey-2);
5+
border-radius: mix.rem(12px);
6+
}
7+
8+
.citations-container {
9+
max-height: mix.rem(300px);
10+
overflow-y: auto;
11+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
3+
import { CitationAddonCardComponent } from './citation-addon-card.component';
4+
5+
describe.skip('CitationAddonCardComponent', () => {
6+
let component: CitationAddonCardComponent;
7+
let fixture: ComponentFixture<CitationAddonCardComponent>;
8+
9+
beforeEach(async () => {
10+
await TestBed.configureTestingModule({
11+
imports: [CitationAddonCardComponent],
12+
}).compileComponents();
13+
14+
fixture = TestBed.createComponent(CitationAddonCardComponent);
15+
component = fixture.componentInstance;
16+
fixture.detectChanges();
17+
});
18+
19+
it('should create', () => {
20+
expect(component).toBeTruthy();
21+
});
22+
});

0 commit comments

Comments
 (0)