From af6dcfe0b8108645319145c4100ca335cb408511 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Glasn=C3=A1k?= Date: Thu, 13 Nov 2025 01:22:53 +0100 Subject: [PATCH 1/2] fix(calendar): prevent adding timeblocks outside of working hours --- app/src/plugins/app@vendor/vue-cal/cell.vue | 56 +++++++++++++-------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/app/src/plugins/app@vendor/vue-cal/cell.vue b/app/src/plugins/app@vendor/vue-cal/cell.vue index 8025033..7ce3f61 100644 --- a/app/src/plugins/app@vendor/vue-cal/cell.vue +++ b/app/src/plugins/app@vendor/vue-cal/cell.vue @@ -282,31 +282,47 @@ export default { }, onCellClick(DOMEvent, split) { - const dateFrom = split.date; - dateFrom.setHours(Math.floor(DOMEvent.offsetY / 100), 0, 0, 0); - const dateTo = new Date(dateFrom); - dateTo.setHours(dateFrom.getHours() + 1); + const allNonWorkingHoursEvents = + DOMEvent.target.querySelectorAll('.non-working-event'); - const time = moment(dateFrom).format('HH:mm'); + const calendarHeight = DOMEvent.target.offsetHeight; - const isTeamCalendar = this.$route.name === 'Dashboard - Teams'; - const employee = isTeamCalendar - ? split.employee_id - : Number(localStorage.getItem('selectedEmployee') || this.user.id); + const morningNonWorkingHoursEventHeight = + allNonWorkingHoursEvents?.[0]?.offsetHeight || 950; + const afternoonNonWorkingHoursEventHeight = + allNonWorkingHoursEvents?.[1]?.offsetHeight || 1700; - this.$events.emit('show-menu-modal', { - time, - date: tmUtils.formatDateTimeForBackend(dateFrom), - employee, - }); + if ( + // Check if the click is not in the non-working hours events + DOMEvent.offsetY > morningNonWorkingHoursEventHeight && + DOMEvent.offsetY < calendarHeight - afternoonNonWorkingHoursEventHeight + ) { + const dateFrom = split.date; + dateFrom.setHours(Math.floor(DOMEvent.offsetY / 100), 0, 0, 0); + const dateTo = new Date(dateFrom); + dateTo.setHours(dateFrom.getHours() + 1); - setTimeout(() => { - this.$events.emit('add-timeblock', { - id: null, - start: tmUtils.formatDateTimeForBackend(dateFrom), - end: tmUtils.formatDateTimeForBackend(dateTo), + const time = moment(dateFrom).format('HH:mm'); + + const isTeamCalendar = this.$route.name === 'Dashboard - Teams'; + const employee = isTeamCalendar + ? split.employee_id + : Number(localStorage.getItem('selectedEmployee') || this.user.id); + + this.$events.emit('show-menu-modal', { + time, + date: tmUtils.formatDateTimeForBackend(dateFrom), + employee, }); - }, 150); + + setTimeout(() => { + this.$events.emit('add-timeblock', { + id: null, + start: tmUtils.formatDateTimeForBackend(dateFrom), + end: tmUtils.formatDateTimeForBackend(dateTo), + }); + }, 150); + } if (!this.isDOMElementAnEvent(DOMEvent.target)) this.selectCell(DOMEvent); }, From 7befa9a4ea6f6e1dabb818234f65bd5d9af88f7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Glasn=C3=A1k?= Date: Thu, 13 Nov 2025 01:23:30 +0100 Subject: [PATCH 2/2] build(calendar): ensure timeblock creation is restricted to working hours --- app/dist/js/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/dist/js/index.js b/app/dist/js/index.js index 4a67778..808a5bd 100644 --- a/app/dist/js/index.js +++ b/app/dist/js/index.js @@ -433,7 +433,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _cel /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.push.js */ \"./node_modules/core-js/modules/es.array.push.js\");\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _event_vue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./event.vue */ \"./src/plugins/app@vendor/vue-cal/event.vue\");\n/* harmony import */ var _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @/plugins/tm@_utils/tm.utils */ \"./src/plugins/tm@_utils/tm.utils.ts\");\n/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\");\n/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(moment__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var vuex__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! vuex */ \"./node_modules/vuex/dist/vuex.esm-bundler.js\");\n\n\n\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n inject: ['vuecal', 'utils', 'modules', 'view', 'domEvents'],\n components: {\n Event: _event_vue__WEBPACK_IMPORTED_MODULE_1__[\"default\"]\n },\n props: {\n // Vue-cal main component options (props).\n options: {\n type: Object,\n default: () => ({})\n },\n editEvents: {\n type: Object,\n required: true\n },\n data: {\n type: Object,\n required: true\n },\n cellSplits: {\n type: Array,\n default: () => []\n },\n minTimestamp: {\n type: [Number, null],\n default: null\n },\n maxTimestamp: {\n type: [Number, null],\n default: null\n },\n cellWidth: {\n type: [Number, Boolean],\n default: false\n },\n allDay: {\n type: Boolean,\n default: false\n }\n },\n data: () => ({\n tmUtils: _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_2__[\"default\"],\n cellOverlaps: {},\n cellOverlapsStreak: 1,\n // Largest amount of simultaneous events in cell.\n // On mouse down, save the time at cursor so it can be reused on cell focus event\n // where there is no cursor coords.\n timeAtCursor: null,\n highlighted: false,\n // On event drag over.\n highlightedSplit: null\n }),\n methods: {\n getSplitAtCursor({\n target\n }) {\n const targetIsSplit = target.classList.contains('vuecal__cell-split');\n let split = targetIsSplit ? target : this.vuecal.findAncestor(target, 'vuecal__cell-split');\n if (split) {\n split = split.attributes['data-split'].value;\n // Convert to a numeric value if split id is a number.\n if (parseInt(split).toString() === split.toString()) split = parseInt(split);\n }\n return split || null;\n },\n splitClasses(split) {\n return {\n 'vuecal__cell-split': true,\n 'vuecal__cell-split--highlighted': this.highlightedSplit === split.id,\n 'vuecal__cell-split--weekend': split.isWeekend,\n [split.class]: !!split.class\n };\n },\n checkCellOverlappingEvents() {\n // If splits, checkCellOverlappingEvents() is called from within computed splits.\n if (this.options.time && this.eventsCount && !this.splitsCount) {\n if (this.eventsCount === 1) {\n this.cellOverlaps = [];\n this.cellOverlapsStreak = 1;\n }\n // If only 1 event remains re-init the overlaps.\n else [this.cellOverlaps, this.cellOverlapsStreak] = this.utils.event.checkCellOverlappingEvents(this.events, this.options);\n }\n },\n isDOMElementAnEvent(el) {\n return this.vuecal.isDOMElementAnEvent(el);\n },\n /**\n * Select a cell and go to narrower view on double click or single click according to vuecalProps option.\n */\n selectCell(DOMEvent, force = false) {\n // If splitting days, also return the clicked split on cell click when emitting event.\n const split = this.splitsCount ? this.getSplitAtCursor(DOMEvent) : null;\n this.utils.cell.selectCell(force, this.timeAtCursor, split);\n this.timeAtCursor = null;\n },\n onCellkeyPressEnter(DOMEvent) {\n if (!this.isSelected) this.onCellFocus(DOMEvent);\n\n // If splitting days, also return the clicked split on cell keypress when emitting event.\n const split = this.splitsCount ? this.getSplitAtCursor(DOMEvent) : null;\n this.utils.cell.keyPressEnterCell(this.timeAtCursor, split);\n this.timeAtCursor = null;\n },\n /**\n * On cell focus, from tab key or from mousedown, highlight the cell and emit\n * the cell-focus event with the date of the cell start when focusing from tab or\n * the date & time at cursor if click/touch.\n */\n onCellFocus(DOMEvent) {\n if (!this.isSelected && !this.isDisabled) {\n this.isSelected = this.data.startDate; // Highlight the cell.\n\n // If splitting days, also return the clicked split on cell focus when emitting event.\n const split = this.splitsCount ? this.getSplitAtCursor(DOMEvent) : null;\n\n // Cell-focus event returns the cell start date (at midnight) if triggered from tab key,\n // or cursor coords time if clicked.\n const date = this.timeAtCursor || this.data.startDate;\n this.vuecal.$emit('cell-focus', split ? {\n date,\n split\n } : date);\n }\n },\n onCellMouseDown(DOMEvent, split = null, touch = false) {\n // Prevent a double mouse down on touch devices.\n if ('ontouchstart' in window && !touch) return false;\n if (!this.isSelected) this.onCellFocus(DOMEvent);\n const {\n clickHoldACell,\n focusAnEvent\n } = this.domEvents;\n // Reinit the click trigger on each mousedown.\n // In some cases we explicitly set this flag to prevent the click event to trigger,\n // and cancel event creation.\n this.domEvents.cancelClickEventCreation = false;\n // Also reinit this var on each mousedown.\n clickHoldACell.eventCreated = false;\n this.timeAtCursor = new Date(this.data.startDate);\n const {\n minutes,\n cursorCoords: {\n y\n }\n } = this.vuecal.minutesAtCursor(DOMEvent);\n this.timeAtCursor.setMinutes(minutes);\n const mouseDownOnEvent = this.isDOMElementAnEvent(DOMEvent.target);\n // Unfocus an event if any is focused and clicking on cell outside of an event.\n if (!mouseDownOnEvent && focusAnEvent._eid) {\n (this.view.events.find(e => e._eid === focusAnEvent._eid) || {}).focused = false;\n }\n\n // Only if event creation is allowed and mousedown is on a cell (not on event).\n if (this.editEvents.create && !mouseDownOnEvent) this.setUpEventCreation(DOMEvent, y);\n },\n setUpEventCreation(DOMEvent, startCursorY) {\n // If dragToCreateEvent is true, start the event creation from dragging\n // only on week and day views (doesn't make sense on month view).\n if (this.options.dragToCreateEvent && ['week', 'day'].includes(this.view.id)) {\n const {\n dragCreateAnEvent\n } = this.domEvents;\n dragCreateAnEvent.startCursorY = startCursorY;\n\n // If splitting days, store the clicked split to create an event in it from the global\n // mousemove handler in index.vue.\n dragCreateAnEvent.split = this.splitsCount ? this.getSplitAtCursor(DOMEvent) : null;\n\n // Save the time at cursor on initial mousedown.\n dragCreateAnEvent.start = this.timeAtCursor;\n\n // If snapToTime, set the start to the closest intervaled number.\n if (this.options.snapToTime) {\n let timeMinutes = this.timeAtCursor.getHours() * 60 + this.timeAtCursor.getMinutes();\n const plusHalfSnapTime = timeMinutes + this.options.snapToTime / 2;\n timeMinutes = plusHalfSnapTime - plusHalfSnapTime % this.options.snapToTime;\n dragCreateAnEvent.start.setHours(0, timeMinutes, 0, 0);\n }\n }\n\n // If the cellClickHold option is true and not mousedown on an event, click & hold to create an event.\n else if (this.options.cellClickHold && ['month', 'week', 'day'].includes(this.view.id)) {\n this.setUpCellHoldTimer(DOMEvent);\n }\n },\n // When click & holding a cell, and if allowed, set a timeout to create an event (can be cancelled).\n setUpCellHoldTimer(DOMEvent) {\n const {\n clickHoldACell\n } = this.domEvents;\n clickHoldACell.cellId = `${this.vuecal._.uid}_${this.data.formattedDate}`;\n // If splitting days, store the clicked split to create an event in it from the global\n // mousemove handler in index.vue.\n clickHoldACell.split = this.splitsCount ? this.getSplitAtCursor(DOMEvent) : null;\n clickHoldACell.timeoutId = setTimeout(() => {\n if (clickHoldACell.cellId && !this.domEvents.cancelClickEventCreation) {\n const {\n _eid\n } = this.utils.event.createAnEvent(this.timeAtCursor, null, clickHoldACell.split ? {\n split: clickHoldACell.split\n } : {});\n clickHoldACell.eventCreated = _eid;\n }\n }, clickHoldACell.timeout);\n },\n onCellTouchStart(DOMEvent, split = null) {\n // If not mousedown on an event.\n this.onCellMouseDown(DOMEvent, split, true);\n },\n onCellClick(DOMEvent, split) {\n if (DOMEvent.offsetY > 950 && DOMEvent.offsetY < 1700) {\n const dateFrom = split.date;\n dateFrom.setHours(Math.floor(DOMEvent.offsetY / 100), 0, 0, 0);\n const dateTo = new Date(dateFrom);\n dateTo.setHours(dateFrom.getHours() + 1);\n const time = moment__WEBPACK_IMPORTED_MODULE_3___default()(dateFrom).format('HH:mm');\n const isTeamCalendar = this.$route.name === 'Dashboard - Teams';\n const employee = isTeamCalendar ? split.employee_id : Number(localStorage.getItem('selectedEmployee') || this.user.id);\n this.$events.emit('show-menu-modal', {\n time,\n date: _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].formatDateTimeForBackend(dateFrom),\n employee\n });\n setTimeout(() => {\n this.$events.emit('add-timeblock', {\n id: null,\n start: _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].formatDateTimeForBackend(dateFrom),\n end: _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].formatDateTimeForBackend(dateTo)\n });\n }, 150);\n }\n if (!this.isDOMElementAnEvent(DOMEvent.target)) this.selectCell(DOMEvent);\n },\n onCellDblClick(DOMEvent) {\n const date = new Date(this.data.startDate);\n date.setMinutes(this.vuecal.minutesAtCursor(DOMEvent).minutes);\n\n // If splitting days, also return the clicked split on cell dblclick when emitting event.\n const split = this.splitsCount ? this.getSplitAtCursor(DOMEvent) : null;\n this.vuecal.$emit('cell-dblclick', split ? {\n date,\n split\n } : date);\n if (this.options.dblclickToNavigate) this.vuecal.switchToNarrowerView();\n },\n onCellContextMenu(DOMEvent) {\n DOMEvent.stopPropagation();\n DOMEvent.preventDefault();\n const date = new Date(this.data.startDate);\n const {\n cursorCoords,\n minutes\n } = this.vuecal.minutesAtCursor(DOMEvent);\n date.setMinutes(minutes);\n\n // If splitting days, also return the clicked split on cell contextmenu when emitting event.\n const split = this.splitsCount ? this.getSplitAtCursor(DOMEvent) : null;\n this.vuecal.$emit('cell-contextmenu', {\n date,\n ...cursorCoords,\n ...(split || {}),\n e: DOMEvent\n });\n }\n },\n computed: {\n ...(0,vuex__WEBPACK_IMPORTED_MODULE_4__.mapGetters)(\"auth\", [\"user\"]),\n // Drag & drop module.\n dnd() {\n return this.modules.dnd;\n },\n nowInMinutes() {\n return this.utils.date.dateToMinutes(this.vuecal.now);\n },\n isBeforeMinDate() {\n return this.minTimestamp !== null && this.minTimestamp > this.data.endDate.getTime();\n },\n isAfterMaxDate() {\n return this.maxTimestamp && this.maxTimestamp < this.data.startDate.getTime();\n },\n // Is the current cell disabled or not.\n isDisabled() {\n const {\n disableDays\n } = this.options;\n const {\n isYearsOrYearView\n } = this.vuecal;\n if (disableDays.length && disableDays.includes(this.data.formattedDate) && !isYearsOrYearView) return true;\n return this.isBeforeMinDate || this.isAfterMaxDate;\n },\n // Is the current cell selected or not.\n isSelected: {\n get() {\n let selected = false;\n const {\n selectedDate\n } = this.view;\n if (this.view.id === 'years') {\n selected = selectedDate.getFullYear() === this.data.startDate.getFullYear();\n } else if (this.view.id === 'year') {\n selected = selectedDate.getFullYear() === this.data.startDate.getFullYear() && selectedDate.getMonth() === this.data.startDate.getMonth();\n } else selected = selectedDate.getTime() === this.data.startDate.getTime();\n return selected;\n },\n set(date) {\n this.view.selectedDate = date;\n this.vuecal.$emit('update:selected-date', this.view.selectedDate);\n }\n },\n // Cache result for performance.\n isWeekOrDayView() {\n return ['week', 'day'].includes(this.view.id);\n },\n transitionDirection() {\n return this.vuecal.transitionDirection;\n },\n specialHours() {\n // this.data.specialHours is always an array, but may be empty.\n return this.data.specialHours.map(block => {\n let {\n from,\n to\n } = block;\n from = Math.max(from, this.options.timeFrom);\n to = Math.min(to, this.options.timeTo);\n return {\n ...block,\n height: (to - from) * this.timeScale,\n top: (from - this.options.timeFrom) * this.timeScale\n };\n });\n },\n events() {\n const {\n startDate: cellStart,\n endDate: cellEnd\n } = this.data;\n let events = [];\n\n // Calculate events on month/week/day views or years/year if eventsCountOnYearView.\n if (!(['years', 'year'].includes(this.view.id) && !this.options.eventsCountOnYearView)) {\n // Means that when vuecal.view.events changes all the cells will be looking up new value. :/\n // Also clone array to prevent modifying original.\n events = this.view.events.slice(0);\n if (this.view.id === 'month') {\n events.push(...this.view.outOfScopeEvents);\n }\n\n // Only keep events in cell time range.\n events = events.filter(e => this.utils.event.eventInRange(e, cellStart, cellEnd));\n if (this.options.showAllDayEvents && this.view.id !== 'month') events = events.filter(e => !!e.allDay === this.allDay);\n\n // From events in view, filter the ones that are out of `time-from`-`time-to` range in this cell.\n if (this.options.time && this.isWeekOrDayView && !this.allDay) {\n const {\n timeFrom,\n timeTo\n } = this.options;\n events = events.filter(e => {\n const segment = e.daysCount > 1 && e.segments[this.data.formattedDate] || {};\n const singleDayInRange = e.daysCount === 1 && e.startTimeMinutes < timeTo && e.endTimeMinutes > timeFrom;\n const multipleDayInRange = e.daysCount > 1 && segment.startTimeMinutes < timeTo && segment.endTimeMinutes > timeFrom;\n const recurrMultDayInRange = false; // e.daysCount > 1 && e.repeat && recurringEventInRange(e, cellStart, cellEnd)\n return e.allDay || singleDayInRange || multipleDayInRange || recurrMultDayInRange;\n });\n }\n\n // Position events with time in the timeline when there is a timeline and not in allDay slot.\n if (this.options.time && this.isWeekOrDayView && !(this.options.showAllDayEvents && this.allDay)) {\n // Sort events in chronological order.\n events.sort((a, b) => a.start < b.start ? -1 : 1);\n }\n\n // If splits, checkCellOverlappingEvents() is called from within computed splits.\n if (!this.cellSplits.length) this.$nextTick(this.checkCellOverlappingEvents);\n }\n return events;\n },\n eventsCount() {\n return this.events.length;\n },\n splits() {\n return this.cellSplits.map((item, i) => {\n const events = this.events.filter(e => e.split === item.id);\n const [overlaps, streak] = this.utils.event.checkCellOverlappingEvents(events.filter(e => !e.background && !e.allDay), this.options);\n return {\n ...item,\n overlaps,\n overlapsStreak: streak,\n events\n };\n });\n },\n splitsCount() {\n return this.splits.length;\n },\n cellClasses() {\n return {\n [this.data.class]: !!this.data.class,\n 'vuecal__cell--current': this.data.current,\n // E.g. Current year in years view.\n 'vuecal__cell--today': this.data.today,\n 'vuecal__cell--out-of-scope': this.data.outOfScope,\n 'vuecal__cell--before-min': this.isDisabled && this.isBeforeMinDate,\n 'vuecal__cell--after-max': this.isDisabled && this.isAfterMaxDate,\n 'vuecal__cell--disabled': this.isDisabled,\n 'vuecal__cell--selected': this.isSelected,\n 'vuecal__cell--highlighted': this.highlighted,\n 'vuecal__cell--has-splits': this.splitsCount,\n 'vuecal__cell--has-events': this.eventsCount\n };\n },\n cellStyles() {\n return {\n // cellWidth is only applied when hiding weekdays on month and week views.\n ...(this.cellWidth ? {\n width: `${this.cellWidth}%`\n } : {})\n };\n },\n timelineVisible() {\n const {\n time,\n timeTo\n } = this.options;\n return this.data.today && this.isWeekOrDayView && time && !this.allDay && this.nowInMinutes <= timeTo;\n },\n todaysTimePosition() {\n // Skip the Maths if not relevant.\n if (!this.data.today || !this.options.time) return;\n const minutesFromTop = this.nowInMinutes - this.options.timeFrom;\n return Math.round(minutesFromTop * this.timeScale);\n },\n timeScale() {\n return this.options.timeCellHeight / this.options.timeStep;\n }\n }\n});\n\n//# sourceURL=webpack://jandl/./src/plugins/app@vendor/vue-cal/cell.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.push.js */ \"./node_modules/core-js/modules/es.array.push.js\");\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _event_vue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./event.vue */ \"./src/plugins/app@vendor/vue-cal/event.vue\");\n/* harmony import */ var _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @/plugins/tm@_utils/tm.utils */ \"./src/plugins/tm@_utils/tm.utils.ts\");\n/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\");\n/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(moment__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var vuex__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! vuex */ \"./node_modules/vuex/dist/vuex.esm-bundler.js\");\n\n\n\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n inject: ['vuecal', 'utils', 'modules', 'view', 'domEvents'],\n components: {\n Event: _event_vue__WEBPACK_IMPORTED_MODULE_1__[\"default\"]\n },\n props: {\n // Vue-cal main component options (props).\n options: {\n type: Object,\n default: () => ({})\n },\n editEvents: {\n type: Object,\n required: true\n },\n data: {\n type: Object,\n required: true\n },\n cellSplits: {\n type: Array,\n default: () => []\n },\n minTimestamp: {\n type: [Number, null],\n default: null\n },\n maxTimestamp: {\n type: [Number, null],\n default: null\n },\n cellWidth: {\n type: [Number, Boolean],\n default: false\n },\n allDay: {\n type: Boolean,\n default: false\n }\n },\n data: () => ({\n tmUtils: _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_2__[\"default\"],\n cellOverlaps: {},\n cellOverlapsStreak: 1,\n // Largest amount of simultaneous events in cell.\n // On mouse down, save the time at cursor so it can be reused on cell focus event\n // where there is no cursor coords.\n timeAtCursor: null,\n highlighted: false,\n // On event drag over.\n highlightedSplit: null\n }),\n methods: {\n getSplitAtCursor({\n target\n }) {\n const targetIsSplit = target.classList.contains('vuecal__cell-split');\n let split = targetIsSplit ? target : this.vuecal.findAncestor(target, 'vuecal__cell-split');\n if (split) {\n split = split.attributes['data-split'].value;\n // Convert to a numeric value if split id is a number.\n if (parseInt(split).toString() === split.toString()) split = parseInt(split);\n }\n return split || null;\n },\n splitClasses(split) {\n return {\n 'vuecal__cell-split': true,\n 'vuecal__cell-split--highlighted': this.highlightedSplit === split.id,\n 'vuecal__cell-split--weekend': split.isWeekend,\n [split.class]: !!split.class\n };\n },\n checkCellOverlappingEvents() {\n // If splits, checkCellOverlappingEvents() is called from within computed splits.\n if (this.options.time && this.eventsCount && !this.splitsCount) {\n if (this.eventsCount === 1) {\n this.cellOverlaps = [];\n this.cellOverlapsStreak = 1;\n }\n // If only 1 event remains re-init the overlaps.\n else [this.cellOverlaps, this.cellOverlapsStreak] = this.utils.event.checkCellOverlappingEvents(this.events, this.options);\n }\n },\n isDOMElementAnEvent(el) {\n return this.vuecal.isDOMElementAnEvent(el);\n },\n /**\n * Select a cell and go to narrower view on double click or single click according to vuecalProps option.\n */\n selectCell(DOMEvent, force = false) {\n // If splitting days, also return the clicked split on cell click when emitting event.\n const split = this.splitsCount ? this.getSplitAtCursor(DOMEvent) : null;\n this.utils.cell.selectCell(force, this.timeAtCursor, split);\n this.timeAtCursor = null;\n },\n onCellkeyPressEnter(DOMEvent) {\n if (!this.isSelected) this.onCellFocus(DOMEvent);\n\n // If splitting days, also return the clicked split on cell keypress when emitting event.\n const split = this.splitsCount ? this.getSplitAtCursor(DOMEvent) : null;\n this.utils.cell.keyPressEnterCell(this.timeAtCursor, split);\n this.timeAtCursor = null;\n },\n /**\n * On cell focus, from tab key or from mousedown, highlight the cell and emit\n * the cell-focus event with the date of the cell start when focusing from tab or\n * the date & time at cursor if click/touch.\n */\n onCellFocus(DOMEvent) {\n if (!this.isSelected && !this.isDisabled) {\n this.isSelected = this.data.startDate; // Highlight the cell.\n\n // If splitting days, also return the clicked split on cell focus when emitting event.\n const split = this.splitsCount ? this.getSplitAtCursor(DOMEvent) : null;\n\n // Cell-focus event returns the cell start date (at midnight) if triggered from tab key,\n // or cursor coords time if clicked.\n const date = this.timeAtCursor || this.data.startDate;\n this.vuecal.$emit('cell-focus', split ? {\n date,\n split\n } : date);\n }\n },\n onCellMouseDown(DOMEvent, split = null, touch = false) {\n // Prevent a double mouse down on touch devices.\n if ('ontouchstart' in window && !touch) return false;\n if (!this.isSelected) this.onCellFocus(DOMEvent);\n const {\n clickHoldACell,\n focusAnEvent\n } = this.domEvents;\n // Reinit the click trigger on each mousedown.\n // In some cases we explicitly set this flag to prevent the click event to trigger,\n // and cancel event creation.\n this.domEvents.cancelClickEventCreation = false;\n // Also reinit this var on each mousedown.\n clickHoldACell.eventCreated = false;\n this.timeAtCursor = new Date(this.data.startDate);\n const {\n minutes,\n cursorCoords: {\n y\n }\n } = this.vuecal.minutesAtCursor(DOMEvent);\n this.timeAtCursor.setMinutes(minutes);\n const mouseDownOnEvent = this.isDOMElementAnEvent(DOMEvent.target);\n // Unfocus an event if any is focused and clicking on cell outside of an event.\n if (!mouseDownOnEvent && focusAnEvent._eid) {\n (this.view.events.find(e => e._eid === focusAnEvent._eid) || {}).focused = false;\n }\n\n // Only if event creation is allowed and mousedown is on a cell (not on event).\n if (this.editEvents.create && !mouseDownOnEvent) this.setUpEventCreation(DOMEvent, y);\n },\n setUpEventCreation(DOMEvent, startCursorY) {\n // If dragToCreateEvent is true, start the event creation from dragging\n // only on week and day views (doesn't make sense on month view).\n if (this.options.dragToCreateEvent && ['week', 'day'].includes(this.view.id)) {\n const {\n dragCreateAnEvent\n } = this.domEvents;\n dragCreateAnEvent.startCursorY = startCursorY;\n\n // If splitting days, store the clicked split to create an event in it from the global\n // mousemove handler in index.vue.\n dragCreateAnEvent.split = this.splitsCount ? this.getSplitAtCursor(DOMEvent) : null;\n\n // Save the time at cursor on initial mousedown.\n dragCreateAnEvent.start = this.timeAtCursor;\n\n // If snapToTime, set the start to the closest intervaled number.\n if (this.options.snapToTime) {\n let timeMinutes = this.timeAtCursor.getHours() * 60 + this.timeAtCursor.getMinutes();\n const plusHalfSnapTime = timeMinutes + this.options.snapToTime / 2;\n timeMinutes = plusHalfSnapTime - plusHalfSnapTime % this.options.snapToTime;\n dragCreateAnEvent.start.setHours(0, timeMinutes, 0, 0);\n }\n }\n\n // If the cellClickHold option is true and not mousedown on an event, click & hold to create an event.\n else if (this.options.cellClickHold && ['month', 'week', 'day'].includes(this.view.id)) {\n this.setUpCellHoldTimer(DOMEvent);\n }\n },\n // When click & holding a cell, and if allowed, set a timeout to create an event (can be cancelled).\n setUpCellHoldTimer(DOMEvent) {\n const {\n clickHoldACell\n } = this.domEvents;\n clickHoldACell.cellId = `${this.vuecal._.uid}_${this.data.formattedDate}`;\n // If splitting days, store the clicked split to create an event in it from the global\n // mousemove handler in index.vue.\n clickHoldACell.split = this.splitsCount ? this.getSplitAtCursor(DOMEvent) : null;\n clickHoldACell.timeoutId = setTimeout(() => {\n if (clickHoldACell.cellId && !this.domEvents.cancelClickEventCreation) {\n const {\n _eid\n } = this.utils.event.createAnEvent(this.timeAtCursor, null, clickHoldACell.split ? {\n split: clickHoldACell.split\n } : {});\n clickHoldACell.eventCreated = _eid;\n }\n }, clickHoldACell.timeout);\n },\n onCellTouchStart(DOMEvent, split = null) {\n // If not mousedown on an event.\n this.onCellMouseDown(DOMEvent, split, true);\n },\n onCellClick(DOMEvent, split) {\n const allNonWorkingHoursEvents = DOMEvent.target.querySelectorAll('.non-working-event');\n const calendarHeight = DOMEvent.target.offsetHeight;\n const morningNonWorkingHoursEventHeight = allNonWorkingHoursEvents?.[0]?.offsetHeight || 950;\n const afternoonNonWorkingHoursEventHeight = allNonWorkingHoursEvents?.[1]?.offsetHeight || 1700;\n if (\n // Check if the click is not in the non-working hours events\n DOMEvent.offsetY > morningNonWorkingHoursEventHeight && DOMEvent.offsetY < calendarHeight - afternoonNonWorkingHoursEventHeight) {\n const dateFrom = split.date;\n dateFrom.setHours(Math.floor(DOMEvent.offsetY / 100), 0, 0, 0);\n const dateTo = new Date(dateFrom);\n dateTo.setHours(dateFrom.getHours() + 1);\n const time = moment__WEBPACK_IMPORTED_MODULE_3___default()(dateFrom).format('HH:mm');\n const isTeamCalendar = this.$route.name === 'Dashboard - Teams';\n const employee = isTeamCalendar ? split.employee_id : Number(localStorage.getItem('selectedEmployee') || this.user.id);\n this.$events.emit('show-menu-modal', {\n time,\n date: _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].formatDateTimeForBackend(dateFrom),\n employee\n });\n setTimeout(() => {\n this.$events.emit('add-timeblock', {\n id: null,\n start: _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].formatDateTimeForBackend(dateFrom),\n end: _plugins_tm_utils_tm_utils__WEBPACK_IMPORTED_MODULE_2__[\"default\"].formatDateTimeForBackend(dateTo)\n });\n }, 150);\n }\n if (!this.isDOMElementAnEvent(DOMEvent.target)) this.selectCell(DOMEvent);\n },\n onCellDblClick(DOMEvent) {\n const date = new Date(this.data.startDate);\n date.setMinutes(this.vuecal.minutesAtCursor(DOMEvent).minutes);\n\n // If splitting days, also return the clicked split on cell dblclick when emitting event.\n const split = this.splitsCount ? this.getSplitAtCursor(DOMEvent) : null;\n this.vuecal.$emit('cell-dblclick', split ? {\n date,\n split\n } : date);\n if (this.options.dblclickToNavigate) this.vuecal.switchToNarrowerView();\n },\n onCellContextMenu(DOMEvent) {\n DOMEvent.stopPropagation();\n DOMEvent.preventDefault();\n const date = new Date(this.data.startDate);\n const {\n cursorCoords,\n minutes\n } = this.vuecal.minutesAtCursor(DOMEvent);\n date.setMinutes(minutes);\n\n // If splitting days, also return the clicked split on cell contextmenu when emitting event.\n const split = this.splitsCount ? this.getSplitAtCursor(DOMEvent) : null;\n this.vuecal.$emit('cell-contextmenu', {\n date,\n ...cursorCoords,\n ...(split || {}),\n e: DOMEvent\n });\n }\n },\n computed: {\n ...(0,vuex__WEBPACK_IMPORTED_MODULE_4__.mapGetters)('auth', ['user']),\n // Drag & drop module.\n dnd() {\n return this.modules.dnd;\n },\n nowInMinutes() {\n return this.utils.date.dateToMinutes(this.vuecal.now);\n },\n isBeforeMinDate() {\n return this.minTimestamp !== null && this.minTimestamp > this.data.endDate.getTime();\n },\n isAfterMaxDate() {\n return this.maxTimestamp && this.maxTimestamp < this.data.startDate.getTime();\n },\n // Is the current cell disabled or not.\n isDisabled() {\n const {\n disableDays\n } = this.options;\n const {\n isYearsOrYearView\n } = this.vuecal;\n if (disableDays.length && disableDays.includes(this.data.formattedDate) && !isYearsOrYearView) return true;\n return this.isBeforeMinDate || this.isAfterMaxDate;\n },\n // Is the current cell selected or not.\n isSelected: {\n get() {\n let selected = false;\n const {\n selectedDate\n } = this.view;\n if (this.view.id === 'years') {\n selected = selectedDate.getFullYear() === this.data.startDate.getFullYear();\n } else if (this.view.id === 'year') {\n selected = selectedDate.getFullYear() === this.data.startDate.getFullYear() && selectedDate.getMonth() === this.data.startDate.getMonth();\n } else selected = selectedDate.getTime() === this.data.startDate.getTime();\n return selected;\n },\n set(date) {\n this.view.selectedDate = date;\n this.vuecal.$emit('update:selected-date', this.view.selectedDate);\n }\n },\n // Cache result for performance.\n isWeekOrDayView() {\n return ['week', 'day'].includes(this.view.id);\n },\n transitionDirection() {\n return this.vuecal.transitionDirection;\n },\n specialHours() {\n // this.data.specialHours is always an array, but may be empty.\n return this.data.specialHours.map(block => {\n let {\n from,\n to\n } = block;\n from = Math.max(from, this.options.timeFrom);\n to = Math.min(to, this.options.timeTo);\n return {\n ...block,\n height: (to - from) * this.timeScale,\n top: (from - this.options.timeFrom) * this.timeScale\n };\n });\n },\n events() {\n const {\n startDate: cellStart,\n endDate: cellEnd\n } = this.data;\n let events = [];\n\n // Calculate events on month/week/day views or years/year if eventsCountOnYearView.\n if (!(['years', 'year'].includes(this.view.id) && !this.options.eventsCountOnYearView)) {\n // Means that when vuecal.view.events changes all the cells will be looking up new value. :/\n // Also clone array to prevent modifying original.\n events = this.view.events.slice(0);\n if (this.view.id === 'month') {\n events.push(...this.view.outOfScopeEvents);\n }\n\n // Only keep events in cell time range.\n events = events.filter(e => this.utils.event.eventInRange(e, cellStart, cellEnd));\n if (this.options.showAllDayEvents && this.view.id !== 'month') events = events.filter(e => !!e.allDay === this.allDay);\n\n // From events in view, filter the ones that are out of `time-from`-`time-to` range in this cell.\n if (this.options.time && this.isWeekOrDayView && !this.allDay) {\n const {\n timeFrom,\n timeTo\n } = this.options;\n events = events.filter(e => {\n const segment = e.daysCount > 1 && e.segments[this.data.formattedDate] || {};\n const singleDayInRange = e.daysCount === 1 && e.startTimeMinutes < timeTo && e.endTimeMinutes > timeFrom;\n const multipleDayInRange = e.daysCount > 1 && segment.startTimeMinutes < timeTo && segment.endTimeMinutes > timeFrom;\n const recurrMultDayInRange = false; // e.daysCount > 1 && e.repeat && recurringEventInRange(e, cellStart, cellEnd)\n return e.allDay || singleDayInRange || multipleDayInRange || recurrMultDayInRange;\n });\n }\n\n // Position events with time in the timeline when there is a timeline and not in allDay slot.\n if (this.options.time && this.isWeekOrDayView && !(this.options.showAllDayEvents && this.allDay)) {\n // Sort events in chronological order.\n events.sort((a, b) => a.start < b.start ? -1 : 1);\n }\n\n // If splits, checkCellOverlappingEvents() is called from within computed splits.\n if (!this.cellSplits.length) this.$nextTick(this.checkCellOverlappingEvents);\n }\n return events;\n },\n eventsCount() {\n return this.events.length;\n },\n splits() {\n return this.cellSplits.map((item, i) => {\n const events = this.events.filter(e => e.split === item.id);\n const [overlaps, streak] = this.utils.event.checkCellOverlappingEvents(events.filter(e => !e.background && !e.allDay), this.options);\n return {\n ...item,\n overlaps,\n overlapsStreak: streak,\n events\n };\n });\n },\n splitsCount() {\n return this.splits.length;\n },\n cellClasses() {\n return {\n [this.data.class]: !!this.data.class,\n 'vuecal__cell--current': this.data.current,\n // E.g. Current year in years view.\n 'vuecal__cell--today': this.data.today,\n 'vuecal__cell--out-of-scope': this.data.outOfScope,\n 'vuecal__cell--before-min': this.isDisabled && this.isBeforeMinDate,\n 'vuecal__cell--after-max': this.isDisabled && this.isAfterMaxDate,\n 'vuecal__cell--disabled': this.isDisabled,\n 'vuecal__cell--selected': this.isSelected,\n 'vuecal__cell--highlighted': this.highlighted,\n 'vuecal__cell--has-splits': this.splitsCount,\n 'vuecal__cell--has-events': this.eventsCount\n };\n },\n cellStyles() {\n return {\n // cellWidth is only applied when hiding weekdays on month and week views.\n ...(this.cellWidth ? {\n width: `${this.cellWidth}%`\n } : {})\n };\n },\n timelineVisible() {\n const {\n time,\n timeTo\n } = this.options;\n return this.data.today && this.isWeekOrDayView && time && !this.allDay && this.nowInMinutes <= timeTo;\n },\n todaysTimePosition() {\n // Skip the Maths if not relevant.\n if (!this.data.today || !this.options.time) return;\n const minutesFromTop = this.nowInMinutes - this.options.timeFrom;\n return Math.round(minutesFromTop * this.timeScale);\n },\n timeScale() {\n return this.options.timeCellHeight / this.options.timeStep;\n }\n }\n});\n\n//# sourceURL=webpack://jandl/./src/plugins/app@vendor/vue-cal/cell.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D"); /***/ }), @@ -972,7 +972,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/css-loader/dist/runtime/noSourceMaps.js */ \"./node_modules/css-loader/dist/runtime/noSourceMaps.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);\n// Imports\n\n\nvar ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".vuecal__cell {\\n position: relative;\\n width: 100%;\\n display: flex;\\n justify-content: center;\\n align-items: center;\\n text-align: center;\\n transition: 0.15s ease-in-out background-color;\\n}\\n.vuecal__cells.month-view .vuecal__cell, .vuecal__cells.week-view .vuecal__cell {\\n width: 14.2857%;\\n}\\n.vuecal--hide-weekends .vuecal__cells.month-view .vuecal__cell, .vuecal--hide-weekends .vuecal__cells.week-view .vuecal__cell {\\n width: 20%;\\n}\\n.vuecal__cells.years-view .vuecal__cell {\\n width: 20%;\\n}\\n.vuecal__cells.year-view .vuecal__cell {\\n width: 33.33%;\\n}\\n.vuecal__cells.day-view .vuecal__cell {\\n flex: 1;\\n}\\n.vuecal--overflow-x.vuecal--day-view .vuecal__cell {\\n width: auto;\\n}\\n.vuecal--click-to-navigate .vuecal__cell:not(.vuecal__cell--disabled) {\\n cursor: pointer;\\n}\\n.vuecal--view-with-time .vuecal__cell, .vuecal--week-view.vuecal--no-time .vuecal__cell:not(.vuecal__cell--has-splits), .vuecal--day-view.vuecal--no-time .vuecal__cell:not(.vuecal__cell--has-splits) {\\n display: block;\\n}\\n.vuecal__cell.vuecal__cell--has-splits {\\n flex-direction: row;\\n display: flex;\\n}\\n.vuecal__cell:before {\\n content: \\\"\\\";\\n position: absolute;\\n z-index: 0;\\n top: 0;\\n left: 0;\\n right: -1px;\\n bottom: -1px;\\n border: 1px solid rgba(196, 196, 196, 0.25);\\n}\\n.vuecal--overflow-x.vuecal--day-view .vuecal__cell:before {\\n bottom: 0;\\n}\\n.vuecal__cell--today, .vuecal__cell--current {\\n background-color: rgba(240, 240, 255, 0.4);\\n z-index: 1;\\n}\\n.vuecal__cell--selected {\\n background-color: rgba(235, 255, 245, 0.4);\\n z-index: 2;\\n}\\n.vuecal--day-view .vuecal__cell--selected {\\n background: none;\\n}\\n.vuecal__cell--out-of-scope {\\n color: rgba(0, 0, 0, 0.25);\\n}\\n.vuecal__cell--disabled {\\n color: rgba(0, 0, 0, 0.25);\\n cursor: not-allowed;\\n}\\n.vuecal__cell--highlighted:not(.vuecal__cell--has-splits), .vuecal__cell-split.vuecal__cell-split--highlighted {\\n background-color: rgba(0, 0, 0, 0.04);\\n transition-duration: 5ms;\\n}\\n.vuecal__cell-content {\\n position: relative;\\n width: 100%;\\n height: 100%;\\n outline: none;\\n}\\n.vuecal--years-view .vuecal__cell-content, .vuecal--year-view .vuecal__cell-content, .vuecal--month-view .vuecal__cell-content {\\n justify-content: center;\\n}\\n.vuecal__cell .cell-time-labels {\\n position: absolute;\\n top: 0;\\n left: 0;\\n right: 0;\\n bottom: 0;\\n display: flex;\\n flex-direction: column;\\n}\\n.vuecal__cell .cell-time-label {\\n flex-grow: 1;\\n font-size: 0.8em;\\n opacity: 0.3;\\n line-height: 1.7;\\n}\\n.vuecal__cell-split {\\n display: flex;\\n flex-grow: 1;\\n flex-direction: column;\\n height: 100%;\\n position: relative;\\n transition: 0.15s ease-in-out background-color;\\n}\\n.vuecal__cell-events {\\n width: 100%;\\n}\\n.vuecal__cell-events-count {\\n position: absolute;\\n left: 50%;\\n top: 65%;\\n transform: translateX(-50%);\\n min-width: 12px;\\n height: 12px;\\n line-height: 12px;\\n padding: 0 3px;\\n background: #999;\\n color: #fff;\\n border-radius: 12px;\\n font-size: 10px;\\n box-sizing: border-box;\\n}\\n.vuecal__cell .vuecal__special-hours {\\n position: absolute;\\n left: 0;\\n right: 0;\\n box-sizing: border-box;\\n}\\n.vuecal--overflow-x.vuecal--week-view .vuecal__cell, .vuecal__cell-split {\\n overflow: hidden;\\n}\\n.vuecal__no-event {\\n padding-top: 1em;\\n color: #aaa;\\n justify-self: flex-start;\\n margin-bottom: auto;\\n}\\n.vuecal__all-day .vuecal__no-event {\\n display: none;\\n}\\n.vuecal__now-line {\\n position: absolute;\\n left: 0;\\n width: 100%;\\n height: 0;\\n color: red;\\n border-top: 1px solid currentColor;\\n opacity: 0.6;\\n z-index: 1;\\n}\\n.vuecal__now-line:before {\\n content: \\\"\\\";\\n position: absolute;\\n top: -6px;\\n left: 0;\\n border: 5px solid transparent;\\n border-left-color: currentColor;\\n}\", \"\"]);\n// Exports\n/* harmony default export */ __webpack_exports__[\"default\"] = (___CSS_LOADER_EXPORT___);\n\n\n//# sourceURL=webpack://jandl/./src/plugins/app@vendor/vue-cal/cell.vue?./node_modules/css-loader/dist/cjs.js??clonedRuleSet-22.use%5B1%5D!./node_modules/vue-loader/dist/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-22.use%5B2%5D!./node_modules/sass-loader/dist/cjs.js??clonedRuleSet-22.use%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../node_modules/css-loader/dist/runtime/noSourceMaps.js */ \"./node_modules/css-loader/dist/runtime/noSourceMaps.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);\n// Imports\n\n\nvar ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".vuecal__cell {\\n position: relative;\\n width: 100%;\\n display: flex;\\n justify-content: center;\\n align-items: center;\\n text-align: center;\\n transition: 0.15s ease-in-out background-color;\\n}\\n.vuecal__cells.month-view .vuecal__cell, .vuecal__cells.week-view .vuecal__cell {\\n width: 14.2857%;\\n}\\n.vuecal--hide-weekends .vuecal__cells.month-view .vuecal__cell, .vuecal--hide-weekends .vuecal__cells.week-view .vuecal__cell {\\n width: 20%;\\n}\\n.vuecal__cells.years-view .vuecal__cell {\\n width: 20%;\\n}\\n.vuecal__cells.year-view .vuecal__cell {\\n width: 33.33%;\\n}\\n.vuecal__cells.day-view .vuecal__cell {\\n flex: 1;\\n}\\n.vuecal--overflow-x.vuecal--day-view .vuecal__cell {\\n width: auto;\\n}\\n.vuecal--click-to-navigate .vuecal__cell:not(.vuecal__cell--disabled) {\\n cursor: pointer;\\n}\\n.vuecal--view-with-time .vuecal__cell, .vuecal--week-view.vuecal--no-time .vuecal__cell:not(.vuecal__cell--has-splits), .vuecal--day-view.vuecal--no-time .vuecal__cell:not(.vuecal__cell--has-splits) {\\n display: block;\\n}\\n.vuecal__cell.vuecal__cell--has-splits {\\n flex-direction: row;\\n display: flex;\\n}\\n.vuecal__cell:before {\\n content: \\\"\\\";\\n position: absolute;\\n z-index: 0;\\n top: 0;\\n left: 0;\\n right: -1px;\\n bottom: -1px;\\n border: 1px solid rgba(196, 196, 196, 0.25);\\n}\\n.vuecal--overflow-x.vuecal--day-view .vuecal__cell:before {\\n bottom: 0;\\n}\\n.vuecal__cell--today, .vuecal__cell--current {\\n background-color: rgba(240, 240, 255, 0.4);\\n z-index: 1;\\n}\\n.vuecal__cell--selected {\\n background-color: rgba(235, 255, 245, 0.4);\\n z-index: 2;\\n}\\n.vuecal--day-view .vuecal__cell--selected {\\n background: none;\\n}\\n.vuecal__cell--out-of-scope {\\n color: rgba(0, 0, 0, 0.25);\\n}\\n.vuecal__cell--disabled {\\n color: rgba(0, 0, 0, 0.25);\\n cursor: not-allowed;\\n}\\n.vuecal__cell--highlighted:not(.vuecal__cell--has-splits), .vuecal__cell-split.vuecal__cell-split--highlighted {\\n background-color: rgba(0, 0, 0, 0.04);\\n transition-duration: 5ms;\\n}\\n.vuecal__cell-content {\\n position: relative;\\n width: 100%;\\n height: 100%;\\n outline: none;\\n}\\n.vuecal--years-view .vuecal__cell-content, .vuecal--year-view .vuecal__cell-content, .vuecal--month-view .vuecal__cell-content {\\n justify-content: center;\\n}\\n.vuecal__cell .cell-time-labels {\\n position: absolute;\\n top: 0;\\n left: 0;\\n right: 0;\\n bottom: 0;\\n display: flex;\\n flex-direction: column;\\n}\\n.vuecal__cell .cell-time-label {\\n flex-grow: 1;\\n font-size: 0.8em;\\n opacity: 0.3;\\n line-height: 1.7;\\n}\\n.vuecal__cell-split {\\n display: flex;\\n flex-grow: 1;\\n flex-direction: column;\\n height: 100%;\\n position: relative;\\n transition: 0.15s ease-in-out background-color;\\n}\\n.vuecal__cell-events {\\n width: 100%;\\n}\\n.vuecal__cell-events-count {\\n position: absolute;\\n left: 50%;\\n top: 65%;\\n transform: translateX(-50%);\\n min-width: 12px;\\n height: 12px;\\n line-height: 12px;\\n padding: 0 3px;\\n background: #999;\\n color: #fff;\\n border-radius: 12px;\\n font-size: 10px;\\n box-sizing: border-box;\\n}\\n.vuecal__cell .vuecal__special-hours {\\n position: absolute;\\n left: 0;\\n right: 0;\\n box-sizing: border-box;\\n}\\n.vuecal--overflow-x.vuecal--week-view .vuecal__cell,\\n.vuecal__cell-split {\\n overflow: hidden;\\n}\\n.vuecal__no-event {\\n padding-top: 1em;\\n color: #aaa;\\n justify-self: flex-start;\\n margin-bottom: auto;\\n}\\n.vuecal__all-day .vuecal__no-event {\\n display: none;\\n}\\n.vuecal__now-line {\\n position: absolute;\\n left: 0;\\n width: 100%;\\n height: 0;\\n color: red;\\n border-top: 1px solid currentColor;\\n opacity: 0.6;\\n z-index: 1;\\n}\\n.vuecal__now-line:before {\\n content: \\\"\\\";\\n position: absolute;\\n top: -6px;\\n left: 0;\\n border: 5px solid transparent;\\n border-left-color: currentColor;\\n}\", \"\"]);\n// Exports\n/* harmony default export */ __webpack_exports__[\"default\"] = (___CSS_LOADER_EXPORT___);\n\n\n//# sourceURL=webpack://jandl/./src/plugins/app@vendor/vue-cal/cell.vue?./node_modules/css-loader/dist/cjs.js??clonedRuleSet-22.use%5B1%5D!./node_modules/vue-loader/dist/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-22.use%5B2%5D!./node_modules/sass-loader/dist/cjs.js??clonedRuleSet-22.use%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D"); /***/ }),