Skip to content

Commit fa8a050

Browse files
committed
Merge branch 'release/20.12.0'
2 parents a8c62bd + 965151b commit fa8a050

File tree

132 files changed

+4478
-521
lines changed

Some content is hidden

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

132 files changed

+4478
-521
lines changed

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ 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+
## [20.12.0] - 2020-12-08
8+
### Added
9+
- branded registries moderation
10+
711
## [20.11.0] - 2020-11-03
812
### Added
913
- storage caps support in quickfiles and draft registrations
@@ -1674,7 +1678,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
16741678
### Added
16751679
- Quick Files
16761680

1677-
[Unreleased]: https://github.com/CenterForOpenScience/ember-osf-web/compare/20.11.0...develop
1681+
[Unreleased]: https://github.com/CenterForOpenScience/ember-osf-web/compare/20.12.0...develop
1682+
[20.12.0]: https://github.com/CenterForOpenScience/ember-osf-web/releases/tag/20.12.0
16781683
[20.11.0]: https://github.com/CenterForOpenScience/ember-osf-web/releases/tag/20.11.0
16791684
[20.10.1]: https://github.com/CenterForOpenScience/ember-osf-web/releases/tag/20.10.1
16801685
[20.10.0]: https://github.com/CenterForOpenScience/ember-osf-web/releases/tag/20.10.0

app/adapters/moderator.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import DS from 'ember-data';
2+
import OsfAdapter from './osf-adapter';
3+
4+
interface ModeratorAdapterOptions {
5+
providerId: string;
6+
}
7+
8+
export default class ModeratorAdapter extends OsfAdapter {
9+
parentRelationship = 'provider';
10+
urlForFindRecord(id: string, _: string, snapshot: DS.Snapshot): string {
11+
const adapterOptions = snapshot.adapterOptions as ModeratorAdapterOptions;
12+
const { providerId } = adapterOptions;
13+
return `${this.urlPrefix()}/providers/registrations/${providerId}/moderators/${id}`;
14+
}
15+
}
16+
17+
declare module 'ember-data/types/registries/adapter' {
18+
export default interface AdapterRegistry {
19+
moderator: ModeratorAdapter;
20+
} // eslint-disable-line semi
21+
}

app/adapters/review-action.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import OsfAdapter from './osf-adapter';
22

33
export default class ReviewActionAdapter extends OsfAdapter {
4-
pathForType(_: string): string {
5-
return 'actions/reviews/';
6-
}
4+
parentRelationship = 'target';
75
}
86

