Skip to content

Commit

Permalink
invitation table view and api integration
Browse files Browse the repository at this point in the history
  • Loading branch information
ipula committed Aug 12, 2024
1 parent e72ac93 commit e2b7aab
Show file tree
Hide file tree
Showing 29 changed files with 682 additions and 416 deletions.
6 changes: 4 additions & 2 deletions public/globals.js
Original file line number Diff line number Diff line change
Expand Up @@ -527,8 +527,8 @@ window.pkp = {
'submissions.declined': 'Declined',
'submissions.incomplete': 'Incomplete',
todo: '##todo##',
'user.email': 'Email',
'user.emailAddress': 'Email Address',
'about.contact.email': 'Email',
'user.email': 'Email Address',
'user.orcid': 'ORCID iD',
'user.username': 'Username',
'user.password': 'Password',
Expand Down Expand Up @@ -563,6 +563,8 @@ window.pkp = {
'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.',

},

Expand Down
2 changes: 0 additions & 2 deletions src/components/Container/PageOJS.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@ import Page from '@/components/Container/Page.vue';
import DashboardPage from '@/pages/dashboard/DashboardPage.vue';
import UserInvitationPage from '@/pages/userInvitation/UserInvitationPage.vue';
import AcceptInvitationPage from '@/pages/acceptInvitation/AcceptInvitationPage.vue';
import InvitationPage from '@/pages/invitation/InvitationPage.vue';
export default {
components: {
DashboardPage,
UserInvitationPage,
AcceptInvitationPage,
InvitationPage,
},
extends: Page,
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {Primary, Controls, Stories, Meta, ArgTypes} from '@storybook/blocks';

import * as InvitationPage from './InvitationPage.stories.js';
import * as InvitationManager from './InvitationManager.stories.js';

<Meta of={InvitationPage} />
<Meta of={InvitationManager} />

# Invitation page

Expand Down
42 changes: 42 additions & 0 deletions src/managers/InvitationManager/InvitationManager.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import InvitationManager from './InvitationManager.vue';
import {http, HttpResponse} from 'msw';
import invitationMock from './mocks/invitationMock.js';

export default {
title: 'Managers/InvitationManager',
component: InvitationManager,
};

export const Init = {
render: (args) => ({
components: {InvitationManager},
setup() {
return {args};
},
template: '<InvitationManager 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,
});
},
),
],
},
},
args: [],
};
108 changes: 108 additions & 0 deletions src/managers/InvitationManager/InvitationManager.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<template>
<div
v-if="!isInvitationLoading"
class="flex items-center pb-2 pt-2 text-3xl-normal"
>
<h4>
{{ t('invitation.header') }}({{ store.invitationsPagination.itemCount }})
</h4>
<div class="ml-auto">
<PkpButton @click="store.sendInvitation">
{{ t('invitation.inviteToRole.btn') }}
</PkpButton>
</div>
</div>
<PkpTable aria-label="Example for basic table">
<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></TableColumn>
</TableHeader>
<TableBody>
<TableRow v-if="store.invitations.length === 0">
<TableCell>No invitation have been sent out yet.</TableCell>
<TableCell></TableCell>
<TableCell></TableCell>
<TableCell></TableCell>
<TableCell></TableCell>
<TableCell></TableCell>
</TableRow>
<TableRow v-for="(row, index) in store.invitations" :key="index">
<TableCell>
{{ store.getFullName(row.givenName, row.familyName) }}
<Icon icon="orcid" :inline="true" />
</TableCell>
<TableCell>
{{ row.invitationModel.email }}
</TableCell>
<TableCell>
<template v-for="(userGroups, i) in row.userGroupsToAdd" :key="i">
<span>
{{ localize(userGroups.userGroupPayload.userGroup._data.name) }}
</span>
<br />
</template>
</TableCell>
<TableCell>
Invited
{{
new Date(row.invitationModel.createdAt).toLocaleDateString('en-US')
}}
</TableCell>
<TableCell>
{{ localize(row.affiliation) }}
</TableCell>
<TableCell>
<DropdownActions
:actions="[
{
label: 'View',
url: store.pageUrl + '/' + row.invitationModel.id,
icon: 'View',
},
{
label: 'Cancel Invite',
url: store.pageUrl + '/' + row.invitationModel.id,
icon: 'Cancel',
isWarnable: true,
},
]"
label="Invitation management options"
:display-as-ellipsis="true"
direction="left"
/>
</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/TableNext/Table.vue';
import TableCell from '@/components/TableNext/TableCell.vue';
import TableHeader from '@/components/TableNext/TableHeader.vue';
import TableColumn from '@/components/TableNext/TableColumn.vue';
import TableBody from '@/components/TableNext/TableBody.vue';
import TableRow from '@/components/TableNext/TableRow.vue';
import Icon from '@/components/Icon/Icon.vue';
import PkpButton from '@/components/Button/Button.vue';
import {useInvitationManagerStore} from './InvitationManagerStore.js';
import Pagination from '@/components/Pagination/Pagination.vue';
import {useTranslation} from '@/composables/useTranslation';
import DropdownActions from '@/components/DropdownActions/DropdownActions.vue';
const store = useInvitationManagerStore();
const {t} = useTranslation();
</script>
Original file line number Diff line number Diff line change
@@ -1,26 +1,35 @@
import {useTranslation} from '@/composables/useTranslation';
import {defineComponentStore} from '@/utils/defineComponentStore';
import {useApiUrl} from '@/composables/useApiUrl';
import {useUrl} from '@/composables/useUrl';
import {useFetch} from '@/composables/useFetch';
import {useAnnouncer} from '@/composables/useAnnouncer';
import {useUrl} from '@/composables/useUrl';
import {useLocalize} from '@/composables/useLocalize';
import {useFetchPaginated} from '@/composables/useFetchPaginated';
import {computed, ref, watch} from 'vue';

