diff --git a/app/components/nav-bar/index.hbs b/app/components/nav-bar/index.hbs index 6564c9d80..5b82f7a5c 100644 --- a/app/components/nav-bar/index.hbs +++ b/app/components/nav-bar/index.hbs @@ -13,6 +13,9 @@
${JSON.stringify(reposThatUserAgreedToDeposit.map(repo => repo.id)).replace(/[\[\]']/g, '')}${JSON.stringify(reposWithoutAgreementText.map(repo => repo.id)).replace(/[\[\]']/g, '')} `;
+ }
+ if (reposWithWebLink.length > 0) {
+ swalMsg = `${swalMsg}You were prompted to submit to: ${JSON.stringify(reposWithWebLink.map(repo => repo.id)).replace(/[\[\]']/g, '')}`;
+ }
+
+ let result = await swal({
+ title: 'Confirm submission',
+ html: swalMsg, // eslint-disable-line
+ confirmButtonText: 'Confirm',
+ showCancelButton: true,
+ });
+
+ if (result.value) {
+ // Update repos to reflect repos that user agreed to deposit.
+ // Must keep web-link repos.
+ this.set('model.sub.repositories', get(this, 'model.sub.repositories').filter((repo) => {
+ if (get(repo, '_isWebLink')) {
+ return true;
+ }
+ let temp = reposWithAgreementText.map(x => x.id).includes(get(repo, 'name'));
+ if (!temp) {
+ return true;
+ } else if (reposThatUserAgreedToDeposit.map(r => r.id).includes(get(repo, 'name'))) {
+ return true;
+ }
+ return false;
+ }));
+
+ let sub = get(this, 'model.sub');
+ let message = this.message;
+ this.submissionHandler.approveSubmission(sub, message);
+ }
+ } else {
+ // there were repositories, but the user didn't sign any of the agreements
+ let reposUserDidNotAgreeToDeposit = reposWithAgreementText.filter((repo) => {
+ if (!reposThatUserAgreedToDeposit.includes(repo)) {
+ return true;
+ }
+ });
+ let result = await swal({
+ title: 'Your submission cannot be submitted.',
+ html: `You declined to agree to the deposit agreement(s) for ${JSON.stringify(reposUserDidNotAgreeToDeposit.map(repo => repo.id)).replace(/[\[\]']/g, '')}. Therefore, this submission cannot be submitted. \n You can either (a) cancel the submission or (b) return to the submission to provide required input and try again.`,
+ confirmButtonText: 'Cancel submission',
+ showCancelButton: true,
+ cancelButtonText: 'Go back to edit information'
+ });
+
+ if (result.value) {
+ this.cancelSubmission();
+ }
+ }
+ } else {
+ // no repositories associated with the submission
+ let result = await swal({
+ title: 'Your submission cannot be submitted.',
+ html: 'No repositories are associated with this submission. \n You can either (a) cancel the submission or (b) return to the submission and edit it to include a repository.',
+ confirmButtonText: 'Cancel submission',
+ showCancelButton: true,
+ cancelButtonText: 'Go back to edit information'
+ });
+
+ if (result.value) {
+ this.cancelSubmission();
+ }
+ }
+ }
+ }
+
+ @action
+ async cancelSubmission() {
+ let message = this.message;
+ let sub = get(this, 'model.sub');
+
+ if (!message) {
+ swal(
+ 'Comment field empty',
+ 'Please add a comment for your cancellation.',
+ 'warning'
+ );
+ return;
+ }
+
+ let result = await swal({
+ title: 'Are you sure?',
+ text: 'If you cancel this submission, it will not be able to be resumed.',
+ confirmButtonText: 'Yes, cancel this submission',
+ confirmButtonColor: '#f86c6b',
+ cancelButtonText: 'Never mind',
+ showCancelButton: true,
+ });
+
+ if (result.value) {
+ $('.block-user-input').css('display', 'block');
+ await this.submissionHandler.cancelSubmission(sub, message);
+ window.location.reload(true);
+ }
+ }
+
+ @action
+ async deleteSubmission(submission) {
+ let result = await swal({
+ text: 'Are you sure you want to delete this draft submission? This cannot be undone.',
+ confirmButtonText: 'Delete',
+ confirmButtonColor: '#f86c6b',
+ showCancelButton: true
+ });
+
+ if (result.value) {
+ const ignoreList = this.searchHelper;
+
+ await this.submissionHandler.deleteSubmission(submission);
+ ignoreList.clearIgnore();
+ ignoreList.ignore(submission.get('id'));
+ this.transitionToRoute('submissions');
+ }
+ }
+}
diff --git a/app/controllers/administrator/index.js b/app/controllers/administrator/index.js
new file mode 100644
index 000000000..6a8d82de0
--- /dev/null
+++ b/app/controllers/administrator/index.js
@@ -0,0 +1,144 @@
+import Controller from '@ember/controller';
+import { tracked } from '@glimmer/tracking';
+import Bootstrap4Theme from 'ember-models-table/themes/bootstrap4';
+import { set, get } from '@ember/object';
+import { inject as service } from '@ember/service';
+import {action} from '@ember/object';
+
+export default class SubmissionsIndex extends Controller {
+ @service currentUser;
+ @service('app-static-config') configurator;
+
+ actionData = null;
+ @tracked assetsUri = null;
+ @tracked themeInstance = Bootstrap4Theme.create();
+ // Bound to message dialog.
+ @tracked messageShow = false
+ @tracked messageTo = '';
+ @tracked messageSubject = '';
+ @tracked messageText = '';
+ @tracked tablePageSize = 10;
+ @tracked tablePageSizeValues = [10, 25, 50];
+
+ constructor() {
+ super(...arguments);
+
+ this.configurator.getStaticConfig()
+ .then(config => this.set('assetsUri', config.assetsUri));
+ }
+
+ // Columns displayed depend on the user role
+ get columns() {
+ if (get(this, 'currentUser.user.isAdmin')) {
+ return [
+ {
+ propertyName: 'publication',
+ title: 'Article',
+ className: 'title-column',
+ component: 'submissions-article-cell',
+ disableSorting: true,
+ disableFiltering: true
+ },
+ {
+ propertyName: 'awardNumber',
+ title: 'Award Number',
+ className: 'awardnum-funder-column',
+ component: 'submissions-award-cell',
+ disableSorting: true,
+ disableFiltering: true
+ },
+ {
+ propertyName: 'Funder',
+ title: 'Funder',
+ className: 'funder-column',
+ component: 'submissions-funder-cell',
+ disableSorting: true,
+ disableFiltering: true
+ },
+ {
+ propertyName: 'repositories',
+ title: 'Repositories',
+ className: 'repositories-column',
+ component: 'submissions-repo-cell',
+ },
+ {
+ propertyName: 'submittedDate',
+ title: 'Submitted Date',
+ className: 'date-column',
+ component: 'date-cell'
+ },
+ {
+ propertyName: 'submissionStatus',
+ title: 'Status',
+ className: 'status-column',
+ component: 'submissions-status-cell',
+ filterWithSelect: true
+ },
+ {
+ propertyName: 'submitterName',
+ title: 'Submitter Name',
+ className: 'name-column',
+ component: 'submissions-name-cell'
+ },
+ {
+ propertyName: 'submitterEmail',
+ title: 'Submitter Email',
+ className: 'email-column',
+ component: 'submissions-email-cell'
+ },
+ {
+ propertyName: 'repoCopies',
+ title: 'Manuscript IDs',
+ className: 'msid-column',
+ component: 'submissions-repoid-cell',
+ disableSorting: true,
+ disableFiltering: true
+ }
+ ];
+ } else { // eslint-disable-line
+ return [];
+ }
+ }
+
+ @action
+ myAction(data) {
+ let filteredColumn = this.getFilteredColumns(data);
+ let sortedColumn = this.getSortedColumns(data);
+
+ this.send('updateTable', {sortedColumn: sortedColumn,
+ filteredColumn: filteredColumn})
+ }
+
+ getSortedColumns(data) {
+ if (data.sort.length === 0) {
+ return undefined;
+ }
+ let sort = data.sort[0].split(':')
+ let propertyName = sort[0];
+ let sortDirection = sort[1];
+
+ let querySort = {};
+ querySort[propertyName] = {
+ missing: '_last',
+ order: `${sortDirection}`
+ }
+ console.log(querySort)
+ return [querySort];
+ }
+
+ getFilteredColumns(data) {
+ if (Object.keys(data.columnFilters).length === 0) {
+ return undefined;
+ }
+ let filterSort = [];
+ for (let column in data.columnFilters) {
+ let query = { 'term' : {}}
+ if (column === "publication") {
+ }
+ query['term'][column] = data.columnFilters[column]
+ filterSort.push(query)
+ }
+ return filterSort;
+ }
+
+}
diff --git a/app/router.js b/app/router.js
index ba14f45b9..7c99400d7 100644
--- a/app/router.js
+++ b/app/router.js
@@ -9,6 +9,10 @@ class Router extends EmberRouter {
Router.map(function () {
this.route('dashboard', { path: '/' });
+ this.route('administrator', function() {
+ this.route('detail', {path: '/*path'});
+ this.route('detail', {path: '/:submission_id'});
+ });
this.route('submissions', function () {
this.route('detail', { path: '/*path' });
this.route('detail', { path: '/:submission_id' });
@@ -26,6 +30,7 @@ Router.map(function () {
this.route('detail', { path: '/*path' });
this.route('detail', { path: '/:grant_id' });
});
+
this.route('not-found-error', { path: '/*path' });
this.route('thanks');
});
diff --git a/app/routes/administrator/detail.js b/app/routes/administrator/detail.js
new file mode 100644
index 000000000..55e961ec1
--- /dev/null
+++ b/app/routes/administrator/detail.js
@@ -0,0 +1,36 @@
+import CheckSessionRoute from '../check-session-route';
+import { hash } from 'rsvp';
+
+export default class DetailRoute extends CheckSessionRoute {
+ model(params) {
+ if (!params || !params.submission_id) {
+ this.errorHandler.handleError(new Error('didNotLoadData'));
+ return;
+ }
+
+ const querySize = 500;
+ const sub = this.store.findRecord('submission', params.submission_id);
+ const files = this.store.query('file', { term: { submission: params.submission_id }, size: querySize });
+ const deposits = this.store.query('deposit', { term: { submission: params.submission_id }, size: querySize });
+ const submissionEvents = this.store.query('submissionEvent', {
+ sort: [
+ { performedDate: 'asc' }
+ ],
+ query: {
+ term: { submission: params.submission_id }
+ }
+ });
+ const repoCopies = sub.then(s =>
+ this.store.query('repositoryCopy', { term: { publication: s.get('publication.id') }, size: querySize }));
+ const repos = sub.then(s => s.get('repositories'));
+
+ return hash({
+ sub,
+ files,
+ deposits,
+ repoCopies,
+ submissionEvents,
+ repos
+ });
+ }
+}
diff --git a/app/routes/administrator/index.js b/app/routes/administrator/index.js
new file mode 100644
index 000000000..869740cc6
--- /dev/null
+++ b/app/routes/administrator/index.js
@@ -0,0 +1,134 @@
+import { inject as service } from '@ember/service';
+import CheckSessionRoute from '../check-session-route';
+import RSVP from 'rsvp';
+import { get } from '@ember/object';
+import {action} from '@ember/object';
+import PublicationModel from '../../models/publication';
+
+export default class IndexRoute extends CheckSessionRoute {
+ @service('current-user')
+ currentUser;
+
+ @service('search-helper')
+ searchHelper;
+
+ defaultAdminSort = [{
+ submittedDate: {
+ missing: '_last',
+ order: 'desc'
+ }
+ }];
+
+ defaultSubmitterSort = [
+ { submitted: { missing: '_last', order: 'asc' } },
+ { submittedDate: { missing: '_last', order: 'desc' } },
+ { submissionStatus: { missing: '_last', order: 'asc' } }
+ ];
+
+ sort = undefined;
+ filter = undefined;
+
+
+ async model() {
+ const user = get(this, 'currentUser.user');
+
+ let submissions = null;
+
+ //Method 1 of updating model
+ if (user.get('isAdmin')) {
+ submissions = this._doAdmin(this.sort, this.filter);
+ } else if (user.get('isSubmitter')) {
+ submissions = this._doSubmitter(user, this.sort, this.filter);
+ }
+
+ /* Default model - Method 2
+ if (user.get('isAdmin')) {
+ submissions = this._doAdmin();
+ } else if (user.get('isSubmitter')) {
+ submissions = this._doSubmitter(user);
+ } */
+
+ submissions.then(() => this.searchHelper.clearIgnore());
+
+ return RSVP.hash({
+ submissions
+ });
+ }
+
+
+
+ _doAdmin(sortedColumn = this.defaultAdminSort, filteredColumn = []) {
+ const ignoreList = this.searchHelper.getIgnoreList();
+
+ const query = {
+ sort: sortedColumn,
+ query: {
+ match_all: {},
+ filter: filteredColumn,
+ must_not: [
+ { term: { submissionStatus: 'cancelled' } }
+ ]
+ },
+ size: 500
+ };
+
+ if (ignoreList && ignoreList.length > 0) {
+ query.query.must_not.push({ terms: { '@id': ignoreList } });
+ }
+
+ return this.store.query('submission', query);
+ }
+
+ _doSubmitter(user, sortedColumn = this.defaultSubmitterSort, filteredColumn = []) {
+ const ignoreList = this.searchHelper.getIgnoreList();
+ const query = {
+ sort: sortedColumn,
+ query: {
+ bool: {
+ should: [
+ { term: { submitter: user.get('id') } },
+ { term: { preparers: user.get('id') } },
+ ],
+ must_not: [
+ { term: { submissionStatus: 'cancelled' } }
+ ]
+
+ },
+ },
+ size: 500
+ };
+ if (ignoreList && ignoreList.length > 0) {
+ query.query.bool.must_not.push({ terms: { '@id': ignoreList } });
+ }
+
+ console.log("tets")
+ return this.store.query('submission', query);
+ }
+
+ @action
+ async updateTable({sortedColumn, filteredColumn}) {
+ const user = get(this, 'currentUser.user');
+
+ //Method 1 of updating model
+ //Update fields then call model()
+ this.sort = sortedColumn;
+ this.filter = filteredColumn;
+ this.model();
+
+ /* Method 2 of updating model
+ let submissions = null;
+
+ if (user.get('isAdmin')) {
+ submissions = this._doAdmin(sortedColumn, filteredColumn);
+ } else if (user.get('isSubmitter')) {
+ submissions = this._doSubmitter(user, sortedColumn, filteredColumn);
+ }
+
+ submissions.then(() => this.searchHelper.clearIgnore());
+
+ return RSVP.hash({
+ submissions
+ });
+ */
+ }
+}
diff --git a/app/styles/app.scss b/app/styles/app.scss
index e533d7cf5..22b501913 100644
--- a/app/styles/app.scss
+++ b/app/styles/app.scss
@@ -428,6 +428,8 @@ table td {
.msid-column { min-width: 10rem; }
.actions-column { min-width: 8rem; }
.awardnum-column { min-width: 8rem; }
+.name-column{ min-width: 8rem;}
+.email-column{ min-width: 8rem;}
.awardnum-funder-column {
min-width: 9.5rem;
}
diff --git a/app/templates/administrator.hbs b/app/templates/administrator.hbs
new file mode 100644
index 000000000..e2147cab0
--- /dev/null
+++ b/app/templates/administrator.hbs
@@ -0,0 +1 @@
+{{outlet}}
\ No newline at end of file
diff --git a/app/templates/administrator/detail.hbs b/app/templates/administrator/detail.hbs
new file mode 100644
index 000000000..736c00848
--- /dev/null
+++ b/app/templates/administrator/detail.hbs
@@ -0,0 +1,241 @@
+DOI: {{#if this.model.sub.publication.doi}}{{this.model.sub.publication.doi}}{{else}}None{{/if}}
+| Submission status | +
+ |
+ ||||||||
| + |
+
+ This submission was marked as pertaining to COVID-19 research
+ (What does this mean?)
+
+ |
+ ||||||||
| Grants | +
+
+ {{/if}} + {{/each}} + |
+ ||||||||
| Repositories | +
+
|
+ ||||||||
| External Submission Repositories | +
+
|
+ ||||||||
| Submitter | ++ {{#if (eq this.model.sub.source "other")}} + This submission did not originate from PASS + {{else if this.displaySubmitterName}} + {{this.displaySubmitterName}} + {{/if}} + {{#if this.displaySubmitterEmail}} + ({{this.displaySubmitterEmail}}) + {{/if}} + | +||||||||
| Preparer(s) | ++ {{#each (await this.model.sub.preparers) as |preparer index|}} + {{#if index}}, {{/if}} {{get (await preparer) 'displayName'}} + {{#if (get (await preparer) 'email')}} + ({{get (await preparer) 'email'}}) + {{/if}} + {{/each}} + | +||||||||
|
+ External Submission Required
+ + {{#if this.disableSubmit}} + + {{/if}} + |
+
+
+
|
+ ||||||||
| Details | +
+ |
+ ||||||||
| Files | +
+ {{#if (eq this.model.sub.source "other")}}
+ + We do not have a copy of manuscript files because this submission did not originate from PASS + + {{else}} +
|
+ ||||||||
| Comments | +
+ |
+
+ This list contains all Submissions uploaded in pass. Please see our + FAQ page +
+