From 1ef01481fa9e70ef688b24ffd7957b97f020bb2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=B6rnquist?= Date: Fri, 10 Dec 2021 01:49:11 +0100 Subject: Major move from week to calendar meta-view. Also repairs month view. --- module/calp/html/vcomponent.scm | 350 +++++++++++++++++++++++-------- module/calp/html/view/calendar.scm | 6 + module/calp/html/view/calendar/month.scm | 23 +- module/calp/html/view/calendar/week.scm | 175 +--------------- static/components/vevent-block.ts | 61 +++--- static/style.scss | 11 +- 6 files changed, 329 insertions(+), 297 deletions(-) diff --git a/module/calp/html/vcomponent.scm b/module/calp/html/vcomponent.scm index b5a4260e..43efe656 100644 --- a/module/calp/html/vcomponent.scm +++ b/module/calp/html/vcomponent.scm @@ -200,98 +200,6 @@ ))) -(define-public (edit-template calendars) - `(div (@ (class " eventtext edit-tab ")) - (form (@ (class "edit-form")) - (select (@ (class "calendar-selection")) - (option "- Choose a Calendar -") - ,@(let ((dflt (get-config 'default-calendar))) - (map (lambda (calendar) - (define name (prop calendar 'NAME)) - `(option (@ (value ,(base64encode name)) - ,@(when (string=? name dflt) - '((selected)))) - ,name)) - calendars))) - (h3 (input (@ (type "text") - (placeholder "Sammanfattning") - (name "summary") (required) - (data-property "summary") - ; (value ,(prop ev 'SUMMARY)) - ))) - - (div (@ (class "timeinput")) - - ,@(with-label - "Starttid" - '(date-time-input (@ (name "dtstart") - (data-property "dtstart") - ))) - - ,@(with-label - "Sluttid" - '(date-time-input (@ (name "dtend") - (data-property "dtend")))) - - (div (@ (class "checkboxes")) - ,@(with-label - "Heldag?" - `(input (@ (type "checkbox") - (name "wholeday") - ))) - ,@(with-label - "Upprepande?" - `(input (@ (type "checkbox") - (name "has_repeats") - )))) - - ) - - ,@(with-label - "Plats" - `(input (@ (placeholder "Plats") - (name "location") - (type "text") - (data-property "location") - ; (value ,(or (prop ev 'LOCATION) "")) - ))) - - ,@(with-label - "Beskrivning" - `(textarea (@ (placeholder "Beskrivning") - (data-property "description") - (name "description")) - ; ,(prop ev 'DESCRIPTION) - )) - - ,@(with-label - "Kategorier" - `(input-list - (@ (name "categories") - (data-property "categories")) - (input (@ (type "text") - (placeholder "Kattegori"))))) - - ;; TODO This should be a "list" where any field can be edited - ;; directly. Major thing holding us back currently is that - ;; doesn't supported advanced inputs - ;; (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"))) - ))) - ;; Single event in side bar (text objects) @@ -427,3 +335,261 @@ (prop event 'DTSTART))) "~Y-~m-~dT~H:~M:~S")))))) + +(define (week-day-select args) + `(select (@ ,@args) + (option "-") + ,@(map (lambda (x) `(option (@ (value ,(car x))) ,(cadr x))) + '((MO "Monday") + (TU "Tuesday") + (WE "Wednesday") + (TH "Thursday") + (FR "Friday") + (SA "Saturday") + (SU "Sunday"))))) + + +;;; Templates + + +;; edit tab of popup +(define-public (edit-template calendars) + `(template + (@ (id "vevent-edit")) + (div (@ (class " eventtext edit-tab ")) + (form (@ (class "edit-form")) + (select (@ (class "calendar-selection")) + (option "- Choose a Calendar -") + ,@(let ((dflt (get-config 'default-calendar))) + (map (lambda (calendar) + (define name (prop calendar 'NAME)) + `(option (@ (value ,(base64encode name)) + ,@(when (string=? name dflt) + '((selected)))) + ,name)) + calendars))) + (h3 (input (@ (type "text") + (placeholder "Sammanfattning") + (name "summary") (required) + (data-property "summary") + ; (value ,(prop ev 'SUMMARY)) + ))) + + (div (@ (class "timeinput")) + + ,@(with-label + "Starttid" + '(date-time-input (@ (name "dtstart") + (data-property "dtstart") + ))) + + ,@(with-label + "Sluttid" + '(date-time-input (@ (name "dtend") + (data-property "dtend")))) + + (div (@ (class "checkboxes")) + ,@(with-label + "Heldag?" + `(input (@ (type "checkbox") + (name "wholeday") + ))) + ,@(with-label + "Upprepande?" + `(input (@ (type "checkbox") + (name "has_repeats") + )))) + + ) + + ,@(with-label + "Plats" + `(input (@ (placeholder "Plats") + (name "location") + (type "text") + (data-property "location") + ; (value ,(or (prop ev 'LOCATION) "")) + ))) + + ,@(with-label + "Beskrivning" + `(textarea (@ (placeholder "Beskrivning") + (data-property "description") + (name "description")) + ; ,(prop ev 'DESCRIPTION) + )) + + ,@(with-label + "Kategorier" + `(input-list + (@ (name "categories") + (data-property "categories")) + (input (@ (type "text") + (placeholder "Kattegori"))))) + + ;; TODO This should be a "list" where any field can be edited + ;; directly. Major thing holding us back currently is that + ;; doesn't supported advanced inputs + ;; (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"))) + )))) + +;; description in sidebar / tab of popup +;; Template data for +(define-public (description-template) + '(template + (@ (id "vevent-description")) + (div (@ (class " vevent eventtext summary-tab " ())) + (h3 ((span (@ (class "repeating")) ; "↺" + ) + (span (@ (class "summary") + (data-property "summary"))))) + (div (div (time (@ (class "dtstart") + (data-property "dtstart") + (data-fmt "~L~H:~M") + (datetime ; "2021-09-29T19:56:46" + )) + ; "19:56" + ) + "\xa0—\xa0" + (time (@ (class "dtend") + (data-property "dtend") + (data-fmt "~L~H:~M") + (datetime ; "2021-09-29T19:56:46" + )) + ; "20:56" + )) + (div (@ (class "fields")) + (div (b "Plats: ") + (div (@ (class "location") + (data-property "location")) + ; "Alsättersgatan 13" + )) + (div (@ (class "description") + (data-property "description")) + ; "With a description" + ) + + (div (@ (class "categories") + (data-property "categories"))) + ;; (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" + )))))) + +(define-public (vevent-edit-rrule-template) + `(template + (@ (id "vevent-edit-rrule")) + (div (@ (class "eventtext")) + (h2 "Upprepningar") + (dl + (dt "Frequency") + (dd (select (@ (name "freq")) + (option "-") + ,@(map (lambda (x) `(option (@ (value ,x)) ,(string-titlecase (symbol->string x)))) + '(SECONDLY MINUTELY HOURLY DAILY WEEKLY MONTHLY YEARLY)))) + + (dt "Until") + (dd (date-time-input (@ (name "until")))) + + (dt "Conut") + (dd (input (@ (type "number") (name "count") (min 0)))) + + (dt "Interval") + (dd (input (@ (type "number") (name "interval") ; min and max depend on FREQ + ))) + + ,@(concatenate + (map (lambda (pair) + (define name (list-ref pair 0)) + (define pretty-name (list-ref pair 1)) + (define min (list-ref pair 2)) + (define max (list-ref pair 3)) + `((dt ,pretty-name) + (dd (input-list (@ (name ,name)) + (input (@ (type "number") + (min ,min) (max ,max))))))) + '((bysecond "By Second" 0 60) + (byminute "By Minute" 0 59) + (byhour "By Hour" 0 23) + (bymonthday "By Month Day" -31 31) ; except 0 + (byyearday "By Year Day" -366 366) ; except 0 + (byweekno "By Week Number" -53 53) ; except 0 + (bymonth "By Month" 1 12) + (bysetpos "By Set Position" -366 366) ; except 0 + ))) + + ;; (dt "By Week Day") + ;; (dd (input-list (@ (name "byweekday")) + ;; (input (@ (type number) + ;; (min -53) (max 53) ; except 0 + ;; )) + ;; ,(week-day-select '()) + ;; )) + + (dt "Weekstart") + (dd ,(week-day-select '((name "wkst"))))))) + ) + + +;; Based on popup:s output +(define-public (popup-template) + `(template + (@ (id "popup-template")) + ;; becomes the direct child of + (div (@ (class "popup-root window") + (onclick "event.stopPropagation()")) + + (nav (@ (class "popup-control")) + (button (@ (class "close-button") + (title "Stäng") + (aria-label "Close")) + "×") + (button (@ (class "maximize-button") + (title "Fullskärm") + ;; (aria-label "") + ) + "🗖") + (button (@ (class "remove-button") + (title "Ta Bort")) + "🗑")) + + (tab-group (@ (class "window-body")) + (vevent-description + (@ (data-label "📅") (data-title "Översikt") + (class "vevent"))) + + (vevent-edit + (@ (data-label "🖊") (data-title "Redigera"))) + + ;; (vevent-edit-rrule + ;; (@ (data-label "↺") (data-title "Upprepningar"))) + + (vevent-changelog + (@ (data-label "📒") (date-title "Changelog"))) + + ,@(when (debug) + '((vevent-dl + (@ (data-label "🐸") (data-title "Debug"))))))))) diff --git a/module/calp/html/view/calendar.scm b/module/calp/html/view/calendar.scm index 62d55210..d08210bc 100644 --- a/module/calp/html/view/calendar.scm +++ b/module/calp/html/view/calendar.scm @@ -339,6 +339,12 @@ window.default_calendar='~a';" ;; ;; ,(popup event (string-append "popup" (html-id event)))) ;; )) + ;;; Templates used by our custom components + ,((@ (calp html vcomponent) edit-template) calendars) + ,((@ (calp html vcomponent) description-template)) + ,((@ (calp html vcomponent) vevent-edit-rrule-template)) + ,((@ (calp html vcomponent) popup-template)) + ;; Auto-complets when adding new fields to a component ;; Any string is however still valid. (datalist (@ (id "known-fields")) diff --git a/module/calp/html/view/calendar/month.scm b/module/calp/html/view/calendar/month.scm index 0ac69292..0e29f5b2 100644 --- a/module/calp/html/view/calendar/month.scm +++ b/module/calp/html/view/calendar/month.scm @@ -11,7 +11,7 @@ :select (really-long-event? events-between)) :use-module ((calp html vcomponent) - :select (make-block)) + :select (make-block output-uid)) :use-module ((vcomponent group) :select (group-stream get-groups-between)) ) @@ -77,11 +77,26 @@ (repeating-naturals 1 7) ))) - ;; These popups are relative the document root. Can thus be placed anywhere in the DOM. + ;; These popups are relative the document root. + ;; Can thus be placed anywhere in the DOM. ,@(for event in (stream->list (events-between start-date end-date events)) - ((@ (calp html vcomponent) popup) event - (string-append "popup" ((@ (calp html util) html-id) event)))) + `(popup-element + (@ (class "vevent") + (data-uid ,(output-uid event))))) + + (template + (@ (id "vevent-block")) + ;; TODO this is more or less copied verbatim from week's + ;; version, warts and all. Figure out what should and shouldn't + ;; be shared between the two. + (div (@ (data-calendar "unknown")) + (div (@ (class "event-body")) + (span (@ (class "repeating"))) + (span (@ (class "summary") + (data-property "summary"))) + (span (@ (class "location") + (data-property "location")))))) )) diff --git a/module/calp/html/view/calendar/week.scm b/module/calp/html/view/calendar/week.scm index 16ceeb6f..3eb8752b 100644 --- a/module/calp/html/view/calendar/week.scm +++ b/module/calp/html/view/calendar/week.scm @@ -59,184 +59,19 @@ (@ (class "vevent") (data-uid ,(output-uid event))))))) - ;; description in sidebar / tab of popup - (template (@ (id "vevent-description")) - ,(description-template) - ) - - ;; edit tab of popup - (template (@ (id "vevent-edit")) - ,((@ (calp html vcomponent) edit-template) - calendars - )) - ;; "physical" block + ;; This template is here, instead of in (calp html calendar) since it only + ;; applies to this specific view. (calp html calendar month) is assumed to + ;; have its own variant of it. (template (@ (id "vevent-block")) ,(block-template) ) - (template (@ (id "vevent-edit-rrule")) - ,(vevent-edit-rrule-template)) - - ;; Based on popup:s output - (template (@ (id "popup-template")) - ,(popup-template))))) - - -(define-record-type tab - (fields title label body)) - -(define (popup-template) - - ;; becomes the direct child of - `(div (@ (class "popup-root window") - (onclick "event.stopPropagation()")) - - (nav (@ (class "popup-control")) - (button (@ (class "close-button") - (title "Stäng") - (aria-label "Close")) - "×") - (button (@ (class "maximize-button") - (title "Fullskärm") - ;; (aria-label "") - ) - "🗖") - (button (@ (class "remove-button") - (title "Ta Bort")) - "🗑")) - - (tab-group (@ (class "window-body")) - (vevent-description - (@ (data-label "📅") (data-title "Översikt") - (class "vevent"))) - - (vevent-edit - (@ (data-label "🖊") (data-title "Redigera"))) - - ;; (vevent-edit-rrule - ;; (@ (data-label "↺") (data-title "Upprepningar"))) - - (vevent-changelog - (@ (data-label "📒") (date-title "Changelog"))) - ,@(when (debug) - '((vevent-dl - (@ (data-label "🐸") (data-title "Debug"))))) - ))) - -(define (week-day-select args) - `(select (@ ,@args) - (option "-") - ,@(map (lambda (x) `(option (@ (value ,(car x))) ,(cadr x))) - '((MO "Monday") - (TU "Tuesday") - (WE "Wednesday") - (TH "Thursday") - (FR "Friday") - (SA "Saturday") - (SU "Sunday"))))) - -(define (vevent-edit-rrule-template) - `(div (@ (class "eventtext")) - (h2 "Upprepningar") - (dl - (dt "Frequency") - (dd (select (@ (name "freq")) - (option "-") - ,@(map (lambda (x) `(option (@ (value ,x)) ,(string-titlecase (symbol->string x)))) - '(SECONDLY MINUTELY HOURLY DAILY WEEKLY MONTHLY YEARLY)))) - - (dt "Until") - (dd (date-time-input (@ (name "until")))) - - (dt "Conut") - (dd (input (@ (type "number") (name "count") (min 0)))) - - (dt "Interval") - (dd (input (@ (type "number") (name "interval") ; min and max depend on FREQ - ))) - - ,@(concatenate - (map (lambda (pair) - (define name (list-ref pair 0)) - (define pretty-name (list-ref pair 1)) - (define min (list-ref pair 2)) - (define max (list-ref pair 3)) - `((dt ,pretty-name) - (dd (input-list (@ (name ,name)) - (input (@ (type "number") - (min ,min) (max ,max))))))) - '((bysecond "By Second" 0 60) - (byminute "By Minute" 0 59) - (byhour "By Hour" 0 23) - (bymonthday "By Month Day" -31 31) ; except 0 - (byyearday "By Year Day" -366 366) ; except 0 - (byweekno "By Week Number" -53 53) ; except 0 - (bymonth "By Month" 1 12) - (bysetpos "By Set Position" -366 366) ; except 0 - ))) - - ;; (dt "By Week Day") - ;; (dd (input-list (@ (name "byweekday")) - ;; (input (@ (type number) - ;; (min -53) (max 53) ; except 0 - ;; )) - ;; ,(week-day-select '()) - ;; )) - - (dt "Weekstart") - (dd ,(week-day-select '((name "wkst"))))))) - -;; Template data for -(define (description-template) - '(div (@ (class " vevent eventtext summary-tab " ())) - (h3 ((span (@ (class "repeating")) ; "↺" - ) - (span (@ (class "summary") - (data-property "summary"))))) - (div (div (time (@ (class "dtstart") - (data-property "dtstart") - (data-fmt "~L~H:~M") - (datetime ; "2021-09-29T19:56:46" - )) - ; "19:56" - ) - "\xa0—\xa0" - (time (@ (class "dtend") - (data-property "dtend") - (data-fmt "~L~H:~M") - (datetime ; "2021-09-29T19:56:46" - )) - ; "20:56" - )) - (div (@ (class "fields")) - (div (b "Plats: ") - (div (@ (class "location") - (data-property "location")) - ; "Alsättersgatan 13" - )) - (div (@ (class "description") - (data-property "description")) - ; "With a description" - ) +))) - (div (@ (class "categories") - (data-property "categories"))) - ;; (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" - ))))) +;; "physical" block (define (block-template) `(div (@ ; (id ,(html-id ev)) (data-calendar "unknown") diff --git a/static/components/vevent-block.ts b/static/components/vevent-block.ts index 6b3e7dec..95c72592 100644 --- a/static/components/vevent-block.ts +++ b/static/components/vevent-block.ts @@ -48,34 +48,36 @@ class ComponentBlock extends ComponentVEvent { /* -------------------------------------------------- */ - let p; - if ((p = data.getProperty('dtstart'))) { - let c = this.closest('.event-container') as HTMLElement - let start = parseDate(c.dataset.start!).getTime() - let end = parseDate(c.dataset.end!).getTime(); - // console.log(p); - let pp = to_local(p).getTime() - let result = 100 * (Math.min(end, Math.max(start, pp)) - start) / (end - start) + "%" - if (c.classList.contains('longevents')) { - this.style.left = result - } else { - this.style.top = result + if (window.VIEW === 'week') { + let p; + if ((p = data.getProperty('dtstart'))) { + let c = this.closest('.event-container') as HTMLElement + let start = parseDate(c.dataset.start!).getTime() + let end = parseDate(c.dataset.end!).getTime(); + // console.log(p); + let pp = to_local(p).getTime() + let result = 100 * (Math.min(end, Math.max(start, pp)) - start) / (end - start) + "%" + if (c.classList.contains('longevents')) { + this.style.left = result + } else { + this.style.top = result + } + // console.log('dtstart', p); } - // console.log('dtstart', p); - } - if ((p = data.getProperty('dtend'))) { - // console.log('dtend', p); - let c = this.closest('.event-container') as HTMLElement - let start = parseDate(c.dataset.start!).getTime() - let end = parseDate(c.dataset.end!).getTime(); - let pp = to_local(p).getTime() - let result = 100 - (100 * (Math.min(end, Math.max(start, pp)) - start) / (end - start)) + "%" - if (c.classList.contains('longevents')) { - this.style.width = 'unset'; - this.style.right = result; - } else { - this.style.height = 'unset'; - this.style.bottom = result; + if ((p = data.getProperty('dtend'))) { + // console.log('dtend', p); + let c = this.closest('.event-container') as HTMLElement + let start = parseDate(c.dataset.start!).getTime() + let end = parseDate(c.dataset.end!).getTime(); + let pp = to_local(p).getTime() + let result = 100 - (100 * (Math.min(end, Math.max(start, pp)) - start) / (end - start)) + "%" + if (c.classList.contains('longevents')) { + this.style.width = 'unset'; + this.style.right = result; + } else { + this.style.height = 'unset'; + this.style.bottom = result; + } } } @@ -84,7 +86,10 @@ class ComponentBlock extends ComponentVEvent { } if (data.getProperty('rrule') !== undefined) { - (this.getElementsByClassName('repeating')![0] as HTMLElement).innerText = '↺' + let rep = this.getElementsByClassName('repeating') + if (rep && rep.length !== 0) { + (rep[0] as HTMLElement).innerText = '↺' + } } } } diff --git a/static/style.scss b/static/style.scss index 92ab9441..2ae55a31 100644 --- a/static/style.scss +++ b/static/style.scss @@ -332,12 +332,15 @@ along with their colors. .cal-cell { overflow-y: auto; - .event { + .event, vevent-block { font-size: 8pt; border-radius: 5px; padding: 2px; - margin: 2px; + margin-top: 2px; + margin-bottom: 2px; font-family: arial; + + box-sizing: border-box; } } @@ -545,7 +548,9 @@ vevent-block, .event { background-color: var(--color); color: var(--complement); - position: absolute; + // position: absolute; + display: block; + width: 100%; min-height: 1em; border: 1px solid black; -- cgit v1.2.3