| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- <template>
- <div class="centered-box">
- <div>
- <h3>Planning Actif</h3>
- <styled-input label="Identifiant" :modelValue="evenement.uuid" disabled />
- <styled-input
- label="Nom de l'événement"
- :modelValue="evenement.name"
- @input="inputListener($event, 'name')"
- />
- <datepicker label="Début" target="hour" v-model="start" />
- <datepicker label="Fin" target="hour" v-model="end" />
- <div class="actions" style="text-align: center">
- <button class="btn success" @click="$emit('solve')">
- <i class="material-icons">play_arrow</i> Résoudre la plannification
- </button>
- <div
- class="tooltiped tooltiped--medium"
- style="
- cursor: pointer;
- display: inline-block;
- vertical-align: middle;
- margin-left: 8px;
- color: var(--color-accent-400);
- "
- aria-tooltip="Comment ça marche"
- >
- <i class="material-icons" @click="$router.push('docs')">info</i>
- </div>
- </div>
- <div class="actions" style="margin-top: 8px">
- <button class="btn primary small" @click="$emit('save')">
- <i class="material-icons">save</i> Sauvegarder
- </button>
- <button class="btn primary small" @click="exportStateToJson">
- <i class="material-icons">download</i> Télécharger les données
- </button>
- <button class="btn primary small" @click="clickInput">
- <i class="material-icons">upload</i>Import des données
- </button>
- <button
- class="btn small icon error tooltiped tooltiped--medium"
- @click="toggleModal"
- aria-tooltip="Nettoyer le planning"
- >
- <i class="material-icons">event_busy</i>
- </button>
- <input
- ref="input"
- style="display: none"
- type="file"
- accept=".json,application/json"
- @change="importJsonState"
- />
- </div>
- <div class="actions">
- <button class="btn primary small" @click="copyLink">
- <i class="material-icons">link</i>Lien pour les bénévoles
- </button>
- <a v-if="inscription" class="btn primary small" :href="inscription">
- <i class="material-icons">launch</i>Page pour l'inscription
- </a>
- </div>
- <div class="actions">
- <button class="btn primary small" @click="duplicateEvent">
- <i class="material-icons">content_copy</i>Dupliquer l'événement
- </button>
- </div>
- </div>
- <div v-if="showModal" class="modal" @click="toggleModal">
- <div class="modal-content" @click="(e) => e.stopPropagation()">
- <h3>Confirmer la suppression des créneaux</h3>
- <p>
- Êtes vous sûr de vouloir supprimer tout les créneaux qui ne sont pas entre le<br />
- {{ start.format("dddd DD MMMM YYYY, HH:mm") }}<br />
- et le <br />{{ end.format("dddd DD MMMM YYYY, HH:mm") }}
- </p>
- <div class="actions" style="margin-top: 8px; text-align: right">
- <button class="btn error small" @click="clearCreneau">
- <i class="material-icons">delete_forever</i>Confirmer
- </button>
- <button class="btn primary small" @click="toggleModal">
- <i class="material-icons">close</i>Annuler
- </button>
- </div>
- </div>
- </div>
- <div>
- <h2>
- Version antérieurs
- <button
- class="btn icon small secondary tooltiped tooltiped--medium"
- aria-tooltip="Rafraichir le liste des versions"
- @click="updatePlanningVersions"
- >
- <i class="material-icons">refresh</i>
- </button>
- </h2>
- <evenement-data-table
- :versions="planningVersions"
- @loadVersion="loadVersion"
- ></evenement-data-table>
- </div>
- </div>
- </template>
- <script lang="ts">
- import { Dayjs } from "dayjs";
- import { v4 as uuidv4 } from "uuid";
- import { defineComponent } from "vue";
- import { MutationTypes } from "@/store/Mutations";
- import Evenement from "@/models/Evenement";
- import EvenementVersion from "@/models/EvenementVersion";
- import styledInput from "@/components/Form/Input.vue";
- import datepicker from "@/components/Form/DatePicker.vue";
- import EvenementDataTable from "@/components/EvenementDataTable.vue";
- import updatePlanningVersions from "@/mixins/updatePlanningVersions";
- import fetchPlanningVersion from "@/mixins/fetchPlanningVersion";
- import Toast from "@/utils/Toast";
- import commit from "@/mixins/commit";
- const API_URL = process.env.VUE_APP_API_URL;
- export default defineComponent({
- mixins: [updatePlanningVersions, fetchPlanningVersion, commit],
- components: { styledInput, datepicker, EvenementDataTable },
- data() {
- return {
- start: null as Dayjs | null,
- end: null as Dayjs | null,
- showModal: false,
- };
- },
- watch: {
- start(val: Dayjs, oldval) {
- if (oldval && !val.isSame(this.evenement.startingDate)) {
- this.commit(MutationTypes.editEvenement, {
- field: "start",
- value: val.toDate(),
- });
- }
- },
- end(val: Dayjs, oldval) {
- if (oldval && !val.isSame(this.evenement.endingDate, "minutes")) {
- this.commit(MutationTypes.editEvenement, {
- field: "end",
- value: val.subtract(1, "h").endOf("h").toDate(),
- });
- }
- },
- "evenement.start": function () {
- this.initDate();
- },
- "evenement.end": function () {
- this.initDate();
- },
- },
- computed: {
- evenement(): Evenement {
- return this.$store.state.evenement;
- },
- planningVersions(): Array<EvenementVersion> {
- return this.$store.state.history;
- },
- inscription(): string {
- return this.planningVersions.length > 0 ? `/inscription/${this.evenement.uuid}` : "";
- },
- },
- methods: {
- copyLink() {
- const link = `${API_URL}planning/display/${this.evenement.uuid}`;
- navigator.clipboard.writeText(link);
- Toast({
- html: `Lien copié <a href="http://${link}" target="_blank"><i class="material-icons" style="vertical-align: middle;margin-left: 8px;">launch</i></a>`,
- displayLength: 5000,
- });
- },
- loadVersion(version: EvenementVersion) {
- this.fetchPlanningVersions(
- `${API_URL}api/evenements/history/${version.uuid}/content/${version.id}`
- ).then(() => {
- Toast({ html: "Version du " + version.lastModified + " chargée" });
- });
- },
- toggleModal() {
- this.showModal = !this.showModal;
- },
- duplicateEvent() {
- if (
- confirm(
- "Êtes vous sûr de vouloir copié toutes les données relatives à l'événement " +
- this.evenement.name
- )
- ) {
- this.commit(MutationTypes.editEvenement, { field: "uuid", value: uuidv4() });
- this.commit(MutationTypes.editEvenement, {
- field: "name",
- value: "Copie de " + this.evenement.name,
- });
- this.$emit("save");
- }
- },
- initDate() {
- if (this.evenement) {
- this.start = this.evenement.startingDate;
- this.end = this.evenement.endingDate;
- }
- },
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- inputListener(event: any, field: keyof Evenement) {
- this.commit(MutationTypes.editEvenement, {
- field: field,
- value: event.target.value,
- });
- },
- exportStateToJson() {
- this.$emit("export");
- },
- clickInput() {
- (this.$refs["input"] as HTMLElement).click();
- },
- importJsonState(event: InputEvent) {
- const files = (event.target as HTMLInputElement).files;
- if (files) {
- const file = files[0];
- if (file) {
- var reader = new FileReader();
- reader.onload = () => {
- var obj = JSON.parse(reader.result as string);
- this.$emit("import", obj);
- };
- reader.readAsText(file);
- }
- }
- },
- clearCreneau() {
- this.showModal = false;
- const max = this.$store.state.evenement.end;
- const min = this.$store.state.evenement.start;
- const toBeRemoved = this.$store.state.creneauList.filter((c) => max < c.start || c.end < min);
- for (let elt of toBeRemoved) {
- this.commit(MutationTypes.removeCreneau, elt.id);
- }
- },
- },
- mounted() {
- this.initDate();
- },
- });
- </script>
- <style scoped>
- .centered-box {
- display: flex;
- justify-content: center;
- align-items: center;
- margin: 20px;
- flex-direction: column;
- }
- .centered-box > div {
- box-shadow: 0 0 2px var(--color-neutral-400);
- padding: 16px;
- margin-bottom: 32px;
- }
- .actions {
- margin-top: 8px;
- text-align: center;
- }
- h2 {
- margin-top: 0px;
- margin-left: 8px;
- }
- table {
- margin: 8px;
- max-height: 800px;
- overflow: auto;
- }
- </style>
|