time_table 0.1.5 → 0.1.6
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} +118 -29
- data/app/assets/javascript/time_table/helpers/drag_event_state.js +11 -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") {
|
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) {
|
@@ -36,10 +52,12 @@ export default class extends Controller {
|
|
36
52
|
}
|
37
53
|
|
38
54
|
this.dragEvent = new DragEventState({
|
55
|
+
date: event.params.column || event.target.closest(".column").dataset.timetableColumnParam,
|
39
56
|
type: event.params.dragEvent,
|
40
57
|
scrollFrame: this.scrollFrame,
|
41
58
|
timeKeeper: this.timeKeeper,
|
42
|
-
target: event.currentTarget.closest(".event")
|
59
|
+
target: event.currentTarget.closest(".event"),
|
60
|
+
column: event.currentTarget.closest(".column")
|
43
61
|
});
|
44
62
|
|
45
63
|
this.dragEvent.captureOriginSnapshot(event);
|
@@ -50,8 +68,21 @@ export default class extends Controller {
|
|
50
68
|
drag(event) {
|
51
69
|
if(this.dragEvent) {
|
52
70
|
|
71
|
+
if(this.dragEvent.prevent) {
|
72
|
+
this.dragEvent = null;
|
73
|
+
return;
|
74
|
+
}
|
75
|
+
|
53
76
|
this.dragEvent.captureSnapshot(event);
|
77
|
+
if(this.dragEvent.current.realTime - this.dragEvent.origin.realTime < 100) {
|
78
|
+
return;
|
79
|
+
}
|
54
80
|
|
81
|
+
// HACKY
|
82
|
+
this.dragEvent.dragging = true;
|
83
|
+
if(this.dragEvent.type != "create" && this.dragEvent.target) {
|
84
|
+
this.#dispatchDragClick(this.dragEvent.target);
|
85
|
+
}
|
55
86
|
// Calls dragResize, dragMove, dragCreate, etc.
|
56
87
|
this.#invokeDragMethodFor(this.dragEvent.type);
|
57
88
|
|
@@ -63,6 +94,27 @@ export default class extends Controller {
|
|
63
94
|
|
64
95
|
stopDragEvent(event) {
|
65
96
|
event.preventDefault();
|
97
|
+
event.stopPropagation();
|
98
|
+
|
99
|
+
// HACK - Should come up with system of determining form target to submit (ADD CREATE CHECK TO DELETE UNSET EVENT HERE)
|
100
|
+
if(this.dragEvent && (this.dragEvent.type == "move" || this.dragEvent.type == "resize") && this.dragEvent.origin.type != "create") {
|
101
|
+
if(Math.abs(this.dragEvent.origin.time.real - this.dragEvent.current.time.real) > 100 || this.dragEvent.origin.column != this.dragEvent.current.column) {
|
102
|
+
console.log("Submitting form");
|
103
|
+
let form = this.dragEvent.target.querySelector(".calendar-event-form");
|
104
|
+
form.requestSubmit();
|
105
|
+
}
|
106
|
+
}
|
107
|
+
|
108
|
+
if(this.dragEvent && !this.dragEvent.dragging && this.dragEvent.target) {
|
109
|
+
this.#dispatchStillClick(this.dragEvent.target)
|
110
|
+
}
|
111
|
+
|
112
|
+
if(this.dragEvent && this.dragEvent.origin.type == "create" && this.dragEvent.previous) {
|
113
|
+
let target = this.dragEvent.target;
|
114
|
+
setTimeout(() => {
|
115
|
+
this.#dispatchStillClick(target);
|
116
|
+
}, 100);
|
117
|
+
}
|
66
118
|
|
67
119
|
this.dragEvent = null;
|
68
120
|
|
@@ -70,6 +122,12 @@ export default class extends Controller {
|
|
70
122
|
this.#removeDragEventListeners();
|
71
123
|
}
|
72
124
|
|
125
|
+
preventDragEvent(event) {
|
126
|
+
event.stopPropagation();
|
127
|
+
if(this.dragEvent) {
|
128
|
+
this.dragEvent.prevent = true;
|
129
|
+
}
|
130
|
+
}
|
73
131
|
|
74
132
|
//////////////////
|
75
133
|
// Drag Methods //
|
@@ -77,17 +135,23 @@ export default class extends Controller {
|
|
77
135
|
|
78
136
|
dragCreate(event) {
|
79
137
|
let timeBoundaries = this.timeKeeper.timeBoundaries(this.dragEvent.current.time.clipped, this.dragEvent.origin.time.clipped);
|
80
|
-
|
138
|
+
|
139
|
+
let eventElement = this.renderer.createEventElement(this.dragEvent.date, timeBoundaries);
|
81
140
|
|
82
141
|
this.eventsListTarget.appendChild(eventElement);
|
83
142
|
|
143
|
+
// Come up with better way to select events list, maybe remove child div all together
|
144
|
+
this.dragEvent.column.querySelector(".timetable-events").appendChild(eventElement);
|
145
|
+
// this.eventsListTarget
|
146
|
+
|
84
147
|
this.dragEvent.shift({ type: "resize", target: eventElement });
|
85
148
|
this.handleOverlap(eventElement);
|
86
149
|
}
|
87
150
|
|
88
151
|
dragResize(event) {
|
89
152
|
let timeBoundaries = this.timeKeeper.timeBoundaries(this.dragEvent.current.time.clipped, this.dragEvent.origin.target.startTime.real);
|
90
|
-
|
153
|
+
|
154
|
+
this.renderer.updateEventElement(this.dragEvent.target, this.dragEvent.date, timeBoundaries);
|
91
155
|
this.handleOverlap(this.dragEvent.target);
|
92
156
|
}
|
93
157
|
|
@@ -98,7 +162,7 @@ export default class extends Controller {
|
|
98
162
|
|
99
163
|
let timeBoundaries = this.timeKeeper.timeBoundaries(updatedStartTime, updatedEndTime);
|
100
164
|
|
101
|
-
|
165
|
+
this.renderer.updateEventElement(this.dragEvent.target, this.dragEvent.date, timeBoundaries);
|
102
166
|
this.handleOverlap(this.dragEvent.target);
|
103
167
|
}
|
104
168
|
|
@@ -113,31 +177,31 @@ export default class extends Controller {
|
|
113
177
|
this.eventTargets.forEach((event) => {
|
114
178
|
event.style.setProperty("height", `${event.offsetHeight * (scaleChange)}px`);
|
115
179
|
event.style.setProperty("top", `${event.offsetTop * (scaleChange)}px`);
|
116
|
-
|
180
|
+
this.renderer.setSpecialClasses(event);
|
117
181
|
});
|
118
182
|
}
|
119
183
|
|
120
184
|
handleOverlap(element) {
|
121
185
|
let eventTop = element.offsetTop;
|
122
186
|
let eventBottom = eventTop + element.offsetHeight;
|
123
|
-
|
124
|
-
this.
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
});
|
187
|
+
// TODO: Change query method
|
188
|
+
// this.dragEvent.column.querySelector(".timetable-events").querySelectorAll(".event").forEach((event) => {
|
189
|
+
// if(event != element) {
|
190
|
+
// let top = event.offsetTop;
|
191
|
+
// let bottom = top + event.offsetHeight;
|
192
|
+
|
193
|
+
// if(eventTop >= top && eventBottom <= bottom) {
|
194
|
+
// element.style.setProperty("left", "50px");
|
195
|
+
// event.style.setProperty("right", "20px");
|
196
|
+
// } else if(eventTop < bottom && eventBottom > top) {
|
197
|
+
// element.style.setProperty("left", "50%");
|
198
|
+
// event.style.setProperty("right", "50%");
|
199
|
+
// } else {
|
200
|
+
// element.style.setProperty("left", "50px");
|
201
|
+
// event.style.setProperty("right", "20px");
|
202
|
+
// }
|
203
|
+
// }
|
204
|
+
// });
|
141
205
|
}
|
142
206
|
|
143
207
|
|
@@ -147,6 +211,7 @@ export default class extends Controller {
|
|
147
211
|
////////////////////
|
148
212
|
|
149
213
|
handleScroll(status) {
|
214
|
+
console.log("SHOULD BE SCROLLING");
|
150
215
|
if(status == "ABOVE") {
|
151
216
|
console.log("ABOVE");
|
152
217
|
this.insertTimestampAbove();
|
@@ -168,7 +233,7 @@ export default class extends Controller {
|
|
168
233
|
let time = new Date(this.timeKeeper.endTime.getTime());
|
169
234
|
time.setHours(time.getHours() + 1);
|
170
235
|
this.timeKeeper.endTime = time;
|
171
|
-
let timestampDiv =
|
236
|
+
let timestampDiv = this.renderer.timestamp(time);
|
172
237
|
this.element.querySelector(".timestamps").appendChild(timestampDiv);
|
173
238
|
}
|
174
239
|
|
@@ -185,7 +250,7 @@ export default class extends Controller {
|
|
185
250
|
|
186
251
|
if (this[`drag${capitalizedType}`]) {
|
187
252
|
this[`drag${capitalizedType}`]();
|
188
|
-
} else {
|
253
|
+
} else {
|
189
254
|
console.error(`No drag method found for type: ${type}`);
|
190
255
|
}
|
191
256
|
}
|
@@ -194,6 +259,30 @@ export default class extends Controller {
|
|
194
259
|
// Helpers //
|
195
260
|
/////////////
|
196
261
|
|
262
|
+
#dispatchStillClick(target) {
|
263
|
+
target.dispatchEvent(this.#stillClickEvent());
|
264
|
+
}
|
265
|
+
|
266
|
+
#stillClickEvent() {
|
267
|
+
return new CustomEvent("still:click", {
|
268
|
+
detail: {
|
269
|
+
dragEvent: this.dragEvent
|
270
|
+
}
|
271
|
+
})
|
272
|
+
}
|
273
|
+
|
274
|
+
#dispatchDragClick(target) {
|
275
|
+
target.dispatchEvent(this.#dragClickEvent());
|
276
|
+
}
|
277
|
+
|
278
|
+
#dragClickEvent() {
|
279
|
+
return new CustomEvent("drag:click", {
|
280
|
+
detail: {
|
281
|
+
dragEvent: this.dragEvent
|
282
|
+
}
|
283
|
+
})
|
284
|
+
}
|
285
|
+
|
197
286
|
#setDragEventListeners() {
|
198
287
|
document.addEventListener("mousemove", this.drag.bind(this));
|
199
288
|
document.addEventListener("mouseup", this.stopDragEvent.bind(this));
|
@@ -1,9 +1,13 @@
|
|
1
1
|
export default class DragEventState {
|
2
|
-
constructor({ type, scrollFrame, timeKeeper, target }) {
|
2
|
+
constructor({ type, scrollFrame, timeKeeper, target, column, 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
|
7
11
|
}
|
8
12
|
|
9
13
|
captureOriginSnapshot(event) {
|
@@ -27,12 +31,17 @@ export default class DragEventState {
|
|
27
31
|
let relativePosition = this.scrollFrame.relativeCursorPosition(event);
|
28
32
|
return {
|
29
33
|
event: event,
|
34
|
+
type: this.type,
|
35
|
+
date: this.date,
|
30
36
|
position: relativePosition,
|
31
37
|
time: this.timeKeeper.timeAtPosition(relativePosition.scroll.y),
|
32
|
-
|
38
|
+
column: this.column,
|
39
|
+
target: this.targetSnapshot(this.target),
|
40
|
+
realTime: new Date(),
|
33
41
|
}
|
34
42
|
}
|
35
43
|
|
44
|
+
// Probably want to add column here
|
36
45
|
targetSnapshot(target) {
|
37
46
|
if(!target) {
|
38
47
|
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
|