aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--module/calp/html/vcomponent.scm34
-rw-r--r--module/calp/html/view/calendar/week.scm51
-rw-r--r--static/globals.ts120
-rw-r--r--static/style.scss3
-rw-r--r--static/vevent.ts4
5 files changed, 190 insertions, 22 deletions
diff --git a/module/calp/html/vcomponent.scm b/module/calp/html/vcomponent.scm
index 09d0038b..d1cd4886 100644
--- a/module/calp/html/vcomponent.scm
+++ b/module/calp/html/vcomponent.scm
@@ -316,6 +316,40 @@
(input (@ (type "submit")))
)))
+;; (define-public (property-input-template)
+;; (div (@ (class ""))
+;; (input (@ (type "text")
+;; (name "name")
+;; (list "known-fields")
+;; (placeholder "Nytt fält")))
+;; (select (@ (name "type"))
+;; (option (@ (value "TEXT")) "Text"))
+;; (span
+;; (input (@ (type "text")
+;; (name "value")
+;; (placeholder "Värde"))))))
+
+;; (define (list-input-template)
+;; ;; 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")
+;; ))))
;; Single event in side bar (text objects)
(define-public (fmt-day day)
diff --git a/module/calp/html/view/calendar/week.scm b/module/calp/html/view/calendar/week.scm
index 17bb3b2d..388c2f07 100644
--- a/module/calp/html/view/calendar/week.scm
+++ b/module/calp/html/view/calendar/week.scm
@@ -99,18 +99,51 @@
;; onclick: "close_popup(document.getElementById(this.closest('.popup-container').id))"
class: '("close-tooltip")))
- ,(tabset
- `(("📅" title: "Översikt"
- (vevent-description
- (@ (class "vevent populate-with-uid")))
- )
+ (div (@ (class "tabgroup"))
+ (tab-element
+ (@ (title "Översikt"))
+ (span (@ (slot "label")) "📅")
+ (vevent-description
+ (@ (slot "content")
+ (class "vevent populate-with-uid"))))
+ (tab-element
+ (@ (title "Redigera"))
+ (span (@ (slot "label")) "📅")
+ (vevent-edit (@ (slot "content")
+ (class "populate-with-uid")))
+ ))
- ,@(when (edit-mode)
- `(("📅" title: "Redigera"
- (vevent-edit (@ (class "populate-with-uid"))))))
+ ;; ,(tabset
+ ;; `(("📅" title: "Översikt"
+ ;; (vevent-description
+ ;; (@ (class "vevent populate-with-uid")))
+ ;; )
- )))))
+ ;; ,@(when (edit-mode)
+ ;; `(("📅" title: "Redigera"
+ ;; (vevent-edit (@ (class "populate-with-uid"))))))
+ ;; ))
+ )))
+
+ (template
+ (@ (id "tab-template"))
+ ;; ,((@ (calp html components) include-css) "/static/tab.css")
+ (div (@ (class "tab"))
+ (input (@ (type "radio")
+ ;; id
+ ;; (name ,tabgroup)
+ ))
+ (label (@ ; for id
+ ;; style= top: calc(var(--tab-size) * i)
+ (title ; title
+ ))
+ (slot (@ (name "label")) "??")
+ )
+ (div (@ (class "content"))
+ (slot (@ (name "content"))
+ (span (@ (class "error"))
+ "CONTENT MISSING")))))
)))
;; based on the output of fmt-single-event
diff --git a/static/globals.ts b/static/globals.ts
index 0df1aabd..970de8f7 100644
--- a/static/globals.ts
+++ b/static/globals.ts
@@ -63,6 +63,18 @@ class ComponentDescription extends ComponentVEvent {
}
+function popuplateTab(tab: HTMLElement, tabgroup: string, index: number) {
+ // console.log(tab);
+ let new_id = gensym();
+ let input = tab.querySelector('input[type="radio"]') as HTMLInputElement;
+ let label = tab.querySelector("label")!
+ tab.style.setProperty('--tab-index', '' + index);
+ /* TODO this throws a number of errors, but somehow still works...? */
+ input.name = tabgroup
+ input.id = new_id;
+ label.setAttribute('for', new_id);
+}
+
class ComponentEdit extends ComponentVEvent {
firstTime: boolean
@@ -246,7 +258,7 @@ class DateTimeInput extends /* HTMLInputElement */ HTMLElement {
constructor() {
super();
this.innerHTML = '<input type="date" /><input type="time" />'
- console.log('constructing datetime input')
+ // console.log('constructing datetime input')
}
static get observedAttributes() {
@@ -254,7 +266,7 @@ class DateTimeInput extends /* HTMLInputElement */ HTMLElement {
}
attributeChangedCallback(name: string, from: any, to: any) {
- console.log(this, name, boolean(from), boolean(to));
+ // console.log(this, name, boolean(from), boolean(to));
switch (name) {
case 'dateonly':
(this.querySelector('input[type="time"]') as HTMLInputElement)
@@ -290,7 +302,7 @@ class DateTimeInput extends /* HTMLInputElement */ HTMLElement {
}
set value(new_value: Date | string) {
- console.log('Setting date');
+ // console.log('Setting date');
let date, time;
if (new_value instanceof Date) {
date = new_value.format("~L~Y-~m-~d");
@@ -314,16 +326,67 @@ class DateTimeInput extends /* HTMLInputElement */ HTMLElement {
customElements.define('date-time-input', DateTimeInput /*, { extends: 'input' } */)
+function verifySlot(el: Node | null): el is HTMLElement {
+ if (el === null) {
+ console.error("Element is null");
+ return false;
+ }
+ if (!(el instanceof HTMLElement)) {
+ console.error("Node is not an HTMLElement", el);
+ return false;
+ }
+ return true
+}
+
+class TabElement extends HTMLElement {
+ constructor() {
+ super();
+ }
+
+ connectedCallback() {
+ // this.replaceChildren(template.cloneNode(true));
+ let template
+ = (document.getElementById('tab-template') as HTMLTemplateElement)
+ .content
+ // const shadowRoot = this.attachShadow({ mode: 'open' })
+ // .appendChild(template.cloneNode(true));
+ // console.log(this);
+ let label = this.querySelector('[slot="label"]')
+ let content = this.querySelector('[slot="content"]')
+ if (!verifySlot(label)) throw "Bad label";
+ if (!verifySlot(content)) throw "Bad content";
+
+ this.replaceChildren(template.cloneNode(true));
+ this.querySelector('slot[name="label"]')!.replaceWith(label);
+ this.querySelector('slot[name="content"]')!.replaceWith(content);
+ }
+}
+
+function buildDescriptionList(data: [string, any][]): HTMLElement {
+ let dl = document.createElement('dl');
+ for (let [key, val] of data) {
+ dl.appendChild(makeElement('dt', { innerText: key }))
+ dl.appendChild(makeElement('dd', { innerText: val }))
+ }
+ return dl;
+}
+
class PopupElement extends HTMLElement {
+
+ tabgroup_id: string
+ tabcount: number
+
constructor() {
super();
/* TODO populate remaining */
// this.id = 'popup' + this.dataset.uid
+ this.tabgroup_id = gensym();
+ this.tabcount = 0
}
redraw() {
- console.log('IMPLEMENT ME');
+ console.warn('IMPLEMENT ME');
}
connectedCallback() {
@@ -340,14 +403,23 @@ class PopupElement extends HTMLElement {
.forEach((e) => e.setAttribute('data-uid', uid));
/* tabs */
- let tabgroup_id = gensym();
- for (let tab of body.querySelectorAll(".tabgroup .tab")) {
- let new_id = gensym();
- let input = tab.querySelector("input")!;
- input.id = new_id;
- input.name = tabgroup_id;
- tab.querySelector("label")!.setAttribute('for', new_id);
- }
+ // for (let tab of body.querySelectorAll(".tabgroup .tab")) {
+ // }
+ window.setTimeout(() => {
+ // let tabs = this.querySelector('tab-element')!
+ // .shadowRoot!
+ // .querySelectorAll('label')
+ // console.log(tabs);
+ // console.log(this.getElementsByTagName('tab-element'))
+ for (let tab of this.getElementsByTagName('tab-element')) {
+ // console.log(tab_container);
+ // let tab = tab_container.shadowRoot!;
+ // tab.documentElement.style.setProperty('--i', i);
+ popuplateTab(tab as TabElement, this.tabgroup_id, this.tabcount)
+ this.tabcount += 1
+ }
+ (this.querySelector('tab-element label') as HTMLInputElement).click()
+ });
/* end tabs */
/* nav bar */
@@ -370,11 +442,35 @@ class PopupElement extends HTMLElement {
// event.properties.calendar = this.value;
});
+
+
+ let tab = makeElement('tab-element', { title: 'Debug' }) as TabElement
+ /// let tab = new TabElement();
+ tab.setAttribute('title', 'Debug')
+ tab.appendChild(makeElement('span', { slot: 'label', innerText: 'D' }))
+ // let dl = makeElement('dl', { slot: 'content' })
+ let obj = vcal_objects.get(uid)!
+ let dl = buildDescriptionList(
+ Array.from(obj.boundProperties)
+ .map(key => [key, obj.getProperty(key)]))
+ dl.slot = 'content'
+ tab.appendChild(dl)
+
+ this.addTab(tab);
+ // window.setTimeout(() => { this.addTab(tab) })
+ }
+
+ addTab(tab: TabElement) {
+ let tabgroup = this.getElementsByClassName('tabgroup')![0]!
+ tabgroup.append(tab);
+ popuplateTab(tab, this.tabgroup_id, this.tabcount)
+ this.tabcount += 1
}
}
window.addEventListener('load', function() {
customElements.define('popup-element', PopupElement)
+ customElements.define('tab-element', TabElement)
});
function wholeday_checkbox(box: HTMLInputElement) {
diff --git a/static/style.scss b/static/style.scss
index cc1ae15b..56acd18c 100644
--- a/static/style.scss
+++ b/static/style.scss
@@ -856,9 +856,10 @@ popup-element {
.tab {
> label {
position: absolute;
+ top: calc(var(--tab-size) * var(--tab-index));
left: 100%;
- top: 0;
+ /*top: 0; */
display: block;
max-height: 5ex;
diff --git a/static/vevent.ts b/static/vevent.ts
index 9d6cec88..ade5d222 100644
--- a/static/vevent.ts
+++ b/static/vevent.ts
@@ -77,6 +77,10 @@ class VEvent {
return e.value;
}
+ get boundProperties(): IterableIterator<string> {
+ return this.properties.keys()
+ }
+
setProperty(key: string, value: any) {
let e = this.properties.get(key);
if (!e) {