Skip to content
This repository has been archived by the owner on Nov 19, 2024. It is now read-only.

Commit

Permalink
Merge pull request #57 from JiveOff/edition-membres-projets
Browse files Browse the repository at this point in the history
Edition membres projets
  • Loading branch information
ThibClnt authored May 20, 2023
2 parents fa40489 + f849ef4 commit aaccdd0
Show file tree
Hide file tree
Showing 5 changed files with 250 additions and 40 deletions.
185 changes: 170 additions & 15 deletions components/projects/UserTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
<DataTable
:value="modelValue"
removable-sort
resizable-columns
table-style="min-width: 50rem"
:rows="5"
paginator
>
<template #header>
<div class="flex justify-content-between align-items-center pr-5">
Expand All @@ -13,12 +16,12 @@
class="my-2"
severity="info"
size="large"
@click="setDialogVisible(true)"
@click="setAddDialogVisible(true)"
></Button>
</div>
</template>

<Column field="user" sortable header="Nom">
<Column field="user" sortable header="Nom" style="min-width: 16rem">
<template #body="slotProps">
<div class="flex align-items-center gap-4">
<img
Expand All @@ -29,18 +32,40 @@
</div>
</template>
</Column>
<Column field="role" sortable header="Role">

<Column field="role" sortable header="Role" style="min-width: 12rem">
<template #body="slotProps">
<span>{{
roles.find(({ role }) => role === slotProps.data.role)?.name
}}</span>
</template>
</Column>

<Column style="min-width: 8rem; width: 10rem">
<template #body="slotProps">
<Button
v-if="slotProps.data.role != 'OWNER'"
icon="pi pi-pencil"
rounded
class="mr-2"
severity="info"
@click="(event) => askUpdateMember(event, slotProps.data)"
></Button>
<Button
v-if="slotProps.data.role != 'OWNER'"
icon="pi pi-trash"
rounded
severity="danger"
@click="(event) => askDeleteMember(event, slotProps.data)"
></Button>
</template>
</Column>
</DataTable>
</div>

<!-- Dialog displayed when adding a member -->
<Dialog
v-model:visible="isDialogVisible"
v-model:visible="isAddDialogVisible"
modal
header="Ajouter un membre au projet"
class="w-5"
Expand Down Expand Up @@ -82,16 +107,74 @@
label="Annuler"
severity="danger"
class="w-4"
@click="setDialogVisible(false)"
@click="setAddDialogVisible(false)"
></Button>
</div>
</div>
</Dialog>

<!-- Overlay displayed when updating a member's role -->
<OverlayPanel ref="updateOverlay">
<div>
<div class="field text-center w-100">
<SelectButton
v-model="selectedRole"
:options="roles.slice(1)"
option-label="name"
class="w-full m-auto"
unselectable
>
</SelectButton>
</div>

<div class="flex justify-content-center align-items-center">
<Button
icon="pi pi-check"
severity="success"
class="mr-4"
rounded
@click="updateMember()"
></Button>
<Button
icon="pi pi-times"
severity="danger"
rounded
@click="updateOverlay.hide()"
></Button>
</div>
</div>
</OverlayPanel>

<!-- Overlay displayed when deleting a member -->
<OverlayPanel ref="deleteOverlay">
<div>
<div class="text-center w-100">
<p class="strong">Veuillez-confirmer pour supprimer.</p>
</div>

<div class="flex justify-content-center align-items-center">
<Button
icon="pi pi-check"
severity="success"
class="mr-4"
rounded
@click="deleteMember()"
></Button>
<Button
icon="pi pi-times"
severity="danger"
rounded
@click="deleteOverlay.hide()"
></Button>
</div>
</div>
</OverlayPanel>
</template>

