@operato/shell 10.29.44 → 10.29.45

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.
@@ -71,6 +71,9 @@ export declare class PageView extends LitElement {
71
71
  */
72
72
  contextPath?: string;
73
73
  _oldLifecycleInfo$: any;
74
+ /** The path this page is shown at: its route arguments are what that path's claims leave of the address. */
75
+ private shownAt?;
76
+ private unclaimed;
74
77
  /**
75
78
  * Handles page updates and lifecycle events. Subclasses can override this method
76
79
  * to implement custom logic for initializing, updating, and disposing of the page.
@@ -7,6 +7,7 @@ import { OxPrompt } from '@operato/popup/ox-prompt.js';
7
7
  import { UPDATE_CONTEXT } from '../../actions/const.js';
8
8
  import { store } from '../../store.js';
9
9
  import { getPathInfo } from '@operato/utils';
10
+ import { addressController } from '@operato/utils/address.js';
10
11
  import { UnsavedDraftController } from '../../drafts/unsaved-draft-controller.js';
11
12
  function diff(after, before) {
12
13
  var changed = false;
@@ -205,7 +206,11 @@ export class PageView extends LitElement {
205
206
  }
206
207
  return active;
207
208
  }
208
- /* lifecycle */
209
+ unclaimed(params) {
210
+ const url = new URL(this.shownAt, location.origin);
211
+ url.search = new URLSearchParams(params).toString();
212
+ return addressController().params({ ...addressController().entry, url });
213
+ }
209
214
  /**
210
215
  * Handles page updates and lifecycle events. Subclasses can override this method
211
216
  * to implement custom logic for initializing, updating, and disposing of the page.
@@ -220,6 +225,19 @@ export class PageView extends LitElement {
220
225
  contextPath: this.contextPath,
221
226
  ...changes
222
227
  };
228
+ /*
229
+ * Route arguments are compared under today's claims. A grid or tab claims its keys only after the page is drawn,
230
+ * so the page opened by an address with `filters` stored them as an argument; on the next route dispatch they
231
+ * are none. Counting that as a change made a screen read its list again and drop the edits it held.
232
+ */
233
+ if (after.active)
234
+ this.shownAt = location.pathname;
235
+ if (this.shownAt) {
236
+ if (before.params)
237
+ before = { ...before, params: this.unclaimed(before.params) };
238
+ if (after.params)
239
+ after = { ...after, params: this.unclaimed(after.params) };
240
+ }
223
241
  if (!('initialized' in changes) && after.active && !before.initialized) {
224
242
  after.initialized = true;
225
243
  }
@@ -1 +1 @@
1
- {"version":3,"file":"page-view.js","sourceRoot":"","sources":["../../../../src/app/pages/page-view.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, PropertyValues, type ReactiveControllerHost } from 'lit'\nimport { property } from 'lit/decorators.js'\nimport isEqual from 'lodash-es/isEqual.js'\nimport { i18next } from '@operato/i18n'\nimport { OxPrompt } from '@operato/popup/ox-prompt.js'\n\nimport { UPDATE_CONTEXT } from '../../actions/const.js'\nimport { store } from '../../store.js'\nimport { getPathInfo } from '@operato/utils'\nimport { UnsavedDraftController } from '../../drafts/unsaved-draft-controller.js'\n\ntype ListDraftSource = HTMLElement &\n ReactiveControllerHost & {\n draftSnapshot?: { value: unknown; base: string | number | null }\n draftRevision: string | number | null\n dirtyRecords?: unknown[]\n restoreUnsavedDraft(value: unknown, base: string | number | null): void\n flushEdits(): void\n }\n\nexport type PageLifecycle = {\n active: boolean\n params: object\n resourceId?: string\n page?: string\n}\n\nfunction diff(after: any, before: any): any {\n var changed = false\n var changes: { [key: string]: any } = {}\n\n Object.getOwnPropertyNames(after).forEach(function (key) {\n let before_val = before[key]\n let after_val = after[key]\n\n if (!isEqual(before_val, after_val)) {\n changes[key] = after_val\n changed = true\n }\n })\n\n return changed && changes\n}\n\n/**\n * PageView is a base class for creating page elements with lifecycle management.\n * Subclasses can extend PageView to define custom behavior and handle page lifecycle events.\n */\nexport class PageView extends LitElement {\n /**\n * Closing this page instance (an MDI tab) destroys it, so its unsaved edits are asked about first: the bar\n * removes the tab only on yes. A page switch only caches the instance and asks nothing.\n */\n async confirmClose(): Promise<boolean> {\n if (!this.addressDirty && !this.listDirty(false)) return true\n if (!(await this.canDeactivate())) return false\n this.discardAddressEdits()\n return true\n }\n private listDrafts = new Map<ListDraftSource, { query: string; controller: UnsavedDraftController<unknown> }>()\n\n private listDraft = (event: Event) => {\n const { source, query, action, pathname } = (\n event as CustomEvent<{\n source: ListDraftSource\n query: string\n pathname: string\n action: 'edit' | 'loaded' | 'leave' | 'discard'\n }>\n ).detail\n let binding = this.listDrafts.get(source)\n if (binding && binding.query !== query) {\n binding.controller.dispose()\n this.listDrafts.delete(source)\n binding = undefined\n }\n if (!binding && action !== 'leave' && action !== 'discard') {\n const state = store.getState() as { auth?: { user?: { id?: string } } }\n const user = state.auth?.user?.id\n const target = JSON.stringify([\n source.id || Array.from(this.renderRoot.querySelectorAll('ox-grist')).indexOf(source),\n query\n ])\n const controller = new UnsavedDraftController(source, {\n address: () => {\n const current = store.getState() as { auth?: { user?: { id?: string } } }\n return user && current.auth?.user?.id === user\n ? { user, domain: getPathInfo(pathname).domain || '', screen: pathname, target }\n : undefined\n },\n snapshot: () => {\n source.flushEdits()\n return source.draftSnapshot\n },\n savedRevision: () => source.draftRevision,\n restore: (value, base) => source.restoreUnsavedDraft(value, base)\n })\n binding = { query, controller }\n this.listDrafts.set(source, binding)\n }\n if (!binding) return\n if (action === 'discard') void binding.controller.settled()\n if (action === 'edit') void binding.controller.flush()\n if (action === 'loaded' && this.active && pathname === location.pathname) void binding.controller.offer()\n if (action === 'leave') {\n if (source.draftSnapshot) void binding.controller.flush()\n binding.controller.dispose()\n this.listDrafts.delete(source)\n }\n }\n\n /** True only for the current edit's completed IndexedDB write; an unwritten edit still needs protection. */\n get addressEditsKept(): boolean {\n this.flushAddressEdits()\n const grids = Array.from(this.renderRoot.querySelectorAll('ox-grist')) as ListDraftSource[]\n const dirty = [...new Set([...grids, ...this.listDrafts.keys()])].filter(source => source.dirtyRecords?.length)\n return dirty.length > 0 && dirty.every(source => this.listDrafts.get(source)?.controller.keeps)\n }\n\n private queryChanged = () => {\n if (this.active) this.updateContext()\n }\n\n connectedCallback() {\n super.connectedCallback()\n this.addEventListener('query-state-change', this.queryChanged)\n this.addEventListener('list-draft', this.listDraft)\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n this.removeEventListener('query-state-change', this.queryChanged)\n for (const [source, binding] of this.listDrafts) {\n if (source.draftSnapshot) void binding.controller.flush()\n binding.controller.dispose()\n }\n this.listDrafts.clear()\n this.removeEventListener('list-draft', this.listDraft)\n }\n /**\n * Whether `change` would discard unsaved edits, so the shell asks first (address-state-ownership §6.4,\n * 2026-10-19). `stays`: this page instance stays on screen. Grid edits stay in the cached page when another\n * page is shown; they are lost when this page gets new route arguments (every grid reloads) or a new list\n * query (the url-bound grids reload). A page's own unsaved state (`addressDirty`) is asked about whenever the\n * page is left or changed, as `canDeactivate` was before 2026-10-17.\n */\n discards(change: { route: boolean; query: boolean }, stays: boolean): boolean {\n if (!change.route && !change.query) return false\n if (this.addressDirty) return true\n return stays && this.listDirty(!change.route)\n }\n\n /** Whether the page's grids hold unsaved edits - only those bound to the address when `urlBound`. */\n protected listDirty(urlBound: boolean): boolean {\n return this.listGrids(urlBound).some(grid => grid.dirtyRecords?.length)\n }\n\n private listGrids(urlBound: boolean) {\n this.flushAddressEdits()\n const grids = Array.from(this.renderRoot.querySelectorAll('ox-grist')) as (HTMLElement & {\n dirtyRecords?: unknown[]\n urlParamsSensitive?: boolean\n reset(): void\n })[]\n return urlBound ? grids.filter(grid => grid.urlParamsSensitive) : grids\n }\n\n /** The question asked when `discards` says so: asked before an app request, or at a traversal's arrival. */\n get deactivation(): boolean | Parameters<typeof OxPrompt.open>[0] {\n if (!this.addressDirty && !this.listDirty(false)) return true\n return {\n type: 'warning',\n title: i18next.t('title.unsaved-draft', { defaultValue: 'there is an unsaved edit' }),\n text: this.addressDiscardText,\n confirmButton: { text: i18next.t('button.discard', { defaultValue: 'discard' }), destructive: true },\n cancelButton: { text: i18next.t('button.cancel', { defaultValue: 'cancel' }) }\n }\n }\n\n async canDeactivate(signal?: AbortSignal): Promise<boolean> {\n const decision = this.deactivation\n return typeof decision === 'boolean' ? decision : OxPrompt.open({ ...decision, signal })\n }\n\n protected get addressDiscardText(): string {\n return i18next.t('text.unsaved-may-be-lost', { defaultValue: 'anything not saved is lost.' })\n }\n\n /** The page's own unsaved state, apart from its grids (a modeller's model). */\n get addressDirty(): boolean {\n return false\n }\n\n protected flushAddressEdits(): void {\n const grids = Array.from(this.renderRoot.querySelectorAll('ox-grist')) as (HTMLElement & {\n flushEdits?: () => void\n })[]\n grids.forEach(grid => grid.flushEdits?.())\n }\n\n /**\n * Runs only once a change `discards` approved has committed, never while a question is pending or canceled.\n * A list query change resets only the url-bound grids: the others keep their edits.\n */\n discardAddressEdits(change?: { route: boolean }): void {\n this.listGrids(!!change && !change.route)\n .filter(grid => grid.dirtyRecords?.length)\n .forEach(grid => grid.reset())\n }\n\n /**\n * Determines whether the page should update. This method is called whenever there are\n * changes to the page's properties.\n * @param changes - A map of changed property values.\n * @returns True if the page should update, or false otherwise.\n */\n shouldUpdate(changes: PropertyValues<this>) {\n var active = String(this.active) == 'true'\n var { active: oldActive = false } = this._oldLifecycleInfo$ || {}\n\n /*\n * page lifecycle\n * case 1. page가 새로 activate 되었다.\n * case 2. page가 active 상태에서 lifecycle 정보가 바뀌었다.\n **/\n if (active) {\n this.pageUpdate({\n active\n })\n } else if (oldActive) {\n this.pageUpdate({\n active\n })\n }\n\n return active\n }\n\n /**\n * Indicates whether the page is currently active.\n */\n @property({ type: Boolean }) active: boolean = false\n\n /**\n * Stores information about the page's lifecycle.\n */\n @property({ type: Object }) lifecycle!: PageLifecycle\n\n /**\n * The context path for the page.\n */\n @property({ type: String, attribute: 'context-path' }) contextPath?: string\n\n _oldLifecycleInfo$: any\n\n /* lifecycle */\n\n /**\n * Handles page updates and lifecycle events. Subclasses can override this method\n * to implement custom logic for initializing, updating, and disposing of the page.\n * @param changes - A map of changed properties.\n * @param force - If true, forces an update of the page.\n */\n async pageUpdate(changes: any = {}, force: boolean = false) {\n var before = this._oldLifecycleInfo$ || {}\n\n var after = {\n ...before,\n ...this.lifecycle,\n contextPath: this.contextPath,\n ...changes\n }\n\n if (!('initialized' in changes) && after.active && !before.initialized) {\n after.initialized = true\n }\n\n if (force) {\n after.updated = Date.now()\n }\n\n var changed = diff(after, before)\n if (!changed) {\n return\n }\n\n this._oldLifecycleInfo$ = after\n\n /* page의 이미 초기화된 상태에서 contextPath가 바뀐다면, 무조건 page가 리셋되어야 한다. */\n if (before.initialized && changed.contextPath) {\n await this.pageReset()\n return\n }\n\n if (changed.initialized) {\n await this.pageInitialized(after)\n }\n\n if ('initialized' in changed) {\n if (changed.initialized) {\n /*\n * 방금 초기화된 경우라면, 엘리먼트들이 만들어지지 않았을 가능성이 있으므로,\n * 다음 animationFrame에서 pageUpdated 콜백을 호출한다.\n */\n requestAnimationFrame(async () => {\n await this.pageUpdated(changed, after, before)\n /* active page인 경우에는, page Context 갱신도 필요할 것이다. */\n after.active && this.updateContext()\n })\n } else {\n await this.pageDisposed(after)\n }\n } else {\n await this.pageUpdated(changed, after, before)\n /* active page인 경우에는, page Context 갱신도 필요할 것이다. */\n after.active && this.updateContext()\n }\n }\n\n /**\n * Resets the page. Subclasses can override this method to perform custom reset logic.\n */\n async pageReset() {\n var { initialized } = this._oldLifecycleInfo$ || {}\n\n if (initialized) {\n await this.pageDispose()\n await this.pageUpdate({}, true)\n }\n }\n\n /**\n * Disposes of the page. Subclasses can override this method to perform custom disposal logic.\n */\n async pageDispose() {\n await this.pageUpdate({\n initialized: false\n })\n }\n\n /**\n * Initializes the page. Subclasses can override this method to perform custom initialization logic.\n * @param pageInfo - Information about the page's state.\n */\n pageInitialized(pageInfo: any) {}\n\n /**\n * Handles page updates and changes in properties.\n * Subclasses can override this method to implement custom update logic.\n * @param changes - A map of changed properties.\n * @param after - The current state of the page.\n * @param before - The previous state of the page.\n */\n pageUpdated(changes: any, after: any, before: any) {}\n\n /**\n * Handles the disposal of the page. Subclasses can override this method\n * to implement custom disposal logic.\n * @param pageInfo - Information about the page's state.\n */\n pageDisposed(pageInfo: any) {}\n\n /* context */\n updateContext(override?: any) {\n store.dispatch({\n type: UPDATE_CONTEXT,\n context: override ? { ...this.context, ...override } : this.context\n })\n }\n\n /**\n * Updates the context of the page. Subclasses can override the `context` getter\n * to provide specific context information for the page. The context will be updated\n * using the `updateContext` method inherited from PageView.\n * @param override - An optional object with context properties to override.\n */\n get context() {\n return {}\n }\n}\n\n/** Whether the page shown at `before` stays on screen at `after`: the same path, or a path naming the same page. */\nexport function staysOn(page: PageView, after: URL, before: URL): boolean {\n if (after.origin === before.origin && after.pathname === before.pathname) return true\n const name = decodeURIComponent(getPathInfo(after.pathname).path || '').match(/^\\/([^\\/]+)/)?.[1] || ''\n return !!name && page.getAttribute('data-page') === name\n}\n"]}
1
+ {"version":3,"file":"page-view.js","sourceRoot":"","sources":["../../../../src/app/pages/page-view.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, PropertyValues, type ReactiveControllerHost } from 'lit'\nimport { property } from 'lit/decorators.js'\nimport isEqual from 'lodash-es/isEqual.js'\nimport { i18next } from '@operato/i18n'\nimport { OxPrompt } from '@operato/popup/ox-prompt.js'\n\nimport { UPDATE_CONTEXT } from '../../actions/const.js'\nimport { store } from '../../store.js'\nimport { getPathInfo } from '@operato/utils'\nimport { addressController } from '@operato/utils/address.js'\nimport { UnsavedDraftController } from '../../drafts/unsaved-draft-controller.js'\n\ntype ListDraftSource = HTMLElement &\n ReactiveControllerHost & {\n draftSnapshot?: { value: unknown; base: string | number | null }\n draftRevision: string | number | null\n dirtyRecords?: unknown[]\n restoreUnsavedDraft(value: unknown, base: string | number | null): void\n flushEdits(): void\n }\n\nexport type PageLifecycle = {\n active: boolean\n params: object\n resourceId?: string\n page?: string\n}\n\nfunction diff(after: any, before: any): any {\n var changed = false\n var changes: { [key: string]: any } = {}\n\n Object.getOwnPropertyNames(after).forEach(function (key) {\n let before_val = before[key]\n let after_val = after[key]\n\n if (!isEqual(before_val, after_val)) {\n changes[key] = after_val\n changed = true\n }\n })\n\n return changed && changes\n}\n\n/**\n * PageView is a base class for creating page elements with lifecycle management.\n * Subclasses can extend PageView to define custom behavior and handle page lifecycle events.\n */\nexport class PageView extends LitElement {\n /**\n * Closing this page instance (an MDI tab) destroys it, so its unsaved edits are asked about first: the bar\n * removes the tab only on yes. A page switch only caches the instance and asks nothing.\n */\n async confirmClose(): Promise<boolean> {\n if (!this.addressDirty && !this.listDirty(false)) return true\n if (!(await this.canDeactivate())) return false\n this.discardAddressEdits()\n return true\n }\n private listDrafts = new Map<ListDraftSource, { query: string; controller: UnsavedDraftController<unknown> }>()\n\n private listDraft = (event: Event) => {\n const { source, query, action, pathname } = (\n event as CustomEvent<{\n source: ListDraftSource\n query: string\n pathname: string\n action: 'edit' | 'loaded' | 'leave' | 'discard'\n }>\n ).detail\n let binding = this.listDrafts.get(source)\n if (binding && binding.query !== query) {\n binding.controller.dispose()\n this.listDrafts.delete(source)\n binding = undefined\n }\n if (!binding && action !== 'leave' && action !== 'discard') {\n const state = store.getState() as { auth?: { user?: { id?: string } } }\n const user = state.auth?.user?.id\n const target = JSON.stringify([\n source.id || Array.from(this.renderRoot.querySelectorAll('ox-grist')).indexOf(source),\n query\n ])\n const controller = new UnsavedDraftController(source, {\n address: () => {\n const current = store.getState() as { auth?: { user?: { id?: string } } }\n return user && current.auth?.user?.id === user\n ? { user, domain: getPathInfo(pathname).domain || '', screen: pathname, target }\n : undefined\n },\n snapshot: () => {\n source.flushEdits()\n return source.draftSnapshot\n },\n savedRevision: () => source.draftRevision,\n restore: (value, base) => source.restoreUnsavedDraft(value, base)\n })\n binding = { query, controller }\n this.listDrafts.set(source, binding)\n }\n if (!binding) return\n if (action === 'discard') void binding.controller.settled()\n if (action === 'edit') void binding.controller.flush()\n if (action === 'loaded' && this.active && pathname === location.pathname) void binding.controller.offer()\n if (action === 'leave') {\n if (source.draftSnapshot) void binding.controller.flush()\n binding.controller.dispose()\n this.listDrafts.delete(source)\n }\n }\n\n /** True only for the current edit's completed IndexedDB write; an unwritten edit still needs protection. */\n get addressEditsKept(): boolean {\n this.flushAddressEdits()\n const grids = Array.from(this.renderRoot.querySelectorAll('ox-grist')) as ListDraftSource[]\n const dirty = [...new Set([...grids, ...this.listDrafts.keys()])].filter(source => source.dirtyRecords?.length)\n return dirty.length > 0 && dirty.every(source => this.listDrafts.get(source)?.controller.keeps)\n }\n\n private queryChanged = () => {\n if (this.active) this.updateContext()\n }\n\n connectedCallback() {\n super.connectedCallback()\n this.addEventListener('query-state-change', this.queryChanged)\n this.addEventListener('list-draft', this.listDraft)\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n this.removeEventListener('query-state-change', this.queryChanged)\n for (const [source, binding] of this.listDrafts) {\n if (source.draftSnapshot) void binding.controller.flush()\n binding.controller.dispose()\n }\n this.listDrafts.clear()\n this.removeEventListener('list-draft', this.listDraft)\n }\n /**\n * Whether `change` would discard unsaved edits, so the shell asks first (address-state-ownership §6.4,\n * 2026-10-19). `stays`: this page instance stays on screen. Grid edits stay in the cached page when another\n * page is shown; they are lost when this page gets new route arguments (every grid reloads) or a new list\n * query (the url-bound grids reload). A page's own unsaved state (`addressDirty`) is asked about whenever the\n * page is left or changed, as `canDeactivate` was before 2026-10-17.\n */\n discards(change: { route: boolean; query: boolean }, stays: boolean): boolean {\n if (!change.route && !change.query) return false\n if (this.addressDirty) return true\n return stays && this.listDirty(!change.route)\n }\n\n /** Whether the page's grids hold unsaved edits - only those bound to the address when `urlBound`. */\n protected listDirty(urlBound: boolean): boolean {\n return this.listGrids(urlBound).some(grid => grid.dirtyRecords?.length)\n }\n\n private listGrids(urlBound: boolean) {\n this.flushAddressEdits()\n const grids = Array.from(this.renderRoot.querySelectorAll('ox-grist')) as (HTMLElement & {\n dirtyRecords?: unknown[]\n urlParamsSensitive?: boolean\n reset(): void\n })[]\n return urlBound ? grids.filter(grid => grid.urlParamsSensitive) : grids\n }\n\n /** The question asked when `discards` says so: asked before an app request, or at a traversal's arrival. */\n get deactivation(): boolean | Parameters<typeof OxPrompt.open>[0] {\n if (!this.addressDirty && !this.listDirty(false)) return true\n return {\n type: 'warning',\n title: i18next.t('title.unsaved-draft', { defaultValue: 'there is an unsaved edit' }),\n text: this.addressDiscardText,\n confirmButton: { text: i18next.t('button.discard', { defaultValue: 'discard' }), destructive: true },\n cancelButton: { text: i18next.t('button.cancel', { defaultValue: 'cancel' }) }\n }\n }\n\n async canDeactivate(signal?: AbortSignal): Promise<boolean> {\n const decision = this.deactivation\n return typeof decision === 'boolean' ? decision : OxPrompt.open({ ...decision, signal })\n }\n\n protected get addressDiscardText(): string {\n return i18next.t('text.unsaved-may-be-lost', { defaultValue: 'anything not saved is lost.' })\n }\n\n /** The page's own unsaved state, apart from its grids (a modeller's model). */\n get addressDirty(): boolean {\n return false\n }\n\n protected flushAddressEdits(): void {\n const grids = Array.from(this.renderRoot.querySelectorAll('ox-grist')) as (HTMLElement & {\n flushEdits?: () => void\n })[]\n grids.forEach(grid => grid.flushEdits?.())\n }\n\n /**\n * Runs only once a change `discards` approved has committed, never while a question is pending or canceled.\n * A list query change resets only the url-bound grids: the others keep their edits.\n */\n discardAddressEdits(change?: { route: boolean }): void {\n this.listGrids(!!change && !change.route)\n .filter(grid => grid.dirtyRecords?.length)\n .forEach(grid => grid.reset())\n }\n\n /**\n * Determines whether the page should update. This method is called whenever there are\n * changes to the page's properties.\n * @param changes - A map of changed property values.\n * @returns True if the page should update, or false otherwise.\n */\n shouldUpdate(changes: PropertyValues<this>) {\n var active = String(this.active) == 'true'\n var { active: oldActive = false } = this._oldLifecycleInfo$ || {}\n\n /*\n * page lifecycle\n * case 1. page가 새로 activate 되었다.\n * case 2. page가 active 상태에서 lifecycle 정보가 바뀌었다.\n **/\n if (active) {\n this.pageUpdate({\n active\n })\n } else if (oldActive) {\n this.pageUpdate({\n active\n })\n }\n\n return active\n }\n\n /**\n * Indicates whether the page is currently active.\n */\n @property({ type: Boolean }) active: boolean = false\n\n /**\n * Stores information about the page's lifecycle.\n */\n @property({ type: Object }) lifecycle!: PageLifecycle\n\n /**\n * The context path for the page.\n */\n @property({ type: String, attribute: 'context-path' }) contextPath?: string\n\n _oldLifecycleInfo$: any\n\n /* lifecycle */\n\n /** The path this page is shown at: its route arguments are what that path's claims leave of the address. */\n private shownAt?: string\n\n private unclaimed(params: Record<string, any>): Record<string, string> {\n const url = new URL(this.shownAt!, location.origin)\n url.search = new URLSearchParams(params).toString()\n return addressController().params({ ...addressController().entry, url })\n }\n\n /**\n * Handles page updates and lifecycle events. Subclasses can override this method\n * to implement custom logic for initializing, updating, and disposing of the page.\n * @param changes - A map of changed properties.\n * @param force - If true, forces an update of the page.\n */\n async pageUpdate(changes: any = {}, force: boolean = false) {\n var before = this._oldLifecycleInfo$ || {}\n\n var after = {\n ...before,\n ...this.lifecycle,\n contextPath: this.contextPath,\n ...changes\n }\n\n /*\n * Route arguments are compared under today's claims. A grid or tab claims its keys only after the page is drawn,\n * so the page opened by an address with `filters` stored them as an argument; on the next route dispatch they\n * are none. Counting that as a change made a screen read its list again and drop the edits it held.\n */\n if (after.active) this.shownAt = location.pathname\n if (this.shownAt) {\n if (before.params) before = { ...before, params: this.unclaimed(before.params) }\n if (after.params) after = { ...after, params: this.unclaimed(after.params) }\n }\n\n if (!('initialized' in changes) && after.active && !before.initialized) {\n after.initialized = true\n }\n\n if (force) {\n after.updated = Date.now()\n }\n\n var changed = diff(after, before)\n if (!changed) {\n return\n }\n\n this._oldLifecycleInfo$ = after\n\n /* page의 이미 초기화된 상태에서 contextPath가 바뀐다면, 무조건 page가 리셋되어야 한다. */\n if (before.initialized && changed.contextPath) {\n await this.pageReset()\n return\n }\n\n if (changed.initialized) {\n await this.pageInitialized(after)\n }\n\n if ('initialized' in changed) {\n if (changed.initialized) {\n /*\n * 방금 초기화된 경우라면, 엘리먼트들이 만들어지지 않았을 가능성이 있으므로,\n * 다음 animationFrame에서 pageUpdated 콜백을 호출한다.\n */\n requestAnimationFrame(async () => {\n await this.pageUpdated(changed, after, before)\n /* active page인 경우에는, page Context 갱신도 필요할 것이다. */\n after.active && this.updateContext()\n })\n } else {\n await this.pageDisposed(after)\n }\n } else {\n await this.pageUpdated(changed, after, before)\n /* active page인 경우에는, page Context 갱신도 필요할 것이다. */\n after.active && this.updateContext()\n }\n }\n\n /**\n * Resets the page. Subclasses can override this method to perform custom reset logic.\n */\n async pageReset() {\n var { initialized } = this._oldLifecycleInfo$ || {}\n\n if (initialized) {\n await this.pageDispose()\n await this.pageUpdate({}, true)\n }\n }\n\n /**\n * Disposes of the page. Subclasses can override this method to perform custom disposal logic.\n */\n async pageDispose() {\n await this.pageUpdate({\n initialized: false\n })\n }\n\n /**\n * Initializes the page. Subclasses can override this method to perform custom initialization logic.\n * @param pageInfo - Information about the page's state.\n */\n pageInitialized(pageInfo: any) {}\n\n /**\n * Handles page updates and changes in properties.\n * Subclasses can override this method to implement custom update logic.\n * @param changes - A map of changed properties.\n * @param after - The current state of the page.\n * @param before - The previous state of the page.\n */\n pageUpdated(changes: any, after: any, before: any) {}\n\n /**\n * Handles the disposal of the page. Subclasses can override this method\n * to implement custom disposal logic.\n * @param pageInfo - Information about the page's state.\n */\n pageDisposed(pageInfo: any) {}\n\n /* context */\n updateContext(override?: any) {\n store.dispatch({\n type: UPDATE_CONTEXT,\n context: override ? { ...this.context, ...override } : this.context\n })\n }\n\n /**\n * Updates the context of the page. Subclasses can override the `context` getter\n * to provide specific context information for the page. The context will be updated\n * using the `updateContext` method inherited from PageView.\n * @param override - An optional object with context properties to override.\n */\n get context() {\n return {}\n }\n}\n\n/** Whether the page shown at `before` stays on screen at `after`: the same path, or a path naming the same page. */\nexport function staysOn(page: PageView, after: URL, before: URL): boolean {\n if (after.origin === before.origin && after.pathname === before.pathname) return true\n const name = decodeURIComponent(getPathInfo(after.pathname).path || '').match(/^\\/([^\\/]+)/)?.[1] || ''\n return !!name && page.getAttribute('data-page') === name\n}\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,45 @@
1
+ import { expect, fixture } from '@open-wc/testing';
2
+ import { html } from 'lit';
3
+ import { addressController } from '@operato/utils/address.js';
4
+ import { PageView } from '../src/app/pages/page-view.js';
5
+ /*
6
+ * A page's route arguments are compared under the claims of today. A page opened by an address with `filters`
7
+ * stores them among its arguments, because its grid claims `filters` only after it is drawn; on the next route
8
+ * dispatch they are no longer an argument. That is no change of the page's arguments - a screen that reads its list
9
+ * again on one (the Office ledgers) dropped the edits it held when the user came back from another screen.
10
+ */
11
+ class Counting extends PageView {
12
+ constructor() {
13
+ super(...arguments);
14
+ this.changed = [];
15
+ }
16
+ async pageUpdated(changes) {
17
+ if (changes.params)
18
+ this.changed.push(changes.params);
19
+ }
20
+ }
21
+ customElements.define('route-claims-page', Counting);
22
+ describe('route arguments and the regions claimed after a page opened', () => {
23
+ it('a key claimed by a list after the page opened is no argument change', async () => {
24
+ const path = `/route-claims-${Math.random().toString(36).slice(2)}`;
25
+ history.replaceState({}, '', `${path}?filters=[1]&contract=one`);
26
+ const page = await fixture(html `<route-claims-page></route-claims-page>`);
27
+ page.lifecycle = { active: true, params: { filters: '[1]', contract: 'one' } };
28
+ page.active = true;
29
+ await page.updateComplete;
30
+ await new Promise(resolve => setTimeout(resolve, 0));
31
+ page.changed = [];
32
+ addressController().registerQuery(path);
33
+ page.lifecycle = { active: true, params: { contract: 'one' } };
34
+ page.requestUpdate();
35
+ await page.updateComplete;
36
+ await new Promise(resolve => setTimeout(resolve, 0));
37
+ expect(page.changed).to.deep.equal([]);
38
+ page.lifecycle = { active: true, params: { contract: 'two' } };
39
+ page.requestUpdate();
40
+ await page.updateComplete;
41
+ await new Promise(resolve => setTimeout(resolve, 0));
42
+ expect(page.changed).to.deep.equal([{ contract: 'two' }]);
43
+ });
44
+ });
45
+ //# sourceMappingURL=route-claims.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-claims.test.js","sourceRoot":"","sources":["../../test/route-claims.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAA;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAE7D,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAA;AAExD;;;;;GAKG;AAEH,MAAM,QAAS,SAAQ,QAAQ;IAA/B;;QACE,YAAO,GAAU,EAAE,CAAA;IAIrB,CAAC;IAHC,KAAK,CAAC,WAAW,CAAC,OAAY;QAC5B,IAAI,OAAO,CAAC,MAAM;YAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IACvD,CAAC;CACF;AACD,cAAc,CAAC,MAAM,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAA;AAEpD,QAAQ,CAAC,6DAA6D,EAAE,GAAG,EAAE;IAC3E,EAAE,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;QACnF,MAAM,IAAI,GAAG,iBAAiB,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;QACnE,OAAO,CAAC,YAAY,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,IAAI,2BAA2B,CAAC,CAAA;QAChE,MAAM,IAAI,GAAG,MAAM,OAAO,CAAW,IAAI,CAAA,yCAAyC,CAAC,CAAA;QACnF,IAAI,CAAC,SAAS,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAA;QAC9E,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;QAClB,MAAM,IAAI,CAAC,cAAc,CAAA;QACzB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAA;QACpD,IAAI,CAAC,OAAO,GAAG,EAAE,CAAA;QAEjB,iBAAiB,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,CAAA;QACvC,IAAI,CAAC,SAAS,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAA;QAC9D,IAAI,CAAC,aAAa,EAAE,CAAA;QACpB,MAAM,IAAI,CAAC,cAAc,CAAA;QACzB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAA;QACpD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QAEtC,IAAI,CAAC,SAAS,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAA;QAC9D,IAAI,CAAC,aAAa,EAAE,CAAA;QACpB,MAAM,IAAI,CAAC,cAAc,CAAA;QACzB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAA;QACpD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;IAC3D,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA","sourcesContent":["import { expect, fixture } from '@open-wc/testing'\nimport { html } from 'lit'\nimport { addressController } from '@operato/utils/address.js'\n\nimport { PageView } from '../src/app/pages/page-view.js'\n\n/*\n * A page's route arguments are compared under the claims of today. A page opened by an address with `filters`\n * stores them among its arguments, because its grid claims `filters` only after it is drawn; on the next route\n * dispatch they are no longer an argument. That is no change of the page's arguments - a screen that reads its list\n * again on one (the Office ledgers) dropped the edits it held when the user came back from another screen.\n */\n\nclass Counting extends PageView {\n changed: any[] = []\n async pageUpdated(changes: any) {\n if (changes.params) this.changed.push(changes.params)\n }\n}\ncustomElements.define('route-claims-page', Counting)\n\ndescribe('route arguments and the regions claimed after a page opened', () => {\n it('a key claimed by a list after the page opened is no argument change', async () => {\n const path = `/route-claims-${Math.random().toString(36).slice(2)}`\n history.replaceState({}, '', `${path}?filters=[1]&contract=one`)\n const page = await fixture<Counting>(html`<route-claims-page></route-claims-page>`)\n page.lifecycle = { active: true, params: { filters: '[1]', contract: 'one' } }\n page.active = true\n await page.updateComplete\n await new Promise(resolve => setTimeout(resolve, 0))\n page.changed = []\n\n addressController().registerQuery(path)\n page.lifecycle = { active: true, params: { contract: 'one' } }\n page.requestUpdate()\n await page.updateComplete\n await new Promise(resolve => setTimeout(resolve, 0))\n expect(page.changed).to.deep.equal([])\n\n page.lifecycle = { active: true, params: { contract: 'two' } }\n page.requestUpdate()\n await page.updateComplete\n await new Promise(resolve => setTimeout(resolve, 0))\n expect(page.changed).to.deep.equal([{ contract: 'two' }])\n })\n})\n"]}