• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

CenterForOpenScience / ember-osf-web / 12892580303

21 Jan 2025 05:34PM UTC coverage: 68.238% (+3.3%) from 64.94%
12892580303

Pull #2447

github

web-flow
Merge df98061b6 into 8621f29d7
Pull Request #2447: [ENG-6813] FE Reference PR for Preprints DOI Versioning

2961 of 4719 branches covered (62.75%)

Branch coverage included in aggregate %.

203 of 269 new or added lines in 13 files covered. (75.46%)

91 existing lines in 1 file now uncovered.

7418 of 10491 relevant lines covered (70.71%)

203.22 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

74.73
/app/preprints/detail/route.ts
1
import Store from '@ember-data/store';
2
import Route from '@ember/routing/route';
3
import RouterService from '@ember/routing/router-service';
4
import { inject as service } from '@ember/service';
5
import { waitFor } from '@ember/test-waiters';
6
import { taskFor } from 'ember-concurrency-ts';
7
import Intl from 'ember-intl/services/intl';
8
import { all, restartableTask } from 'ember-concurrency';
9
import moment from 'moment-timezone';
10

11
import config from 'ember-osf-web/config/environment';
12
import CurrentUser from 'ember-osf-web/services/current-user';
13
import Identifier from 'ember-osf-web/models/identifier';
14
import LicenseModel from 'ember-osf-web/models/license';
15
import { ReviewsState } from 'ember-osf-web/models/provider';
16
import { SparseModel } from 'ember-osf-web/utils/sparse-fieldsets';
17
import MetaTags, { HeadTagDef } from 'ember-osf-web/services/meta-tags';
18
import Ready from 'ember-osf-web/services/ready';
19
import Theme from 'ember-osf-web/services/theme';
20
import captureException from 'ember-osf-web/utils/capture-exception';
21
import { notFoundURL } from 'ember-osf-web/utils/clean-url';
22
import pathJoin from 'ember-osf-web/utils/path-join';
23

24
import PrePrintsDetailController from './controller';
25

26

27
/**
28
 * @module ember-preprints
29
 * @submodule routes
30
 */
31

32
/**
33
 * @class Content Route Handler
34
 */
35

36

37
/**
38
 * Loads all disciplines and preprint providers to the index page
39
 * @class Index Route Handler
40
 */
