mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-10-20 10:49:36 +00:00
reworked coodle timeslot creation
This commit is contained in:
@@ -880,4 +880,9 @@ html {
|
||||
|
||||
.coodleCalendarTimeslotCardIcon:hover {
|
||||
color: var(--fhc-primary);
|
||||
}
|
||||
|
||||
#coodleCalendar .fhc-calendar-base .part-body,
|
||||
#coodleCalendar .fhc-calendar-base .fhc-calendar-base-grid-line-background {
|
||||
z-index: 1 !important;
|
||||
}
|
||||
@@ -116,7 +116,8 @@ export default {
|
||||
"update:date",
|
||||
"update:mode",
|
||||
"update:range",
|
||||
"drop"
|
||||
"drop",
|
||||
"emptyClicked",
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
@@ -297,10 +298,10 @@ export default {
|
||||
:is="modes ? modes[cMode] : null || 'div'"
|
||||
ref="mode"
|
||||
v-model:current-date="cDate"
|
||||
@emptyCellClicked="$emit('emptyCellClicked', $event)"
|
||||
@update:range="$emit('update:range', $event)"
|
||||
@request-modal-open="showEventModal"
|
||||
@request-modal-close="hideEventModal"
|
||||
@emptyClicked="$emit('emptyClicked', $event)"
|
||||
v-bind="modeOptions ? modeOptions[cMode] : null || {}"
|
||||
>
|
||||
<template v-slot="slot"><slot v-bind="slot" /></template>
|
||||
|
||||
@@ -2,6 +2,7 @@ import GridLine from './Grid/Line.js';
|
||||
import GridLineEvent from './Grid/Line/Event.js';
|
||||
|
||||
import CalDnd from '../../../directives/Calendar/DragAndDrop.js';
|
||||
import CalClick from '../../../directives/Calendar/Click.js';
|
||||
|
||||
export default {
|
||||
name: "CalendarGrid",
|
||||
@@ -10,7 +11,7 @@ export default {
|
||||
GridLineEvent
|
||||
},
|
||||
directives: {
|
||||
CalDnd
|
||||
CalDnd,
|
||||
},
|
||||
inject: {
|
||||
originalEvents: "events",
|
||||
|
||||
@@ -83,11 +83,8 @@ export default {
|
||||
<template #part-body="params">
|
||||
<slot name="part-body">
|
||||
<div
|
||||
@click="($event) => {
|
||||
$event.params = params;
|
||||
$emit('emptyCellClicked', $event)
|
||||
}"
|
||||
class="position-absolute h-100 w-100" style="z-index:1"></div>
|
||||
@click="$emit('emptyClicked', { event: $event, params })"
|
||||
class="position-absolute h-100 w-100"></div>
|
||||
</slot>
|
||||
</template>
|
||||
<template #event="slot">
|
||||
|
||||
@@ -55,13 +55,13 @@ export default {
|
||||
events() {
|
||||
let events = this.timeslotCalendarEvents;
|
||||
|
||||
const participantWithVisibleSchedules =
|
||||
const participantsWithDisplayedSchedules =
|
||||
this.$props.surveyFormDataParticipants.filter(
|
||||
(participant) => participant.isCalendarShown,
|
||||
);
|
||||
participantWithVisibleSchedules.forEach((participant) => {
|
||||
participantsWithDisplayedSchedules.forEach((participant) => {
|
||||
let participantEvents =
|
||||
cachedParticipantSchedules[participant.uid] ?? [];
|
||||
this.cachedParticipantSchedules[participant.uid] ?? [];
|
||||
participantEvents = participantEvents.map((event) => {
|
||||
event.farbe =
|
||||
this.$props.participantScheduleColors.find(
|
||||
@@ -158,6 +158,20 @@ export default {
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
surveyFormDataParticipants: {
|
||||
handler() {
|
||||
let participantsWithDisplayedSchedules =
|
||||
this.$props.surveyFormDataParticipants.filter(
|
||||
(participant) => participant.isCalendarShown,
|
||||
);
|
||||
participantsWithDisplayedSchedules.forEach((participant) => {
|
||||
if (!this.cachedParticipantSchedules[participant.uid]) {
|
||||
this.fetchParticipantSchedule(participant.uid);
|
||||
}
|
||||
});
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
setTimeslotCalendarEvents() {
|
||||
@@ -167,13 +181,13 @@ export default {
|
||||
return this.generateTimeslotCalendarEvent(startDate);
|
||||
}) ?? [];
|
||||
},
|
||||
addTimeslotOnCalendarClick(clickEvent) {
|
||||
addTimeslotOnCalendarClick(event) {
|
||||
if (this.timeslotCalendarEvents.length >= 50) {
|
||||
return;
|
||||
}
|
||||
|
||||
const elementRectangle = clickEvent.target.getBoundingClientRect();
|
||||
const relativeClickLocation = clickEvent.y - elementRectangle.top;
|
||||
const elementRectangle = event.event.target.getBoundingClientRect();
|
||||
const relativeClickLocation = event.event.y - elementRectangle.top;
|
||||
let minutes =
|
||||
Math.floor(
|
||||
(relativeClickLocation / elementRectangle.height) * 12,
|
||||
@@ -182,12 +196,12 @@ export default {
|
||||
minutes = 0;
|
||||
}
|
||||
|
||||
let hours = clickEvent.params?.part?.values?.hours ?? 12;
|
||||
let hours = event.params?.part?.values?.hours ?? 12;
|
||||
if (hours < 7 || hours > 22) {
|
||||
hours = 12;
|
||||
}
|
||||
|
||||
let start = new Date(clickEvent.params.date.ts);
|
||||
let start = new Date(event.params.date.ts);
|
||||
start.setHours(hours);
|
||||
start.setMinutes(minutes);
|
||||
|
||||
@@ -291,6 +305,9 @@ export default {
|
||||
);
|
||||
this.isTimeslotCardEditInProgress = false;
|
||||
},
|
||||
fetchParticipantSchedule(uid) {
|
||||
// todo: fetch, format as events, add as array with uid as key to cachedParticipantSchedules
|
||||
},
|
||||
getEventStyle(event) {
|
||||
if (!event.farbe) return undefined;
|
||||
return "--event-bg:#" + event.farbe;
|
||||
@@ -300,33 +317,33 @@ export default {
|
||||
this.setTimeslotCalendarEvents();
|
||||
},
|
||||
template: /*html*/ `
|
||||
<div class="d-flex flex-column gap-3">
|
||||
<div id="coodleCalendar" class="d-flex flex-column gap-3">
|
||||
<div class="d-flex flex-column">
|
||||
<span class="fw-bold">{{ "Timeslot selection" }}</span>
|
||||
<span class="fst-italic">{{ "You can add timeslots directly to the calendar or from the list down below." }}</span>
|
||||
</div>
|
||||
<div style="height:800px;">
|
||||
<fhc-calendar
|
||||
@emptyCellClicked="addTimeslotOnCalendarClick($event)"
|
||||
:ref="'coodleCalendar'"
|
||||
:timezone="timezone"
|
||||
:modes="modes"
|
||||
:modeOptions="modeOptions"
|
||||
:mode="'Week'"
|
||||
:timeGrid="null"
|
||||
:locale="$p.user_locale.value"
|
||||
:events="events"
|
||||
:backgrounds="backgrounds"
|
||||
:draggableEvents="true"
|
||||
:droppableEvents="true"
|
||||
:onDrop="true"
|
||||
:isAutoScrollEnabled="false"
|
||||
>
|
||||
<div style="height:800px;">
|
||||
<fhc-calendar
|
||||
@emptyClicked="addTimeslotOnCalendarClick($event)"
|
||||
:ref="'coodleCalendar'"
|
||||
:timezone="timezone"
|
||||
:modes="modes"
|
||||
:modeOptions="modeOptions"
|
||||
:mode="'Week'"
|
||||
:timeGrid="null"
|
||||
:locale="$p.user_locale.value"
|
||||
:events="events"
|
||||
:backgrounds="backgrounds"
|
||||
:draggableEvents="true"
|
||||
:droppableEvents="true"
|
||||
:onDrop="true"
|
||||
:isAutoScrollEnabled="false"
|
||||
>
|
||||
<template v-slot="{ event, mode }">
|
||||
<div
|
||||
:class="'event-type-' + event.type + ' ' + mode + 'PageContainer'"
|
||||
:type="mode == 'day' ? 'button' : undefined"
|
||||
:style="getEventStyle(event)"
|
||||
:style="getEventStyle(event)"
|
||||
>
|
||||
<component
|
||||
v-if="mode == 'event'"
|
||||
@@ -347,8 +364,8 @@ export default {
|
||||
></component>
|
||||
</div>
|
||||
</template>
|
||||
</fhc-calendar>
|
||||
</div>
|
||||
</fhc-calendar>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div v-for="timeslot in sortedTimeslotCalendarEvents.concat([null])" class="col-12 col-md-6 col-xl-4">
|
||||
<coodle-survey-calendar-timeslot-card
|
||||
|
||||
+27
-7
@@ -64,11 +64,15 @@ export default {
|
||||
},
|
||||
isMaxDisplayedParticipantSchedulesReached() {
|
||||
return (
|
||||
this.participants.filter(
|
||||
(participant) => participant.isCalendarShown,
|
||||
).length >= this.participantScheduleColors.length
|
||||
this.displayedParticipantSchedulesCount >=
|
||||
this.participantScheduleColors.length
|
||||
);
|
||||
},
|
||||
displayedParticipantSchedulesCount() {
|
||||
return this.participants.filter(
|
||||
(participant) => participant.isCalendarShown,
|
||||
).length;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
searchInput() {
|
||||
@@ -143,7 +147,7 @@ export default {
|
||||
if (!occupiedParticipantColor) return;
|
||||
occupiedParticipantColor.uid = null;
|
||||
},
|
||||
showCalendar(participantForCalendarToBeDisplayed) {
|
||||
showSchedule(participantForCalendarToBeDisplayed) {
|
||||
if (this.isMaxDisplayedParticipantSchedulesReached) return;
|
||||
|
||||
this.participants = this.participants.map((participant) => {
|
||||
@@ -160,7 +164,7 @@ export default {
|
||||
(participantColor) => !participantColor.uid,
|
||||
).uid = participantForCalendarToBeDisplayed.uid;
|
||||
},
|
||||
hideCalendar(participant) {
|
||||
hideSchedule(participant) {
|
||||
participant.isCalendarShown = false;
|
||||
|
||||
let occupiedParticipantColor = this.participantScheduleColors.find(
|
||||
@@ -169,6 +173,14 @@ export default {
|
||||
if (!occupiedParticipantColor) return;
|
||||
occupiedParticipantColor.uid = null;
|
||||
},
|
||||
hideAllSchedules() {
|
||||
this.participants.forEach((participant) => {
|
||||
participant.isCalendarShown = false;
|
||||
});
|
||||
this.participantScheduleColors.forEach((participantColor) => {
|
||||
participantColor.uid = null;
|
||||
});
|
||||
},
|
||||
getParticipantScheduleColor(participant) {
|
||||
return this.participantScheduleColors.find(
|
||||
(participantColor) => participantColor.uid === participant.uid,
|
||||
@@ -229,7 +241,7 @@ export default {
|
||||
<div class="d-flex flex-row align-items-center gap-3">
|
||||
<i
|
||||
v-if="participant.isCalendarShown"
|
||||
@click="hideCalendar(participant)"
|
||||
@click="hideSchedule(participant)"
|
||||
type="button"
|
||||
class="fa-solid fa-calendar"
|
||||
:style="{color: getParticipantScheduleColor(participant)}"
|
||||
@@ -240,7 +252,7 @@ export default {
|
||||
></i>
|
||||
<i
|
||||
v-else
|
||||
@click="showCalendar(participant)"
|
||||
@click="showSchedule(participant)"
|
||||
type="button"
|
||||
class="fa-regular fa-calendar"
|
||||
></i>
|
||||
@@ -251,6 +263,14 @@ export default {
|
||||
<span v-if="isMaxDisplayedParticipantSchedulesReached" class="fst-italic">
|
||||
{{ "You can display no more participant schedules!" }}
|
||||
</span>
|
||||
<span
|
||||
v-if="displayedParticipantSchedulesCount"
|
||||
@click="hideAllSchedules()"
|
||||
type="button"
|
||||
class="text-decoration-underline"
|
||||
>
|
||||
{{ "Hide all participant schedules" }}
|
||||
</span>
|
||||
</div>
|
||||
`,
|
||||
};
|
||||
|
||||
@@ -9,10 +9,13 @@ function saveAddClickListener(el, source, value) {
|
||||
const listener = evt => {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
if (typeof value === "function") {
|
||||
value = value(evt);
|
||||
}
|
||||
const customEvent = new CustomEvent('cal-click', {
|
||||
cancelable: true,
|
||||
bubbles: true,
|
||||
detail: { source, value }
|
||||
detail: { source, value },
|
||||
});
|
||||
evt.target.dispatchEvent(customEvent);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user