mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-10-21 19:29:35 +00:00
WIP: added print mods to the range mode
This commit is contained in:
@@ -92,9 +92,16 @@ function generatePrintCSS($path)
|
||||
$ci =& get_instance();
|
||||
$cachetoken = '?'.$ci->config->item('fhcomplete_build_version');
|
||||
|
||||
if (isset($path)) {
|
||||
if (is_array($path)) {
|
||||
foreach ($path as $p) {
|
||||
echo sprintf($cssLink, base_url($p).$cachetoken) . PHP_EOL;
|
||||
}
|
||||
|
||||
|
||||
} else if (isset($path)) {
|
||||
echo sprintf($cssLink, base_url($path).$cachetoken) . PHP_EOL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,7 +31,10 @@
|
||||
'customJSModules' => [
|
||||
'public/js/apps/Tempus.js'
|
||||
],
|
||||
'printCssPath' => 'public/css/Tempus_print.css'
|
||||
'printCssPath' => [
|
||||
'public/css/Tempus_print.css',
|
||||
'public/css/Tempus_print_range.css'
|
||||
]
|
||||
);
|
||||
|
||||
$this->load->view('templates/FHC-Header', $includesArray);
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
@page {
|
||||
size: landscape;
|
||||
}
|
||||
|
||||
* {
|
||||
background-color: white !important;
|
||||
color: black !important;
|
||||
font-size: x-small !important;
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
html,
|
||||
body,
|
||||
#main,
|
||||
.tempus {
|
||||
height: auto !important;
|
||||
min-height: 0 !important;
|
||||
max-height: none !important;
|
||||
}
|
||||
|
||||
.fhc-calendar-base-slider > div {
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
header,
|
||||
#skiplink,
|
||||
#cis-lvplan-personal-heading,
|
||||
#sidebarMenu,
|
||||
.cis-lvplan-personal hr,
|
||||
.tempus .horizontalsplit-container > .horizontalsplitted:first-child,
|
||||
.tempus .horizontalsplitter,
|
||||
.fhc-calendar-base-header,
|
||||
.fhc-calendar-mode-range .grid-allday,
|
||||
.fhc-calendar-mode-range #rangePresetSelector,
|
||||
.fhc-calendar-base-grid-dropzone,
|
||||
.fhc-calendar-base-grid .main-header .form-check,
|
||||
.fhc-calendar-base-grid-line-background,
|
||||
.fhc-calendar-base-grid-line-background > div,
|
||||
.p-tooltip {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.tempus .container-fluid,
|
||||
.tempus .container-fluid > .row,
|
||||
.tempus .horizontalsplit-container {
|
||||
display: block !important;
|
||||
width: 100% !important;
|
||||
max-width: none !important;
|
||||
height: auto !important;
|
||||
max-height: none !important;
|
||||
}
|
||||
|
||||
.tempus .horizontalsplit-container > .horizontalsplitted:last-child {
|
||||
display: block !important;
|
||||
width: 100% !important;
|
||||
max-width: none !important;
|
||||
height: auto !important;
|
||||
max-height: none !important;
|
||||
flex: 0 0 100% !important;
|
||||
}
|
||||
|
||||
.fhc-calendar-mode-range,
|
||||
.fhc-calendar-mode-range > .flex-grow-1,
|
||||
.fhc-calendar-mode-range .fhc-calendar-base-slider {
|
||||
width: 100% !important;
|
||||
max-width: 100% !important;
|
||||
min-width: 0 !important;
|
||||
}
|
||||
|
||||
.fhc-calendar-mode-range .fhc-calendar-mode-range-view,
|
||||
.fhc-calendar-mode-range .fhc-calendar-mode-range-view > div {
|
||||
width: 100% !important;
|
||||
height: 100vh !important;
|
||||
min-width: 0 !important;
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
.fhc-calendar-mode-range .fhc-calendar-mode-range-view > div {
|
||||
width: var(--fhc-calendar-print-layout-width, 100%) !important;
|
||||
transform: scale(
|
||||
var(--fhc-calendar-print-scale-x, 1),
|
||||
var(--fhc-calendar-print-scale-y, 1)
|
||||
) !important;
|
||||
transform-origin: top left !important;
|
||||
}
|
||||
|
||||
.fhc-calendar-print-measure {
|
||||
position: fixed !important;
|
||||
visibility: hidden !important;
|
||||
width: 100vw !important;
|
||||
height: 0 !important;
|
||||
pointer-events: none !important;
|
||||
}
|
||||
|
||||
.fhc-calendar-mode-range .fhc-calendar-mode-range-view > div {
|
||||
break-after: page !important;
|
||||
page-break-after: always !important;
|
||||
break-inside: avoid-page !important;
|
||||
page-break-inside: avoid !important;
|
||||
}
|
||||
|
||||
.fhc-calendar-mode-range .fhc-calendar-base-grid {
|
||||
width: 100% !important;
|
||||
grid-template-rows: auto minmax(0, 1fr) !important;
|
||||
gap: 1px !important;
|
||||
background-color: #b8b8b8 !important;
|
||||
}
|
||||
|
||||
.fhc-calendar-mode-range .fhc-calendar-base-grid .grid-header,
|
||||
.fhc-calendar-mode-range .fhc-calendar-base-grid .grid-main,
|
||||
.fhc-calendar-mode-range .fhc-calendar-base-grid .grid-body {
|
||||
gap: 1px !important;
|
||||
background-color: #b8b8b8 !important;
|
||||
}
|
||||
|
||||
.fhc-calendar-mode-range .fhc-calendar-base-grid > #grid-main-scrollable {
|
||||
border-top: solid 1px #b8b8b8 !important;
|
||||
grid-row: 2 !important;
|
||||
height: 100% !important;
|
||||
min-height: 0 !important;
|
||||
}
|
||||
|
||||
.fhc-calendar-mode-range .fhc-calendar-base-grid .grid-main,
|
||||
.fhc-calendar-mode-range .fhc-calendar-base-grid .grid-body {
|
||||
height: 100% !important;
|
||||
min-height: 0 !important;
|
||||
align-self: stretch !important;
|
||||
}
|
||||
|
||||
.fhc-calendar-mode-range .fhc-calendar-base-grid .grid-header:before,
|
||||
.fhc-calendar-mode-range .fhc-calendar-base-grid .main-header,
|
||||
.fhc-calendar-mode-range .fhc-calendar-base-grid .part-header,
|
||||
.fhc-calendar-mode-range .fhc-calendar-base-grid .part-body {
|
||||
background-color: white !important;
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
.fhc-calendar-mode-range .fhc-calendar-base-grid .grid-header:before {
|
||||
grid-column: 1 !important;
|
||||
grid-row: 1 !important;
|
||||
}
|
||||
|
||||
.fhc-calendar-mode-range .main-header:not(.main-header-empty) {
|
||||
padding-top: 0.25rem !important;
|
||||
}
|
||||
|
||||
.fhc-calendar-mode-range .fhc-calendar-base-grid-line {
|
||||
background-color: transparent !important;
|
||||
border: 0 !important;
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
.fhc-calendar-mode-range .fhc-calendar-base-grid-line-event {
|
||||
break-inside: avoid !important;
|
||||
margin: 1px !important;
|
||||
page-break-inside: avoid !important;
|
||||
z-index: auto !important;
|
||||
}
|
||||
|
||||
.fhc-calendar-mode-range
|
||||
.fhc-calendar-base-grid-line-event
|
||||
> .rangePageContainer {
|
||||
background-color: var(--event-bg, var(--event-default-bg)) !important;
|
||||
break-inside: avoid !important;
|
||||
page-break-inside: avoid !important;
|
||||
}
|
||||
|
||||
.fhc-calendar-mode-range
|
||||
.fhc-calendar-base-grid-line-event
|
||||
> .rangePageContainer
|
||||
* {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
import BaseSlider from "../Base/Slider.js";
|
||||
import RangeView from "./Range/View.js";
|
||||
import FormInput from "../../Form/Input.js";
|
||||
import BaseSlider from '../Base/Slider.js';
|
||||
import RangeView from './Range/View.js';
|
||||
import FormInput from '../../Form/Input.js';
|
||||
|
||||
export default {
|
||||
name: "ModeRange",
|
||||
name: 'ModeRange',
|
||||
components: {
|
||||
BaseSlider,
|
||||
RangeView,
|
||||
@@ -26,7 +26,7 @@ export default {
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
emits: ["update:currentDate", "update:range", "click", "requestModalOpen"],
|
||||
emits: ['update:currentDate', 'update:range', 'click', 'requestModalOpen'],
|
||||
data() {
|
||||
return {
|
||||
selectedRangePreset: null,
|
||||
@@ -34,18 +34,21 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
range() {
|
||||
let first = this.$props.currentDate;
|
||||
let last = first.plus({ days: this.rangeLength });
|
||||
const rangeLength = Math.max(parseInt(this.rangeLength) || 1, 1);
|
||||
const first = this.currentDate.startOf('week', { useLocaleWeeks: true });
|
||||
const last = this.currentDate
|
||||
.plus({ days: rangeLength - 1 })
|
||||
.endOf('week', { useLocaleWeeks: true });
|
||||
|
||||
return luxon.Interval.fromDateTimes(first, last);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
currentDate() {
|
||||
this.$emit("update:range", this.range);
|
||||
this.$emit('update:range', this.range);
|
||||
},
|
||||
rangeLength() {
|
||||
this.$emit("update:range", this.range);
|
||||
this.$emit('update:range', this.range);
|
||||
},
|
||||
selectedRangePreset() {
|
||||
if (!this.selectedRangePreset) return;
|
||||
@@ -55,10 +58,9 @@ export default {
|
||||
);
|
||||
if (!preset) return;
|
||||
|
||||
this.$emit("update:date", {
|
||||
this.$emit('update:date', {
|
||||
date: preset.startDate,
|
||||
rangeLength:
|
||||
preset.endDate.diff(preset.startDate, "days").days + 1,
|
||||
rangeLength: preset.endDate.diff(preset.startDate, 'days').days + 1,
|
||||
});
|
||||
|
||||
this.selectedRangePreset = null;
|
||||
@@ -66,33 +68,113 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
viewAttrs() {
|
||||
const day = this.$props.currentDate.startOf("day");
|
||||
const day = this.$props.currentDate.startOf('day');
|
||||
const rangeLength = parseInt(this.rangeLength);
|
||||
return { ...this.$attrs, day, rangeLength };
|
||||
},
|
||||
handleClickDefaults(evt) {
|
||||
switch (evt.detail.source) {
|
||||
case "day":
|
||||
case 'day':
|
||||
// default: Set current-date
|
||||
this.$emit("update:currentDate", {
|
||||
this.$emit('update:currentDate', {
|
||||
date: evt.detail.value,
|
||||
});
|
||||
break;
|
||||
case "event":
|
||||
case 'event':
|
||||
// default: Request Modal
|
||||
this.$emit("requestModalOpen", { event: evt.detail.value });
|
||||
this.$emit('requestModalOpen', { event: evt.detail.value });
|
||||
break;
|
||||
}
|
||||
},
|
||||
preparePrintLayout() {
|
||||
const view = this.$el?.querySelector('.fhc-calendar-mode-range-view');
|
||||
if (!view) return;
|
||||
|
||||
const weeks = Array.from(view.children);
|
||||
weeks.forEach((week) => {
|
||||
week.style.setProperty('--fhc-calendar-print-scale-x', '1');
|
||||
week.style.setProperty('--fhc-calendar-print-scale-y', '1');
|
||||
week.style.setProperty(
|
||||
'--fhc-calendar-print-layout-width',
|
||||
'max-content',
|
||||
);
|
||||
});
|
||||
|
||||
const viewWidth = view.getBoundingClientRect().width;
|
||||
const printViewportWidth = document
|
||||
.querySelector('.fhc-calendar-base-slider')
|
||||
.getBoundingClientRect().width;
|
||||
const availableWidth = printViewportWidth
|
||||
? Math.min(viewWidth, printViewportWidth)
|
||||
: viewWidth;
|
||||
if (!availableWidth) return;
|
||||
|
||||
weeks.forEach((week) => {
|
||||
const grid = week.querySelector('.fhc-calendar-base-grid');
|
||||
if (!grid) return;
|
||||
|
||||
const gridRect = grid.getBoundingClientRect();
|
||||
const contentRight = Array.from(grid.querySelectorAll('*')).reduce(
|
||||
(right, element) =>
|
||||
Math.max(right, element.getBoundingClientRect().right),
|
||||
gridRect.right,
|
||||
);
|
||||
const gridWidth = Math.ceil(
|
||||
Math.max(
|
||||
week.scrollWidth,
|
||||
grid.scrollWidth,
|
||||
gridRect.width,
|
||||
contentRight - gridRect.left,
|
||||
),
|
||||
);
|
||||
if (!gridWidth) return;
|
||||
|
||||
const scale = Math.min(1, availableWidth / gridWidth);
|
||||
const verticalScale = 1 - (1 - scale) * 0.9;
|
||||
|
||||
week.style.setProperty(
|
||||
'--fhc-calendar-print-scale-x',
|
||||
scale.toFixed(4),
|
||||
);
|
||||
week.style.setProperty(
|
||||
'--fhc-calendar-print-scale-y',
|
||||
verticalScale.toFixed(4),
|
||||
);
|
||||
week.style.setProperty(
|
||||
'--fhc-calendar-print-layout-width',
|
||||
gridWidth + 'px',
|
||||
);
|
||||
});
|
||||
},
|
||||
resetPrintLayout() {
|
||||
const view = this.$el?.querySelector('.fhc-calendar-mode-week-view');
|
||||
if (!view) return;
|
||||
|
||||
Array.from(view.children).forEach((week) => {
|
||||
week.style.removeProperty('--fhc-calendar-print-scale-x');
|
||||
week.style.removeProperty('--fhc-calendar-print-scale-y');
|
||||
week.style.removeProperty('--fhc-calendar-print-layout-width');
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$emit("update:range", this.range);
|
||||
this.$emit('update:range', this.range);
|
||||
|
||||
this.beforePrintHandler = () => this.preparePrintLayout();
|
||||
this.afterPrintHandler = () => this.resetPrintLayout();
|
||||
window.addEventListener('beforeprint', this.beforePrintHandler);
|
||||
window.addEventListener('afterprint', this.afterPrintHandler);
|
||||
},
|
||||
beforeUnmount() {
|
||||
window.removeEventListener('beforeprint', this.beforePrintHandler);
|
||||
window.removeEventListener('afterprint', this.afterPrintHandler);
|
||||
},
|
||||
template: /*html*/ `
|
||||
<div
|
||||
class="fhc-calendar-mode-range flex-grow-1 position-relative d-flex flex-column"
|
||||
@cal-click-default.capture="handleClickDefaults"
|
||||
>
|
||||
<div ref="printMeasure" class="fhc-calendar-print-measure" aria-hidden="true"></div>
|
||||
<div
|
||||
v-if="rangeViewPresetsConfig?.presets?.length"
|
||||
id="rangePresetSelector"
|
||||
|
||||
@@ -38,7 +38,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visibleDays: JSON.parse(
|
||||
dayVisibilityStates: JSON.parse(
|
||||
localStorage.getItem('fhc-calender-visible-days'),
|
||||
) ?? [true, true, true, true, true, true, true],
|
||||
gridWidthEqualizingData: {
|
||||
@@ -48,11 +48,6 @@ export default {
|
||||
syncing: false,
|
||||
isActive: false,
|
||||
},
|
||||
gridHeightEqualizingData: {
|
||||
resizeObserver: null,
|
||||
gridHeights: [],
|
||||
observedGrids: Vue.markRaw(new Set()),
|
||||
},
|
||||
gridColumnWidthEqualizingData: {
|
||||
sharedDayWidths: null,
|
||||
largestDayWidths: null,
|
||||
@@ -128,21 +123,16 @@ export default {
|
||||
},
|
||||
);
|
||||
},
|
||||
dayVisibility() {
|
||||
return this.daysGroupedByWeek[this.weekStartDays[0]].map(
|
||||
(date) => this.visibleDays[date.weekday - 1],
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
isToday(date) {
|
||||
return date.hasSame(luxon.DateTime.now().setZone(this.timezone), 'day');
|
||||
},
|
||||
toggleDayVisibility(day) {
|
||||
this.visibleDays.splice(day, 1, !this.visibleDays[day]);
|
||||
this.dayVisibilityStates.splice(day, 1, !this.dayVisibilityStates[day]);
|
||||
localStorage.setItem(
|
||||
'fhc-calender-visible-days',
|
||||
JSON.stringify(this.visibleDays),
|
||||
JSON.stringify(this.dayVisibilityStates),
|
||||
);
|
||||
this.$nextTick(() => this.scheduleGridWidthSync());
|
||||
},
|
||||
@@ -281,55 +271,6 @@ export default {
|
||||
grid.style.removeProperty('min-width'),
|
||||
);
|
||||
},
|
||||
resetGridHeightsForEventReload() {
|
||||
this.gridHeightEqualizingData.gridHeights = [];
|
||||
this.$nextTick(() => this.initializeGridHeights());
|
||||
},
|
||||
initializeGridHeights() {
|
||||
const grids = this.getGridElements();
|
||||
const firstGrid = grids[0];
|
||||
if (!firstGrid) return;
|
||||
const initialGridHeight = Math.ceil(
|
||||
firstGrid.getBoundingClientRect().height,
|
||||
);
|
||||
if (!Number.isFinite(initialGridHeight) || initialGridHeight <= 0) return;
|
||||
this.gridHeightEqualizingData.gridHeights = grids.map(
|
||||
() => initialGridHeight,
|
||||
);
|
||||
this.$nextTick(() => this.syncGridResizeObservation());
|
||||
},
|
||||
syncGridResizeObservation() {
|
||||
const grids = this.getGridElements();
|
||||
const currentGrids = new Set(grids);
|
||||
this.gridHeightEqualizingData.observedGrids.forEach((grid) => {
|
||||
if (!currentGrids.has(grid)) {
|
||||
this.gridHeightEqualizingData?.resizeObserver.unobserve(grid);
|
||||
this.gridHeightEqualizingData.observedGrids.delete(grid);
|
||||
}
|
||||
});
|
||||
if (this.gridHeightEqualizingData.gridHeights.length > grids.length)
|
||||
this.gridHeightEqualizingData.gridHeights.splice(grids.length);
|
||||
grids.forEach((grid, index) => {
|
||||
if (!this.gridHeightEqualizingData.observedGrids.has(grid)) {
|
||||
this.gridHeightEqualizingData.resizeObserver.observe(grid);
|
||||
this.gridHeightEqualizingData.observedGrids.add(grid);
|
||||
this.setGridHeight(
|
||||
index,
|
||||
Math.ceil(grid.getBoundingClientRect().height),
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
measureAndRecordGridHeight(grid) {
|
||||
const index = this.getGridElements().indexOf(grid);
|
||||
if (index === -1) return;
|
||||
this.setGridHeight(index, Math.ceil(grid.getBoundingClientRect().height));
|
||||
},
|
||||
setGridHeight(index, height) {
|
||||
if (!Number.isFinite(height) || height <= 0) return;
|
||||
if (this.gridHeightEqualizingData.gridHeights[index] !== height)
|
||||
this.gridHeightEqualizingData.gridHeights.splice(index, 1, height);
|
||||
},
|
||||
resetColumnWidthAdjustment() {
|
||||
this.gridColumnWidthEqualizingData.sharedDayWidths = null;
|
||||
this.gridColumnWidthEqualizingData.largestDayWidths = null;
|
||||
@@ -360,7 +301,7 @@ export default {
|
||||
flushFreshColumnWidthSync() {
|
||||
if (
|
||||
!this.gridColumnWidthEqualizingData.syncRequested ||
|
||||
this.gridWidthEqualizingData.syncing
|
||||
this.gridColumnWidthEqualizingData.syncing
|
||||
)
|
||||
return;
|
||||
this.gridColumnWidthEqualizingData.syncRequested = false;
|
||||
@@ -400,7 +341,6 @@ export default {
|
||||
);
|
||||
if (!relevantMutations.length) return;
|
||||
this.$nextTick(() => {
|
||||
this.syncGridResizeObservation();
|
||||
if (
|
||||
!this.gridColumnWidthEqualizingData.initialEventsSeen &&
|
||||
this.hasColumnWidthEvents()
|
||||
@@ -418,15 +358,6 @@ export default {
|
||||
subtree: true,
|
||||
});
|
||||
|
||||
this.gridHeightEqualizingData.resizeObserver = Vue.markRaw(
|
||||
new ResizeObserver((entries) => {
|
||||
entries.forEach((entry) =>
|
||||
this.measureAndRecordGridHeight(entry.target),
|
||||
);
|
||||
}),
|
||||
);
|
||||
this.initializeGridHeights();
|
||||
|
||||
if (this.hasColumnWidthEvents()) {
|
||||
this.gridColumnWidthEqualizingData.initialEventsSeen = true;
|
||||
this.startFreshColumnWidthSync();
|
||||
@@ -445,8 +376,6 @@ export default {
|
||||
cancelAnimationFrame(
|
||||
this.gridColumnWidthEqualizingData.initialSyncAnimationFrame,
|
||||
);
|
||||
|
||||
this.gridHeightEqualizingData?.resizeObserver?.disconnect();
|
||||
},
|
||||
template: /* html */ `
|
||||
<div
|
||||
@@ -468,7 +397,7 @@ export default {
|
||||
weekStartDay in eventsGroupedByWeek ? eventsGroupedByWeek[weekStartDay] : []
|
||||
"
|
||||
:shouldMatchParentHeight="false"
|
||||
:day-visibility="dayVisibility"
|
||||
:day-visibility="dayVisibilityStates"
|
||||
:sticky-header="isHeaderSticky"
|
||||
:scrollable="false"
|
||||
:main-column-widths="gridColumnWidthEqualizingData.sharedDayWidths"
|
||||
@@ -485,7 +414,7 @@ export default {
|
||||
/>
|
||||
<form-input
|
||||
type="checkbox"
|
||||
:checked="visibleDays[date.weekday - 1]"
|
||||
:checked="dayVisibilityStates[date.weekday - 1]"
|
||||
@change="toggleDayVisibility(date.weekday - 1)"
|
||||
@click.stop
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user