export const useInvitationsPageStore = defineComponentStore(
export const useInvitationManagerStore = defineComponentStore(
'invitationsPage',
() => {
/**
* Translation
*/

const {t} = useTranslation();

const {t} = useLocalize();
/** Announcer */

const {announce} = useAnnouncer();
const pageTitle = ref(null);
/**
* redirect to send invitation page
*/
const {pageUrl} = useUrl('invitation/invite');
const sendInvitationPageUrl = computed(() => {
return pageUrl.value;
});
function sendInvitation() {
window.location = sendInvitationPageUrl.value;
}

/**
* get invitations twith paginations
*/
const invitationCount = ref(0);

const countPerPage = ref(2);
const currentPage = ref(1);
function setCurrentPage(_currentPage) {
currentPage.value = _currentPage;
Expand All @@ -30,21 +39,14 @@ export const useInvitationsPageStore = defineComponentStore(
const getInvitationApiUrl = computed(() => {
return apiUrl.value;
});

const {pageUrl} = useUrl('management/settings/invitations');
const sendInvitationPageUrl = computed(() => {
return pageUrl.value;
});

function sendInvitation() {
window.location = sendInvitationPageUrl.value;
}
const {
data: invitations,
items: invitations,
pagination: invitationsPagination,
isLoading: isInvitationLoading,
fetch: fetchInvitation,
} = useFetch(getInvitationApiUrl, {
query: {page: currentPage},
} = useFetchPaginated(getInvitationApiUrl, {
currentPage,
pageSize: countPerPage,
});
watch(
[currentPage],
Expand All @@ -57,15 +59,27 @@ export const useInvitationsPageStore = defineComponentStore(
{immediate: true},
);

/**
* create user full name
* @param String givenName
* @param String familyName
* @returns String
*/
function getFullName(givenName, familyName) {
return givenName + ' ' + familyName;
}

return {
pageTitle,
invitationCount,
setCurrentPage,
sendInvitation,
currentPage,
invitationsPagination,
pageUrl,
// invitation table data
invitations,
isInvitationLoading,
getFullName,
};
},
);
89 changes: 89 additions & 0 deletions src/managers/InvitationManager/mocks/invitationMock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
export default {
itemsMax: 3,
items: [
{
invitationModel: {
invitation_id: 44,
user_id: null,
expiry_date: '2024-08-29T14:10:26.000000Z',
status: 'PENDING',
email: '[email protected]',
context_id: 1,
},
orcid: null,
givenName: 'asd',
familyName: 'ads',
affiliation: null,
country: null,
username: null,
password: null,
emailSubject: null,
emailBody: null,
existingUser: null,
userGroupsToAdd: [
{
masthead: true,
dateStart: '2024-07-26',
userGroup: 2,
},
],
userGroupsToRemove: [],
},
{
invitationModel: {
invitation_id: 45,
user_id: null,
expiry_date: '2024-08-29T14:26:09.000000Z',
status: 'PENDING',
email: '[email protected]',
context_id: 1,
},
orcid: null,
givenName: 'asd',
familyName: 'asd',
affiliation: null,
country: null,
username: null,
password: null,
emailSubject: null,
emailBody: null,
existingUser: null,
userGroupsToAdd: [
{
masthead: true,
dateStart: '2024-07-26',
userGroup: 10,
},
],
userGroupsToRemove: [],
},
{
invitationModel: {
invitation_id: 46,
user_id: null,
expiry_date: '2024-08-29T15:46:56.000000Z',
status: 'PENDING',
email: '[email protected]',
context_id: 1,
},
orcid: null,
givenName: 'zxc',
familyName: 'sdf',
affiliation: null,
country: null,
username: null,
password: null,
emailSubject: null,
emailBody: null,
existingUser: null,
userGroupsToAdd: [
{
masthead: true,
dateStart: '2024-07-26',
userGroup: 2,
},
],
userGroupsToRemove: [],
},
],
};
Loading

0 comments on commit e2b7aab

Please sign in to comment.