From 6c537f3f60aaac8ae850f8ecaefc2a0d04a8431e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=B6rnquist?= Date: Thu, 2 Dec 2021 01:51:28 +0100 Subject: Add basic changelog view --- static/components/changelog.ts | 49 ++++++++++++++++++++++++++++++++++++++++ static/components/vevent-edit.ts | 2 +- static/elements.ts | 2 ++ static/types.ts | 10 +++++++- static/vevent.ts | 48 ++++++++++++++++++++++++++++++++++++++- 5 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 static/components/changelog.ts (limited to 'static') diff --git a/static/components/changelog.ts b/static/components/changelog.ts new file mode 100644 index 00000000..8f45794d --- /dev/null +++ b/static/components/changelog.ts @@ -0,0 +1,49 @@ +import { makeElement } from '../lib' +import { ComponentVEvent } from './vevent' +import { VEvent } from '../vevent' + +export { VEventChangelog } + +class VEventChangelog extends ComponentVEvent { + + ul: HTMLElement + + constructor(uid?: string) { + super(uid); + + this.ul = makeElement('ul'); + } + + connectedCallback() { + this.replaceChildren(this.ul); + } + + redraw(data: VEvent) { + /* TODO only redraw what is needed */ + let children = [] + for (let el of data._changelog) { + let msg = ''; + switch (el.type) { + case 'property': + msg += `change ${el.name}: ` + msg += `from "${el.from}" to "${el.to}"` + break; + case 'calendar': + if (el.from === null && el.to === null) { + msg += '???' + } else if (el.from === null) { + msg += `set calendar to "${atob(el.to!)}"` + } else if (el.to === null) { + msg += `Remove calendar "${atob(el.from)}"` + } else { + msg += `Change calendar from "${atob(el.from)}" to "${atob(el.to)}"` + } + break; + } + + children.push(makeElement('li', { textContent: msg })); + } + + this.ul.replaceChildren(...children) + } +} diff --git a/static/components/vevent-edit.ts b/static/components/vevent-edit.ts index 58cee870..d48c7967 100644 --- a/static/components/vevent-edit.ts +++ b/static/components/vevent-edit.ts @@ -58,7 +58,7 @@ class ComponentEdit extends ComponentVEvent { // console.log(el); el.addEventListener('input', (e) => { let obj = vcal_objects.get(this.uid) - console.log(el, e); + // console.log(el, e); if (obj === undefined) { throw 'No object with uid ' + this.uid } diff --git a/static/elements.ts b/static/elements.ts index 870a27e6..199839f6 100644 --- a/static/elements.ts +++ b/static/elements.ts @@ -7,6 +7,7 @@ import { PopupElement } from './components/popup-element' import { InputList } from './components/input-list' import { EditRRule } from './components/edit-rrule' import { TabGroupElement } from './components/tab-group-element' +import { VEventChangelog } from './components/changelog' export { initialize_components } @@ -31,4 +32,5 @@ function initialize_components() { /* These maybe also require that the global maps are initialized */ customElements.define('popup-element', PopupElement) customElements.define('tab-group', TabGroupElement) + customElements.define('vevent-changelog', VEventChangelog); } diff --git a/static/types.ts b/static/types.ts index 567b9a95..64e2c709 100644 --- a/static/types.ts +++ b/static/types.ts @@ -2,7 +2,8 @@ export { ical_type, valid_input_types, JCalProperty, JCal, - xcal, uid + xcal, uid, + ChangeLogEntry } let all_types = [ @@ -198,3 +199,10 @@ type JCalProperty type JCal = [tagname, JCalProperty[], JCal[]] const xcal = "urn:ietf:params:xml:ns:icalendar-2.0"; + +interface ChangeLogEntry { + type: 'calendar' | 'property', + name: string, + from: string | null, + to: string | null, +} diff --git a/static/vevent.ts b/static/vevent.ts index 4b6d44c6..c7dcd406 100644 --- a/static/vevent.ts +++ b/static/vevent.ts @@ -1,4 +1,4 @@ -import { uid, ical_type, valid_input_types, JCal, JCalProperty } from './types' +import { uid, ical_type, valid_input_types, JCal, JCalProperty, ChangeLogEntry } from './types' import { parseDate } from './lib' export { @@ -103,6 +103,32 @@ class VEvent { _calendar: string | null = null; + _changelog: ChangeLogEntry[] = [] + + addlog(entry: ChangeLogEntry) { + let len = this._changelog.length + let last = this._changelog[len - 1] + + // console.log('entry = ', entry, ', last = ', last); + + if (!last) { + // console.log('Adding new entry', entry, this.getProperty('uid')); + this._changelog.push(entry); + return; + } + + if (entry.type === last.type + && entry.name === last.name + && entry.from === last.to) { + this._changelog.pop(); + entry.from = last.from + // console.log('Changing old entry', entry, this.getProperty('uid')); + this._changelog.push(entry) + } else { + this._changelog.push(entry) + } + } + constructor( properties: Map = new Map(), components: VEvent[] = [] @@ -159,6 +185,20 @@ class VEvent { } key = key.toUpperCase(); + + /* + To is mostly for the user. From is to allow an undo button + */ + let entry: ChangeLogEntry = { + type: 'property', + name: key, + from: this.getProperty(key), // TODO what happens if getProperty returns a weird type + to: '' + value, + } + // console.log('Logging ', entry); + this.addlog(entry); + + if (Array.isArray(value)) { this.properties.set(key, value.map(el => new VEventValue(resolve_type(key, type), el))) @@ -201,6 +241,12 @@ class VEvent { set calendar(calendar: string | null) { + this.addlog({ + type: 'calendar', + name: '', + from: this._calendar, + to: calendar, + }); this._calendar = calendar; for (let el of this.registered) { el.redraw(this); -- cgit v1.2.3