@fmsim/layout-view 2.0.0-beta.9 → 2.0.0-beta.92

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/dist-client/board-provider.js +2 -1
  2. package/dist-client/board-provider.js.map +1 -1
  3. package/dist-client/data-grist/animation-map-editor.js +63 -18
  4. package/dist-client/data-grist/animation-map-editor.js.map +1 -1
  5. package/dist-client/data-grist/ox-input-animation-config.d.ts +1 -0
  6. package/dist-client/data-grist/ox-input-animation-config.js +42 -37
  7. package/dist-client/data-grist/ox-input-animation-config.js.map +1 -1
  8. package/dist-client/data-grist/ox-input-animation-map.d.ts +12 -5
  9. package/dist-client/data-grist/ox-input-animation-map.js +76 -28
  10. package/dist-client/data-grist/ox-input-animation-map.js.map +1 -1
  11. package/dist-client/pages/board-modeller-page.d.ts +1 -0
  12. package/dist-client/pages/board-modeller-page.js +9 -0
  13. package/dist-client/pages/board-modeller-page.js.map +1 -1
  14. package/dist-client/pages/board-viewer-page.d.ts +1 -0
  15. package/dist-client/pages/board-viewer-page.js +23 -8
  16. package/dist-client/pages/board-viewer-page.js.map +1 -1
  17. package/dist-client/pages/theme/theme-list-page.js +1 -4
  18. package/dist-client/pages/theme/theme-list-page.js.map +1 -1
  19. package/dist-client/tsconfig.tsbuildinfo +1 -1
  20. package/dist-server/tsconfig.tsbuildinfo +1 -1
  21. package/package.json +5 -5
  22. package/translations/en.json +14 -1
  23. package/translations/ja.json +14 -1
  24. package/translations/ko.json +14 -1
  25. package/translations/ms.json +14 -1
  26. package/translations/zh.json +14 -1
  27. package/dist-client/pages/theme/theme-editors.d.ts +0 -5
  28. package/dist-client/pages/theme/theme-editors.js +0 -61
  29. package/dist-client/pages/theme/theme-editors.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ox-input-animation-map.js","sourceRoot":"","sources":["../../client/data-grist/ox-input-animation-map.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Animation Map 에디터\n *\n * key-value 맵에서 value가 애니메이션 설정 객체인 경우를 위한 편집기.\n * 각 행은 key 입력 + ox-input-animation-config 폼으로 구성된다.\n *\n * value 구조:\n * {\n * \"1001\": { type: \"rotation\", duration: 1000, delay: 0, theta: 360, repeat: true, delta: \"linear\", ease: \"in\" },\n * \"1007\": { type: \"vibration\", duration: 500, ... },\n * \"default\": \"\"\n * }\n */\n\nimport '@material/web/icon/icon.js'\nimport './ox-input-animation-config.js'\n\nimport { css, html, LitElement, nothing } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { keyed } from 'lit/directives/keyed.js'\n\ntype AnimationConfig = {\n type?: string\n delay?: number\n duration?: number\n interval?: number\n theta?: number\n scale?: number\n x?: number\n y?: number\n startAlpha?: number\n endAlpha?: number\n repeat?: boolean\n autoplay?: boolean\n delta?: string\n ease?: string\n}\n\ntype AnimationMap = { default?: any; [key: string]: AnimationConfig | any }\n\n@customElement('ox-input-animation-map')\nexport class OxInputAnimationMap extends LitElement {\n static styles = css`\n :host {\n display: flex;\n flex-direction: column;\n gap: 4px;\n font-size: var(--fontsize-default, 12px);\n\n --md-icon-size: 16px;\n }\n\n .entry {\n display: flex;\n flex-direction: row;\n align-items: flex-start;\n gap: 6px;\n padding: 6px 8px;\n border: 1px solid var(--md-sys-color-outline-variant, #ddd);\n border-radius: 4px;\n background: var(--md-sys-color-surface-container, #f8f8f8);\n }\n\n .entry-key {\n flex: 0 0 80px;\n padding-top: 3px;\n }\n\n .entry-key input {\n width: 100%;\n box-sizing: border-box;\n border: 0;\n border-bottom: 1px solid transparent;\n padding: 3px 4px;\n font: var(--input-font, 12px sans-serif);\n font-weight: 600;\n color: var(--md-sys-color-on-primary-container, #333);\n background: transparent;\n }\n\n .entry-key input:focus {\n outline: none;\n border-bottom-color: var(--md-sys-color-primary, #1976d2);\n }\n\n .entry-value {\n flex: 1;\n min-width: 0;\n }\n\n .entry-action {\n flex: 0 0 auto;\n padding-top: 2px;\n }\n\n button {\n border: none;\n background: transparent;\n cursor: pointer;\n padding: 2px;\n color: var(--md-sys-color-on-surface-variant, #666);\n line-height: 0;\n }\n\n button:hover {\n color: var(--md-sys-color-primary, #1976d2);\n }\n\n .add-entry {\n opacity: 0.6;\n }\n\n .add-entry:focus-within {\n opacity: 1;\n }\n `\n\n @property({ type: Object }) value: AnimationMap = {}\n\n render() {\n const entries = this._toArray(this.value)\n\n return html`\n ${entries.map(\n (item, idx) => html`\n <div class=\"entry\" data-record data-index=${idx}>\n <div class=\"entry-key\">\n <input type=\"text\" data-key .value=${item.key} placeholder=\"key\" />\n </div>\n <div class=\"entry-value\">\n <ox-input-animation-config\n .value=${item.value}\n @change=${(e: CustomEvent) => this._onConfigChange(e, idx)}\n ></ox-input-animation-config>\n </div>\n <div class=\"entry-action\">\n <button @click=${() => this._delete(idx)} tabindex=\"-1\">\n <md-icon>remove</md-icon>\n </button>\n </div>\n </div>\n `\n )}\n ${keyed(\n Date.now(),\n html`\n <div class=\"entry add-entry\" data-record-new>\n <div class=\"entry-key\">\n <input type=\"text\" data-key value=\"\" placeholder=\"new key\" @change=${this._onNewKeyChange} />\n </div>\n <div class=\"entry-value\">\n <ox-input-animation-config .value=${{}}></ox-input-animation-config>\n </div>\n <div class=\"entry-action\">\n <button @click=${() => this._add()} tabindex=\"-1\">\n <md-icon>add</md-icon>\n </button>\n </div>\n </div>\n `\n )}\n `\n }\n\n private _onConfigChange(e: CustomEvent, idx: number) {\n e.stopPropagation()\n\n const entries = this._toArray(this.value)\n const key = entries[idx]?.key\n if (!key) return\n\n this.value = { ...this.value, [key]: e.detail }\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))\n }\n\n private _onNewKeyChange = (e: Event) => {\n e.stopPropagation()\n const input = e.target as HTMLInputElement\n if (input.value) {\n this._add()\n }\n }\n\n firstUpdated() {\n this.renderRoot.addEventListener('change', (e: Event) => {\n const target = e.target as HTMLElement\n const entry = target.closest('[data-record]')\n if (!entry) return\n\n // key 변경 시 rebuild\n if (target.hasAttribute('data-key')) {\n e.stopPropagation()\n this._build()\n }\n })\n }\n\n private _build() {\n const records = this.renderRoot.querySelectorAll('[data-record]')\n const newMap: AnimationMap = {}\n\n records.forEach(record => {\n const key = (record.querySelector('[data-key]') as HTMLInputElement)?.value\n if (!key) return\n\n const configEl = record.querySelector('ox-input-animation-config') as any\n newMap[key] = configEl?.value || {}\n })\n\n if (this.value?.default !== undefined) {\n newMap.default = this.value.default\n }\n\n this.value = newMap\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))\n }\n\n private _add() {\n const newEntry = this.renderRoot.querySelector('[data-record-new]')\n if (!newEntry) return\n\n const key = (newEntry.querySelector('[data-key]') as HTMLInputElement)?.value\n if (!key) return\n\n const configEl = newEntry.querySelector('ox-input-animation-config') as any\n const config = configEl?.value || {}\n\n this.value = { ...this.value, [key]: config }\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))\n }\n\n private _delete(idx: number) {\n const entries = this._toArray(this.value)\n const key = entries[idx]?.key\n if (!key) return\n\n const newMap = { ...this.value }\n delete newMap[key]\n this.value = newMap\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))\n }\n\n private _toArray(map: AnimationMap): { key: string; value: AnimationConfig }[] {\n const arr: { key: string; value: AnimationConfig }[] = []\n for (const key in map) {\n if (key === 'default') continue\n const val = map[key]\n arr.push({\n key,\n value: typeof val === 'object' ? val : {}\n })\n }\n return arr\n }\n}\n"]}