<script lang="ts" setup>
const auth = useAuth();
// Setup props and events
const props = defineProps<{
modelValue: Exclude<
Awaited<ReturnType<typeof getProject>>,
Expand All @@ -102,12 +185,12 @@ const props = defineProps<{
const emit = defineEmits<{
(event: "update:modelValue", payload: typeof props.modelValue): void;
(event: "memberAdded", payload: typeof props.modelValue[number]): void;
(event: "memberAdded", payload: (typeof props.modelValue)[number]): void;
(event: "memberEdited", payload: (typeof props.modelValue)[number]): void;
(event: "memberDeleted", payload: (typeof props.modelValue)[number]): void;
}>();
// Add user dialog
const selectedUser: Ref<any | undefined> = ref();
// Init variables
const roles: Array<{
name: string;
role: (typeof props.modelValue)[number]["role"];
Expand All @@ -116,32 +199,52 @@ const roles: Array<{
{ name: "Développeur", role: "DEVELOPER" },
{ name: "Gestionnaire", role: "MANAGER" },
];
const selectedUser: Ref<
Exclude<Awaited<ReturnType<typeof getUsers>>, undefined>[number] | undefined
> = ref();
const selectedMember: Ref<
| Exclude<
Awaited<ReturnType<typeof getProject>>,
undefined
>["members"][number]
| undefined
> = ref();
const selectedRole = ref(roles[1]);
const isDialogVisible = ref(false);
const updateOverlay = ref();
const deleteOverlay = ref();
const isAddDialogVisible = ref(false);
// Set the user to add
const setSelectedUser = (user: any) => {
if (typeof user !== "string" && user !== null) {
selectedUser.value = user;
}
};
const setDialogVisible = (value: boolean) => {
isDialogVisible.value = value;
// Control the add member dialog
const setAddDialogVisible = (value: boolean) => {
isAddDialogVisible.value = value;
if (!value) {
selectedRole.value = roles[1];
}
};
// Add a new member to the project
const addMember = async () => {
if (!selectedRole.value || !selectedUser.value) return;
// Check if the member already exists
if (
props.modelValue?.find(
(member) => member.user.name === selectedUser.value?.name
)
)
) {
return;
}
// Create and push the new member
const newMember = {
id: "",
role: selectedRole.value.role,
Expand All @@ -150,12 +253,64 @@ const addMember = async () => {
name: selectedUser.value.name,
image: selectedUser.value.image,
},
}
};
props.modelValue?.push(newMember);
emit("memberAdded", newMember);
setAddDialogVisible(false);
};
// Toggle the updateOverlay (and set the selected member and its current role)
const askUpdateMember = (
event: any,
member: Exclude<
Awaited<ReturnType<typeof getProject>>,
undefined
>["members"][number]
) => {
selectedMember.value = member;
updateOverlay.value.toggle(event);
if (selectedMember.value !== undefined) {
selectedRole.value =
roles.find(({ role }) => role === selectedMember.value?.role) ?? roles[1];
}
};
// Update the role of the selected member
const updateMember = async () => {
if (!selectedRole.value || !selectedMember.value) return;
const currentMemberIndex = props.modelValue.indexOf(selectedMember.value);
if (currentMemberIndex === -1) return;
props.modelValue[currentMemberIndex].role = selectedRole.value.role;
emit("memberEdited", selectedMember.value);
updateOverlay.value.hide();
};
// Toggle the deleteOverlay (asks if the user really wants to delete the selectedMember)
const askDeleteMember = (
event: any,
member: Exclude<
Awaited<ReturnType<typeof getProject>>,
undefined
>["members"][number]
) => {
selectedMember.value = member;
deleteOverlay.value.toggle(event);
};
// Delete the selected member
const deleteMember = async () => {
if (!selectedMember.value) return;
const currentMemberIndex = props.modelValue.indexOf(selectedMember.value);
if (currentMemberIndex === -1) return;
setDialogVisible(false);
props.modelValue.splice(currentMemberIndex, 1);
emit("memberDeleted", selectedMember.value);
deleteOverlay.value.hide();
};
</script>

Expand Down
22 changes: 22 additions & 0 deletions pages/projects/update/[id].vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
:model-value="members ?? []"
:users-available="userList"
@member-added="addMember"
@member-edited="updateMember"
@member-deleted="deleteMember"
></ProjectsUserTable>
</div>

Expand Down Expand Up @@ -112,6 +114,8 @@ const members: Ref<
| undefined
> = ref();
const newMembers: typeof members = ref([]);
const updatedMembers: typeof members = ref([]);
const deletedMembers: typeof members = ref([]);
// Fetch data
const loaded = ref(false);
Expand Down Expand Up @@ -153,6 +157,22 @@ const addMember = (
newMembers.value?.push(member);
};
// Tracl members to update
const updateMember = (
member: Exclude<(typeof members)["value"], undefined>[number]
) => {
updatedMembers.value?.push(member);
};
// Track members to delete
const deleteMember = (
member: Exclude<(typeof members)["value"], undefined>[number]
) => {
deletedMembers.value?.push(member);
};
// Track members to delete
// Form validation
const nameErrorMessage = ref("");
const membersErrorMessage = ref("");
Expand Down Expand Up @@ -196,6 +216,8 @@ const updateThisProject = async () => {
userId: member.user.id,
role: member.role,
})) ?? [],
updateMembers: updatedMembers.value,
deleteMembers: deletedMembers.value,
});
};
Expand Down
2 changes: 2 additions & 0 deletions plugins/primevue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import DataTable from "primevue/datatable";
import Column from "primevue/column";
import Dialog from "primevue/dialog";
import Listbox from "primevue/listbox";
import OverlayPanel from "primevue/overlaypanel";

import ToastService from "primevue/toastservice";
import Toast from "primevue/toast";
Expand All @@ -35,4 +36,5 @@ export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.component("Column", Column);
nuxtApp.vueApp.component("Dialog", Dialog);
nuxtApp.vueApp.component("Listbox", Listbox);
nuxtApp.vueApp.component("OverlayPanel", OverlayPanel);
});
Loading

0 comments on commit aaccdd0

Please sign in to comment.