diff --git a/src/Bundle/ChillTicketBundle/src/Resources/public/types.ts b/src/Bundle/ChillTicketBundle/src/Resources/public/types.ts index 24e4d295e..b024c1a55 100644 --- a/src/Bundle/ChillTicketBundle/src/Resources/public/types.ts +++ b/src/Bundle/ChillTicketBundle/src/Resources/public/types.ts @@ -6,15 +6,19 @@ import { } from "ChillMainAssets/types"; import { Person } from "ChillPersonAssets/types"; import { Thirdparty } from "../../../../ChillThirdPartyBundle/Resources/public/types"; +import { StoredObject } from "ChillDocStoreAssets/types"; export interface Motive { type: "ticket_motive"; id: number; active: boolean; label: TranslatableString; + makeTicketEmergency: TicketEmergencyState; + storedObjects: StoredObject[]; + supplementaryComments: { label: string }[]; } -export type TicketState = "open" | "closed"; +export type TicketState = "open" | "closed" | "close"; export type TicketEmergencyState = "yes" | "no"; @@ -55,9 +59,7 @@ export interface Comment { updatedBy: User | null; updatedAt: DateTime | null; deleted: boolean; - supplementaryComments: { - label: string; - }; + supplementaryComments: { label: string }[]; } export interface AddresseeHistory { @@ -162,7 +164,7 @@ export interface TicketFilters { byCreatedAfter: string; byCreatedBefore: string; byResponseTimeExceeded: boolean; - byMyTickets: boolean; + byAddresseeToMe: boolean; } export interface TicketFilterParams { @@ -173,5 +175,12 @@ export interface TicketFilterParams { byCreatedAfter?: string; byCreatedBefore?: string; byResponseTimeExceeded?: string; - byMyTickets?: boolean; + byAddresseeToMe?: boolean; +} + +export interface TicketInitForm { + content: string; + motive?: Motive; + persons: Person[]; + caller: Person | null; } diff --git a/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/App.vue b/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/App.vue index a024bdeb3..ed3e489e8 100644 --- a/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/App.vue +++ b/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/App.vue @@ -1,25 +1,68 @@ - + diff --git a/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/components/ActionToolbarComponent.vue b/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/components/ActionToolbarComponent.vue index d78e8e2a5..589066e3d 100644 --- a/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/components/ActionToolbarComponent.vue +++ b/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/components/ActionToolbarComponent.vue @@ -29,6 +29,7 @@
{ return returnPath; }); -const motive = ref( - ticket.value.currentMotive ? ticket.value.currentMotive : ({} as Motive), -); +const motive = ref(ticket.value.currentMotive as Motive); const content = ref("" as Comment["content"]); const addressees = ref(ticket.value.currentAddressees as UserGroupOrUser[]); const persons = ref(ticket.value.currentPersons as Person[]); const caller = ref(ticket.value.caller as Person); async function submitAction() { - try { - switch (activeTab.value) { - case "add_comment": - if (!content.value) { - toast.error(trans(CHILL_TICKET_TICKET_ADD_COMMENT_ERROR)); - } else { - await store.dispatch("createComment", { - ticketId: ticket.value.id, - content: content.value, - }); - content.value = ""; - activeTab.value = ""; - toast.success(trans(CHILL_TICKET_TICKET_ADD_COMMENT_SUCCESS)); - } - break; - case "set_motive": - if (!motive.value.id) { - toast.error(trans(CHILL_TICKET_TICKET_SET_MOTIVE_ERROR)); - } else { - await store.dispatch("createMotive", { - ticketId: ticket.value.id, - motive: motive.value, - }); - activeTab.value = ""; - toast.success(trans(CHILL_TICKET_TICKET_SET_MOTIVE_SUCCESS)); - } - break; - case "addressees_state": - if (!addressees.value.length) { - toast.error(trans(CHILL_TICKET_TICKET_ADD_ADDRESSEE_ERROR)); - } else { - await store.dispatch("setAdressees", { - ticketId: ticket.value.id, - addressees: addressees.value, - }); + switch (activeTab.value) { + case "add_comment": + if (!content.value) { + toast.error(trans(CHILL_TICKET_TICKET_ADD_COMMENT_ERROR)); + } else { + await store.dispatch("createComment", content.value); + content.value = ""; + activeTab.value = ""; + toast.success(trans(CHILL_TICKET_TICKET_ADD_COMMENT_SUCCESS)); + } + break; + case "set_motive": + if (!motive.value) { + toast.error(trans(CHILL_TICKET_TICKET_SET_MOTIVE_ERROR)); + } else { + await store.dispatch("createMotive", motive.value); + activeTab.value = ""; + toast.success(trans(CHILL_TICKET_TICKET_SET_MOTIVE_SUCCESS)); + } + break; + case "addressees_state": + if (addressees.value.length) { + try { + await store.dispatch( + "setAddressees", + addressees.value as UserGroupOrUser[], + ); activeTab.value = ""; toast.success(trans(CHILL_TICKET_TICKET_ADD_ADDRESSEE_SUCCESS)); + } catch (error) { + console.error(trans(CHILL_TICKET_TICKET_ADD_ADDRESSEE_ERROR), error); + toast.error(trans(CHILL_TICKET_TICKET_ADD_ADDRESSEE_ERROR)); } - break; - case "persons_state": - await store.dispatch("setPersons", { - persons: persons.value, - }); - await store.dispatch("fetchTicketsByPerson"); - activeTab.value = ""; + } else { + await store.dispatch("setAddressees", [] as UserGroupOrUser[]); + toast.success(trans(CHILL_TICKET_TICKET_ADD_ADDRESSEE_SUCCESS)); + } + break; + case "persons_state": + if (persons.value.length) { + await store.dispatch("setPersons", persons.value); + try { + await store.dispatch("fetchTicketList", { + byPerson: persons.value.map((person) => person.id), + }); + activeTab.value = ""; + toast.success(trans(CHILL_TICKET_TICKET_SET_PERSONS_SUCCESS)); + } catch (error) { + console.error(trans(CHILL_TICKET_TICKET_SET_PERSONS_ERROR), error); + toast.error(trans(CHILL_TICKET_TICKET_SET_PERSONS_ERROR)); + } + } else { + store.dispatch("setPersons", [] as Person[]); toast.success(trans(CHILL_TICKET_TICKET_SET_PERSONS_SUCCESS)); - break; - } - } catch (error) { - toast.error(error as string); + } + break; } } async function closeTicket() { try { - await store.dispatch("closeTicket"); + await store.dispatch("setTicketState", "close"); closeAllActions(); toast.success(trans(CHILL_TICKET_TICKET_ACTIONS_TOOLBAR_CLOSE_SUCCESS)); } catch (error) { @@ -324,7 +330,7 @@ async function closeTicket() { async function reopenTicket() { try { - await store.dispatch("reopenTicket"); + await store.dispatch("setTicketState", "open"); toast.success(trans(CHILL_TICKET_TICKET_ACTIONS_TOOLBAR_REOPEN_SUCCESS)); } catch (error) { console.error(error); @@ -337,7 +343,7 @@ function closeAllActions() { } watch(caller, async (newCaller) => { - await store.dispatch("setCaller", { caller: newCaller }); + await store.dispatch("setCaller", newCaller); await store.dispatch("getSuggestedPersons"); }); diff --git a/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/components/BannerComponent.vue b/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/components/BannerComponent.vue index 975e26fae..f48e6aec9 100644 --- a/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/components/BannerComponent.vue +++ b/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/components/BannerComponent.vue @@ -8,31 +8,21 @@

- {{ ticket.currentPersons.map((person) => person.text).join(", ") }} + {{ + ticket.currentPersons + .map((person: Person) => person.text) + .join(", ") + }}

- - - {{ trans(CHILL_TICKET_TICKET_BANNER_OPEN) }} - - - {{ trans(CHILL_TICKET_TICKET_BANNER_CLOSED) }} - +

@@ -102,26 +92,33 @@ diff --git a/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/components/Comment/CommentComponent.vue b/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/components/Comment/CommentComponent.vue index 8723c7c72..da5ca4ccb 100644 --- a/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/components/Comment/CommentComponent.vue +++ b/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/components/Comment/CommentComponent.vue @@ -1,19 +1,103 @@ diff --git a/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/components/PelotonComponent.vue b/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/components/PelotonComponent.vue new file mode 100644 index 000000000..b50682a02 --- /dev/null +++ b/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/components/PelotonComponent.vue @@ -0,0 +1,262 @@ + + + + + diff --git a/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/components/PreviousTicketsComponent.vue b/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/components/PreviousTicketsComponent.vue index cd826d9e9..8c33d804c 100644 --- a/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/components/PreviousTicketsComponent.vue +++ b/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketApp/components/PreviousTicketsComponent.vue @@ -37,8 +37,10 @@ diff --git a/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketList/index.ts b/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketList/index.ts index 328f7362a..b59961d66 100644 --- a/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketList/index.ts +++ b/src/Bundle/ChillTicketBundle/src/Resources/public/vuejs/TicketList/index.ts @@ -1,6 +1,8 @@ import App from "./App.vue"; import { createApp } from "vue"; import { store } from "../TicketApp/store"; +import VueToast from "vue-toast-notification"; +import "vue-toast-notification/dist/theme-sugar.css"; declare global { interface Window { @@ -12,4 +14,4 @@ const _app = createApp({ template: "", }); -_app.component("app", App).use(store).mount("#ticketList"); +_app.component("app", App).use(store).use(VueToast).mount("#ticketList"); diff --git a/src/Bundle/ChillTicketBundle/src/translations/messages+intl-icu.fr.yml b/src/Bundle/ChillTicketBundle/src/translations/messages+intl-icu.fr.yml index 2c2285426..bad68a2de 100644 --- a/src/Bundle/ChillTicketBundle/src/translations/messages+intl-icu.fr.yml +++ b/src/Bundle/ChillTicketBundle/src/translations/messages+intl-icu.fr.yml @@ -1,3 +1,4 @@ +restore: Restaurer chill_ticket: list: title: Tickets @@ -5,6 +6,7 @@ chill_ticket: no_tickets: "Aucun ticket" loading_ticket: "Chargement des tickets..." loading_ticket_details: "Chargement de l'historique du ticket..." + error_loading_ticket: "Erreur lors du chargement des ticket" load_more: "Voir plus..." addressees: "Attribué à" persons: "Usager concernés" @@ -15,7 +17,7 @@ chill_ticket: created_between: Créés entre state_change: État actuel title: "Filtres des tickets" - persons_concerned: "Usager concernés" + persons_concerned: "Usagers concernés" by_person: "Par personne" by_motives: "Par motifs" current_state: "État actuel" @@ -26,13 +28,19 @@ chill_ticket: created_after: "Créé après" created_before: "Créé avant" response_time_exceeded: "Temps de réponse dépassé" - response_time_warning: 'Attention : Ce filtre supprime automatiquement les filtres "État actuel" et "Créé avant"' + response_time_warning: 'Attention : ce filtre désactive les filtres "par dates" et affiche uniquement les tickets ouverts' reset: "Réinitialiser" apply: "Appliquer les filtres" remove: "Supprimer" result: "{count, plural, =0 {Aucun résultat} =1 {resultat} other {resultats}}" ticket: + init_form: + title: "Ajouter des informations sur le ticket" + submit: "Mettre à jour le ticket" + reset: "Réinitialiser" + success: "Ticket mis à jour avec succès" + error: "Veuillez remplir tous les champs obligatoires" history: add_comment: "Nouveau commentaire" addressees_state: "Attributions" @@ -42,6 +50,7 @@ chill_ticket: create_ticket: "Ticket créé" state_change: "" emergency_change: "" + deleted: "Supprimé" previous_tickets: "Précédents tickets" actions_toolbar: cancel: "Annuler" @@ -52,6 +61,13 @@ chill_ticket: reopen: "Rouvrir" reopen_success: "Rouverture du ticket réussie" reopen_error: "Erreur lors de la rouverture du ticket" + restore_comment: + success: "Commentaire restauré" + delete_comment: + success: "Commentaire supprimé" + edit_comment: + title: "Éditer le commentaire" + success: "Commentaire modifié" add_comment: title: "Commentaire" label: "Ajouter un commentaire" @@ -78,8 +94,8 @@ chill_ticket: success: "Appelants et usagers mis à jour" error: "Aucun usager sélectionné" banner: - person: "{count, plural, =0 {Aucun usager concerné} =1 {Usager concerné} other {Usagers concernés}}" - speaker: "{count, plural, =0 {Aucun intervenant} =1 {Attribué à} other {Attribués à}}" + person: "{count, plural, =0 {Aucun usager impliqué} =1 {Usager impliqué} other {Usagers impliqués}}" + speaker: "{count, plural, =0 {Aucun intervenant} =1 {Intervenant attribué} other {Intervenants attribués}}" caller: "{count, plural, =0 {Aucun appelant} =1 {Appelant} other {Appelants}}" open: "Ouvert" closed: "Fermé" @@ -87,27 +103,40 @@ chill_ticket: and: "et" days: >- {count, plural, - =0 {aucun jour} - =1 {1 jour} - other {# jours} + =0 {aucun jour} + =1 {1 jour} + other {# jours} } hours: >- {count, plural, - =0 {aucune heure} - =1 {1 heure} - other {# heures} + =0 {aucune heure} + =1 {1 heure} + other {# heures} } minutes: >- {count, plural, - =0 {aucune minute} - =1 {1 minute} - other {# minutes} + =0 {aucune minute} + =1 {1 minute} + other {# minutes} } seconds: >- {count, plural, - =0 {aucune seconde} - =1 {1 seconde} - other {# secondes} + =0 {aucune seconde} + =1 {1 seconde} + other {# secondes} } - no_motive: "Pas de motif" + no_motive: "Aucun motif" emergency: "URGENT" + emergency_success: "Ticket marqué comme urgent" + emergency_error: "Erreur lors de la tentative de marquage du ticket comme urgent" + no_emergency_success: "Ticket marqué comme non urgent" + no_emergency_error: "Erreur lors de la tentative de marquage du ticket comme non urgent" + peloton: + loading: "Chargement..." + loading_document: "Chargement du document..." + error_loading: "Erreur lors du chargement du document." + error_not_ready: "Le document n'est pas prêt ou accessible." + unsupported_type: "Type de document non supporté pour l'affichage." + open_new_tab: "Ouvrir dans un nouvel onglet" + iframe_not_supported: "Votre navigateur ne supporte pas les iframes." + click_to_open_pdf: "Cliquez ici pour ouvrir le PDF"