mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
492 lines
17 KiB
Vue
492 lines
17 KiB
Vue
<template>
|
|
<div>
|
|
<h2 class="chill-red">{{ $t('edit_your_calendar_range') }}</h2>
|
|
|
|
<div class="form-check">
|
|
<input type="checkbox" id="myCalendar" class="form-check-input" v-model="showMyCalendarWidget" />
|
|
<label class="form-check-label" for="myCalendar">{{ $t('show_my_calendar') }}</label>
|
|
</div>
|
|
<div class="form-check">
|
|
<input type="checkbox" id="weekends" class="form-check-input" @click="toggleWeekends" />
|
|
<label class="form-check-label" for="weekends">{{ $t('show_weekends') }}</label>
|
|
</div>
|
|
|
|
<FullCalendar ref="fullCalendar" :options="calendarOptions">
|
|
<template v-slot:eventContent='arg' >
|
|
<span class='calendarRangeItems'>
|
|
<b v-if="arg.event.extendedProps.myCalendar" style="text-decoration: underline" >{{ arg.timeText }}</b>
|
|
<b v-else-if="!arg.event.extendedProps.myCalendar && arg.event.extendedProps.toDelete" style="text-decoration: line-through red" >{{ arg.timeText }}</b>
|
|
<b v-else >{{ arg.timeText }}</b>
|
|
<i> {{ arg.event.title }}</i>
|
|
<a v-if=!arg.event.extendedProps.myCalendar class="fa fa-fw fa-times"
|
|
@click.prevent="onClickDelete(arg.event)">
|
|
</a>
|
|
</span>
|
|
</template>
|
|
</FullCalendar>
|
|
<div>
|
|
<ul class="record_actions">
|
|
<!-- <li>
|
|
<button class="btn btn-save" :disabled="!dirty"
|
|
@click.prevent="onClickSave">
|
|
{{ $t('action.save')}}
|
|
</button>
|
|
<span v-if="flag.loading" class="loading">
|
|
<i class="fa fa-circle-o-notch fa-spin fa-fw"></i>
|
|
<span class="sr-only">{{ $t('loading') }}</span>
|
|
</span>
|
|
</li> -->
|
|
<li>
|
|
<button v-if="disableCopyDayButton" class="btn btn-action" disabled>
|
|
{{ $t('copy_range_to_next_day')}}
|
|
</button>
|
|
<button v-else class="btn btn-action"
|
|
@click.prevent="copyDay">
|
|
{{ $t('copy_range_from_day')}} {{this.lastNewDate.toLocaleDateString()}} {{ $t('to_the_next_day')}}
|
|
</button>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div>
|
|
<div v-if="newCalendarRanges.length > 0">
|
|
<h4>{{ $t('new_range_to_save') }}</h4>
|
|
<ul>
|
|
<li v-for="i in newCalendarRanges" :key="i.start">
|
|
{{ i.start.toLocaleString() }} - {{ i.end.toLocaleString() }}
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div v-if="updateCalendarRanges.length > 0">
|
|
<h4>{{ $t('update_range_to_save') }}</h4>
|
|
<ul>
|
|
<li v-for="i in updateCalendarRanges" :key="i.start">
|
|
{{ i.start.toLocaleString() }} - {{ i.end.toLocaleString() }}
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div v-if="deleteCalendarRanges.length > 0">
|
|
<h4>{{ $t('delete_range_to_save') }}</h4>
|
|
<ul>
|
|
<li v-for="i in deleteCalendarRanges" :key="i.start">
|
|
{{ i.start.toLocaleString() }} - {{ i.end.toLocaleString() }}
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<teleport to="body">
|
|
<modal v-if="modal.showModal"
|
|
:modalDialogClass="modal.modalDialogClass"
|
|
@close="modal.showModal = false">
|
|
|
|
<template v-slot:header>
|
|
<h2 class="modal-title">{{ this.renderEventDate() }}</h2>
|
|
</template>
|
|
|
|
<template v-slot:body>
|
|
<p>{{ $t('by')}} {{this.myCalendarClickedEvent.user.username }}</p>
|
|
<p>{{ $t('main_user_concerned') }} : {{ this.myCalendarClickedEvent.mainUser.username }}</p>
|
|
<p v-if="myCalendarClickedEvent.comment.length > 0" >{{ this.myCalendarClickedEvent.comment }}</p>
|
|
</template>
|
|
|
|
<template v-slot:footer>
|
|
<ul class="record_actions">
|
|
<li>
|
|
<a
|
|
class="btn btn-show"
|
|
:href=myCalendarEventShowLink() >
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a
|
|
class="btn btn-update"
|
|
:href=myCalendarEventUpdateLink() >
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a
|
|
class="btn btn-delete"
|
|
:href=myCalendarEventDeleteLink() >
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</template>
|
|
|
|
</modal>
|
|
</teleport>
|
|
</template>
|
|
|
|
<script>
|
|
import '@fullcalendar/core/vdom'; // solves problem with Vite
|
|
import frLocale from '@fullcalendar/core/locales/fr';
|
|
import FullCalendar from '@fullcalendar/vue3';
|
|
import dayGridPlugin from '@fullcalendar/daygrid';
|
|
import interactionPlugin from '@fullcalendar/interaction';
|
|
import timeGridPlugin from '@fullcalendar/timegrid';
|
|
import Modal from 'ChillMainAssets/vuejs/_components/Modal';
|
|
import { deleteCalendarRange, fetchCalendar, fetchCalendarRangesByUser, patchCalendarRange, postCalendarRange } from '../_api/api';
|
|
import { mapState } from 'vuex';
|
|
|
|
export default {
|
|
name: "App",
|
|
components: {
|
|
FullCalendar,
|
|
Modal
|
|
},
|
|
data() {
|
|
return {
|
|
errorMsg: [],
|
|
modal: {
|
|
showModal: false,
|
|
modalDialogClass: "modal-dialog-scrollable modal-m"
|
|
},
|
|
flag: {
|
|
loading: false
|
|
},
|
|
userId: window.userId,
|
|
showMyCalendar: true,
|
|
myCalendarClickedEvent: null,
|
|
calendarEvents: {
|
|
userCalendar: null,
|
|
userCalendarRange: null,
|
|
new: {
|
|
events: [],
|
|
color: "#3788d8"
|
|
}
|
|
},
|
|
lastNewDate: null,
|
|
disableCopyDayButton: true,
|
|
calendarOptions: {
|
|
locale: frLocale,
|
|
plugins: [ dayGridPlugin, interactionPlugin, timeGridPlugin ],
|
|
initialView: 'timeGridWeek',
|
|
initialDate: window.startDate !== undefined ? window.startDate : new Date(),
|
|
eventSource: [],
|
|
selectable: true,
|
|
select: this.onDateSelect,
|
|
eventChange: this.onEventChange,
|
|
eventDrop: this.onEventDropOrResize,
|
|
eventResize: this.onEventDropOrResize,
|
|
eventClick: this.onEventClick,
|
|
selectMirror: false,
|
|
editable: true,
|
|
weekends: false,
|
|
slotDuration: '00:15:00',
|
|
slotMinutes: 15,
|
|
slotMinTime: "08:00:00",
|
|
slotMaxTime: "18:00:00",
|
|
headerToolbar: {
|
|
left: 'prev,next today',
|
|
center: 'title',
|
|
right: 'dayGridMonth,timeGridWeek,timeGridDay'
|
|
},
|
|
},
|
|
}
|
|
},
|
|
computed: {
|
|
...mapState({
|
|
newCalendarRanges: state => state.newCalendarRanges,
|
|
updateCalendarRanges: state => state.updateCalendarRanges,
|
|
deleteCalendarRanges: state => state.deleteCalendarRanges,
|
|
dirty: state => state.newCalendarRanges.length > 0 || state.updateCalendarRanges.length > 0 || state.deleteCalendarRanges.length > 0
|
|
}),
|
|
showMyCalendarWidget: {
|
|
set(value) {
|
|
this.toggleMyCalendar(value);
|
|
this.updateEventsSource();
|
|
},
|
|
get() {
|
|
return this.showMyCalendar;
|
|
}
|
|
},
|
|
},
|
|
methods: {
|
|
init() {
|
|
console.log('init')
|
|
this.fetchData();
|
|
},
|
|
openModal() {
|
|
this.modal.showModal = true;
|
|
},
|
|
myCalendarEventShowLink() {
|
|
return `/fr/calendar/calendar/${this.myCalendarClickedEvent.id}/show?user_id=${ this.userId }`
|
|
},
|
|
myCalendarEventUpdateLink() {
|
|
return `/fr/calendar/calendar/${this.myCalendarClickedEvent.id}/edit?user_id=${ this.userId }`
|
|
},
|
|
myCalendarEventDeleteLink() {
|
|
return `/fr/calendar/calendar/${this.myCalendarClickedEvent.id}/delete?user_id=${ this.userId }`
|
|
},
|
|
resetCalendar() {
|
|
this.fetchData();
|
|
this.calendarEvents.new = {
|
|
events: [],
|
|
color: "#3788d8"
|
|
};
|
|
this.updateEventsSource();
|
|
},
|
|
fetchData() {
|
|
this.flag.loading = true;
|
|
fetchCalendarRangesByUser(this.userId).then(calendarRanges => new Promise((resolve, reject) => {
|
|
// console.log('calendar ranges', calendarRanges.results)
|
|
let events = calendarRanges.results.map(i =>
|
|
({
|
|
start: i.startDate.datetime,
|
|
end: i.endDate.datetime,
|
|
calendarRangeId: i.id,
|
|
toDelete: false
|
|
})
|
|
);
|
|
let calendarRangeEvents = {
|
|
events: events,
|
|
borderColor: "#3788d8",
|
|
backgroundColor: '#ffffff',
|
|
textColor: '#444444',
|
|
};
|
|
this.calendarEvents.userCalendarRange = calendarRangeEvents;
|
|
|
|
fetchCalendar(this.userId).then(calendar => new Promise((resolve, reject) => {
|
|
let events = calendar.results.map(i =>
|
|
({
|
|
myCalendar: true,
|
|
calendarId: i.id,
|
|
start: i.startDate.datetime,
|
|
end: i.endDate.datetime,
|
|
user: i.user,
|
|
mainUser: i.mainUser,
|
|
persons: i.persons,
|
|
professionals: i.professionals,
|
|
comment: i.comment
|
|
})
|
|
);
|
|
let calendarEventsCurrentUser = {
|
|
events: events,
|
|
color: 'darkblue',
|
|
id: 1000,
|
|
editable: false
|
|
};
|
|
this.calendarEvents.userCalendar = calendarEventsCurrentUser;
|
|
this.updateEventsSource();
|
|
this.flag.loading = false;
|
|
resolve();
|
|
}));
|
|
|
|
resolve();
|
|
}));
|
|
},
|
|
updateEventsSource() {
|
|
this.calendarOptions.eventSources = [];
|
|
this.calendarOptions.eventSources.push(this.calendarEvents.new);
|
|
this.calendarOptions.eventSources.push(this.calendarEvents.userCalendarRange);
|
|
if (this.showMyCalendar) {
|
|
this.calendarOptions.eventSources.push(this.calendarEvents.userCalendar);
|
|
}
|
|
// console.log(this.calendarOptions.eventSources);
|
|
},
|
|
toggleMyCalendar(value) {
|
|
this.showMyCalendar = value;
|
|
},
|
|
toggleWeekends: function() {
|
|
this.calendarOptions.weekends = !this.calendarOptions.weekends;
|
|
},
|
|
onDateSelect(payload) {
|
|
// console.log('payload', payload);
|
|
let events = this.calendarEvents.new.events;
|
|
// events.push({
|
|
// start: payload.startStr,
|
|
// end: payload.endStr
|
|
// });
|
|
// this.calendarEvents.new = {
|
|
// events: events,
|
|
// borderColor: "#3788d8",
|
|
// backgroundColor: '#fffadf',
|
|
// textColor: '#444444',
|
|
// };
|
|
this.disableCopyDayButton = false;
|
|
this.lastNewDate = new Date(payload.startStr);
|
|
this.updateEventsSource();
|
|
// this.$store.dispatch('createRange', payload);
|
|
postCalendarRange({
|
|
user: {
|
|
type: 'user',
|
|
id: window.userId,
|
|
},
|
|
startDate: {
|
|
datetime: `${payload.start.toISOString().split('.')[0]}+0000`, //should be like "2021-08-20T15:00:00+0200",
|
|
},
|
|
endDate: {
|
|
datetime: `${payload.end.toISOString().split('.')[0]}+0000`, // TODO check if OK with time zone
|
|
},
|
|
}).then(() => {
|
|
this.init();
|
|
})
|
|
},
|
|
onEventChange(payload) {
|
|
},
|
|
onEventDropOrResize(payload) {
|
|
payload.event.setProp('borderColor', '#3788d8');
|
|
payload.event.setProp('backgroundColor', '#fffadf');
|
|
payload.event.setProp('textColor', '#444444');
|
|
this.$store.dispatch('updateRange', payload);
|
|
},
|
|
onEventClick(payload) {
|
|
if (payload.event.extendedProps.myCalendar) {
|
|
this.myCalendarClickedEvent = {
|
|
id: payload.event.extendedProps.calendarId,
|
|
start: payload.event.start,
|
|
end: payload.event.end,
|
|
user: payload.event.extendedProps.user,
|
|
mainUser: payload.event.extendedProps.mainUser,
|
|
persons: payload.event.extendedProps.persons,
|
|
professionals: payload.event.extendedProps.professionals,
|
|
comment: payload.event.extendedProps.comment
|
|
};
|
|
// console.log(this.myCalendarClickedEvent)
|
|
this.openModal();
|
|
}
|
|
},
|
|
// onClickSave(payload) {
|
|
// this.flag.loading = true;
|
|
// if (this.$store.state.newCalendarRanges.length > 0){
|
|
// Promise.all(this.$store.state.newCalendarRanges.map(cr => {
|
|
// postCalendarRange({
|
|
// user: {
|
|
// type: 'user',
|
|
// id: window.userId,
|
|
// },
|
|
// startDate: {
|
|
// datetime: `${cr.start.toISOString().split('.')[0]}+0000`, //should be like "2021-08-20T15:00:00+0200",
|
|
// },
|
|
// endDate: {
|
|
// datetime: `${cr.end.toISOString().split('.')[0]}+0000`, // TODO check if OK with time zone
|
|
// },
|
|
// })
|
|
// })
|
|
// ).then((_r) => this.resetCalendar());
|
|
|
|
// this.$store.dispatch('clearNewCalendarRanges', payload);
|
|
// }
|
|
// if (this.$store.state.updateCalendarRanges.length > 0){
|
|
// Promise.all(this.$store.state.updateCalendarRanges.map(cr => {
|
|
// patchCalendarRange(cr.id,
|
|
// {
|
|
// startDate: {
|
|
// datetime: `${cr.start.toISOString().split('.')[0]}+0000`, //should be like "2021-08-20T15:00:00+0200",
|
|
// },
|
|
// endDate: {
|
|
// datetime: `${cr.end.toISOString().split('.')[0]}+0000`, // TODO check if OK with time zone
|
|
// },
|
|
// })
|
|
// })
|
|
// ).then((_r) => this.resetCalendar());
|
|
// this.$store.dispatch('clearUpdateCalendarRanges', payload);
|
|
// }
|
|
// if (this.$store.state.deleteCalendarRanges.length > 0){
|
|
// Promise.all(this.$store.state.deleteCalendarRanges.map(cr => {
|
|
// deleteCalendarRange(cr.id)
|
|
// })
|
|
// ).then((_r) => this.resetCalendar());
|
|
// this.$store.dispatch('clearDeleteCalendarRanges', payload);
|
|
// }
|
|
|
|
// },
|
|
onClickDelete(payload) {
|
|
if (payload.extendedProps.hasOwnProperty("calendarRangeId")) {
|
|
deleteCalendarRange(payload.extendedProps.calendarRangeId).then(() => {
|
|
this.init();
|
|
})
|
|
// if (payload.extendedProps.toDelete) {
|
|
// payload.setExtendedProp('toDelete', false)
|
|
// payload.setProp('borderColor', '#79bafc');
|
|
// this.$store.dispatch('removeFromDeleteRange', payload);
|
|
// } else {
|
|
// payload.setExtendedProp('toDelete', true)
|
|
// payload.setProp('borderColor', '#dddddd');
|
|
// this.$store.dispatch('deleteRange', payload);
|
|
// }
|
|
} else {
|
|
let newEvents = this.calendarEvents.new.events;
|
|
let filterEvents = newEvents.filter((e) =>
|
|
e.start !== payload.startStr && e.end !== payload.endStr
|
|
);
|
|
this.calendarEvents.new = {
|
|
events: filterEvents,
|
|
color: "#3788d8"
|
|
};
|
|
|
|
this.$store.dispatch('removeNewCalendarRanges', payload);
|
|
|
|
this.updateEventsSource();
|
|
}
|
|
|
|
},
|
|
isSameDay(date1, date2) {
|
|
return date1.getFullYear() === date2.getFullYear() &&
|
|
date1.getMonth() === date2.getMonth() &&
|
|
date1.getDate() === date2.getDate();
|
|
},
|
|
isFriday(date) {
|
|
return date.getDay() === 5
|
|
},
|
|
copyDay(_payload) {
|
|
// console.log(this.calendarEvents.new);
|
|
if (this.calendarEvents.new.events.length > 0) {
|
|
// Create the copied events
|
|
let increment = !this.calendarOptions.weekends && this.isFriday(this.lastNewDate) ? 24*60*60*1000*3 : 24*60*60*1000;
|
|
let events = this.calendarEvents.new.events.filter(
|
|
i => this.isSameDay(new Date(i.start), this.lastNewDate)).map(
|
|
i => {
|
|
let startDate = new Date(new Date(i.start).getTime() + increment);
|
|
let endDate = new Date(new Date(i.end).getTime() + increment);
|
|
return ({
|
|
start: startDate.toISOString(),
|
|
end: endDate.toISOString()
|
|
})
|
|
}
|
|
);
|
|
let copiedEvents = {
|
|
events: events,
|
|
color: "#3788d8"
|
|
};
|
|
// console.log(copiedEvents);
|
|
|
|
// Add to the calendar
|
|
let newEvents = this.calendarEvents.new.events;
|
|
newEvents.push(...copiedEvents.events);
|
|
this.calendarEvents.new = {
|
|
events: newEvents,
|
|
color: "#3788d8"
|
|
};
|
|
this.updateEventsSource();
|
|
|
|
// Set the last new date
|
|
this.lastNewDate = new Date(copiedEvents.events[copiedEvents.events.length - 1].start);
|
|
|
|
// Dispatch in store for saving
|
|
for (let i = 0; i < copiedEvents.events.length; i++) {
|
|
let eventObj = {
|
|
start: new Date(copiedEvents.events[i].start),
|
|
end: new Date(copiedEvents.events[i].end)
|
|
}
|
|
this.$store.dispatch('createRange', eventObj);
|
|
}
|
|
|
|
} else {
|
|
console.log('no new events to copy-paste!')
|
|
}
|
|
},
|
|
renderEventDate() {
|
|
let start = this.myCalendarClickedEvent.start;
|
|
let end = this.myCalendarClickedEvent.end;
|
|
return start.getDate() === end.getDate() ?
|
|
`${start.toLocaleDateString()}, ${start.toLocaleTimeString()} - ${end.toLocaleTimeString()}` :
|
|
`${start.toLocaleString()} - ${end.toLocaleString()}`;
|
|
}
|
|
},
|
|
mounted() {
|
|
this.init();
|
|
}
|
|
}
|
|
</script>
|