diff --git a/src/components/Modal/ModalManager.vue b/src/components/Modal/ModalManager.vue
index 0b6e88c20..d6efce49e 100644
--- a/src/components/Modal/ModalManager.vue
+++ b/src/components/Modal/ModalManager.vue
@@ -70,8 +70,9 @@ import {storeToRefs} from 'pinia';
import SideModal from '@/components/Modal/SideModal.vue';
import LegacyAjax from '@/components/Modal/SideModalBodyLegacyAjax.vue';
import PkpDialog from '@/components/Modal/Dialog.vue';
+import WorkflowLogResponseModal from '@/managers/ReviewerManager/modals/WorkflowLogResponseModal.vue';
-const GlobalModals = {LegacyAjax};
+const GlobalModals = {LegacyAjax, WorkflowLogResponseModal};
const modalStore = useModalStore();
const {
diff --git a/src/managers/ReviewerManager/modals/WorkflowLogResponseModal.mdx b/src/managers/ReviewerManager/modals/WorkflowLogResponseModal.mdx
new file mode 100644
index 000000000..a37fa3842
--- /dev/null
+++ b/src/managers/ReviewerManager/modals/WorkflowLogResponseModal.mdx
@@ -0,0 +1,11 @@
+import {Meta, ArgTypes} from '@storybook/blocks';
+
+import * as WorkflowLogResponseModalStories from './WorkflowLogResponseModal.stories';
+
+
+
+# Log Response Modal
+
+A vue modal containing a form for and admin to log a response to a review request on behalf of the reviewer.
+
+
diff --git a/src/managers/ReviewerManager/modals/WorkflowLogResponseModal.stories.js b/src/managers/ReviewerManager/modals/WorkflowLogResponseModal.stories.js
new file mode 100644
index 000000000..f1651251a
--- /dev/null
+++ b/src/managers/ReviewerManager/modals/WorkflowLogResponseModal.stories.js
@@ -0,0 +1,77 @@
+import WorkflowLogResponseModal from './WorkflowLogResponseModal.vue';
+import PkpButton from '@/components/Button/Button.vue';
+import {useModal} from '@/composables/useModal';
+import {within, userEvent} from '@storybook/test';
+
+export default {
+ title: 'Pages/Workflow/LogResponse',
+ component: WorkflowLogResponseModal,
+};
+
+export const Base = {
+ render: (args) => ({
+ components: {WorkflowLogResponseModal, PkpButton},
+ setup() {
+ const {openSideModal} = useModal();
+
+ function logResponse() {
+ openSideModal(WorkflowLogResponseModal, args.modalProps);
+ }
+ return {logResponse, ...args};
+ },
+ template: 'Log Response',
+ }),
+ args: {
+ modalProps: {
+ description:
+ 'Sodium butyrate improves growth performance of weaned piglets during the first period after weaning',
+ submissionId: 12,
+ logResponseForm: {
+ id: 'logResponseForm',
+ method: 'POST',
+ action:
+ 'http://localhost:7003/index.php/publicknowledge/$$$call$$$/grid/users/reviewer/reviewer-grid/add-log?submissionId=12&reviewAssignmentId=17&stageId=3&round=0',
+ fields: [
+ {
+ name: 'acceptReview',
+ isRequired: true,
+ description:
+ 'If the reviewer contacts you through email or any other means, you can record their response for them',
+ component: 'field-options',
+ label: 'Record the response on behalf of the reviewer',
+ value: false,
+ type: 'radio',
+ options: [
+ {
+ value: 1,
+ label: 'Reviewer has accepted the invitation to review',
+ },
+ {
+ value: 0,
+ label: 'Reviewer has declined the invitation to review',
+ },
+ ],
+ groupId: 'default',
+ },
+ ],
+ groups: [{id: 'default', pageId: 'default'}],
+ pages: [{id: 'default', submitButton: {label: 'Log Response'}}],
+ primaryLocale: 'en',
+ visibleLocales: ['en'],
+ supportedFormLocales: ['en', 'fr_CA'],
+ },
+ },
+ },
+ play: async ({canvasElement}) => {
+ // Assigns canvas to the component root element
+ const canvas = within(canvasElement);
+ const user = userEvent.setup();
+
+ await user.click(canvas.getByText('Log Response'));
+ },
+ decorators: [
+ () => ({
+ template: '
',
+ }),
+ ],
+};
diff --git a/src/managers/ReviewerManager/modals/WorkflowLogResponseModal.vue b/src/managers/ReviewerManager/modals/WorkflowLogResponseModal.vue
new file mode 100644
index 000000000..f1ba431fa
--- /dev/null
+++ b/src/managers/ReviewerManager/modals/WorkflowLogResponseModal.vue
@@ -0,0 +1,35 @@
+
+
+
+ {{ submissionId }}
+
+
+ {{ t('editor.review.logResponse.for') }}
+
+
+ {{ title }}
+
+
+
+
+
+
diff --git a/src/managers/ReviewerManager/modals/workflowLogResponseModalStore.js b/src/managers/ReviewerManager/modals/workflowLogResponseModalStore.js
new file mode 100644
index 000000000..5ba8fcce9
--- /dev/null
+++ b/src/managers/ReviewerManager/modals/workflowLogResponseModalStore.js
@@ -0,0 +1,17 @@
+import {inject} from 'vue';
+import {defineComponentStore} from '@/utils/defineComponentStore';
+import {useForm} from '@/composables/useForm';
+
+export const useWorkflowLogResponseModalStore = defineComponentStore(
+ 'workflowLogResponseModal',
+ (props) => {
+ const closeModal = inject('closeModal');
+ const {set: updateForm, form} = useForm(props.logResponseForm);
+
+ function formSuccess() {
+ closeModal();
+ }
+
+ return {form, formSuccess, updateForm};
+ },
+);
diff --git a/src/managers/ReviewerManager/reviewerManagerStore.js b/src/managers/ReviewerManager/reviewerManagerStore.js
index 0a3bfa350..1e1e90339 100644
--- a/src/managers/ReviewerManager/reviewerManagerStore.js
+++ b/src/managers/ReviewerManager/reviewerManagerStore.js
@@ -157,6 +157,13 @@ export const useReviewerManagerStore = defineComponentStore(
);
}
+ function reviewerLogResponse({reviewAssignment}) {
+ _actionFns.reviewerLogResponse(
+ getActionArgs({reviewAssignment}),
+ dataUpdateCallback,
+ );
+ }
+
function getItemActions(args) {
return _actionFns.getItemActions(args);
}
@@ -190,6 +197,7 @@ export const useReviewerManagerStore = defineComponentStore(
reviewerThankReviewer,
reviewerRevertConsider,
reviewerSendReminder,
+ reviewerLogResponse,
_reviewerManagerActionFns: _actionFns,
};
},
diff --git a/src/managers/ReviewerManager/useReviewerManagerActions.js b/src/managers/ReviewerManager/useReviewerManagerActions.js
index cc454e2df..add0eab3c 100644
--- a/src/managers/ReviewerManager/useReviewerManagerActions.js
+++ b/src/managers/ReviewerManager/useReviewerManagerActions.js
@@ -4,6 +4,9 @@ import {useModal} from '@/composables/useModal';
import {useLocalize} from '@/composables/useLocalize';
import {useSubmission} from '@/composables/useSubmission';
import {useFetch, getCSRFToken} from '@/composables/useFetch';
+import WorkflowLogResponseModal from '@/managers/ReviewerManager/modals/WorkflowLogResponseModal.vue';
+import {useDashboardPageStore} from '@/pages/dashboard/dashboardPageStore';
+import {useApiUrl} from '@/composables/useApiUrl';
export const Actions = {
REVIEWER_ADD_REVIEWER: 'reviewerAddReviewer',
@@ -22,6 +25,7 @@ export const Actions = {
REVIEWER_THANK_REVIEWER: 'reviewerThankReviewer',
REVIEWER_REVERT_CONSIDER: 'reviewerRevertConsider',
REVIEWER_SEND_REMINDER: 'reviewerSendReminder',
+ REVIEWER_LOG_RESPONSE: 'reviewerLogResponse',
};
export function useReviewerManagerActions() {
@@ -186,6 +190,14 @@ export function useReviewerManagerActions() {
icon: 'DefaultDocument',
});
+ if (!reviewAssignment.dateConfirmed) {
+ actions.push({
+ label: t('editor.review.logResponse'),
+ name: Actions.REVIEWER_LOG_RESPONSE,
+ icon: 'ReviewAssignments',
+ });
+ }
+
return actions;
}
@@ -564,6 +576,37 @@ export function useReviewerManagerActions() {
openLegacyModal({title: t('editor.review.reminder')}, finishedCallback);
}
+ function reviewerLogResponse(
+ {submission, reviewAssignment, submissionStageId},
+ finishedCallback,
+ ) {
+ const {openSideModal} = useModal();
+
+ const dashboardStore = useDashboardPageStore();
+ let form = dashboardStore.componentForms.logResponseForm;
+ let submissionId = submission.id;
+
+ const {getCurrentPublication} = useSubmission();
+ const currentPublication = getCurrentPublication(submission);
+ const title = `${localizeSubmission(currentPublication.fullTitle, currentPublication.locale)}`;
+
+ const {apiUrl} = useApiUrl(
+ `reviews/${submissionId}/${reviewAssignment.id}/confirmReview`,
+ );
+
+ form.action = apiUrl;
+
+ openSideModal(
+ WorkflowLogResponseModal,
+ {
+ title: title,
+ submissionId: submissionId,
+ logResponseForm: dashboardStore.componentForms.logResponseForm,
+ },
+ {onClose: finishedCallback},
+ );
+ }
+
return {
getTopActions,
getItemActions,
@@ -584,5 +627,6 @@ export function useReviewerManagerActions() {
reviewerThankReviewer,
reviewerRevertConsider,
reviewerSendReminder,
+ reviewerLogResponse,
};
}