Skip to content

Commit

Permalink
Merge branch 'release/0.125.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
jamescdavis committed Apr 9, 2019
2 parents 0b94df1 + a9e1612 commit 63f40e4
Show file tree
Hide file tree
Showing 27 changed files with 1,984 additions and 241 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [0.125.0] - 2019-04-10
### Added
- Chronos submission
- Preprint withdrawals

## [0.124.2] - 2019-04-08
### Fixed
- make sure there are no line breaks or extra spaces in author list
Expand Down
108 changes: 108 additions & 0 deletions app/components/chronos-submission-panel/component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import Component from '@ember/component';
import { inject as service } from '@ember/service';
import { task, timeout } from 'ember-concurrency';
import { A } from '@ember/array';
import config from 'ember-get-config';

export default Component.extend({
store: service(),
toast: service(),
isLoading: false,
canLoadMore: false,
page: 1,
selectedJournal: null,
keyword: '',
preprint: null,
journals: A(),
publisherFilterKeyword: null,

didReceiveAttrs() {
this.get('_fetchAllApprovedJournals').perform();
},

actions: {
/*
This action is not used because we only need 7 journals from APA
*/
getInitialJournals(keyword) {
this.get('_fetchInitialJournals').perform(keyword);
},
/*
This action is not used because we only need 7 journals from APA
*/
getMoreJournals() {
this.get('_fetchMoreJournals').perform();
},
journalSelected(journal) {
this.set('selectedJournal', journal);
},
cancelSubmission() {
this.set('journals', A());
this.set('selectedJournal', null);
},
},

_fetchAllApprovedJournals: task(function* () {
const approvedJournals = yield this.get('store').query(
'chronos-journal',
{
page: 1,
'filter[id]': config.approvedChronosJournalIds.join(','),
'page[size]': 100,
},
);
this.set('journals', approvedJournals);
}),
/*
This function is not used because we only need 7 journals for APA.
*/
_fetchInitialJournals: task(function* (keyword) {
// Wait a bit for the user to finish typing.
yield timeout(500);
// Reset the list of journals
this.set('journals', A());
// Reset page number
this.set('page', 1);
this.set('isLoading', true);
const journals = yield this.get('store').query('chronos-journal', { page: 1, 'filter[title]': keyword, 'filter[name]': this.get('publisherFilterKeyword') });
this.set('isLoading', false);
const canLoadMore = !(journals.get('meta.total_pages') === this.get('page'));
// Set the keyword
this.set('keyword', keyword);
this.set('canLoadMore', canLoadMore);
this.set('journals', journals);
}).restartable(),

/*
This function is not used because we only need 7 journals for APA.
*/
_fetchMoreJournals: task(function* () {
const journals = this.get('journals');
const page = this.get('page');
const keyword = this.get('keyword');
this.set('isLoading', true);
const moreJournals = yield this.get('store').query('chronos-journal', { page: page + 1, 'filter[title]': keyword, 'filter[name]': this.get('publisherFilterKeyword') });
journals.pushObjects(moreJournals.toArray().map(item => item._internalModel));
this.set('isLoading', false);
const canLoadMore = page + 1 < journals.get('meta.total_pages');
if (canLoadMore) {
this.set('page', page + 1);
}
this.set('canLoadMore', canLoadMore);
}).enqueue(),
_submit: task(function* () {
const newTab = window.open();
const submission = this.get('store').createRecord('chronos-submission', {
journal: this.get('selectedJournal'),
preprint: this.get('preprint'),
});
try {
yield submission.save();
newTab.location.href = submission.get('submissionUrl');
window.location.reload(true);
} catch (e) {
newTab.close();
this.get('toast').error(e.errors[0].detail);
}
}).drop(),
});
28 changes: 28 additions & 0 deletions app/components/chronos-submission-panel/template.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{{#cp-panel}}
{{#cp-panel-toggle}}
<p>{{t 'components.chronos-submission-panel.link_text'}}</p>
{{/cp-panel-toggle}}

{{#cp-panel-body}}
<div>
{{!-- This section is commented out because we only need 7 APA journals.
{{#power-select search=(perform _fetchInitialJournals) optionsComponent=(component 'lazy-options' loadMore=(action "getMoreJournals") isLoading=isLoading canLoadMore=canLoadMore) options=journals placeholder="Select a journal" selected=selectedJournal onfocus=(action "getInitialJournals" "") oninput=(action "getInitialJournals") onchange=(action "journalSelected") as |journal|}}
<strong>{{journal.title}}</strong>
{{/power-select}}
--}}
{{#power-select options=journals placeholder="Select a journal" selected=selectedJournal onchange=(action "journalSelected") as |journal|}}
<strong>{{journal.title}}</strong>
{{/power-select}}
</div>
{{#if selectedJournal}}
<div style="padding-top: 5px">
<p>{{t 'components.chronos-submission-panel.helper_text'}}</p>
</div>

<div class="pull-right">
<button class="btn btn-default" onClick={{action 'cancelSubmission'}}>Cancel</button>
<button class="btn btn-success" onClick={{perform _submit}}>Submit</button>
</div>
{{/if}}
{{/cp-panel-body}}
{{/cp-panel}}
49 changes: 49 additions & 0 deletions app/components/chronos-submission-status-list-row/component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import Component from '@ember/component';
import { inject as service } from '@ember/service';
import { computed } from '@ember/object';

const DRAFTED = 'DRAFT';
const SUBMITTED = 'SUBMITTED';
const ACCEPTED = 'ACCEPTED';
const REJECTED = 'CANCELLED';
const PUBLISHED = 'PUBLISHED';

const STATUS_ICON = {
[DRAFTED]: 'fa-file-text-o',
[SUBMITTED]: 'fa-hourglass-o',
[ACCEPTED]: 'fa-check-circle-o',
[REJECTED]: 'fa-times-circle-o',
[PUBLISHED]: 'fa-book',
};

const ICON_CLASS = {
[DRAFTED]: 'chronos-status-drafted',
[SUBMITTED]: 'chronos-status-submitted',
[ACCEPTED]: 'chronos-status-accepted',
[REJECTED]: 'chronos-status-rejected',
[PUBLISHED]: 'chronos-status-published',
};

const STATUS_LANGUAGE = {
[DRAFTED]: 'components.chronos-submission-status-list-row.drafted',
[SUBMITTED]: 'components.chronos-submission-status-list-row.submitted',
[ACCEPTED]: 'components.chronos-submission-status-list-row.accepted',
[REJECTED]: 'components.chronos-submission-status-list-row.rejected',
[PUBLISHED]: 'components.chronos-submission-status-list-row.published',
};


export default Component.extend({
i18n: service(),
submission: null,
isContributor: false,
statusIcon: computed('submission.status', function () {
return STATUS_ICON[this.get('submission.status')];
}),
statusIconClass: computed('submission.status', function () {
return ICON_CLASS[this.get('submission.status')];
}),
statusLanguage: computed('submission.{status,journal.title}', function () {
return this.get('i18n').t(STATUS_LANGUAGE[this.get('submission.status')], { title: this.get('submission.journal.title') });
}),
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<div>
{{fa-icon statusIcon class=statusIconClass}} {{statusLanguage}}
{{#if isContributor}}
<a target="_blank" rel="noopener" class="fa fa-external-link" href={{submission.submissionUrl}}></a>
{{/if}}
</div>
7 changes: 7 additions & 0 deletions app/components/chronos-submission-status-list/component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Component from '@ember/component';
import { inject as service } from '@ember/service';

export default Component.extend({
store: service(),
submissions: null,
});
9 changes: 9 additions & 0 deletions app/components/chronos-submission-status-list/template.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{{#each submissions as |submission|}}
{{#if isContributor}}
{{chronos-submission-status-list-row submission=submission isContributor=isContributor}}
{{else}}
{{#if (or (eq submission.status "ACCEPTED") (eq submission.status "PUBLISHED"))}}
{{chronos-submission-status-list-row submission=submission isContributor=isContributor}}
{{/if}}
{{/if}}
{{/each}}
28 changes: 28 additions & 0 deletions app/components/chronos-widget/component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import Component from '@ember/component';
import { inject as service } from '@ember/service';
import { task } from 'ember-concurrency';

export default Component.extend({
store: service(),
preprint: null,
submissions: null,
isAllowSubmissions: false,
isAdmin: false,
isContributor: false,
didReceiveAttrs() {
this.get('fetchSubmissions').perform(this.get('preprint.id'));
},
fetchSubmissions: task(function* (preprintId) {
const submissions = yield this.get('store').query('chronos-submission', { preprintId });
this.set('submissions', submissions);
const submittedOrRejectedSubmissions = submissions.filter((item) => {
const status = item.get('status');
return status === 'SUBMITTED' || status === 'PUBLISHED' || status === 'ACCEPTED';
});
if (submittedOrRejectedSubmissions.length > 0) {
this.set('isAllowSubmissions', false);
} else if (this.get('isAdmin') && this.get('preprint.reviewsState') === 'accepted' && (this.get('preprint.provider.reviewsWorkflow') === 'pre-moderation' || this.get('preprint.provider.reviewsWorkflow') === 'post-moderation')) {
this.set('isAllowSubmissions', true);
}
}),
});
1 change: 1 addition & 0 deletions app/components/chronos-widget/template.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{ yield preprint submissions isAllowSubmissions isContributor }}
73 changes: 53 additions & 20 deletions app/components/preprint-status-banner/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { alias } from '@ember/object/computed';
const PENDING = 'pending';
const ACCEPTED = 'accepted';
const REJECTED = 'rejected';
const PENDING_WITHDRAWAL = 'pendingWithdrawal';
const WITHDRAWN = 'withdrawn';

const PRE_MODERATION = 'pre-moderation';
const POST_MODERATION = 'post-moderation';
Expand All @@ -14,19 +16,24 @@ const ICONS = {
[PENDING]: 'fa-hourglass-o',
[ACCEPTED]: 'fa-check-circle-o',
[REJECTED]: 'fa-times-circle-o',
[PENDING_WITHDRAWAL]: 'fa-hourglass-o',
[WITHDRAWN]: 'fa-exclamation-triangle',
};

const STATUS = {
[PENDING]: 'components.preprint-status-banner.pending',
[ACCEPTED]: 'components.preprint-status-banner.accepted',
[REJECTED]: 'components.preprint-status-banner.rejected',
[PENDING_WITHDRAWAL]: 'components.preprint-status-banner.pending_withdrawal',
};

const MESSAGE = {
[PRE_MODERATION]: 'components.preprint-status-banner.message.pending_pre',
[POST_MODERATION]: 'components.preprint-status-banner.message.pending_post',
[ACCEPTED]: 'components.preprint-status-banner.message.accepted',
[REJECTED]: 'components.preprint-status-banner.message.rejected',
[PENDING_WITHDRAWAL]: 'components.preprint-status-banner.message.pending_withdrawal',
[WITHDRAWN]: 'components.preprint-status-banner.message.withdrawn',
};

const WORKFLOW = {
Expand All @@ -39,12 +46,16 @@ const CLASS_NAMES = {
[POST_MODERATION]: 'preprint-status-pending-post',
[ACCEPTED]: 'preprint-status-accepted',
[REJECTED]: 'preprint-status-rejected',
[PENDING_WITHDRAWAL]: 'preprint-status-rejected',
[WITHDRAWN]: 'preprint-status-withdrawn',
};

export default Component.extend({
i18n: service(),
theme: service(),

isWithdrawn: false,

// translations
labelModeratorFeedback: 'components.preprint-status-banner.feedback.moderator_feedback',
moderator: 'components.preprint-status-banner.feedback.moderator',
Expand All @@ -59,35 +70,57 @@ export default Component.extend({
reviewerComment: alias('latestAction.comment'),
reviewerName: alias('latestAction.creator.fullName'),

getClassName: computed('submission.{provider.reviewsWorkflow,reviewsState}', function() {
return this.get('submission.reviewsState') === PENDING ?
CLASS_NAMES[this.get('submission.provider.reviewsWorkflow')] :
CLASS_NAMES[this.get('submission.reviewsState')];
getClassName: computed('submission.{provider.reviewsWorkflow,reviewsState}', 'isPendingWithdrawal', 'isWithdrawn', function() {
if (this.get('isPendingWithdrawal')) {
return CLASS_NAMES[PENDING_WITHDRAWAL];
} else if (this.get('isWithdrawn')) {
return CLASS_NAMES[WITHDRAWN];
} else {
return this.get('submission.reviewsState') === PENDING ?
CLASS_NAMES[this.get('submission.provider.reviewsWorkflow')] :
CLASS_NAMES[this.get('submission.reviewsState')];
}
}),

bannerContent: computed('statusExplanation', 'workflow', 'theme.{isProvider,provider.name}', function() {
bannerContent: computed('statusExplanation', 'workflow', 'theme.{isProvider,provider.name}', 'isPendingWithdrawal', 'isWithdrawn', function() {
const i18n = this.get('i18n');
const tName = this.get('theme.isProvider') ?
this.get('theme.provider.name') :
i18n.t('global.brand_name');

const tWorkflow = i18n.t(this.get('workflow'));
const tStatusExplanation = i18n.t(this.get('statusExplanation'));
return `${i18n.t(this.get('baseMessage'), { name: tName, reviewsWorkflow: tWorkflow, documentType: this.get('submission.provider.documentType') })} ${tStatusExplanation}.`;
if (this.get('isPendingWithdrawal')) {
return i18n.t(this.get('statusExplanation'), { documentType: this.get('submission.provider.documentType') });
} else if (this.get('isWithdrawn')) {
return i18n.t(MESSAGE[WITHDRAWN], { documentType: this.get('submission.provider.documentType') });
} else {
const tName = this.get('theme.isProvider') ?
this.get('theme.provider.name') :
i18n.t('global.brand_name');
const tWorkflow = i18n.t(this.get('workflow'));
const tStatusExplanation = i18n.t(this.get('statusExplanation'));
return `${i18n.t(this.get('baseMessage'), { name: tName, reviewsWorkflow: tWorkflow, documentType: this.get('submission.provider.documentType') })} ${tStatusExplanation}.`;
}
}),

statusExplanation: computed('submission.{provider.reviewsWorkflow,reviewsState}', function() {
return this.get('submission.reviewsState') === PENDING ?
MESSAGE[this.get('submission.provider.reviewsWorkflow')] :
MESSAGE[this.get('submission.reviewsState')];
statusExplanation: computed('submission.{provider.reviewsWorkflow,reviewsState}', 'isPendingWithdrawal', function() {
if (this.get('isPendingWithdrawal')) {
return MESSAGE[PENDING_WITHDRAWAL];
} else {
return this.get('submission.reviewsState') === PENDING ?
MESSAGE[this.get('submission.provider.reviewsWorkflow')] :
MESSAGE[this.get('submission.reviewsState')];
}
}),

status: computed('submission.reviewsState', function() {
return STATUS[this.get('submission.reviewsState')];
status: computed('submission.reviewsState', 'isPendingWithdrawal', function() {
const currentState = this.get('isPendingWithdrawal') ? PENDING_WITHDRAWAL : this.get('submission.reviewsState');
return STATUS[currentState];
}),

icon: computed('submission.reviewsState', function() {
return ICONS[this.get('submission.reviewsState')];
icon: computed('submission.reviewsState', 'isPendingWithdrawal', 'isWithdrawn', function() {
let currentState = this.get('submission.reviewsState');
if (this.get('isPendingWithdrawal')) {
currentState = PENDING_WITHDRAWAL;
} else if (this.get('isWithdrawn')) {
currentState = WITHDRAWN;
}
return ICONS[currentState];
}),

workflow: computed('submission.provider.reviewsWorkflow', function () {
Expand Down
Loading

0 comments on commit 63f40e4

Please sign in to comment.