|
@@ -3,11 +3,36 @@
|
|
|
<div class="timeline">
|
|
<div class="timeline">
|
|
|
<div class="timelime-control">
|
|
<div class="timelime-control">
|
|
|
<h1>Planning global de l'événement</h1>
|
|
<h1>Planning global de l'événement</h1>
|
|
|
- <button class="btn primary"><i class="material-icons">upload_file</i></button>
|
|
|
|
|
- <button class="btn primary"><i class="material-icons">save</i></button>
|
|
|
|
|
|
|
+ <div class="actions">
|
|
|
|
|
+ <button class="btn icon small primary">
|
|
|
|
|
+ <i class="material-icons">upload_file</i>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ <button class="btn icon small primary"><i class="material-icons">save</i></button>
|
|
|
|
|
+ <button
|
|
|
|
|
+ class="btn small secondary"
|
|
|
|
|
+ @click="createCreneau"
|
|
|
|
|
+ :disabled="creneauGroupList.length == 0"
|
|
|
|
|
+ >
|
|
|
|
|
+ <i class="material-icons">create</i>Creneau
|
|
|
|
|
+ </button>
|
|
|
|
|
+ <button class="btn small secondary" @click="createRessource">
|
|
|
|
|
+ <i class="material-icons">create</i>Ligne
|
|
|
|
|
+ </button>
|
|
|
|
|
+ <button class="btn icon small primary" @click="zoom(1)">
|
|
|
|
|
+ <i class="material-icons">zoom_in</i>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ <button class="btn icon small primary" @click="zoom(-1)">
|
|
|
|
|
+ <i class="material-icons">zoom_out</i>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
<jc-timeline
|
|
<jc-timeline
|
|
|
ref="timeline"
|
|
ref="timeline"
|
|
|
|
|
+ :slotduration="slotduration"
|
|
|
|
|
+ :legendspan="legendspan"
|
|
|
|
|
+ :slotwidth="slotwidth"
|
|
|
|
|
+ start="2021-04-04T22:00:00.000Z"
|
|
|
|
|
+ end="2021-04-06T21:59:00.000Z"
|
|
|
@event-change="eventChangeHandler"
|
|
@event-change="eventChangeHandler"
|
|
|
@item-selected="selectionChangeHandler"
|
|
@item-selected="selectionChangeHandler"
|
|
|
@reorder-ressource="ressourceChangeHandler"
|
|
@reorder-ressource="ressourceChangeHandler"
|
|
@@ -17,7 +42,11 @@
|
|
|
<editeur-creneau
|
|
<editeur-creneau
|
|
|
v-if="currentCreneau"
|
|
v-if="currentCreneau"
|
|
|
class="editor"
|
|
class="editor"
|
|
|
- :creneauId="currentCreneau.id"
|
|
|
|
|
|
|
+ :creneau="currentCreneau"
|
|
|
|
|
+ @create="createCreneau"
|
|
|
|
|
+ @delete="deleteCreneau"
|
|
|
|
|
+ @duplicate="duplicateCreneau"
|
|
|
|
|
+ @edit="updateCreneau"
|
|
|
></editeur-creneau>
|
|
></editeur-creneau>
|
|
|
<editeur-ligne
|
|
<editeur-ligne
|
|
|
v-else
|
|
v-else
|
|
@@ -43,7 +72,11 @@ import { Ressource } from "jc-timeline";
|
|
|
import Creneau from "@/models/Creneau";
|
|
import Creneau from "@/models/Creneau";
|
|
|
import { MutationTypes } from "@/store/Mutations";
|
|
import { MutationTypes } from "@/store/Mutations";
|
|
|
import Selectable from "node_modules/jc-timeline/lib/utils/selectable";
|
|
import Selectable from "node_modules/jc-timeline/lib/utils/selectable";
|
|
|
|
|
+import toast from "@/utils/Toast";
|
|
|
|
|
|
|
|
|
|
+import * as dayjs from "dayjs";
|
|
|
|
|
+import "dayjs/locale/fr";
|
|
|
|
|
+dayjs.locale("fr");
|
|
|
type changePayload = {
|
|
type changePayload = {
|
|
|
items: Array<jcEvent>;
|
|
items: Array<jcEvent>;
|
|
|
};
|
|
};
|
|
@@ -60,15 +93,72 @@ export default defineComponent({
|
|
|
endDate: "",
|
|
endDate: "",
|
|
|
currentCreneau: undefined as Creneau | undefined,
|
|
currentCreneau: undefined as Creneau | undefined,
|
|
|
currentCreneauGroup: undefined as Ressource | undefined,
|
|
currentCreneauGroup: undefined as Ressource | undefined,
|
|
|
|
|
+ zoomLevel: 14,
|
|
|
|
|
+ slotduration: 30,
|
|
|
|
|
+ legendspan: 2,
|
|
|
|
|
+ slotwidth: 30,
|
|
|
};
|
|
};
|
|
|
},
|
|
},
|
|
|
methods: {
|
|
methods: {
|
|
|
|
|
+ createCreneau(): void {
|
|
|
|
|
+ const groupId = this.currentCreneau
|
|
|
|
|
+ ? this.currentCreneau.ressourceId
|
|
|
|
|
+ : this.currentCreneauGroup
|
|
|
|
|
+ ? this.currentCreneauGroup.id
|
|
|
|
|
+ : false;
|
|
|
|
|
+ if (groupId) {
|
|
|
|
|
+ const start = new Date(this.timeline.start);
|
|
|
|
|
+ const e = this.timeline.addEvent(
|
|
|
|
|
+ new jcEvent({
|
|
|
|
|
+ id: uuidv4(),
|
|
|
|
|
+ start: start,
|
|
|
|
|
+ end: new Date(start.getTime() + 1000 * 60 * 60),
|
|
|
|
|
+ ressourceId: groupId,
|
|
|
|
|
+ title: "Nouveau creneau",
|
|
|
|
|
+ })
|
|
|
|
|
+ );
|
|
|
|
|
+ if (e) {
|
|
|
|
|
+ this.timeline.clearSelectedItems();
|
|
|
|
|
+ e.selected = true;
|
|
|
|
|
+ const creneau = new Creneau({
|
|
|
|
|
+ event: e,
|
|
|
|
|
+ penibility: 12,
|
|
|
|
|
+ minAttendee: 1,
|
|
|
|
|
+ maxAttendee: 1,
|
|
|
|
|
+ benevoleIdList: [],
|
|
|
|
|
+ competencesIdList: [],
|
|
|
|
|
+ description: "",
|
|
|
|
|
+ });
|
|
|
|
|
+ this.$store.commit(MutationTypes.addCreneau, creneau);
|
|
|
|
|
+
|
|
|
|
|
+ this.currentCreneau = this.$store.getters.getCreneauById(creneau.id);
|
|
|
|
|
+ this.currentCreneauGroup = undefined;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ toast({
|
|
|
|
|
+ html:
|
|
|
|
|
+ "Erreur: Pas de ligne auquel associer un nouveau creneau.<br>" +
|
|
|
|
|
+ " Veuillez selectioné un créneau existant ou une ligne.",
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
createRessource(): void {
|
|
createRessource(): void {
|
|
|
const ressource = new Ressource({ id: uuidv4(), title: "Nouvelle ligne" });
|
|
const ressource = new Ressource({ id: uuidv4(), title: "Nouvelle ligne" });
|
|
|
this.$store.commit(MutationTypes.addCreneauGroup, ressource);
|
|
this.$store.commit(MutationTypes.addCreneauGroup, ressource);
|
|
|
- this.timeline.addRessource(ressource);
|
|
|
|
|
|
|
+ this.timeline.clearSelectedItems();
|
|
|
|
|
+ this.timeline.addRessource(ressource).selected = true;
|
|
|
this.currentCreneauGroup = ressource;
|
|
this.currentCreneauGroup = ressource;
|
|
|
},
|
|
},
|
|
|
|
|
+ duplicateCreneau(payload: Creneau) {
|
|
|
|
|
+ const newCreneau = new Creneau({
|
|
|
|
|
+ ...payload.toPlainObject(),
|
|
|
|
|
+ event: new jcEvent({ ...payload.event, id: uuidv4() }),
|
|
|
|
|
+ });
|
|
|
|
|
+ newCreneau.title = "Copy de " + newCreneau.title;
|
|
|
|
|
+ this.timeline.addEvent(newCreneau.event);
|
|
|
|
|
+ this.$store.commit(MutationTypes.addCreneau, newCreneau);
|
|
|
|
|
+ this.currentCreneau = newCreneau;
|
|
|
|
|
+ },
|
|
|
deleteRessource(): void {
|
|
deleteRessource(): void {
|
|
|
if (this.currentCreneauGroup) {
|
|
if (this.currentCreneauGroup) {
|
|
|
const contentRemoved = this.timeline.removeRessourceById(this.currentCreneauGroup.id);
|
|
const contentRemoved = this.timeline.removeRessourceById(this.currentCreneauGroup.id);
|
|
@@ -81,6 +171,12 @@ export default defineComponent({
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
|
|
+ deleteCreneau(): void {
|
|
|
|
|
+ if (this.currentCreneau) {
|
|
|
|
|
+ this.timeline.removeEventById(this.currentCreneau.id);
|
|
|
|
|
+ this.$store.commit(MutationTypes.removeCreneau, this.currentCreneau);
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
selectionChangeHandler(ev: CustomEvent) {
|
|
selectionChangeHandler(ev: CustomEvent) {
|
|
|
const elts = ev.detail.items as Array<Selectable>;
|
|
const elts = ev.detail.items as Array<Selectable>;
|
|
|
if (elts.length == 1) {
|
|
if (elts.length == 1) {
|
|
@@ -100,7 +196,9 @@ export default defineComponent({
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
eventChangeHandler(ev: CustomEvent<changePayload>) {
|
|
eventChangeHandler(ev: CustomEvent<changePayload>) {
|
|
|
|
|
+ this.currentCreneauGroup = undefined;
|
|
|
const jcEvents = ev.detail.items;
|
|
const jcEvents = ev.detail.items;
|
|
|
|
|
+
|
|
|
for (let index = 0; index < jcEvents.length; index++) {
|
|
for (let index = 0; index < jcEvents.length; index++) {
|
|
|
const element = jcEvents[index];
|
|
const element = jcEvents[index];
|
|
|
this.$store.commit(MutationTypes.editCreneau, {
|
|
this.$store.commit(MutationTypes.editCreneau, {
|
|
@@ -118,6 +216,7 @@ export default defineComponent({
|
|
|
field: "ressourceId",
|
|
field: "ressourceId",
|
|
|
value: element.ressourceId,
|
|
value: element.ressourceId,
|
|
|
});
|
|
});
|
|
|
|
|
+ this.currentCreneau = this.$store.getters.getCreneauById(element.id);
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
ressourceChangeHandler(ev: CustomEvent<{ ressources: Array<Ressource> }>) {
|
|
ressourceChangeHandler(ev: CustomEvent<{ ressources: Array<Ressource> }>) {
|
|
@@ -128,28 +227,59 @@ export default defineComponent({
|
|
|
field: K;
|
|
field: K;
|
|
|
value: Ressource[K];
|
|
value: Ressource[K];
|
|
|
}) {
|
|
}) {
|
|
|
- this.$store.commit(MutationTypes.editCreneauGroup, payload);
|
|
|
|
|
- const newRessource = this.$store.getters.getCreneauGroupById(payload.id);
|
|
|
|
|
- if (newRessource) {
|
|
|
|
|
- if (payload.field == "parent") {
|
|
|
|
|
- const content = this.timeline.removeRessourceById(payload.id);
|
|
|
|
|
- this.timeline.addRessources(
|
|
|
|
|
- content.ressources.map((o) => (o.id == payload.id ? newRessource : o))
|
|
|
|
|
- );
|
|
|
|
|
- this.timeline.addRessources(content.items);
|
|
|
|
|
- } else {
|
|
|
|
|
- this.timeline.updateLegend();
|
|
|
|
|
|
|
+ const prevState = this.$store.getters.getCreneauGroupById(payload.id);
|
|
|
|
|
+ if (prevState && prevState[payload.field] !== payload.value) {
|
|
|
|
|
+ const r = this.timeline.updateRessource(payload.id, payload.field, payload.value);
|
|
|
|
|
+ if (r) {
|
|
|
|
|
+ payload.value = r[payload.field];
|
|
|
}
|
|
}
|
|
|
|
|
+ this.$store.commit(MutationTypes.editCreneauGroup, payload);
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
updateCreneau<K extends keyof Creneau>(payload: { id: string; field: K; value: Creneau[K] }) {
|
|
updateCreneau<K extends keyof Creneau>(payload: { id: string; field: K; value: Creneau[K] }) {
|
|
|
this.$store.commit(MutationTypes.editCreneau, payload);
|
|
this.$store.commit(MutationTypes.editCreneau, payload);
|
|
|
- this.timeline.updateEventById(payload.id);
|
|
|
|
|
|
|
+ const creneau = this.$store.getters.getCreneauById(payload.id);
|
|
|
|
|
+ if (creneau) {
|
|
|
|
|
+ this.timeline.removeEventById(payload.id);
|
|
|
|
|
+ this.timeline.addEvent(creneau.event);
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ zoom(lvl: number) {
|
|
|
|
|
+ const durations = [
|
|
|
|
|
+ 10080,
|
|
|
|
|
+ 10080,
|
|
|
|
|
+ 10080,
|
|
|
|
|
+ 10080,
|
|
|
|
|
+ 10080,
|
|
|
|
|
+ 1440,
|
|
|
|
|
+ 1440,
|
|
|
|
|
+ 720,
|
|
|
|
|
+ 720,
|
|
|
|
|
+ 360,
|
|
|
|
|
+ 120,
|
|
|
|
|
+ 60,
|
|
|
|
|
+ 60,
|
|
|
|
|
+ 60,
|
|
|
|
|
+ 30,
|
|
|
|
|
+ 30,
|
|
|
|
|
+ 15,
|
|
|
|
|
+ 5,
|
|
|
|
|
+ ];
|
|
|
|
|
+ const slotWidths = [40, 60, 80, 120, 160, 30, 40, 30, 50, 40, 25, 20, 30, 40, 30, 40, 35, 20];
|
|
|
|
|
+ const legendSpans = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 1, 4];
|
|
|
|
|
+ this.zoomLevel += lvl;
|
|
|
|
|
+ this.zoomLevel = Math.min(Math.max(0, this.zoomLevel), durations.length - 1);
|
|
|
|
|
+
|
|
|
|
|
+ this.slotduration = durations[this.zoomLevel];
|
|
|
|
|
+ this.slotwidth = slotWidths[this.zoomLevel];
|
|
|
|
|
+ this.legendspan = legendSpans[this.zoomLevel];
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
computed: {
|
|
computed: {
|
|
|
timeline(): Timeline {
|
|
timeline(): Timeline {
|
|
|
- return this.$refs["timeline"] as Timeline;
|
|
|
|
|
|
|
+ const output = this.$refs["timeline"];
|
|
|
|
|
+ console.log(output);
|
|
|
|
|
+ return output as Timeline;
|
|
|
},
|
|
},
|
|
|
currentCreneauGroupId(): string {
|
|
currentCreneauGroupId(): string {
|
|
|
return this.currentCreneauGroup ? this.currentCreneauGroup.id : "";
|
|
return this.currentCreneauGroup ? this.currentCreneauGroup.id : "";
|
|
@@ -164,17 +294,31 @@ export default defineComponent({
|
|
|
return this.$store.state.creneauGroupList;
|
|
return this.$store.state.creneauGroupList;
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
- watch: {
|
|
|
|
|
- creneauGroupList() {
|
|
|
|
|
- this.timeline.requestUpdate();
|
|
|
|
|
- },
|
|
|
|
|
- creneauList() {
|
|
|
|
|
- this.timeline.requestUpdate();
|
|
|
|
|
- },
|
|
|
|
|
- },
|
|
|
|
|
|
|
+ watch: {},
|
|
|
mounted() {
|
|
mounted() {
|
|
|
this.timeline.addRessources(this.creneauGroupList);
|
|
this.timeline.addRessources(this.creneauGroupList);
|
|
|
this.timeline.addEvents(this.eventList);
|
|
this.timeline.addEvents(this.eventList);
|
|
|
|
|
+ this.timeline.setLegendUnitFormat("d", "dddd D MMMM");
|
|
|
|
|
+ this.timeline.customStyle = `.bubble{
|
|
|
|
|
+ height: 20px;
|
|
|
|
|
+ width: 20px;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ right: -4px;
|
|
|
|
|
+ bottom: -4px;
|
|
|
|
|
+ border-radius: 50%;
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ background: green;
|
|
|
|
|
+}
|
|
|
|
|
+.bubble.red{
|
|
|
|
|
+ background: red;
|
|
|
|
|
+}
|
|
|
|
|
+.bubble.orange{
|
|
|
|
|
+ background: orange;
|
|
|
|
|
+}`;
|
|
|
},
|
|
},
|
|
|
});
|
|
});
|
|
|
</script>
|
|
</script>
|
|
@@ -198,4 +342,11 @@ jc-timeline {
|
|
|
box-shadow: 0 0 2px 2px var(--color-neutral-600);
|
|
box-shadow: 0 0 2px 2px var(--color-neutral-600);
|
|
|
height: 100%;
|
|
height: 100%;
|
|
|
}
|
|
}
|
|
|
|
|
+.actions {
|
|
|
|
|
+ display: inline-flex;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.actions > button {
|
|
|
|
|
+ margin-right: 4px;
|
|
|
|
|
+}
|
|
|
</style>
|
|
</style>
|