-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
invitation table view and api integration
- Loading branch information
Showing
28 changed files
with
1,318 additions
and
330 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -119,23 +119,6 @@ window.pkp = { | |
* Locale keys loaded on the server-side | ||
*/ | ||
localeKeys: { | ||
'acceptInvitation.modal.button': '##acceptInvitation.modal.button##', | ||
'acceptInvitation.modal.message': '##acceptInvitation.modal.message##', | ||
'acceptInvitation.modal.title': '##acceptInvitation.modal.title##', | ||
'acceptInvitation.passwordField.description': | ||
'##acceptInvitation.passwordField.description##', | ||
'acceptInvitation.privacyStatement.btn': | ||
'##acceptInvitation.privacyStatement.btn##', | ||
'acceptInvitation.privacyStatement.label': | ||
'##acceptInvitation.privacyStatement.label##', | ||
'acceptInvitation.review.accountDetails': | ||
'##acceptInvitation.review.accountDetails##', | ||
'acceptInvitation.review.userDetails': | ||
'##acceptInvitation.review.userDetails##', | ||
'acceptInvitation.skipVerifyOrcid': '##acceptInvitation.skipVerifyOrcid##', | ||
'acceptInvitation.usernameField.description': | ||
'##acceptInvitation.usernameField.description##', | ||
'acceptInvitation.verifyOrcid': '##acceptInvitation.verifyOrcid##', | ||
'admin.jobs.failed.action.redispatch': 'Try Again', | ||
'admin.jobs.failed.action.redispatch.all': 'Requeue All Failed Jobs', | ||
'article.article': 'Article', | ||
|
@@ -441,14 +424,12 @@ window.pkp = { | |
'Log in as this user? All actions you perform will be attributed to this user.', | ||
'help.help': 'Help', | ||
'informationCenter.informationCenter': 'Information Center', | ||
'invitation.orcid.acceptInvitation.message': | ||
'##invitation.orcid.acceptInvitation.message##', | ||
'invitation.role.addRole.button': '##invitation.role.addRole.button##', | ||
'invitation.role.dateStart': '##invitation.role.dateStart##', | ||
'invitation.role.masthead': '##invitation.role.masthead##', | ||
'invitation.role.addRole.button': 'Add Another Role', | ||
'invitation.role.dateStart': 'Start Date', | ||
'invitation.role.masthead': 'Journal Masthead', | ||
'invitation.role.removeRole.button': | ||
'##invitation.role.removeRole.button##', | ||
'invitation.role.selectRole': '##invitation.role.selectRole##', | ||
'Remove Role', | ||
'invitation.role.selectRole': 'Select a new role', | ||
'invitation.wizard.completeSteps': '##invitation.wizard.completeSteps##', | ||
'invitation.wizard.errors': '##invitation.wizard.errors##', | ||
'issue.issue': 'Issue', | ||
|
@@ -695,31 +676,60 @@ window.pkp = { | |
'submissions.declined': 'Declined', | ||
'submissions.incomplete': 'Incomplete', | ||
todo: '##todo##', | ||
'about.contact.email': 'Email', | ||
'user.email': 'Email Address', | ||
'user.affiliation': 'Affiliation', | ||
'user.email': 'Email', | ||
'user.emailAddress': '##user.emailAddress##', | ||
'user.familyName': 'Family Name', | ||
'user.givenName': 'Given Name', | ||
'user.gossip': 'Editorial Notes', | ||
'user.orcid': 'ORCID iD', | ||
'user.password': 'Password', | ||
'user.username': 'Username', | ||
'userInvitation.emailField.description': | ||
'##userInvitation.emailField.description##', | ||
'userInvitation.modal.button': '##userInvitation.modal.button##', | ||
'userInvitation.modal.message': '##userInvitation.modal.message##', | ||
'userInvitation.modal.title': '##userInvitation.modal.title##', | ||
'userInvitation.orcidField.description': | ||
'##userInvitation.orcidField.description##', | ||
'userInvitation.roleTable.endDate': '##userInvitation.roleTable.endDate##', | ||
'userInvitation.roleTable.journalMasthead': | ||
'##userInvitation.roleTable.journalMasthead##', | ||
'userInvitation.roleTable.role': '##userInvitation.roleTable.role##', | ||
'userInvitation.roleTable.startDate': | ||
'##userInvitation.roleTable.startDate##', | ||
'userInvitation.usernameField.description': | ||
'##userInvitation.usernameField.description##', | ||
'validator.required': 'This field is required.', | ||
'invitation.notification.closeBtn':'View all users', | ||
'invitation.orcid.acceptInvitation.message':'Not verified. You can verify your ORCID iD from your profile section in OJS', | ||
'userInvitation.emailField.description':'e.g. [email protected]', | ||
'userInvitation.usernameField.description':'e.g. mickeymouse', | ||
'userInvitation.orcidField.description':'e.g. 0000-0000-0000-0000', | ||
'userInvitation.roleTable.role':'Role', | ||
'userInvitation.roleTable.startDate':'Start Date', | ||
'userInvitation.roleTable.endDate':'End Date', | ||
'userInvitation.roleTable.journalMasthead':'Journal Masthead', | ||
'userInvitation.modal.title':'Invitation Sent', | ||
'userInvitation.modal.message':'{$email} has been invited to new role in OJS.You can be updated about users on the User and Roles page, your ojs notification and/ or your email', | ||
'userInvitation.modal.button':'View All Users', | ||
'acceptInvitation.usernameField.description':'It should be 10 characters long and could be a combination of uppercase letters, lowercase letters or numbers', | ||
'acceptInvitation.passwordField.description':'It should be 12 characters long and should be a combination of uppercase letters, lowercase letters, numbers and symbols', | ||
'acceptInvitation.review.userDetails':'User Details', | ||
'acceptInvitation.review.accountDetails':'Account Details', | ||
'acceptInvitation.verifyOrcid':'Verify ORCID iD', | ||
'acceptInvitation.skipVerifyOrcid':'Skip ORCID verification', | ||
'acceptInvitation.modal.title':"You've been assigned a new role in OJS", | ||
'acceptInvitation.modal.message':'Congratulations on your new role in OJS! You might now have access to new options. If you need assistance navigating the system, please click on the “Help” buttons throughout the interface for guidance', | ||
'acceptInvitation.modal.button':'View All Submissions', | ||
'acceptInvitation.privacyStatement.btn':'Privacy Statement', | ||
'acceptInvitation.privacyStatement.label':'Yes, I agree to have my data collected and stored according to the', | ||
'invitation.cancel': 'Cancel Invite', | ||
'invitation.inviteToRole.btn': 'Invite to a role', | ||
'invitation.header': 'Invitation', | ||
'invitation.tableHeader.name': 'Name', | ||
'invitation.searchForm.emptyError': 'At least provide one search criteria.', | ||
'invitation.cancelInvite.actionName':'Cancel Invite', | ||
'invitation.cancelInvite.title':'Cancel Invitation', | ||
'invitation.cancelInvite.message': 'Cancel the invitation sent to {$givenName} {$familyName} will deactivate acceptance link sent via email. Here are the invitation details:', | ||
'invitation.role.modifyRole.button':'Modify Role', | ||
'invitation.masthead.show':'Appear on the masthead', | ||
'invitation.masthead.hidden':'Does not appear on the masthead', | ||
'invitation.removeRoles':'Remove Role', | ||
'invitation.management.options':'Invitation management options', | ||
'userInvitation.cancel.message':'Are you sure wnat to cancel this invitation ?', | ||
'userInvitation.cancel.keepWorking':'Keep Working', | ||
'userInvitation.status.invited':'Invited', | ||
'userInvitation.search.userNotFound':'The user does not have a role in this journal', | ||
'userInvitation.search.userFound':'The user already exists in the journal', | ||
'userInvitation.edit.title':'Edit Invitation', | ||
'userInvitation.edit.message':'If you edit the existing invitation or add a new role, the current invitation will be canceled and, a new one will be sent. Are you sure you want to proceed?', | ||
'invitation.step':'STEP', | ||
}, | ||
|
||
tinyMCE: { | ||
|
11 changes: 11 additions & 0 deletions
11
src/managers/UserInvitationManager/UserInvitationManager.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import {Primary, Controls, Stories, Meta, ArgTypes} from '@storybook/blocks'; | ||
|
||
import * as UserInvitationManager from './UserInvitationManager.stories.js'; | ||
|
||
<Meta of={UserInvitationManager} /> | ||
|
||
# User Invitation page | ||
|
||
This page will show the current pending invitation list and handles the edit and cancel invite. | ||
|
||
<ArgTypes /> |
50 changes: 50 additions & 0 deletions
50
src/managers/UserInvitationManager/UserInvitationManager.stories.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import UserInvitationManager from './UserInvitationManager.vue'; | ||
import {http, HttpResponse} from 'msw'; | ||
import invitationMock from './mocks/invitationMock.js'; | ||
|
||
export default { | ||
title: 'Managers/UserInvitationManager', | ||
component: UserInvitationManager, | ||
}; | ||
|
||
export const Init = { | ||
render: (args) => ({ | ||
components: {UserInvitationManager}, | ||
setup() { | ||
return {args}; | ||
}, | ||
template: '<UserInvitationManager v-bind="args"/>', | ||
}), | ||
parameters: { | ||
msw: { | ||
handlers: [ | ||
http.get( | ||
'https://mock/index.php/publicknowledge/api/v1/invitations', | ||
async ({request}) => { | ||
const url = new URL(request.url); | ||
const offset = parseInt(url.searchParams.get('offset') || 0); | ||
const count = parseInt(url.searchParams.get('count')); | ||
const invitations = invitationMock.items.slice( | ||
offset, | ||
offset + count, | ||
); | ||
|
||
return HttpResponse.json({ | ||
itemsMax: invitationMock.itemsMax, | ||
items: invitations, | ||
}); | ||
}, | ||
), | ||
http.post( | ||
'https://mock/index.php/publicknowledge/api/v1/invitations/1/cancel', | ||
async ({request}) => { | ||
return HttpResponse.json({ | ||
request, | ||
}); | ||
}, | ||
), | ||
], | ||
}, | ||
}, | ||
args: [], | ||
}; |
116 changes: 116 additions & 0 deletions
116
src/managers/UserInvitationManager/UserInvitationManager.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
<template> | ||
<PkpTable> | ||
<template #label> | ||
<h3 class="text-3xl-bold"> | ||
{{ t('invitation.header') }}({{ | ||
store.invitationsPagination.itemCount | ||
}}) | ||
</h3> | ||
</template> | ||
<template #top-controls> | ||
<div class="flex space-x-2"> | ||
<PkpButton @click="store.createNewInvitation"> | ||
{{ t('invitation.inviteToRole.btn') }} | ||
</PkpButton> | ||
</div> | ||
</template> | ||
<TableHeader> | ||
<TableColumn>{{ t('invitation.tableHeader.name') }}</TableColumn> | ||
<TableColumn>{{ t('about.contact.email') }}</TableColumn> | ||
<TableColumn>{{ t('invitation.header') }}</TableColumn> | ||
<TableColumn>{{ t('common.status') }}</TableColumn> | ||
<TableColumn>{{ t('user.affiliation') }}</TableColumn> | ||
<TableColumn> | ||
<span class="sr-only">{{ t('common.moreActions') }}</span> | ||
</TableColumn> | ||
</TableHeader> | ||
<TableBody> | ||
<TableRow v-for="(row, index) in store.invitations" :key="index"> | ||
<TableCell> | ||
{{ row.userId ? row.existingUser.fullName : row.newUser.fullName }} | ||
<Icon | ||
v-if="row.existingUser?.orcid || row.newUser?.orcid" | ||
icon="orcid" | ||
:inline="true" | ||
/> | ||
</TableCell> | ||
<TableCell> | ||
{{ row.userId ? row.existingUser.email : row.email }} | ||
</TableCell> | ||
<TableCell> | ||
<template v-for="(userGroups, i) in row.userGroupsToAdd" :key="i"> | ||
<div class="flex flex-col"> | ||
{{ localize(userGroups.userGroupName) }} | ||
</div> | ||
</template> | ||
</TableCell> | ||
<TableCell> | ||
{{ | ||
t('userInvitation.status.invited') + | ||
' ' + | ||
formatShortDate(row.createdAt) | ||
}} | ||
</TableCell> | ||
<TableCell> | ||
{{ | ||
row.userId | ||
? localize(row.existingUser.affiliation) | ||
: localize(row.affiliation) | ||
}} | ||
</TableCell> | ||
<TableCell> | ||
<DropdownActions | ||
:actions="[ | ||
{ | ||
label: t('common.edit'), | ||
name: 'editInvite', | ||
icon: 'Edit', | ||
}, | ||
{ | ||
label: t('invitation.cancelInvite.actionName'), | ||
icon: 'Cancel', | ||
name: 'cancelInvite', | ||
isWarnable: true, | ||
}, | ||
]" | ||
:label="t('invitation.management.options')" | ||
:display-as-ellipsis="true" | ||
direction="left" | ||
@action=" | ||
(actionName) => store.handleInvitationAction(actionName, row) | ||
" | ||
/> | ||
</TableCell> | ||
</TableRow> | ||
</TableBody> | ||
</PkpTable> | ||
<div class="flex justify-end"> | ||
<Pagination | ||
:current-page="store.invitationsPagination.currentPage" | ||
:last-page="store.invitationsPagination.pageCount" | ||
:is-loading="store.isInvitationLoading" | ||
:show-adjacent-pages="3" | ||
@set-page="store.setCurrentPage" | ||
/> | ||
</div> | ||
</template> | ||
|
||
<script setup> | ||
import PkpTable from '@/components/Table/Table.vue'; | ||
import TableCell from '@/components/Table/TableCell.vue'; | ||
import TableHeader from '@/components/Table/TableHeader.vue'; | ||
import TableColumn from '@/components/Table/TableColumn.vue'; | ||
import TableBody from '@/components/Table/TableBody.vue'; | ||
import TableRow from '@/components/Table/TableRow.vue'; | ||
import Icon from '@/components/Icon/Icon.vue'; | ||
import PkpButton from '@/components/Button/Button.vue'; | ||
import {useUserInvitationManagerStore} from './UserInvitationManagerStore.js'; | ||
import Pagination from '@/components/Pagination/Pagination.vue'; | ||
import {useTranslation} from '@/composables/useTranslation'; | ||
import {useDate} from '@/composables/useDate'; | ||
import DropdownActions from '@/components/DropdownActions/DropdownActions.vue'; | ||
const store = useUserInvitationManagerStore(); | ||
const {t} = useTranslation(); | ||
const {formatShortDate} = useDate(); | ||
</script> |
27 changes: 27 additions & 0 deletions
27
src/managers/UserInvitationManager/UserInvitationManagerCancelInvitationDialogBody.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<template> | ||
<p>{{ message }}</p> | ||
<div> | ||
<ul> | ||
<li>{{ t('user.email') }} : {{ email }}</li> | ||
<li>{{ t('userInvitation.roleTable.role') }} : {{ roles }}</li> | ||
<li>{{ t('common.status') }} : {{ status }}</li> | ||
<li>{{ t('user.affiliation') }} : {{ affiliation }}</li> | ||
</ul> | ||
</div> | ||
</template> | ||
|
||
<script setup> | ||
import {useTranslation} from '@/composables/useTranslation'; | ||
defineProps({ | ||
message: {type: String, required: true}, | ||
email: {type: String, required: true}, | ||
roles: {type: String, required: true}, | ||
status: {type: String, required: true}, | ||
affiliation: {type: String, required: true}, | ||
}); | ||
const {t} = useTranslation(); | ||
</script> | ||
|
||
<style lang="less"></style> |
Oops, something went wrong.