Skip to content

Commit

Permalink
pkp/pkp-lib#9453 Add sections to the round history modal
Browse files Browse the repository at this point in the history
pkp/pkp-lib#9453 Connect the new API for the round history

pkp/pkp-lib#9453 Use the localized recommandation value

pkp/pkp-lib#9453 Show review comments as HTML

pkp/pkp-lib#9453 Refactor the round history UI to follow the proper design

pkp/pkp-lib#9453 Fix the download URL for file component

pkp/pkp-lib#9453 Adding ReviewerSubmissionPage to storybook

pkp/pkp-lib#9453 Use tailwind instead of panels and localize data from the api

pkp/pkp-lib#9453 Fix for chromatic

pkp/pkp-lib#9453 Better data for review history mocks

pkp/pkp-lib#9453 Fix typo

pkp/pkp-lib#9453 Adjust the viewport height for storybook

pkp/pkp-lib#9453 Minor UI ajustements asked by Devika
  • Loading branch information
nibou230 authored and jardakotesovec committed Apr 24, 2024
1 parent 32e8487 commit fe684d6
Show file tree
Hide file tree
Showing 11 changed files with 551 additions and 38 deletions.
40 changes: 33 additions & 7 deletions public/globals.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ window.pkp = {
apiBaseUrl: 'https://mock/index.php/publicknowledge/api/v1/',
pageBaseUrl: 'https://mock/index.php/publicknowledge/',
},

