From c655dde172a6f0edf17aed94338eea5d97edb12f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Ivi=C4=8Di=C4=8D?= <492712@mail.muni.cz> Date: Thu, 22 Feb 2024 20:57:45 +0100 Subject: [PATCH 01/13] added table demo --- package.json | 4 +- .../component/content-pane/content-pane.ts | 1 + .../observations-editor.less | 86 +++++++++ .../observations-editor.ts | 89 ++++++++++ .../observations-set/observations-set.less | 1 + .../observations-set/observations-set.ts | 165 ++++++++++++++++++ src/html/util/config.ts | 2 +- src/html/window.html | 4 +- 8 files changed, 348 insertions(+), 4 deletions(-) create mode 100644 src/html/component/observations-editor/observations-editor.less create mode 100644 src/html/component/observations-editor/observations-editor.ts create mode 100644 src/html/component/observations-editor/observations-set/observations-set.less create mode 100644 src/html/component/observations-editor/observations-set/observations-set.ts diff --git a/package.json b/package.json index 66bac31..d474dcb 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "dataclass": "^2.1.1", "lit": "^3.0.2", "lodash": "^4.17.21", + "tabulator-tables": "^5.6.1", "uikit": "^3.17.8", "uikit-icons": "^0.5.0" }, @@ -35,8 +36,9 @@ "@types/cytoscape-edgehandles": "^4.0.3", "@types/cytoscape-popper": "^2.0.4", "@types/lodash": "^4.14.202", - "@types/node": "^20.3.2", + "@types/node": "^20.11.19", "@types/rollup-plugin-less": "^1.1.4", + "@types/tabulator-tables": "^5.5.10", "@types/uikit": "^3.14.0", "@typescript-eslint/eslint-plugin": "^6.9.1", "@typescript-eslint/parser": "^6.9.1", diff --git a/src/html/component/content-pane/content-pane.ts b/src/html/component/content-pane/content-pane.ts index ed5ee5b..dd38b00 100644 --- a/src/html/component/content-pane/content-pane.ts +++ b/src/html/component/content-pane/content-pane.ts @@ -5,6 +5,7 @@ import { TabData } from '../../util/tab-data' import { library, icon } from '@fortawesome/fontawesome-svg-core' import '../regulations-editor/regulations-editor' import '../functions-editor/functions-editor' +import '../observations-editor/observations-editor' import { faLock, faLockOpen } from '@fortawesome/free-solid-svg-icons' import { aeonState } from '../../../aeon_events' import { ContentData } from '../../util/data-interfaces' diff --git a/src/html/component/observations-editor/observations-editor.less b/src/html/component/observations-editor/observations-editor.less new file mode 100644 index 0000000..fabede5 --- /dev/null +++ b/src/html/component/observations-editor/observations-editor.less @@ -0,0 +1,86 @@ +@import '/src/uikit-theme'; + +.accordion { + .container { + position: relative; + margin: 0.5em 0.5em; + } + + .container.active .content { + height: 100%; + padding-top: 2em; + } + + .container.active .label::before { + content: '-'; + font-size: 2em; + } + + .label { + font-size: 1.5em; + position: relative; + cursor: pointer; + } + + .label::before { + content: '+'; + position: absolute; + top: 50%; + right: -0em; + font-size: 2em; + transform: translateY(-50%); + transition: content 1s; + + } + + .content { + position: relative; + height: 0; + text-align: justify; + overflow: hidden; + } + + hr { + width: 100%; + margin-left: 0; + border: 1px solid grey; + } +} + +.observations { + height: 100%; + width: 100%; + margin: 0; + padding-bottom: 3em; + max-width: inherit; + max-height: inherit; + overflow-y: auto; + overflow-x: hidden; +} + +.header { + width: 100%; + height: 4em; + display: flex; + justify-content: space-between; + align-items: center; +} + +.import-button { + height: 2em; + right: -1em; +} + +.heading { + justify-self: center; +} + +@media (prefers-color-scheme: dark) { + .heading { + color: white; + } + +} + +@media (prefers-color-scheme: light) { +} diff --git a/src/html/component/observations-editor/observations-editor.ts b/src/html/component/observations-editor/observations-editor.ts new file mode 100644 index 0000000..e5d8374 --- /dev/null +++ b/src/html/component/observations-editor/observations-editor.ts @@ -0,0 +1,89 @@ +import { html, css, unsafeCSS, LitElement, type TemplateResult } from 'lit' +import { customElement, property, state } from 'lit/decorators.js' +import style_less from './observations-editor.less?inline' +import './observations-set/observations-set' +import { ContentData, type IVariableData } from '../../util/data-interfaces' +import { map } from 'lit/directives/map.js' +import { dummyData } from '../../util/dummy-data' +import { dialog } from '@tauri-apps/api' + +@customElement('observations-editor') +class ObservationsEditor extends LitElement { + static styles = css`${unsafeCSS(style_less)}` + @property() contentData = ContentData.create() + @state() sets: IObservationSet[] = [] + + constructor () { + super() + this.addSet('TEST') + } + + private async import (): Promise { + const handle = await dialog.open({ + title: 'Import observation set...', + multiple: false, + filters: [ + { + name: 'Comma-separated values', + extensions: ['csv'] + }, + { + name: 'Tab-separated values', + extensions: ['tsv', 'tab'] + }, + { + name: 'All', + extensions: ['*'] + } + ] + }) + if (handle === null) return + if (Array.isArray(handle)) { + this.addSet(handle.pop() ?? 'unknown') + } else { + this.addSet(handle) + } + } + + private addSet (filePath: string): void { + this.sets = this.sets.concat({ + name: filePath, + data: dummyData.variables + }) + } + + render (): TemplateResult { + return html` +
+
+
+

Observations

+ +
+
+
+ ${map(this.sets, (set) => html` +
+
+ ${set.name} +
+
+ + +
+
+
+ `)} +
+
+
+ + ` + } +} + +interface IObservationSet { + name: string + data: IVariableData[] +} diff --git a/src/html/component/observations-editor/observations-set/observations-set.less b/src/html/component/observations-editor/observations-set/observations-set.less new file mode 100644 index 0000000..da1d389 --- /dev/null +++ b/src/html/component/observations-editor/observations-set/observations-set.less @@ -0,0 +1 @@ +@import '/src/uikit-theme'; diff --git a/src/html/component/observations-editor/observations-set/observations-set.ts b/src/html/component/observations-editor/observations-set/observations-set.ts new file mode 100644 index 0000000..29c703a --- /dev/null +++ b/src/html/component/observations-editor/observations-set/observations-set.ts @@ -0,0 +1,165 @@ +import { html, css, unsafeCSS, LitElement, type TemplateResult, type PropertyValues } from 'lit' +import { customElement, query, property } from 'lit/decorators.js' +import style_less from './observations-set.less?inline' +import style_tab from 'tabulator-tables/dist/css/tabulator_simple.min.css?inline' +import { Tabulator, SortModule, EditModule, PageModule, FilterModule, SelectRowModule, FormatModule } from 'tabulator-tables' + +import { type IVariableData } from '../../../util/data-interfaces' + +@customElement('observations-set') +class ObservationsSet extends LitElement { + static styles = [css`${unsafeCSS(style_less)}`, css`${unsafeCSS(style_tab)}`] + @property() data: IVariableData[] = [] + @query('#table-wrapper') table: HTMLElement | undefined + tabulator: Tabulator | undefined + dummy = Array(100001).fill(0).map((_, index) => { + return { + name: 'var' + index, + var0: Math.round(Math.random()), + var1: Math.round(Math.random()), + var2: Math.round(Math.random()), + var3: Math.round(Math.random()), + var4: Math.round(Math.random()), + var5: Math.round(Math.random()), + var6: Math.round(Math.random()), + var7: Math.round(Math.random()), + var8: Math.round(Math.random()), + var9: Math.round(Math.random()) + } + }) + + constructor () { + super() + Tabulator.registerModule(SortModule) + Tabulator.registerModule(EditModule) + Tabulator.registerModule(PageModule) + Tabulator.registerModule(FilterModule) + Tabulator.registerModule(SelectRowModule) + Tabulator.registerModule(FormatModule) + // this.datatable = new Tabulator('#table-wrapper') + } + + protected firstUpdated (_changedProperties: PropertyValues): void { + super.firstUpdated(_changedProperties) + if (this.table !== undefined) { + this.tabulator = new Tabulator(this.table, { + columns: [ + { + title: '', + formatter: 'rowSelection', + titleFormatter: 'rowSelection', + headerSort: false + }, + { + title: 'Name', + field: 'name', + width: 100, + sorter: 'string', + headerFilter: 'input' + }, + { + title: 'Var0', + field: 'var0', + editor: 'textarea', + sorter: 'number', + headerFilter: 'tickCross', + hozAlign: 'center', + headerFilterParams: { tristate: true } + }, + { + title: 'Var1', + field: 'var1', + editor: 'textarea', + sorter: 'number', + headerFilter: 'tickCross', + hozAlign: 'center', + headerFilterParams: { tristate: true } + }, + { + title: 'Var2', + field: 'var2', + editor: 'textarea', + sorter: 'number', + headerFilter: 'tickCross', + hozAlign: 'center', + headerFilterParams: { tristate: true } + }, { + title: 'Var3', + field: 'var3', + editor: 'textarea', + sorter: 'number', + headerFilter: 'tickCross', + hozAlign: 'center', + headerFilterParams: { tristate: true } + }, { + title: 'Var4', + field: 'var4', + editor: 'textarea', + sorter: 'number', + headerFilter: 'tickCross', + hozAlign: 'center', + headerFilterParams: { tristate: true } + }, { + title: 'Var5', + field: 'var5', + editor: 'textarea', + sorter: 'number', + headerFilter: 'tickCross', + hozAlign: 'center', + headerFilterParams: { tristate: true } + }, { + title: 'Var6', + field: 'var6', + editor: 'textarea', + sorter: 'number', + headerFilter: 'tickCross', + hozAlign: 'center', + headerFilterParams: { tristate: true } + }, { + title: 'Var7', + field: 'var7', + editor: 'textarea', + sorter: 'number', + headerFilter: 'tickCross', + hozAlign: 'center', + headerFilterParams: { tristate: true } + }, { + title: 'Var8', + field: 'var8', + editor: 'textarea', + sorter: 'number', + headerFilter: 'tickCross', + hozAlign: 'center', + headerFilterParams: { tristate: true } + }, + { + title: 'Var9', + field: 'var9', + editor: 'textarea', + sorter: 'number', + headerFilter: 'tickCross', + hozAlign: 'center', + headerFilterParams: { tristate: true } + } + ], + data: this.dummy, + layout: 'fitDataTable', + pagination: true, + renderVerticalBuffer: 300, + sortMode: 'local', + initialSort: [{ column: 'var0', dir: 'asc' }], + headerSort: true, + index: 'name', + paginationSize: 20, + selectable: 'highlight' + } + ) + } + } + + render (): TemplateResult { + return html` +
+ ` + } +} diff --git a/src/html/util/config.ts b/src/html/util/config.ts index cd8a939..583102e 100644 --- a/src/html/util/config.ts +++ b/src/html/util/config.ts @@ -20,7 +20,7 @@ export const tabList: TabData[] = [ TabData.create({ id: index++, name: 'Observations', - content: () => html`

Content of observations tab

`, + content: (contentData) => html``, icon: 'o' }), TabData.create({ diff --git a/src/html/window.html b/src/html/window.html index 78e7e9a..764a5d3 100644 --- a/src/html/window.html +++ b/src/html/window.html @@ -1,10 +1,10 @@ - + Title - + From d1befbf6627d91c8fd8955c8e511b16615c2054d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Ivi=C4=8Di=C4=8D?= <492712@mail.muni.cz> Date: Thu, 29 Feb 2024 15:07:13 +0100 Subject: [PATCH 02/13] updated eslint config --- .eslintrc.yml | 10 +++------- package.json | 3 ++- src/html/component/content-pane/content-pane.ts | 2 +- src/html/component/menu/menu.ts | 2 +- src/html/component/nav-bar/nav-bar.ts | 2 +- .../observations-editor/observations-editor.ts | 2 +- .../regulations-editor/float-menu/float-menu.ts | 2 +- .../component/regulations-editor/regulations-editor.ts | 6 ++++-- src/html/component/root-component/root-component.ts | 2 +- src/html/component/search/search.ts | 2 +- src/html/component/tab-bar/tab-bar.ts | 2 +- src/html/component/undo-redo/undo-redo.ts | 2 +- 12 files changed, 18 insertions(+), 19 deletions(-) diff --git a/.eslintrc.yml b/.eslintrc.yml index f3dd41d..ddcc022 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -3,6 +3,7 @@ env: es2021: true extends: - standard-with-typescript + - plugin:wc/recommended - plugin:lit/recommended overrides: [] parserOptions: @@ -10,10 +11,5 @@ parserOptions: sourceType: module plugins: - '@typescript-eslint' -rules: { - "no-unused-vars": "off", - "@typescript-eslint/no-unused-vars": [ "error", { - "varsIgnorePattern": "^[A-Z][a-zA-Z]*$", - "argsIgnorePattern": "^[A-Z][a-zA-Z]*$" - }] -} + - 'wc' + - 'lit' diff --git a/package.json b/package.json index d474dcb..6efb698 100644 --- a/package.json +++ b/package.json @@ -46,9 +46,10 @@ "eslint": "^8.55.0", "eslint-config-standard-with-typescript": "^39.1.1", "eslint-plugin-import": "^2.29.0", - "eslint-plugin-lit": "^1.10.1", + "eslint-plugin-lit": "^1.11.0", "eslint-plugin-n": "^16.2.0", "eslint-plugin-promise": "^6.1.1", + "eslint-plugin-wc": "^2.0.4", "less": "^4.2.0", "less-loader": "^11.1.3", "typescript": "^4.9.5", diff --git a/src/html/component/content-pane/content-pane.ts b/src/html/component/content-pane/content-pane.ts index dd38b00..4c0e9d0 100644 --- a/src/html/component/content-pane/content-pane.ts +++ b/src/html/component/content-pane/content-pane.ts @@ -13,7 +13,7 @@ import { ContentData } from '../../util/data-interfaces' library.add(faLock, faLockOpen) @customElement('content-pane') -export class ContentPane extends LitElement { +export default class ContentPane extends LitElement { static styles = css`${unsafeCSS(style_less)}` @property() private readonly tab: TabData = TabData.create() diff --git a/src/html/component/menu/menu.ts b/src/html/component/menu/menu.ts index 4ad9d1d..8352280 100644 --- a/src/html/component/menu/menu.ts +++ b/src/html/component/menu/menu.ts @@ -3,7 +3,7 @@ import { customElement } from 'lit/decorators.js' import style_less from './menu.less?inline' @customElement('hamburger-menu') -class Menu extends LitElement { +export default class Menu extends LitElement { static styles = css`${unsafeCSS(style_less)}` render (): TemplateResult { diff --git a/src/html/component/nav-bar/nav-bar.ts b/src/html/component/nav-bar/nav-bar.ts index 4efc1ed..b20835f 100644 --- a/src/html/component/nav-bar/nav-bar.ts +++ b/src/html/component/nav-bar/nav-bar.ts @@ -8,7 +8,7 @@ import '../search/search' import { type TabData } from '../../util/tab-data' @customElement('nav-bar') -class NavBar extends LitElement { +export default class NavBar extends LitElement { static styles = css`${unsafeCSS(style_less)}` @property() tabs: TabData[] = [] diff --git a/src/html/component/observations-editor/observations-editor.ts b/src/html/component/observations-editor/observations-editor.ts index e5d8374..84c3c82 100644 --- a/src/html/component/observations-editor/observations-editor.ts +++ b/src/html/component/observations-editor/observations-editor.ts @@ -8,7 +8,7 @@ import { dummyData } from '../../util/dummy-data' import { dialog } from '@tauri-apps/api' @customElement('observations-editor') -class ObservationsEditor extends LitElement { +export default class ObservationsEditor extends LitElement { static styles = css`${unsafeCSS(style_less)}` @property() contentData = ContentData.create() @state() sets: IObservationSet[] = [] diff --git a/src/html/component/regulations-editor/float-menu/float-menu.ts b/src/html/component/regulations-editor/float-menu/float-menu.ts index 3f2bfc4..2e0f3c0 100644 --- a/src/html/component/regulations-editor/float-menu/float-menu.ts +++ b/src/html/component/regulations-editor/float-menu/float-menu.ts @@ -28,7 +28,7 @@ import { library.add(faRightLeft, faArrowTrendUp, faArrowTrendDown, faCalculator, faEye, faEyeSlash, faPen, faTrash, faPlus) @customElement('float-menu') -class FloatMenu extends LitElement { +export default class FloatMenu extends LitElement { static styles = css`${unsafeCSS(style_less)}` @property() type = ElementType.NONE @property() position: Position = { x: 0, y: 0 } diff --git a/src/html/component/regulations-editor/regulations-editor.ts b/src/html/component/regulations-editor/regulations-editor.ts index 8f0cd4c..757c06d 100644 --- a/src/html/component/regulations-editor/regulations-editor.ts +++ b/src/html/component/regulations-editor/regulations-editor.ts @@ -12,7 +12,7 @@ import { type Event as TauriEvent } from '@tauri-apps/api/event' import { ContentData, ElementType, type IRegulationData, type IVariableData } from '../../util/data-interfaces' @customElement('regulations-editor') -class RegulationsEditor extends LitElement { +export default class RegulationsEditor extends LitElement { static styles = css`${unsafeCSS(style_less)}` dialogs: Record = {} editorElement @@ -36,7 +36,9 @@ class RegulationsEditor extends LitElement { this.addEventListener('rename-node', (e) => { void this.renameNodeDialog(e) }) - this.addEventListener('focus-function', () => { this.toggleMenu(ElementType.NONE) }) + this.addEventListener('focus-function', () => { + this.toggleMenu(ElementType.NONE) + }) this.editorElement = document.createElement('div') this.editorElement.id = 'cytoscape-editor' } diff --git a/src/html/component/root-component/root-component.ts b/src/html/component/root-component/root-component.ts index 53ce33b..4608303 100644 --- a/src/html/component/root-component/root-component.ts +++ b/src/html/component/root-component/root-component.ts @@ -27,7 +27,7 @@ import { getNextEssentiality, getNextMonotonicity } from '../../util/utilities' const LAYOUT = 'default' @customElement('root-component') -class RootComponent extends LitElement { +export default class RootComponent extends LitElement { static styles = css`${unsafeCSS(style_less)}` @state() data: ContentData = ContentData.create() @state() tabs: TabData[] = tabList diff --git a/src/html/component/search/search.ts b/src/html/component/search/search.ts index caa6406..c32c578 100644 --- a/src/html/component/search/search.ts +++ b/src/html/component/search/search.ts @@ -3,7 +3,7 @@ import { customElement } from 'lit/decorators.js' import style_less from './search.less?inline' @customElement('search-bar') -class SearchBar extends LitElement { +export default class SearchBar extends LitElement { static styles = css`${unsafeCSS(style_less)}` render (): TemplateResult { diff --git a/src/html/component/tab-bar/tab-bar.ts b/src/html/component/tab-bar/tab-bar.ts index e969c50..f4540e4 100644 --- a/src/html/component/tab-bar/tab-bar.ts +++ b/src/html/component/tab-bar/tab-bar.ts @@ -9,7 +9,7 @@ import { aeonState } from '../../../aeon_events' library.add(faLock, fas) @customElement('tab-bar') -class TabBar extends LitElement { +export default class TabBar extends LitElement { static styles = css`${unsafeCSS(style_less)}` @property() tabs: TabData[] = [] diff --git a/src/html/component/undo-redo/undo-redo.ts b/src/html/component/undo-redo/undo-redo.ts index d58b283..9ba68ca 100644 --- a/src/html/component/undo-redo/undo-redo.ts +++ b/src/html/component/undo-redo/undo-redo.ts @@ -7,7 +7,7 @@ import { aeonState } from '../../../aeon_events' library.add(faArrowLeft, faArrowRight) @customElement('undo-redo') -class UndoRedo extends LitElement { +export default class UndoRedo extends LitElement { static styles = css`${unsafeCSS(style_less)}` @state() From 794eddbf91bb62ce682658af5b6f987e244ab38c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Ivi=C4=8Di=C4=8D?= <492712@mail.muni.cz> Date: Thu, 29 Feb 2024 15:40:28 +0100 Subject: [PATCH 03/13] component folder cleanup --- .../regulations-editor/regulations-editor.ts | 2 +- .../rename-dialog/rename-dialog.html | 0 .../rename-dialog/rename-dialog.less | 1 + .../rename-dialog/rename-dialog.ts | 77 +++++++++++++++++++ 4 files changed, 79 insertions(+), 1 deletion(-) rename src/html/component/{ => regulations-editor}/rename-dialog/rename-dialog.html (100%) create mode 100644 src/html/component/regulations-editor/rename-dialog/rename-dialog.less create mode 100644 src/html/component/regulations-editor/rename-dialog/rename-dialog.ts diff --git a/src/html/component/regulations-editor/regulations-editor.ts b/src/html/component/regulations-editor/regulations-editor.ts index 757c06d..3abe967 100644 --- a/src/html/component/regulations-editor/regulations-editor.ts +++ b/src/html/component/regulations-editor/regulations-editor.ts @@ -221,7 +221,7 @@ export default class RegulationsEditor extends LitElement { return } const renameDialog = new WebviewWindow(`renameDialog${Math.floor(Math.random() * 1000000)}`, { - url: 'src/html/component/rename-dialog/rename-dialog.html', + url: 'src/html/component/regulations-editor/rename-dialog/rename-dialog.html', title: `Edit node (${variableId} / ${variableName})`, alwaysOnTop: true, maximizable: false, diff --git a/src/html/component/rename-dialog/rename-dialog.html b/src/html/component/regulations-editor/rename-dialog/rename-dialog.html similarity index 100% rename from src/html/component/rename-dialog/rename-dialog.html rename to src/html/component/regulations-editor/rename-dialog/rename-dialog.html diff --git a/src/html/component/regulations-editor/rename-dialog/rename-dialog.less b/src/html/component/regulations-editor/rename-dialog/rename-dialog.less new file mode 100644 index 0000000..da1d389 --- /dev/null +++ b/src/html/component/regulations-editor/rename-dialog/rename-dialog.less @@ -0,0 +1 @@ +@import '/src/uikit-theme'; diff --git a/src/html/component/regulations-editor/rename-dialog/rename-dialog.ts b/src/html/component/regulations-editor/rename-dialog/rename-dialog.ts new file mode 100644 index 0000000..fb8d99d --- /dev/null +++ b/src/html/component/regulations-editor/rename-dialog/rename-dialog.ts @@ -0,0 +1,77 @@ +import { html, css, unsafeCSS, LitElement, type TemplateResult } from 'lit' +import { customElement, query } from 'lit/decorators.js' +import style_less from './rename-dialog.less?inline' +import { emit, type Event as TauriEvent, once } from '@tauri-apps/api/event' +import { appWindow, LogicalSize } from '@tauri-apps/api/window' + +@customElement('rename-dialog') +class RenameDialog extends LitElement { + static styles = css`${unsafeCSS(style_less)}` + @query('#node-name') nameField: HTMLInputElement | undefined + @query('#node-id') variableIdField: HTMLInputElement | undefined + variableId = '' + name = '' + + async firstUpdated (): Promise { + await once('edit_node_update', (event: TauriEvent<{ id: string, name: string }>) => { + this.variableId = event.payload.id + this.name = event.payload.name + if (this.variableIdField !== undefined) this.variableIdField.value = this.variableId + if (this.nameField !== undefined) this.nameField.value = this.name + }) + await emit('loaded', {}) + this.variableIdField?.focus() + await appWindow.setSize(new LogicalSize(window.outerWidth, (document.querySelector('body')?.offsetHeight ?? 200) + 20)) + } + + private async handleSubmit (event: Event): Promise { + event.preventDefault() + if (this.variableId === '' || this.name === '') { + this.nameField?.classList.remove('uk-form-danger') + this.variableIdField?.classList.remove('uk-form-danger') + if (this.variableId === '') { + this.variableIdField?.classList.add('uk-form-danger') + } + if (this.name === '') { + this.nameField?.classList.add('uk-form-danger') + } + + return + } + await emit('edit_node_dialog', { + id: this.variableId, + name: this.name + }) + await appWindow.close() + } + + private handleIdUpdate (e: Event): void { + this.variableId = (e.target as HTMLInputElement).value + } + + private handleNameUpdate (e: Event): void { + this.name = (e.target as HTMLInputElement).value + } + + render (): TemplateResult { + return html` +
+
+ +
+ +
+
+
+ +
+ +
+
+ + + +
+ ` + } +} From ffa2fb8ddf895f7e5fc260b6e2ad2a5cad67be75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Ivi=C4=8Di=C4=8D?= <492712@mail.muni.cz> Date: Thu, 29 Feb 2024 17:32:55 +0100 Subject: [PATCH 04/13] add editing to observations-editor --- .../edit-observation/edit-observation.html | 11 + .../edit-observation/edit-observation.less} | 0 .../edit-observation/edit-observation.ts | 65 +++++ .../observations-editor.ts | 6 +- .../observations-set/observations-set.less | 6 + .../observations-set/observations-set.ts | 223 +++++++++--------- .../component/rename-dialog/rename-dialog.ts | 77 ------ 7 files changed, 201 insertions(+), 187 deletions(-) create mode 100644 src/html/component/observations-editor/edit-observation/edit-observation.html rename src/html/component/{rename-dialog/rename-dialog.less => observations-editor/edit-observation/edit-observation.less} (100%) create mode 100644 src/html/component/observations-editor/edit-observation/edit-observation.ts delete mode 100644 src/html/component/rename-dialog/rename-dialog.ts diff --git a/src/html/component/observations-editor/edit-observation/edit-observation.html b/src/html/component/observations-editor/edit-observation/edit-observation.html new file mode 100644 index 0000000..ed4ac8e --- /dev/null +++ b/src/html/component/observations-editor/edit-observation/edit-observation.html @@ -0,0 +1,11 @@ + + + + + + Edit observation + + + + + \ No newline at end of file diff --git a/src/html/component/rename-dialog/rename-dialog.less b/src/html/component/observations-editor/edit-observation/edit-observation.less similarity index 100% rename from src/html/component/rename-dialog/rename-dialog.less rename to src/html/component/observations-editor/edit-observation/edit-observation.less diff --git a/src/html/component/observations-editor/edit-observation/edit-observation.ts b/src/html/component/observations-editor/edit-observation/edit-observation.ts new file mode 100644 index 0000000..8942023 --- /dev/null +++ b/src/html/component/observations-editor/edit-observation/edit-observation.ts @@ -0,0 +1,65 @@ +import { html, css, unsafeCSS, LitElement, type TemplateResult } from 'lit' +import { customElement, query, state } from 'lit/decorators.js' +import style_less from './edit-observation.less?inline' +import { emit, type Event as TauriEvent, once } from '@tauri-apps/api/event' +import { appWindow } from '@tauri-apps/api/window' +import { map } from 'lit/directives/map.js' +import { type IDummyObservation } from '../observations-set/observations-set' + +@customElement('edit-observation') +export default class EditObservation extends LitElement { + static styles = css`${unsafeCSS(style_less)}` + @query('#node-name') nameField: HTMLInputElement | undefined + @query('#node-id') variableIdField: HTMLInputElement | undefined + @state() data: IDummyObservation | undefined + id = '' + + async firstUpdated (): Promise { + await once('edit_observation_update', (event: TauriEvent) => { + this.id = event.payload.id + this.data = event.payload + }) + await emit('loaded', {}) + this.variableIdField?.focus() + } + + private async handleSubmit (event: Event): Promise { + event.preventDefault() + await emit('edit_observation_dialog', { + id: this.id, + data: this.data + }) + await appWindow.close() + } + + private getValue(data: T, key: string): T[keyof T] { + const newKey = key as keyof typeof data + return data[newKey] + } + + private setValue(data: T, key: string, value: string): void { + const newKey = key as keyof typeof data + data[newKey] = value as T[keyof T] + } + + render (): TemplateResult { + return html` +
+
+ ${map(Object.keys(this.data ?? {}), (key) => { + return html` +
+ +
+ +
+
` + })} +
+ + + +
+ ` + } +} diff --git a/src/html/component/observations-editor/observations-editor.ts b/src/html/component/observations-editor/observations-editor.ts index 84c3c82..77a3a00 100644 --- a/src/html/component/observations-editor/observations-editor.ts +++ b/src/html/component/observations-editor/observations-editor.ts @@ -62,9 +62,9 @@ export default class ObservationsEditor extends LitElement {
- ${map(this.sets, (set) => html` -
-
+ ${map(this.sets, (set, index) => html` +
+
${set.name}
diff --git a/src/html/component/observations-editor/observations-set/observations-set.less b/src/html/component/observations-editor/observations-set/observations-set.less index da1d389..6d5b229 100644 --- a/src/html/component/observations-editor/observations-set/observations-set.less +++ b/src/html/component/observations-editor/observations-set/observations-set.less @@ -1 +1,7 @@ @import '/src/uikit-theme'; + +#table-wrapper { + width: 100%; + height: 100%; + overflow-x: auto; +} \ No newline at end of file diff --git a/src/html/component/observations-editor/observations-set/observations-set.ts b/src/html/component/observations-editor/observations-set/observations-set.ts index 29c703a..e704293 100644 --- a/src/html/component/observations-editor/observations-set/observations-set.ts +++ b/src/html/component/observations-editor/observations-set/observations-set.ts @@ -1,20 +1,32 @@ import { html, css, unsafeCSS, LitElement, type TemplateResult, type PropertyValues } from 'lit' -import { customElement, query, property } from 'lit/decorators.js' +import { customElement, query, property, state } from 'lit/decorators.js' import style_less from './observations-set.less?inline' import style_tab from 'tabulator-tables/dist/css/tabulator_simple.min.css?inline' -import { Tabulator, SortModule, EditModule, PageModule, FilterModule, SelectRowModule, FormatModule } from 'tabulator-tables' +import { + Tabulator, + SortModule, + EditModule, + PageModule, + FilterModule, + SelectRowModule, + FormatModule, + type ColumnDefinition, type CellComponent, InteractionModule +} from 'tabulator-tables' import { type IVariableData } from '../../../util/data-interfaces' +import { appWindow, WebviewWindow } from '@tauri-apps/api/window' +import { type Event as TauriEvent } from '@tauri-apps/api/helpers/event' @customElement('observations-set') -class ObservationsSet extends LitElement { +export default class ObservationsSet extends LitElement { static styles = [css`${unsafeCSS(style_less)}`, css`${unsafeCSS(style_tab)}`] @property() data: IVariableData[] = [] @query('#table-wrapper') table: HTMLElement | undefined tabulator: Tabulator | undefined - dummy = Array(100001).fill(0).map((_, index) => { + @state() dummy: IDummyObservation[] = Array(100001).fill(0).map((_, index) => { return { - name: 'var' + index, + id: 'var' + String(index).padStart(4, '0'), + name: 'var' + String(index).padStart(4, '0'), var0: Math.round(Math.random()), var1: Math.round(Math.random()), var2: Math.round(Math.random()), @@ -28,6 +40,8 @@ class ObservationsSet extends LitElement { } }) + dialogs: Record = {} + constructor () { super() Tabulator.registerModule(SortModule) @@ -36,120 +50,63 @@ class ObservationsSet extends LitElement { Tabulator.registerModule(FilterModule) Tabulator.registerModule(SelectRowModule) Tabulator.registerModule(FormatModule) - // this.datatable = new Tabulator('#table-wrapper') + Tabulator.registerModule(InteractionModule) } - protected firstUpdated (_changedProperties: PropertyValues): void { + protected async firstUpdated (_changedProperties: PropertyValues): Promise { super.firstUpdated(_changedProperties) + const dataCell = (field: string): ColumnDefinition => { + return { + title: field, + field, + editor: 'textarea', + sorter: 'number', + headerFilter: 'tickCross', + hozAlign: 'center', + headerFilterParams: { tristate: true } + } + } + const columns: ColumnDefinition[] = [ + { + title: '', + formatter: 'rowSelection', + titleFormatter: 'rowSelection', + headerSort: false + }, + { + title: 'Name', + field: 'name', + width: 100, + sorter: 'string', + headerFilter: 'input' + } + ] + for (let i = 0; i < 10; i++) { + columns.push(dataCell('var' + i)) + } + columns.push({ + title: '', + formatter: (_cell, _params, _callback): string => { + return "" + }, + width: 100, + cellClick: (_e: UIEvent, _cell: CellComponent) => { + console.log('test', _e, _cell.getData()) + void this.editObservation(_cell.getData() as IDummyObservation) + } + }) if (this.table !== undefined) { this.tabulator = new Tabulator(this.table, { - columns: [ - { - title: '', - formatter: 'rowSelection', - titleFormatter: 'rowSelection', - headerSort: false - }, - { - title: 'Name', - field: 'name', - width: 100, - sorter: 'string', - headerFilter: 'input' - }, - { - title: 'Var0', - field: 'var0', - editor: 'textarea', - sorter: 'number', - headerFilter: 'tickCross', - hozAlign: 'center', - headerFilterParams: { tristate: true } - }, - { - title: 'Var1', - field: 'var1', - editor: 'textarea', - sorter: 'number', - headerFilter: 'tickCross', - hozAlign: 'center', - headerFilterParams: { tristate: true } - }, - { - title: 'Var2', - field: 'var2', - editor: 'textarea', - sorter: 'number', - headerFilter: 'tickCross', - hozAlign: 'center', - headerFilterParams: { tristate: true } - }, { - title: 'Var3', - field: 'var3', - editor: 'textarea', - sorter: 'number', - headerFilter: 'tickCross', - hozAlign: 'center', - headerFilterParams: { tristate: true } - }, { - title: 'Var4', - field: 'var4', - editor: 'textarea', - sorter: 'number', - headerFilter: 'tickCross', - hozAlign: 'center', - headerFilterParams: { tristate: true } - }, { - title: 'Var5', - field: 'var5', - editor: 'textarea', - sorter: 'number', - headerFilter: 'tickCross', - hozAlign: 'center', - headerFilterParams: { tristate: true } - }, { - title: 'Var6', - field: 'var6', - editor: 'textarea', - sorter: 'number', - headerFilter: 'tickCross', - hozAlign: 'center', - headerFilterParams: { tristate: true } - }, { - title: 'Var7', - field: 'var7', - editor: 'textarea', - sorter: 'number', - headerFilter: 'tickCross', - hozAlign: 'center', - headerFilterParams: { tristate: true } - }, { - title: 'Var8', - field: 'var8', - editor: 'textarea', - sorter: 'number', - headerFilter: 'tickCross', - hozAlign: 'center', - headerFilterParams: { tristate: true } - }, - { - title: 'Var9', - field: 'var9', - editor: 'textarea', - sorter: 'number', - headerFilter: 'tickCross', - hozAlign: 'center', - headerFilterParams: { tristate: true } - } - ], + columns, data: this.dummy, layout: 'fitDataTable', + responsiveLayout: false, pagination: true, renderVerticalBuffer: 300, sortMode: 'local', initialSort: [{ column: 'var0', dir: 'asc' }], headerSort: true, - index: 'name', + index: 'id', paginationSize: 20, selectable: 'highlight' } @@ -157,9 +114,61 @@ class ObservationsSet extends LitElement { } } + private async editObservation (data: IDummyObservation): Promise { + const pos = await appWindow.outerPosition() + const size = await appWindow.outerSize() + if (this.dialogs[data.id] !== undefined) { + await this.dialogs[data.id]?.setFocus() + return + } + const renameDialog = new WebviewWindow(`editObservation${Math.floor(Math.random() * 1000000)}`, { + url: 'src/html/component/observations-editor/edit-observation/edit-observation.html', + title: `Edit observation (${data.id} / ${data.name})`, + alwaysOnTop: true, + maximizable: false, + minimizable: false, + skipTaskbar: true, + height: 500, + width: 400, + x: pos.x + (size.width / 2) - 200, + y: pos.y + size.height / 4 + }) + this.dialogs[data.id] = renameDialog + void renameDialog.once('loaded', () => { + void renameDialog.emit('edit_observation_update', { + ...data + }) + }) + void renameDialog.once('edit_observation_dialog', (event: TauriEvent<{ id: string, data: IDummyObservation }>) => { + this.dialogs[data.id] = undefined + const index = this.dummy.findIndex(observation => observation.id === data.id) + if (index === -1) return + void this.tabulator?.updateRow(event.payload.id, event.payload.data) + console.log(event.payload) + }) + void renameDialog.onCloseRequested(() => { + this.dialogs[data.id] = undefined + }) + } + render (): TemplateResult { return html`
` } } + +export interface IDummyObservation { + id: string + name: string + var0: number + var1: number + var2: number + var3: number + var4: number + var5: number + var6: number + var7: number + var8: number + var9: number +} diff --git a/src/html/component/rename-dialog/rename-dialog.ts b/src/html/component/rename-dialog/rename-dialog.ts deleted file mode 100644 index fb8d99d..0000000 --- a/src/html/component/rename-dialog/rename-dialog.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { html, css, unsafeCSS, LitElement, type TemplateResult } from 'lit' -import { customElement, query } from 'lit/decorators.js' -import style_less from './rename-dialog.less?inline' -import { emit, type Event as TauriEvent, once } from '@tauri-apps/api/event' -import { appWindow, LogicalSize } from '@tauri-apps/api/window' - -@customElement('rename-dialog') -class RenameDialog extends LitElement { - static styles = css`${unsafeCSS(style_less)}` - @query('#node-name') nameField: HTMLInputElement | undefined - @query('#node-id') variableIdField: HTMLInputElement | undefined - variableId = '' - name = '' - - async firstUpdated (): Promise { - await once('edit_node_update', (event: TauriEvent<{ id: string, name: string }>) => { - this.variableId = event.payload.id - this.name = event.payload.name - if (this.variableIdField !== undefined) this.variableIdField.value = this.variableId - if (this.nameField !== undefined) this.nameField.value = this.name - }) - await emit('loaded', {}) - this.variableIdField?.focus() - await appWindow.setSize(new LogicalSize(window.outerWidth, (document.querySelector('body')?.offsetHeight ?? 200) + 20)) - } - - private async handleSubmit (event: Event): Promise { - event.preventDefault() - if (this.variableId === '' || this.name === '') { - this.nameField?.classList.remove('uk-form-danger') - this.variableIdField?.classList.remove('uk-form-danger') - if (this.variableId === '') { - this.variableIdField?.classList.add('uk-form-danger') - } - if (this.name === '') { - this.nameField?.classList.add('uk-form-danger') - } - - return - } - await emit('edit_node_dialog', { - id: this.variableId, - name: this.name - }) - await appWindow.close() - } - - private handleIdUpdate (e: Event): void { - this.variableId = (e.target as HTMLInputElement).value - } - - private handleNameUpdate (e: Event): void { - this.name = (e.target as HTMLInputElement).value - } - - render (): TemplateResult { - return html` -
-
- -
- -
-
-
- -
- -
-
- - - -
- ` - } -} From bf96234b6bc6d5b0685d344d9c28ae2041947bc7 Mon Sep 17 00:00:00 2001 From: Petr Ivicic Date: Fri, 1 Mar 2024 13:57:06 +0100 Subject: [PATCH 05/13] fixed table formatting --- .../observations-set/observations-set.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/html/component/observations-editor/observations-set/observations-set.ts b/src/html/component/observations-editor/observations-set/observations-set.ts index e704293..ec49cc7 100644 --- a/src/html/component/observations-editor/observations-set/observations-set.ts +++ b/src/html/component/observations-editor/observations-set/observations-set.ts @@ -25,8 +25,8 @@ export default class ObservationsSet extends LitElement { tabulator: Tabulator | undefined @state() dummy: IDummyObservation[] = Array(100001).fill(0).map((_, index) => { return { - id: 'var' + String(index).padStart(4, '0'), - name: 'var' + String(index).padStart(4, '0'), + id: 'var' + String(index).padStart(5, '0'), + name: 'var' + String(index).padStart(5, '0'), var0: Math.round(Math.random()), var1: Math.round(Math.random()), var2: Math.round(Math.random()), @@ -55,6 +55,11 @@ export default class ObservationsSet extends LitElement { protected async firstUpdated (_changedProperties: PropertyValues): Promise { super.firstUpdated(_changedProperties) + await this.init() + this.tabulator?.redraw(true) + } + + private async init(): Promise { const dataCell = (field: string): ColumnDefinition => { return { title: field, @@ -89,7 +94,9 @@ export default class ObservationsSet extends LitElement { formatter: (_cell, _params, _callback): string => { return "" }, - width: 100, + width: 70, + headerSort: false, + hozAlign: 'center', cellClick: (_e: UIEvent, _cell: CellComponent) => { console.log('test', _e, _cell.getData()) void this.editObservation(_cell.getData() as IDummyObservation) @@ -104,7 +111,7 @@ export default class ObservationsSet extends LitElement { pagination: true, renderVerticalBuffer: 300, sortMode: 'local', - initialSort: [{ column: 'var0', dir: 'asc' }], + initialSort: [{ column: 'name', dir: 'asc' }], headerSort: true, index: 'id', paginationSize: 20, From c4cd41a9dcadda21c065d38ea00d17e7302152c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Ivi=C4=8Di=C4=8D?= <492712@mail.muni.cz> Date: Thu, 7 Mar 2024 19:39:25 +0100 Subject: [PATCH 06/13] add import dialog --- .../edit-observation/edit-observation.ts | 6 +- .../observations-editor.ts | 66 ++++++-- .../observations-import.html | 11 ++ .../observations-import.less | 89 +++++++++++ .../observations-import.ts | 141 ++++++++++++++++++ .../observations-set/observations-set.ts | 57 ++----- src/html/util/data-interfaces.ts | 6 + 7 files changed, 319 insertions(+), 57 deletions(-) create mode 100644 src/html/component/observations-editor/observations-import/observations-import.html create mode 100644 src/html/component/observations-editor/observations-import/observations-import.less create mode 100644 src/html/component/observations-editor/observations-import/observations-import.ts diff --git a/src/html/component/observations-editor/edit-observation/edit-observation.ts b/src/html/component/observations-editor/edit-observation/edit-observation.ts index 8942023..dec58d3 100644 --- a/src/html/component/observations-editor/edit-observation/edit-observation.ts +++ b/src/html/component/observations-editor/edit-observation/edit-observation.ts @@ -4,18 +4,18 @@ import style_less from './edit-observation.less?inline' import { emit, type Event as TauriEvent, once } from '@tauri-apps/api/event' import { appWindow } from '@tauri-apps/api/window' import { map } from 'lit/directives/map.js' -import { type IDummyObservation } from '../observations-set/observations-set' +import { type IObservation } from '../../../util/data-interfaces' @customElement('edit-observation') export default class EditObservation extends LitElement { static styles = css`${unsafeCSS(style_less)}` @query('#node-name') nameField: HTMLInputElement | undefined @query('#node-id') variableIdField: HTMLInputElement | undefined - @state() data: IDummyObservation | undefined + @state() data: IObservation | undefined id = '' async firstUpdated (): Promise { - await once('edit_observation_update', (event: TauriEvent) => { + await once('edit_observation_update', (event: TauriEvent) => { this.id = event.payload.id this.data = event.payload }) diff --git a/src/html/component/observations-editor/observations-editor.ts b/src/html/component/observations-editor/observations-editor.ts index 77a3a00..62efbe0 100644 --- a/src/html/component/observations-editor/observations-editor.ts +++ b/src/html/component/observations-editor/observations-editor.ts @@ -2,10 +2,12 @@ import { html, css, unsafeCSS, LitElement, type TemplateResult } from 'lit' import { customElement, property, state } from 'lit/decorators.js' import style_less from './observations-editor.less?inline' import './observations-set/observations-set' -import { ContentData, type IVariableData } from '../../util/data-interfaces' +import { ContentData, type IObservation } from '../../util/data-interfaces' import { map } from 'lit/directives/map.js' -import { dummyData } from '../../util/dummy-data' import { dialog } from '@tauri-apps/api' +import { appWindow, WebviewWindow } from '@tauri-apps/api/window' +import { type Event as TauriEvent } from '@tauri-apps/api/helpers/event' +import { dummyData } from '../../util/dummy-data' @customElement('observations-editor') export default class ObservationsEditor extends LitElement { @@ -13,9 +15,24 @@ export default class ObservationsEditor extends LitElement { @property() contentData = ContentData.create() @state() sets: IObservationSet[] = [] + getDummy = (): IObservation[] => Array(100001).fill(0).map((_, index) => { + const ret: IObservation = { + id: 'obs' + String(index).padStart(4, '0'), + name: 'obs' + String(index).padStart(4, '0') + } + this.contentData.variables.forEach(v => { + ret[v.name] = Math.round(Math.random()) + }) + return ret + }) + constructor () { super() - this.addSet('TEST') + this.sets = [{ + name: 'TEST', + data: this.getDummy(), + variables: dummyData.variables.map(v => v.name) + }] } private async import (): Promise { @@ -38,17 +55,42 @@ export default class ObservationsEditor extends LitElement { ] }) if (handle === null) return + let fileName if (Array.isArray(handle)) { - this.addSet(handle.pop() ?? 'unknown') + fileName = handle.pop() ?? 'unknown' } else { - this.addSet(handle) + fileName = handle } + + void this.importObservations(fileName, this.getDummy(), this.contentData.variables.map(v => v.name)) } - private addSet (filePath: string): void { - this.sets = this.sets.concat({ - name: filePath, - data: dummyData.variables + private async importObservations (name: string, data: IObservation[], variables: string[]): Promise { + const pos = await appWindow.outerPosition() + const size = await appWindow.outerSize() + const importDialog = new WebviewWindow(`editObservation${Math.floor(Math.random() * 1000000)}`, { + url: 'src/html/component/observations-editor/observations-import/observations-import.html', + title: 'Import observation set', + alwaysOnTop: true, + maximizable: false, + minimizable: false, + skipTaskbar: true, + x: pos.x + (size.width / 2) - 200, + y: pos.y + size.height / 4 + }) + void importDialog.once('loaded', () => { + void importDialog.emit('observations_import_update', { + data, + variables: this.contentData.variables.map(v => v.name) + }) + }) + void importDialog.once('observations_import_dialog', (event: TauriEvent) => { + console.log(event.payload) + this.sets = this.sets.concat({ + name, + data: event.payload, + variables + }) }) } @@ -69,7 +111,8 @@ export default class ObservationsEditor extends LitElement {
+ .data="${set.data}" + .variables="${set.variables}">
@@ -85,5 +128,6 @@ export default class ObservationsEditor extends LitElement { interface IObservationSet { name: string - data: IVariableData[] + data: IObservation[] + variables: string[] } diff --git a/src/html/component/observations-editor/observations-import/observations-import.html b/src/html/component/observations-editor/observations-import/observations-import.html new file mode 100644 index 0000000..e28658d --- /dev/null +++ b/src/html/component/observations-editor/observations-import/observations-import.html @@ -0,0 +1,11 @@ + + + + + + Observations import + + + + + \ No newline at end of file diff --git a/src/html/component/observations-editor/observations-import/observations-import.less b/src/html/component/observations-editor/observations-import/observations-import.less new file mode 100644 index 0000000..6dc0cf3 --- /dev/null +++ b/src/html/component/observations-editor/observations-import/observations-import.less @@ -0,0 +1,89 @@ +@import '/src/uikit-theme'; + +#import-wrapper { + height: 100%; + width: 100%; +} + +#table-wrapper { + width: 100%; + height: 100%; + overflow-x: auto; +} + +h1 { + font: 2em 'Roboto', sans-serif; + margin-bottom: 40px; +} + +.sk-cube-grid { + width: 40px; + height: 40px; + margin: 100px auto; +} + +.sk-cube-grid .sk-cube { + width: 33%; + height: 33%; + background-color: #333; + float: left; + -webkit-animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out; + animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out; +} +.sk-cube-grid .sk-cube1 { + -webkit-animation-delay: 0.2s; + animation-delay: 0.2s; } +.sk-cube-grid .sk-cube2 { + -webkit-animation-delay: 0.3s; + animation-delay: 0.3s; } +.sk-cube-grid .sk-cube3 { + -webkit-animation-delay: 0.4s; + animation-delay: 0.4s; } +.sk-cube-grid .sk-cube4 { + -webkit-animation-delay: 0.1s; + animation-delay: 0.1s; } +.sk-cube-grid .sk-cube5 { + -webkit-animation-delay: 0.2s; + animation-delay: 0.2s; } +.sk-cube-grid .sk-cube6 { + -webkit-animation-delay: 0.3s; + animation-delay: 0.3s; } +.sk-cube-grid .sk-cube7 { + -webkit-animation-delay: 0s; + animation-delay: 0s; } +.sk-cube-grid .sk-cube8 { + -webkit-animation-delay: 0.1s; + animation-delay: 0.1s; } +.sk-cube-grid .sk-cube9 { + -webkit-animation-delay: 0.2s; + animation-delay: 0.2s; } + +@-webkit-keyframes sk-cubeGridScaleDelay { + 0%, 70%, 100% { + -webkit-transform: scale3D(1, 1, 1); + transform: scale3D(1, 1, 1); + } 35% { + -webkit-transform: scale3D(0, 0, 1); + transform: scale3D(0, 0, 1); + } +} + +@keyframes sk-cubeGridScaleDelay { + 0%, 70%, 100% { + -webkit-transform: scale3D(1, 1, 1); + transform: scale3D(1, 1, 1); + } 35% { + -webkit-transform: scale3D(0, 0, 1); + transform: scale3D(0, 0, 1); + } +} +@keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} diff --git a/src/html/component/observations-editor/observations-import/observations-import.ts b/src/html/component/observations-editor/observations-import/observations-import.ts new file mode 100644 index 0000000..01b64cb --- /dev/null +++ b/src/html/component/observations-editor/observations-import/observations-import.ts @@ -0,0 +1,141 @@ +import { html, css, unsafeCSS, LitElement, type TemplateResult } from 'lit' +import { when } from 'lit/directives/when.js' +import { customElement, state } from 'lit/decorators.js' +import style_less from './observations-import.less?inline' +import { emit, type Event as TauriEvent, once } from '@tauri-apps/api/event' +import { appWindow } from '@tauri-apps/api/window' +import { type IObservation } from '../../../util/data-interfaces' +import style_tab from 'tabulator-tables/dist/css/tabulator_simple.min.css?inline' +import { + AjaxModule, + type ColumnDefinition, + EditModule, + FilterModule, FormatModule, InteractionModule, + PageModule, + SelectRowModule, + SortModule, + Tabulator +} from 'tabulator-tables' + +@customElement('observations-import') +export default class ObservationsImport extends LitElement { + static styles = [css`${unsafeCSS(style_less)}`, css`${unsafeCSS(style_tab)}`] + @state() data: IObservation[] = [] + @state() variables: string[] = [] + @state() loaded = false + table = document.createElement('div') + + tabulator: Tabulator | undefined + + constructor () { + super() + Tabulator.registerModule(SortModule) + Tabulator.registerModule(EditModule) + Tabulator.registerModule(PageModule) + Tabulator.registerModule(FilterModule) + Tabulator.registerModule(SelectRowModule) + Tabulator.registerModule(FormatModule) + Tabulator.registerModule(InteractionModule) + Tabulator.registerModule(AjaxModule) + this.table.id = 'table-wrapper' + } + + async firstUpdated (): Promise { + await once('observations_import_update', (event: TauriEvent<{ + data: IObservation[] + variables: string[] + }>) => { + this.data = event.payload.data + this.variables = event.payload.variables + void this.init() + this.loaded = true + }) + await emit('loaded', {}) + } + + createColumns (): ColumnDefinition[] { + const dataCell = (field: string): ColumnDefinition => { + return { + title: field, + field, + editor: 'textarea', + sorter: 'number', + headerFilter: 'tickCross', + hozAlign: 'center', + headerFilterParams: { tristate: true } + } + } + const columns: ColumnDefinition[] = [ + { + title: '', + formatter: 'rowSelection', + titleFormatter: 'rowSelection', + headerSort: false + }, + { + title: 'Name', + field: 'name', + width: 100, + sorter: 'string', + headerFilter: 'input' + } + ] + this.variables.forEach(v => { + columns.push(dataCell(v)) + }) + return columns + } + + private async init (): Promise { + if (this.table !== undefined) { + this.tabulator = new Tabulator(this.table, { + columns: this.createColumns(), + data: this.data, + layout: 'fitDataTable', + responsiveLayout: false, + pagination: true, + renderVerticalBuffer: 300, + sortMode: 'local', + initialSort: [{ column: 'name', dir: 'asc' }], + headerSort: true, + index: 'id', + paginationSize: 20, + selectable: 'highlight' + }) + } + } + + private async handleSubmit (event: Event): Promise { + event.preventDefault() + await emit('observations_import_dialog', this.tabulator?.getSelectedData()) + await appWindow.close() + } + + render (): TemplateResult { + return html`${when(this.loaded, + () => html` +
+

Select rows to be imported

+ ${this.table} + +
+ `, + () => html` + ${this.table} +

Loading data...

+
+
+
+
+
+
+
+
+
+
+
+ `)}` + } +} diff --git a/src/html/component/observations-editor/observations-set/observations-set.ts b/src/html/component/observations-editor/observations-set/observations-set.ts index ec49cc7..2818435 100644 --- a/src/html/component/observations-editor/observations-set/observations-set.ts +++ b/src/html/component/observations-editor/observations-set/observations-set.ts @@ -1,5 +1,5 @@ import { html, css, unsafeCSS, LitElement, type TemplateResult, type PropertyValues } from 'lit' -import { customElement, query, property, state } from 'lit/decorators.js' +import { customElement, query, property } from 'lit/decorators.js' import style_less from './observations-set.less?inline' import style_tab from 'tabulator-tables/dist/css/tabulator_simple.min.css?inline' import { @@ -13,32 +13,17 @@ import { type ColumnDefinition, type CellComponent, InteractionModule } from 'tabulator-tables' -import { type IVariableData } from '../../../util/data-interfaces' +import { type IObservation } from '../../../util/data-interfaces' import { appWindow, WebviewWindow } from '@tauri-apps/api/window' import { type Event as TauriEvent } from '@tauri-apps/api/helpers/event' @customElement('observations-set') export default class ObservationsSet extends LitElement { static styles = [css`${unsafeCSS(style_less)}`, css`${unsafeCSS(style_tab)}`] - @property() data: IVariableData[] = [] + @property() data: IObservation[] = [] + @property() variables: string[] = [] @query('#table-wrapper') table: HTMLElement | undefined tabulator: Tabulator | undefined - @state() dummy: IDummyObservation[] = Array(100001).fill(0).map((_, index) => { - return { - id: 'var' + String(index).padStart(5, '0'), - name: 'var' + String(index).padStart(5, '0'), - var0: Math.round(Math.random()), - var1: Math.round(Math.random()), - var2: Math.round(Math.random()), - var3: Math.round(Math.random()), - var4: Math.round(Math.random()), - var5: Math.round(Math.random()), - var6: Math.round(Math.random()), - var7: Math.round(Math.random()), - var8: Math.round(Math.random()), - var9: Math.round(Math.random()) - } - }) dialogs: Record = {} @@ -59,7 +44,7 @@ export default class ObservationsSet extends LitElement { this.tabulator?.redraw(true) } - private async init(): Promise { + private async init (): Promise { const dataCell = (field: string): ColumnDefinition => { return { title: field, @@ -86,9 +71,9 @@ export default class ObservationsSet extends LitElement { headerFilter: 'input' } ] - for (let i = 0; i < 10; i++) { - columns.push(dataCell('var' + i)) - } + this.variables.forEach(v => { + columns.push(dataCell(v)) + }) columns.push({ title: '', formatter: (_cell, _params, _callback): string => { @@ -99,13 +84,13 @@ export default class ObservationsSet extends LitElement { hozAlign: 'center', cellClick: (_e: UIEvent, _cell: CellComponent) => { console.log('test', _e, _cell.getData()) - void this.editObservation(_cell.getData() as IDummyObservation) + void this.editObservation(_cell.getData() as IObservation) } }) if (this.table !== undefined) { this.tabulator = new Tabulator(this.table, { columns, - data: this.dummy, + data: this.data, layout: 'fitDataTable', responsiveLayout: false, pagination: true, @@ -118,10 +103,11 @@ export default class ObservationsSet extends LitElement { selectable: 'highlight' } ) + this.tabulator.redraw(true) } } - private async editObservation (data: IDummyObservation): Promise { + private async editObservation (data: IObservation): Promise { const pos = await appWindow.outerPosition() const size = await appWindow.outerSize() if (this.dialogs[data.id] !== undefined) { @@ -146,9 +132,9 @@ export default class ObservationsSet extends LitElement { ...data }) }) - void renameDialog.once('edit_observation_dialog', (event: TauriEvent<{ id: string, data: IDummyObservation }>) => { + void renameDialog.once('edit_observation_dialog', (event: TauriEvent<{ id: string, data: IObservation }>) => { this.dialogs[data.id] = undefined - const index = this.dummy.findIndex(observation => observation.id === data.id) + const index = this.data.findIndex(observation => observation.id === data.id) if (index === -1) return void this.tabulator?.updateRow(event.payload.id, event.payload.data) console.log(event.payload) @@ -164,18 +150,3 @@ export default class ObservationsSet extends LitElement { ` } } - -export interface IDummyObservation { - id: string - name: string - var0: number - var1: number - var2: number - var3: number - var4: number - var5: number - var6: number - var7: number - var8: number - var9: number -} diff --git a/src/html/util/data-interfaces.ts b/src/html/util/data-interfaces.ts index 330c083..2cf7a16 100644 --- a/src/html/util/data-interfaces.ts +++ b/src/html/util/data-interfaces.ts @@ -47,3 +47,9 @@ export interface IFunctionData { function: string variables: IRegulationData[] } + +export interface IObservation { + id: string + name: string + [key: string]: string | number +} From d64ddef62c7f78f473776ef6fcae6ece73b17064 Mon Sep 17 00:00:00 2001 From: Petr Ivicic Date: Fri, 8 Mar 2024 14:32:43 +0100 Subject: [PATCH 07/13] removed dead table in observations --- .../observations-editor/observations-editor.ts | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/html/component/observations-editor/observations-editor.ts b/src/html/component/observations-editor/observations-editor.ts index 62efbe0..90a13db 100644 --- a/src/html/component/observations-editor/observations-editor.ts +++ b/src/html/component/observations-editor/observations-editor.ts @@ -7,7 +7,7 @@ import { map } from 'lit/directives/map.js' import { dialog } from '@tauri-apps/api' import { appWindow, WebviewWindow } from '@tauri-apps/api/window' import { type Event as TauriEvent } from '@tauri-apps/api/helpers/event' -import { dummyData } from '../../util/dummy-data' +import { basename } from '@tauri-apps/api/path' @customElement('observations-editor') export default class ObservationsEditor extends LitElement { @@ -26,15 +26,6 @@ export default class ObservationsEditor extends LitElement { return ret }) - constructor () { - super() - this.sets = [{ - name: 'TEST', - data: this.getDummy(), - variables: dummyData.variables.map(v => v.name) - }] - } - private async import (): Promise { const handle = await dialog.open({ title: 'Import observation set...', @@ -61,8 +52,8 @@ export default class ObservationsEditor extends LitElement { } else { fileName = handle } - - void this.importObservations(fileName, this.getDummy(), this.contentData.variables.map(v => v.name)) + const name = await basename(fileName) + void this.importObservations(name, this.getDummy(), this.contentData.variables.map(v => v.name)) } private async importObservations (name: string, data: IObservation[], variables: string[]): Promise { From 2c067784ea646f82ec4b9e3ce2e99f6c1deb96bd Mon Sep 17 00:00:00 2001 From: Petr Ivicic Date: Fri, 8 Mar 2024 14:33:17 +0100 Subject: [PATCH 08/13] changed button verb in edit observation --- .../observations-editor/edit-observation/edit-observation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/html/component/observations-editor/edit-observation/edit-observation.ts b/src/html/component/observations-editor/edit-observation/edit-observation.ts index dec58d3..fa6f049 100644 --- a/src/html/component/observations-editor/edit-observation/edit-observation.ts +++ b/src/html/component/observations-editor/edit-observation/edit-observation.ts @@ -58,7 +58,7 @@ export default class EditObservation extends LitElement {
- + ` } From 7d9b4943f675153eb30110dae2c40c136310f053 Mon Sep 17 00:00:00 2001 From: Petr Ivicic Date: Fri, 8 Mar 2024 14:34:20 +0100 Subject: [PATCH 09/13] add path to tauri allow list --- src-tauri/tauri.conf.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index c4117e0..6379362 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -25,6 +25,9 @@ "close": true, "setSize": true, "setFocus": true + }, + "path": { + "all": true } }, "bundle": { From 479227b1978b2ec46310c83694ed4f5e124323cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Ivi=C4=8Di=C4=8D?= <492712@mail.muni.cz> Date: Wed, 13 Mar 2024 21:28:31 +0100 Subject: [PATCH 10/13] cleanup --- .../observations-editor.ts | 10 --- .../observations-import.ts | 58 ++--------------- .../observations-set/observations-set.ts | 62 +++---------------- .../observations-editor/tabulator-utility.ts | 61 ++++++++++++++++++ 4 files changed, 74 insertions(+), 117 deletions(-) create mode 100644 src/html/component/observations-editor/tabulator-utility.ts diff --git a/src/html/component/observations-editor/observations-editor.ts b/src/html/component/observations-editor/observations-editor.ts index 62efbe0..0aa58db 100644 --- a/src/html/component/observations-editor/observations-editor.ts +++ b/src/html/component/observations-editor/observations-editor.ts @@ -7,7 +7,6 @@ import { map } from 'lit/directives/map.js' import { dialog } from '@tauri-apps/api' import { appWindow, WebviewWindow } from '@tauri-apps/api/window' import { type Event as TauriEvent } from '@tauri-apps/api/helpers/event' -import { dummyData } from '../../util/dummy-data' @customElement('observations-editor') export default class ObservationsEditor extends LitElement { @@ -26,15 +25,6 @@ export default class ObservationsEditor extends LitElement { return ret }) - constructor () { - super() - this.sets = [{ - name: 'TEST', - data: this.getDummy(), - variables: dummyData.variables.map(v => v.name) - }] - } - private async import (): Promise { const handle = await dialog.open({ title: 'Import observation set...', diff --git a/src/html/component/observations-editor/observations-import/observations-import.ts b/src/html/component/observations-editor/observations-import/observations-import.ts index 01b64cb..3868d40 100644 --- a/src/html/component/observations-editor/observations-import/observations-import.ts +++ b/src/html/component/observations-editor/observations-import/observations-import.ts @@ -6,16 +6,8 @@ import { emit, type Event as TauriEvent, once } from '@tauri-apps/api/event' import { appWindow } from '@tauri-apps/api/window' import { type IObservation } from '../../../util/data-interfaces' import style_tab from 'tabulator-tables/dist/css/tabulator_simple.min.css?inline' -import { - AjaxModule, - type ColumnDefinition, - EditModule, - FilterModule, FormatModule, InteractionModule, - PageModule, - SelectRowModule, - SortModule, - Tabulator -} from 'tabulator-tables' +import { type ColumnDefinition, Tabulator } from 'tabulator-tables' +import { checkboxColumn, dataCell, loadTabulatorPlugins, nameColumn, tabulatorOptions } from '../tabulator-utility' @customElement('observations-import') export default class ObservationsImport extends LitElement { @@ -29,14 +21,7 @@ export default class ObservationsImport extends LitElement { constructor () { super() - Tabulator.registerModule(SortModule) - Tabulator.registerModule(EditModule) - Tabulator.registerModule(PageModule) - Tabulator.registerModule(FilterModule) - Tabulator.registerModule(SelectRowModule) - Tabulator.registerModule(FormatModule) - Tabulator.registerModule(InteractionModule) - Tabulator.registerModule(AjaxModule) + loadTabulatorPlugins() this.table.id = 'table-wrapper' } @@ -54,31 +39,9 @@ export default class ObservationsImport extends LitElement { } createColumns (): ColumnDefinition[] { - const dataCell = (field: string): ColumnDefinition => { - return { - title: field, - field, - editor: 'textarea', - sorter: 'number', - headerFilter: 'tickCross', - hozAlign: 'center', - headerFilterParams: { tristate: true } - } - } const columns: ColumnDefinition[] = [ - { - title: '', - formatter: 'rowSelection', - titleFormatter: 'rowSelection', - headerSort: false - }, - { - title: 'Name', - field: 'name', - width: 100, - sorter: 'string', - headerFilter: 'input' - } + checkboxColumn, + nameColumn ] this.variables.forEach(v => { columns.push(dataCell(v)) @@ -91,16 +54,7 @@ export default class ObservationsImport extends LitElement { this.tabulator = new Tabulator(this.table, { columns: this.createColumns(), data: this.data, - layout: 'fitDataTable', - responsiveLayout: false, - pagination: true, - renderVerticalBuffer: 300, - sortMode: 'local', - initialSort: [{ column: 'name', dir: 'asc' }], - headerSort: true, - index: 'id', - paginationSize: 20, - selectable: 'highlight' + ...tabulatorOptions }) } } diff --git a/src/html/component/observations-editor/observations-set/observations-set.ts b/src/html/component/observations-editor/observations-set/observations-set.ts index 2818435..d61f985 100644 --- a/src/html/component/observations-editor/observations-set/observations-set.ts +++ b/src/html/component/observations-editor/observations-set/observations-set.ts @@ -2,20 +2,11 @@ import { html, css, unsafeCSS, LitElement, type TemplateResult, type PropertyVal import { customElement, query, property } from 'lit/decorators.js' import style_less from './observations-set.less?inline' import style_tab from 'tabulator-tables/dist/css/tabulator_simple.min.css?inline' -import { - Tabulator, - SortModule, - EditModule, - PageModule, - FilterModule, - SelectRowModule, - FormatModule, - type ColumnDefinition, type CellComponent, InteractionModule -} from 'tabulator-tables' - +import { Tabulator, type ColumnDefinition, type CellComponent } from 'tabulator-tables' import { type IObservation } from '../../../util/data-interfaces' import { appWindow, WebviewWindow } from '@tauri-apps/api/window' import { type Event as TauriEvent } from '@tauri-apps/api/helpers/event' +import { checkboxColumn, dataCell, loadTabulatorPlugins, nameColumn, tabulatorOptions } from '../tabulator-utility' @customElement('observations-set') export default class ObservationsSet extends LitElement { @@ -29,13 +20,7 @@ export default class ObservationsSet extends LitElement { constructor () { super() - Tabulator.registerModule(SortModule) - Tabulator.registerModule(EditModule) - Tabulator.registerModule(PageModule) - Tabulator.registerModule(FilterModule) - Tabulator.registerModule(SelectRowModule) - Tabulator.registerModule(FormatModule) - Tabulator.registerModule(InteractionModule) + loadTabulatorPlugins() } protected async firstUpdated (_changedProperties: PropertyValues): Promise { @@ -45,31 +30,9 @@ export default class ObservationsSet extends LitElement { } private async init (): Promise { - const dataCell = (field: string): ColumnDefinition => { - return { - title: field, - field, - editor: 'textarea', - sorter: 'number', - headerFilter: 'tickCross', - hozAlign: 'center', - headerFilterParams: { tristate: true } - } - } const columns: ColumnDefinition[] = [ - { - title: '', - formatter: 'rowSelection', - titleFormatter: 'rowSelection', - headerSort: false - }, - { - title: 'Name', - field: 'name', - width: 100, - sorter: 'string', - headerFilter: 'input' - } + checkboxColumn, + nameColumn ] this.variables.forEach(v => { columns.push(dataCell(v)) @@ -83,7 +46,6 @@ export default class ObservationsSet extends LitElement { headerSort: false, hozAlign: 'center', cellClick: (_e: UIEvent, _cell: CellComponent) => { - console.log('test', _e, _cell.getData()) void this.editObservation(_cell.getData() as IObservation) } }) @@ -91,18 +53,8 @@ export default class ObservationsSet extends LitElement { this.tabulator = new Tabulator(this.table, { columns, data: this.data, - layout: 'fitDataTable', - responsiveLayout: false, - pagination: true, - renderVerticalBuffer: 300, - sortMode: 'local', - initialSort: [{ column: 'name', dir: 'asc' }], - headerSort: true, - index: 'id', - paginationSize: 20, - selectable: 'highlight' - } - ) + ...tabulatorOptions + }) this.tabulator.redraw(true) } } diff --git a/src/html/component/observations-editor/tabulator-utility.ts b/src/html/component/observations-editor/tabulator-utility.ts new file mode 100644 index 0000000..a3da257 --- /dev/null +++ b/src/html/component/observations-editor/tabulator-utility.ts @@ -0,0 +1,61 @@ +import { + AjaxModule, + type ColumnDefinition, + EditModule, + FilterModule, FormatModule, InteractionModule, + type Options, + PageModule, SelectRowModule, + SortModule, + Tabulator +} from 'tabulator-tables' + +export const dataCell = (field: string): ColumnDefinition => { + return { + title: field, + field, + editor: 'textarea', + sorter: 'number', + headerFilter: 'tickCross', + hozAlign: 'center', + headerFilterParams: { tristate: true } + } +} + +export const checkboxColumn: ColumnDefinition = { + title: '', + formatter: 'rowSelection', + titleFormatter: 'rowSelection', + headerSort: false +} + +export const nameColumn: ColumnDefinition = { + title: 'Name', + field: 'name', + width: 100, + sorter: 'string', + headerFilter: 'input' +} + +export const tabulatorOptions: Options = { + layout: 'fitDataTable', + responsiveLayout: false, + pagination: true, + renderVerticalBuffer: 300, + sortMode: 'local', + initialSort: [{ column: 'name', dir: 'asc' }], + headerSort: true, + index: 'id', + paginationSize: 20, + selectable: 'highlight' +} + +export const loadTabulatorPlugins = (): void => { + Tabulator.registerModule(SortModule) + Tabulator.registerModule(EditModule) + Tabulator.registerModule(PageModule) + Tabulator.registerModule(FilterModule) + Tabulator.registerModule(SelectRowModule) + Tabulator.registerModule(FormatModule) + Tabulator.registerModule(InteractionModule) + Tabulator.registerModule(AjaxModule) +} From cbbdb6e5ee0cf0cce2dcc5f55cd866217facf978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Ivi=C4=8Di=C4=8D?= <492712@mail.muni.cz> Date: Wed, 13 Mar 2024 21:35:20 +0100 Subject: [PATCH 11/13] credit css --- .../observations-import/observations-import.less | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/html/component/observations-editor/observations-import/observations-import.less b/src/html/component/observations-editor/observations-import/observations-import.less index 6dc0cf3..fe9ca90 100644 --- a/src/html/component/observations-editor/observations-import/observations-import.less +++ b/src/html/component/observations-editor/observations-import/observations-import.less @@ -16,6 +16,9 @@ h1 { margin-bottom: 40px; } +/* Spinner taken from https://github.com/tobiasahlin/SpinKit */ +/* Licensed under the MIT License (http://opensource.org/licenses/MIT) */ + .sk-cube-grid { width: 40px; height: 40px; From ffaf75d5418d73a9ab51cad5e0076c7315437c40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Ivi=C4=8Di=C4=8D?= <492712@mail.muni.cz> Date: Wed, 13 Mar 2024 21:57:59 +0100 Subject: [PATCH 12/13] fix eslint errors --- .../functions-editor/editor-tile/function-tile.ts | 2 +- .../functions-editor/editor-tile/variable-tile.ts | 2 +- src/html/component/functions-editor/functions-editor.ts | 2 +- .../edit-observation/edit-observation.ts | 2 +- .../component/regulations-editor/regulations-editor.ts | 7 ++++--- .../regulations-editor/rename-dialog/rename-dialog.ts | 2 +- 6 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/html/component/functions-editor/editor-tile/function-tile.ts b/src/html/component/functions-editor/editor-tile/function-tile.ts index 4f93879..96b772d 100644 --- a/src/html/component/functions-editor/editor-tile/function-tile.ts +++ b/src/html/component/functions-editor/editor-tile/function-tile.ts @@ -13,7 +13,7 @@ import { EditorTile } from './editor-tile' library.add(faTrash, faMagnifyingGlass) @customElement('function-tile') -class FunctionTile extends EditorTile { +export class FunctionTile extends EditorTile { varIndex = 0 constructor () { super() diff --git a/src/html/component/functions-editor/editor-tile/variable-tile.ts b/src/html/component/functions-editor/editor-tile/variable-tile.ts index 77755c5..88bb50d 100644 --- a/src/html/component/functions-editor/editor-tile/variable-tile.ts +++ b/src/html/component/functions-editor/editor-tile/variable-tile.ts @@ -12,7 +12,7 @@ import { EditorTile } from './editor-tile' library.add(faTrash, faMagnifyingGlass) @customElement('variable-tile') -class VariableTile extends EditorTile { +export class VariableTile extends EditorTile { @property() regulations: IRegulationData[] = [] @property() variables: IVariableData[] = [] diff --git a/src/html/component/functions-editor/functions-editor.ts b/src/html/component/functions-editor/functions-editor.ts index 0c24646..7f08d7e 100644 --- a/src/html/component/functions-editor/functions-editor.ts +++ b/src/html/component/functions-editor/functions-editor.ts @@ -11,7 +11,7 @@ import { getNextEssentiality, getNextMonotonicity } from '../../util/utilities' import { dialog } from '@tauri-apps/api' @customElement('functions-editor') -class FunctionsEditor extends LitElement { +export class FunctionsEditor extends LitElement { static styles = css`${unsafeCSS(style_less)}` @property() contentData: ContentData = ContentData.create() @state() functions: IFunctionData[] = [] diff --git a/src/html/component/observations-editor/edit-observation/edit-observation.ts b/src/html/component/observations-editor/edit-observation/edit-observation.ts index fa6f049..048063d 100644 --- a/src/html/component/observations-editor/edit-observation/edit-observation.ts +++ b/src/html/component/observations-editor/edit-observation/edit-observation.ts @@ -51,7 +51,7 @@ export default class EditObservation extends LitElement {
- +
` })} diff --git a/src/html/component/regulations-editor/regulations-editor.ts b/src/html/component/regulations-editor/regulations-editor.ts index 3abe967..6f6ba4a 100644 --- a/src/html/component/regulations-editor/regulations-editor.ts +++ b/src/html/component/regulations-editor/regulations-editor.ts @@ -12,7 +12,7 @@ import { type Event as TauriEvent } from '@tauri-apps/api/event' import { ContentData, ElementType, type IRegulationData, type IVariableData } from '../../util/data-interfaces' @customElement('regulations-editor') -export default class RegulationsEditor extends LitElement { +export class RegulationsEditor extends LitElement { static styles = css`${unsafeCSS(style_less)}` dialogs: Record = {} editorElement @@ -101,14 +101,15 @@ export default class RegulationsEditor extends LitElement { } private addEdge (event: Event): void { - this.cy?.nodes().deselect() + if (this.cy === undefined) return + this.cy.nodes().deselect() this.toggleMenu(ElementType.NONE) const variableId = (event as CustomEvent).detail.id // start attribute wrongly typed - added weird typecast to avoid tslint error this.edgeHandles?.start((this.cy?.$id(variableId) as unknown as string)) // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error + // @ts-expect-error renderer exists but its missing from the *.d.ts file this.cy.renderer().hoverData.capture = true } diff --git a/src/html/component/regulations-editor/rename-dialog/rename-dialog.ts b/src/html/component/regulations-editor/rename-dialog/rename-dialog.ts index fb8d99d..b49155d 100644 --- a/src/html/component/regulations-editor/rename-dialog/rename-dialog.ts +++ b/src/html/component/regulations-editor/rename-dialog/rename-dialog.ts @@ -5,7 +5,7 @@ import { emit, type Event as TauriEvent, once } from '@tauri-apps/api/event' import { appWindow, LogicalSize } from '@tauri-apps/api/window' @customElement('rename-dialog') -class RenameDialog extends LitElement { +export class RenameDialog extends LitElement { static styles = css`${unsafeCSS(style_less)}` @query('#node-name') nameField: HTMLInputElement | undefined @query('#node-id') variableIdField: HTMLInputElement | undefined From c936ac2e17ffc78549079732af799c19571157e5 Mon Sep 17 00:00:00 2001 From: Samuel Pastva Date: Fri, 15 Mar 2024 14:03:20 +0100 Subject: [PATCH 13/13] Extend allow list. --- src-tauri/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 9c3b004..d1b57cd 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -19,7 +19,7 @@ biodivine-lib-bdd = ">=0.5.6, <1.0.0" biodivine-lib-param-bn = ">=0.5.0, <1.0.0" lazy_static = "1.4.0" regex = "1.10.2" -tauri = { version = "1.4", features = [ "window-set-focus", "window-set-size", "window-close", "window-create", "dialog-all", "shell-open"] } +tauri = { version = "1.4", features = [ "window-set-focus", "window-set-size", "window-close", "window-create", "dialog-all", "shell-open", "path-all"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0"