diff --git a/public/css/components/calendar/events.css b/public/css/components/calendar/events.css
index f224c6f7b..b10303a7f 100644
--- a/public/css/components/calendar/events.css
+++ b/public/css/components/calendar/events.css
@@ -109,3 +109,24 @@
z-index: 2;
}
+.fhc-calendar-mode-range .fhc-calendar-base-grid-line-event {
+ position: relative;
+}
+
+.fhc-calendar-mode-range .fhc-resize-bar {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ height: auto;
+ width: 15px;
+ margin: 0;
+ cursor: ew-resize;
+}
+
+.fhc-calendar-mode-range .fhc-resize-bar--left {
+ left: 0;
+}
+
+.fhc-calendar-mode-range .fhc-resize-bar--right {
+ right: 0;
+}
diff --git a/public/js/components/Calendar/Base/Grid.js b/public/js/components/Calendar/Base/Grid.js
index 081d6b2a9..148a46fd4 100644
--- a/public/js/components/Calendar/Base/Grid.js
+++ b/public/js/components/Calendar/Base/Grid.js
@@ -479,7 +479,7 @@ export default {
ctrlKey: !!(evt?.ctrlKey || evt?.metaKey)
});
},
- handleResizeStart({ edge, evt, el, event })
+ handleResizeStart({ edge, evt, horizontal, el, event })
{
const gridEl = this.$refs.body;
@@ -490,6 +490,7 @@ export default {
el,
gridEl,
event,
+ horizontal,
timeGrid: this.timeGrid,
onEnd: ({ event, newStart, newEnd }) => {
const orig = event?.orig;
@@ -650,4 +651,4 @@ export default {
`
-}
\ No newline at end of file
+}
diff --git a/public/js/components/Calendar/Base/Grid/Line/Event.js b/public/js/components/Calendar/Base/Grid/Line/Event.js
index 04d733583..1bd97ef8c 100644
--- a/public/js/components/Calendar/Base/Grid/Line/Event.js
+++ b/public/js/components/Calendar/Base/Grid/Line/Event.js
@@ -94,6 +94,7 @@ export default {
this.$emit('resize-start', {
edge,
evt,
+ horizontal: this.mode === 'range',
el: this.$refs.eventEl,
event: this.event
});
@@ -153,7 +154,7 @@ export default {
data-cy="calendar-event"
>
+
+
+
+
+
+
-
`
-}
\ No newline at end of file
+}
diff --git a/public/js/components/Calendar/Tempus.js b/public/js/components/Calendar/Tempus.js
index 64b5ef298..07b3d7441 100644
--- a/public/js/components/Calendar/Tempus.js
+++ b/public/js/components/Calendar/Tempus.js
@@ -5,15 +5,22 @@ import { useEventLoader } from '../../composables/EventLoader.js';
import ModeWeek from './Mode/Week.js';
import ModeMonth from './Mode/Month.js';
import ModeTable from './Mode/Table.js';
+import ModeRange from './Mode/Range.js';
import ApiKalender from '../../api/factory/tempus/kalender.js';
import draggable from '../../directives/draggable.js';
-
+import ApiStudiensemester from '../../api/factory/studiensemester.js';
export default {
name: "CalendarTempus",
components: {
FhcCalendar
},
+ provide() {
+ return {
+ rangeLength: Vue.computed(() => this.rangeLength),
+ rangeViewPresets: Vue.computed(() => this.semesterRangePresets)
+ };
+ },
inject: {
renderers: {from: 'renderers'},
canToggleGrid: {
@@ -25,7 +32,14 @@ export default {
default: {
visible_status: 'all'
}
- }
+ },
+ rangeLength: {
+ default: 1,
+ },
+ shouldIncludeRangeMode: {
+ type: Boolean,
+ default: false,
+ },
},
directives: {
draggable,
@@ -79,13 +93,13 @@ export default {
"event-unhover",
"open-reservierung"
],
-
data() {
return {
modes: {
week: Vue.markRaw(ModeWeek),
month: Vue.markRaw(ModeMonth),
tableList: Vue.markRaw(ModeTable),
+ range: Vue.markRaw(ModeRange),
},
modeOptions: {
day: {
@@ -100,6 +114,10 @@ export default {
teachingunits: null,
hoursplan: null,
showRaster: true,
+ semesterRangePresets: {
+ label: null,
+ presets: [],
+ },
};
},
computed: {
@@ -114,7 +132,9 @@ export default {
end: now.startOf('day')
}];
}
- else
+ else if (this.mode == 'Range') {
+ return [];
+ } else
{
past = [{
class: 'background-past',
@@ -183,6 +203,24 @@ export default {
navigateNext() {
this.$refs.calendar.clickNext();
},
+ async fetchSemesters() {
+ const semestersResponse = await this.$api.call(ApiStudiensemester.getAll());
+ if (semestersResponse.meta.status === "success") {
+ this.semesterRangePresets = {
+ label: "View specific semester",
+ presets: semestersResponse.data.map((semester) => {
+ let startDate = luxon.DateTime.fromISO(semester.start);
+ let endDate = luxon.DateTime.fromISO(semester.ende);
+ return {
+ startDate,
+ endDate,
+ name: semester.studiensemester_kurzbz,
+ description: semester.bezeichnung,
+ };
+ })
+ };
+ }
+ },
},
setup(props, context) {
const rangeInterval = Vue.ref(null);
@@ -220,6 +258,8 @@ export default {
end: res.data.end
};
});
+
+ this.fetchSemesters();
},
template: /* html */`
$emit('update:date', newDate, newMode)"
@update:mode="(newMode, newDate) => { currentMode = newMode; $emit('update:mode', newMode, newDate) }"
diff --git a/public/js/components/Tempus/Renderer/Lehreinheit/calendarEvent.js b/public/js/components/Tempus/Renderer/Lehreinheit/calendarEvent.js
index 4d2a92fc4..a019aa871 100644
--- a/public/js/components/Tempus/Renderer/Lehreinheit/calendarEvent.js
+++ b/public/js/components/Tempus/Renderer/Lehreinheit/calendarEvent.js
@@ -1,4 +1,10 @@
export default {
+ inject: {
+ mode: {
+ from: 'mode',
+ default: null,
+ },
+ },
props: {
event: {
type: Object,
@@ -148,19 +154,6 @@ export default {
class="position-relative"
@wheel.stop
>
-
-
-
-
-
{{event.verplante_stunden}}
@@ -172,7 +165,28 @@ export default {
{{ end }}
-
{{ topicString }}
+
+
{{ topicString }}
+
+
+
+
+
+
maxBottom)
- newHeight = maxBottom - activeResize.startTop;
+ const minSize = MIN_HEIGHT_PX;
+ const newSize = Math.max(minSize, (activeResize.horizontal
+ ? activeResize.startWidth
+ : activeResize.startHeight) + draggedPx);
+ const startPosition = activeResize.horizontal
+ ? activeResize.startLeft
+ : activeResize.startTop;
+ const constrainedSize = Math.min(newSize, maxEnd - startPosition);
- ghost.updatePosition(null, newHeight);
+ if (activeResize.horizontal)
+ ghost.updatePosition(null, null, constrainedSize);
+ else
+ ghost.updatePosition(null, constrainedSize);
}
else if (activeResize.edge === 'start')
{
- let newTop = activeResize.startTop + draggedPx;
- let newHeight = activeResize.startHeight - draggedPx;
+ const startPosition = activeResize.horizontal
+ ? activeResize.startLeft
+ : activeResize.startTop;
+ const startSize = activeResize.horizontal
+ ? activeResize.startWidth
+ : activeResize.startHeight;
+ let newPosition = startPosition + draggedPx;
+ let newSize = startSize - draggedPx;
- if (newTop < 0)
+ if (newPosition < 0)
{
- newHeight -= (0 - newTop);
- newTop = 0;
+ newSize -= (0 - newPosition);
+ newPosition = 0;
}
- if (newHeight < MIN_HEIGHT_PX)
+ if (newSize < MIN_HEIGHT_PX)
{
- newTop = (activeResize.startTop + activeResize.startHeight) - MIN_HEIGHT_PX;
- newHeight = MIN_HEIGHT_PX;
+ newPosition = (startPosition + startSize) - MIN_HEIGHT_PX;
+ newSize = MIN_HEIGHT_PX;
}
- ghost.updatePosition(newTop, newHeight);
+ if (activeResize.horizontal)
+ ghost.updatePosition(null, null, newSize, newPosition);
+ else
+ ghost.updatePosition(newPosition, newSize);
}
updateGhostLabel();
@@ -176,9 +215,9 @@ export function useResizeHandler() {
activeResize = null;
}
- function startResize(edge, evt, { el, gridEl, event, timeGrid, onEnd })
+ function startResize(edge, evt, { el, gridEl, event, horizontal = false, timeGrid, onEnd })
{
- const { startTop, startHeight } = ghost.create(gridEl, el, edge);
+ const { startTop, startHeight, startLeft, startWidth } = ghost.create(gridEl, el, edge);
activeResize = {
edge,
@@ -186,11 +225,15 @@ export function useResizeHandler() {
eventEl: el,
gridEl,
event,
+ horizontal,
timeGrid,
onEnd,
dragStartY: (evt.clientY - gridEl.getBoundingClientRect().top) + gridEl.scrollTop,
+ dragStartX: (evt.clientX - gridEl.getBoundingClientRect().left) + gridEl.scrollLeft,
startTop,
startHeight,
+ startLeft,
+ startWidth,
originalOpacity: el.style.opacity,
};
@@ -214,4 +257,4 @@ export function useResizeHandler() {
}
return { startResize, cleanup };
-}
\ No newline at end of file
+}