/**
* Dummy constants required by components
*/
Expand Down Expand Up @@ -262,6 +261,7 @@ window.pkp = {
'manager.dois.update.partialFailure': 'Some DOI(s) could not be updated',
'manager.dois.update.success': 'DOI(s) successfully updated',
'navigation.backTo': '\u27f5 Back to {$page}',
'navigation.submissions': 'Submissions',
'publication.jats.autoCreatedMessage':
'This JATS file is generated automatically by the submission metadata',
'publication.jats.confirmDeleteFileButton': 'Delete JATS File',
Expand All @@ -273,12 +273,38 @@ window.pkp = {
'publication.status.published': 'Published',
'publication.status.unpublished': 'Unpublished',
'publication.version': 'Version {$version}',
'reviewer.article.decision.accept': 'Accept Submission',
'reviewer.article.decision.decline': 'Decline Submission',
'reviewer.article.decision.pendingRevisions': 'Revisions Required',
'reviewer.article.decision.resubmitElsewhere': 'Resubmit Elsewhere',
'reviewer.article.decision.resubmitHere': 'Resubmit for Review',
'reviewer.article.decision.seeComments': 'See Comments',
'reviewer.article.recommendation': 'Recommendation',
'reviewer.submission.acceptedOn': 'Review Accepted On',
'reviewer.submission.responseDueDate': 'Response Due Date',
'reviewer.submission.reviewDueDate': 'Review Due Date',
'reviewer.submission.reviewRequestDate': "Editor's Request",
'reviewer.submission.reviewRound.attachments': 'Attachments',
'reviewer.submission.reviewRound.attachments.description':
'These are files that you attached along with your review',
'reviewer.submission.reviewRound.comments': 'Reviewer Comments',
'reviewer.submission.reviewRound.comments.authorAndEditor':
'For editors and authors',
'reviewer.submission.reviewRound.comments.editorOnly': 'For editors only',
'reviewer.submission.reviewRound.comments.prefix': 'Comment {$index}: ',
'reviewer.submission.reviewRound.emailLog': 'Decline reason sent by email',
'reviewer.submission.reviewRound.emailLog.defaultMessage':
'No reason given to the decline of the review invitation.',
'reviewer.submission.reviewRound.files': 'Files For Review',
'reviewer.submission.reviewRound.files.description':
'These files were sent to you for review',
'reviewer.submission.reviewRound.general': 'General Information',
'reviewer.submission.reviewRound.info': 'Previous Reviews',
'reviewer.submission.reviewRound.info.modal.title':
'Round {$round} Review submitted by you for',
'reviewer.submission.reviewRound.info.read': 'Read Round {$round} Review',
'reviewer.submission.reviewRound.info.submittedOn':
'Round {$round} Review Submitted on {$submittedOn}',
'reviewer.submission.reviewRound.metadata': 'Article Metadata',
'reviewer.submission.reviewRound.metadata.abstract': 'Abstract',
'reviewer.submission.reviewRound.metadata.keywords': 'Keywords',
'reviewer.submission.reviewRound.metadata.type': 'Type',
'reviewer.submission.reviewRound.reviewDeclineDate': 'Declined Date',
'reviewer.submission.submittedOn': 'Review Submitted On',
'stats.countWithYearlyAverage': '{$count} ({$average}/year)',
'stats.descriptionForStat': 'Description for {$stat}',
'submission.list.assignEditor': 'Assign Editor',
Expand Down
3 changes: 1 addition & 2 deletions src/components/File/File.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
{{ fileId }}
</span>
<span class="ms-1">
<a v-if="url" class="underline" href="url" target="_blank">{{ name }}</a>
<a v-if="url" class="underline" :href="url" target="_blank">{{ name }}</a>
<template v-else>
{{ name }}
</template>
Expand Down Expand Up @@ -35,7 +35,6 @@ export default {
type: String,
required: true,
},
/** Optional. If the file should be be url to download file */
url: {
type: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
<template>
<ListPanel :title="title" :description="description" :items="files">
<template #header>
<h2 class="pkpHeader__title">
<span class="text-dark-accent">{{ title }}</span>
</h2>
<div v-if="description">{{ description }}</div>
</template>
<template #item="{item}">
<div class="flex items-center">
<div class="me-2 flex-grow truncate">
Expand Down
13 changes: 13 additions & 0 deletions src/pages/reviewerSubmission/ReviewerSubmissionPage.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import {Primary, Controls, Stories, Meta, ArgTypes} from '@storybook/blocks';

import * as ReviewerSubmissionPageStories from './ReviewerSubmissionPage.stories.js';

<Meta of={ReviewerSubmissionPageStories} />

# Reviewer Page

Only reviews history for now, until rest of the page is migrated from old stack.

## Server side configuration

<ArgTypes />
86 changes: 86 additions & 0 deletions src/pages/reviewerSubmission/ReviewerSubmissionPage.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import {within, userEvent} from '@storybook/testing-library';
import {http, HttpResponse} from 'msw';

import ReviewerSubmissionPage from './ReviewerSubmissionPage.vue';
import Review1Mock from './mocks/review1';
import Review2Mock from './mocks/review2';

export default {
title: 'Pages/ReviewerSubmission',
component: ReviewerSubmissionPage,
render: (args) => ({
components: {ReviewerSubmissionPage},
setup() {
return {args};
},
template: '<ReviewerSubmissionPage v-bind="args.pageInitConfig" />',
}),
args: {
pageInitConfig: {
reviewRoundHistories: [
{
submissionId: 16,
reviewRoundId: 15,
reviewRoundNumber: 1,
submittedOn: '2024-02-08 12:45:38',
},
{
submissionId: 16,
reviewRoundId: 16,
reviewRoundNumber: 2,
submittedOn: '2024-02-08 12:51:12',
},
],
},
},
parameters: {
msw: {
handlers: [
http.get(
'https://mock/index.php/publicknowledge/api/v1/reviews/history/16/15',
async (r) => {
return HttpResponse.json(Review1Mock);
},
),
http.get(
'https://mock/index.php/publicknowledge/api/v1/reviews/history/16/16',
async (r) => {
return HttpResponse.json(Review2Mock);
},
),
],
},
},
};

export const Base = {};

export const OpenModalAccepted = {
play: async ({canvasElement}) => {
// Assigns canvas to the component root element
const canvas = within(canvasElement);
const user = userEvent.setup();

await user.click(canvas.getByText('Read Round 1 Review'));
},
decorators: [
() => ({
template: '<div style="height: 1200px"><story/></div>',
}),
],
};

export const OpenModalDeclined = {
play: async ({canvasElement}) => {
// Assigns canvas to the component root element
const canvas = within(canvasElement);
const user = userEvent.setup();

await user.click(canvas.getByText('Read Round 2 Review'));
},
decorators: [
() => ({
template: '<div style="height: 1200px"><story/></div>',
}),
],
};
30 changes: 22 additions & 8 deletions src/pages/reviewerSubmission/ReviewerSubmissionPage.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
<template>
<div class="mb-4 space-x-2">
<PkpButton
<div class="bg-lightest border border-light text-dark p-8 mb-4">
<h2 class="text-dark-accent">{{ t('reviewer.submission.reviewRound.info') }}</h2>
<p
v-for="review in store.reviewRoundHistories"
:key="review.reviewRoundId"
@click="store.openRoundHistoryModal(review)"
>
{{ t('submission.round', {round: review.reviewRoundNumber}) }}
</PkpButton>
<span class="text-lg-normal">
{{ t(
'reviewer.submission.reviewRound.info.submittedOn',
{round: review.reviewRoundNumber, submittedOn: formatShortDate(review.submittedOn)}
) }}
</span>
<PkpButton
is-link="true"
class="ms-4"
@click="store.openRoundHistoryModal(review)"
>
{{ t('reviewer.submission.reviewRound.info.read', {round: review.reviewRoundNumber}) }}
</PkpButton>
</p>
</div>
<SideModal
:open="store.isRoundHistoryModalOpened"
Expand All @@ -20,13 +32,15 @@

<script setup>
import {defineProps} from 'vue';
import SideModal from '@/components/Modal/SideModal.vue';
import RoundHistoryModal from './RoundHistoryModal.vue';
import {useTranslation} from '@/composables/useTranslation';
import {useReviewerSubmissionPageStore} from './reviewerSubmissionPageStore';
import moment from 'moment';
function formatShortDate(dateString) {
return moment(dateString).format('DD-MM-YYYY');
}
const {t} = useTranslation();
Expand Down
133 changes: 120 additions & 13 deletions src/pages/reviewerSubmission/RoundHistoryModal.vue
Original file line number Diff line number Diff line change
@@ -1,33 +1,140 @@
<template>
<SideModalBody>
<template #title>Title TODO</template>
<div class="p-4">
<div class="bg-secondary p-5">
Here goes all metadata, submissionId: {{ store.submissionId }}, roundId:
{{ store.reviewRoundId }}

<div v-if="store.submission">
<div class="text-xl-bold">
{{ localize(store.submission.publications[0].title) }}
<SideModalBody v-if="store.reviewRoundHistory" class="text-dark">
<template v-if="store.reviewRoundHistory.reviewAssignment" #pre-title>
{{ store.reviewRoundHistory.reviewAssignment.submissionId }}
</template>
<template #title>
<h1 class="underline text-dark-accent">
{{ t('reviewer.submission.reviewRound.info.modal.title', {round: store.reviewRoundNumber}) }}
</h1>
</template>
<template v-if="store.reviewRoundHistory.publicationTitle" #description>
{{ localize(store.reviewRoundHistory.publicationTitle) }}
</template>
<SideModalLayout2Columns>
<template #left>
<div v-if="store.reviewRoundHistory.reviewAssignment.declined">
<div class="border border-light p-4 mb-4">
<h2 class="text-2xl-bold mb-4 text-dark-accent">{{ t('reviewer.submission.reviewRound.reviewDeclineDate') }}</h2>
<p>{{ formatShortDate(store.reviewRoundHistory.reviewAssignment.dateConfirmed) }}</p>
</div>

<div v-if="store.reviewRoundHistory.declineEmail" class="border border-light p-4">
<h2 class="text-2xl-bold text-dark-accent mb-4">{{ t('reviewer.submission.reviewRound.emailLog') }}</h2>
<p v-html="store.reviewRoundHistory.declineEmail.subject" class="font-bold mb-4"></p>
<hr class="opacity-50">
<p v-html="store.reviewRoundHistory.declineEmail.body" class="mt-4"></p>
</div>
<p v-else>{{ t('reviewer.submission.reviewRound.emailLog.defaultMessage') }}</p>
</div>
<div v-else>
<div v-if="store.reviewRoundHistory.recommendation" class="border border-light p-4 mb-4">
<h2 class="text-2xl-bold text-dark-accent mb-4">{{ t('reviewer.article.recommendation') }}</h2>
<p>{{ store.reviewRoundHistory.recommendation }}</p>
</div>

<div v-if="store.reviewRoundHistory.comments.length || store.reviewRoundHistory.privateComments.length" class="border border-light mb-4">
<div class="border-b border-light p-4">
<h2 class="text-2xl-bold text-dark-accent">{{ t('reviewer.submission.reviewRound.comments') }}</h2>
</div>
<div v-if="store.reviewRoundHistory.comments.length" class="border-b border-light p-4">
<h2 class="text-xl-bold text-light mb-4">{{ t('reviewer.submission.reviewRound.comments.authorAndEditor') }}</h2>
<p v-for="(reviewComment, index) in store.reviewRoundHistory.comments">
<span class="text-xl-bold">{{ t('reviewer.submission.reviewRound.comments.prefix', {index: index + 1}) }}</span>
<span v-html="reviewComment"></span>
</p>
</div>
<div v-if="store.reviewRoundHistory.privateComments.length" class="p-4">
<h2 class="text-xl-bold text-light mb-4">{{ t('reviewer.submission.reviewRound.comments.editorOnly') }}</h2>
<p v-for="(reviewComment, index) in store.reviewRoundHistory.privateComments">
<span class="text-xl-bold">{{ t('reviewer.submission.reviewRound.comments.prefix', {index: index + 1}) }}</span>
<span v-html="reviewComment"></span>
</p>
</div>
</div>

<ListingFilesListPanel
v-if="store.reviewRoundHistory.attachments.length"
class="mb-4"
:title="t('reviewer.submission.reviewRound.attachments')"
:description="t('reviewer.submission.reviewRound.attachments.description')"
:files="store.reviewRoundHistory.attachments"
></ListingFilesListPanel>

<ListingFilesListPanel
v-if="store.reviewRoundHistory.files.length"
:title="t('reviewer.submission.reviewRound.files')"
:description="t('reviewer.submission.reviewRound.files.description')"
:files="store.reviewRoundHistory.files"
></ListingFilesListPanel>
</div>
</template>
<template #right1>
<div class="text-xl-bold text-dark-accent">{{ t('reviewer.submission.reviewRound.metadata') }}</div>
<div v-if="store.reviewRoundHistory.publicationType" class="mt-4">
<div class="text-lg-bold text-dark-accent">{{ t('reviewer.submission.reviewRound.metadata.type') }}:</div>
<div class="text-base-normal mt-1">{{ localize(store.reviewRoundHistory.publicationType) }}</div>
</div>
</div>
</div>
<div v-if="store.reviewRoundHistory.publicationAbstract" class="mt-4">
<div class="text-lg-bold text-dark-accent">{{ t('reviewer.submission.reviewRound.metadata.abstract') }}:</div>
<div class="text-base-normal mt-1" v-html="localize(store.reviewRoundHistory.publicationAbstract)"></div>
</div>
<div v-if="store.reviewRoundHistory.publicationKeywords" class="mt-4">
<div class="text-lg-bold text-dark-accent">{{ t('reviewer.submission.reviewRound.metadata.keywords') }}:</div>
<div class="text-base-normal mt-1">
<template v-for="(keyword, index) in localize(store.reviewRoundHistory.publicationKeywords)">
<template v-if="index > 0">, </template><span>{{ keyword }}</span>
</template>
</div>
</div>
</template>
<template v-if="store.reviewRoundHistory.reviewAssignment" #right2>
<div class="text-xl-bold text-dark-accent">{{ t('reviewer.submission.reviewRound.general') }}</div>
<div v-if="store.reviewRoundHistory.reviewAssignment.dateNotified" class="mt-4">
<div class="text-lg-bold text-dark-accent">{{ t('reviewer.submission.reviewRequestDate') }}:</div>
<div class="text-base-normal mt-1">{{ formatShortDate(store.reviewRoundHistory.reviewAssignment.dateNotified) }}</div>
</div>
<div v-if="store.reviewRoundHistory.reviewAssignment.dateResponseDue" class="mt-4">
<div class="text-lg-bold text-dark-accent">{{ t('reviewer.submission.responseDueDate') }}:</div>
<div class="text-base-normal mt-1">{{ formatShortDate(store.reviewRoundHistory.reviewAssignment.dateResponseDue) }}</div>
</div>
<div v-if="store.reviewRoundHistory.reviewAssignment.dateConfirmed" class="mt-4">
<div class="text-lg-bold text-dark-accent">{{ t('reviewer.submission.acceptedOn') }}:</div>
<div class="text-base-normal mt-1">{{ formatShortDate(store.reviewRoundHistory.reviewAssignment.dateConfirmed) }}</div>
</div>
<div v-if="store.reviewRoundHistory.reviewAssignment.dateDue" class="mt-4">
<div class="text-lg-bold text-dark-accent">{{ t('reviewer.submission.reviewDueDate') }}:</div>
<div class="text-base-normal mt-1">{{ formatShortDate(store.reviewRoundHistory.reviewAssignment.dateDue) }}</div>
</div>
<div v-if="store.reviewRoundHistory.reviewAssignment.dateCompleted" class="mt-4">
<div class="text-lg-bold text-dark-accent">{{ t('reviewer.submission.submittedOn') }}:</div>
<div class="text-base-normal mt-1">{{ formatShortDate(store.reviewRoundHistory.reviewAssignment.dateCompleted) }}</div>
</div>
</template>
</SideModalLayout2Columns>
</SideModalBody>
</template>

<script setup>
import {defineProps} from 'vue';
import SideModalBody from '@/components/Modal/SideModalBody.vue';
import SideModalLayout2Columns from "@/components/Modal/SideModalLayout2Columns.vue";
import ListingFilesListPanel from "@/components/ListPanel/listingFiles/ListingFilesListPanel.vue";
import {useTranslation} from '@/composables/useTranslation';
import {useRoundHistoryModalStore} from './roundHistoryModalStore';
import moment from 'moment';
function formatShortDate(dateString) {
return moment(dateString).format('DD-MM-YYYY');
}
const props = defineProps({
submissionId: {type: Number, required: true},
reviewRoundId: {type: Number, required: true},
reviewRoundNumber: {type: Number, required: true},
});
const {localize} = useTranslation();
const {t, localize} = useTranslation();
const store = useRoundHistoryModalStore(props);
</script>
Loading

0 comments on commit fe684d6

Please sign in to comment.