Skip to content

pkp/pkp-lib#9658 changes in invitation and user access table #515

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Feb 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions public/globals.js
Original file line number Diff line number Diff line change
Expand Up @@ -839,12 +839,12 @@ window.pkp = {
'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?',
'userInvitation.edit.title': 'Edit Invitation',
'userInvitation.emailField.description': 'e.g. [email protected]',
'userInvitation.searchField.description':
'e.g. [email protected] or aeinstein or 0000-0000-0000-0000',
'userInvitation.modal.button': 'View All Users',
'userInvitation.modal.message':
"{$email} has been invited to new role in OJS. You can be updated about the user's decision on the User and Role page, your OJS notification and/or your email",
'userInvitation.modal.title': 'Invitation Sent',
'userInvitation.orcidField.description': 'e.g. 0000-0000-0000-0000',
'userInvitation.roleTable.endDate': 'End Date',
'userInvitation.roleTable.journalMasthead': 'Journal Masthead',
'userInvitation.roleTable.role': 'Role',
Expand All @@ -853,7 +853,6 @@ window.pkp = {
'userInvitation.search.userNotFound':
'The user does not have a role in this journal',
'userInvitation.status.invited': 'Invited {$date}',
'userInvitation.usernameField.description': 'e.g. mickeymouse',
'validator.required': 'This field is required.',
'workflow.review.externalReview': 'Review',
'workflow.review.internalReview': 'Internal Review',
Expand All @@ -867,6 +866,19 @@ window.pkp = {
'workflow.submissionNextReviewRoundInFutureStage':
'The submission advanced to the next review round, was accepted, and is currently in the {$stage} stage.',
'workflow.uploadRevisions': 'Upload revisions',
'userInvitation.searchField':
'Search for a user by email address, username, or ORCID iD. Enter only one to get started!',
'grid.user.enable': 'Enable User',
'grid.user.disable': 'Disable User',
'grid.user.remove': 'Remove User',
'grid.user.logInAs': 'Login As',
'grid.user.grid.user.enableReasonDescription':
"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.",
'user.disabledModal.description': 'Current Roles : {$roles}',
'user.disabledModal.title': 'Disable {$fullName}',
'user.enabledModal.title': 'Enable {$fullName}',
},
tinyMCE: {
skinUrl: '/styles/tinymce',
Expand Down
3 changes: 3 additions & 0 deletions src/components/Modal/SideModalBodyLegacyAjax.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<template>
<SideModalBody>
<template #title>{{ legacyOptions.title }}</template>
<template #description>
<p class="mt-1 text-lg-normal">{{ legacyOptions.description }}</p>
</template>
<div class="p-4">
<div class="bg-secondary p-4">
<AjaxModalWrapper
Expand Down
6 changes: 5 additions & 1 deletion src/composables/useLegacyGridUrl.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ export function useLegacyGridUrl({
return `${baseUrl}${queryParamsString.value}`;
});

function openLegacyModal({title, closeOnFormSuccessId}, finishedCallback) {
function openLegacyModal(
{title, closeOnFormSuccessId, description},
finishedCallback,
) {
const {openSideModal} = useModal();

openSideModal(
Expand All @@ -45,6 +48,7 @@ export function useLegacyGridUrl({
title,
url,
closeOnFormSuccessId,
description,
},
},
{
Expand Down
6 changes: 6 additions & 0 deletions src/managers/UserAccessManager/UserAccessManagerCellName.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
</span>

<Icon v-if="user.orcid" icon="Orcid" class="h-4 w-4" :inline="true" />
<Icon
v-if="user.disabled"
icon="DisableUser"
class="h-4 w-4 text-negative"
:inline="true"
/>
</TableCell>
</template>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
<TableCell>
<template v-for="(userGroups, i) in user.groups" :key="i">
<div class="flex flex-col">
{{ formatShortDate(userGroups?.startDate) }}
{{
!userGroups.dateEnd
? userGroups?.dateStart && formatShortDate(userGroups?.dateStart)
: ''
}}
</div>
</template>
</TableCell>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<TableCell>
<template v-for="(userGroups, i) in user.groups" :key="i">
<div class="flex flex-col">
{{ userGroups.name }}
{{ !userGroups.dateEnd ? userGroups.name : '' }}
</div>
</template>
</TableCell>
Expand Down
41 changes: 26 additions & 15 deletions src/managers/UserAccessManager/useUserAccessManagerActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,25 @@ export function useUserAccessManagerActions() {
if (getCurrentUserId() !== user.id) {
user.canLoginAs &&
actions.push({
label: t('grid.action.logInAs'),
label: t('grid.user.logInAs'),
icon: 'LoginAs',
name: Actions.USER_ACCESS_LOGIN_AS,
});

actions.push({
label: t('grid.action.remove'),
icon: 'Cancel',
name: Actions.USER_ACCESS_REMOVE_USER,
isWarnable: true,
});
if (user.groups.find((value) => value.dateEnd === null)) {
actions.push({
label: t('grid.user.remove'),
icon: 'Cancel',
name: Actions.USER_ACCESS_REMOVE_USER,
isWarnable: true,
});
}

actions.push({
label: user.disabled
? t('grid.action.enable')
: t('grid.action.disable'),
icon: 'DisableUser',
label: user.disabled ? t('grid.user.enable') : t('grid.user.disable'),
icon: user.disabled ? 'User' : 'DisableUser',
name: Actions.USER_ACCESS_DISABLE_USER,
isWarnable: true,
isWarnable: !user.disabled,
});

user.canMergeUser &&
Expand Down Expand Up @@ -89,10 +89,21 @@ export function useUserAccessManagerActions() {
enable: user.disabled ? '1' : '',
},
});
const currentRoles = user.groups.map((group) => group.name).join(', ');

openLegacyModal({title: t('grid.user.disable')}, (closeData) => {
finishedCallback();
});
openLegacyModal(
{
title: !user.disabled
? t('user.disabledModal.title', {fullName: user.fullName})
: t('user.enabledModal.title', {fullName: user.fullName}),
description: t('user.disabledModal.description', {
roles: currentRoles,
}),
},
(closeData) => {
finishedCallback();
},
);
}

const {openDialog, openDialogNetworkError} = useModal();
Expand Down
11 changes: 11 additions & 0 deletions src/pages/userInvitation/UserInvitationDetailsFormStep.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
<template>
<div
v-if="store.invitationPayload.disabled"
class="m-8 border-x border-b border-t border-light bg-secondary p-4"
>
<h2 class="text-xl-bold text-heading">
{{ t('userInvitation.user.disableTitle') }}
</h2>
<p class="text-base-normal text-secondary">
{{ t('userInvitation.user.disableMessage') }}
</p>
</div>
<div v-if="store.invitationPayload.userId === null">
<div v-if="Object.keys(store.errors).length" class="p-4">
<FormErrorSummary :errors="store.errors" />
Expand Down
75 changes: 52 additions & 23 deletions src/pages/userInvitation/UserInvitationPageStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const useUserInvitationPageStore = defineComponentStore(
const updatedPayload = ref({});
const invitationType = ref(pageInitConfig.invitationType);
const invitationMode = ref(pageInitConfig.invitationMode);
const detectChanges = ref(false);

function updatePayload(fieldName, value, initialValue = true) {
invitationPayload.value[fieldName] = value;
Expand Down Expand Up @@ -267,6 +268,7 @@ export const useUserInvitationPageStore = defineComponentStore(
await createInvitation();

if (validationError.value) {
delete validationError.value.errors['userId'];
errors.value = validationError.value.errors;
} else {
errors.value = [];
Expand Down Expand Up @@ -299,7 +301,27 @@ export const useUserInvitationPageStore = defineComponentStore(
}

const {redirectToPage} = useUrl('management/settings/access');
const isSubmitting = ref(false);
const isSubmitting = ref(
invitationMode.value === 'editUser'
? true
: invitationPayload.value.disabled,
);

/**
* change isSubmitting value based on
* user disable or not for disable submit button
*/
watch(
invitationPayload,
async (newVal, oldVal) => {
isSubmitting.value = invitationPayload.value.disabled;
if (invitationPayload.value.userGroupsToAdd.length === 0) {
isSubmitting.value = true;
}
detectChanges.value = true;
},
{deep: true},
);
/** Submit invitation */
async function submitInvitation() {
await updateInvitation();
Expand Down Expand Up @@ -336,28 +358,35 @@ export const useUserInvitationPageStore = defineComponentStore(
}

function cancel() {
openDialog({
name: 'cancel',
title: t('invitation.cancelInvite.title'),
message: t('userInvitation.cancel.message'),
actions: [
{
label: t('invitation.cancelInvite.actionName'),
isWarnable: true,
callback: (close) => {
redirectToPage();
},
},
{
label: t('userInvitation.cancel.goBack'),
callback: (close) => {
redirectToPage();
close();
},
},
],
modalStyle: 'negative',
});
if (detectChanges.value) {
if (invitationMode.value === 'editUser') {
confirm(t('form.dataHasChanged')) ? redirectToPage() : '';
} else {
openDialog({
name: 'cancel',
title: t('invitation.cancelInvite.title'),
message: t('userInvitation.cancel.message'),
actions: [
{
label: t('invitation.cancelInvite.actionName'),
isWarnable: true,
callback: (close) => {
redirectToPage();
},
},
{
label: t('userInvitation.cancel.goBack'),
callback: (close) => {
close();
},
},
],
modalStyle: 'negative',
});
}
} else {
redirectToPage();
}
}

const registeredActionsForSteps = {};
Expand Down
Loading