Merge branch '1849-1848-1920-1921-fix-bugs' into 'ticket-app-master'

1849 1848 1920 1921 fix bugs

See merge request Chill-Projet/chill-bundles!940
This commit is contained in:
2025-12-12 09:17:22 +00:00
6 changed files with 284 additions and 311 deletions

View File

@@ -30,7 +30,7 @@
<Modal <Modal
v-if="showTicketInitFormModal" v-if="showTicketInitFormModal"
:show="showTicketInitFormModal" :show="showTicketInitFormModal"
modal-dialog-class="modal-lg" :modal-dialog-class="modalDialogClass"
@close="closeModal" @close="closeModal"
> >
<template #header> <template #header>
@@ -41,18 +41,24 @@
<template #body> <template #body>
<ticket-init-form-component <ticket-init-form-component
v-model="ticketForm"
:ticket="ticket" :ticket="ticket"
:motives="motives" :motives="motives"
:suggested-persons="suggestedPersons" :suggested-persons="suggestedPersons"
@submit="handleFormSubmit" @submit="handleFormSubmit"
/> />
</template> </template>
<template #footer>
<button class="btn btn-primary" @click="handleFormSubmit">
{{ trans(CHILL_TICKET_TICKET_INIT_FORM_SUBMIT) }}
</button>
</template>
</Modal> </Modal>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useToast } from "vue-toast-notification"; import { useToast } from "vue-toast-notification";
import { computed, onMounted, ref } from "vue"; import { computed, onMounted, onUnmounted, ref } from "vue";
import { useStore } from "vuex"; import { useStore } from "vuex";
// Types // Types
@@ -71,6 +77,7 @@ import ToggleComponent from "../TicketList/components/ToggleComponent.vue";
// Translations // Translations
import { import {
trans, trans,
CHILL_TICKET_TICKET_INIT_FORM_SUBMIT,
CHILL_TICKET_TICKET_INIT_FORM_TITLE, CHILL_TICKET_TICKET_INIT_FORM_TITLE,
CHILL_TICKET_TICKET_INIT_FORM_SUCCESS, CHILL_TICKET_TICKET_INIT_FORM_SUCCESS,
CHILL_TICKET_TICKET_INIT_FORM_ERROR, CHILL_TICKET_TICKET_INIT_FORM_ERROR,
@@ -96,26 +103,49 @@ const showTicketInitFormModal = ref(false);
const loading = ref(true); const loading = ref(true);
const refreshKey = ref(0); const refreshKey = ref(0);
async function handleFormSubmit(ticketForm: TicketInitForm) { // ticketForm réactif pour v-model
const ticketForm = ref({
content: "",
addressees: ticket.value?.currentAddressees,
motive: ticket.value?.currentMotive,
persons: ticket.value?.currentPersons,
caller: ticket.value?.caller,
emergency: ticket.value?.emergency,
} as TicketInitForm);
const modalDialogClass = ref(
window.innerWidth < 990 ? "modal-fullscreen" : "modal-lg",
);
function updateModalClass() {
modalDialogClass.value =
window.innerWidth < 990 ? "modal-fullscreen" : "modal-lg";
}
window.addEventListener("resize", updateModalClass);
async function handleFormSubmit() {
try { try {
if (!ticketForm.motive || ticketForm.content.trim() === "") { if (!ticketForm.value.motive || ticketForm.value.content.trim() === "") {
toast.warning(trans(CHILL_TICKET_TICKET_INIT_FORM_WARNING)); toast.warning(trans(CHILL_TICKET_TICKET_INIT_FORM_WARNING));
return; return;
} }
if (ticketForm.motive) { if (ticketForm.value.motive) {
await store.dispatch("createMotive", ticketForm.motive); await store.dispatch("createMotive", ticketForm.value.motive);
} }
if (ticketForm.content.trim() !== "") { if (ticketForm.value.content.trim() !== "") {
await store.dispatch("createComment", ticketForm.content); await store.dispatch("createComment", ticketForm.value.content);
} }
// Ne pas mettre à jour emergency si le motif force l'état d'urgence // Ne pas mettre à jour emergency si le motif force l'état d'urgence
if (ticketForm.motive && !ticketForm.motive.makeTicketEmergency) { if (
await store.dispatch("setEmergency", ticketForm.emergency); ticketForm.value.motive &&
!ticketForm.value.motive.makeTicketEmergency
) {
await store.dispatch("setEmergency", ticketForm.value.emergency);
} }
await store.dispatch("setAddressees", ticketForm.addressees); await store.dispatch("setAddressees", ticketForm.value.addressees);
await store.dispatch("setPersons", ticketForm.persons); await store.dispatch("setPersons", ticketForm.value.persons);
// Forcer le rafraîchissement des composants // Forcer le rafraîchissement des composants
refreshKey.value++; refreshKey.value++;
@@ -147,6 +177,10 @@ onMounted(() => {
loading.value = false; loading.value = false;
} }
}); });
onUnmounted(() => {
window.removeEventListener("resize", updateModalClass);
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -7,7 +7,6 @@
class="btn btn-link p-0" class="btn btn-link p-0"
style=" style="
position: absolute; position: absolute;
top: 0.5rem;
right: 0.5rem; right: 0.5rem;
font-size: 2rem; font-size: 2rem;
line-height: 1; line-height: 1;
@@ -26,7 +25,7 @@
</label> </label>
</div> </div>
<form @submit.prevent="submitAction"> <form class="p-2" @submit.prevent="submitAction">
<comment-editor-component <comment-editor-component
v-model="content" v-model="content"
:motive="motive" :motive="motive"

View File

@@ -18,7 +18,7 @@
<select <select
v-model="selectedStoredObject" v-model="selectedStoredObject"
class="form-select" class="form-select"
@change="onSelectionChange" @change="fetchDocument"
style="max-width: 400px" style="max-width: 400px"
> >
<option <option
@@ -125,22 +125,7 @@ const isLoading = ref<boolean>(false);
const error = ref<string>(""); const error = ref<string>("");
const showPelotonsModal = ref<boolean>(false); const showPelotonsModal = ref<boolean>(false);
watch( async function fetchDocument() {
() => props.storedObjects,
(newStoredObjects) => {
if (
newStoredObjects &&
newStoredObjects.length > 0 &&
!selectedStoredObject.value
) {
selectedStoredObject.value = newStoredObjects[0];
onSelectionChange();
}
},
{ immediate: true },
);
async function onSelectionChange() {
if (!selectedStoredObject.value) { if (!selectedStoredObject.value) {
cleanupPrevious(); cleanupPrevious();
documentType.value = ""; documentType.value = "";
@@ -162,7 +147,6 @@ async function onSelectionChange() {
selectedStoredObject.value, selectedStoredObject.value,
selectedStoredObject.value.currentVersion, selectedStoredObject.value.currentVersion,
); );
console.log("downloadInfo", downloadInfo);
const rawResponse = await window.fetch(downloadInfo.url); const rawResponse = await window.fetch(downloadInfo.url);
if (!rawResponse.ok) { if (!rawResponse.ok) {
@@ -228,22 +212,22 @@ function cleanupPrevious() {
documentUrl.value = ""; documentUrl.value = "";
} }
} }
function handleClick() { function handleClick() {
fetchDocument();
showPelotonsModal.value = true; showPelotonsModal.value = true;
if (
!selectedStoredObject.value &&
props.storedObjects &&
props.storedObjects.length > 0
) {
selectedStoredObject.value = props.storedObjects[0];
onSelectionChange();
}
} }
function closeModal() { function closeModal() {
showPelotonsModal.value = false; showPelotonsModal.value = false;
} }
watch(
() => props.storedObjects,
(newStoredObjects) => {
selectedStoredObject.value = newStoredObjects ? newStoredObjects[0] : null;
},
{ immediate: true },
);
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -1,84 +1,73 @@
<template> <template>
<div class="card mb-4"> <div class="card mb-4">
<div class="card-body"> <div class="card-body">
<form @submit.prevent="submitForm"> <div class="mb-3">
<div class="mb-3"> <label class="form-label pe-2" for="emergency">
<label class="form-label pe-2" for="emergency"> {{ trans(CHILL_TICKET_LIST_FILTER_EMERGENCY) }}
{{ trans(CHILL_TICKET_LIST_FILTER_EMERGENCY) }} </label>
</label> <emergency-toggle-component v-model="isEmergency" class="float-end" />
<emergency-toggle-component v-model="isEmergency" class="float-end" /> </div>
</div>
<!-- Sélection du motif --> <!-- Sélection du motif -->
<div class="mb-3"> <div class="mb-3">
<label class="form-label">{{ <label class="form-label">{{
trans(CHILL_TICKET_TICKET_SET_MOTIVE_TITLE) trans(CHILL_TICKET_TICKET_SET_MOTIVE_TITLE)
}}</label> }}</label>
<motive-selector-component <motive-selector-component
v-model="ticketForm.motive" v-model="ticketForm.motive"
:motives="motives" :motives="motives"
/> />
</div> </div>
<!-- Sélection des personnes --> <!-- Sélection des personnes -->
<div class="row mb-3"> <div class="row mb-3">
<div class="col-md-6"> <div class="col-md-6">
<label class="form-label">
{{ trans(CHILL_TICKET_TICKET_SET_PERSONS_TITLE_CALLER) }}
</label>
<persons-selector-component
v-model="ticketForm.caller"
:suggested="[]"
:multiple="false"
:types="['person', 'thirdparty']"
:label="trans(CHILL_TICKET_TICKET_SET_PERSONS_CALLER_LABEL)"
/>
</div>
<div class="col-md-6">
<label class="form-label">
{{ trans(CHILL_TICKET_TICKET_SET_PERSONS_TITLE_PERSON) }}
</label>
<persons-selector-component
v-model="ticketForm.persons"
:suggested="suggestedPersons"
:multiple="true"
:types="['person']"
:label="trans(CHILL_TICKET_TICKET_SET_PERSONS_USER_LABEL)"
/>
</div>
</div>
<!-- Éditeur de commentaire -->
<div class="mb-3">
<label class="form-label">{{
trans(CHILL_TICKET_TICKET_ADD_COMMENT_TITLE)
}}</label>
<comment-editor-component
v-model="ticketForm.content"
:motive="ticketForm.motive ? ticketForm.motive : null"
/>
</div>
<!-- Attribution des tickets -->
<div class="mb-3">
<label class="form-label"> <label class="form-label">
{{ trans(CHILL_TICKET_TICKET_ADD_ADDRESSEE_TITLE) }} {{ trans(CHILL_TICKET_TICKET_SET_PERSONS_TITLE_CALLER) }}
</label> </label>
<addressee-selector-component <persons-selector-component
v-model="ticketForm.addressees" v-model="ticketForm.caller"
:suggested="userGroups" :suggested="[]"
:multiple="false"
:types="['person', 'thirdparty']"
:label="trans(CHILL_TICKET_TICKET_SET_PERSONS_CALLER_LABEL)"
/> />
</div> </div>
<!-- Boutons d'action --> <div class="col-md-6">
<div class="d-flex justify-content-end gap-2 mt-4"> <label class="form-label">
<button type="button" class="btn btn-secondary" @click="resetForm"> {{ trans(CHILL_TICKET_TICKET_SET_PERSONS_TITLE_PERSON) }}
{{ trans(CHILL_TICKET_TICKET_INIT_FORM_RESET) }} </label>
</button> <persons-selector-component
<button type="submit" class="btn btn-primary"> v-model="ticketForm.persons"
{{ trans(CHILL_TICKET_TICKET_INIT_FORM_SUBMIT) }} :suggested="suggestedPersons"
</button> :multiple="true"
:types="['person']"
:label="trans(CHILL_TICKET_TICKET_SET_PERSONS_USER_LABEL)"
/>
</div> </div>
</form> </div>
<!-- Éditeur de commentaire -->
<div class="mb-3">
<label class="form-label">{{
trans(CHILL_TICKET_TICKET_ADD_COMMENT_TITLE)
}}</label>
<comment-editor-component
v-model="ticketForm.content"
:motive="ticketForm.motive ? ticketForm.motive : null"
/>
</div>
<!-- Attribution des tickets -->
<div class="mb-3">
<label class="form-label">
{{ trans(CHILL_TICKET_TICKET_ADD_ADDRESSEE_TITLE) }}
</label>
<addressee-selector-component
v-model="ticketForm.addressees"
:suggested="userGroups"
/>
</div>
</div> </div>
</div> </div>
</template> </template>
@@ -94,20 +83,12 @@ import PersonsSelectorComponent from "./Person/PersonsSelectorComponent.vue";
import AddresseeSelectorComponent from "./Addressee/AddresseeSelectorComponent.vue"; import AddresseeSelectorComponent from "./Addressee/AddresseeSelectorComponent.vue";
import EmergencyToggleComponent from "./Emergency/EmergencyToggleComponent.vue"; import EmergencyToggleComponent from "./Emergency/EmergencyToggleComponent.vue";
// Types // Types
import { import { Motive, TicketInitForm } from "../../../types";
Motive,
MotiveWithParent,
Ticket,
TicketEmergencyState,
TicketInitForm,
} from "../../../types";
import { Person } from "ChillPersonAssets/types"; import { Person } from "ChillPersonAssets/types";
// Translations // Translations
import { import {
trans, trans,
CHILL_TICKET_TICKET_INIT_FORM_SUBMIT,
CHILL_TICKET_TICKET_INIT_FORM_RESET,
CHILL_TICKET_TICKET_SET_MOTIVE_TITLE, CHILL_TICKET_TICKET_SET_MOTIVE_TITLE,
CHILL_TICKET_TICKET_ADD_COMMENT_TITLE, CHILL_TICKET_TICKET_ADD_COMMENT_TITLE,
CHILL_TICKET_TICKET_SET_PERSONS_TITLE_CALLER, CHILL_TICKET_TICKET_SET_PERSONS_TITLE_CALLER,
@@ -117,32 +98,23 @@ import {
CHILL_TICKET_LIST_FILTER_EMERGENCY, CHILL_TICKET_LIST_FILTER_EMERGENCY,
CHILL_TICKET_TICKET_ADD_ADDRESSEE_TITLE, CHILL_TICKET_TICKET_ADD_ADDRESSEE_TITLE,
} from "translator"; } from "translator";
import { UserGroup, UserGroupOrUser } from "ChillMainAssets/types"; import { UserGroup } from "ChillMainAssets/types";
const props = defineProps<{ const props = defineProps<{
ticket: Ticket; modelValue: TicketInitForm;
motives: Motive[]; motives: Motive[];
suggestedPersons: Person[]; suggestedPersons: Person[];
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
"update:modelValue": [value: TicketInitForm]; "update:modelValue": [value: TicketInitForm];
submit: [formData: TicketInitForm];
}>(); }>();
const store = useStore(); const store = useStore();
const ticketForm = reactive({ const ticketForm = reactive({ ...props.modelValue });
content: "",
addressees: props.ticket.currentAddressees as UserGroupOrUser[],
motive: props.ticket.currentMotive as MotiveWithParent | null,
persons: props.ticket.currentPersons as Person[],
caller: props.ticket.caller as Person | null,
emergency: props.ticket.emergency as TicketEmergencyState,
} as TicketInitForm);
const isEmergency = ref<boolean>( const isEmergency = ref<boolean>(
props.ticket.emergency == "yes" ? true : false, props.modelValue.emergency == "yes" ? true : false,
); );
const userGroups = computed(() => store.getters.getUserGroups as UserGroup[]); const userGroups = computed(() => store.getters.getUserGroups as UserGroup[]);
@@ -155,23 +127,16 @@ watch(
}, },
); );
function submitForm() { watch(
emit("submit", { ticketForm,
content: ticketForm.content, (newVal) => {
motive: ticketForm.motive, emit("update:modelValue", {
addressees: [...ticketForm.addressees], ...newVal,
persons: [...ticketForm.persons], emergency: isEmergency.value ? "yes" : "no",
caller: ticketForm.caller, });
emergency: isEmergency.value ? "yes" : "no", },
}); { deep: true },
} );
function resetForm() {
ticketForm.content = "";
ticketForm.motive = null;
ticketForm.persons = [];
ticketForm.caller = null;
ticketForm.emergency = props.ticket.emergency as TicketEmergencyState;
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -3,13 +3,7 @@
<div class="card-body"> <div class="card-body">
<div class="wrap-header"> <div class="wrap-header">
<div class="row align-items-top"> <div class="row align-items-top">
<div <div class="col-6">
v-if="
null !== ticket.currentMotive &&
null !== ticket.currentMotive.parent
"
class="col-6"
>
<div class="small text-muted"> <div class="small text-muted">
{{ motiveHierarchyLabel(ticket.currentMotive) }} {{ motiveHierarchyLabel(ticket.currentMotive) }}
</div> </div>
@@ -100,8 +94,6 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { defineProps, defineEmits } from "vue";
// Types // Types
import { TicketSimple } from "../../../types"; import { TicketSimple } from "../../../types";
import { Person } from "ChillPersonAssets/types"; import { Person } from "ChillPersonAssets/types";

View File

@@ -1,156 +1,155 @@
restore: Restaurer restore: Restaurer
chill_ticket: chill_ticket:
list: list:
title: "Tickets" title: "Tickets"
title_with_name: "{name, select, null {Tickets} undefined {Tickets} other {Tickets de {name}}}" title_with_name: "{name, select, null {Tickets} undefined {Tickets} other {Tickets de {name}}}"
title_menu: "Tickets de l'usager" title_menu: "Tickets de l'usager"
show_all_history: "Afficher tout l'historique" show_all_history: "Afficher tout l'historique"
title_previous_tickets: "{name, select, other {Précédent ticket de {name}} undefined {Précédent ticket}}" title_previous_tickets: "{name, select, other {Précédent ticket de {name}} undefined {Précédent ticket}}"
no_tickets: "Aucun ticket" no_tickets: "Aucun ticket"
loading_ticket: "Chargement des tickets..." loading_ticket: "Chargement des tickets..."
loading_ticket_details: "Chargement de l'historique du ticket..." loading_ticket_details: "Chargement de l'historique du ticket..."
error_loading_ticket: "Erreur lors du chargement des ticket" error_loading_ticket: "Erreur lors du chargement des ticket"
load_more: "Voir plus..." load_more: "Voir plus..."
addressees: "Destinataires" addressees: "Destinataires"
persons: "Usager concernés" persons: "Usager concernés"
callers: "Appelants" callers: "Appelants"
filter: filter:
to_me: Tickets qui me sont destinés to_me: Tickets qui me sont destinés
in_alert: Tickets en alerte (délai de résolution dépassé) in_alert: Tickets en alerte (délai de résolution dépassé)
created_between: Créés entre created_between: Créés entre
state_change: État actuel state_change: État actuel
title: "Filtres des tickets" title: "Filtres des tickets"
persons_concerned: "Usagers concernés" persons_concerned: "Usagers concernés"
by_person: "Par personne" by_person: "Par personne"
creators: "Créateurs" creators: "Créateurs"
by_creator: "Par créateur" by_creator: "Par créateur"
addressees: "Par destinataire" addressees: "Par destinataire"
by_addressees: "Par destinataire" by_addressees: "Par destinataire"
by_motives: "Par motifs" by_motives: "Par motifs"
by_ticket_id: "Par numéro de ticket" by_ticket_id: "Par numéro de ticket"
ticket_id: "Numéro de ticket" ticket_id: "Numéro de ticket"
current_state: "État actuel" current_state: "État actuel"
open: "Ouvert" open: "Ouvert"
closed: "Clôturé" closed: "Clôturé"
emergency: "Urgent" emergency: "Urgent"
no_emergency: "Non urgent" no_emergency: "Non urgent"
created_after: "Créé après" created_after: "Créé après"
created_before: "Créé avant" created_before: "Créé avant"
response_time_exceeded: "Temps de réponse dépassé" response_time_exceeded: "Temps de réponse dépassé"
response_time_warning: 'Attention : ce filtre désactive les filtres "par dates" et affiche uniquement les tickets ouverts' response_time_warning: 'Attention : ce filtre désactive les filtres "par dates" et affiche uniquement les tickets ouverts'
reset: "Réinitialiser" reset: "Réinitialiser"
apply: "Appliquer les filtres" apply: "Appliquer les filtres"
remove: "Supprimer" remove: "Supprimer"
result: "{count, plural, =0 {Aucun résultat} =1 {resultat} other {resultats}}" result: "{count, plural, =0 {Aucun résultat} =1 {resultat} other {resultats}}"
ticket: ticket:
init_form: init_form:
title: "Ajouter des informations sur le ticket" title: "Ajouter des informations sur le ticket"
submit: "Mettre à jour le ticket" submit: "Mettre à jour le ticket"
reset: "Réinitialiser" success: "Ticket mis à jour avec succès"
success: "Ticket mis à jour avec succès" error: "Veuillez remplir tous les champs obligatoires"
error: "Veuillez remplir tous les champs obligatoires" warning: "Veuillez remplir au minimum le motif et le commentaire"
warning: "Veuillez remplir au minimum le motif et le commentaire" history:
history: add_comment: "Commentaire ajouté"
add_comment: "Commentaire ajouté" addressees_state: "{count, plural, =0 {Destinataire supprimé} =1 {Destinataire ajouté} other {Destinataire ajoutés}}"
addressees_state: "{count, plural, =0 {Destinataire supprimé} =1 {Destinataire ajouté} other {Destinataire ajoutés}}" persons_state: "{count, plural, =0 {Usagers supprimés} =1 {Usager concerné ajouté} other {Usagers concernés ajoutés}}"
persons_state: "{count, plural, =0 {Usagers supprimés} =1 {Usager concerné ajouté} other {Usagers concernés ajoutés}}" set_caller: "{id, select, null {Appelant supprimé} other {Appelant ajouté}}"
set_caller: "{id, select, null {Appelant supprimé} other {Appelant ajouté}}" set_motive: "Motif ajouté"
set_motive: "Motif ajouté" create_ticket: "Ticket créé"
create_ticket: "Ticket créé" state_change: ""
state_change: "" emergency_change: ""
emergency_change: "" mask_comment: "Supprimer"
mask_comment: "Supprimer" previous_tickets: "Précédents tickets"
previous_tickets: "Précédents tickets" actions_toolbar:
actions_toolbar: cancel: "Annuler"
cancel: "Annuler" save: "Enregistrer"
save: "Enregistrer" close: "Clôturer"
close: "Clôturer" close_success: "Ticket clôturé"
close_success: "Ticket clôturé" close_error: "Erreur lors de la clotûre du ticket"
close_error: "Erreur lors de la clotûre du ticket" reopen: "Rouvrir"
reopen: "Rouvrir" reopen_success: "Rouverture du ticket réussie"
reopen_success: "Rouverture du ticket réussie" reopen_error: "Erreur lors de la rouverture du ticket"
reopen_error: "Erreur lors de la rouverture du ticket" visible_comment:
visible_comment: success: "Commentaire restauré"
success: "Commentaire restauré" mask_comment:
mask_comment: success: "Commentaire supprimé"
success: "Commentaire supprimé" hint: "Ce commentaire a été supprimé."
hint: "Ce commentaire a été supprimé." edit_comment:
edit_comment: title: "Éditer le commentaire"
title: "Éditer le commentaire" success: "Commentaire modifié"
success: "Commentaire modifié" add_comment:
add_comment: title: "Commentaire"
title: "Commentaire" label: "Ajouter un commentaire"
label: "Ajouter un commentaire" success: "Commentaire enregistré"
success: "Commentaire enregistré" content: "Ajouter un commentaire"
content: "Ajouter un commentaire" error: "Aucun commentaire ajouté"
error: "Aucun commentaire ajouté" set_motive:
set_motive: title: "Motif"
title: "Motif" label: "Choisir un motif"
label: "Choisir un motif" success: "Motif enregistré"
success: "Motif enregistré" error: "Aucun motif sélectionné"
error: "Aucun motif sélectionné" add_addressee:
add_addressee: title: "Attribuer"
title: "Attribuer" user_group_label: "Attribuer à un groupe"
user_group_label: "Attribuer à un groupe" user_label: "Attribuer à un ou plusieurs utilisateurs"
user_label: "Attribuer à un ou plusieurs utilisateurs" success: "Attribution effectuée"
success: "Attribution effectuée" error: "Aucun destinataire sélectionné"
error: "Aucun destinataire sélectionné" set_persons:
set_persons: title: "Appelant et usager(s)"
title: "Appelant et usager(s)" title_person: "Usager(s)"
title_person: "Usager(s)" title_caller: "Appelant"
title_caller: "Appelant" user_label: "Ajouter un usager"
user_label: "Ajouter un usager" caller_label: "Ajouter un appelant"
caller_label: "Ajouter un appelant" success: "Appelants et usagers mis à jour"
success: "Appelants et usagers mis à jour" error: "Aucun usager sélectionné"
error: "Aucun usager sélectionné" banner:
banner: person: "{count, plural, =0 {Aucun usager impliqué} =1 {Usager impliqué} other {Usagers impliqués}}"
person: "{count, plural, =0 {Aucun usager impliqué} =1 {Usager impliqué} other {Usagers impliqués}}" speaker: "{count, plural, =0 {Aucun destinataire} =1 {Destinataire} other {Destinataires}}"
speaker: "{count, plural, =0 {Aucun destinataire} =1 {Destinataire} other {Destinataires}}" caller: "{count, plural, =0 {Aucun appelant} =1 {Appelant} other {Appelants}}"
caller: "{count, plural, =0 {Aucun appelant} =1 {Appelant} other {Appelants}}" open: "Ouvert"
open: "Ouvert" closed: "Clôturé"
closed: "Clôturé" since: "Depuis {time}"
since: "Depuis {time}" and: "et"
and: "et" days: >-
days: >- {count, plural,
{count, plural, =0 {aucun jour}
=0 {aucun jour} =1 {1 jour}
=1 {1 jour} other {# jours}
other {# jours} }
} hours: >-
hours: >- {count, plural,
{count, plural, =0 {aucune heure}
=0 {aucune heure} =1 {1 heure}
=1 {1 heure} other {# heures}
other {# heures} }
} minutes: >-
minutes: >- {count, plural,
{count, plural, =0 {aucune minute}
=0 {aucune minute} =1 {1 minute}
=1 {1 minute} other {# minutes}
other {# minutes} }
} seconds: >-
seconds: >- {count, plural,
{count, plural, =0 {aucune seconde}
=0 {aucune seconde} =1 {1 seconde}
=1 {1 seconde} other {# secondes}
other {# secondes} }
} no_motive: "Aucun motif"
no_motive: "Aucun motif" emergency: "URGENT"
emergency: "URGENT" emergency_success: "Ticket marqué comme urgent"
emergency_success: "Ticket marqué comme urgent" emergency_error: "Erreur lors de la tentative de marquage du ticket 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_success: "Ticket marqué comme non urgent" no_emergency_error: "Erreur lors de la tentative de marquage du ticket comme non urgent"
no_emergency_error: "Erreur lors de la tentative de marquage du ticket comme non urgent" peloton:
peloton: loading: "Chargement..."
loading: "Chargement..." loading_document: "Chargement du document..."
loading_document: "Chargement du document..." error_loading: "Erreur lors du chargement du document."
error_loading: "Erreur lors du chargement du document." error_not_ready: "Le document n'est pas prêt ou accessible."
error_not_ready: "Le document n'est pas prêt ou accessible." unsupported_type: "Type de document non supporté pour l'affichage."
unsupported_type: "Type de document non supporté pour l'affichage." open_new_tab: "Ouvrir dans un nouvel onglet"
open_new_tab: "Ouvrir dans un nouvel onglet" iframe_not_supported: "Votre navigateur ne supporte pas les iframes."
iframe_not_supported: "Votre navigateur ne supporte pas les iframes." click_to_open_pdf: "Cliquez ici pour ouvrir le PDF"
click_to_open_pdf: "Cliquez ici pour ouvrir le PDF"
admin: admin:
ticket: ticket:
@@ -168,7 +167,7 @@ crud:
title_new: Nouveau motif title_new: Nouveau motif
title_edit: Modifier le motif title_edit: Modifier le motif
new: new:
"Create a new motive": "Créer un nouveau motif" "Create a new motive": "Créer un nouveau motif"
"Label": "Libellé" "Label": "Libellé"
"Active": "Actif" "Active": "Actif"