aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHugo Hörnquist <hugo@lysator.liu.se>2021-10-01 03:34:06 +0200
committerHugo Hörnquist <hugo@lysator.liu.se>2021-10-01 03:34:06 +0200
commit927bd58d3340965328f0ccd05f865175b49a6ed5 (patch)
tree1f1602ab98a9e337dcde918c58b71b4aa54bdb34
parentReplace today-button with web component. (diff)
downloadcalp-927bd58d3340965328f0ccd05f865175b49a6ed5.tar.gz
calp-927bd58d3340965328f0ccd05f865175b49a6ed5.tar.xz
Got date-times working in new system.
-rw-r--r--module/calp/html/vcomponent.scm121
-rw-r--r--module/calp/html/view/calendar/week.scm49
-rw-r--r--static/clock.js2
-rw-r--r--static/globals.js96
4 files changed, 177 insertions, 91 deletions
diff --git a/module/calp/html/vcomponent.scm b/module/calp/html/vcomponent.scm
index 4b3e9ec7..63b3df3b 100644
--- a/module/calp/html/vcomponent.scm
+++ b/module/calp/html/vcomponent.scm
@@ -206,11 +206,12 @@
(define-public (edit-template)
`(div (@ (class " eventtext edit-tab "))
(form (@ (class "edit-form"))
+ ;; TODO actually have calendar list here, since we are just a template
(div (@ (class "dropdown-goes-here")))
(h3 (input (@ (type "text")
(placeholder "Sammanfattning")
(name "summary") (required)
- (class "bind") (data-property "summary")
+ (class "interactive") (data-property "summary")
; (value ,(prop ev 'SUMMARY))
)))
@@ -218,36 +219,22 @@
,@(with-label
"Starttid"
- `(div (@ (class "date-time")
- (name "dtstart"))
- (input (@ (type "date")
- ; (value ,(date->string (as-date start)))
- ))
- (input (@ (type "time")
- ; (value ,(time->string (as-time start) "~H:~M"))
- ; ,@(when (date? start) '((disabled)))
- ))))
-
- ;; TODO some way to add an endtime if missing beforehand
- ;; TODO, actually proper support for event without end times
+ '(date-time-input (@ (name "dtstart")
+ (class "interactive")
+ (data-property "dtstart")
+ )))
+
,@(with-label
"Sluttid"
- `(div (@ (class "date-time")
- (name "dtend"))
- (input (@ (type "date")
- ; (value ,(date->string (as-date end)))
- ))
- (input (@ (type "time")
- ; (value ,(time->string (as-time end) "~H:~M"))
- ; ,@(when (date? end) '((disabled)))
- ))))
+ '(date-time-input (@ (name "dtend")
+ (class "interactive")
+ (data-property "dtend"))))
(div
,@(with-label
"Heldag?"
`(input (@ (type "checkbox")
(name "wholeday")
- ; ,@(when (date? start) '((checked)))
))))
)
@@ -257,6 +244,7 @@
`(input (@ (placeholder "Plats")
(name "location")
(type "text")
+ (class "interactive")
(data-property "location")
; (value ,(or (prop ev 'LOCATION) ""))
)))
@@ -264,54 +252,55 @@
,@(with-label
"Beskrivning"
`(textarea (@ (placeholder "Beskrivning")
+ (class "interactive")
(data-property "description")
(name "description"))
; ,(prop ev 'DESCRIPTION)
))
- ,@(with-label
- "Kategorier"
- ;; It would be better if these input-list's worked on the same
- ;; class=bind system as the fields above. The problem with that
- ;; is however that each input-list requires different search
- ;; and join procedures. Currently this is bound in the JS, see
- ;; [CATEGORIES_BIND].
- ;; It matches on ".input-list[data-property='categories']".
- `(div (@ (class "input-list")
- (data-property "categories"))
- #;
- ,@(awhen (prop ev 'CATEGORIES)
- (map (lambda (c)
- `(input (@ (size 2)
- (class "unit")
- (value ,c))))
- it))
-
- (input (@ (class "unit final")
- (size 2)
- (type "text")
- ))))
-
- (hr)
-
- ;; For custom user fields
- ;; TODO these are currently not bound to anything, so entering data
- ;; here does nothing. Bigest hurdle to overcome is supporting arbitrary
- ;; fields which will come and go in the JavaScript.
- ;; TODO also, all (most? maybe not LAST-MODIFIED) remaining properties
- ;; should be exposed here.
- (div (@ (class "input-list"))
- (div (@ (class "unit final newfield"))
- (input (@ (type "text")
- (list "known-fields")
- (placeholder "Nytt fält")))
- (select (@ (name "TYPE"))
- (option (@ (value "TEXT")) "Text"))
- (span
- (input (@ (type "text")
- (placeholder "Värde"))))))
-
- (hr)
+ ;; ,@(with-label
+ ;; "Kategorier"
+ ;; ;; It would be better if these input-list's worked on the same
+ ;; ;; class=bind system as the fields above. The problem with that
+ ;; ;; is however that each input-list requires different search
+ ;; ;; and join procedures. Currently this is bound in the JS, see
+ ;; ;; [CATEGORIES_BIND].
+ ;; ;; It matches on ".input-list[data-property='categories']".
+ ;; `(div (@ (class "input-list")
+ ;; (data-property "categories"))
+ ;; #;
+ ;; ,@(awhen (prop ev 'CATEGORIES)
+ ;; (map (lambda (c)
+ ;; `(input (@ (size 2)
+ ;; (class "unit")
+ ;; (value ,c))))
+ ;; it))
+
+ ;; (input (@ (class "unit final")
+ ;; (size 2)
+ ;; (type "text")
+ ;; ))))
+
+ ;; (hr)
+
+ ;; ;; For custom user fields
+ ;; ;; TODO these are currently not bound to anything, so entering data
+ ;; ;; here does nothing. Bigest hurdle to overcome is supporting arbitrary
+ ;; ;; fields which will come and go in the JavaScript.
+ ;; ;; TODO also, all (most? maybe not LAST-MODIFIED) remaining properties
+ ;; ;; should be exposed here.
+ ;; (div (@ (class "input-list"))
+ ;; (div (@ (class "unit final newfield"))
+ ;; (input (@ (type "text")
+ ;; (list "known-fields")
+ ;; (placeholder "Nytt fält")))
+ ;; (select (@ (name "TYPE"))
+ ;; (option (@ (value "TEXT")) "Text"))
+ ;; (span
+ ;; (input (@ (type "text")
+ ;; (placeholder "Värde"))))))
+
+ ;; (hr)
(input (@ (type "submit")))
diff --git a/module/calp/html/view/calendar/week.scm b/module/calp/html/view/calendar/week.scm
index 340db7d5..c2165a8e 100644
--- a/module/calp/html/view/calendar/week.scm
+++ b/module/calp/html/view/calendar/week.scm
@@ -75,46 +75,53 @@
;; based on the output of fmt-single-event
(define (description-template)
'(div (@ (class " eventtext summary-tab " ()))
- (h3 ((span (@ (class "repeating")) "↺")
+ (h3 ((span (@ (class "repeating")) ; "↺"
+ )
(span (@ (class "bind summary")
- (data-property "summary"))
- "Test")))
+ (data-property "summary")))))
(div (div (time (@ (class "bind dtstart")
(data-property "dtstart")
(data-fmt "~L~H:~M")
- (datetime "2021-09-29T19:56:46"))
- "19:56")
+ (datetime ; "2021-09-29T19:56:46"
+ ))
+ ; "19:56"
+ )
"\xa0—\xa0"
(time (@ (class "bind dtend")
(data-property "dtend")
(data-fmt "~L~H:~M")
- (datetime "2021-09-29T19:56:46"))
- "20:56"))
+ (datetime ; "2021-09-29T19:56:46"
+ ))
+ ; "20:56"
+ ))
(div (@ (class "fields"))
(div (b "Plats: ")
(div (@ (class "bind location")
(data-property "location"))
- "Alsättersgatan 13"))
+ ; "Alsättersgatan 13"
+ ))
(div (@ (class "bind description")
(data-property "description"))
- ("With a description"))
- (div (@ (class "categories"))
- (a (@ (class "category")
- (href "/search/?"
- "q=%28member%20%22test%22%20%28or%20%28prop%20event%20%28quote%20CATEGORIES%29%29%20%28quote%20%28%29%29%29%29"))
- test))
- (div (@ (class "rrule"))
- "Upprepas "
- "varje vecka"
- ".")
+ ; "With a description"
+ )
+ ;; (div (@ (class "categories"))
+ ;; (a (@ (class "category")
+ ;; (href "/search/?"
+ ;; "q=%28member%20%22test%22%20%28or%20%28prop%20event%20%28quote%20CATEGORIES%29%29%20%28quote%20%28%29%29%29%29"))
+ ;; test))
+ ;; (div (@ (class "rrule"))
+ ;; "Upprepas "
+ ;; "varje vecka"
+ ;; ".")
(div (@ (class "last-modified"))
- "Senast ändrad "
- "2021-09-29 19:56")))))
+ "Senast ändrad -"
+ ; "2021-09-29 19:56"
+ )))))
(define (block-template)
`(div (@ ; (id ,(html-id ev))
(data-calendar "unknown")
- (class "event CAL_unknown"
+ (class "event CAL_unknown"
;; ,(when (and (prop ev 'PARTSTAT)
;; (eq? 'TENTATIVE (prop ev 'PARTSTAT)))
;; " tentative")
diff --git a/static/clock.js b/static/clock.js
index 240041a9..d33d603a 100644
--- a/static/clock.js
+++ b/static/clock.js
@@ -75,7 +75,7 @@ class ClockElement extends HTMLElement {
this.update(new Date)
}
- static get observerAttributes () {
+ static get observedAttributes () {
return ['timer_id']
}
diff --git a/static/globals.js b/static/globals.js
index b881c531..4ee3c62a 100644
--- a/static/globals.js
+++ b/static/globals.js
@@ -35,6 +35,7 @@ class VEvent {
e.value = value;
}
for (let el of this.registered) {
+ /* TODO update correct fields, allow component to redraw themselves */
el.redraw(this);
}
}
@@ -188,10 +189,13 @@ class ComponentVEvent extends HTMLElement {
for (let el of body.getElementsByClassName("bind")) {
let p = el.dataset.property;
- let d;
+ let d, fmt;
if ((d = data.getProperty(p))) {
- /* TODO format */
- el.innerHTML = d;
+ if ((fmt = el.dataset.fmt)) {
+ el.innerHTML = d.format(fmt);
+ } else {
+ el.innerHTML = d;
+ }
}
}
@@ -211,10 +215,61 @@ class ComponentEdit extends ComponentVEvent {
constructor () {
super();
+ this.firstTime = true;
+ }
+
+ connectedCallback() {
+
/* Edit tab is rendered here. It's left blank server-side, since
it only makes sense to have something here if we have javascript */
this.redraw(vcal_objects[this.dataset.uid]);
+
+ for (let el of this.getElementsByClassName("interactive")) {
+ el.addEventListener('input', () => {
+ vcal_objects[this.dataset.uid].setProperty(
+ el.dataset.property,
+ el.value)
+ });
+ }
}
+
+ redraw (data) {
+ // update ourselves from template
+
+ if (! this.template) {
+ throw "Something";
+ }
+
+ let body;
+ if (this.firstTime) {
+ body = this.template.content.cloneNode(true).firstElementChild;
+ } else {
+ body = this;
+ }
+
+ for (let el of body.getElementsByClassName("interactive")) {
+ let p = el.dataset.property;
+ let d;
+ if ((d = data.getProperty(p))) {
+ /*
+ https://stackoverflow.com/questions/57157830/how-can-i-specify-the-sequence-of-running-nested-web-components-constructors
+ */
+ window.setTimeout (() => {
+ /* NOTE Some specific types might require special formatting
+ here. But due to my custom components implementing custom
+ `.value' procedures, we might not need any special cases
+ here */
+ el.value = d;
+ });
+ }
+ }
+
+ if (this.firstTime) {
+ this.replaceChildren(body);
+ this.firstTime = false;
+ }
+ }
+
}
class ComponentBlock extends ComponentVEvent {
@@ -255,3 +310,38 @@ window.addEventListener('load', function () {
customElements.define('vevent-block', ComponentBlock);
})
+
+
+class DateTimeInput extends HTMLElement {
+ constructor () {
+ super();
+ this.innerHTML = '<input type="date" /><input type="time" />'
+ }
+
+ get value () {
+ let date = this.querySelector("[type='date']").value;
+ let time = this.querySelector("[type='time']").value;
+ return parseDate(date + 'T' + time)
+ }
+
+ set value (new_value) {
+ let date, time;
+ if (new_value instanceof Date) {
+ date = new_value.format("~L~Y-~m-~d");
+ time = new_value.format("~L~H:~M:~S");
+ } else {
+ [date, time] = new_value.split('T')
+ }
+ this.querySelector("[type='date']").value = date;
+ this.querySelector("[type='time']").value = time;
+ }
+
+ addEventListener(type, proc) {
+ if (type != 'input') throw "Only input supported";
+
+ this.querySelector("[type='date']").addEventListener(type, proc);
+ this.querySelector("[type='time']").addEventListener(type, proc);
+ }
+}
+
+customElements.define('date-time-input', DateTimeInput)