diff --git a/app/decorators/check-auth.ts b/app/decorators/check-auth.ts index 38cac24562a..16ea7b27ed9 100644 --- a/app/decorators/check-auth.ts +++ b/app/decorators/check-auth.ts @@ -37,10 +37,12 @@ export default function checkAuth>( // Need to handle view-only links before checking auth, and this is the only reasonable place to do it. // This limitation points toward replacing this decorator with a service method meant to be // called in Route.beforeModel. Decorator mixins should probably be considered an anti-pattern. - const { viewOnlyToken = '' } = this.paramsFor('application') as Record; + let { viewOnlyToken = '' } = this.paramsFor('application') as Record; try { if (!this.session.isAuthenticated || this.currentUser.viewOnlyToken !== viewOnlyToken) { + // This is for ENG-8174 where occasionally a %2F or / is at the end of the viewOnlyToken + viewOnlyToken = viewOnlyToken.replace(/(%2[fF]|\/)$/g, ''); this.currentUser.setProperties({ viewOnlyToken }); // Check whether user is actually logged in. diff --git a/app/preprints/-components/preprint-metrics/component.ts b/app/preprints/-components/preprint-metrics/component.ts new file mode 100644 index 00000000000..9d4c5397482 --- /dev/null +++ b/app/preprints/-components/preprint-metrics/component.ts @@ -0,0 +1,48 @@ +import Component from '@glimmer/component'; +import { inject as service } from '@ember/service'; +import { tracked } from '@glimmer/tracking'; +import { task } from 'ember-concurrency'; +import { waitFor } from '@ember/test-waiters'; +import { taskFor } from 'ember-concurrency-ts'; +import Store from '@ember-data/store'; +import config from 'ember-osf-web/config/environment'; +import { BaseMeta } from 'osf-api'; + + +interface InputArgs { + guid: string; +} + +export default class PreprintMetrics extends Component { + @service store!: Store; + @tracked apiMeta!: BaseMeta; + + metricsStartDate = config.OSF.metricsStartDate; + + constructor(owner: unknown, args: InputArgs) { + super(owner, args); + + taskFor(this.loadPreprintMetrics).perform(); + } + + @task + @waitFor + private async loadPreprintMetrics() { + try { + const adapterOptions = Object({ + query: { + 'metrics[views]': 'total', + 'metrics[downloads]': 'total', + }, + }); + + const preprintMetrics = await this.store.findRecord('preprint', this.args.guid, { + reload: true, + adapterOptions, + }); + + this.apiMeta = preprintMetrics.apiMeta; + // eslint-disable-next-line + } catch (_){ } + } +} diff --git a/app/preprints/-components/preprint-metrics/template.hbs b/app/preprints/-components/preprint-metrics/template.hbs new file mode 100644 index 00000000000..4d18dbf9a63 --- /dev/null +++ b/app/preprints/-components/preprint-metrics/template.hbs @@ -0,0 +1,17 @@ +
+ {{#if this.loadPreprintMetrics.isRunning}} + + {{else}} + + {{t 'preprints.detail.share.views'}}: + + {{this.apiMeta.metrics.views}} | + + {{t 'preprints.detail.share.downloads'}}: + + {{this.apiMeta.metrics.downloads}} + + {{t 'preprints.detail.share.metrics_disclaimer'}} {{moment-format this.metricsStartDate 'YYYY-MM-DD'}} + + {{/if}} +
\ No newline at end of file diff --git a/app/preprints/-components/preprint-status-banner/component.ts b/app/preprints/-components/preprint-status-banner/component.ts index 83368aa2712..e14a3485f17 100644 --- a/app/preprints/-components/preprint-status-banner/component.ts +++ b/app/preprints/-components/preprint-status-banner/component.ts @@ -22,6 +22,8 @@ const WITHDRAWN = 'withdrawn'; const PRE_MODERATION = 'pre-moderation'; const POST_MODERATION = 'post-moderation'; +const PROVIDER_OSF = 'provider-osf'; + const STATUS = Object({}); STATUS[PENDING]= 'preprints.detail.status_banner.pending'; STATUS[ACCEPTED]= 'preprints.detail.status_banner.accepted'; @@ -30,6 +32,7 @@ STATUS[PENDING_WITHDRAWAL]= 'preprints.detail.status_banner.pending_withdrawal'; STATUS[WITHDRAWAL_REJECTED]= 'preprints.detail.status_banner.withdrawal_rejected'; const MESSAGE = Object({}); +MESSAGE[PROVIDER_OSF] = 'preprints.detail.status_banner.message.provider_osf'; MESSAGE[PRE_MODERATION] = 'preprints.detail.status_banner.message.pending_pre'; MESSAGE[POST_MODERATION] = 'preprints.detail.status_banner.message.pending_post'; MESSAGE[ACCEPTED] = 'preprints.detail.status_banner.message.accepted'; @@ -45,6 +48,7 @@ WORKFLOW[POST_MODERATION] = 'preprints.detail.status_banner.post_moderation'; WORKFLOW[UNKNOWN] = 'preprints.detail.status_banner.post_moderation'; const CLASS_NAMES = Object({}); +CLASS_NAMES[PROVIDER_OSF] = 'preprint-status-pending-pre'; CLASS_NAMES[PRE_MODERATION] = 'preprint-status-pending-pre'; CLASS_NAMES[POST_MODERATION] = 'preprint-status-pending-post'; CLASS_NAMES[ACCEPTED] = 'preprint-status-accepted'; @@ -68,6 +72,7 @@ interface InputArgs { provider: PreprintProviderModel; latestWithdrawalRequest: PreprintRequestModel | null; latestAction: PreprintRequestActionModel | ReviewActionModel | null; + isOSFBanner: boolean | null; } export default class PreprintStatusBanner extends Component{ @@ -104,7 +109,9 @@ export default class PreprintStatusBanner extends Component{ } public get getClassName(): string { - if (this.isPendingWithdrawal) { + if (this.args.isOSFBanner) { + return CLASS_NAMES[PROVIDER_OSF]; + } else if (this.isPendingWithdrawal) { return CLASS_NAMES[PENDING_WITHDRAWAL]; } else if (this.isWithdrawn) { return CLASS_NAMES[WITHDRAWN]; @@ -119,7 +126,12 @@ export default class PreprintStatusBanner extends Component{ public get bannerContent(): string { const { provider } = this.args; - if (this.isPendingWithdrawal) { + if (this.args.isOSFBanner) { + return this.intl.t(MESSAGE[PROVIDER_OSF], { + name: 'OSF', + documentType: provider.documentType.plural, + }); + } else if (this.isPendingWithdrawal) { return this.intl.t(this.statusExplanation, { documentType: provider.documentType.singular }); } else if (this.isWithdrawn) { return this.intl.t(MESSAGE[WITHDRAWN], { documentType: provider.documentType.singular }); diff --git a/app/preprints/-components/preprint-status-banner/template.hbs b/app/preprints/-components/preprint-status-banner/template.hbs index b634ca2003f..cb9965be220 100644 --- a/app/preprints/-components/preprint-status-banner/template.hbs +++ b/app/preprints/-components/preprint-status-banner/template.hbs @@ -4,10 +4,14 @@ {{else}}
- {{#if this.isWithdrawn}} + {{#if @isOSFBanner}} +
+ {{this.bannerContent}} +
+ {{else if this.isWithdrawn}}
{{else}}
diff --git a/app/preprints/-components/submit/file/template.hbs b/app/preprints/-components/submit/file/template.hbs index 4b7a5615e5e..6cc10b46760 100644 --- a/app/preprints/-components/submit/file/template.hbs +++ b/app/preprints/-components/submit/file/template.hbs @@ -68,7 +68,6 @@ @manager={{@manager}} @preprint={{@manager.preprint}} @clickableElementId={{id}} - @enable={{true}} @dragEnter={{fn (mut this.dragging) true}} @dragOver={{fn (mut this.dragging) true}} @dragLeave={{fn (mut this.dragging) false}} diff --git a/app/preprints/-components/submit/file/upload-file/component.ts b/app/preprints/-components/submit/file/upload-file/component.ts index aa9e99b09ae..775d7c95daf 100644 --- a/app/preprints/-components/submit/file/upload-file/component.ts +++ b/app/preprints/-components/submit/file/upload-file/component.ts @@ -30,6 +30,7 @@ export default class PreprintUpload extends Component { rootFolder?: FileModel; primaryFile: FileModel | undefined; @tracked isUploadFileDisplayed = false; + @tracked isEnabled = false; constructor(owner: unknown, args: any) { super(owner, args); @@ -75,6 +76,7 @@ export default class PreprintUpload extends Component { this.url = new URL( urlString ); this.rootFolder = rootFolder; + this.isEnabled = true; } @action diff --git a/app/preprints/-components/submit/file/upload-file/template.hbs b/app/preprints/-components/submit/file/upload-file/template.hbs index c5e71647423..4e5cd6280f2 100644 --- a/app/preprints/-components/submit/file/upload-file/template.hbs +++ b/app/preprints/-components/submit/file/upload-file/template.hbs @@ -12,7 +12,7 @@ @dragleave={{@dragLeave}} @dragover={{@dragOver}} @drop={{@drop}} - @enable={{@enable}} + @enable={{this.isEnabled}} @id={{id}} @clickable={{this.clickableElementSelectors}} @preUpload={{perform this.preUpload}} diff --git a/app/preprints/-components/submit/supplements/component.ts b/app/preprints/-components/submit/supplements/component.ts index bc593966661..6c4dbe337d5 100644 --- a/app/preprints/-components/submit/supplements/component.ts +++ b/app/preprints/-components/submit/supplements/component.ts @@ -69,6 +69,7 @@ export default class Supplements extends Component{ @waitFor public async removeSelectedProject(): Promise { try { + this.validate(false); await this.args.manager.preprint.removeM2MRelationship('node'); // Remove relationship // Remove relationship on the node side, this only clears the cache locally this.args.manager.preprint.node.get('preprints') @@ -89,7 +90,7 @@ export default class Supplements extends Component{ } @action - public validate(): void { - this.args.manager.validateSupplements(true); + public validate(isValid = true): void { + this.args.manager.validateSupplements(isValid); } } diff --git a/app/preprints/detail/controller.ts b/app/preprints/detail/controller.ts index edb46714c24..b803be299d0 100644 --- a/app/preprints/detail/controller.ts +++ b/app/preprints/detail/controller.ts @@ -61,7 +61,6 @@ export default class PrePrintsDetailController extends Controller { @tracked fullScreenMFR = false; @tracked plauditIsReady = false; - metricsStartDate = config.OSF.metricsStartDate; reviewStateLabelKeyMap = VersionStatusSimpleLabelKey; get hyperlink(): string { @@ -152,6 +151,10 @@ export default class PrePrintsDetailController extends Controller { return false; } + get showOSFBanner(): boolean { + return this.model.provider.id === config.defaultProvider; + } + get showStatusBanner(): boolean { return ( this.model.provider.reviewsWorkflow diff --git a/app/preprints/detail/route.ts b/app/preprints/detail/route.ts index fc93b4f8177..d644d078f9d 100644 --- a/app/preprints/detail/route.ts +++ b/app/preprints/detail/route.ts @@ -60,15 +60,11 @@ export default class PreprintsDetail extends Route { 'contributors', 'identifiers', ]; + + const preprint = await this.store.findRecord('preprint', guid, { reload: true, include: embeddableFields, - adapterOptions: { - query: { - 'metrics[views]': 'total', - 'metrics[downloads]': 'total', - }, - }, }); const provider = await preprint?.get('provider'); @@ -119,6 +115,7 @@ export default class PreprintsDetail extends Route { && !isWithdrawalRejected && !hasPendingWithdrawal; return { + guid, preprint, brand: provider.brand.content, contributors, diff --git a/app/preprints/detail/template.hbs b/app/preprints/detail/template.hbs index 95cef805cdc..317e1eed432 100644 --- a/app/preprints/detail/template.hbs +++ b/app/preprints/detail/template.hbs @@ -109,6 +109,13 @@ @latestAction={{this.model.latestAction}} /> {{/if}} + {{#if this.showOSFBanner}} + + {{/if}}
{{#if this.model.preprint.isWithdrawn}}
- - {{t 'preprints.detail.share.views'}}: - - {{this.model.preprint.apiMeta.metrics.views}} | - - {{t 'preprints.detail.share.downloads'}}: - - {{this.model.preprint.apiMeta.metrics.downloads}} - - {{t 'preprints.detail.share.metrics_disclaimer'}} {{moment-format this.metricsStartDate 'YYYY-MM-DD'}} - +
diff --git a/app/serializers/collection-submission.ts b/app/serializers/collection-submission.ts index d14ff560096..ccffba24fad 100644 --- a/app/serializers/collection-submission.ts +++ b/app/serializers/collection-submission.ts @@ -11,7 +11,8 @@ export default class CollectionSubmissionSerializer extends OsfSerializer { */ serialize(snapshot: DS.Snapshot, options: {}) { const serialized = super.serialize(snapshot, options); - const { data, data: { attributes, relationships } } = serialized; + const { data, data: { relationships } } = serialized; + data.attributes = data.attributes || { }; data.type = 'collection-submissions'; @@ -19,8 +20,9 @@ export default class CollectionSubmissionSerializer extends OsfSerializer { const { guid } = relationships; if ('data' in guid) { const { data: guidData } = guid; + if (guidData && 'id' in guidData) { - attributes!.guid = guidData.id; + data.attributes!.guid = guidData.id; delete relationships.guid; } } diff --git a/mirage/views/addons.ts b/mirage/views/addons.ts index e77522960c3..b5801d6be5f 100644 --- a/mirage/views/addons.ts +++ b/mirage/views/addons.ts @@ -478,7 +478,7 @@ function fakeCheckCredentials( async function emulateUserDoingOAuthFlow(authorizedAccount: ModelInstance, schema: Schema) { await timeout(1000); // eslint-disable-next-line no-console - console.log('Mirage addons view: emulateUserDoingOAuthFlow done'); + console.info('Mirage addons view: emulateUserDoingOAuthFlow done'); const currentUser = schema.roots.first().currentUser; authorizedAccount.update({ credentialsAvailable: true, diff --git a/translations/en-us.yml b/translations/en-us.yml index c3ad0073d91..24d29d82745 100644 --- a/translations/en-us.yml +++ b/translations/en-us.yml @@ -1884,6 +1884,7 @@ preprints: close: 'Close' message: base: '{name} uses {reviewsWorkflow}. This {documentType}' + provider_osf: '{name} {documentType} are not peer-reviewed and acceptance is not an indicator of scholarly merit.' pending_pre: 'is not publicly available or searchable until approved by a moderator.' pending_post: 'is publicly available and searchable but is subject to removal by a moderator.' accepted: 'has been accepted by a moderator and is publicly available and searchable.'