@operato/data-grist 10.29.14 → 10.29.18
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.
- package/CHANGELOG.md +18 -0
- package/coverage/lcov-report/index.html +161 -161
- package/coverage/lcov-report/webpack/bootstrap.html +1 -1
- package/coverage/lcov-report/webpack/index.html +1 -1
- package/coverage/lcov-report/webpack/runtime/define property getters.html +1 -1
- package/coverage/lcov-report/webpack/runtime/global.html +1 -1
- package/coverage/lcov-report/webpack/runtime/hasOwnProperty shorthand.html +1 -1
- package/coverage/lcov-report/webpack/runtime/index.html +1 -1
- package/coverage/lcov-report/webpack/runtime/make namespace object.html +1 -1
- package/coverage/lcov.info +37856 -37153
- package/dist/src/filters/filters-form.js +33 -47
- package/dist/src/filters/filters-form.js.map +1 -1
- package/dist/src/record-view/event-handlers/record-view-body-click-handler.d.ts +1 -1
- package/dist/src/record-view/event-handlers/record-view-body-click-handler.js +23 -1
- package/dist/src/record-view/event-handlers/record-view-body-click-handler.js.map +1 -1
- package/dist/test/filter-labels.test.d.ts +2 -0
- package/dist/test/filter-labels.test.js +60 -0
- package/dist/test/filter-labels.test.js.map +1 -0
- package/dist/test/record-view-popup-editor.test.d.ts +1 -0
- package/dist/test/record-view-popup-editor.test.js +58 -0
- package/dist/test/record-view-popup-editor.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -6
- package/test/filter-labels.test.ts +68 -0
- package/test/record-view-popup-editor.test.ts +68 -0
|
@@ -169,55 +169,41 @@ let OxFiltersForm = class OxFiltersForm extends LitElement {
|
|
|
169
169
|
if (!renderer) {
|
|
170
170
|
return html ``;
|
|
171
171
|
}
|
|
172
|
-
|
|
172
|
+
if (type === 'boolean' || type === 'checkbox') {
|
|
173
|
+
return renderer(column, value, this);
|
|
174
|
+
}
|
|
175
|
+
const chooser = type !== 'select'
|
|
173
176
|
? renderer(column, value, this)
|
|
174
|
-
:
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
operator,
|
|
192
|
-
value: e.detail
|
|
193
|
-
}
|
|
194
|
-
}));
|
|
195
|
-
}}
|
|
196
|
-
>
|
|
197
|
-
<ox-popup-list multiple attr-selected="checked" with-search>
|
|
177
|
+
: html `
|
|
178
|
+
<ox-select
|
|
179
|
+
name=${name}
|
|
180
|
+
.value=${value}
|
|
181
|
+
@change=${(e) => {
|
|
182
|
+
var _a;
|
|
183
|
+
return (_a = e.target) === null || _a === void 0 ? void 0 : _a.dispatchEvent(new CustomEvent('filter-change', {
|
|
184
|
+
detail: {
|
|
185
|
+
name,
|
|
186
|
+
operator,
|
|
187
|
+
value: e.detail
|
|
188
|
+
}
|
|
189
|
+
}));
|
|
190
|
+
}}
|
|
191
|
+
>
|
|
192
|
+
${operator === 'in'
|
|
193
|
+
? html `<ox-popup-list multiple attr-selected="checked" with-search>
|
|
198
194
|
${renderer(column, value, this)}
|
|
199
|
-
</ox-popup-list
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
name,
|
|
212
|
-
operator,
|
|
213
|
-
value: e.detail
|
|
214
|
-
}
|
|
215
|
-
}));
|
|
216
|
-
}}
|
|
217
|
-
>
|
|
218
|
-
<ox-popup-list with-search> ${renderer(column, value, this)} </ox-popup-list>
|
|
219
|
-
</ox-select>
|
|
220
|
-
`;
|
|
195
|
+
</ox-popup-list>`
|
|
196
|
+
: html `<ox-popup-list with-search> ${renderer(column, value, this)} </ox-popup-list>`}
|
|
197
|
+
</ox-select>
|
|
198
|
+
`;
|
|
199
|
+
/*
|
|
200
|
+
* Every filter says what it filters, beside its chooser - a select too. A select used to carry its
|
|
201
|
+
* name only as a placeholder, which a chosen value replaces: the bar then showed 「진행 중」 with
|
|
202
|
+
* nothing saying it was the status.
|
|
203
|
+
*/
|
|
204
|
+
return labelText
|
|
205
|
+
? html `<label filter-title ?between=${operator === 'between'}><span>${labelText}</span> ${chooser}</label> `
|
|
206
|
+
: chooser;
|
|
221
207
|
})}
|
|
222
208
|
</form>
|
|
223
209
|
</div>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filters-form.js","sourceRoot":"","sources":["../../../src/filters/filters-form.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/input/ox-checkbox.js'\nimport '@operato/input/ox-select.js'\nimport '@operato/popup/ox-popup-list.js'\nimport '@operato/input/ox-input-search.js'\n\nimport { css, html, LitElement, PropertyValues, TemplateResult, nothing } from 'lit'\nimport { customElement, property, queryAsync, state } from 'lit/decorators.js'\nimport { i18next } from '@operato/i18n'\nimport { isMobileDevice } from '@operato/utils'\nimport { styles as MDTypeScaleStyles } from '@material/web/typography/md-typescale-styles.js'\n\nimport { PagePreferenceProvider } from '@operato/p13n'\nimport { getDefaultValue } from '@operato/time-calculator'\n\nimport {\n ColumnConfig,\n FilterConfigObject,\n FilterPreference,\n FilterOperator,\n FilterValue,\n GristConfig,\n PersonalGristPreference\n} from '../types.js'\nimport { DataGrist } from '../data-grist.js'\nimport { FilterStyles } from './filter-styles.js'\nimport { getFilterRenderer } from './registry.js'\n\nexport type QueryFilterRangeValue = [from: number, to: number]\n\nexport type QueryFilter = {\n name: string\n operator: FilterOperator\n value: any\n}\n\n@customElement('ox-filters-form')\nexport class OxFiltersForm extends LitElement {\n static styles = [\n MDTypeScaleStyles,\n FilterStyles,\n css`\n :host {\n display: flex;\n padding: var(--spacing-small);\n }\n\n form {\n flex: 1;\n\n display: flex;\n flex-flow: row wrap;\n gap: var(--ox-filters-form-gap);\n }\n\n form > * {\n display: flex;\n align-items: center;\n gap: var(--input-intra-gap, 7px);\n }\n\n label span {\n display: block;\n }\n\n /* 모바일 필터 아코디언 토글 */\n .filters-toggle {\n display: none;\n }\n\n .filters-mobile-fold {\n flex: 1;\n display: contents;\n }\n\n @media only screen and (max-width: 460px) {\n :host([mobile-fold]) {\n flex-direction: column;\n }\n\n form {\n flex-direction: column;\n flex-flow: column;\n }\n\n :host([mobile-fold]) .filters-toggle {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 6px 0;\n cursor: pointer;\n font-size: 14px;\n color: var(--secondary-color, #666);\n }\n\n :host([mobile-fold]) .filters-toggle md-icon {\n font-size: 18px;\n transition: transform 0.2s;\n }\n\n :host([mobile-fold]) .filters-toggle[open] md-icon {\n transform: rotate(180deg);\n }\n\n :host([mobile-fold]) .filters-mobile-fold {\n display: block;\n overflow: hidden;\n max-height: 0;\n transition: max-height 0.3s ease;\n }\n\n :host([mobile-fold]) .filters-mobile-fold[open] {\n max-height: 500px;\n }\n }\n `\n ]\n\n @property({ type: Array }) value: FilterValue[] = []\n @property({ type: Boolean, attribute: 'without-search' }) withoutSearch: boolean = false\n @property({ type: Boolean, attribute: 'autofocus' }) autofocus: boolean = true\n @property({ type: Boolean, attribute: 'empty', reflect: true }) empty: boolean = true\n @property({ type: Boolean, attribute: 'mobile-fold', reflect: true }) mobileFold: boolean = false\n\n @state() private _filtersOpen: boolean = true\n\n @state() personalConfigProvider?: PagePreferenceProvider\n @state() personalConfig?: PersonalGristPreference\n @state() personalFilters?: FilterPreference[]\n\n @state() config!: GristConfig\n @state() filterColumns: ColumnConfig[] = []\n @state() searchColumns: ColumnConfig[] = []\n\n @queryAsync('form') form!: HTMLFormElement\n\n private autoUpdateTargetsOnChange: { [name: string]: string[] } = {}\n private objectValue?: object\n\n connectedCallback(): void {\n super.connectedCallback()\n\n /* 모바일에서 mobile-fold 모드일 때 필터 접힌 상태로 시작 */\n if (this.mobileFold && isMobileDevice()) {\n this._filtersOpen = false\n }\n\n const grist = this.closest('ox-grist') as DataGrist\n\n if (grist) {\n this.config = grist.compiledConfig\n this.personalConfigProvider = grist.personalConfigProvider\n\n grist.addEventListener('config-change', (e: Event) => {\n this.config = (e as CustomEvent).detail\n })\n\n grist.addEventListener('fetch-params-change', (e: Event) => {\n const { filters, from } = (e as CustomEvent).detail || {}\n if (from === 'filters-form') {\n return\n }\n\n this.value = filters\n })\n\n this.renderRoot.addEventListener('change', async (e: Event) => {\n const { target, detail: value } = e as CustomEvent\n const name = (target as HTMLInputElement).name\n const { filter } = this.filterColumns.find(filter => filter.name == name) || {}\n\n if (this.autoUpdateTargetsOnChange[name]) {\n /* 일단은 심플하게, boundTo로 연결된 필터값이 바뀌면, 폼 전체를 update하도록 함. */\n ;(this.autoUpdateTargetsOnChange[name] || []).forEach(name => {\n const target = this.renderRoot.querySelector(`[name='${name}']`)\n if (target) {\n ;(target as HTMLInputElement).value = ''\n }\n })\n\n await this.updateObjectValues()\n this.requestUpdate()\n }\n\n const onchange = typeof filter == 'object' ? filter.onchange : null\n const keepGoing = onchange ? await onchange.call(null, value ?? (target as HTMLInputElement).value, this) : true\n\n keepGoing &&\n this.dispatchEvent(\n new CustomEvent('fetch-params-change', {\n bubbles: true,\n composed: true,\n detail: {\n filters: await this.getQueryFilters(),\n from: 'filters-form'\n }\n })\n )\n })\n }\n\n // filter에 있는 캘린더 타입 input에 클릭 시 캘린더 오픈 이벤트 추가\n this.renderRoot.addEventListener('click', (e: Event) => {\n const target = e.target as HTMLInputElement\n if (target.matches('[type=\"date\"], [type=\"time\"], [type=\"datetime-local\"], [type=\"month\"], [type=\"week\"]')) {\n target.showPicker()\n }\n })\n\n if (this.autofocus) {\n setTimeout(() => {\n this.focusFirstFormControl()\n }, 100)\n }\n }\n\n buildDefaultValue(operator: FilterOperator, defaultValue: any) {\n if (defaultValue === undefined) {\n return\n }\n if (operator == 'between') {\n return (defaultValue as Array<any>).map(v => getDefaultValue(v, this))\n } else {\n return getDefaultValue(defaultValue, this)\n }\n }\n\n async updated(changes: PropertyValues<this>) {\n /*\n * ── 둘을 함께 본다 — `else if` 가 설정 변화를 삼켰다 ───────────────────────\n *\n * 이 폼은 붙는 순간(`connectedCallback`)에 표에게서 설정과 개인 설정 제공자를 **한 번에**\n * 받는다. 그래서 첫 갱신에는 두 변화가 같은 주기에 들어온다.\n *\n * `else if` 였을 때는 앞 가지가 이겨서 **그 주기의 설정 변화가 버려졌다.** 표가 설정을 늦게\n * 주는 화면(참조 고르기 팝업)에서 필터 영역이 빈 채로 남던 이유가 이것이다.\n */\n if (changes.has('personalConfigProvider') && this.personalConfigProvider) {\n this.personalConfig = await this.personalConfigProvider.load()\n }\n\n if (changes.has('config') || changes.has('personalConfig')) {\n this.applyUpdatedConfiguration()\n }\n }\n\n render(): TemplateResult {\n const searchValue =\n (this.value?.find(filter => filter.operator === 'search')?.value as string)?.match(/^\\%(.*)\\%$/)?.[1] || ''\n\n return this.empty\n ? html``\n : html`\n <div\n class=\"filters-toggle\"\n ?open=${this._filtersOpen}\n @click=${() => {\n this._filtersOpen = !this._filtersOpen\n this.requestUpdate()\n }}\n >\n <md-icon>expand_more</md-icon>\n ${i18next.t('label.filter')}\n </div>\n <div class=\"filters-mobile-fold\" ?open=${this._filtersOpen}>\n <form\n class=\"md-typescale-body-medium-prominent\"\n @submit=${(e: Event) => {\n e.stopPropagation()\n e.preventDefault()\n\n const grist = this.closest('ox-grist') as DataGrist\n\n /* fetchFailed has already drawn a failure on the grid; this only stops an unhandled rejection. */\n grist && grist.fetch().catch(() => {})\n }}\n >\n ${this.filterColumns\n .filter(column => !(column.filter as FilterConfigObject).hidden)\n .map((column: ColumnConfig) => {\n const { name, header, label, filter } = column\n\n const type = (filter as FilterConfigObject).type\n\n if (type == 'search') {\n return html`\n <ox-input-search name=\"search\" .value=${searchValue} ?autofocus=${this.autofocus}></ox-input-search>\n `\n }\n\n const operator = (filter as FilterConfigObject).operator\n const filterLabel = (filter as FilterConfigObject).label\n\n const labelText =\n filterLabel !== undefined\n ? filterLabel\n : typeof label === 'object' && label.renderer\n ? label.renderer(column)\n : header.renderer(column) || name\n\n const idx = operator === 'between' ? 1 : 0\n const renderer = getFilterRenderer(\n operator === 'like' || operator === 'i_like' || operator === 'i_nlike' || operator === 'nlike'\n ? 'text'\n : type\n )[idx]\n const value =\n this.value?.find(filter => filter.name == name)?.value ??\n this.buildDefaultValue(operator!, (filter as FilterConfigObject)?.value)\n\n if (!renderer) {\n return html``\n }\n\n return type === 'boolean' || type === 'checkbox'\n ? renderer(column, value, this)\n : type !== 'select' && labelText\n ? html`<label filter-title ?between=${operator === 'between'}\n ><span>${labelText}</span> ${renderer(column, value, this)}\n </label> `\n : type !== 'select' && !labelText\n ? renderer(column, value, this)\n : operator === 'in'\n ? html`\n <ox-select\n name=${name}\n placeholder=${labelText}\n .value=${value}\n @change=${(e: CustomEvent) =>\n e.target?.dispatchEvent(\n new CustomEvent('filter-change', {\n detail: {\n name,\n operator,\n value: e.detail\n }\n })\n )}\n >\n <ox-popup-list multiple attr-selected=\"checked\" with-search>\n ${renderer(column, value, this)}\n </ox-popup-list>\n </ox-select>\n `\n : html`\n <ox-select\n name=${name}\n placeholder=${labelText}\n .value=${value}\n @change=${(e: CustomEvent) =>\n e.target?.dispatchEvent(\n new CustomEvent('filter-change', {\n detail: {\n name,\n operator,\n value: e.detail\n }\n })\n )}\n >\n <ox-popup-list with-search> ${renderer(column, value, this)} </ox-popup-list>\n </ox-select>\n `\n })}\n </form>\n </div>\n <slot name=\"setting\"></slot>\n `\n }\n\n applyUpdatedConfiguration() {\n if (!this.config) {\n return\n }\n\n const filters = this.config.columns.filter(columnConfig => !!columnConfig.filter)\n\n this.filterColumns = filters.filter((columnConfig: ColumnConfig) => {\n const filter = columnConfig.filter as FilterConfigObject\n return filter!.operator !== 'search'\n })\n this.searchColumns = filters.filter(columnConfig => {\n const filter = columnConfig.filter as FilterConfigObject\n return filter!.operator === 'search'\n })\n\n if (this.searchColumns.length > 0 && !this.withoutSearch) {\n this.filterColumns.unshift({ name: 'search', filter: { type: 'search' } } as any)\n }\n\n if (!this.personalConfig) {\n this.personalFilters = this.filterColumns.map(column => {\n return { name: column.name }\n })\n } else {\n const { filters: personalFilters = [] } = this.personalConfig\n\n if (personalFilters) {\n const xfilters = this.filterColumns.map(column => {\n return personalFilters.find(pFilter => pFilter.name == column.name) || { name: column.name }\n })\n\n function reorderList(a: FilterPreference[], b: FilterPreference[]): FilterPreference[] {\n // 결과 배열 초기화, a 배열 길이만큼 undefined로 채움\n const result = new Array(a.length)\n\n // b 배열에 없는 아이템은 원래 위치로 채움\n a.forEach((item, index) => {\n if (!item.name || !b.find(bi => bi.name == item.name)) {\n result[index] = item\n }\n })\n\n b.forEach(item => {\n const ai = a.find(ai => ai.name == item.name)\n if (ai) {\n result[result.findIndex(slot => slot === undefined)] = ai\n }\n })\n\n return result\n }\n\n // 배열 재정렬 실행\n this.personalFilters = reorderList(xfilters as any, personalFilters as any) as FilterPreference[]\n\n this.filterColumns = this.personalFilters\n .map(filter => {\n const column = this.filterColumns.find(column => column.name == filter.name)\n if (column?.filter) {\n ;(column.filter as FilterConfigObject)!.hidden = filter.hidden\n }\n return column\n })\n .filter(Boolean) as ColumnConfig[]\n }\n }\n\n const grist = this.closest('ox-grist') as DataGrist\n\n this.value = (grist?.filters || []).map(filter => {\n return {\n ...filter,\n value: this.buildDefaultValue(filter!.operator, filter!.value)\n }\n })\n\n this.empty = (this.searchColumns.length === 0 || this.withoutSearch) && this.filterColumns.length === 0\n\n this.autoUpdateTargetsOnChange = {}\n this.filterColumns\n ?.filter(({ filter }) => {\n return typeof filter == 'object' && filter.boundTo && filter.boundTo.length > 0\n })\n .map(({ name, filter }) => {\n const boundTo = (filter as FilterConfigObject).boundTo\n\n boundTo!.forEach(to => {\n const origin = this.autoUpdateTargetsOnChange[to] || []\n if (name && !origin.includes(name)) {\n this.autoUpdateTargetsOnChange[to] = [...origin, name]\n }\n })\n })\n }\n\n async getQueryFilters(): Promise<QueryFilter[]> {\n const form = await this.form\n if (!form) return []\n\n const formData = new FormData(form)\n const search: string | undefined = formData.get('search')?.toString()\n\n var filters = this.filterColumns\n .filter(column => column.name !== 'search' && !(column.filter as FilterConfigObject)!.hidden)\n .map((column: ColumnConfig) => {\n const { name, type, filter } = column\n const operator = (filter as FilterConfigObject).operator\n\n var value = formData.getAll(name)\n if (value.length == 0) {\n return\n }\n\n if (-1 === value.findIndex(v => v !== '')) {\n return\n }\n\n const filterValue = value.map(v => {\n const value = v.toString()\n\n /* TODO registry에서 타입별로 parsing 방법을 지정할 수 있도록 해야한다. */\n switch (type) {\n case 'integer':\n case 'float':\n case 'number':\n case 'progress':\n case 'checkbox':\n case 'boolean':\n return !value ? undefined : JSON.parse(value)\n default:\n return value\n }\n })\n\n return {\n name,\n operator,\n value: filterValue.length === 1 ? filterValue[0] : filterValue\n }\n })\n .filter(result => result !== undefined) as QueryFilter[]\n\n if (search) {\n filters = filters.concat(\n this.searchColumns.map((column: ColumnConfig) => {\n const { name } = column\n\n return {\n name,\n operator: 'search',\n value: `%${search}%`\n }\n })\n )\n }\n\n return filters\n }\n\n public setInputValue(name: string, value: any) {\n const input = this.renderRoot.querySelector(`form [name=\"${name}\"]`) as HTMLInputElement\n if (input) {\n input.value = value\n input.dispatchEvent(new Event('change', { bubbles: true }))\n }\n }\n\n public getInputValue(name: string): any {\n const input = this.renderRoot.querySelector(`form [name=\"${name}\"]`) as HTMLInputElement\n return input?.value\n }\n\n private async focusFirstFormControl() {\n const form = await this.form\n if (!form) return\n\n // 첫번째가 input이면 autofocus, ox-input-search는 프로퍼티로 포커스 셋팅\n const target = form.querySelector('ox-input-search, input:not([type=\"hidden\"]):not(:disabled)') as HTMLInputElement\n if (target && target.tagName !== 'OX-INPUT-SEARCH') {\n target.focus()\n }\n }\n\n private async updateObjectValues() {\n const form = await this.form\n if (!form) return []\n\n const formData = new FormData(form)\n\n const object = {} as any\n formData.forEach((value, key) => {\n const prev = object[key]\n\n if (key in object) {\n object[key] = prev instanceof Array ? [...prev, value] : [prev, value]\n } else {\n object[key] = value\n }\n })\n\n this.objectValue = object\n }\n\n public getFormObjectValue() {\n return this.objectValue\n }\n\n reset() {\n this.form\n .then((form: HTMLFormElement) => {\n form.reset()\n })\n .catch((error: any) => {\n console.error('Error resetting the form:', error)\n })\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"filters-form.js","sourceRoot":"","sources":["../../../src/filters/filters-form.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/input/ox-checkbox.js'\nimport '@operato/input/ox-select.js'\nimport '@operato/popup/ox-popup-list.js'\nimport '@operato/input/ox-input-search.js'\n\nimport { css, html, LitElement, PropertyValues, TemplateResult, nothing } from 'lit'\nimport { customElement, property, queryAsync, state } from 'lit/decorators.js'\nimport { i18next } from '@operato/i18n'\nimport { isMobileDevice } from '@operato/utils'\nimport { styles as MDTypeScaleStyles } from '@material/web/typography/md-typescale-styles.js'\n\nimport { PagePreferenceProvider } from '@operato/p13n'\nimport { getDefaultValue } from '@operato/time-calculator'\n\nimport {\n ColumnConfig,\n FilterConfigObject,\n FilterPreference,\n FilterOperator,\n FilterValue,\n GristConfig,\n PersonalGristPreference\n} from '../types.js'\nimport { DataGrist } from '../data-grist.js'\nimport { FilterStyles } from './filter-styles.js'\nimport { getFilterRenderer } from './registry.js'\n\nexport type QueryFilterRangeValue = [from: number, to: number]\n\nexport type QueryFilter = {\n name: string\n operator: FilterOperator\n value: any\n}\n\n@customElement('ox-filters-form')\nexport class OxFiltersForm extends LitElement {\n static styles = [\n MDTypeScaleStyles,\n FilterStyles,\n css`\n :host {\n display: flex;\n padding: var(--spacing-small);\n }\n\n form {\n flex: 1;\n\n display: flex;\n flex-flow: row wrap;\n gap: var(--ox-filters-form-gap);\n }\n\n form > * {\n display: flex;\n align-items: center;\n gap: var(--input-intra-gap, 7px);\n }\n\n label span {\n display: block;\n }\n\n /* 모바일 필터 아코디언 토글 */\n .filters-toggle {\n display: none;\n }\n\n .filters-mobile-fold {\n flex: 1;\n display: contents;\n }\n\n @media only screen and (max-width: 460px) {\n :host([mobile-fold]) {\n flex-direction: column;\n }\n\n form {\n flex-direction: column;\n flex-flow: column;\n }\n\n :host([mobile-fold]) .filters-toggle {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 6px 0;\n cursor: pointer;\n font-size: 14px;\n color: var(--secondary-color, #666);\n }\n\n :host([mobile-fold]) .filters-toggle md-icon {\n font-size: 18px;\n transition: transform 0.2s;\n }\n\n :host([mobile-fold]) .filters-toggle[open] md-icon {\n transform: rotate(180deg);\n }\n\n :host([mobile-fold]) .filters-mobile-fold {\n display: block;\n overflow: hidden;\n max-height: 0;\n transition: max-height 0.3s ease;\n }\n\n :host([mobile-fold]) .filters-mobile-fold[open] {\n max-height: 500px;\n }\n }\n `\n ]\n\n @property({ type: Array }) value: FilterValue[] = []\n @property({ type: Boolean, attribute: 'without-search' }) withoutSearch: boolean = false\n @property({ type: Boolean, attribute: 'autofocus' }) autofocus: boolean = true\n @property({ type: Boolean, attribute: 'empty', reflect: true }) empty: boolean = true\n @property({ type: Boolean, attribute: 'mobile-fold', reflect: true }) mobileFold: boolean = false\n\n @state() private _filtersOpen: boolean = true\n\n @state() personalConfigProvider?: PagePreferenceProvider\n @state() personalConfig?: PersonalGristPreference\n @state() personalFilters?: FilterPreference[]\n\n @state() config!: GristConfig\n @state() filterColumns: ColumnConfig[] = []\n @state() searchColumns: ColumnConfig[] = []\n\n @queryAsync('form') form!: HTMLFormElement\n\n private autoUpdateTargetsOnChange: { [name: string]: string[] } = {}\n private objectValue?: object\n\n connectedCallback(): void {\n super.connectedCallback()\n\n /* 모바일에서 mobile-fold 모드일 때 필터 접힌 상태로 시작 */\n if (this.mobileFold && isMobileDevice()) {\n this._filtersOpen = false\n }\n\n const grist = this.closest('ox-grist') as DataGrist\n\n if (grist) {\n this.config = grist.compiledConfig\n this.personalConfigProvider = grist.personalConfigProvider\n\n grist.addEventListener('config-change', (e: Event) => {\n this.config = (e as CustomEvent).detail\n })\n\n grist.addEventListener('fetch-params-change', (e: Event) => {\n const { filters, from } = (e as CustomEvent).detail || {}\n if (from === 'filters-form') {\n return\n }\n\n this.value = filters\n })\n\n this.renderRoot.addEventListener('change', async (e: Event) => {\n const { target, detail: value } = e as CustomEvent\n const name = (target as HTMLInputElement).name\n const { filter } = this.filterColumns.find(filter => filter.name == name) || {}\n\n if (this.autoUpdateTargetsOnChange[name]) {\n /* 일단은 심플하게, boundTo로 연결된 필터값이 바뀌면, 폼 전체를 update하도록 함. */\n ;(this.autoUpdateTargetsOnChange[name] || []).forEach(name => {\n const target = this.renderRoot.querySelector(`[name='${name}']`)\n if (target) {\n ;(target as HTMLInputElement).value = ''\n }\n })\n\n await this.updateObjectValues()\n this.requestUpdate()\n }\n\n const onchange = typeof filter == 'object' ? filter.onchange : null\n const keepGoing = onchange ? await onchange.call(null, value ?? (target as HTMLInputElement).value, this) : true\n\n keepGoing &&\n this.dispatchEvent(\n new CustomEvent('fetch-params-change', {\n bubbles: true,\n composed: true,\n detail: {\n filters: await this.getQueryFilters(),\n from: 'filters-form'\n }\n })\n )\n })\n }\n\n // filter에 있는 캘린더 타입 input에 클릭 시 캘린더 오픈 이벤트 추가\n this.renderRoot.addEventListener('click', (e: Event) => {\n const target = e.target as HTMLInputElement\n if (target.matches('[type=\"date\"], [type=\"time\"], [type=\"datetime-local\"], [type=\"month\"], [type=\"week\"]')) {\n target.showPicker()\n }\n })\n\n if (this.autofocus) {\n setTimeout(() => {\n this.focusFirstFormControl()\n }, 100)\n }\n }\n\n buildDefaultValue(operator: FilterOperator, defaultValue: any) {\n if (defaultValue === undefined) {\n return\n }\n if (operator == 'between') {\n return (defaultValue as Array<any>).map(v => getDefaultValue(v, this))\n } else {\n return getDefaultValue(defaultValue, this)\n }\n }\n\n async updated(changes: PropertyValues<this>) {\n /*\n * ── 둘을 함께 본다 — `else if` 가 설정 변화를 삼켰다 ───────────────────────\n *\n * 이 폼은 붙는 순간(`connectedCallback`)에 표에게서 설정과 개인 설정 제공자를 **한 번에**\n * 받는다. 그래서 첫 갱신에는 두 변화가 같은 주기에 들어온다.\n *\n * `else if` 였을 때는 앞 가지가 이겨서 **그 주기의 설정 변화가 버려졌다.** 표가 설정을 늦게\n * 주는 화면(참조 고르기 팝업)에서 필터 영역이 빈 채로 남던 이유가 이것이다.\n */\n if (changes.has('personalConfigProvider') && this.personalConfigProvider) {\n this.personalConfig = await this.personalConfigProvider.load()\n }\n\n if (changes.has('config') || changes.has('personalConfig')) {\n this.applyUpdatedConfiguration()\n }\n }\n\n render(): TemplateResult {\n const searchValue =\n (this.value?.find(filter => filter.operator === 'search')?.value as string)?.match(/^\\%(.*)\\%$/)?.[1] || ''\n\n return this.empty\n ? html``\n : html`\n <div\n class=\"filters-toggle\"\n ?open=${this._filtersOpen}\n @click=${() => {\n this._filtersOpen = !this._filtersOpen\n this.requestUpdate()\n }}\n >\n <md-icon>expand_more</md-icon>\n ${i18next.t('label.filter')}\n </div>\n <div class=\"filters-mobile-fold\" ?open=${this._filtersOpen}>\n <form\n class=\"md-typescale-body-medium-prominent\"\n @submit=${(e: Event) => {\n e.stopPropagation()\n e.preventDefault()\n\n const grist = this.closest('ox-grist') as DataGrist\n\n /* fetchFailed has already drawn a failure on the grid; this only stops an unhandled rejection. */\n grist && grist.fetch().catch(() => {})\n }}\n >\n ${this.filterColumns\n .filter(column => !(column.filter as FilterConfigObject).hidden)\n .map((column: ColumnConfig) => {\n const { name, header, label, filter } = column\n\n const type = (filter as FilterConfigObject).type\n\n if (type == 'search') {\n return html`\n <ox-input-search name=\"search\" .value=${searchValue} ?autofocus=${this.autofocus}></ox-input-search>\n `\n }\n\n const operator = (filter as FilterConfigObject).operator\n const filterLabel = (filter as FilterConfigObject).label\n\n const labelText =\n filterLabel !== undefined\n ? filterLabel\n : typeof label === 'object' && label.renderer\n ? label.renderer(column)\n : header.renderer(column) || name\n\n const idx = operator === 'between' ? 1 : 0\n const renderer = getFilterRenderer(\n operator === 'like' || operator === 'i_like' || operator === 'i_nlike' || operator === 'nlike'\n ? 'text'\n : type\n )[idx]\n const value =\n this.value?.find(filter => filter.name == name)?.value ??\n this.buildDefaultValue(operator!, (filter as FilterConfigObject)?.value)\n\n if (!renderer) {\n return html``\n }\n\n if (type === 'boolean' || type === 'checkbox') {\n return renderer(column, value, this)\n }\n\n const chooser =\n type !== 'select'\n ? renderer(column, value, this)\n : html`\n <ox-select\n name=${name}\n .value=${value}\n @change=${(e: CustomEvent) =>\n e.target?.dispatchEvent(\n new CustomEvent('filter-change', {\n detail: {\n name,\n operator,\n value: e.detail\n }\n })\n )}\n >\n ${operator === 'in'\n ? html`<ox-popup-list multiple attr-selected=\"checked\" with-search>\n ${renderer(column, value, this)}\n </ox-popup-list>`\n : html`<ox-popup-list with-search> ${renderer(column, value, this)} </ox-popup-list>`}\n </ox-select>\n `\n\n /*\n * Every filter says what it filters, beside its chooser - a select too. A select used to carry its\n * name only as a placeholder, which a chosen value replaces: the bar then showed 「진행 중」 with\n * nothing saying it was the status.\n */\n return labelText\n ? html`<label filter-title ?between=${operator === 'between'}><span>${labelText}</span> ${chooser}</label> `\n : chooser\n })}\n </form>\n </div>\n <slot name=\"setting\"></slot>\n `\n }\n\n applyUpdatedConfiguration() {\n if (!this.config) {\n return\n }\n\n const filters = this.config.columns.filter(columnConfig => !!columnConfig.filter)\n\n this.filterColumns = filters.filter((columnConfig: ColumnConfig) => {\n const filter = columnConfig.filter as FilterConfigObject\n return filter!.operator !== 'search'\n })\n this.searchColumns = filters.filter(columnConfig => {\n const filter = columnConfig.filter as FilterConfigObject\n return filter!.operator === 'search'\n })\n\n if (this.searchColumns.length > 0 && !this.withoutSearch) {\n this.filterColumns.unshift({ name: 'search', filter: { type: 'search' } } as any)\n }\n\n if (!this.personalConfig) {\n this.personalFilters = this.filterColumns.map(column => {\n return { name: column.name }\n })\n } else {\n const { filters: personalFilters = [] } = this.personalConfig\n\n if (personalFilters) {\n const xfilters = this.filterColumns.map(column => {\n return personalFilters.find(pFilter => pFilter.name == column.name) || { name: column.name }\n })\n\n function reorderList(a: FilterPreference[], b: FilterPreference[]): FilterPreference[] {\n // 결과 배열 초기화, a 배열 길이만큼 undefined로 채움\n const result = new Array(a.length)\n\n // b 배열에 없는 아이템은 원래 위치로 채움\n a.forEach((item, index) => {\n if (!item.name || !b.find(bi => bi.name == item.name)) {\n result[index] = item\n }\n })\n\n b.forEach(item => {\n const ai = a.find(ai => ai.name == item.name)\n if (ai) {\n result[result.findIndex(slot => slot === undefined)] = ai\n }\n })\n\n return result\n }\n\n // 배열 재정렬 실행\n this.personalFilters = reorderList(xfilters as any, personalFilters as any) as FilterPreference[]\n\n this.filterColumns = this.personalFilters\n .map(filter => {\n const column = this.filterColumns.find(column => column.name == filter.name)\n if (column?.filter) {\n ;(column.filter as FilterConfigObject)!.hidden = filter.hidden\n }\n return column\n })\n .filter(Boolean) as ColumnConfig[]\n }\n }\n\n const grist = this.closest('ox-grist') as DataGrist\n\n this.value = (grist?.filters || []).map(filter => {\n return {\n ...filter,\n value: this.buildDefaultValue(filter!.operator, filter!.value)\n }\n })\n\n this.empty = (this.searchColumns.length === 0 || this.withoutSearch) && this.filterColumns.length === 0\n\n this.autoUpdateTargetsOnChange = {}\n this.filterColumns\n ?.filter(({ filter }) => {\n return typeof filter == 'object' && filter.boundTo && filter.boundTo.length > 0\n })\n .map(({ name, filter }) => {\n const boundTo = (filter as FilterConfigObject).boundTo\n\n boundTo!.forEach(to => {\n const origin = this.autoUpdateTargetsOnChange[to] || []\n if (name && !origin.includes(name)) {\n this.autoUpdateTargetsOnChange[to] = [...origin, name]\n }\n })\n })\n }\n\n async getQueryFilters(): Promise<QueryFilter[]> {\n const form = await this.form\n if (!form) return []\n\n const formData = new FormData(form)\n const search: string | undefined = formData.get('search')?.toString()\n\n var filters = this.filterColumns\n .filter(column => column.name !== 'search' && !(column.filter as FilterConfigObject)!.hidden)\n .map((column: ColumnConfig) => {\n const { name, type, filter } = column\n const operator = (filter as FilterConfigObject).operator\n\n var value = formData.getAll(name)\n if (value.length == 0) {\n return\n }\n\n if (-1 === value.findIndex(v => v !== '')) {\n return\n }\n\n const filterValue = value.map(v => {\n const value = v.toString()\n\n /* TODO registry에서 타입별로 parsing 방법을 지정할 수 있도록 해야한다. */\n switch (type) {\n case 'integer':\n case 'float':\n case 'number':\n case 'progress':\n case 'checkbox':\n case 'boolean':\n return !value ? undefined : JSON.parse(value)\n default:\n return value\n }\n })\n\n return {\n name,\n operator,\n value: filterValue.length === 1 ? filterValue[0] : filterValue\n }\n })\n .filter(result => result !== undefined) as QueryFilter[]\n\n if (search) {\n filters = filters.concat(\n this.searchColumns.map((column: ColumnConfig) => {\n const { name } = column\n\n return {\n name,\n operator: 'search',\n value: `%${search}%`\n }\n })\n )\n }\n\n return filters\n }\n\n public setInputValue(name: string, value: any) {\n const input = this.renderRoot.querySelector(`form [name=\"${name}\"]`) as HTMLInputElement\n if (input) {\n input.value = value\n input.dispatchEvent(new Event('change', { bubbles: true }))\n }\n }\n\n public getInputValue(name: string): any {\n const input = this.renderRoot.querySelector(`form [name=\"${name}\"]`) as HTMLInputElement\n return input?.value\n }\n\n private async focusFirstFormControl() {\n const form = await this.form\n if (!form) return\n\n // 첫번째가 input이면 autofocus, ox-input-search는 프로퍼티로 포커스 셋팅\n const target = form.querySelector('ox-input-search, input:not([type=\"hidden\"]):not(:disabled)') as HTMLInputElement\n if (target && target.tagName !== 'OX-INPUT-SEARCH') {\n target.focus()\n }\n }\n\n private async updateObjectValues() {\n const form = await this.form\n if (!form) return []\n\n const formData = new FormData(form)\n\n const object = {} as any\n formData.forEach((value, key) => {\n const prev = object[key]\n\n if (key in object) {\n object[key] = prev instanceof Array ? [...prev, value] : [prev, value]\n } else {\n object[key] = value\n }\n })\n\n this.objectValue = object\n }\n\n public getFormObjectValue() {\n return this.objectValue\n }\n\n reset() {\n this.form\n .then((form: HTMLFormElement) => {\n form.reset()\n })\n .catch((error: any) => {\n console.error('Error resetting the form:', error)\n })\n }\n}\n"]}
|
|
@@ -4,4 +4,4 @@ import { RecordViewBody } from '../record-view-body.js';
|
|
|
4
4
|
*
|
|
5
5
|
* - handler의 this 는 ox-record-view-body임.
|
|
6
6
|
*/
|
|
7
|
-
export declare function recordViewBodyClickHandler(this: RecordViewBody, e: Event): void
|
|
7
|
+
export declare function recordViewBodyClickHandler(this: RecordViewBody, e: Event): Promise<void>;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { OxGristEditor } from '../../editors/ox-grist-editor.js';
|
|
1
2
|
/**
|
|
2
3
|
* ox-record-view-body 의 click handler
|
|
3
4
|
*
|
|
4
5
|
* - handler의 this 는 ox-record-view-body임.
|
|
5
6
|
*/
|
|
6
|
-
export function recordViewBodyClickHandler(e) {
|
|
7
|
+
export async function recordViewBodyClickHandler(e) {
|
|
7
8
|
var _a;
|
|
8
9
|
e.stopPropagation();
|
|
9
10
|
/* target should be 'ox-grid-field' */
|
|
@@ -23,5 +24,26 @@ export function recordViewBodyClickHandler(e) {
|
|
|
23
24
|
}
|
|
24
25
|
this.currentTarget = target;
|
|
25
26
|
target.setAttribute('editing', 'true');
|
|
27
|
+
/*
|
|
28
|
+
* ── 양식에서는 칸을 누르는 것이 곧 고치는 것이다 ─────────────────────────
|
|
29
|
+
*
|
|
30
|
+
* 표에서 팝업 편집기 칸은 한 번 누르면 고르기이고, 표식이나 더블클릭으로 연다. 양식(이 몸통)은
|
|
31
|
+
* 고르기가 없다 — 칸을 누른 사람은 고치려는 것이다. 그런데 팝업 편집기는 편집 상태가 돼도
|
|
32
|
+
* 자기 자신이 한 번 더 눌려야 열려서, 첫 클릭 뒤 친 글자가 아무 데도 들어가지 않았다.
|
|
33
|
+
*
|
|
34
|
+
* [확인함] 2026-10-10 · pdf 템플릿 「만들기」 · 본문(HTML) 칸을 눌러 친 글이 저장되지 않음
|
|
35
|
+
* (편집기 ox-grist-editor-code 가 그려졌지만 팝업은 표식을 눌러야 열림)
|
|
36
|
+
*
|
|
37
|
+
* 편집 상태로 그려진 편집기에 클릭 하나를 넘긴다. 버블링하지 않게 보낸다 — 올라오면 이 처리기가
|
|
38
|
+
* 다시 불려 편집 상태를 껐다 켜며 같은 클릭을 또 보낸다.
|
|
39
|
+
*/
|
|
40
|
+
if (!target.opensPopup) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
await target.updateComplete;
|
|
44
|
+
const editor = Array.from(target.renderRoot.children).find(child => child instanceof OxGristEditor);
|
|
45
|
+
/* The editor hears clicks from its own first update on (OxGristEditor.firstUpdated). */
|
|
46
|
+
await (editor === null || editor === void 0 ? void 0 : editor.updateComplete);
|
|
47
|
+
editor === null || editor === void 0 ? void 0 : editor.dispatchEvent(new MouseEvent('click', { bubbles: false, composed: false }));
|
|
26
48
|
}
|
|
27
49
|
//# sourceMappingURL=record-view-body-click-handler.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record-view-body-click-handler.js","sourceRoot":"","sources":["../../../../src/record-view/event-handlers/record-view-body-click-handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"record-view-body-click-handler.js","sourceRoot":"","sources":["../../../../src/record-view/event-handlers/record-view-body-click-handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAA;AAGhE;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAuB,CAAQ;;IAC7E,CAAC,CAAC,eAAe,EAAE,CAAA;IAEnB,sCAAsC;IACtC,IAAI,MAAM,GAAG,CAAC,CAAC,MAAuB,CAAA;IAEtC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACvB,IAAI,CAAC,KAAK,EAAE,CAAA;QACZ,IAAI,CAAC,aAAa,CAAC,eAAe,CAAC,SAAS,CAAC,CAAA;IAC/C,CAAC;IAED,IAAI,QAAQ,GAAG,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,MAAM,0CAAE,MAAM,CAAC,QAAQ,CAAA;IAC9C,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;QACnC,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;IACnG,CAAC;IAED,IAAI,MAAM,CAAC,OAAO,KAAK,eAAe,IAAI,CAAC,QAAQ,EAAE,CAAC;QACpD,IAAI,CAAC,KAAK,EAAE,CAAA;QACZ,IAAI,CAAC,aAAa,GAAG,IAAI,CAAA;QACzB,OAAM;IACR,CAAC;IAED,IAAI,CAAC,aAAa,GAAG,MAAM,CAAA;IAC3B,MAAM,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;IAEtC;;;;;;;;;;;;OAYG;IACH,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QACvB,OAAM;IACR,CAAC;IACD,MAAM,MAAM,CAAC,cAAc,CAAA;IAC3B,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,YAAY,aAAa,CAA8B,CAAA;IAChI,wFAAwF;IACxF,MAAM,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,cAAc,CAAA,CAAA;IAC5B,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,aAAa,CAAC,IAAI,UAAU,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;AACrF,CAAC","sourcesContent":["import { DataGridField } from '../../data-grid/data-grid-field.js'\nimport { OxGristEditor } from '../../editors/ox-grist-editor.js'\nimport { RecordViewBody } from '../record-view-body.js'\n\n/**\n * ox-record-view-body 의 click handler\n *\n * - handler의 this 는 ox-record-view-body임.\n */\nexport async function recordViewBodyClickHandler(this: RecordViewBody, e: Event): Promise<void> {\n e.stopPropagation()\n\n /* target should be 'ox-grid-field' */\n var target = e.target as DataGridField\n\n if (this.currentTarget) {\n this.focus()\n this.currentTarget.removeAttribute('editing')\n }\n\n let editable = target?.column?.record.editable\n if (typeof editable === 'function') {\n editable = editable.call(this, target.value, target.column, target.record, target.rowIndex, this)\n }\n\n if (target.tagName !== 'OX-GRID-FIELD' || !editable) {\n this.focus()\n this.currentTarget = null\n return\n }\n\n this.currentTarget = target\n target.setAttribute('editing', 'true')\n\n /*\n * ── 양식에서는 칸을 누르는 것이 곧 고치는 것이다 ─────────────────────────\n *\n * 표에서 팝업 편집기 칸은 한 번 누르면 고르기이고, 표식이나 더블클릭으로 연다. 양식(이 몸통)은\n * 고르기가 없다 — 칸을 누른 사람은 고치려는 것이다. 그런데 팝업 편집기는 편집 상태가 돼도\n * 자기 자신이 한 번 더 눌려야 열려서, 첫 클릭 뒤 친 글자가 아무 데도 들어가지 않았다.\n *\n * [확인함] 2026-10-10 · pdf 템플릿 「만들기」 · 본문(HTML) 칸을 눌러 친 글이 저장되지 않음\n * (편집기 ox-grist-editor-code 가 그려졌지만 팝업은 표식을 눌러야 열림)\n *\n * 편집 상태로 그려진 편집기에 클릭 하나를 넘긴다. 버블링하지 않게 보낸다 — 올라오면 이 처리기가\n * 다시 불려 편집 상태를 껐다 켜며 같은 클릭을 또 보낸다.\n */\n if (!target.opensPopup) {\n return\n }\n await target.updateComplete\n const editor = Array.from(target.renderRoot.children).find(child => child instanceof OxGristEditor) as OxGristEditor | undefined\n /* The editor hears clicks from its own first update on (OxGristEditor.firstUpdated). */\n await editor?.updateComplete\n editor?.dispatchEvent(new MouseEvent('click', { bubbles: false, composed: false }))\n}\n"]}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/* Elements are compared by presence, not by value: a failing element comparison makes chai render the DOM and hang the runner. */
|
|
2
|
+
import { expect, fixture } from '@open-wc/testing';
|
|
3
|
+
import { html } from 'lit';
|
|
4
|
+
import '../src/data-grist.js';
|
|
5
|
+
import '../src/filters/filters-form.js';
|
|
6
|
+
/*
|
|
7
|
+
* Every filter in the form says what it filters, beside its chooser. A select once carried its name only as a
|
|
8
|
+
* placeholder, which a chosen value replaces - the bar then showed 「진행 중」 with nothing saying it was the status.
|
|
9
|
+
*/
|
|
10
|
+
const columns = [
|
|
11
|
+
{ type: 'string', name: 'name', header: 'name', filter: 'i_like' },
|
|
12
|
+
{ type: 'select', name: 'status', header: 'status', record: { options: ['', 'OPEN', 'CLOSED'] }, filter: 'in' },
|
|
13
|
+
{ type: 'select', name: 'kind', header: 'kind', record: { options: ['', 'A', 'B'] }, filter: true },
|
|
14
|
+
{ type: 'date', name: 'day', header: 'day', filter: 'between' }
|
|
15
|
+
];
|
|
16
|
+
const settle = (ms = 150) => new Promise(resolve => setTimeout(resolve, ms));
|
|
17
|
+
describe('필터 라벨', () => {
|
|
18
|
+
const ignoreResizeLoop = (e) => {
|
|
19
|
+
if (String(e.message).includes('ResizeObserver loop')) {
|
|
20
|
+
e.stopImmediatePropagation();
|
|
21
|
+
e.preventDefault();
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
let previousOnError = null;
|
|
25
|
+
before(() => {
|
|
26
|
+
window.addEventListener('error', ignoreResizeLoop, true);
|
|
27
|
+
previousOnError = window.onerror;
|
|
28
|
+
window.onerror = (message, ...rest) => String(message).includes('ResizeObserver loop') ? true : previousOnError === null || previousOnError === void 0 ? void 0 : previousOnError.call(window, message, ...rest);
|
|
29
|
+
});
|
|
30
|
+
after(() => {
|
|
31
|
+
window.removeEventListener('error', ignoreResizeLoop, true);
|
|
32
|
+
window.onerror = previousOnError;
|
|
33
|
+
});
|
|
34
|
+
it('every filter, a select too, sits in a label that names it', async () => {
|
|
35
|
+
var _a, _b;
|
|
36
|
+
const el = (await fixture(html `
|
|
37
|
+
<ox-grist
|
|
38
|
+
style="height: 300px"
|
|
39
|
+
mode="GRID"
|
|
40
|
+
.config=${{ columns, pagination: { pages: [20] } }}
|
|
41
|
+
.fetchHandler=${async () => ({ page: 1, limit: 20, total: 0, records: [] })}
|
|
42
|
+
>
|
|
43
|
+
<div slot="headroom"><ox-filters-form without-search></ox-filters-form></div>
|
|
44
|
+
</ox-grist>
|
|
45
|
+
`));
|
|
46
|
+
await settle();
|
|
47
|
+
const form = el.querySelector('ox-filters-form');
|
|
48
|
+
await form.updateComplete;
|
|
49
|
+
const root = form.renderRoot;
|
|
50
|
+
const named = (name) => root.querySelector(`[name="${name}"]`);
|
|
51
|
+
for (const name of ['name', 'status', 'kind', 'day']) {
|
|
52
|
+
const chooser = named(name);
|
|
53
|
+
expect(!!chooser, `${name} is rendered`).to.equal(true);
|
|
54
|
+
const label = chooser.closest('label[filter-title]');
|
|
55
|
+
expect(!!label, `${name} sits in a label`).to.equal(true);
|
|
56
|
+
expect((_b = (_a = label.querySelector('span')) === null || _a === void 0 ? void 0 : _a.textContent) === null || _b === void 0 ? void 0 : _b.trim()).to.equal(name);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
//# sourceMappingURL=filter-labels.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter-labels.test.js","sourceRoot":"","sources":["../../test/filter-labels.test.ts"],"names":[],"mappings":"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","sourcesContent":["/* Elements are compared by presence, not by value: a failing element comparison makes chai render the DOM and hang the runner. */\nimport { expect, fixture } from '@open-wc/testing'\nimport { html } from 'lit'\n\nimport '../src/data-grist.js'\nimport '../src/filters/filters-form.js'\n\n/*\n * Every filter in the form says what it filters, beside its chooser. A select once carried its name only as a\n * placeholder, which a chosen value replaces - the bar then showed 「진행 중」 with nothing saying it was the status.\n */\n\nconst columns = [\n { type: 'string', name: 'name', header: 'name', filter: 'i_like' },\n { type: 'select', name: 'status', header: 'status', record: { options: ['', 'OPEN', 'CLOSED'] }, filter: 'in' },\n { type: 'select', name: 'kind', header: 'kind', record: { options: ['', 'A', 'B'] }, filter: true },\n { type: 'date', name: 'day', header: 'day', filter: 'between' }\n]\n\nconst settle = (ms = 150) => new Promise(resolve => setTimeout(resolve, ms))\n\ndescribe('필터 라벨', () => {\n const ignoreResizeLoop = (e: ErrorEvent) => {\n if (String(e.message).includes('ResizeObserver loop')) {\n e.stopImmediatePropagation()\n e.preventDefault()\n }\n }\n let previousOnError: OnErrorEventHandler = null\n\n before(() => {\n window.addEventListener('error', ignoreResizeLoop, true)\n previousOnError = window.onerror\n window.onerror = (message, ...rest) =>\n String(message).includes('ResizeObserver loop') ? true : previousOnError?.call(window, message, ...rest)\n })\n\n after(() => {\n window.removeEventListener('error', ignoreResizeLoop, true)\n window.onerror = previousOnError\n })\n\n it('every filter, a select too, sits in a label that names it', async () => {\n const el = (await fixture(html`\n <ox-grist\n style=\"height: 300px\"\n mode=\"GRID\"\n .config=${{ columns, pagination: { pages: [20] } }}\n .fetchHandler=${async () => ({ page: 1, limit: 20, total: 0, records: [] })}\n >\n <div slot=\"headroom\"><ox-filters-form without-search></ox-filters-form></div>\n </ox-grist>\n `)) as any\n await settle()\n\n const form = el.querySelector('ox-filters-form') as any\n await form.updateComplete\n const root = form.renderRoot as ShadowRoot\n const named = (name: string) => root.querySelector(`[name=\"${name}\"]`)\n for (const name of ['name', 'status', 'kind', 'day']) {\n const chooser = named(name)\n expect(!!chooser, `${name} is rendered`).to.equal(true)\n const label = chooser!.closest('label[filter-title]')\n expect(!!label, `${name} sits in a label`).to.equal(true)\n expect(label!.querySelector('span')?.textContent?.trim()).to.equal(name)\n }\n })\n})\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import '../src/record-view/record-view.js';
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/* Elements are compared by presence, not by value: a failing element comparison makes chai render the DOM and hang the runner. */
|
|
2
|
+
import { expect, fixture } from '@open-wc/testing';
|
|
3
|
+
import { html } from 'lit';
|
|
4
|
+
import '../src/record-view/record-view.js';
|
|
5
|
+
import { buildColumn } from '../src/configure/column-builder.js';
|
|
6
|
+
import { OxGristEditor } from '../src/editors/ox-grist-editor.js';
|
|
7
|
+
import { registerEditor } from '../src/editors/registry.js';
|
|
8
|
+
/*
|
|
9
|
+
* In a form (ox-record-view - the 「만들기」 dialog of a grid) a field is pressed to be edited. A field whose editor
|
|
10
|
+
* opens a popup used to become 「editing」 on the first press but open nothing until its editor was pressed again,
|
|
11
|
+
* so what was typed after the first press went nowhere (pdf template 「만들기」, body HTML, 2026-10-10).
|
|
12
|
+
*/
|
|
13
|
+
let opened = 0;
|
|
14
|
+
class ProbePopupEditor extends OxGristEditor {
|
|
15
|
+
_onclick(e) {
|
|
16
|
+
e.stopPropagation();
|
|
17
|
+
opened++;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
ProbePopupEditor.opensPopup = true;
|
|
21
|
+
customElements.define('probe-popup-editor', ProbePopupEditor);
|
|
22
|
+
registerEditor('probe-popup', ProbePopupEditor);
|
|
23
|
+
const settle = (ms = 100) => new Promise(resolve => setTimeout(resolve, ms));
|
|
24
|
+
describe('a popup field in a form', () => {
|
|
25
|
+
it('opens its popup on the first press', async () => {
|
|
26
|
+
opened = 0;
|
|
27
|
+
const columns = [
|
|
28
|
+
buildColumn({ type: 'string', name: 'name', header: 'name', record: { editable: true } }),
|
|
29
|
+
buildColumn({ type: 'probe-popup', name: 'body', header: 'body', record: { editable: true } })
|
|
30
|
+
];
|
|
31
|
+
const view = (await fixture(html `<ox-record-view .columns=${columns} .record=${{}}></ox-record-view>`));
|
|
32
|
+
await view.updateComplete;
|
|
33
|
+
await settle();
|
|
34
|
+
const body = view.renderRoot.querySelector('ox-record-view-body');
|
|
35
|
+
await body.updateComplete;
|
|
36
|
+
const field = Array.from(body.renderRoot.querySelectorAll('ox-grid-field')).find(one => { var _a; return ((_a = one.column) === null || _a === void 0 ? void 0 : _a.name) === 'body'; });
|
|
37
|
+
expect(!!field, 'the body field is drawn').to.equal(true);
|
|
38
|
+
field.click();
|
|
39
|
+
await settle(200);
|
|
40
|
+
expect(field.getAttribute('editing'), 'the field is being edited').to.equal('true');
|
|
41
|
+
expect(opened, 'the popup editor was opened once').to.equal(1);
|
|
42
|
+
});
|
|
43
|
+
it('leaves a field edited in place as it was - nothing extra is pressed', async () => {
|
|
44
|
+
opened = 0;
|
|
45
|
+
const columns = [buildColumn({ type: 'string', name: 'name', header: 'name', record: { editable: true } })];
|
|
46
|
+
const view = (await fixture(html `<ox-record-view .columns=${columns} .record=${{}}></ox-record-view>`));
|
|
47
|
+
await view.updateComplete;
|
|
48
|
+
await settle();
|
|
49
|
+
const body = view.renderRoot.querySelector('ox-record-view-body');
|
|
50
|
+
await body.updateComplete;
|
|
51
|
+
const field = body.renderRoot.querySelector('ox-grid-field');
|
|
52
|
+
field.click();
|
|
53
|
+
await settle(200);
|
|
54
|
+
expect(field.getAttribute('editing')).to.equal('true');
|
|
55
|
+
expect(opened).to.equal(0);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
//# sourceMappingURL=record-view-popup-editor.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record-view-popup-editor.test.js","sourceRoot":"","sources":["../../test/record-view-popup-editor.test.ts"],"names":[],"mappings":"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","sourcesContent":["/* Elements are compared by presence, not by value: a failing element comparison makes chai render the DOM and hang the runner. */\nimport { expect, fixture } from '@open-wc/testing'\nimport { html } from 'lit'\n\nimport '../src/record-view/record-view.js'\nimport { buildColumn } from '../src/configure/column-builder.js'\nimport { OxGristEditor } from '../src/editors/ox-grist-editor.js'\nimport { registerEditor } from '../src/editors/registry.js'\n\n/*\n * In a form (ox-record-view - the 「만들기」 dialog of a grid) a field is pressed to be edited. A field whose editor\n * opens a popup used to become 「editing」 on the first press but open nothing until its editor was pressed again,\n * so what was typed after the first press went nowhere (pdf template 「만들기」, body HTML, 2026-10-10).\n */\n\nlet opened = 0\n\nclass ProbePopupEditor extends OxGristEditor {\n static opensPopup = true\n\n _onclick(e: Event): void {\n e.stopPropagation()\n opened++\n }\n}\ncustomElements.define('probe-popup-editor', ProbePopupEditor)\nregisterEditor('probe-popup', ProbePopupEditor)\n\nconst settle = (ms = 100) => new Promise(resolve => setTimeout(resolve, ms))\n\ndescribe('a popup field in a form', () => {\n it('opens its popup on the first press', async () => {\n opened = 0\n const columns = [\n buildColumn({ type: 'string', name: 'name', header: 'name', record: { editable: true } } as any),\n buildColumn({ type: 'probe-popup', name: 'body', header: 'body', record: { editable: true } } as any)\n ]\n const view = (await fixture(html`<ox-record-view .columns=${columns} .record=${{}}></ox-record-view>`)) as any\n await view.updateComplete\n await settle()\n\n const body = view.renderRoot.querySelector('ox-record-view-body') as any\n await body.updateComplete\n const field = Array.from(body.renderRoot.querySelectorAll('ox-grid-field') as NodeListOf<any>).find(one => one.column?.name === 'body')\n expect(!!field, 'the body field is drawn').to.equal(true)\n\n field.click()\n await settle(200)\n\n expect(field.getAttribute('editing'), 'the field is being edited').to.equal('true')\n expect(opened, 'the popup editor was opened once').to.equal(1)\n })\n\n it('leaves a field edited in place as it was - nothing extra is pressed', async () => {\n opened = 0\n const columns = [buildColumn({ type: 'string', name: 'name', header: 'name', record: { editable: true } } as any)]\n const view = (await fixture(html`<ox-record-view .columns=${columns} .record=${{}}></ox-record-view>`)) as any\n await view.updateComplete\n await settle()\n const body = view.renderRoot.querySelector('ox-record-view-body') as any\n await body.updateComplete\n const field = body.renderRoot.querySelector('ox-grid-field') as any\n field.click()\n await settle(200)\n expect(field.getAttribute('editing')).to.equal('true')\n expect(opened).to.equal(0)\n })\n})\n"]}
|