diff --git a/public/globals.js b/public/globals.js
index f6c3ec363..91d1cf456 100644
--- a/public/globals.js
+++ b/public/globals.js
@@ -1014,6 +1014,14 @@ window.pkp = {
"Once the user is enabled, they will regain access to OJS, and you'll be able to invite them to roles as needed.",
'grid.user.grid.user.disableReasonDescription':
"Please note that once a user is disabled, you won't be able to add them to any roles until they are enabled again.",
+ 'reviewerInvitation.responseDueDate':'Review Response Date',
+ 'reviewerInvitation.reviewDueDate':'Review Response Due Date',
+ 'reviewerInvitation.reviewTypes':'Review Types',
+ 'reviewerInvitation.modal.message':'{$email} has been invited to review the submission "{$articleTitle}"
You can be updated about the user\'s descision on the reviewer panel in the review workflow or through email and OJS notifications',
+ 'reviewerInvitation.modal.button':'View submission',
+ 'reviewerInvitation.reviewTypes.anonymusAuthorOrReviewer':'Anonymus Reviewer / Anonymus Author',
+ 'reviewerInvitation.reviewTypes.disclosedAuthor':'Anonymus Reviewer / Disclosed Author',
+ 'reviewerInvitation.reviewTypes.open':'Open'
},
tinyMCE: {
skinUrl: '/styles/tinymce',
diff --git a/src/components/ListPanel/users/SelectReviewerListItem.vue b/src/components/ListPanel/users/SelectReviewerListItem.vue
index 65e2b1fec..f729a7cdf 100644
--- a/src/components/ListPanel/users/SelectReviewerListItem.vue
+++ b/src/components/ListPanel/users/SelectReviewerListItem.vue
@@ -244,6 +244,8 @@ import ListItem from '@/components/List/ListItem.vue';
import Badge from '@/components/Badge/Badge.vue';
import PkpButton from '@/components/Button/Button.vue';
import Icon from '@/components/Icon/Icon.vue';
+import {useWorkflowStore} from '@/pages/workflow/workflowStore';
+import {useUrl} from '@/composables/useUrl';
export default {
components: {
@@ -482,8 +484,16 @@ export default {
* @param
*/
select() {
- this.$emit('select', this.item);
- pkp.eventBus.$emit('selected:reviewer', this.item);
+ const workflow = useWorkflowStore();
+ const {redirectToPage: redirectToReviewerInvitationPage} = useUrl(
+ 'invitation/create/reviewerAccess',
+ {
+ userId: this.item.id,
+ submissionId: workflow.submission.id,
+ reviewRoundId: workflow.selectedMenuState.reviewRoundId,
+ },
+ );
+ redirectToReviewerInvitationPage();
},
/**
diff --git a/src/pages/userInvitation/ReviewerReviewDetailsStep.vue b/src/pages/userInvitation/ReviewerReviewDetailsStep.vue
new file mode 100644
index 000000000..3064ec491
--- /dev/null
+++ b/src/pages/userInvitation/ReviewerReviewDetailsStep.vue
@@ -0,0 +1,84 @@
+
+
+ updateReviewDetails(index, fieldName, newValue)
+ "
+ />
+
+
+ updateReviewDetails(index, fieldName, newValue)
+ "
+ />
+
+ updateReviewDetails(index, fieldName, newValue)
+ "
+ />
+
+
+
diff --git a/src/pages/userInvitation/UserInvitationPage.stories.js b/src/pages/userInvitation/UserInvitationPage.stories.js
index 4e0d28edd..fc0ed96d8 100644
--- a/src/pages/userInvitation/UserInvitationPage.stories.js
+++ b/src/pages/userInvitation/UserInvitationPage.stories.js
@@ -2,6 +2,7 @@ import UserInvitationPage from './UserInvitationPage.vue';
import {http, HttpResponse} from 'msw';
import userMock from './mocks/userMock.js';
import PageInitConfigMock from './mocks/pageInitConfig';
+import ReviewerPageInitConfigMock from './mocks/reviewerPageInitConfig';
export default {title: 'Pages/UserInvitation', component: UserInvitationPage};
@@ -118,3 +119,100 @@ export const Init = {
},
args: PageInitConfigMock,
};
+
+export const Reviewer = {
+ render: (args) => ({
+ components: {UserInvitationPage},
+ setup() {
+ return {args};
+ },
+ template: '',
+ }),
+ parameters: {
+ msw: {
+ handlers: [
+ http.post(
+ 'https://mock/index.php/publicknowledge/api/v1/invitations/add/reviewerAccessInvite',
+ () => {
+ return HttpResponse.json({invitationId: 15});
+ },
+ ),
+ http.post(
+ 'https://mock/index.php/publicknowledge/api/v1/invitations/15/populate',
+ async ({request}) => {
+ const data = await request.json();
+ let errors = {};
+ console.log(data.invitationData);
+
+ data.invitationData.userGroupsToAdd.forEach((element, index) => {
+ Object.keys(element).forEach((key) => {
+ if (element[key] === null) {
+ errors = {
+ ...errors,
+ ['userGroupsToAdd.' + index + '.' + key]: [
+ 'This field is required',
+ ],
+ };
+ }
+ });
+ });
+
+ if (data.invitationData.email === '') {
+ errors['email'] = ['This field is required'];
+ }
+ if (data.invitationData.familyName === '') {
+ errors['familyName'] = ['This field is required'];
+ }
+ if (data.invitationData.givenName === '') {
+ errors['givenName'] = ['This field is required'];
+ }
+
+ if (data.invitationData.responseDueDate === '') {
+ errors['responseDueDate'] = ['This field is required'];
+ }
+
+ if (data.invitationData.reviewDueDate === '') {
+ errors['reviewDueDate'] = ['This field is required'];
+ }
+
+ if (data.invitationData.reviewTypes === '') {
+ errors['reviewTypes'] = ['This field is required'];
+ }
+
+ if (data.invitationData.emailComposer) {
+ Object.keys(data.invitationData.emailComposer).forEach(
+ (element) => {
+ if (data.invitationData.emailComposer[element] === '') {
+ errors['emailComposer'] = {
+ ...errors['emailComposer'],
+ [element]: ['This field is required'],
+ };
+ }
+ },
+ );
+ }
+
+ if (Object.keys(errors).length > 0) {
+ return HttpResponse.json({errors: errors}, {status: 422});
+ }
+
+ return HttpResponse.json({status: 201});
+ },
+ ),
+ http.post(
+ 'https://mock/index.php/publicknowledge/api/v1/invitations/15/invite',
+ () => {
+ return HttpResponse.json({});
+ },
+ ),
+ http.post(
+ 'https://mock/index.php/publicknowledge/api/v1/user/_invite',
+ () => {
+ return HttpResponse.json('invitation send successfully');
+ },
+ ),
+ ],
+ },
+ },
+ args: ReviewerPageInitConfigMock,
+};
diff --git a/src/pages/userInvitation/UserInvitationPage.vue b/src/pages/userInvitation/UserInvitationPage.vue
index 1dbdbdebc..1971d126f 100644
--- a/src/pages/userInvitation/UserInvitationPage.vue
+++ b/src/pages/userInvitation/UserInvitationPage.vue
@@ -91,6 +91,7 @@ import UserInvitationHeader from './UserInvitationHeader.vue';
import UserInvitationDetailsFormStep from './UserInvitationDetailsFormStep.vue';
import UserInvitationSearchFormStep from './UserInvitationSearchFormStep.vue';
import UserInvitationEmailComposerStep from './UserInvitationEmailComposerStep.vue';
+import ReviewerReviewDetailsStep from './ReviewerReviewDetailsStep.vue';
const props = defineProps({
/** steps for invite user */
@@ -140,5 +141,7 @@ const userInvitationComponents = {
UserInvitationDetailsFormStep,
UserInvitationSearchFormStep,
UserInvitationEmailComposerStep,
+ ReviewerReviewDetailsStep,
};
+console.log(props);
diff --git a/src/pages/userInvitation/UserInvitationPageStore.js b/src/pages/userInvitation/UserInvitationPageStore.js
index 4cd79e6fe..e55649880 100644
--- a/src/pages/userInvitation/UserInvitationPageStore.js
+++ b/src/pages/userInvitation/UserInvitationPageStore.js
@@ -7,6 +7,8 @@ import {useModal} from '@/composables/useModal';
export const useUserInvitationPageStore = defineComponentStore(
'userInvitationPage',
(pageInitConfig) => {
+ const invitationUserRoleAssignment = 'userRoleAssignment';
+ const invitationReviewerAccessInvite = 'reviewerAccess';
const {openDialog} = useModal();
const {t} = useLocalize();
/**
@@ -26,6 +28,13 @@ export const useUserInvitationPageStore = defineComponentStore(
const invitationUserData = ref(pageInitConfig.invitationUserData);
const detectChanges = ref(false);
+ invitationPayload.value.submissionId &&
+ (updatedPayload.value['submissionId'] =
+ invitationPayload.value.submissionId);
+ invitationPayload.value.reviewRoundId &&
+ (updatedPayload.value['reviewRoundId'] =
+ invitationPayload.value.reviewRoundId);
+
function updatePayload(fieldName, value, initialValue = true) {
invitationPayload.value[fieldName] = value;
if (!initialValue) {
@@ -76,6 +85,14 @@ export const useUserInvitationPageStore = defineComponentStore(
return currentStepIndex.value === steps.value.length - 1;
});
+ const isUserRoleAssignment = computed(() => {
+ return invitationType.value === invitationUserRoleAssignment;
+ });
+
+ const isReviewerAccess = computed(() => {
+ return invitationType.value === invitationReviewerAccessInvite;
+ });
+
/**
* Add a step change to the browser history so the
* user can use the browser's back button
@@ -317,7 +334,7 @@ export const useUserInvitationPageStore = defineComponentStore(
async (newVal, oldVal) => {
isSubmitting.value = invitationPayload.value.disabled;
if (invitationPayload.value.userGroupsToAdd.length === 0) {
- isSubmitting.value = true;
+ // isSubmitting.value = true;
}
detectChanges.value = true;
},
@@ -339,12 +356,21 @@ export const useUserInvitationPageStore = defineComponentStore(
if (data.value) {
openDialog({
title: t('userInvitation.modal.title'),
- message: t('userInvitation.modal.message', {
- email: invitationPayload.value.inviteeEmail,
- }),
+ message:
+ invitationType.value === invitationUserRoleAssignment
+ ? t('userInvitation.modal.message', {
+ email: invitationPayload.value.inviteeEmail,
+ })
+ : t('reviewerInvitation.modal.message', {
+ email: invitationPayload.value.inviteeEmail,
+ articleTitle: '',
+ }),
actions: [
{
- label: t('userInvitation.modal.button'),
+ label:
+ invitationType.value === invitationUserRoleAssignment
+ ? t('userInvitation.modal.button')
+ : t('reviewerInvitation.modal.button'),
callback: (close) => {
redirectToPage();
},
@@ -413,6 +439,8 @@ export const useUserInvitationPageStore = defineComponentStore(
registerActionForStepId,
emailTemplatesApiUrl,
invitationUserData,
+ isUserRoleAssignment,
+ isReviewerAccess,
currentStep,
currentStepIndex,
diff --git a/src/pages/userInvitation/UserInvitationUserGroupsTable.vue b/src/pages/userInvitation/UserInvitationUserGroupsTable.vue
index f9fb380ed..80163785b 100644
--- a/src/pages/userInvitation/UserInvitationUserGroupsTable.vue
+++ b/src/pages/userInvitation/UserInvitationUserGroupsTable.vue
@@ -58,7 +58,16 @@
-
+
-
+
+ reviewerUserGroupIds.value.includes(group.id),
+ ) &&
+ store.isReviewerAccess
+) {
+ store.updatePayload('userGroupsToAdd', [], false);
+}
diff --git a/src/pages/userInvitation/mocks/reviewerPageInitConfig.js b/src/pages/userInvitation/mocks/reviewerPageInitConfig.js
new file mode 100644
index 000000000..af0baa5f7
--- /dev/null
+++ b/src/pages/userInvitation/mocks/reviewerPageInitConfig.js
@@ -0,0 +1,640 @@
+import InsertContentMock from '@/mocks/insertContent';
+import emailTemplate from '@/mocks/emailTemplate';
+
+const recipientOptions = [
+ {
+ value: 2,
+ label: {
+ en: 'Carlo Corino',
+ fr_CA: 'Carlo Fr Corino',
+ },
+ },
+ {
+ value: 3,
+ label: {
+ en: 'Daniel Barnes',
+ fr_CA: 'Daniel Fr Barnes',
+ },
+ },
+ {
+ value: 4,
+ label: {
+ en: 'Stephanie Minoue',
+ fr_CA: 'Stephanie Fr Minoue',
+ },
+ },
+ {
+ value: 5,
+ label: {
+ en: 'Paul Hudson',
+ fr_CA: 'Paul Fr Hudson',
+ },
+ },
+];
+
+export default {
+ emailTemplatesApiUrl:
+ 'https://mock/index.php/publicknowledge/api/v1/EmailTemplateMocks',
+ pageTitle: 'Invite user to take a role',
+ pageTitleDescription:
+ 'You are inviting a user to take a role in OJS along with appearing in the journal masthead',
+ primaryLocale: 'en',
+ invitationType: 'reviewerAccess',
+ invitationMode: 'create',
+ invitationPayload: {
+ userId: null,
+ email: '',
+ orcid: '',
+ givenName: '',
+ familyName: '',
+ orcidValidation: false,
+ submissionId: 10,
+ reviewRoundId: 1,
+ responseDueDate: '',
+ reviewDueDate: '',
+ reviewTypes: '',
+ userGroupsToAdd: [{userGroupId: 16, dateStart: null, masthead: null}],
+ currentUserGroups: [],
+ userGroupsToRemove: [],
+ emailComposer: {
+ body: '',
+ subject: '',
+ },
+ },
+ steps: [
+ {
+ id: 'userDetails',
+ name: 'Enter details',
+ stepLabel: '{$step} - Enter details and invite for roles',
+ type: 'form',
+ description: 'You can invite them to take up a role in OJS',
+ nextButtonLabel: 'Save And Continue (t)',
+ skipInvitationUpdate: false,
+ sections: [
+ {
+ id: 'userDetailsForm',
+ type: 'form',
+ description:
+ 'Please provide the following details to help us manage your submission in our system.
',
+ sectionComponent: 'UserInvitationDetailsFormStep',
+ props: {
+ userGroups: [
+ {
+ userGroupId: 2,
+ contextId: 1,
+ roleId: 16,
+ isDefault: true,
+ showTitle: true,
+ permitSelfRegistration: false,
+ permitMetadataEdit: true,
+ permitSettings: true,
+ masthead: false,
+ nameLocaleKey: 'default.groups.name.manager',
+ abbrevLocaleKey: 'default.groups.abbrev.manager',
+ name: {
+ en: 'Journal manager',
+ fr_CA: 'Directeur-trice de la revue',
+ },
+ abbrev: {
+ en: 'JM',
+ fr_CA: 'DIR',
+ },
+ },
+ {
+ userGroupId: 3,
+ contextId: 1,
+ roleId: 16,
+ isDefault: true,
+ showTitle: true,
+ permitSelfRegistration: false,
+ permitMetadataEdit: true,
+ permitSettings: true,
+ masthead: true,
+ nameLocaleKey: 'default.groups.name.editor',
+ abbrevLocaleKey: 'default.groups.abbrev.editor',
+ name: {
+ en: 'Journal editor',
+ fr_CA: 'Rédacteur-trice',
+ },
+ abbrev: {
+ en: 'JE',
+ fr_CA: 'RÉD',
+ },
+ },
+ {
+ userGroupId: 4,
+ contextId: 1,
+ roleId: 16,
+ isDefault: true,
+ showTitle: true,
+ permitSelfRegistration: false,
+ permitMetadataEdit: true,
+ permitSettings: true,
+ masthead: false,
+ nameLocaleKey: 'default.groups.name.productionEditor',
+ abbrevLocaleKey: 'default.groups.abbrev.productionEditor',
+ name: {
+ en: 'Production editor',
+ fr_CA: 'Directeur-trice de production',
+ },
+ abbrev: {
+ en: 'ProdE',
+ fr_CA: 'DirProd',
+ },
+ },
+ {
+ userGroupId: 5,
+ contextId: 1,
+ roleId: 17,
+ isDefault: true,
+ showTitle: true,
+ permitSelfRegistration: false,
+ permitMetadataEdit: true,
+ permitSettings: false,
+ masthead: true,
+ nameLocaleKey: 'default.groups.name.sectionEditor',
+ abbrevLocaleKey: 'default.groups.abbrev.sectionEditor',
+ name: {
+ en: 'Section editor',
+ fr_CA: 'Rédacteur-trice de rubrique',
+ },
+ abbrev: {
+ en: 'SecE',
+ fr_CA: 'RÉDRUB',
+ },
+ },
+ {
+ userGroupId: 6,
+ contextId: 1,
+ roleId: 17,
+ isDefault: true,
+ showTitle: true,
+ permitSelfRegistration: false,
+ permitMetadataEdit: false,
+ permitSettings: false,
+ masthead: false,
+ nameLocaleKey: 'default.groups.name.guestEditor',
+ abbrevLocaleKey: 'default.groups.abbrev.guestEditor',
+ name: {
+ en: 'Guest editor',
+ fr_CA: 'Rédacteur-trice invité-e',
+ },
+ abbrev: {
+ en: 'GE',
+ fr_CA: 'RÉDINV',
+ },
+ },
+ {
+ userGroupId: 7,
+ contextId: 1,
+ roleId: 4097,
+ isDefault: true,
+ showTitle: true,
+ permitSelfRegistration: false,
+ permitMetadataEdit: false,
+ permitSettings: false,
+ masthead: false,
+ nameLocaleKey: 'default.groups.name.copyeditor',
+ abbrevLocaleKey: 'default.groups.abbrev.copyeditor',
+ name: {
+ en: 'Copyeditor',
+ fr_CA: 'Réviseur-e',
+ },
+ abbrev: {
+ en: 'CE',
+ fr_CA: 'RÉV',
+ },
+ },
+ {
+ userGroupId: 8,
+ contextId: 1,
+ roleId: 4097,
+ isDefault: true,
+ showTitle: true,
+ permitSelfRegistration: false,
+ permitMetadataEdit: false,
+ permitSettings: false,
+ masthead: false,
+ nameLocaleKey: 'default.groups.name.designer',
+ abbrevLocaleKey: 'default.groups.abbrev.designer',
+ name: {
+ en: 'Designer',
+ fr_CA: 'Designer',
+ },
+ abbrev: {
+ en: 'Design',
+ fr_CA: 'Design',
+ },
+ },
+ {
+ userGroupId: 9,
+ contextId: 1,
+ roleId: 4097,
+ isDefault: true,
+ showTitle: true,
+ permitSelfRegistration: false,
+ permitMetadataEdit: false,
+ permitSettings: false,
+ masthead: false,
+ nameLocaleKey: 'default.groups.name.funding',
+ abbrevLocaleKey: 'default.groups.abbrev.funding',
+ name: {
+ en: 'Funding coordinator',
+ fr_CA: 'Coordonnateur-trice du financement',
+ },
+ abbrev: {
+ en: 'FC',
+ fr_CA: 'CF',
+ },
+ },
+ {
+ userGroupId: 10,
+ contextId: 1,
+ roleId: 4097,
+ isDefault: true,
+ showTitle: true,
+ permitSelfRegistration: false,
+ permitMetadataEdit: false,
+ permitSettings: false,
+ masthead: false,
+ nameLocaleKey: 'default.groups.name.indexer',
+ abbrevLocaleKey: 'default.groups.abbrev.indexer',
+ name: {
+ en: 'Indexer',
+ fr_CA: 'Indexeur-e',
+ },
+ abbrev: {
+ en: 'IND',
+ fr_CA: 'Indx',
+ },
+ },
+ {
+ userGroupId: 11,
+ contextId: 1,
+ roleId: 4097,
+ isDefault: true,
+ showTitle: true,
+ permitSelfRegistration: false,
+ permitMetadataEdit: false,
+ permitSettings: false,
+ masthead: false,
+ nameLocaleKey: 'default.groups.name.layoutEditor',
+ abbrevLocaleKey: 'default.groups.abbrev.layoutEditor',
+ name: {
+ en: 'Layout Editor',
+ fr_CA: 'Responsable de la mise en page',
+ },
+ abbrev: {
+ en: 'LE',
+ fr_CA: 'RespMP',
+ },
+ },
+ {
+ userGroupId: 12,
+ contextId: 1,
+ roleId: 4097,
+ isDefault: true,
+ showTitle: true,
+ permitSelfRegistration: false,
+ permitMetadataEdit: false,
+ permitSettings: false,
+ masthead: false,
+ nameLocaleKey: 'default.groups.name.marketing',
+ abbrevLocaleKey: 'default.groups.abbrev.marketing',
+ name: {
+ en: 'Marketing and sales coordinator',
+ fr_CA: 'Coordonnateur-trice des ventes et du marketing',
+ },
+ abbrev: {
+ en: 'MS',
+ fr_CA: 'CVM',
+ },
+ },
+ {
+ userGroupId: 13,
+ contextId: 1,
+ roleId: 4097,
+ isDefault: true,
+ showTitle: true,
+ permitSelfRegistration: false,
+ permitMetadataEdit: false,
+ permitSettings: false,
+ masthead: false,
+ nameLocaleKey: 'default.groups.name.proofreader',
+ abbrevLocaleKey: 'default.groups.abbrev.proofreader',
+ name: {
+ en: 'Proofreader',
+ fr_CA: "Correcteur-trice d'épreuves",
+ },
+ abbrev: {
+ en: 'PR',
+ fr_CA: 'CorEp',
+ },
+ },
+ {
+ userGroupId: 14,
+ contextId: 1,
+ roleId: 65536,
+ isDefault: true,
+ showTitle: true,
+ permitSelfRegistration: true,
+ permitMetadataEdit: false,
+ permitSettings: false,
+ masthead: false,
+ nameLocaleKey: 'default.groups.name.author',
+ abbrevLocaleKey: 'default.groups.abbrev.author',
+ name: {
+ en: 'Author',
+ fr_CA: 'Auteur-e',
+ },
+ abbrev: {
+ en: 'AU',
+ fr_CA: 'AU',
+ },
+ },
+ {
+ userGroupId: 15,
+ contextId: 1,
+ roleId: 65536,
+ isDefault: true,
+ showTitle: true,
+ permitSelfRegistration: false,
+ permitMetadataEdit: false,
+ permitSettings: false,
+ masthead: false,
+ nameLocaleKey: 'default.groups.name.translator',
+ abbrevLocaleKey: 'default.groups.abbrev.translator',
+ name: {
+ en: 'Translator',
+ fr_CA: 'Traducteur-trice',
+ },
+ abbrev: {
+ en: 'Trans',
+ fr_CA: 'Trad',
+ },
+ },
+ {
+ userGroupId: 16,
+ contextId: 1,
+ roleId: 4096,
+ isDefault: true,
+ showTitle: true,
+ permitSelfRegistration: true,
+ permitMetadataEdit: false,
+ permitSettings: false,
+ masthead: true,
+ nameLocaleKey: 'default.groups.name.externalReviewer',
+ abbrevLocaleKey: 'default.groups.abbrev.externalReviewer',
+ name: {
+ en: 'Reviewer',
+ fr_CA: 'Évaluateur-trice',
+ },
+ abbrev: {
+ en: 'R',
+ fr_CA: 'ÉVAL',
+ },
+ },
+ {
+ userGroupId: 17,
+ contextId: 1,
+ roleId: 1048576,
+ isDefault: true,
+ showTitle: true,
+ permitSelfRegistration: true,
+ permitMetadataEdit: false,
+ permitSettings: false,
+ masthead: false,
+ nameLocaleKey: 'default.groups.name.reader',
+ abbrevLocaleKey: 'default.groups.abbrev.reader',
+ name: {
+ en: 'Reader',
+ fr_CA: 'Lecteur-trice',
+ },
+ abbrev: {
+ en: 'Read',
+ fr_CA: 'Lect',
+ },
+ },
+ {
+ userGroupId: 18,
+ contextId: 1,
+ roleId: 2097152,
+ isDefault: true,
+ showTitle: true,
+ permitSelfRegistration: false,
+ permitMetadataEdit: false,
+ permitSettings: false,
+ masthead: false,
+ nameLocaleKey: 'default.groups.name.subscriptionManager',
+ abbrevLocaleKey: 'default.groups.abbrev.subscriptionManager',
+ name: {
+ en: 'Subscription Manager',
+ fr_CA: 'Responsable des abonnements',
+ },
+ abbrev: {
+ en: 'SubM',
+ fr_CA: 'RespAB',
+ },
+ },
+ {
+ userGroupId: 19,
+ contextId: 1,
+ roleId: 4097,
+ isDefault: true,
+ showTitle: true,
+ permitSelfRegistration: false,
+ permitMetadataEdit: false,
+ permitSettings: false,
+ masthead: true,
+ nameLocaleKey: 'default.groups.name.editorialBoardMember',
+ abbrevLocaleKey: 'default.groups.abbrev.editorialBoardMember',
+ name: {
+ en: 'Editorial Board Member',
+ },
+ abbrev: {
+ en: 'EBM',
+ },
+ },
+ ],
+ form: {
+ id: 'userDetails',
+ method: 'POST',
+ action:
+ 'http://localhost/ojs/index.php/publicknowledge/api/v1/users',
+ fields: [
+ {
+ name: 'email',
+ component: 'field-text',
+ label: 'Email address',
+ groupId: 'default',
+ isRequired: true,
+ isMultilingual: false,
+ description: 'e.g. aeinstein@example.com',
+ value: 'null',
+ inputType: 'text',
+ optIntoEdit: false,
+ optIntoEditLabel: '',
+ size: 'large',
+ prefix: '',
+ },
+ {
+ component: 'field-html',
+ description:
+ 'On accepting the invite, the user will be redirected to ORCID to verify their account, if they wish to.',
+ groupId: 'default',
+ isInert: true,
+ isMultilingual: false,
+ isRequired: false,
+ label: 'ORCID iD',
+ name: 'orcid',
+ value: null,
+ },
+ {
+ name: 'givenName',
+ component: 'field-text',
+ label: 'Given Name',
+ groupId: 'default',
+ isRequired: false,
+ isMultilingual: true,
+ description:
+ 'If you know the given name of the user, you can enter the information. However, this information can be changed by the user',
+ value: {
+ en: '',
+ fr_CA: '',
+ },
+ inputType: 'text',
+ optIntoEdit: false,
+ optIntoEditLabel: '',
+ size: 'large',
+ prefix: '',
+ },
+ {
+ name: 'familyName',
+ component: 'field-text',
+ label: 'Family Name',
+ groupId: 'default',
+ isRequired: false,
+ isMultilingual: true,
+ description:
+ 'If you know the family name of the user, you can enter the information. However, this information can be changed by the user',
+ value: {
+ en: '',
+ fr_CA: '',
+ },
+ inputType: 'text',
+ optIntoEdit: false,
+ optIntoEditLabel: '',
+ size: 'large',
+ prefix: '',
+ },
+ ],
+ groups: [
+ {
+ id: 'default',
+ pageId: 'default',
+ },
+ ],
+ hiddenFields: {},
+ pages: [{id: 'default', submitButton: null}],
+ primaryLocale: 'en',
+ visibleLocales: ['en'],
+ supportedFormLocales: [
+ {
+ key: 'en',
+ label: 'English',
+ },
+ {
+ key: 'fr_CA',
+ label: 'French',
+ },
+ ],
+ errors: {},
+ },
+ validateFields: [
+ 'email',
+ 'givenName',
+ 'familyName',
+ 'userGroupsToAdd',
+ ],
+ },
+ },
+ ],
+ },
+ {
+ id: 'reviewerReviewDetails',
+ name: 'Review Details',
+ stepLabel: '{$step} - Enter Review Details',
+ description: 'You can add review related details',
+ nextButtonLabel: 'Invite user to the role (t)',
+ skipInvitationUpdate: false,
+ sections: [
+ {
+ id: 'reviewDetails',
+ description:
+ 'Please provide the following details to help us manage your submission in our system.
',
+ sectionComponent: 'ReviewerReviewDetailsStep',
+ props: {
+ validateFields: ['responseDueDate', 'reviewTypes', 'reviewDueDate'],
+ },
+ },
+ ],
+ },
+ {
+ id: 'userInvitedEmail',
+ name: 'Review & invite for roles',
+ stepLabel: '{$step} - Modify email shared with the user',
+ type: 'email',
+ description:
+ 'Send the user an email to let them know about the invitation, next steps, journal GDPR polices and ORCiD verification',
+ nextButtonLabel: 'Invite user to the role (t)',
+ sections: [
+ {
+ id: 'userInvited',
+ type: 'email',
+ description:
+ 'Please provide the following details to help us manage your submission in our system.
',
+ sectionComponent: 'UserInvitationEmailComposerStep',
+ props: {
+ email: {
+ id: 'userInvited',
+ type: 'email',
+ name: 'Invite Users',
+ attachers: [],
+ canChangeRecipients: false,
+ canSkip: true,
+ description:
+ 'Send an email to the authors to let them know that this submission will be sent for peer review. If possible, give the authors some indication of how long the peer review process might take and when they should expect to hear from the editors again. This email will not be sent until the decision is recorded.',
+ errors: {},
+ initialTemplateKey: 'EDITOR_DECISION_ACCEPT',
+ anonymousRecipients: false,
+ locale: 'en',
+ body: "{$recipientName}
\\n\n
\\n\nYou have now been registered as a user with Journal of Public Knowledge. We have included your username and password in this email, which are needed for all work with this journal through its website. At any point, you can ask to be removed from the journal's list of users by contacting me.
\\n\n
\\n\naccept url: {$acceptUrl}
\\n\ndecline url: {$declineUrl}
\\n\n
\\n\nThank you,
\\n\nadmin admin
\n",
+ subject: 'User invited',
+ emailTemplates: [emailTemplate],
+ emailTemplatesApiUrl:
+ 'https://httbin.org/publicknowledge/api/v1/emailTemplates',
+ locales: [
+ {
+ locale: 'en',
+ name: 'English',
+ },
+ {
+ locale: 'fr_CA',
+ name: 'French',
+ },
+ ],
+ to: [2, 3],
+ recipientOptions: recipientOptions,
+ recipients: recipientOptions.map((r) => r.value),
+ variables: {
+ en: [...InsertContentMock],
+ fr_CA: [...InsertContentMock],
+ },
+ },
+ validateFields: ['emailComposer'],
+ },
+ },
+ ],
+ },
+ ],
+};