97
declare module 'ember-data/types/registries/adapter' {

app/adapters/subscription.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import OsfAdapter from './osf-adapter';
2+
3+
export default class SubscriptionAdapter extends OsfAdapter {
4+
}
5+
6+
declare module 'ember-data/types/registries/adapter' {
7+
export default interface AdapterRegistry {
8+
subscription: SubscriptionAdapter;
9+
} // eslint-disable-line semi
10+
}

app/models/moderator.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import DS from 'ember-data';
2+
3+
import UserModel from 'ember-osf-web/models/user';
4+
import OsfModel from './osf-model';
5+
import RegistrationProviderModel from './registration-provider';
6+
7+
const { attr, belongsTo } = DS;
8+
9+
export enum PermissionGroup {
10+
Admin = 'admin',
11+
Moderator = 'moderator',
12+
}
13+
14+
export default class ModeratorModel extends OsfModel {
15+
@attr('string') permissionGroup!: PermissionGroup;
16+
17+
// Write-only attributes
18+
@attr('string') fullName!: string;
19+
@attr('string') email!: string;
20+
21+
@belongsTo('registration-provider', { inverse: 'moderators', polymorphic: true })
22+
provider!: RegistrationProviderModel;
23+
24+
@belongsTo('user', { inverse: null })
25+
user!: UserModel;
26+
}
27+
28+
declare module 'ember-data/types/registries/model' {
29+
export default interface ModelRegistry {
30+
'moderator': ModeratorModel;
31+
} // eslint-disable-line semi
32+
}

app/models/preprint-provider.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ export default class PreprintProviderModel extends ProviderModel {
2424

2525
// Reviews settings
2626
@attr('array') permissions!: string[];
27-
@attr('string') reviewsWorkflow!: string | null;
2827
@attr('boolean', { allowNull: true }) reviewsCommentsPrivate!: boolean | null;
29-
@attr('boolean', { allowNull: true }) reviewsCommentsAnonymous!: boolean | null;
3028

3129
// Relationships
3230
@hasMany('preprint', { inverse: 'provider' })

app/models/provider.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,24 @@ export interface Assets {
2020
wide_white: string;
2121
}
2222

23+
export enum ReviewPermissions {
24+
SetUpModeration = 'set_up_moderation',
25+
ViewSubmissions = 'view_submissions',
26+
AcceptSubmissions = 'accept_submissions',
27+
RejectSubmissions = 'reject_submissions',
28+
WithdrawSubmissions = 'withdraw_submissions',
29+
EditReviewComments = 'edit_review_comments',
30+
ViewActions = 'view_actions',
31+
AddModerator = 'add_moderator',
32+
UpdateModerator = 'update_moderator',
33+
RemoveModerator = 'remove_moderator',
34+
EditReviewSettings = 'edit_review_settings',
35+
AddReviewer = 'add_reviewer',
36+
AssignReviewer = 'assign_reviewer',
37+
ViewAssignedSubmissions = 'view_assigned_submissions',
38+
ReviewAssignedSubmissions = 'review_assigned_submissions',
39+
}
40+
2341
/* eslint-enable camelcase */
2442

2543
export default abstract class ProviderModel extends OsfModel {
@@ -34,6 +52,8 @@ export default abstract class ProviderModel extends OsfModel {
3452
@attr('string') facebookAppId!: string;
3553
@attr('boolean') allowSubmissions!: boolean;
3654
@attr('boolean') allowCommenting!: boolean;
55+
@attr('fixstring') reviewsWorkflow!: string | null;
56+
@attr('boolean') reviewsCommentsAnonymous!: boolean | null;
3757
@attr() assets?: Partial<Assets>; // TODO: camelize in transform
3858

3959
@hasMany('subject', { inverse: null, async: false })

app/models/registration-provider.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import DS from 'ember-data';
2+
import ReviewActionModel from 'ember-osf-web/models/review-action';
23

4+
import { computed } from '@ember/object';
35
import RegistrationSchemaModel from 'ember-osf-web/models/registration-schema';
46
import BrandModel from './brand';
5-
import ProviderModel from './provider';
7+
import ModeratorModel from './moderator';
8+
import ProviderModel, { ReviewPermissions } from './provider';
69
import RegistrationModel from './registration';
710

811
const { attr, hasMany, belongsTo } = DS;
@@ -17,11 +20,28 @@ export default class RegistrationProviderModel extends ProviderModel {
1720
@hasMany('registration-schema', { inverse: null })
1821
schemas!: DS.PromiseManyArray<RegistrationSchemaModel> | RegistrationSchemaModel[];
1922

23+
@hasMany('moderator', { inverse: 'provider' })
24+
moderators!: DS.PromiseManyArray<ModeratorModel> | ModeratorModel[];
25+
26+
@hasMany('review-action', { inverse: null })
27+
actions!: DS.PromiseManyArray<ReviewActionModel> | ReviewActionModel[];
28+
2029
@attr('fixstring')
2130
shareSource?: string;
2231

2332
@attr('boolean')
2433
brandedDiscoveryPage?: boolean;
34+
35+
@attr('array')
36+
permissions!: ReviewPermissions[];
37+
38+
@computed('permissions')
39+
get currentUserCanReview() {
40+
if (this.permissions) {
41+
return this.permissions.includes(ReviewPermissions.ViewSubmissions);
42+
}
43+
return false;
44+
}
2545
}
2646

2747
declare module 'ember-data/types/registries/model' {

app/models/registration.ts

Lines changed: 30 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { computed } from '@ember/object';
21
import { buildValidations, validator } from 'ember-cp-validations';
32
import DS from 'ember-data';
43

54
import DraftRegistrationModel from 'ember-osf-web/models/draft-registration';
5+
import ReviewActionModel, { ReviewActionTrigger } from 'ember-osf-web/models/review-action';
66
import { RegistrationResponse } from 'ember-osf-web/packages/registration-schema';
77

88
import CommentModel from './comment';
@@ -15,16 +15,33 @@ import UserModel from './user';
1515

1616
const { attr, belongsTo, hasMany } = DS;
1717

18-
export enum RegistrationState {
19-
Embargoed = 'Embargoed',
20-
Public = 'Public',
21-
Withdrawn = 'Withdrawn',
22-
PendingRegistration = 'PendingRegistration',
23-
PendingWithdrawal = 'PendingWithdrawal',
24-
PendingEmbargo = 'PendingEmbargo',
25-
PendingEmbargoTermination = 'PendingEmbargoTermination',
18+
export enum RegistrationReviewStates {
19+
Initial = 'initial',
20+
Pending = 'pending',
21+
Accepted = 'accepted',
22+
Rejected = 'rejected',
23+
Withdrawn = 'withdrawn',
24+
Embargo = 'embargo',
25+
PendingEmbargoTermination = 'pending_embargo_termination',
26+
PendingWithdrawRequest = 'pending_withdraw_request',
27+
PendingWithdraw = 'pending_withdraw',
2628
}
2729

30+
type NonActionableStates = RegistrationReviewStates.Initial
31+
| RegistrationReviewStates.Withdrawn | RegistrationReviewStates.Rejected;
32+
33+
export type ReviewsStateToDecisionMap = Exclude<RegistrationReviewStates, NonActionableStates>;
34+
export const reviewsStateToDecisionMap: { [index in ReviewsStateToDecisionMap]: ReviewActionTrigger[] } = {
35+
[RegistrationReviewStates.Accepted]: [ReviewActionTrigger.ForceWithdraw],
36+
[RegistrationReviewStates.Embargo]: [ReviewActionTrigger.ForceWithdraw],
37+
[RegistrationReviewStates.Pending]:
38+
[ReviewActionTrigger.AcceptSubmission, ReviewActionTrigger.RejectSubmission],
39+
[RegistrationReviewStates.PendingWithdraw]:
40+
[ReviewActionTrigger.AcceptWithdrawal, ReviewActionTrigger.RejectWithdrawal],
41+
[RegistrationReviewStates.PendingWithdrawRequest]: [ReviewActionTrigger.ForceWithdraw],
42+
[RegistrationReviewStates.PendingEmbargoTermination]: [ReviewActionTrigger.ForceWithdraw],
43+
};
44+
2845
const Validations = buildValidations({
2946
license: [
3047
validator('presence', {
@@ -57,26 +74,13 @@ export default class RegistrationModel extends NodeModel.extend(Validations) {
5774
@attr('fixstring') articleDoi!: string | null;
5875
@attr('object') registeredMeta!: RegistrationMetadata;
5976
@attr('registration-responses') registrationResponses!: RegistrationResponse;
77+
@attr('fixstring') reviewsState!: RegistrationReviewStates;
6078

6179
// Write-only attributes
6280
@attr('array') includedNodeIds?: string[];
6381
@attr('boolean') createDoi?: boolean;
6482
@attr('fixstring') draftRegistrationId?: string;
6583

66-
@computed(
67-
'withdrawn', 'embargoed', 'public', 'pendingRegistrationApproval',
68-
'pendingEmbargoApproval', 'pendingEmbargoTerminationApproval',
69-
'pendingWithdrawal',
70-
)
71-
get state(): RegistrationState {
72-
const stateMap: any = this.registrationStateMap();
73-
const currentState: RegistrationState = Object.keys(stateMap)
74-
.filter(active => stateMap[active])
75-
.map(key => RegistrationState[key as keyof typeof RegistrationState])[0];
76-
77-
return currentState || RegistrationState.Public;
78-
}
79-
8084
@belongsTo('node', { inverse: 'registrations' })
8185
registeredFrom!: DS.PromiseObject<NodeModel> & NodeModel;
8286

@@ -107,31 +111,12 @@ export default class RegistrationModel extends NodeModel.extend(Validations) {
107111
@hasMany('institution', { inverse: 'registrations' })
108112
affiliatedInstitutions!: DS.PromiseManyArray<InstitutionModel> | InstitutionModel[];
109113

114+
@hasMany('review-action', { inverse: 'target' })
115+
reviewActions!: DS.PromiseManyArray<ReviewActionModel> | ReviewActionModel[];
116+
110117
// Write-only relationships
111118
@belongsTo('draft-registration', { inverse: null })
112119
draftRegistration!: DraftRegistrationModel;
113-
114-
registrationStateMap(): Record<RegistrationState, boolean> {
115-
const {
116-
pendingRegistrationApproval,
117-
pendingEmbargoApproval,
118-
pendingEmbargoTerminationApproval,
119-
pendingWithdrawal,
120-
withdrawn,
121-
embargoed,
122-
} = this;
123-
const embargo = embargoed && !pendingEmbargoTerminationApproval;
124-
125-
return {
126-
PendingRegistration: pendingRegistrationApproval,
127-
PendingEmbargo: pendingEmbargoApproval,
128-
PendingEmbargoTermination: pendingEmbargoTerminationApproval,
129-
PendingWithdrawal: pendingWithdrawal,
130-
Withdrawn: withdrawn,
131-
Embargoed: embargo,
132-
Public: !pendingWithdrawal,
133-
};
134-
}
135120
}
136121

137122
declare module 'ember-data/types/registries/model' {

app/models/review-action.ts

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,59 @@
1+
import { computed } from '@ember/object';
2+
import { inject as service } from '@ember/service';
13
import DS from 'ember-data';
4+
import Intl from 'ember-intl/services/intl';
25

36
import OsfModel from './osf-model';
4-
import PreprintModel from './preprint';
5-
import PreprintProviderModel from './preprint-provider';
7+
import RegistrationModel from './registration';
68
import UserModel from './user';
79

810
const { attr, belongsTo } = DS;
911

12+
export enum ReviewActionTrigger {
13+
Submit = 'submit', // registration submitted by admins
14+
AcceptSubmission = 'accept_submission', // accept submission
15+
RejectSubmission = 'reject_submission', // reject submission
16+
ForceWithdraw = 'force_withdraw', // force withdraw without request
17+
RequestWithdrawal = 'request_withdrawal', // request to withdraw by contributors
18+
AcceptWithdrawal = 'accept_withdrawal', // accept withdrawal request
19+
RejectWithdrawal = 'reject_withdrawal', // deny withdrawal request
20+
RequestEmbargoTermination = 'request_embargo_termination', // admin requests embargo termination
21+
}
22+
23+
const TriggerToPastTenseTranslationKey: Record<ReviewActionTrigger, string> = {
24+
submit: 'registries.reviewActions.triggerPastTense.submit',
25+
accept_submission: 'registries.reviewActions.triggerPastTense.accept_submission',
26+
reject_submission: 'registries.reviewActions.triggerPastTense.reject_submission',
27+
force_withdraw: 'registries.reviewActions.triggerPastTense.force_withdraw',
28+
request_withdrawal: 'registries.reviewActions.triggerPastTense.request_withdrawal',
29+
accept_withdrawal: 'registries.reviewActions.triggerPastTense.accept_withdrawal',
30+
reject_withdrawal: 'registries.reviewActions.triggerPastTense.reject_withdrawal',
31+
request_embargo_termination: 'registries.reviewActions.triggerPastTense.request_embargo_termination',
32+
};
33+
1034
export default class ReviewActionModel extends OsfModel {
11-
@attr('string') actionTrigger!: string;
35+
@service intl!: Intl;
36+
37+
@attr('string') actionTrigger!: ReviewActionTrigger;
1238
@attr('string') comment!: string;
1339
@attr('string') fromState!: string;
1440
@attr('string') toState!: string;
1541
@attr('date') dateCreated!: Date;
1642
@attr('date') dateModified!: Date;
43+
@attr('boolean') auto!: boolean;
44+
@attr('boolean') visible!: boolean;
1745

18-
@belongsTo('preprint-provider', { inverse: null })
19-
provider!: DS.PromiseObject<PreprintProviderModel> & PreprintProviderModel;
20-
21-
@belongsTo('preprint', { inverse: 'reviewActions' })
22-
target!: DS.PromiseObject<PreprintModel> & PreprintModel;
46+
@belongsTo('registration', { inverse: 'reviewActions', polymorphic: true })
47+
target!: DS.PromiseObject<RegistrationModel> & RegistrationModel;
2348

2449
@belongsTo('user', { inverse: null })
2550
creator!: DS.PromiseObject<UserModel> & UserModel;
51+
52+
@computed('actionTrigger')
53+
get triggerPastTense(): string {
54+
const translationKey = TriggerToPastTenseTranslationKey[this.actionTrigger];
55+
return translationKey ? this.intl.t(translationKey) : '';
56+
}
2657
}
2758

2859
declare module 'ember-data/types/registries/model' {

0 commit comments

Comments
 (0)