1
+ {"version":3,"file":"ox-input-animation-map.js","sourceRoot":"","sources":["../../client/data-grist/ox-input-animation-map.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Animation Map 에디터\n *\n * key-value 맵에서 value가 애니메이션 설정 객체인 경우를 위한 편집기.\n * 각 행은 key 입력 + ox-input-animation-config 폼으로 구성된다.\n *\n * value 구조 (실제 데이터):\n * {\n * \"CRITICAL\": \"{ animation: { type: 'vibration', duration: 1000, ... }, icon: { ... } }\",\n * \"WARN\": \"{ animation: { type: 'vibration', ... } }\",\n * \"default\": \"\"\n * }\n *\n * 각 entry value는 JSON5 string이며, 내부에 animation 키가 있으면 그 속성만 폼에 표시.\n * 저장 시 animation 외 다른 키(icon 등)는 보존됨.\n */\n\nimport '@material/web/icon/icon.js'\nimport './ox-input-animation-config.js'\n\nimport JSON5 from 'json5'\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { keyed } from 'lit/directives/keyed.js'\n\ntype AnimationConfig = {\n type?: string\n delay?: number\n duration?: number\n interval?: number\n theta?: number\n scale?: number\n x?: number\n y?: number\n startAlpha?: number\n endAlpha?: number\n repeat?: boolean\n autoplay?: boolean\n delta?: string\n ease?: string\n}\n\ntype AnimationMap = { default?: any; [key: string]: AnimationConfig | any }\n\n// 파싱된 entry: 원본 전체 객체와 animation config를 분리 보관\ntype ParsedEntry = {\n key: string\n animation: AnimationConfig\n full: any // 원본 파싱 결과 전체 (icon 등 보존용)\n isNested: boolean // animation 키가 있는 중첩 구조 여부\n}\n\n@customElement('ox-input-animation-map')\nexport class OxInputAnimationMap extends LitElement {\n static styles = css`\n :host {\n display: flex;\n flex-direction: column;\n gap: 4px;\n font-size: var(--fontsize-default, 12px);\n\n --md-icon-size: 16px;\n }\n\n .entry {\n display: flex;\n flex-direction: row;\n align-items: flex-start;\n gap: 6px;\n padding: 6px 8px;\n border: 1px solid var(--md-sys-color-outline-variant, #ddd);\n border-radius: 4px;\n background: var(--md-sys-color-surface-container, #f8f8f8);\n }\n\n .entry-key {\n flex: 0 0 80px;\n padding-top: 3px;\n }\n\n .entry-key input {\n width: 100%;\n box-sizing: border-box;\n border: 0;\n border-bottom: 1px solid transparent;\n padding: 3px 4px;\n font: var(--input-font, 12px sans-serif);\n font-weight: 600;\n color: var(--md-sys-color-on-primary-container, #333);\n background: transparent;\n }\n\n .entry-key input:focus {\n outline: none;\n border-bottom-color: var(--md-sys-color-primary, #1976d2);\n }\n\n .entry-value {\n flex: 1;\n min-width: 0;\n }\n\n .entry-action {\n flex: 0 0 auto;\n padding-top: 2px;\n }\n\n button {\n border: none;\n background: transparent;\n cursor: pointer;\n padding: 2px;\n color: var(--md-sys-color-on-surface-variant, #666);\n line-height: 0;\n }\n\n button:hover {\n color: var(--md-sys-color-primary, #1976d2);\n }\n\n .add-entry {\n opacity: 0.6;\n }\n\n .add-entry:focus-within {\n opacity: 1;\n }\n `\n\n @property({ type: Object })\n set value(v: AnimationMap) {\n const old = this._value\n this._value = this._normalize(v)\n this.requestUpdate('value', old)\n }\n get value(): AnimationMap { return this._value }\n private _value: AnimationMap = {}\n\n // 파싱된 entry 캐시 (원본 구조 보존용)\n private _parsed: ParsedEntry[] = []\n\n render() {\n this._parsed = this._parseEntries(this.value)\n\n return html`\n ${this._parsed.map(\n (item, idx) => html`\n <div class=\"entry\" data-record data-index=${idx}>\n <div class=\"entry-key\">\n <input type=\"text\" data-key .value=${item.key} placeholder=\"key\" />\n </div>\n <div class=\"entry-value\">\n <ox-input-animation-config\n .value=${item.animation}\n @change=${(e: CustomEvent) => this._onConfigChange(e, idx)}\n ></ox-input-animation-config>\n </div>\n <div class=\"entry-action\">\n <button @click=${() => this._delete(idx)} tabindex=\"-1\">\n <md-icon>remove</md-icon>\n </button>\n </div>\n </div>\n `\n )}\n ${keyed(\n Date.now(),\n html`\n <div class=\"entry add-entry\" data-record-new>\n <div class=\"entry-key\">\n <input type=\"text\" data-key value=\"\" placeholder=\"new key\" @change=${this._onNewKeyChange} />\n </div>\n <div class=\"entry-value\">\n <ox-input-animation-config .value=${{}}></ox-input-animation-config>\n </div>\n <div class=\"entry-action\">\n <button @click=${() => this._add()} tabindex=\"-1\">\n <md-icon>add</md-icon>\n </button>\n </div>\n </div>\n `\n )}\n `\n }\n\n private _onConfigChange(e: CustomEvent, idx: number) {\n e.stopPropagation()\n\n const entry = this._parsed[idx]\n if (!entry) return\n\n // 항상 { animation: config } 구조로 저장 (원본에 다른 키가 있으면 보존)\n const newEntryValue = entry.isNested\n ? { ...entry.full, animation: e.detail }\n : { animation: e.detail }\n\n this.value = { ...this.value, [entry.key]: newEntryValue }\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))\n }\n\n private _onNewKeyChange = (e: Event) => {\n e.stopPropagation()\n const input = e.target as HTMLInputElement\n if (input.value) {\n this._add()\n }\n }\n\n firstUpdated() {\n this.renderRoot.addEventListener('change', (e: Event) => {\n const target = e.target as HTMLElement\n const entry = target.closest('[data-record]')\n if (!entry) return\n\n // key 변경 시 rebuild\n if (target.hasAttribute('data-key')) {\n e.stopPropagation()\n this._build()\n }\n })\n }\n\n private _build() {\n const records = this.renderRoot.querySelectorAll('[data-record]')\n const newMap: AnimationMap = {}\n\n records.forEach((record, idx) => {\n const key = (record.querySelector('[data-key]') as HTMLInputElement)?.value\n if (!key) return\n\n const configEl = record.querySelector('ox-input-animation-config') as any\n const animConfig = configEl?.value || {}\n const entry = this._parsed[idx]\n\n newMap[key] = entry?.isNested\n ? { ...entry.full, animation: animConfig }\n : { animation: animConfig }\n })\n\n if (this.value?.default !== undefined) {\n newMap.default = this.value.default\n }\n\n this.value = newMap\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))\n }\n\n private _add() {\n const newEntry = this.renderRoot.querySelector('[data-record-new]')\n if (!newEntry) return\n\n const key = (newEntry.querySelector('[data-key]') as HTMLInputElement)?.value\n if (!key) return\n\n const configEl = newEntry.querySelector('ox-input-animation-config') as any\n const config = configEl?.value || {}\n\n this.value = { ...this.value, [key]: { animation: config } }\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))\n }\n\n private _delete(idx: number) {\n const entry = this._parsed[idx]\n if (!entry) return\n\n const newMap = { ...this.value }\n delete newMap[entry.key]\n this.value = newMap\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))\n }\n\n private _parseEntries(map: AnimationMap): ParsedEntry[] {\n const arr: ParsedEntry[] = []\n for (const key in map) {\n if (key === 'default') continue\n let val = map[key]\n\n // JSON5 string → object 파싱\n if (typeof val === 'string') {\n try { val = JSON5.parse(val) } catch (e) { val = {} }\n }\n\n if (typeof val !== 'object' || val === null) {\n val = {}\n }\n\n // 중첩 구조 { animation: {...}, icon: {...} } 처리\n const isNested = 'animation' in val\n const animation = isNested ? (val.animation || {}) : val\n\n arr.push({ key, animation, full: val, isNested })\n }\n return arr\n }\n\n // 입력 value의 모든 string entry를 object로 정규화 (JSON/JSON5 호환)\n private _normalize(map: AnimationMap): AnimationMap {\n if (!map || typeof map !== 'object') return {}\n const result: AnimationMap = {}\n for (const key in map) {\n const val = map[key]\n if (typeof val === 'string' && val.trim()) {\n try { result[key] = JSON5.parse(val) } catch { result[key] = val }\n } else {\n result[key] = val\n }\n }\n return result\n }\n}\n"]}
@@ -26,6 +26,7 @@ export declare class BoardModellerPage extends BoardModellerPage_base {
26
26
  propertyEditor: any;
27
27
  preparing?: boolean;
28
28
  board: any;
29
+ private _loadTracker?;
29
30
  modeller?: BoardModeller;
30
31
  get context(): {
31
32
  title: string | undefined;
@@ -3,7 +3,9 @@ import './things-scene-components.import';
3
3
  import '@fmsim/board/ox-board-modeller.js';
4
4
  import { css, html } from 'lit';
5
5
  import { customElement, property, query } from 'lit/decorators.js';
6
+ import { BoardModelCache } from '@fmsim/board';
6
7
  import { BoardModeller } from '@fmsim/board/ox-board-modeller.js';
8
+ import { LoadTracker } from '@hatiolab/things-scene';
7
9
  import { OxPropertyEditor } from '@operato/property-editor';
8
10
  import { connect, PageView, store } from '@operato/shell';
9
11
  import { fetchBoardById, updateBoard } from '@fmsim/api';
@@ -61,6 +63,10 @@ let BoardModellerPage = class BoardModellerPage extends connect(store)(PageView)
61
63
  return;
62
64
  }
63
65
  try {
66
+ this.board = null;
67
+ this.model = null;
68
+ this._loadTracker = new LoadTracker();
69
+ this._loadTracker.setPhase('fetch');
64
70
  this.preparing = true;
65
71
  this.updateContext();
66
72
  var { board, themes } = (await fetchBoardById(this.boardId)) || {};
@@ -117,6 +123,7 @@ let BoardModellerPage = class BoardModellerPage extends connect(store)(PageView)
117
123
  : html `
118
124
  <ox-board-modeller
119
125
  .mode=${this.mode}
126
+ .loadTracker=${this._loadTracker}
120
127
  @mode-changed=${e => {
121
128
  this.mode = e.detail.value;
122
129
  }}
@@ -172,6 +179,8 @@ let BoardModellerPage = class BoardModellerPage extends connect(store)(PageView)
172
179
  }
173
180
  async saveBoard() {
174
181
  await this.updateBoard();
182
+ // 저장 후 캐시 무효화 — viewer에서 다음 로드 시 최신 모델 fetch
183
+ await BoardModelCache.remove(this.board.id);
175
184
  }
176
185
  };
177
186
  BoardModellerPage.styles = [
@@ -1 +1 @@
1
- {"version":3,"file":"board-modeller-page.js","sourceRoot":"","sources":["../../client/pages/board-modeller-page.ts"],"names":[],"mappings":"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","sourcesContent":["import './things-scene-components.import'\nimport '@fmsim/board/ox-board-modeller.js'\n\nimport { css, html } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { BoardModeller } from '@fmsim/board/ox-board-modeller.js'\nimport { OxPropertyEditor } from '@operato/property-editor'\nimport { connect, PageView, store } from '@operato/shell'\nimport { fetchBoardById, updateBoard } from '@fmsim/api'\n\nimport { provider } from '../board-provider'\nimport components from './things-scene-components-with-tools.import'\n\nconst NOOP = () => {}\n\n@customElement('board-modeller-page')\nexport class BoardModellerPage extends connect(store)(PageView) {\n constructor() {\n super()\n\n components.forEach(({ templates = [], groups = [] }) => {\n groups.forEach(group => BoardModeller.registerGroup(group))\n BoardModeller.registerTemplate(templates)\n })\n\n /* 컴포넌트에서 정의된 에디터들을 MODELLER_EDITORS에 등록 */\n var addedEditors = {}\n for (let component in components) {\n let { editors } = components[component]\n\n editors &&\n editors.forEach(editor => {\n let { type, element } = editor\n\n addedEditors[type] = element\n })\n }\n\n OxPropertyEditor.register(addedEditors)\n\n this.boardName = ''\n this.model = null\n this.themes = null\n this.baseUrl = ''\n this.selected = []\n this.mode = 1\n this.hideProperty = false\n this.overlay = null\n this.scene = null\n this.fonts = []\n this.board = null\n this.componentGroupList = BoardModeller.groups\n }\n\n static styles = [\n css`\n :host {\n display: flex;\n flex-direction: column;\n\n overflow: hidden;\n position: relative;\n }\n\n board-modeller {\n flex: 1;\n }\n\n oops-note {\n display: block;\n position: absolute;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n }\n `\n ]\n\n @property({ type: String }) boardId?: string | null\n @property({ type: String }) boardName?: string\n @property({ type: Object }) model: any\n @property({ type: Object }) themes: any\n @property({ type: String }) baseUrl?: string\n @property({ type: Array }) selected: any\n @property({ type: Number }) mode?: number\n @property({ type: Boolean }) hideProperty?: boolean\n @property({ type: String }) overlay?: string | null\n @property({ type: Object }) scene: any\n @property({ type: Array }) componentGroupList?: any\n @property({ type: Array }) fonts: any\n @property({ type: Array }) propertyEditor: any\n @property({ type: Boolean }) preparing?: boolean\n\n board: any\n @query('ox-board-modeller') modeller?: BoardModeller\n\n get context() {\n return {\n title: this.board ? this.boardName : this.preparing ? 'Fetching board...' : 'Board Not Found',\n widebleed: true\n }\n }\n\n get oopsNote() {\n return {\n icon: 'color_lens',\n title: 'EMPTY BOARD',\n description: 'There are no board to be designed'\n }\n }\n\n async refresh() {\n if (!this.boardId) {\n this.board = null\n this.model = null\n\n return\n }\n try {\n this.preparing = true\n this.updateContext()\n\n var { board, themes } = (await fetchBoardById(this.boardId)) || {}\n\n if (!board) {\n this.board = null\n throw 'board not found'\n }\n\n this.board = {\n ...board,\n model: {\n ...JSON.parse(board.model)\n }\n }\n\n this.boardName = this.board.name\n this.model = {\n ...this.board.model\n }\n this.themes = themes?.items.reduce((style, theme) => {\n style[theme.name] = theme.value\n return style\n }, {})\n } catch (ex) {\n document.dispatchEvent(\n new CustomEvent('notify', {\n detail: {\n level: 'error',\n message: ex,\n ex\n }\n })\n )\n } finally {\n this.preparing = false\n this.updateContext()\n }\n }\n\n updated(changes) {\n if (changes.has('boardId')) {\n this.refresh()\n }\n }\n\n pageUpdated(changes, lifecycle) {\n if (this.active) {\n this.boardId = lifecycle.resourceId\n } else {\n this.boardId = null\n this.model = null\n this.modeller?.close()\n }\n }\n\n stateChanged(state) {\n this.baseUrl = state.route.rootPath\n this.fonts = state.font\n }\n\n render() {\n var oops = !this.preparing && !this.model && this.oopsNote\n\n return oops\n ? html` <oops-note icon=${oops.icon} title=${oops.title} description=${oops.description}></oops-note> `\n : html`\n <ox-board-modeller\n .mode=${this.mode}\n @mode-changed=${e => {\n this.mode = e.detail.value\n }}\n .model=${this.model}\n @model-changed=${e => {\n this.model = e.detail.value\n }}\n .scene=${this.scene}\n @scene-changed=${e => {\n this.scene = e.detail.value\n }}\n .selected=${this.selected}\n @selected-changed=${e => {\n this.selected = e.detail.value\n }}\n .baseUrl=${this.baseUrl}\n .provider=${provider}\n @save-model=${e => this.saveBoard()}\n .componentGroupList=${this.componentGroupList}\n .fonts=${this.fonts}\n .themes=${this.themes}\n .hideProperty=${this.hideProperty}\n >\n </ox-board-modeller>\n `\n }\n\n async updateBoard() {\n try {\n this.preparing = true\n\n var { id, name, description, groupId } = this.board\n var model = this.scene.model\n\n await updateBoard({ id, name, description, model, groupId })\n\n document.dispatchEvent(\n new CustomEvent('notify', {\n detail: {\n level: 'info',\n message: 'saved'\n }\n })\n )\n } catch (ex) {\n document.dispatchEvent(\n new CustomEvent('notify', {\n detail: {\n level: 'error',\n message: ex,\n ex: ex\n }\n })\n )\n } finally {\n this.preparing = false\n }\n\n this.updateContext()\n }\n\n async saveBoard() {\n await this.updateBoard()\n }\n}\n"]}
1
+ {"version":3,"file":"board-modeller-page.js","sourceRoot":"","sources":["../../client/pages/board-modeller-page.ts"],"names":[],"mappings":"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","sourcesContent":["import './things-scene-components.import'\nimport '@fmsim/board/ox-board-modeller.js'\n\nimport { css, html } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { BoardModelCache } from '@fmsim/board'\nimport { BoardModeller } from '@fmsim/board/ox-board-modeller.js'\nimport { LoadTracker } from '@hatiolab/things-scene'\nimport { OxPropertyEditor } from '@operato/property-editor'\nimport { connect, PageView, store } from '@operato/shell'\nimport { fetchBoardById, updateBoard } from '@fmsim/api'\n\nimport { provider } from '../board-provider'\nimport components from './things-scene-components-with-tools.import'\n\nconst NOOP = () => {}\n\n@customElement('board-modeller-page')\nexport class BoardModellerPage extends connect(store)(PageView) {\n constructor() {\n super()\n\n components.forEach(({ templates = [], groups = [] }) => {\n groups.forEach(group => BoardModeller.registerGroup(group))\n BoardModeller.registerTemplate(templates)\n })\n\n /* 컴포넌트에서 정의된 에디터들을 MODELLER_EDITORS에 등록 */\n var addedEditors = {}\n for (let component in components) {\n let { editors } = components[component]\n\n editors &&\n editors.forEach(editor => {\n let { type, element } = editor\n\n addedEditors[type] = element\n })\n }\n\n OxPropertyEditor.register(addedEditors)\n\n this.boardName = ''\n this.model = null\n this.themes = null\n this.baseUrl = ''\n this.selected = []\n this.mode = 1\n this.hideProperty = false\n this.overlay = null\n this.scene = null\n this.fonts = []\n this.board = null\n this.componentGroupList = BoardModeller.groups\n }\n\n static styles = [\n css`\n :host {\n display: flex;\n flex-direction: column;\n\n overflow: hidden;\n position: relative;\n }\n\n board-modeller {\n flex: 1;\n }\n\n oops-note {\n display: block;\n position: absolute;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n }\n `\n ]\n\n @property({ type: String }) boardId?: string | null\n @property({ type: String }) boardName?: string\n @property({ type: Object }) model: any\n @property({ type: Object }) themes: any\n @property({ type: String }) baseUrl?: string\n @property({ type: Array }) selected: any\n @property({ type: Number }) mode?: number\n @property({ type: Boolean }) hideProperty?: boolean\n @property({ type: String }) overlay?: string | null\n @property({ type: Object }) scene: any\n @property({ type: Array }) componentGroupList?: any\n @property({ type: Array }) fonts: any\n @property({ type: Array }) propertyEditor: any\n @property({ type: Boolean }) preparing?: boolean\n\n board: any\n private _loadTracker?: LoadTracker\n @query('ox-board-modeller') modeller?: BoardModeller\n\n get context() {\n return {\n title: this.board ? this.boardName : this.preparing ? 'Fetching board...' : 'Board Not Found',\n widebleed: true\n }\n }\n\n get oopsNote() {\n return {\n icon: 'color_lens',\n title: 'EMPTY BOARD',\n description: 'There are no board to be designed'\n }\n }\n\n async refresh() {\n if (!this.boardId) {\n this.board = null\n this.model = null\n\n return\n }\n try {\n this.board = null\n this.model = null\n this._loadTracker = new LoadTracker()\n this._loadTracker.setPhase('fetch')\n this.preparing = true\n this.updateContext()\n\n var { board, themes } = (await fetchBoardById(this.boardId)) || {}\n\n if (!board) {\n this.board = null\n throw 'board not found'\n }\n\n this.board = {\n ...board,\n model: {\n ...JSON.parse(board.model)\n }\n }\n\n this.boardName = this.board.name\n this.model = {\n ...this.board.model\n }\n this.themes = themes?.items.reduce((style, theme) => {\n style[theme.name] = theme.value\n return style\n }, {})\n } catch (ex) {\n document.dispatchEvent(\n new CustomEvent('notify', {\n detail: {\n level: 'error',\n message: ex,\n ex\n }\n })\n )\n } finally {\n this.preparing = false\n this.updateContext()\n }\n }\n\n updated(changes) {\n if (changes.has('boardId')) {\n this.refresh()\n }\n }\n\n pageUpdated(changes, lifecycle) {\n if (this.active) {\n this.boardId = lifecycle.resourceId\n } else {\n this.boardId = null\n this.model = null\n this.modeller?.close()\n }\n }\n\n stateChanged(state) {\n this.baseUrl = state.route.rootPath\n this.fonts = state.font\n }\n\n render() {\n var oops = !this.preparing && !this.model && this.oopsNote\n\n return oops\n ? html` <oops-note icon=${oops.icon} title=${oops.title} description=${oops.description}></oops-note> `\n : html`\n <ox-board-modeller\n .mode=${this.mode}\n .loadTracker=${this._loadTracker}\n @mode-changed=${e => {\n this.mode = e.detail.value\n }}\n .model=${this.model}\n @model-changed=${e => {\n this.model = e.detail.value\n }}\n .scene=${this.scene}\n @scene-changed=${e => {\n this.scene = e.detail.value\n }}\n .selected=${this.selected}\n @selected-changed=${e => {\n this.selected = e.detail.value\n }}\n .baseUrl=${this.baseUrl}\n .provider=${provider}\n @save-model=${e => this.saveBoard()}\n .componentGroupList=${this.componentGroupList}\n .fonts=${this.fonts}\n .themes=${this.themes}\n .hideProperty=${this.hideProperty}\n >\n </ox-board-modeller>\n `\n }\n\n async updateBoard() {\n try {\n this.preparing = true\n\n var { id, name, description, groupId } = this.board\n var model = this.scene.model\n\n await updateBoard({ id, name, description, model, groupId })\n\n document.dispatchEvent(\n new CustomEvent('notify', {\n detail: {\n level: 'info',\n message: 'saved'\n }\n })\n )\n } catch (ex) {\n document.dispatchEvent(\n new CustomEvent('notify', {\n detail: {\n level: 'error',\n message: ex,\n ex: ex\n }\n })\n )\n } finally {\n this.preparing = false\n }\n\n this.updateContext()\n }\n\n async saveBoard() {\n await this.updateBoard()\n // 저장 후 캐시 무효화 — viewer에서 다음 로드 시 최신 모델 fetch\n await BoardModelCache.remove(this.board.id)\n }\n}\n"]}
@@ -16,6 +16,7 @@ export declare class BoardViewerPage extends BoardViewerPage_base {
16
16
  _baseUrl?: string;
17
17
  _interactive?: boolean;
18
18
  preparing?: boolean;
19
+ private _loadTracker?;
19
20
  private showFMBUnitInfoHandler;
20
21
  private popup?;
21
22
  boardViewer: BoardViewer;
@@ -4,9 +4,10 @@ import '@fmsim/board/ox-board-viewer.js';
4
4
  import './fmb-unit-info.js';
5
5
  import { css, html } from 'lit';
6
6
  import { customElement, property, query } from 'lit/decorators.js';
7
- import { BoardViewer } from '@fmsim/board';
7
+ import { BoardModelCache, BoardViewer } from '@fmsim/board';
8
+ import { LoadTracker } from '@hatiolab/things-scene';
8
9
  import { connect, store, PageView } from '@operato/shell';
9
- import { fetchBoardById } from '@fmsim/api';
10
+ import { fetchBoardById, fetchPlayback } from '@fmsim/api';
10
11
  import { provider } from '../board-provider.js';
11
12
  let BoardViewerPage = class BoardViewerPage extends connect(store)(PageView) {
12
13
  constructor() {
@@ -35,6 +36,8 @@ let BoardViewerPage = class BoardViewerPage extends connect(store)(PageView) {
35
36
  <ox-board-viewer
36
37
  .board=${this._board}
37
38
  .provider=${provider}
39
+ .loadTracker=${this._loadTracker}
40
+ ._fetchPlaybackData=${fetchPlayback}
38
41
  ?hide-fullscreen=${this._interactive}
39
42
  ?hide-navigation=${this._interactive}
40
43
  ></ox-board-viewer>
@@ -70,23 +73,35 @@ let BoardViewerPage = class BoardViewerPage extends connect(store)(PageView) {
70
73
  this._baseUrl = state.app.baseUrl;
71
74
  }
72
75
  async refresh() {
76
+ var _a;
73
77
  if (!this._boardId) {
74
78
  this._board = null;
75
79
  return;
76
80
  }
77
81
  try {
82
+ this._board = null;
83
+ this._loadTracker = new LoadTracker();
84
+ this._loadTracker.setPhase('fetch');
78
85
  this.preparing = true;
79
86
  this.updateContext();
80
- var { board, themes } = (await fetchBoardById(this._boardId)) || {};
81
- const style = themes === null || themes === void 0 ? void 0 : themes.items.reduce((style, theme) => {
82
- style[theme.name] = theme.value;
83
- return style;
84
- }, {});
87
+ // 캐시 updatedAt을 서버에 전달 → 동일하면 model 생략됨
88
+ const cached = await BoardModelCache.get(this._boardId);
89
+ var { board, themes } = (await fetchBoardById(this._boardId, cached === null || cached === void 0 ? void 0 : cached.updatedAt)) || {};
90
+ this._loadTracker.setPhase('parse');
91
+ const style = (_a = themes === null || themes === void 0 ? void 0 : themes.items) === null || _a === void 0 ? void 0 : _a.reduce((s, t) => { s[t.name] = t.value; return s; }, {});
85
92
  if (!board) {
86
93
  this._board = null;
87
94
  throw 'board not found';
88
95
  }
89
- this._board = Object.assign(Object.assign({}, board), { model: Object.assign({}, JSON.parse(board.model)), style });
96
+ if (board.model === null && cached) {
97
+ // 서버가 model 생략 → 캐시 유효
98
+ this._board = Object.assign(Object.assign({}, cached), { style });
99
+ }
100
+ else {
101
+ // 새 모델 또는 첫 로드
102
+ await BoardModelCache.put(board.id, board.name, board.model, board.updatedAt);
103
+ this._board = Object.assign(Object.assign({}, board), { model: JSON.parse(board.model), style });
104
+ }
90
105
  }
91
106
  catch (ex) {
92
107
  document.dispatchEvent(new CustomEvent('notify', {
@@ -1 +1 @@
1
- {"version":3,"file":"board-viewer-page.js","sourceRoot":"","sources":["../../client/pages/board-viewer-page.ts"],"names":[],"mappings":"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","sourcesContent":["import './things-scene-components.import'\nimport '@fmsim/board/ox-board-viewer.js'\nimport './fmb-unit-info.js'\n\nimport { css, html } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { BoardViewer } from '@fmsim/board'\nimport { connect, store, PageView } from '@operato/shell'\nimport { fetchBoardById } from '@fmsim/api'\n\nimport { provider } from '../board-provider.js'\nimport { FMBUnitInfo } from './fmb-unit-info.js'\n\n@customElement('board-viewer-page')\nexport class BoardViewerPage extends connect(store)(PageView) {\n static styles = [\n css`\n :host {\n display: flex;\n flex-direction: column;\n\n width: 100%; /* 전체화면보기를 위해서 필요함. */\n height: 100%;\n\n overflow: hidden;\n position: relative;\n }\n\n ox-board-viewer {\n flex: 1;\n background-color: white;\n }\n\n ::slotted(fmb-unit-info) {\n position: absolute;\n right: 10px;\n top: 10px;\n width: 200px;\n opacity: 0.9;\n box-shadow: 2px 2px 4px gray;\n }\n\n oops-note {\n display: block;\n position: absolute;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n }\n `\n ]\n\n @property({ type: Object }) _board: any\n @property({ type: String }) _boardId?: string\n @property({ type: String }) _baseUrl?: string\n @property({ type: Boolean }) _interactive?: boolean\n @property({ type: Boolean }) preparing?: boolean\n\n private showFMBUnitInfoHandler = this.showFMBUnitInfo.bind(this)\n private popup?: FMBUnitInfo\n\n @query('ox-board-viewer') boardViewer!: BoardViewer\n\n get oopsNote() {\n return {\n icon: 'insert_chart_outlined',\n title: 'EMPTY BOARD',\n description: 'There are no board to be shown'\n }\n }\n\n get context() {\n return {\n /* can set the page title with the 'title' parameter. */\n title:\n this.lifecycle.params['title'] ||\n (this._board ? this._board.name : this.preparing ? 'Fetching board...' : 'Board Not Found')\n }\n }\n\n render() {\n var oops = !this.preparing && !this._board && this.oopsNote\n\n return oops\n ? html` <oops-note icon=${oops.icon} title=${oops.title} description=${oops.description}></oops-note> `\n : html`\n <ox-board-viewer\n .board=${this._board}\n .provider=${provider}\n ?hide-fullscreen=${this._interactive}\n ?hide-navigation=${this._interactive}\n ></ox-board-viewer>\n\n <slot></slot>\n `\n }\n\n updated(changes) {\n if (changes.has('_boardId')) {\n this.refresh()\n }\n }\n\n pageUpdated(changes, lifecycle) {\n if (this.active) {\n this.hidePopup()\n this._boardId = lifecycle.resourceId\n this._interactive = lifecycle.params['interactive'] === 'true'\n } else {\n /*\n * 비활성화된 페이지에서 render update가 발생하지 않으므로, 강제로 scene을 close 한다.\n * 화면이 inactive 될 때, 굳이 scene을 close하는 이유는,\n * 새로운 board가 선택되어 뷰어가 열릴 때, 기존 보드 잔상이 보이지 않도록 하기위해서이다.\n */\n if (this._boardId) {\n let boardViewer = this.boardViewer\n boardViewer && boardViewer.closeScene()\n }\n\n this._boardId = ''\n }\n }\n\n stateChanged(state) {\n this._baseUrl = state.app.baseUrl\n }\n\n async refresh() {\n if (!this._boardId) {\n this._board = null\n return\n }\n\n try {\n this.preparing = true\n this.updateContext()\n\n var { board, themes } = (await fetchBoardById(this._boardId)) || {}\n const style = themes?.items.reduce((style, theme) => {\n style[theme.name] = theme.value\n return style\n }, {})\n\n if (!board) {\n this._board = null\n throw 'board not found'\n }\n\n this._board = {\n ...board,\n model: {\n ...JSON.parse(board.model)\n },\n style\n }\n } catch (ex) {\n document.dispatchEvent(\n new CustomEvent('notify', {\n detail: {\n level: 'error',\n message: ex,\n ex\n }\n })\n )\n } finally {\n this.preparing = false\n this.updateContext()\n }\n }\n\n showFMBUnitInfo(e: Event) {\n e.stopPropagation()\n\n const { type: etype, model, event, data } = (e as CustomEvent).detail?.value || {}\n const { id, type } = model || {}\n\n console.log(`${id}:${type} ${etype}`)\n\n if (etype == 'hover') {\n return\n }\n\n const unit = (e as CustomEvent).detail?.value || {}\n\n if (!this.popup) {\n const popup = document.createElement('fmb-unit-info') as FMBUnitInfo\n popup.addEventListener('close', e => {\n e.stopPropagation()\n this.hidePopup()\n })\n\n this.appendChild(popup)\n this.popup = popup\n }\n\n this.popup.unit = unit\n }\n\n hidePopup() {\n if (this.popup) {\n this.removeChild(this.popup)\n delete this.popup\n }\n }\n}\n"]}
1
+ {"version":3,"file":"board-viewer-page.js","sourceRoot":"","sources":["../../client/pages/board-viewer-page.ts"],"names":[],"mappings":"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","sourcesContent":["import './things-scene-components.import'\nimport '@fmsim/board/ox-board-viewer.js'\nimport './fmb-unit-info.js'\n\nimport { css, html } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { BoardModelCache, BoardViewer } from '@fmsim/board'\nimport { LoadTracker } from '@hatiolab/things-scene'\nimport { connect, store, PageView } from '@operato/shell'\nimport { fetchBoardById, fetchPlayback } from '@fmsim/api'\n\nimport { provider } from '../board-provider.js'\nimport { FMBUnitInfo } from './fmb-unit-info.js'\n\n@customElement('board-viewer-page')\nexport class BoardViewerPage extends connect(store)(PageView) {\n static styles = [\n css`\n :host {\n display: flex;\n flex-direction: column;\n\n width: 100%; /* 전체화면보기를 위해서 필요함. */\n height: 100%;\n\n overflow: hidden;\n position: relative;\n }\n\n ox-board-viewer {\n flex: 1;\n background-color: white;\n }\n\n ::slotted(fmb-unit-info) {\n position: absolute;\n right: 10px;\n top: 10px;\n width: 200px;\n opacity: 0.9;\n box-shadow: 2px 2px 4px gray;\n }\n\n oops-note {\n display: block;\n position: absolute;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n }\n `\n ]\n\n @property({ type: Object }) _board: any\n @property({ type: String }) _boardId?: string\n @property({ type: String }) _baseUrl?: string\n @property({ type: Boolean }) _interactive?: boolean\n @property({ type: Boolean }) preparing?: boolean\n private _loadTracker?: LoadTracker\n\n private showFMBUnitInfoHandler = this.showFMBUnitInfo.bind(this)\n private popup?: FMBUnitInfo\n\n @query('ox-board-viewer') boardViewer!: BoardViewer\n\n get oopsNote() {\n return {\n icon: 'insert_chart_outlined',\n title: 'EMPTY BOARD',\n description: 'There are no board to be shown'\n }\n }\n\n get context() {\n return {\n /* can set the page title with the 'title' parameter. */\n title:\n this.lifecycle.params['title'] ||\n (this._board ? this._board.name : this.preparing ? 'Fetching board...' : 'Board Not Found')\n }\n }\n\n render() {\n var oops = !this.preparing && !this._board && this.oopsNote\n\n return oops\n ? html` <oops-note icon=${oops.icon} title=${oops.title} description=${oops.description}></oops-note> `\n : html`\n <ox-board-viewer\n .board=${this._board}\n .provider=${provider}\n .loadTracker=${this._loadTracker}\n ._fetchPlaybackData=${fetchPlayback}\n ?hide-fullscreen=${this._interactive}\n ?hide-navigation=${this._interactive}\n ></ox-board-viewer>\n\n <slot></slot>\n `\n }\n\n updated(changes) {\n if (changes.has('_boardId')) {\n this.refresh()\n }\n }\n\n pageUpdated(changes, lifecycle) {\n if (this.active) {\n this.hidePopup()\n this._boardId = lifecycle.resourceId\n this._interactive = lifecycle.params['interactive'] === 'true'\n } else {\n /*\n * 비활성화된 페이지에서 render update가 발생하지 않으므로, 강제로 scene을 close 한다.\n * 화면이 inactive 될 때, 굳이 scene을 close하는 이유는,\n * 새로운 board가 선택되어 뷰어가 열릴 때, 기존 보드 잔상이 보이지 않도록 하기위해서이다.\n */\n if (this._boardId) {\n let boardViewer = this.boardViewer\n boardViewer && boardViewer.closeScene()\n }\n\n this._boardId = ''\n }\n }\n\n stateChanged(state) {\n this._baseUrl = state.app.baseUrl\n }\n\n async refresh() {\n if (!this._boardId) {\n this._board = null\n return\n }\n\n try {\n this._board = null\n this._loadTracker = new LoadTracker()\n this._loadTracker.setPhase('fetch')\n this.preparing = true\n this.updateContext()\n\n // 캐시 updatedAt을 서버에 전달 → 동일하면 model 생략됨\n const cached = await BoardModelCache.get(this._boardId!)\n var { board, themes } = (await fetchBoardById(this._boardId!, cached?.updatedAt)) || ({} as any)\n this._loadTracker.setPhase('parse')\n\n const style = themes?.items?.reduce((s: any, t: any) => { s[t.name] = t.value; return s }, {})\n\n if (!board) {\n this._board = null\n throw 'board not found'\n }\n\n if (board.model === null && cached) {\n // 서버가 model 생략 → 캐시 유효\n this._board = { ...cached, style }\n } else {\n // 새 모델 또는 첫 로드\n await BoardModelCache.put(board.id, board.name, board.model, board.updatedAt)\n this._board = { ...board, model: JSON.parse(board.model), style }\n }\n } catch (ex) {\n document.dispatchEvent(\n new CustomEvent('notify', {\n detail: {\n level: 'error',\n message: ex,\n ex\n }\n })\n )\n } finally {\n this.preparing = false\n this.updateContext()\n }\n }\n\n showFMBUnitInfo(e: Event) {\n e.stopPropagation()\n\n const { type: etype, model, event, data } = (e as CustomEvent).detail?.value || {}\n const { id, type } = model || {}\n\n console.log(`${id}:${type} ${etype}`)\n\n if (etype == 'hover') {\n return\n }\n\n const unit = (e as CustomEvent).detail?.value || {}\n\n if (!this.popup) {\n const popup = document.createElement('fmb-unit-info') as FMBUnitInfo\n popup.addEventListener('close', e => {\n e.stopPropagation()\n this.hidePopup()\n })\n\n this.appendChild(popup)\n this.popup = popup\n }\n\n this.popup.unit = unit\n }\n\n hidePopup() {\n if (this.popup) {\n this.removeChild(this.popup)\n delete this.popup\n }\n }\n}\n"]}
@@ -130,10 +130,7 @@ let ThemeListPage = class ThemeListPage extends connect(store)(localize(i18next)
130
130
  renderer: function (value, column, record, rowIndex, field) {
131
131
  return getRenderer(record.type || 'text')(value, column, record, rowIndex, field);
132
132
  },
133
- editable: true,
134
- options: {
135
- objectified: true
136
- }
133
+ editable: true
137
134
  },
138
135
  sortable: true,
139
136
  width: 180
@@ -1 +1 @@
1
- {"version":3,"file":"theme-list-page.js","sourceRoot":"","sources":["../../../client/pages/theme/theme-list-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/data-grist'\n\nimport { CommonButtonStyles, CommonGristStyles, ScrollbarStyles } from '@operato/styles'\nimport { PageView, store, connect } from '@operato/shell'\nimport { css, html } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements'\nimport { ColumnConfig, DataGrist, FetchOption, SortersControl, getEditor, getRenderer } from '@operato/data-grist'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { OxPopup } from '@operato/popup'\nimport { isMobileDevice } from '@operato/utils'\n\nimport { fetchThemeList, updateMultipleTheme, deleteThemes } from '@fmsim/api'\n\n@customElement('theme-list-page')\nexport class ThemeListPage extends connect(store)(localize(i18next)(ScopedElementsMixin(PageView))) {\n static styles = [\n ScrollbarStyles,\n CommonGristStyles,\n css`\n :host {\n display: flex;\n\n width: 100%;\n\n --grid-record-emphasized-background-color: red;\n --grid-record-emphasized-color: yellow;\n }\n `\n ]\n\n @property({ type: Object }) gristConfig: any\n @property({ type: String }) mode: 'CARD' | 'GRID' | 'LIST' = isMobileDevice() ? 'CARD' : 'GRID'\n\n @query('ox-grist') private grist!: DataGrist\n @query('#sorter-control') private sortersControl!: OxPopup\n\n get context() {\n return {\n title: i18next.t('title.theme list'),\n search: {\n handler: (search: string) => {\n this.grist.searchText = search\n },\n value: this.grist.searchText\n },\n filter: {\n handler: () => {\n this.grist.toggleHeadroom()\n }\n },\n actions: [\n {\n title: i18next.t('button.save'),\n action: this._updateTheme.bind(this),\n ...CommonButtonStyles.save\n },\n {\n title: i18next.t('button.delete'),\n action: this._deleteTheme.bind(this),\n ...CommonButtonStyles.delete\n }\n ]\n }\n }\n\n render() {\n const mode = this.mode || (isMobileDevice() ? 'CARD' : 'GRID')\n\n return html`\n <ox-grist .mode=${mode} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)}>\n <div slot=\"headroom\">\n <div id=\"filters\">\n <ox-filters-form autofocus without-search></ox-filters-form>\n </div>\n\n <div id=\"sorters\">\n Sort\n <md-icon\n @click=${e => {\n const target = e.currentTarget\n this.sortersControl.open({\n right: 0,\n top: target.offsetTop + target.offsetHeight\n })\n }}\n >expand_more</md-icon\n >\n <ox-popup id=\"sorter-control\">\n <ox-sorters-control> </ox-sorters-control>\n </ox-popup>\n </div>\n\n <div id=\"modes\">\n <md-icon @click=${() => (this.mode = 'GRID')} ?active=${mode == 'GRID'}>grid_on</md-icon>\n <md-icon @click=${() => (this.mode = 'LIST')} ?active=${mode == 'LIST'}>format_list_bulleted</md-icon>\n <md-icon @click=${() => (this.mode = 'CARD')} ?active=${mode == 'CARD'}>apps</md-icon>\n </div>\n </div>\n </ox-grist>\n `\n }\n\n async pageInitialized(lifecycle: any) {\n this.gristConfig = {\n list: {\n fields: ['name', 'description'],\n details: ['type', 'updatedAt']\n },\n columns: [\n { type: 'gutter', gutterName: 'sequence' },\n { type: 'gutter', gutterName: 'row-selector', multiple: true },\n {\n type: 'string',\n name: 'name',\n header: i18next.t('field.name'),\n record: {\n editable: true\n },\n filter: 'search',\n sortable: true,\n width: 150\n },\n {\n type: 'string',\n name: 'description',\n header: i18next.t('field.description'),\n record: {\n editable: true\n },\n filter: 'search',\n width: 200\n },\n {\n type: 'checkbox',\n name: 'active',\n header: i18next.t('field.active'),\n record: {\n editable: true\n },\n width: 60\n },\n {\n type: 'select',\n name: 'type',\n header: i18next.t('field.type'),\n record: {\n options: ['', 'color-map', 'color-ranges', 'color', 'text', 'animation-map'],\n editable: true\n },\n width: 120\n },\n {\n type: 'string',\n name: 'value',\n header: i18next.t('field.value'),\n record: {\n editor: function (value, column, record, rowIndex, field) {\n return getEditor(record.type || 'text')(value, column, record, rowIndex, field)\n },\n renderer: function (value, column, record, rowIndex, field) {\n return getRenderer(record.type || 'text')(value, column, record, rowIndex, field)\n },\n editable: true,\n options: {\n objectified: true\n }\n },\n sortable: true,\n width: 180\n },\n {\n type: 'resource-object',\n name: 'updater',\n header: i18next.t('field.updater'),\n record: {\n editable: false\n },\n sortable: true,\n width: 120\n },\n {\n type: 'datetime',\n name: 'updatedAt',\n header: i18next.t('field.updated_at'),\n record: {\n editable: false\n },\n sortable: true,\n width: 180\n }\n ],\n rows: {\n selectable: {\n multiple: true\n }\n },\n sorters: [\n {\n name: 'name'\n }\n ]\n }\n }\n\n async pageUpdated(changes: any, lifecycle: any) {\n if (this.active) {\n // do something here when this page just became as active\n }\n }\n\n async fetchHandler({ page = 1, limit = 100, sortings = [], filters = [] }: FetchOption) {\n const data = (await fetchThemeList({ page, limit, sortings, filters })) || {}\n return {\n total: data.responses.total || 0,\n records: data.responses.items || []\n }\n }\n\n async _deleteTheme() {\n if (confirm(i18next.t('text.sure_to_x', { x: i18next.t('text.delete') }))) {\n const ids = this.grist.selected.map(record => record.id).filter(Boolean)\n if (ids && ids.length > 0) {\n await deleteThemes(ids as string[])\n }\n\n this.grist.fetch()\n }\n }\n\n async _updateTheme() {\n let patches = this.grist.dirtyRecords\n if (patches && patches.length) {\n patches = patches.map(patch => {\n let patchField: any = patch.id ? { id: patch.id } : {}\n const dirtyFields = patch.__dirtyfields__\n for (let key in dirtyFields) {\n patchField[key] = dirtyFields[key].after\n }\n patchField.cuFlag = patch.__dirty__\n\n return patchField\n })\n\n await updateMultipleTheme(patches)\n\n this.grist.fetch()\n }\n }\n}\n"]}
1
+ {"version":3,"file":"theme-list-page.js","sourceRoot":"","sources":["../../../client/pages/theme/theme-list-page.ts"],"names":[],"mappings":";AAAA,OAAO,qBAAqB,CAAA;AAE5B,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACxF,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AACzD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAA;AAC/B,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EAAgB,SAAS,EAA+B,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAElH,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAE/C,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAGvE,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC,CAAC;IAA5F;;QAiBuB,SAAI,GAA6B,cAAc,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAA;IAsNjG,CAAC;IAjNC,IAAI,OAAO;QACT,OAAO;YACL,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,kBAAkB,CAAC;YACpC,MAAM,EAAE;gBACN,OAAO,EAAE,CAAC,MAAc,EAAE,EAAE;oBAC1B,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,MAAM,CAAA;gBAChC,CAAC;gBACD,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU;aAC7B;YACD,MAAM,EAAE;gBACN,OAAO,EAAE,GAAG,EAAE;oBACZ,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAA;gBAC7B,CAAC;aACF;YACD,OAAO,EAAE;gCAEL,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,EAC/B,MAAM,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IACjC,kBAAkB,CAAC,IAAI;gCAG1B,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,EACjC,MAAM,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IACjC,kBAAkB,CAAC,MAAM;aAE/B;SACF,CAAA;IACH,CAAC;IAED,MAAM;QACJ,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;QAE9D,OAAO,IAAI,CAAA;wBACS,IAAI,YAAY,IAAI,CAAC,WAAW,kBAAkB,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;;;;;uBAS/E,CAAC,CAAC,EAAE;YACX,MAAM,MAAM,GAAG,CAAC,CAAC,aAAa,CAAA;YAC9B,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC;gBACvB,KAAK,EAAE,CAAC;gBACR,GAAG,EAAE,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,YAAY;aAC5C,CAAC,CAAA;QACJ,CAAC;;;;;;;;;8BASe,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,YAAY,IAAI,IAAI,MAAM;8BACpD,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,YAAY,IAAI,IAAI,MAAM;8BACpD,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,YAAY,IAAI,IAAI,MAAM;;;;KAI7E,CAAA;IACH,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,SAAc;QAClC,IAAI,CAAC,WAAW,GAAG;YACjB,IAAI,EAAE;gBACJ,MAAM,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC;gBAC/B,OAAO,EAAE,CAAC,MAAM,EAAE,WAAW,CAAC;aAC/B;YACD,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE;gBAC1C,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAC9D;oBACE,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,MAAM;oBACZ,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC;oBAC/B,MAAM,EAAE;wBACN,QAAQ,EAAE,IAAI;qBACf;oBACD,MAAM,EAAE,QAAQ;oBAChB,QAAQ,EAAE,IAAI;oBACd,KAAK,EAAE,GAAG;iBACX;gBACD;oBACE,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,aAAa;oBACnB,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC;oBACtC,MAAM,EAAE;wBACN,QAAQ,EAAE,IAAI;qBACf;oBACD,MAAM,EAAE,QAAQ;oBAChB,KAAK,EAAE,GAAG;iBACX;gBACD;oBACE,IAAI,EAAE,UAAU;oBAChB,IAAI,EAAE,QAAQ;oBACd,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC;oBACjC,MAAM,EAAE;wBACN,QAAQ,EAAE,IAAI;qBACf;oBACD,KAAK,EAAE,EAAE;iBACV;gBACD;oBACE,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,MAAM;oBACZ,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC;oBAC/B,MAAM,EAAE;wBACN,OAAO,EAAE,CAAC,EAAE,EAAE,WAAW,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe,CAAC;wBAC5E,QAAQ,EAAE,IAAI;qBACf;oBACD,KAAK,EAAE,GAAG;iBACX;gBACD;oBACE,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,OAAO;oBACb,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC;oBAChC,MAAM,EAAE;wBACN,MAAM,EAAE,UAAU,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK;4BACtD,OAAO,SAAS,CAAC,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAA;wBACjF,CAAC;wBACD,QAAQ,EAAE,UAAU,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK;4BACxD,OAAO,WAAW,CAAC,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAA;wBACnF,CAAC;wBACD,QAAQ,EAAE,IAAI;qBACf;oBACD,QAAQ,EAAE,IAAI;oBACd,KAAK,EAAE,GAAG;iBACX;gBACD;oBACE,IAAI,EAAE,iBAAiB;oBACvB,IAAI,EAAE,SAAS;oBACf,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;oBAClC,MAAM,EAAE;wBACN,QAAQ,EAAE,KAAK;qBAChB;oBACD,QAAQ,EAAE,IAAI;oBACd,KAAK,EAAE,GAAG;iBACX;gBACD;oBACE,IAAI,EAAE,UAAU;oBAChB,IAAI,EAAE,WAAW;oBACjB,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,kBAAkB,CAAC;oBACrC,MAAM,EAAE;wBACN,QAAQ,EAAE,KAAK;qBAChB;oBACD,QAAQ,EAAE,IAAI;oBACd,KAAK,EAAE,GAAG;iBACX;aACF;YACD,IAAI,EAAE;gBACJ,UAAU,EAAE;oBACV,QAAQ,EAAE,IAAI;iBACf;aACF;YACD,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;iBACb;aACF;SACF,CAAA;IACH,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,OAAY,EAAE,SAAc;QAC5C,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,yDAAyD;QAC3D,CAAC;IACH,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,EAAE,IAAI,GAAG,CAAC,EAAE,KAAK,GAAG,GAAG,EAAE,QAAQ,GAAG,EAAE,EAAE,OAAO,GAAG,EAAE,EAAe;QACpF,MAAM,IAAI,GAAG,CAAC,MAAM,cAAc,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;QAC7E,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC;YAChC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE;SACpC,CAAA;IACH,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;YAC1E,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;YACxE,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,MAAM,YAAY,CAAC,GAAe,CAAC,CAAA;YACrC,CAAC;YAED,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;QACpB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,IAAI,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAA;QACrC,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YAC9B,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;gBAC5B,IAAI,UAAU,GAAQ,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;gBACtD,MAAM,WAAW,GAAG,KAAK,CAAC,eAAe,CAAA;gBACzC,KAAK,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC;oBAC5B,UAAU,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,KAAK,CAAA;gBAC1C,CAAC;gBACD,UAAU,CAAC,MAAM,GAAG,KAAK,CAAC,SAAS,CAAA;gBAEnC,OAAO,UAAU,CAAA;YACnB,CAAC,CAAC,CAAA;YAEF,MAAM,mBAAmB,CAAC,OAAO,CAAC,CAAA;YAElC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;QACpB,CAAC;IACH,CAAC;;AArOM,oBAAM,GAAG;IACd,eAAe;IACf,iBAAiB;IACjB,GAAG,CAAA;;;;;;;;;KASF;CACF,AAbY,CAaZ;AAE2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;kDAAiB;AAChB;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;2CAAoE;AAEpE;IAA1B,KAAK,CAAC,UAAU,CAAC;8BAAiB,SAAS;4CAAA;AACV;IAAjC,KAAK,CAAC,iBAAiB,CAAC;8BAA0B,OAAO;qDAAA;AApB/C,aAAa;IADzB,aAAa,CAAC,iBAAiB,CAAC;GACpB,aAAa,CAuOzB","sourcesContent":["import '@operato/data-grist'\n\nimport { CommonButtonStyles, CommonGristStyles, ScrollbarStyles } from '@operato/styles'\nimport { PageView, store, connect } from '@operato/shell'\nimport { css, html } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements'\nimport { ColumnConfig, DataGrist, FetchOption, SortersControl, getEditor, getRenderer } from '@operato/data-grist'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { OxPopup } from '@operato/popup'\nimport { isMobileDevice } from '@operato/utils'\n\nimport { fetchThemeList, updateMultipleTheme, deleteThemes } from '@fmsim/api'\n\n@customElement('theme-list-page')\nexport class ThemeListPage extends connect(store)(localize(i18next)(ScopedElementsMixin(PageView))) {\n static styles = [\n ScrollbarStyles,\n CommonGristStyles,\n css`\n :host {\n display: flex;\n\n width: 100%;\n\n --grid-record-emphasized-background-color: red;\n --grid-record-emphasized-color: yellow;\n }\n `\n ]\n\n @property({ type: Object }) gristConfig: any\n @property({ type: String }) mode: 'CARD' | 'GRID' | 'LIST' = isMobileDevice() ? 'CARD' : 'GRID'\n\n @query('ox-grist') private grist!: DataGrist\n @query('#sorter-control') private sortersControl!: OxPopup\n\n get context() {\n return {\n title: i18next.t('title.theme list'),\n search: {\n handler: (search: string) => {\n this.grist.searchText = search\n },\n value: this.grist.searchText\n },\n filter: {\n handler: () => {\n this.grist.toggleHeadroom()\n }\n },\n actions: [\n {\n title: i18next.t('button.save'),\n action: this._updateTheme.bind(this),\n ...CommonButtonStyles.save\n },\n {\n title: i18next.t('button.delete'),\n action: this._deleteTheme.bind(this),\n ...CommonButtonStyles.delete\n }\n ]\n }\n }\n\n render() {\n const mode = this.mode || (isMobileDevice() ? 'CARD' : 'GRID')\n\n return html`\n <ox-grist .mode=${mode} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)}>\n <div slot=\"headroom\">\n <div id=\"filters\">\n <ox-filters-form autofocus without-search></ox-filters-form>\n </div>\n\n <div id=\"sorters\">\n Sort\n <md-icon\n @click=${e => {\n const target = e.currentTarget\n this.sortersControl.open({\n right: 0,\n top: target.offsetTop + target.offsetHeight\n })\n }}\n >expand_more</md-icon\n >\n <ox-popup id=\"sorter-control\">\n <ox-sorters-control> </ox-sorters-control>\n </ox-popup>\n </div>\n\n <div id=\"modes\">\n <md-icon @click=${() => (this.mode = 'GRID')} ?active=${mode == 'GRID'}>grid_on</md-icon>\n <md-icon @click=${() => (this.mode = 'LIST')} ?active=${mode == 'LIST'}>format_list_bulleted</md-icon>\n <md-icon @click=${() => (this.mode = 'CARD')} ?active=${mode == 'CARD'}>apps</md-icon>\n </div>\n </div>\n </ox-grist>\n `\n }\n\n async pageInitialized(lifecycle: any) {\n this.gristConfig = {\n list: {\n fields: ['name', 'description'],\n details: ['type', 'updatedAt']\n },\n columns: [\n { type: 'gutter', gutterName: 'sequence' },\n { type: 'gutter', gutterName: 'row-selector', multiple: true },\n {\n type: 'string',\n name: 'name',\n header: i18next.t('field.name'),\n record: {\n editable: true\n },\n filter: 'search',\n sortable: true,\n width: 150\n },\n {\n type: 'string',\n name: 'description',\n header: i18next.t('field.description'),\n record: {\n editable: true\n },\n filter: 'search',\n width: 200\n },\n {\n type: 'checkbox',\n name: 'active',\n header: i18next.t('field.active'),\n record: {\n editable: true\n },\n width: 60\n },\n {\n type: 'select',\n name: 'type',\n header: i18next.t('field.type'),\n record: {\n options: ['', 'color-map', 'color-ranges', 'color', 'text', 'animation-map'],\n editable: true\n },\n width: 120\n },\n {\n type: 'string',\n name: 'value',\n header: i18next.t('field.value'),\n record: {\n editor: function (value, column, record, rowIndex, field) {\n return getEditor(record.type || 'text')(value, column, record, rowIndex, field)\n },\n renderer: function (value, column, record, rowIndex, field) {\n return getRenderer(record.type || 'text')(value, column, record, rowIndex, field)\n },\n editable: true\n },\n sortable: true,\n width: 180\n },\n {\n type: 'resource-object',\n name: 'updater',\n header: i18next.t('field.updater'),\n record: {\n editable: false\n },\n sortable: true,\n width: 120\n },\n {\n type: 'datetime',\n name: 'updatedAt',\n header: i18next.t('field.updated_at'),\n record: {\n editable: false\n },\n sortable: true,\n width: 180\n }\n ],\n rows: {\n selectable: {\n multiple: true\n }\n },\n sorters: [\n {\n name: 'name'\n }\n ]\n }\n }\n\n async pageUpdated(changes: any, lifecycle: any) {\n if (this.active) {\n // do something here when this page just became as active\n }\n }\n\n async fetchHandler({ page = 1, limit = 100, sortings = [], filters = [] }: FetchOption) {\n const data = (await fetchThemeList({ page, limit, sortings, filters })) || {}\n return {\n total: data.responses.total || 0,\n records: data.responses.items || []\n }\n }\n\n async _deleteTheme() {\n if (confirm(i18next.t('text.sure_to_x', { x: i18next.t('text.delete') }))) {\n const ids = this.grist.selected.map(record => record.id).filter(Boolean)\n if (ids && ids.length > 0) {\n await deleteThemes(ids as string[])\n }\n\n this.grist.fetch()\n }\n }\n\n async _updateTheme() {\n let patches = this.grist.dirtyRecords\n if (patches && patches.length) {\n patches = patches.map(patch => {\n let patchField: any = patch.id ? { id: patch.id } : {}\n const dirtyFields = patch.__dirtyfields__\n for (let key in dirtyFields) {\n patchField[key] = dirtyFields[key].after\n }\n patchField.cuFlag = patch.__dirty__\n\n return patchField\n })\n\n await updateMultipleTheme(patches)\n\n this.grist.fetch()\n }\n }\n}\n"]}