time_table 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/javascript/time_table/controllers/index.js +1 -1
- data/app/assets/javascript/time_table/controllers/time_table_controller_old.js +105 -464
- data/app/assets/javascript/time_table/controllers/{time_table_controller.js → timetable_controller.js} +126 -29
- data/app/assets/javascript/time_table/helpers/drag_event_state.js +12 -2
- data/app/assets/javascript/time_table/helpers/time_table_renderer.js +36 -25
- data/app/assets/stylesheets/time_table/timetable.css +143 -0
- data/app/helpers/time_table/{time_table_helper.rb → time_table_old_helper.rb} +17 -5
- data/app/helpers/time_table/timetable_calendar_helper.rb +206 -0
- data/app/views/time_table/{_time_table.html.erb → _time_table_old.html.erb} +1 -7
- data/app/views/time_table/_timetable.html.erb +49 -0
- data/lib/time_table/version.rb +1 -1
- metadata +8 -7
- data/app/assets/javascript/time_table/controllers/time_table_controller_pre_time_keeper.js +0 -350
- data/app/assets/stylesheets/time_table/time_table.css +0 -136
@@ -5,9 +5,19 @@ import DragEventState from "../helpers/drag_event_state.js"
|
|
5
5
|
import TimeTableRenderer from "../helpers/time_table_renderer.js"
|
6
6
|
|
7
7
|
export default class extends Controller {
|
8
|
-
static targets = ["canvas", "eventsList", "event", "eventName", "eventTime", "timestamp"]
|
8
|
+
// static targets = ["canvas", "eventsList", "event", "eventName", "eventTime", "timestamp", "template"]
|
9
|
+
|
10
|
+
static targets = ["event", "template", "eventsList", "eventActionMenu"]
|
9
11
|
|
10
12
|
connect() {
|
13
|
+
this.renderer = new TimeTableRenderer(this.templateTarget);
|
14
|
+
this.eventTargets.forEach((event) => {
|
15
|
+
this.renderer.setSpecialClasses(event);
|
16
|
+
});
|
17
|
+
|
18
|
+
// A little hacky
|
19
|
+
this.element.classList.remove("loading");
|
20
|
+
|
11
21
|
this.timeKeeper = new TimeKeeper({
|
12
22
|
start: new Date(this.element.dataset.timetableStartTime),
|
13
23
|
end: new Date(this.element.dataset.timetableEndTime),
|
@@ -21,10 +31,16 @@ export default class extends Controller {
|
|
21
31
|
this.scrollFrame = new ScrollFrame(this.element, { origin: topPadding });
|
22
32
|
|
23
33
|
this.dragEvent = null;
|
34
|
+
}
|
24
35
|
|
25
|
-
|
26
|
-
|
27
|
-
|
36
|
+
changeColumn(event) {
|
37
|
+
if(this.dragEvent && this.dragEvent.type == "move" && !this.dragEvent.locked) {
|
38
|
+
let currentEvent = this.dragEvent.target;
|
39
|
+
this.dragEvent.column = event.currentTarget.closest(".column");
|
40
|
+
this.dragEvent.date = event.params.column
|
41
|
+
// TODO: Change query method
|
42
|
+
this.dragEvent.column.querySelector(".timetable-events").appendChild(currentEvent);
|
43
|
+
}
|
28
44
|
}
|
29
45
|
|
30
46
|
startDragEvent(event) {
|
@@ -35,11 +51,16 @@ export default class extends Controller {
|
|
35
51
|
return;
|
36
52
|
}
|
37
53
|
|
54
|
+
console.log(event.params)
|
55
|
+
|
38
56
|
this.dragEvent = new DragEventState({
|
57
|
+
date: event.params.column || event.target.closest(".column").dataset.timetableColumnParam,
|
39
58
|
type: event.params.dragEvent,
|
40
59
|
scrollFrame: this.scrollFrame,
|
41
60
|
timeKeeper: this.timeKeeper,
|
42
|
-
|
61
|
+
locked: event.params.locked,
|
62
|
+
target: event.currentTarget.closest(".event"),
|
63
|
+
column: event.currentTarget.closest(".column")
|
43
64
|
});
|
44
65
|
|
45
66
|
this.dragEvent.captureOriginSnapshot(event);
|
@@ -50,8 +71,26 @@ export default class extends Controller {
|
|
50
71
|
drag(event) {
|
51
72
|
if(this.dragEvent) {
|
52
73
|
|
74
|
+
if(this.dragEvent.prevent) {
|
75
|
+
this.dragEvent = null;
|
76
|
+
return;
|
77
|
+
}
|
78
|
+
|
79
|
+
console.log(this.dragEvent.locked);
|
80
|
+
if(this.dragEvent.locked) {
|
81
|
+
return;
|
82
|
+
}
|
83
|
+
|
53
84
|
this.dragEvent.captureSnapshot(event);
|
85
|
+
if(this.dragEvent.current.realTime - this.dragEvent.origin.realTime < 100) {
|
86
|
+
return;
|
87
|
+
}
|
54
88
|
|
89
|
+
// HACKY
|
90
|
+
this.dragEvent.dragging = true;
|
91
|
+
if(this.dragEvent.type != "create" && this.dragEvent.target) {
|
92
|
+
this.#dispatchDragClick(this.dragEvent.target);
|
93
|
+
}
|
55
94
|
// Calls dragResize, dragMove, dragCreate, etc.
|
56
95
|
this.#invokeDragMethodFor(this.dragEvent.type);
|
57
96
|
|
@@ -63,6 +102,27 @@ export default class extends Controller {
|
|
63
102
|
|
64
103
|
stopDragEvent(event) {
|
65
104
|
event.preventDefault();
|
105
|
+
event.stopPropagation();
|
106
|
+
|
107
|
+
// HACK - Should come up with system of determining form target to submit (ADD CREATE CHECK TO DELETE UNSET EVENT HERE)
|
108
|
+
if(this.dragEvent && (this.dragEvent.type == "move" || this.dragEvent.type == "resize") && this.dragEvent.origin.type != "create") {
|
109
|
+
if(Math.abs(this.dragEvent.origin.time.real - this.dragEvent.current.time.real) > 100 || this.dragEvent.origin.column != this.dragEvent.current.column) {
|
110
|
+
console.log("Submitting form");
|
111
|
+
let form = this.dragEvent.target.querySelector(".calendar-event-form");
|
112
|
+
form.requestSubmit();
|
113
|
+
}
|
114
|
+
}
|
115
|
+
|
116
|
+
if(this.dragEvent && !this.dragEvent.dragging && this.dragEvent.target) {
|
117
|
+
this.#dispatchStillClick(this.dragEvent.target)
|
118
|
+
}
|
119
|
+
|
120
|
+
if(this.dragEvent && this.dragEvent.origin.type == "create" && this.dragEvent.previous) {
|
121
|
+
let target = this.dragEvent.target;
|
122
|
+
setTimeout(() => {
|
123
|
+
this.#dispatchStillClick(target);
|
124
|
+
}, 100);
|
125
|
+
}
|
66
126
|
|
67
127
|
this.dragEvent = null;
|
68
128
|
|
@@ -70,6 +130,12 @@ export default class extends Controller {
|
|
70
130
|
this.#removeDragEventListeners();
|
71
131
|
}
|
72
132
|
|
133
|
+
preventDragEvent(event) {
|
134
|
+
event.stopPropagation();
|
135
|
+
if(this.dragEvent) {
|
136
|
+
this.dragEvent.prevent = true;
|
137
|
+
}
|
138
|
+
}
|
73
139
|
|
74
140
|
//////////////////
|
75
141
|
// Drag Methods //
|
@@ -77,17 +143,23 @@ export default class extends Controller {
|
|
77
143
|
|
78
144
|
dragCreate(event) {
|
79
145
|
let timeBoundaries = this.timeKeeper.timeBoundaries(this.dragEvent.current.time.clipped, this.dragEvent.origin.time.clipped);
|
80
|
-
|
146
|
+
|
147
|
+
let eventElement = this.renderer.createEventElement(this.dragEvent.date, timeBoundaries);
|
81
148
|
|
82
149
|
this.eventsListTarget.appendChild(eventElement);
|
83
150
|
|
151
|
+
// Come up with better way to select events list, maybe remove child div all together
|
152
|
+
this.dragEvent.column.querySelector(".timetable-events").appendChild(eventElement);
|
153
|
+
// this.eventsListTarget
|
154
|
+
|
84
155
|
this.dragEvent.shift({ type: "resize", target: eventElement });
|
85
156
|
this.handleOverlap(eventElement);
|
86
157
|
}
|
87
158
|
|
88
159
|
dragResize(event) {
|
89
160
|
let timeBoundaries = this.timeKeeper.timeBoundaries(this.dragEvent.current.time.clipped, this.dragEvent.origin.target.startTime.real);
|
90
|
-
|
161
|
+
|
162
|
+
this.renderer.updateEventElement(this.dragEvent.target, this.dragEvent.date, timeBoundaries);
|
91
163
|
this.handleOverlap(this.dragEvent.target);
|
92
164
|
}
|
93
165
|
|
@@ -98,7 +170,7 @@ export default class extends Controller {
|
|
98
170
|
|
99
171
|
let timeBoundaries = this.timeKeeper.timeBoundaries(updatedStartTime, updatedEndTime);
|
100
172
|
|
101
|
-
|
173
|
+
this.renderer.updateEventElement(this.dragEvent.target, this.dragEvent.date, timeBoundaries);
|
102
174
|
this.handleOverlap(this.dragEvent.target);
|
103
175
|
}
|
104
176
|
|
@@ -113,31 +185,31 @@ export default class extends Controller {
|
|
113
185
|
this.eventTargets.forEach((event) => {
|
114
186
|
event.style.setProperty("height", `${event.offsetHeight * (scaleChange)}px`);
|
115
187
|
event.style.setProperty("top", `${event.offsetTop * (scaleChange)}px`);
|
116
|
-
|
188
|
+
this.renderer.setSpecialClasses(event);
|
117
189
|
});
|
118
190
|
}
|
119
191
|
|
120
192
|
handleOverlap(element) {
|
121
193
|
let eventTop = element.offsetTop;
|
122
194
|
let eventBottom = eventTop + element.offsetHeight;
|
123
|
-
|
124
|
-
this.
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
});
|
195
|
+
// TODO: Change query method
|
196
|
+
// this.dragEvent.column.querySelector(".timetable-events").querySelectorAll(".event").forEach((event) => {
|
197
|
+
// if(event != element) {
|
198
|
+
// let top = event.offsetTop;
|
199
|
+
// let bottom = top + event.offsetHeight;
|
200
|
+
|
201
|
+
// if(eventTop >= top && eventBottom <= bottom) {
|
202
|
+
// element.style.setProperty("left", "50px");
|
203
|
+
// event.style.setProperty("right", "20px");
|
204
|
+
// } else if(eventTop < bottom && eventBottom > top) {
|
205
|
+
// element.style.setProperty("left", "50%");
|
206
|
+
// event.style.setProperty("right", "50%");
|
207
|
+
// } else {
|
208
|
+
// element.style.setProperty("left", "50px");
|
209
|
+
// event.style.setProperty("right", "20px");
|
210
|
+
// }
|
211
|
+
// }
|
212
|
+
// });
|
141
213
|
}
|
142
214
|
|
143
215
|
|
@@ -147,6 +219,7 @@ export default class extends Controller {
|
|
147
219
|
////////////////////
|
148
220
|
|
149
221
|
handleScroll(status) {
|
222
|
+
console.log("SHOULD BE SCROLLING");
|
150
223
|
if(status == "ABOVE") {
|
151
224
|
console.log("ABOVE");
|
152
225
|
this.insertTimestampAbove();
|
@@ -168,7 +241,7 @@ export default class extends Controller {
|
|
168
241
|
let time = new Date(this.timeKeeper.endTime.getTime());
|
169
242
|
time.setHours(time.getHours() + 1);
|
170
243
|
this.timeKeeper.endTime = time;
|
171
|
-
let timestampDiv =
|
244
|
+
let timestampDiv = this.renderer.timestamp(time);
|
172
245
|
this.element.querySelector(".timestamps").appendChild(timestampDiv);
|
173
246
|
}
|
174
247
|
|
@@ -185,7 +258,7 @@ export default class extends Controller {
|
|
185
258
|
|
186
259
|
if (this[`drag${capitalizedType}`]) {
|
187
260
|
this[`drag${capitalizedType}`]();
|
188
|
-
} else {
|
261
|
+
} else {
|
189
262
|
console.error(`No drag method found for type: ${type}`);
|
190
263
|
}
|
191
264
|
}
|
@@ -194,6 +267,30 @@ export default class extends Controller {
|
|
194
267
|
// Helpers //
|
195
268
|
/////////////
|
196
269
|
|
270
|
+
#dispatchStillClick(target) {
|
271
|
+
target.dispatchEvent(this.#stillClickEvent());
|
272
|
+
}
|
273
|
+
|
274
|
+
#stillClickEvent() {
|
275
|
+
return new CustomEvent("still:click", {
|
276
|
+
detail: {
|
277
|
+
dragEvent: this.dragEvent
|
278
|
+
}
|
279
|
+
})
|
280
|
+
}
|
281
|
+
|
282
|
+
#dispatchDragClick(target) {
|
283
|
+
target.dispatchEvent(this.#dragClickEvent());
|
284
|
+
}
|
285
|
+
|
286
|
+
#dragClickEvent() {
|
287
|
+
return new CustomEvent("drag:click", {
|
288
|
+
detail: {
|
289
|
+
dragEvent: this.dragEvent
|
290
|
+
}
|
291
|
+
})
|
292
|
+
}
|
293
|
+
|
197
294
|
#setDragEventListeners() {
|
198
295
|
document.addEventListener("mousemove", this.drag.bind(this));
|
199
296
|
document.addEventListener("mouseup", this.stopDragEvent.bind(this));
|
@@ -1,9 +1,14 @@
|
|
1
1
|
export default class DragEventState {
|
2
|
-
constructor({ type, scrollFrame, timeKeeper, target }) {
|
2
|
+
constructor({ type, scrollFrame, timeKeeper, target, column, locked = false, prevent = false, date }) {
|
3
3
|
this.type = type;
|
4
4
|
this.scrollFrame = scrollFrame;
|
5
5
|
this.timeKeeper = timeKeeper;
|
6
6
|
this.target = target;
|
7
|
+
// TODO: Reconsider this
|
8
|
+
this.column = column;
|
9
|
+
this.date = date;
|
10
|
+
this.prevent = prevent; // Kinda hacky
|
11
|
+
this.locked = locked; // Kinda hacky
|
7
12
|
}
|
8
13
|
|
9
14
|
captureOriginSnapshot(event) {
|
@@ -27,12 +32,17 @@ export default class DragEventState {
|
|
27
32
|
let relativePosition = this.scrollFrame.relativeCursorPosition(event);
|
28
33
|
return {
|
29
34
|
event: event,
|
35
|
+
type: this.type,
|
36
|
+
date: this.date,
|
30
37
|
position: relativePosition,
|
31
38
|
time: this.timeKeeper.timeAtPosition(relativePosition.scroll.y),
|
32
|
-
|
39
|
+
column: this.column,
|
40
|
+
target: this.targetSnapshot(this.target),
|
41
|
+
realTime: new Date(),
|
33
42
|
}
|
34
43
|
}
|
35
44
|
|
45
|
+
// Probably want to add column here
|
36
46
|
targetSnapshot(target) {
|
37
47
|
if(!target) {
|
38
48
|
return null;
|
@@ -1,28 +1,29 @@
|
|
1
|
-
class TimeTableRenderer {
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
element.classList.add("event");
|
6
|
-
element.setAttribute("data-time-table-target", "event");
|
7
|
-
element.setAttribute("data-action", "mousedown->time-table#startDragEvent");
|
8
|
-
element.setAttribute("data-time-table-drag-event-param", "move");
|
9
|
-
|
10
|
-
element.innerHTML = `
|
11
|
-
<div class="event-name"><span style="font-weight: 400; color: gray;">(No Title)</span></div>
|
12
|
-
<div class="event-time" data-action="mousedown->time-table#startDragEvent" data-time-table-drag-event-param="resize">
|
13
|
-
${ this.#durationString(start.time, end.time) }
|
14
|
-
</div>
|
15
|
-
`;
|
16
|
-
|
17
|
-
this.updateEventElement(element, {start, end});
|
1
|
+
export default class TimeTableRenderer {
|
2
|
+
constructor(template) {
|
3
|
+
this.template = template;
|
4
|
+
}
|
18
5
|
|
6
|
+
createEventElement(date, {start, end}) {
|
7
|
+
const element = this.template.content.cloneNode(true).firstElementChild;
|
8
|
+
this.updateEventElement(element, date, {start, end});
|
19
9
|
return element;
|
20
10
|
}
|
21
11
|
|
22
|
-
|
12
|
+
// TODO: Move all app specific logic to rails app
|
13
|
+
// Should move updater to a delegate controller in rails app, maybe creater to
|
14
|
+
updateEventElement(element, date, {start, end}) {
|
23
15
|
element.style.setProperty("top", `${start.location}px`);
|
24
16
|
element.style.setProperty("height", `${end.location - start.location}px`);
|
25
17
|
|
18
|
+
let form = element.querySelector(".calendar-event-form");
|
19
|
+
// This shouldn't happen here
|
20
|
+
if(form.querySelector("#event_date_string")) {
|
21
|
+
form.querySelector("#event_date_string").setAttribute("value", date);
|
22
|
+
form.querySelector("#event_date_string").dispatchEvent(new CustomEvent("value:change", { bubbles: true, detail: { value: date }}));
|
23
|
+
}
|
24
|
+
form.querySelector("#event_start_time").value = this.getMilitaryTime(start.time);
|
25
|
+
form.querySelector("#event_end_time").value = this.getMilitaryTime(end.time);
|
26
|
+
|
26
27
|
this.setSpecialClasses(element);
|
27
28
|
|
28
29
|
element.querySelector(".event-time").innerHTML = this.#durationString(start.time, end.time);
|
@@ -30,16 +31,24 @@ class TimeTableRenderer {
|
|
30
31
|
return element;
|
31
32
|
}
|
32
33
|
|
34
|
+
getMilitaryTime(date) {
|
35
|
+
let hours = date.getUTCHours();
|
36
|
+
let minutes = date.getUTCMinutes();
|
37
|
+
minutes = minutes < 10 ? '0' + minutes : minutes; // Ensure two-digit minutes
|
38
|
+
hours = hours < 10 ? '0' + hours : hours; // Ensure two-digit hours
|
39
|
+
return `${hours}:${minutes}`;
|
40
|
+
}
|
41
|
+
|
33
42
|
timestamp(time) {
|
34
43
|
let timestampeElement = document.createElement("div");
|
35
44
|
timestampeElement.classList.add("timestamp");
|
36
45
|
timestampeElement.classList.add("out-of-bounds");
|
37
|
-
timestampeElement.setAttribute("data-
|
38
|
-
timestampeElement.setAttribute("data-action", "mousedown->
|
39
|
-
timestampeElement.setAttribute("data-
|
46
|
+
timestampeElement.setAttribute("data-timetable-target", "timestamp");
|
47
|
+
timestampeElement.setAttribute("data-action", "mousedown->timetable#startDragEvent");
|
48
|
+
timestampeElement.setAttribute("data-timetable-drag-event-param", "rescale");
|
40
49
|
|
41
50
|
timestampeElement.innerHTML = `
|
42
|
-
<div class="label" data-action="mousedown->
|
51
|
+
<div class="label" data-action="mousedown->timetable#startDragEvent" data-timetable-drag-event-param="rescale">
|
43
52
|
${this.#timeString(time, "short")}
|
44
53
|
</div>
|
45
54
|
`;
|
@@ -48,8 +57,10 @@ class TimeTableRenderer {
|
|
48
57
|
}
|
49
58
|
|
50
59
|
setSpecialClasses(element) {
|
51
|
-
element.classList.toggle("
|
52
|
-
element.classList.toggle("
|
60
|
+
element.classList.toggle("no-content", element.offsetHeight < 15);
|
61
|
+
element.classList.toggle("tiny", element.offsetHeight < 30);
|
62
|
+
element.classList.toggle("mini", element.offsetHeight < 45);
|
63
|
+
element.classList.toggle("small", element.offsetHeight < 75);
|
53
64
|
}
|
54
65
|
|
55
66
|
#timeString(date, format = "long") {
|
@@ -72,4 +83,4 @@ class TimeTableRenderer {
|
|
72
83
|
}
|
73
84
|
}
|
74
85
|
|
75
|
-
export default new TimeTableRenderer();
|
86
|
+
// export default new TimeTableRenderer();
|
@@ -0,0 +1,143 @@
|
|
1
|
+
.timetable {
|
2
|
+
position: relative;
|
3
|
+
height: fit-content;
|
4
|
+
overflow: visible;
|
5
|
+
display: grid;
|
6
|
+
}
|
7
|
+
|
8
|
+
.timetable-calendar .timetable {
|
9
|
+
height: 100%;
|
10
|
+
}
|
11
|
+
|
12
|
+
.timetable > * {
|
13
|
+
grid-column: 1;
|
14
|
+
grid-row: 1;
|
15
|
+
}
|
16
|
+
|
17
|
+
.timetable-canvas {
|
18
|
+
height: calc(100%);
|
19
|
+
flex-grow: 1;
|
20
|
+
position: relative;
|
21
|
+
z-index: 1;
|
22
|
+
}
|
23
|
+
|
24
|
+
.timetable-column {
|
25
|
+
border-left: 1px solid var(--backdrop-5);
|
26
|
+
height: 100%;
|
27
|
+
}
|
28
|
+
|
29
|
+
.timetable-events {
|
30
|
+
width: 100%;
|
31
|
+
position: relative;
|
32
|
+
}
|
33
|
+
|
34
|
+
/**************/
|
35
|
+
/* Timestamps */
|
36
|
+
/**************/
|
37
|
+
|
38
|
+
.timetable .timestamps {
|
39
|
+
z-index: 0;
|
40
|
+
}
|
41
|
+
|
42
|
+
.timetable .timestamp {
|
43
|
+
font-size: 0.8em;
|
44
|
+
width: 100%;
|
45
|
+
position: relative;
|
46
|
+
height: calc(var(--hour-scale) * 1px);
|
47
|
+
overflow: visible;
|
48
|
+
}
|
49
|
+
|
50
|
+
.timetable .timestamp.out-of-bounds {
|
51
|
+
color: rgb(168, 167, 167);
|
52
|
+
}
|
53
|
+
|
54
|
+
.timetable .timestamp .label {
|
55
|
+
margin-top: -0.5em;
|
56
|
+
height: 100%;
|
57
|
+
width: fit-content;
|
58
|
+
z-index: 5;
|
59
|
+
width: 45px !important;
|
60
|
+
text-align: right;
|
61
|
+
padding-right: 5px;
|
62
|
+
}
|
63
|
+
|
64
|
+
.timetable .timestamp .label:hover {
|
65
|
+
cursor: ns-resize;
|
66
|
+
}
|
67
|
+
|
68
|
+
.timetable .timestamp::before {
|
69
|
+
content: "";
|
70
|
+
position: absolute;
|
71
|
+
right: 0;
|
72
|
+
left: 45px;
|
73
|
+
height: 1px;
|
74
|
+
background-color: var(--backdrop-7);
|
75
|
+
opacity: 0.5;
|
76
|
+
}
|
77
|
+
|
78
|
+
/************/
|
79
|
+
/* Calendar */
|
80
|
+
/************/
|
81
|
+
|
82
|
+
.timetable-calendar .timetable-headers,
|
83
|
+
.timetable-calendar .timetable-canvas {
|
84
|
+
margin-left: 45px;
|
85
|
+
display: flex;
|
86
|
+
flex-direction: row;
|
87
|
+
}
|
88
|
+
|
89
|
+
.timetable-calendar .timetable-header,
|
90
|
+
.timetable-calendar .timetable-column {
|
91
|
+
flex: 1 1 0 !important;
|
92
|
+
/* overflow: hidden; */
|
93
|
+
}
|
94
|
+
|
95
|
+
.timetable-calendar .timetable-header {
|
96
|
+
display: flex;
|
97
|
+
flex-direction: column;
|
98
|
+
justify-content: center;
|
99
|
+
}
|
100
|
+
|
101
|
+
.timetable-calendar .timetable-header:only-child {
|
102
|
+
align-items: flex-start;
|
103
|
+
}
|
104
|
+
|
105
|
+
/*********/
|
106
|
+
/* SKINS */
|
107
|
+
/*********/
|
108
|
+
|
109
|
+
.timetable-column {
|
110
|
+
display: grid;
|
111
|
+
}
|
112
|
+
|
113
|
+
.timetable-column > * {
|
114
|
+
grid-area: 1 / -1 / 1 / -1; /* Span the single column */
|
115
|
+
width: 100%; /* Ensure full width */
|
116
|
+
}
|
117
|
+
|
118
|
+
.timetable-skins {
|
119
|
+
width: 100%;
|
120
|
+
position: relative;
|
121
|
+
}
|
122
|
+
|
123
|
+
.timetable-skin {
|
124
|
+
width: 100%;
|
125
|
+
background-color: var(--backdrop-3);
|
126
|
+
position: absolute;
|
127
|
+
right: 0;
|
128
|
+
left: 0;
|
129
|
+
opacity: 0.5;
|
130
|
+
}
|
131
|
+
|
132
|
+
/* .timetable-skin:hover { */
|
133
|
+
/* background-color: var(--backdrop-5); */
|
134
|
+
/* opacity: 0.5; */
|
135
|
+
/* } */
|
136
|
+
|
137
|
+
.timetable-events {
|
138
|
+
pointer-events: none;
|
139
|
+
}
|
140
|
+
|
141
|
+
.timetable-events > * {
|
142
|
+
pointer-events: auto;
|
143
|
+
}
|
@@ -1,18 +1,18 @@
|
|
1
1
|
module TimeTable
|
2
|
-
module
|
2
|
+
module TimeTableOldHelper
|
3
3
|
def time_table(date = nil, frozen: false, scale: 60, events: [], clip: 15, &block)
|
4
4
|
# @time_table = TimeTable.new
|
5
5
|
# @time_table.scale = scale
|
6
|
-
timetable =
|
7
|
-
render "time_table/time_table", timetable: timetable,
|
6
|
+
timetable = TimeTable.new(date, scale: scale, clip_size: clip, frozen: frozen, events: events, view: self,)
|
7
|
+
render "time_table/time_table", timetable: timetable, &block
|
8
8
|
end
|
9
9
|
|
10
10
|
def hours_in_day
|
11
11
|
end
|
12
12
|
|
13
13
|
|
14
|
-
class
|
15
|
-
attr_accessor :start_time, :end_time, :segment_size, :segment_scale, :clip_size, :clock_type, :frozen
|
14
|
+
class TimeTable
|
15
|
+
attr_accessor :start_time, :end_time, :segment_size, :segment_scale, :clip_size, :clock_type, :frozen, :events
|
16
16
|
|
17
17
|
def initialize(date = nil, **options)
|
18
18
|
@start_time = options[:start_time] || 0
|
@@ -24,6 +24,8 @@ module TimeTable
|
|
24
24
|
@clip_size = options[:clip_size] || 15
|
25
25
|
@clock_type = options[:clock_type] || :meridian
|
26
26
|
@frozen = options[:frozen] || false
|
27
|
+
@events = options[:events] || []
|
28
|
+
@view = options[:view] || nil
|
27
29
|
end
|
28
30
|
|
29
31
|
def segments
|
@@ -36,6 +38,16 @@ module TimeTable
|
|
36
38
|
end
|
37
39
|
end
|
38
40
|
|
41
|
+
def render_events
|
42
|
+
@view.content_tag :div, class: "timetable-canvas", data: { time_table_target: "canvas" } do
|
43
|
+
@view.content_tag :div, class: "timetable-events", data: { time_table_target: "eventsList" } do
|
44
|
+
events.each do |event|
|
45
|
+
yield event
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
39
51
|
def time_in_meridian(time)
|
40
52
|
hour = time / 60
|
41
53
|
minute = time % 60
|