41
export default class PreprintsDetail extends Route {
42
    @service store!: Store;
43
    @service theme!: Theme;
44
    @service router!: RouterService;
45
    @service currentUser!: CurrentUser;
46
    @service metaTags!: MetaTags;
47
    @service ready!: Ready;
48
    @service intl!: Intl;
49

50
    headTags?: HeadTagDef[];
51

52
    async model(params: { guid: string }) {
53
        try {
6✔
54
            const guid = params.guid;
6✔
55

56
            const embeddableFields = [
6✔
57
                'license',
58
                'provider',
59
                'bibliographic_contributors',
60
                'contributors',
61
                'identifiers',
62
            ];
63
            const preprint = await this.store.findRecord('preprint', guid, {
6✔
64
                reload: true,
65
                include: embeddableFields,
66
                adapterOptions: {
67
                    query: {
68
                        'metrics[views]': 'total',
69
                        'metrics[downloads]': 'total',
70
                    },
71
                },
72
            });
73

74
            const provider = await preprint?.get('provider');
6✔
75

76
            this.theme.set('providerType', 'preprint');
6✔
77
            this.theme.set('id', provider.id);
6✔
78

79
            let primaryFile;
80

81
            if (!preprint.isWithdrawn) {
6✔
82
                primaryFile = await preprint?.get('primaryFile');
4✔
83
                primaryFile.versions = await primaryFile?.versions;
4✔
84
            }
85

86
            const contributors = await preprint?.contributors;
6✔
87

88
            const license = await preprint?.get('license');
6✔
89

90
            const subjects = await preprint?.subjects;
6✔
91
            const versions = await preprint?.queryHasMany('versions');
6✔
92

93
            const preprintWithdrawableState = [ReviewsState.ACCEPTED, ReviewsState.PENDING]
6✔
94
                .includes(preprint.reviewsState);
95
            let isWithdrawalRejected = false;
6✔
96
            let hasPendingWithdrawal = false;
6✔
97
            let latestWithdrawalRequest = null;
6✔
98
            let latestAction = null;
6✔
99
            if (preprint.currentUserPermissions.length > 0) {
6!
100
                const reviewActions = await preprint?.queryHasMany('reviewActions');
6✔
101
                latestAction = reviewActions.firstObject;
6✔
102
                if (preprintWithdrawableState && preprint.currentUserIsAdmin) {
6✔
103
                    const withdrawalRequests = await preprint?.queryHasMany('requests');
2✔
104
                    latestWithdrawalRequest = withdrawalRequests.firstObject;
2✔
105
                    if (latestWithdrawalRequest) {
2!
NEW
106
                        hasPendingWithdrawal = latestWithdrawalRequest.machineState === 'pending';
×
NEW
107
                        const requestActions = await withdrawalRequests.firstObject?.queryHasMany('actions', {
×
108
                            sort: '-modified',
109
                        });
NEW
110
                        latestAction = requestActions.firstObject;
×
111
                        // @ts-ignore: ActionTrigger is never
NEW
112
                        if (latestAction && latestAction.actionTrigger === 'reject') {
×
NEW
113
                            isWithdrawalRejected = true;
×
114
                        }
115
                    }
116
                }
117
            }
118
            const canDisplayWithdrawalButton = preprint.currentUserIsAdmin && preprintWithdrawableState
6✔
119
                && !isWithdrawalRejected && !hasPendingWithdrawal;
120

121
            return {
6✔
122
                preprint,
123
                brand: provider.brand.content,
124
                contributors,
125
                provider,
126
                primaryFile,
127
                license,
128
                subjects,
129
                versions,
130
                latestWithdrawalRequest,
131
                latestAction,
132
                canDisplayWithdrawalButton,
133
            };
134

135
        } catch (error) {
136
            captureException(error);
×
NEW
137
            this.router.transitionTo('not-found', notFoundURL(window.location.pathname));
×
138
            return null;
×
139
        }
140
    }
141

142
    @restartableTask({ cancelOn: 'deactivate' })
143
    @waitFor
144
    async setHeadTags(model: any) {
145
        const blocker = this.ready.getBlocker();
6✔
146
        const {preprint} = await model;
6✔
147

148
        if (preprint) {
6!
149
            const [
150
                contributors = [],
×
151
                license = null,
×
152
                identifiers = [],
×
153
                provider = null,
×
154
            ] = await all([
6✔
155
                preprint.sparseLoadAll(
156
                    'bibliographicContributors',
157
                    { contributor: ['users', 'index'], user: ['fullName'] },
158
                ),
159
                preprint.license,
160
                preprint.identifiers,
161
                preprint.provider,
162
            ]);
163

164
            const doi = (identifiers as Identifier[]).find(identifier => identifier.category === 'doi');
6✔
165
            const image = 'engines-dist/registries/assets/img/osf-sharing.png';
6✔
166

167
            const preprintTitle = preprint.isWithdrawn ?
6✔
168
                this.intl.t('preprints.detail.withdrawn_title', { title: preprint.title }) :
169
                preprint.title;
170

171
            const metaTagsData = {
6✔
172
                title: preprintTitle,
173
                description: preprint.description,
174
                publishedDate: moment(preprint.datePublished).format('YYYY-MM-DD'),
175
                modifiedDate: moment(preprint.dateModified).format('YYYY-MM-DD'),
176
                identifier: preprint.id,
177
                url: pathJoin(config.OSF.url, preprint.id),
178
                doi: doi && doi.value,
6!
179
                image,
180
                keywords: preprint.tags,
181
                siteName: 'OSF',
182
                license: license && (license as LicenseModel).name,
12✔
183
                author: (contributors as SparseModel[]).map(
184
                    contrib => (contrib.users as { fullName: string }).fullName,
24✔
185
                ),
186
            };
187

188
            const allTags: HeadTagDef[] = this.metaTags.getHeadTags(metaTagsData);
6✔
189

190
            if (provider && provider.assets && provider.assets.favicon) {
6!
191
                allTags.push({
×
192
                    type: 'link',
193
                    attrs: {
194
                        rel: 'icon',
195
                        href: provider.assets.favicon,
196
                    },
197
                });
198
            }
199
            this.set('headTags', allTags);
6✔
200
            this.metaTags.updateHeadTags();
6✔
201
            (this.controller as PrePrintsDetailController).plauditIsReady = true;
6✔
202
        }
203
        blocker.done();
6✔
204
    }
205

206
    afterModel(model: any) {
207
        if (!this.currentUser.viewOnlyToken) {
6!
208
            taskFor(this.setHeadTags).perform(model);
6✔
209
        }
210
    }
211
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc