@operato/data-grist 2.0.0-alpha.119 → 2.0.0-alpha.120

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/src/data-grist.ts CHANGED
@@ -176,6 +176,7 @@ export class DataGrist extends LitElement implements DataConsumer {
176
176
  save(
177
177
  preference?: PersonalGristPreference
178
178
  ): PersonalGristPreference | Promise<PersonalGristPreference | undefined> | undefined
179
+ reset(): void | Promise<void>
179
180
  }
180
181
 
181
182
  @state() personalConfig?: {
@@ -314,17 +315,41 @@ export class DataGrist extends LitElement implements DataConsumer {
314
315
  }
315
316
 
316
317
  public applyUpdatedConfiguration() {
317
- const config = this.config
318
- const { columns } = config
318
+ const config = { ...this.config }
319
+ const columns: Partial<ColumnConfig>[] = config.columns
319
320
 
320
321
  if (this.personalConfig) {
321
322
  const { columns: personalColumns } = this.personalConfig
322
323
 
323
324
  if (personalColumns) {
324
- config.columns = columns.map((column: Partial<ColumnConfig>) => {
325
+ const xcolumns = columns.map((column: Partial<ColumnConfig>) => {
325
326
  const personalColumn = personalColumns.find(pcolumn => pcolumn.name == column.name)
326
327
  return personalColumn ? { ...column, ...personalColumn } : column
327
328
  })
329
+
330
+ function reorderList(a: { name: string }[], b: { name: string }[]): { name: string }[] {
331
+ // 결과 배열 초기화, a 배열 길이만큼 undefined로 채움
332
+ const result = new Array(a.length)
333
+
334
+ // b 배열에 없는 아이템은 원래 위치로 채움
335
+ a.forEach((item, index) => {
336
+ if (!item.name || !b.find(bi => bi.name == item.name)) {
337
+ result[index] = item
338
+ }
339
+ })
340
+
341
+ b.forEach(item => {
342
+ const ai = a.find(ai => ai.name == item.name)
343
+ if (ai) {
344
+ result[result.findIndex(slot => slot === undefined)] = ai
345
+ }
346
+ })
347
+
348
+ return result
349
+ }
350
+
351
+ // 배열 재정렬 실행
352
+ config.columns = reorderList(xcolumns as any, personalColumns as any)
328
353
  }
329
354
  }
330
355
 
@@ -6,8 +6,9 @@ import { customElement, property, state } from 'lit/decorators.js'
6
6
  import { i18next } from '@operato/i18n'
7
7
  import { OxPopupList } from '@operato/popup'
8
8
 
9
- import { GristConfig, PersonalGristPreference } from '../types'
9
+ import { ColumnConfig, PersonalGristPreference } from '../types'
10
10
  import { DataGrist } from '../data-grist'
11
+ import { OxCheckbox } from '@operato/input'
11
12
 
12
13
  @customElement('ox-grist-personalizer')
13
14
  export class OxGristPersonalizer extends LitElement {
@@ -31,6 +32,7 @@ export class OxGristPersonalizer extends LitElement {
31
32
 
32
33
  @property({ type: String }) page!: string
33
34
  @property({ type: String }) element!: string
35
+ @property({ type: Boolean, attribute: true }) debug: boolean = false
34
36
 
35
37
  @state() private preference?: PersonalGristPreference
36
38
 
@@ -43,8 +45,11 @@ export class OxGristPersonalizer extends LitElement {
43
45
  const { config, compiledConfig } = grist
44
46
  const { columns: compiledColumns } = compiledConfig
45
47
 
46
- const columns = (config as GristConfig).columns
47
- .filter(column => column.name && column.type !== 'gutter' && !column.hidden)
48
+ const columns = compiledColumns
49
+ .filter(ccolumn => {
50
+ const column = config.columns.find((column: Partial<ColumnConfig>) => column.name == ccolumn.name)
51
+ return column && column.name && column.type !== 'gutter' && !column.hidden
52
+ })
48
53
  .map(column => compiledColumns.find(compiledColumn => compiledColumn.name == column.name)!)
49
54
 
50
55
  this.preference = {
@@ -59,48 +64,70 @@ export class OxGristPersonalizer extends LitElement {
59
64
 
60
65
  const template = html`
61
66
  <div class="personalizer-header" slot="header">
62
- ${i18next.t('text.column visibility setting')}<md-outlined-button
67
+ <md-icon
63
68
  style="margin-left: auto;"
64
69
  @click=${async (e: MouseEvent) => {
65
70
  if (grist.personalConfigProvider) {
66
- this.preference = await grist.personalConfigProvider.save(this.preference)
71
+ grist.personalConfig = this.preference = await grist.personalConfigProvider.save(this.preference)
72
+ }
73
+ popup.close()
74
+ }}
75
+ title=${String(i18next.t('button.save'))}
76
+ >keep</md-icon
77
+ ><md-icon
78
+ @click=${async (e: MouseEvent) => {
79
+ if (grist.personalConfigProvider) {
80
+ grist.personalConfig = this.preference = {}
81
+ await grist.personalConfigProvider.reset()
67
82
  }
68
- ;((e.target as HTMLElement).closest('ox-popup-list') as OxPopupList)?.close()
83
+ popup.close()
69
84
  }}
70
- >${i18next.t('button.save')}</md-outlined-button
85
+ title=${String(i18next.t('button.delete'))}
86
+ >keep_off</md-icon
87
+ ><md-icon @click=${async (e: MouseEvent) => popup.close()} title=${String(i18next.t('button.close'))}
88
+ >close</md-icon
71
89
  >
72
90
  </div>
73
91
 
74
92
  ${columns.map(
75
- column =>
76
- html`<ox-checkbox label="checkbox" ?checked=${!column.hidden} value=${column.name} option />${column.header.renderer(column)}</ox-checkbox>`
93
+ column => html`
94
+ <ox-checkbox label="checkbox" ?checked=${!column.hidden} value=${column.name} option
95
+ >${column.header.renderer(column)}<span style="position: absolute; right: 10px; cursor: move;" handle
96
+ >☰</span
97
+ ></ox-checkbox
98
+ >
99
+ `
77
100
  )}
78
101
  `
79
102
 
80
103
  const popup = OxPopupList.open({
81
104
  template,
82
105
  multiple: true,
106
+ sortable: true,
107
+ debug: this.debug,
83
108
  attrSelected: 'checked',
84
109
  top: e.pageY,
85
110
  left: e.pageX,
86
111
  styles: css`
87
112
  :host {
88
113
  width: 240px;
89
- max-height: 360px;
90
- overflow: scroll;
114
+ max-height: 300px;
115
+ overflow: auto;
91
116
  }
92
117
 
93
118
  ::slotted(.personalizer-header) {
94
- --md-icon-size: 1.2em;
95
- --md-outlined-button-container-height: 24px;
96
- --md-outlined-button-container-shape: 4px;
97
- --md-outlined-button-leading-space: 4px;
98
- --md-outlined-button-trailing-space: 4px;
119
+ --md-icon-size: 1.4em;
99
120
 
100
121
  display: flex;
101
122
  flex-direction: row;
102
123
  align-items: center;
103
124
  text-transform: capitalize;
125
+ box-shadow: 0 3px 3px rgba(0, 0, 0, 0.3);
126
+ }
127
+
128
+ ::slotted([option]) {
129
+ position: relative;
130
+ user-select: none;
104
131
  }
105
132
  `
106
133
  })
@@ -109,7 +136,9 @@ export class OxGristPersonalizer extends LitElement {
109
136
  const selected = (e as CustomEvent).detail
110
137
 
111
138
  const pconfig: PersonalGristPreference = grist.personalConfig || {}
112
- pconfig.columns = columns.map(column => {
139
+ const pcolumns = this.preference?.columns || columns
140
+
141
+ pconfig.columns = pcolumns.map(column => {
113
142
  return {
114
143
  name: column.name,
115
144
  hidden: selected.indexOf(column.name) == -1,
@@ -123,6 +152,27 @@ export class OxGristPersonalizer extends LitElement {
123
152
 
124
153
  grist.applyUpdatedConfiguration()
125
154
  }
155
+
156
+ popup.addEventListener('sorted', (e: Event) => {
157
+ const sorted = (e as CustomEvent).detail as HTMLElement[]
158
+
159
+ const pconfig: PersonalGristPreference = grist.personalConfig || {}
160
+
161
+ pconfig.columns = sorted.map(element => {
162
+ const name = (element as OxCheckbox).value
163
+ return {
164
+ name,
165
+ hidden: !element.hasAttribute('checked'),
166
+ width: columns.find(column => column.name == name)?.width
167
+ }
168
+ })
169
+
170
+ this.preference = pconfig
171
+
172
+ grist.personalConfig = this.preference
173
+
174
+ grist.applyUpdatedConfiguration()
175
+ })
126
176
  }}
127
177
  >settings</md-icon
128
178
  >
@@ -345,7 +345,8 @@ export default {
345
345
  argTypes: {
346
346
  config: { control: 'object' },
347
347
  mode: { control: 'select', options: ['GRID', 'LIST', 'CARD'] },
348
- urlParamsSensitive: { control: 'boolean' }
348
+ urlParamsSensitive: { control: 'boolean' },
349
+ debug: { control: 'boolean' }
349
350
  }
350
351
  }
351
352
 
@@ -360,9 +361,16 @@ interface ArgTypes {
360
361
  mode: 'GRID' | 'LIST' | 'CARD'
361
362
  urlParamsSensitive: boolean
362
363
  fetchHandler: FetchHandler
364
+ debug: boolean
363
365
  }
364
366
 
365
- const Template: Story<ArgTypes> = ({ config, mode = 'GRID', urlParamsSensitive = false, fetchHandler }: ArgTypes) =>
367
+ const Template: Story<ArgTypes> = ({
368
+ config,
369
+ mode = 'GRID',
370
+ urlParamsSensitive = false,
371
+ debug = false,
372
+ fetchHandler
373
+ }: ArgTypes) =>
366
374
  html` <link
367
375
  href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL@20..48,100..700,0..1"
368
376
  rel="stylesheet"
@@ -402,6 +410,9 @@ const Template: Story<ArgTypes> = ({ config, mode = 'GRID', urlParamsSensitive =
402
410
  await sleep(1000)
403
411
  console.log('saving preference', preference)
404
412
  return preference
413
+ },
414
+ async reset() {
415
+ await sleep(1000)
405
416
  }
406
417
  }}
407
418
  ?url-params-sensitive=${urlParamsSensitive}
@@ -440,7 +451,7 @@ const Template: Story<ArgTypes> = ({ config, mode = 'GRID', urlParamsSensitive =
440
451
  </ox-record-creator>
441
452
  </div>
442
453
 
443
- <ox-grist-personalizer slot="setting"></ox-grist-personalizer>
454
+ <ox-grist-personalizer slot="setting" ?debug=${debug}></ox-grist-personalizer>
444
455
  </ox-grist>`
445
456
 
446
457
  export const Regular = Template.bind({})