Skip to content

Commit 2b183bc

Browse files
committed
Merge remote-tracking branch 'upstream/develop' into feature/verified-resource-linking
2 parents aa75b42 + c41405e commit 2b183bc

File tree

17 files changed

+1070
-96
lines changed

17 files changed

+1070
-96
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
55
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
66

7+
## [25.10.0] - 2025-05-13
8+
### Added
9+
- Re-enable view and download counts for preprints
10+
11+
## [25.09.0] - 2025-05-02
12+
### Added
13+
- Bugfix and Improvements
14+
15+
## [25.08.0] - 2025-04-21
16+
### Added
17+
- Bugfix and Improvements
18+
719
## [25.07.0] - 2025-04-07
820
### Added
921
- Bugfix and Improvements

app/guid-file/route.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import S3File from 'ember-osf-web/packages/files/s3-file';
2626
import CurrentUserService from 'ember-osf-web/services/current-user';
2727
import RegistrationModel from 'ember-osf-web/models/registration';
2828
import CustomFileMetadataRecordModel from 'ember-osf-web/models/custom-file-metadata-record';
29+
import ContributorModel from 'ember-osf-web/models/contributor';
2930

3031
export default class GuidFile extends Route {
3132
@service('head-tags') headTagsService!: HeadTagsService;
@@ -45,6 +46,7 @@ export default class GuidFile extends Route {
4546
const dateCreated = model.dateCreated;
4647
const dateModified = model.dateModified;
4748
const institutions = await model.target.get('affiliatedInstitutions');
49+
const contributors = await model.target.get('bibliographicContributors');
4850
const metaTagsData = {
4951
title: this.metadata.title ? this.metadata.title : model.name,
5052
identifier: model.guid,
@@ -55,6 +57,14 @@ export default class GuidFile extends Route {
5557
this.metadata.description :
5658
this.intl.t('general.presented_by_osf'),
5759
language: this.metadata.language ? this.metadata.language : undefined,
60+
contributors: (contributors as ContributorModel[]).map(
61+
(contrib: ContributorModel) => (
62+
{
63+
givenName: contrib.users.get('givenName'),
64+
familyName: contrib.users.get('familyName'),
65+
}
66+
),
67+
),
5868
};
5969
this.set('headTags', this.metaTags.getHeadTags(metaTagsData));
6070
this.headTagsService.collectHeadTags();

app/models/search-result.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,16 @@ import { languageFromLanguageCode } from 'osf-components/components/file-metadat
77

88
import IndexCardModel from './index-card';
99

10-
const textMatchEvidenceType = 'https://share.osf.io/vocab/2023/trove/TextMatchEvidence';
11-
1210
export interface IriMatchEvidence {
13-
'@type': [string];
1411
matchingIri: string;
1512
osfmapPropertyPath: string[];
13+
propertyPathKey: string;
1614
}
1715

1816
export interface TextMatchEvidence {
19-
'@type': [string];
2017
matchingHighlight: string;
2118
osfmapPropertyPath: string[];
19+
propertyPathKey: string;
2220
}
2321

2422
export const CardLabelTranslationKeys = {
@@ -50,9 +48,11 @@ export default class SearchResultModel extends Model {
5048
if (this.matchEvidence) {
5149
const matchEvidenceString = this.matchEvidence.reduce(
5250
(acc, current) => acc.concat(
53-
`${current.osfmapPropertyPath[0]}: ${current['@type'][0] === textMatchEvidenceType
54-
? (current as TextMatchEvidence).matchingHighlight
55-
: (current as IriMatchEvidence).matchingIri}; `,
51+
`${current.propertyPathKey}: ${
52+
('matchingHighlight' in current)
53+
? current.matchingHighlight
54+
: current.matchingIri
55+
}`,
5656
),
5757
'',
5858
);

app/preprints/-components/submit/file/upload-file/component.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import FileModel from 'ember-osf-web/models/file';
99
import { task } from 'ember-concurrency';
1010
import { waitFor } from '@ember/test-waiters';
1111
import { taskFor } from 'ember-concurrency-ts';
12+
import { tracked } from '@glimmer/tracking';
1213

1314
interface PreprintUploadArgs {
1415
manager: PreprintStateMachine;
@@ -28,6 +29,7 @@ export default class PreprintUpload extends Component<PreprintUploadArgs> {
2829
url?: URL;
2930
rootFolder?: FileModel;
3031
primaryFile: FileModel | undefined;
32+
@tracked isUploadFileDisplayed = false;
3133

3234
constructor(owner: unknown, args: any) {
3335
super(owner, args);
@@ -99,4 +101,11 @@ export default class PreprintUpload extends Component<PreprintUploadArgs> {
99101
}
100102
this.args.validate(file);
101103
}
104+
105+
@task
106+
@waitFor
107+
async preUpload(): Promise<void> {
108+
this.isUploadFileDisplayed = true;
109+
}
110+
102111
}

app/preprints/-components/submit/file/upload-file/template.hbs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{{#if (or this.preUrl.isRunning this.success.isRunning)}}
1+
{{#if (or this.preUrl.isRunning this.success.isRunning this.isUploadFileDisplayed)}}
22
<LoadingIndicator data-test-loading-indicator @dark={{true}} />
33
{{else}}
44
<div ...attributes>
@@ -15,7 +15,7 @@
1515
@enable={{@enable}}
1616
@id={{id}}
1717
@clickable={{this.clickableElementSelectors}}
18-
@preUpload={{this.preUpload}}
18+
@preUpload={{perform this.preUpload}}
1919
@success={{perform this.success}}
2020
>
2121
{{yield}}

app/preprints/detail/route.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import Identifier from 'ember-osf-web/models/identifier';
1414
import LicenseModel from 'ember-osf-web/models/license';
1515
import { ReviewsState } from 'ember-osf-web/models/provider';
1616
import { SparseModel } from 'ember-osf-web/utils/sparse-fieldsets';
17-
import MetaTags, { HeadTagDef } from 'ember-osf-web/services/meta-tags';
17+
import MetaTags, { HeadTagDef, MetaTagsData } from 'ember-osf-web/services/meta-tags';
1818
import Ready from 'ember-osf-web/services/ready';
1919
import Theme from 'ember-osf-web/services/theme';
2020
import captureException from 'ember-osf-web/utils/capture-exception';
@@ -154,7 +154,7 @@ export default class PreprintsDetail extends Route {
154154
] = await all([
155155
preprint.sparseLoadAll(
156156
'bibliographicContributors',
157-
{ contributor: ['users', 'index'], user: ['fullName'] },
157+
{ contributor: ['users', 'index'], user: ['given_name', 'family_name'] },
158158
),
159159
preprint.license,
160160
preprint.identifiers,
@@ -180,10 +180,10 @@ export default class PreprintsDetail extends Route {
180180
keywords: preprint.tags,
181181
siteName: 'OSF',
182182
license: license && (license as LicenseModel).name,
183-
author: (contributors as SparseModel[]).map(
184-
contrib => (contrib.users as { fullName: string }).fullName,
183+
contributors: (contributors as SparseModel[]).map(
184+
(contrib: SparseModel) => (contrib.users as { givenName: string, familyName: string }),
185185
),
186-
};
186+
} as MetaTagsData;
187187

188188
const allTags: HeadTagDef[] = this.metaTags.getHeadTags(metaTagsData);
189189

app/services/meta-tags.ts

Lines changed: 114 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,14 @@ import Intl from 'ember-intl/services/intl';
55
import pathJoin from 'ember-osf-web/utils/path-join';
66
import toArray from 'ember-osf-web/utils/to-array';
77

8-
export type Content = string | number | null | undefined;
8+
interface MetaTagAuthor {
9+
givenName: string;
10+
familyName: string;
11+
}
12+
13+
type Content = string | number | null | undefined | MetaTagAuthor;
914

10-
export type DataContent = Content | Content[];
15+
type DataContent = Content | Content[];
1116

1217
export interface MetaTagsData {
1318
title?: DataContent;
@@ -30,22 +35,22 @@ export interface MetaTagsData {
3035
fbAppId?: DataContent;
3136
twitterSite?: DataContent;
3237
twitterCreator?: DataContent;
33-
author?: DataContent;
38+
contributors?: DataContent;
3439
keywords?: DataContent;
3540
}
3641

37-
export interface MetaTagsDefs {
42+
interface MetaTagsDefs {
3843
[s: string]: DataContent;
3944
}
4045

4146
export interface NameMetaTagAttrs {
4247
name: string;
43-
content: Content;
48+
content: DataContent;
4449
}
4550

4651
export interface PropMetaTagAttrs {
4752
property: string;
48-
content: Content;
53+
content: DataContent;
4954
}
5055

5156
export interface LinkMetaTagAttrs {
@@ -57,7 +62,7 @@ export interface ScriptTagAttrs {
5762
type: string;
5863
}
5964

60-
export type MetaTagAttrs = NameMetaTagAttrs | PropMetaTagAttrs | LinkMetaTagAttrs | ScriptTagAttrs;
65+
type MetaTagAttrs = NameMetaTagAttrs | PropMetaTagAttrs | LinkMetaTagAttrs | ScriptTagAttrs;
6166

6267
export interface HeadTagDef {
6368
type: string;
@@ -70,14 +75,98 @@ export default class MetaTags extends Service {
7075
@service router!: any;
7176
@service headTags!: HeadTagsService;
7277

78+
/**
79+
* buildPersonScriptTag
80+
* ENG-6331 requested more granularity for authors
81+
* This abstracted method get the granulatority required
82+
*
83+
* @param contributors The list of contributors
84+
*
85+
* @returns {HeadTagDef}
86+
*/
87+
private buildPersonScriptTag(contributors: DataContent): HeadTagDef {
88+
const contributor = [];
89+
if(Array.isArray(contributors)) {
90+
contributors.forEach((person: MetaTagAuthor) => {
91+
contributor.push(Object({
92+
'@type': 'schema:Person',
93+
givenName: person.givenName,
94+
familyName: person.familyName,
95+
}));
96+
});
97+
} else {
98+
contributor.push(Object({
99+
'@type': 'schema:Person',
100+
givenName: (contributors as MetaTagAuthor).givenName,
101+
familyName: (contributors as MetaTagAuthor).familyName,
102+
}));
103+
}
104+
105+
return {
106+
type: 'script',
107+
content: JSON.stringify({
108+
'@context': {
109+
dc: 'http://purl.org/dc/elements/1.1/',
110+
schema: 'http://schema.org',
111+
},
112+
'@type': 'schema:CreativeWork',
113+
contributor,
114+
}),
115+
attrs: {
116+
type: 'application/ld+json',
117+
},
118+
};
119+
}
120+
121+
/**
122+
* Get head tag definitions suitable for the head-tags service.
123+
*
124+
* @method getHeadTags
125+
* @param {MetaTagsData} metaTagsData Data values to use for meta tags.
126+
* @return {MetaTagAttrs[]} Returns head tag defintions.
127+
*/
128+
public getHeadTags(metaTagsData: MetaTagsData): HeadTagDef[] {
129+
const metaTagsDefs = this.getMetaTags(metaTagsData);
130+
// Morph MetaTagsDefs into an array of MetaTagAttrs.
131+
const headTagsAttrs: MetaTagAttrs[] = Object.entries(metaTagsDefs)
132+
.reduce(
133+
(acc: MetaTagAttrs[], [name, content]) => acc.concat(
134+
toArray(content).map(contentMember => this.makeMetaTagAttrs(name, contentMember)),
135+
), [],
136+
);
137+
138+
139+
const headTags = headTagsAttrs
140+
.filterBy('content') // Remove tags with no content.
141+
.map(attrs => ({ type: 'meta', attrs }));
142+
143+
if (metaTagsData?.contributors) {
144+
headTags.push(this.buildPersonScriptTag(metaTagsData.contributors));
145+
}
146+
147+
return headTags;
148+
}
149+
150+
public updateHeadTags() {
151+
this.headTags.collectHeadTags();
152+
153+
// https://www.zotero.org/support/dev/exposing_metadata#force_zotero_to_refresh_metadata
154+
const ev = new Event('ZoteroItemUpdated', {
155+
bubbles: true,
156+
cancelable: true,
157+
});
158+
document.dispatchEvent(ev);
159+
}
160+
161+
73162
/**
74163
* Get meta tag definitions.
75164
*
76165
* @method getMetaTags
77166
* @param {MetaTagsData} metaTagsOverrides Data values to override defaults.
78167
* @return {MetaTagsDefs} Returns meta tag definitions.
79168
*/
80-
getMetaTags(metaTagsOverrides: MetaTagsData): MetaTagsDefs {
169+
private getMetaTags(metaTagsOverrides: MetaTagsData): MetaTagsDefs {
81170
// Default values.
82171
const currentUrl = window.location.href;
83172
const metaTagsData: MetaTagsData = {
@@ -109,7 +198,7 @@ export default class MetaTags extends Service {
109198
citation_doi: metaTagsData.doi,
110199
citation_publisher: metaTagsData.siteName,
111200
citation_author_institution: metaTagsData.institution,
112-
citation_author: metaTagsData.author,
201+
citation_author: metaTagsData.contributors,
113202
citation_description: metaTagsData.description,
114203
citation_public_url: metaTagsData.url,
115204
citation_publication_date: metaTagsData.publishedDate,
@@ -123,7 +212,7 @@ export default class MetaTags extends Service {
123212
'dct.created': metaTagsData.publishedDate,
124213
'dc.publisher': metaTagsData.siteName,
125214
'dc.language': metaTagsData.language,
126-
'dc.contributor': metaTagsData.author,
215+
'dc.contributor': metaTagsData.contributors,
127216
'dc.subject': metaTagsData.keywords,
128217
// Open Graph/Facebook
129218
'fb:app_id': metaTagsData.fbAppId,
@@ -151,45 +240,31 @@ export default class MetaTags extends Service {
151240
}
152241

153242
/**
154-
* Get head tag definitions suitable for the head-tags service.
243+
* buildMetaTagContent
244+
* ENG-6331 requested more granularity for authors
245+
* This abstracted method get the granulatority required
155246
*
156-
* @method getHeadTags
157-
* @param {MetaTagsData} metaTagsData Data values to use for meta tags.
158-
* @return {HeadTagDef[]} Returns head tag defintions.
247+
* @param name The name of the attribute
248+
* @param content The content
249+
* @returns {Content}
159250
*/
160-
getHeadTags(metaTagsData: MetaTagsData): HeadTagDef[] {
161-
const metaTagsDefs = this.getMetaTags(metaTagsData);
162-
// Morph MetaTagsDefs into an array of MetaTagAttrs.
163-
const headTagsAttrs: MetaTagAttrs[] = Object.entries(metaTagsDefs)
164-
.reduce(
165-
(acc: MetaTagAttrs[], [name, content]) => acc.concat(
166-
toArray(content).map(contentMember => this.makeMetaTagAttrs(name, contentMember)),
167-
), [],
168-
);
251+
private buildMetaTagContent(name: string, content: Content): Content{
252+
if (['citation_author', 'dc.contributor'].includes(name) && typeof content === 'object') {
253+
return `${content?.familyName}, ${content?.givenName}`;
254+
}
169255

170-
return headTagsAttrs
171-
.filterBy('content') // Remove tags with no content.
172-
.map(attrs => ({ type: 'meta', attrs }));
256+
return content;
173257
}
174258

175-
makeMetaTagAttrs(name: string, content: Content): MetaTagAttrs {
259+
private makeMetaTagAttrs(name: string, content: Content): MetaTagAttrs {
176260
// Open Graph/Facebook tags use 'property' instead of 'name'.
261+
content = this.buildMetaTagContent(name, content);
177262
if (['fb:', 'og:'].includes(name.substring(0, 3))) {
178-
return { property: name, content };
263+
return { property: name, content};
179264
}
180-
return { name, content };
265+
return { name, content};
181266
}
182267

183-
updateHeadTags() {
184-
this.headTags.collectHeadTags();
185-
186-
// https://www.zotero.org/support/dev/exposing_metadata#force_zotero_to_refresh_metadata
187-
const ev = new Event('ZoteroItemUpdated', {
188-
bubbles: true,
189-
cancelable: true,
190-
});
191-
document.dispatchEvent(ev);
192-
}
193268
}
194269

195270
declare module '@ember/service' {

0 commit comments

Comments
 (0)