@operato/data-grist 2.0.0-alpha.99 → 2.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (216) hide show
  1. package/CHANGELOG.md +433 -0
  2. package/demo/data-grist-test.html +1 -1
  3. package/demo/index.html +1 -1
  4. package/dist/src/data-card/data-card-field.js +2 -2
  5. package/dist/src/data-card/data-card-field.js.map +1 -1
  6. package/dist/src/data-card/data-card-gutter-menu.js +5 -5
  7. package/dist/src/data-card/data-card-gutter-menu.js.map +1 -1
  8. package/dist/src/data-card/data-card-gutter.js +6 -6
  9. package/dist/src/data-card/data-card-gutter.js.map +1 -1
  10. package/dist/src/data-card/data-card.js +7 -9
  11. package/dist/src/data-card/data-card.js.map +1 -1
  12. package/dist/src/data-card/record-card.js +9 -10
  13. package/dist/src/data-card/record-card.js.map +1 -1
  14. package/dist/src/data-grid/data-grid-accum-field.js +12 -5
  15. package/dist/src/data-grid/data-grid-accum-field.js.map +1 -1
  16. package/dist/src/data-grid/data-grid-body-style.js +12 -0
  17. package/dist/src/data-grid/data-grid-body-style.js.map +1 -1
  18. package/dist/src/data-grid/data-grid-body.d.ts +0 -1
  19. package/dist/src/data-grid/data-grid-body.js +14 -21
  20. package/dist/src/data-grid/data-grid-body.js.map +1 -1
  21. package/dist/src/data-grid/data-grid-field.js +8 -2
  22. package/dist/src/data-grid/data-grid-field.js.map +1 -1
  23. package/dist/src/data-grid/data-grid-footer.js +4 -2
  24. package/dist/src/data-grid/data-grid-footer.js.map +1 -1
  25. package/dist/src/data-grid/data-grid-header.js +9 -6
  26. package/dist/src/data-grid/data-grid-header.js.map +1 -1
  27. package/dist/src/data-grid/data-grid.js +23 -1
  28. package/dist/src/data-grid/data-grid.js.map +1 -1
  29. package/dist/src/data-grid/event-handlers/data-grid-body-click-handler.js +3 -0
  30. package/dist/src/data-grid/event-handlers/data-grid-body-click-handler.js.map +1 -1
  31. package/dist/src/data-grist.d.ts +10 -2
  32. package/dist/src/data-grist.js +71 -8
  33. package/dist/src/data-grist.js.map +1 -1
  34. package/dist/src/data-list/data-list-field.js +5 -5
  35. package/dist/src/data-list/data-list-field.js.map +1 -1
  36. package/dist/src/data-list/data-list-gutter.js +3 -3
  37. package/dist/src/data-list/data-list-gutter.js.map +1 -1
  38. package/dist/src/data-list/data-list.js +4 -4
  39. package/dist/src/data-list/data-list.js.map +1 -1
  40. package/dist/src/data-list/record-partial.js +9 -10
  41. package/dist/src/data-list/record-partial.js.map +1 -1
  42. package/dist/src/data-manipulator.d.ts +1 -1
  43. package/dist/src/data-manipulator.js +5 -5
  44. package/dist/src/data-manipulator.js.map +1 -1
  45. package/dist/src/data-report/data-report-field.js +2 -1
  46. package/dist/src/data-report/data-report-field.js.map +1 -1
  47. package/dist/src/data-report/data-report-header.js +2 -2
  48. package/dist/src/data-report/data-report-header.js.map +1 -1
  49. package/dist/src/editors/ox-grist-editor-select.js +37 -25
  50. package/dist/src/editors/ox-grist-editor-select.js.map +1 -1
  51. package/dist/src/editors/ox-input-tree.js +8 -8
  52. package/dist/src/editors/ox-input-tree.js.map +1 -1
  53. package/dist/src/filters/filter-input-barcode.js +1 -0
  54. package/dist/src/filters/filter-input-barcode.js.map +1 -1
  55. package/dist/src/filters/filter-select.js +30 -16
  56. package/dist/src/filters/filter-select.js.map +1 -1
  57. package/dist/src/filters/filter-styles.js +46 -31
  58. package/dist/src/filters/filter-styles.js.map +1 -1
  59. package/dist/src/filters/filters-form.d.ts +15 -4
  60. package/dist/src/filters/filters-form.js +205 -70
  61. package/dist/src/filters/filters-form.js.map +1 -1
  62. package/dist/src/gutters/gutter-dirty.js +2 -2
  63. package/dist/src/gutters/gutter-dirty.js.map +1 -1
  64. package/dist/src/index.d.ts +1 -0
  65. package/dist/src/index.js +1 -0
  66. package/dist/src/index.js.map +1 -1
  67. package/dist/src/personalizer/index.d.ts +1 -0
  68. package/dist/src/personalizer/index.js +2 -0
  69. package/dist/src/personalizer/index.js.map +1 -0
  70. package/dist/src/personalizer/ox-grist-filter-personalizer.d.ts +8 -0
  71. package/dist/src/personalizer/ox-grist-filter-personalizer.js +177 -0
  72. package/dist/src/personalizer/ox-grist-filter-personalizer.js.map +1 -0
  73. package/dist/src/personalizer/ox-grist-personalizer.d.ts +8 -0
  74. package/dist/src/personalizer/ox-grist-personalizer.js +178 -0
  75. package/dist/src/personalizer/ox-grist-personalizer.js.map +1 -0
  76. package/dist/src/record-view/record-creator.js +2 -2
  77. package/dist/src/record-view/record-creator.js.map +1 -1
  78. package/dist/src/renderers/ox-grist-renderer-select.js +34 -4
  79. package/dist/src/renderers/ox-grist-renderer-select.js.map +1 -1
  80. package/dist/src/renderers/ox-grist-renderer-tree.js +8 -8
  81. package/dist/src/renderers/ox-grist-renderer-tree.js.map +1 -1
  82. package/dist/src/sorters/sorters-control.js +3 -3
  83. package/dist/src/sorters/sorters-control.js.map +1 -1
  84. package/dist/src/types.d.ts +41 -2
  85. package/dist/src/types.js.map +1 -1
  86. package/dist/stories/{accumulator.stories.d.ts → accumulator-format.stories.d.ts} +9 -0
  87. package/dist/stories/{accumulator.stories.js → accumulator-format.stories.js} +24 -12
  88. package/dist/stories/accumulator-format.stories.js.map +1 -0
  89. package/dist/stories/barcode-input-filter.stories.d.ts +5 -0
  90. package/dist/stories/barcode-input-filter.stories.js +29 -5
  91. package/dist/stories/barcode-input-filter.stories.js.map +1 -1
  92. package/dist/stories/bounded-select-filters.stories.d.ts +30 -0
  93. package/dist/stories/bounded-select-filters.stories.js +288 -0
  94. package/dist/stories/bounded-select-filters.stories.js.map +1 -0
  95. package/dist/stories/bounded-select-record.stories.d.ts +30 -0
  96. package/dist/stories/bounded-select-record.stories.js +291 -0
  97. package/dist/stories/bounded-select-record.stories.js.map +1 -0
  98. package/dist/stories/click-event.stories.d.ts +41 -0
  99. package/dist/stories/click-event.stories.js +234 -0
  100. package/dist/stories/click-event.stories.js.map +1 -0
  101. package/dist/stories/creatable-only-column.stories.d.ts +5 -0
  102. package/dist/stories/creatable-only-column.stories.js +46 -21
  103. package/dist/stories/creatable-only-column.stories.js.map +1 -1
  104. package/dist/stories/default-filters.stories.d.ts +5 -0
  105. package/dist/stories/default-filters.stories.js +84 -17
  106. package/dist/stories/default-filters.stories.js.map +1 -1
  107. package/dist/stories/dynamic-editable.stories.d.ts +5 -0
  108. package/dist/stories/dynamic-editable.stories.js +44 -21
  109. package/dist/stories/dynamic-editable.stories.js.map +1 -1
  110. package/dist/stories/empty-sorters.stories.d.ts +7 -1
  111. package/dist/stories/empty-sorters.stories.js +41 -17
  112. package/dist/stories/empty-sorters.stories.js.map +1 -1
  113. package/dist/stories/explicit-fetch.stories.d.ts +5 -0
  114. package/dist/stories/explicit-fetch.stories.js +40 -17
  115. package/dist/stories/explicit-fetch.stories.js.map +1 -1
  116. package/dist/stories/fixed-column.stories.d.ts +5 -0
  117. package/dist/stories/fixed-column.stories.js +53 -30
  118. package/dist/stories/fixed-column.stories.js.map +1 -1
  119. package/dist/stories/grid-setting.stories.d.ts +20 -4
  120. package/dist/stories/grid-setting.stories.js +96 -51
  121. package/dist/stories/grid-setting.stories.js.map +1 -1
  122. package/dist/stories/grist-modes.stories.d.ts +8 -2
  123. package/dist/stories/grist-modes.stories.js +58 -35
  124. package/dist/stories/grist-modes.stories.js.map +1 -1
  125. package/dist/stories/group-header.stories.d.ts +5 -0
  126. package/dist/stories/group-header.stories.js +53 -30
  127. package/dist/stories/group-header.stories.js.map +1 -1
  128. package/dist/stories/textarea.stories.d.ts +8 -2
  129. package/dist/stories/textarea.stories.js +37 -13
  130. package/dist/stories/textarea.stories.js.map +1 -1
  131. package/dist/stories/tree-column-with-checkbox.stories.d.ts +5 -0
  132. package/dist/stories/tree-column-with-checkbox.stories.js +44 -21
  133. package/dist/stories/tree-column-with-checkbox.stories.js.map +1 -1
  134. package/dist/stories/tree-column.stories.d.ts +5 -0
  135. package/dist/stories/tree-column.stories.js +44 -21
  136. package/dist/stories/tree-column.stories.js.map +1 -1
  137. package/dist/tsconfig.tsbuildinfo +1 -1
  138. package/docs/default-value/value-generator/date-generator.md +29 -0
  139. package/docs/default-value/value-generator/hour-time-generator.md +33 -0
  140. package/docs/default-value/value-generator/minute-time-generator.md +33 -0
  141. package/docs/default-value/value-generator/month-date-generator.md +2 -0
  142. package/docs/default-value/value-generator/now-generator.md +29 -0
  143. package/docs/default-value/value-generator/time-generator.md +31 -0
  144. package/docs/default-value/value-generator/today-generator.md +29 -0
  145. package/docs/default-value/value-generator/week-date-generator.md +31 -0
  146. package/docs/default-value/value-generator/year-date-generator.md +31 -0
  147. package/package.json +15 -10
  148. package/src/data-card/data-card-field.ts +2 -2
  149. package/src/data-card/data-card-gutter-menu.ts +5 -5
  150. package/src/data-card/data-card-gutter.ts +6 -6
  151. package/src/data-card/data-card.ts +7 -9
  152. package/src/data-card/record-card.ts +9 -10
  153. package/src/data-grid/data-grid-accum-field.ts +11 -5
  154. package/src/data-grid/data-grid-body-style.ts +12 -0
  155. package/src/data-grid/data-grid-body.ts +16 -29
  156. package/src/data-grid/data-grid-field.ts +7 -2
  157. package/src/data-grid/data-grid-footer.ts +4 -2
  158. package/src/data-grid/data-grid-header.ts +8 -6
  159. package/src/data-grid/data-grid.ts +23 -1
  160. package/src/data-grid/event-handlers/data-grid-body-click-handler.ts +4 -0
  161. package/src/data-grist.ts +88 -8
  162. package/src/data-list/data-list-field.ts +5 -5
  163. package/src/data-list/data-list-gutter.ts +3 -3
  164. package/src/data-list/data-list.ts +4 -4
  165. package/src/data-list/record-partial.ts +9 -10
  166. package/src/data-manipulator.ts +5 -5
  167. package/src/data-report/data-report-field.ts +2 -1
  168. package/src/data-report/data-report-header.ts +2 -2
  169. package/src/editors/ox-grist-editor-select.ts +41 -28
  170. package/src/editors/ox-input-tree.ts +8 -8
  171. package/src/filters/filter-input-barcode.ts +1 -0
  172. package/src/filters/filter-select.ts +41 -28
  173. package/src/filters/filter-styles.ts +46 -31
  174. package/src/filters/filters-form.ts +273 -119
  175. package/src/gutters/gutter-dirty.ts +2 -2
  176. package/src/index.ts +1 -0
  177. package/src/personalizer/index.ts +1 -0
  178. package/src/personalizer/ox-grist-filter-personalizer.ts +191 -0
  179. package/src/personalizer/ox-grist-personalizer.ts +192 -0
  180. package/src/record-view/record-creator.ts +2 -2
  181. package/src/renderers/ox-grist-renderer-select.ts +41 -6
  182. package/src/renderers/ox-grist-renderer-tree.ts +8 -8
  183. package/src/sorters/sorters-control.ts +3 -3
  184. package/src/types.ts +53 -2
  185. package/stories/{accumulator.stories.ts → accumulator-format.stories.ts} +33 -12
  186. package/stories/barcode-input-filter.stories.ts +31 -6
  187. package/stories/bounded-select-filters.stories.ts +339 -0
  188. package/stories/bounded-select-record.stories.ts +342 -0
  189. package/stories/click-event.stories.ts +269 -0
  190. package/stories/creatable-only-column.stories.ts +54 -28
  191. package/stories/default-filters.stories.ts +92 -24
  192. package/stories/dynamic-editable.stories.ts +52 -28
  193. package/stories/empty-sorters.stories.ts +51 -25
  194. package/stories/explicit-fetch.stories.ts +48 -24
  195. package/stories/fixed-column.stories.ts +62 -39
  196. package/stories/grid-setting.stories.ts +120 -63
  197. package/stories/grist-modes.stories.ts +74 -46
  198. package/stories/group-header.stories.ts +61 -39
  199. package/stories/textarea.stories.ts +49 -17
  200. package/stories/tree-column-with-checkbox.stories.ts +52 -28
  201. package/stories/tree-column.stories.ts +52 -28
  202. package/themes/dark-hc.css +151 -0
  203. package/themes/dark-mc.css +151 -0
  204. package/themes/dark.css +151 -0
  205. package/themes/grist-theme.css +103 -100
  206. package/themes/light-hc.css +151 -0
  207. package/themes/light-mc.css +151 -0
  208. package/themes/light.css +151 -0
  209. package/themes/md-typescale-styles.css +100 -0
  210. package/themes/spacing.css +43 -0
  211. package/themes/state-color.css +6 -0
  212. package/dist/stories/accumulator.stories.js.map +0 -1
  213. package/themes/app-theme.css +0 -145
  214. package/themes/form-theme.css +0 -75
  215. package/themes/oops-theme.css +0 -26
  216. package/themes/report-theme.css +0 -47
@@ -61,6 +61,10 @@ export class DataGridBody extends LitElement {
61
61
  TooltipStyles,
62
62
  dataGridBodyStyle,
63
63
  css`
64
+ :host {
65
+ font-variation-settings: 'FILL' 1;
66
+ }
67
+
64
68
  [select-block] {
65
69
  position: absolute;
66
70
  left: var(--select-box-left);
@@ -91,7 +95,7 @@ export class DataGridBody extends LitElement {
91
95
  }
92
96
 
93
97
  ox-grid-accum-field[fixed] {
94
- background-color: var(--grid-accum-record-background-color, #ccc);
98
+ background-color: var(--md-sys-color-inverse-primary);
95
99
  }
96
100
  `
97
101
  ]
@@ -348,13 +352,14 @@ export class DataGridBody extends LitElement {
348
352
 
349
353
  this.addEventListener('focus-change', dataGridBodyFocusChangeHandler.bind(this))
350
354
 
351
- this.addEventListener('wheel', this._onWheelEvent.bind(this))
355
+ requestAnimationFrame(() => {
356
+ const primaryColor = getComputedStyle(this).getPropertyValue('--md-sys-color-primary')
352
357
 
353
- const primaryColor = getComputedStyle(this).getPropertyValue('--primary-color')
354
- this.style.setProperty(
355
- '--focused-background-image',
356
- `url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'><rect fill='${primaryColor}' x='0' y='0' width='100%' height='100%' style='opacity:.3'/></svg>")`
357
- )
358
+ this.style.setProperty(
359
+ '--focused-background-image',
360
+ `url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'><rect fill='${primaryColor}' fill-opacity='0.2' x='0' y='0' width='100%' height='100%'/></svg>")`
361
+ )
362
+ })
358
363
 
359
364
  this.addEventListener('show-record-view', (e: Event) =>
360
365
  this.popupRecordView((e as CustomEvent).detail as { row: number; record: GristRecord })
@@ -380,26 +385,6 @@ export class DataGridBody extends LitElement {
380
385
  ) as DataGridField
381
386
  }
382
387
 
383
- _onWheelEvent(e: WheelEvent) {
384
- if (this.scrollHeight <= this.clientHeight) {
385
- var delta = Math.max(-1, Math.min(1, e.deltaY || 0))
386
- this.scrollLeft = Math.max(0, this.scrollLeft - delta * 40)
387
-
388
- var maxScrollLeft = this.scrollWidth - this.clientWidth
389
-
390
- var atStart = this.scrollLeft === 0
391
- var atEnd = this.scrollLeft === maxScrollLeft
392
-
393
- // 스크롤이 맨 앞으로 와 있는 상태에서 휠을 올리는 경우 또는
394
- // 스크롤이 맨 끝으로 가 있는 상태에서 휠을 내리는 경우에만 디폴트 동작 허용
395
- if ((atStart && delta > 0) || (atEnd && delta < 0)) {
396
- return true
397
- }
398
-
399
- e.preventDefault()
400
- }
401
- }
402
-
403
388
  startEditTarget(row: number, column: number, valueWith: string | null = null) {
404
389
  var { editable } = this.columns.filter(column => !column.hidden)[column].record
405
390
  if (typeof editable === 'function') {
@@ -637,7 +622,7 @@ export class DataGridBody extends LitElement {
637
622
  const cells = record.querySelectorAll('td')
638
623
  cells.forEach((item, columnIndex) => {
639
624
  const targetColumn = columns[column + columnIndex]
640
- var value = item.textContent as any
625
+ var value = item.textContent?.trim() as any
641
626
  let type = targetColumn.type || item.getAttribute('type') || 'string'
642
627
  type = type.includes('object') ? 'object' : type // 오브젝트 타입 예외처리
643
628
  let { editable } = targetColumn.record
@@ -709,7 +694,9 @@ export class DataGridBody extends LitElement {
709
694
  )
710
695
  }
711
696
  }
712
- } catch (e) {}
697
+ } catch (e) {
698
+ console.log('e : ', e)
699
+ }
713
700
  }
714
701
 
715
702
  setSelectBlock(start?: DataGridField, end?: DataGridField) {
@@ -30,12 +30,15 @@ export class DataGridField extends LitElement {
30
30
  border-bottom: var(--grid-record-border-bottom);
31
31
 
32
32
  font-size: var(--grid-record-wide-fontsize);
33
- min-height: 19px;
33
+ min-height: 30px;
34
+ box-sizing: border-box;
34
35
  }
36
+
35
37
  :host([gutter]) {
36
38
  padding: var(--grid-gutter-padding);
37
39
  text-align: center;
38
40
  }
41
+
39
42
  :host([gutter]) * {
40
43
  cursor: default;
41
44
  }
@@ -89,7 +92,7 @@ export class DataGridField extends LitElement {
89
92
  @property({ type: Object }) value = {}
90
93
  @property({ type: String }) valueWith: string | null = null
91
94
  @property({ attribute: false }) emphasized: any = false
92
- @property({ type: String }) fixed?: string
95
+ @property({ type: String, attribute: true }) fixed?: string
93
96
  @property({ type: String }) type?: string
94
97
  @property({ type: Boolean }) isWorking: boolean = false
95
98
 
@@ -155,6 +158,8 @@ export class DataGridField extends LitElement {
155
158
  if (changes.has('fixed')) {
156
159
  if (this.fixed) {
157
160
  this.style.left = this.fixed + 'px'
161
+ } else {
162
+ this.style.left = 'unset'
158
163
  }
159
164
  }
160
165
 
@@ -14,7 +14,7 @@ export class DataGridFooter extends LitElement {
14
14
  :host {
15
15
  display: flex;
16
16
  flex-direction: row;
17
- gap: 4px;
17
+ gap: var(--spacing-small);
18
18
  overflow: hidden;
19
19
 
20
20
  padding: var(--grid-footer-padding);
@@ -39,12 +39,14 @@ export class DataGridFooter extends LitElement {
39
39
  md-icon {
40
40
  font-size: 1.5em;
41
41
  vertical-align: middle;
42
+
43
+ font-variation-settings: 'FILL' 1;
42
44
  }
43
45
 
44
46
  .limit {
45
47
  display: flex;
46
48
  flex-direction: row;
47
- gap: 6px;
49
+ gap: var(--spacing-small);
48
50
  align-items: center;
49
51
  }
50
52
 
@@ -28,6 +28,8 @@ export class DataGridHeader extends LitElement {
28
28
 
29
29
  border-top: var(--grid-header-top-border);
30
30
  overflow: hidden;
31
+
32
+ font-variation-settings: 'FILL' 1;
31
33
  }
32
34
 
33
35
  div[column] {
@@ -35,7 +37,7 @@ export class DataGridHeader extends LitElement {
35
37
 
36
38
  white-space: nowrap;
37
39
  overflow: hidden;
38
- background-color: var(--grist-background-color);
40
+ background-color: var(--grid-header-background-color);
39
41
  border-bottom: var(--grid-header-bottom-border);
40
42
  padding: var(--grid-header-padding);
41
43
 
@@ -45,7 +47,7 @@ export class DataGridHeader extends LitElement {
45
47
  }
46
48
 
47
49
  div[gutter] {
48
- padding: var(--padding-default) 0 var(--padding-narrow) 0;
50
+ padding: var(--spacing-small) 0;
49
51
  text-align: center;
50
52
  }
51
53
 
@@ -111,8 +113,8 @@ export class DataGridHeader extends LitElement {
111
113
  }
112
114
 
113
115
  [filter] input[type='checkbox'] {
114
- margin-left: 10px;
115
- margin-bottom: 5px;
116
+ margin-left: var(--spacing-medium);
117
+ margin-bottom: var(--spacing-small);
116
118
  }
117
119
 
118
120
  [fixed] {
@@ -350,7 +352,7 @@ export class DataGridHeader extends LitElement {
350
352
  var { renderer } = column.header || {}
351
353
  var title = renderer.call(this, column)
352
354
 
353
- return html` ${title} `
355
+ return html`${column?.record?.mandatory ? '*' : ''} ${title} `
354
356
  }
355
357
 
356
358
  _renderSortHeader(column: ColumnConfig) {
@@ -358,7 +360,7 @@ export class DataGridHeader extends LitElement {
358
360
 
359
361
  var sorter = sorters.find(sorter => column.type !== 'gutter' && column.name == sorter.name)
360
362
  if (!sorter) {
361
- return html``
363
+ return html`<md-icon style="opacity: 0.2;">unfold_more</md-icon>`
362
364
  }
363
365
 
364
366
  if (sorters.length > 1) {
@@ -5,6 +5,7 @@ import './data-grid-footer'
5
5
 
6
6
  import { css, html, LitElement, PropertyValues } from 'lit'
7
7
  import { customElement, property, query, state } from 'lit/decorators.js'
8
+ import { styles as MDTypeScaleStyles } from '@material/web/typography/md-typescale-styles'
8
9
 
9
10
  import { ScrollbarStyles } from '@operato/styles'
10
11
 
@@ -19,6 +20,7 @@ import { DataGridHeader } from './data-grid-header'
19
20
  @customElement('ox-grid')
20
21
  export class DataGrid extends DataManipulator {
21
22
  static styles = [
23
+ MDTypeScaleStyles,
22
24
  ScrollbarStyles,
23
25
  css`
24
26
  :host {
@@ -33,6 +35,16 @@ export class DataGrid extends DataManipulator {
33
35
  ox-grid-body {
34
36
  flex: 1;
35
37
  position: relative;
38
+
39
+ font-variation-settings: 'FILL' 1;
40
+ }
41
+
42
+ ox-grid-header {
43
+ font-variation-settings: 'FILL' 1;
44
+ }
45
+
46
+ ox-grid-footer {
47
+ font-variation-settings: 'FILL' 1;
36
48
  }
37
49
 
38
50
  ox-empty-note {
@@ -232,6 +244,7 @@ export class DataGrid extends DataManipulator {
232
244
  </div>
233
245
 
234
246
  <ox-grid-header
247
+ class="md-typescale-label-medium-prominent"
235
248
  .columns=${columns}
236
249
  .sorters=${this.sorters}
237
250
  .filters=${this.filters}
@@ -247,6 +260,7 @@ export class DataGrid extends DataManipulator {
247
260
  </ox-grid-header>
248
261
 
249
262
  <ox-grid-body
263
+ class="md-typescale-body-medium"
250
264
  .config=${this.config}
251
265
  .columns=${columns}
252
266
  .data=${data}
@@ -255,7 +269,15 @@ export class DataGrid extends DataManipulator {
255
269
  >
256
270
  ${this.empty ? html` <ox-empty-note title="NO RECORDS"></ox-empty-note> ` : html``}
257
271
  </ox-grid-body>
258
- ${paginatable ? html` <ox-grid-footer .data=${data} .pagination=${this.pagination}></ox-grid-footer> ` : html``}
272
+ ${paginatable
273
+ ? html`
274
+ <ox-grid-footer
275
+ class="md-typescale-body-medium"
276
+ .data=${data}
277
+ .pagination=${this.pagination}
278
+ ></ox-grid-footer>
279
+ `
280
+ : html``}
259
281
  `
260
282
  }
261
283
 
@@ -10,6 +10,10 @@ import { DataGridField } from '../data-grid-field'
10
10
  export function dataGridBodyClickHandler(this: DataGridBody, e: Event): void {
11
11
  e.stopPropagation()
12
12
 
13
+ if ((e as MouseEvent).detail === 2) {
14
+ return;
15
+ }
16
+
13
17
  if (this.editTarget) {
14
18
  /* editTarget이 새로 설정되지 않았다면, 이후 기능이 실행된다. */
15
19
  return
package/src/data-grist.ts CHANGED
@@ -10,6 +10,7 @@ import isEqual from 'lodash-es/isEqual'
10
10
  import Headroom from '@operato/headroom'
11
11
  import { pulltorefresh } from '@operato/pull-to-refresh'
12
12
  import { HeadroomStyles, ScrollbarStyles, SpinnerStyles } from '@operato/styles'
13
+ import { PagePreferenceProvider } from '@operato/p13n'
13
14
  import { SnapshotTaker, TimeCapsule } from '@operato/utils'
14
15
 
15
16
  import { buildConfig } from './configure/config-builder'
@@ -29,6 +30,7 @@ import {
29
30
  GristRecord,
30
31
  GristSelectFunction,
31
32
  PaginationConfig,
33
+ PersonalGristPreference,
32
34
  SortersConfig
33
35
  } from './types'
34
36
  import { convertListParamToSearchString, convertSearchStringToListParam } from './utils'
@@ -170,8 +172,21 @@ export class DataGrist extends LitElement implements DataConsumer {
170
172
  */
171
173
  @property({ type: Boolean, attribute: 'url-params-sensitive' }) urlParamsSensitive?: boolean
172
174
 
173
- @state() _data: GristData = ZERO_DATA
174
- @state() _config: GristConfig = ZERO_CONFIG
175
+ @property({ type: Object }) personalConfigProvider: PagePreferenceProvider = {
176
+ load: () => {
177
+ return {}
178
+ },
179
+ save: (preference: any) => preference,
180
+ reset: () => {}
181
+ }
182
+
183
+ @state() personalConfig?: {
184
+ columns?: Partial<ColumnConfig>[]
185
+ [key: string]: any
186
+ }
187
+
188
+ @state() _data: GristData = ZERO_DATA // copy data, dirty data
189
+ @state() _config: GristConfig = ZERO_CONFIG // compiled configuration
175
190
  @state() private _showSpinner: boolean = false
176
191
 
177
192
  @query('slot[name=headroom]') head!: HTMLElement
@@ -188,6 +203,9 @@ export class DataGrist extends LitElement implements DataConsumer {
188
203
  private originMarginTop?: string
189
204
  private lastLocation: { origin?: string; pathname?: string; search?: string } = {}
190
205
 
206
+ /* 그리드가 준비되기 전에 fetch 요청이 있었음을 나타내는 플래그임 */
207
+ private pendingFetch?: boolean
208
+
191
209
  private popstateEventHandler: EventListener = ((e: Event) => {
192
210
  const { origin, pathname, search } = window.location
193
211
  if (
@@ -300,9 +318,61 @@ export class DataGrist extends LitElement implements DataConsumer {
300
318
  }
301
319
  }
302
320
 
303
- private setConfig() {
321
+ public applyUpdatedConfiguration() {
322
+ if (!this.personalConfig || !this.config) {
323
+ return
324
+ }
325
+
326
+ const config = { ...this.config }
327
+ const columns: Partial<ColumnConfig>[] = config.columns
328
+
329
+ const { columns: personalColumns, sorters, pagination, mode } = this.personalConfig
330
+
331
+ if (personalColumns) {
332
+ const xcolumns = columns.map((column: Partial<ColumnConfig>) => {
333
+ const personalColumn = personalColumns.find(pcolumn => pcolumn.name == column.name)
334
+ return personalColumn ? { ...column, ...personalColumn } : column
335
+ })
336
+
337
+ function reorderList(a: { name: string }[], b: { name: string }[]): { name: string }[] {
338
+ // 결과 배열 초기화, a 배열 길이만큼 undefined로 채움
339
+ const result = new Array(a.length)
340
+
341
+ // b 배열에 없는 아이템은 원래 위치로 채움
342
+ a.forEach((item, index) => {
343
+ if (!item.name || !b.find(bi => bi.name == item.name)) {
344
+ result[index] = item
345
+ }
346
+ })
347
+
348
+ b.forEach(item => {
349
+ const ai = a.find(ai => ai.name == item.name)
350
+ if (ai) {
351
+ result[result.findIndex(slot => slot === undefined)] = ai
352
+ }
353
+ })
354
+
355
+ return result
356
+ }
357
+
358
+ // 배열 재정렬 실행
359
+ config.columns = reorderList(xcolumns as any, personalColumns as any)
360
+ }
361
+
362
+ if (pagination) {
363
+ config.pagination = pagination
364
+ }
365
+
366
+ if (sorters) {
367
+ config.sorters = sorters
368
+ }
369
+
370
+ if (mode) {
371
+ this.mode = mode
372
+ }
373
+
304
374
  this._config = buildConfig({
305
- ...this.config
375
+ ...config
306
376
  })
307
377
 
308
378
  this.dispatchEvent(
@@ -348,7 +418,8 @@ export class DataGrist extends LitElement implements DataConsumer {
348
418
  this.dataProvider.limit = limit || pages[0] || ZERO_PAGES[0]
349
419
  }
350
420
 
351
- if (!this.urlParamsSensitive && !this.explicitFetch) {
421
+ if (this.pendingFetch || (!this.urlParamsSensitive && !this.explicitFetch)) {
422
+ this.pendingFetch = false
352
423
  this.fetch()
353
424
  }
354
425
  }
@@ -490,9 +561,10 @@ export class DataGrist extends LitElement implements DataConsumer {
490
561
  * @param {boolean} reset - If true, the method resets the scroll position to the top.
491
562
  */
492
563
  async fetch(reset = true) {
493
- if (!this.compiledConfig) {
564
+ if (this.compiledConfig === ZERO_CONFIG) {
494
565
  /* avoid to be here */
495
566
  console.warn('grist is not configured yet.')
567
+ this.pendingFetch = true
496
568
  return
497
569
  }
498
570
 
@@ -518,6 +590,8 @@ export class DataGrist extends LitElement implements DataConsumer {
518
590
  sortings: this.sorters || this.compiledConfig?.sorters,
519
591
  filters: this.filters
520
592
  })
593
+
594
+ this.pagination && (this.pagination!.limit = limit)
521
595
  }
522
596
  }
523
597
  }
@@ -533,8 +607,10 @@ export class DataGrist extends LitElement implements DataConsumer {
533
607
  await this.requestUpdate()
534
608
  }
535
609
 
536
- if (changes.has('config')) {
537
- this.setConfig()
610
+ if (changes.has('personalConfigProvider')) {
611
+ this.personalConfig = await this.personalConfigProvider.load()
612
+ } else if (changes.has('config') || changes.has('personalConfig')) {
613
+ this.applyUpdatedConfiguration()
538
614
  }
539
615
 
540
616
  if (changes.has('fetchHandler')) {
@@ -1093,4 +1169,8 @@ export class DataGrist extends LitElement implements DataConsumer {
1093
1169
  })
1094
1170
  )
1095
1171
  }
1172
+
1173
+ getCurrentLimit() {
1174
+ return this.dataProvider?.limit || ZERO_PAGINATION.limit
1175
+ }
1096
1176
  }
@@ -17,20 +17,20 @@ export class DataListField extends LitElement {
17
17
  position: relative;
18
18
 
19
19
  white-space: normal;
20
- padding: 1px 7px 1px 0;
20
+ padding: var(--spacing-tiny) var(--spacing-small);
21
21
 
22
22
  font: inherit;
23
23
  }
24
24
 
25
25
  :host > * {
26
26
  flex: 1;
27
- margin: 0;
27
+ margin: var(--spacing-none);
28
28
  text-align: left;
29
29
  }
30
30
 
31
31
  :host > *[center] {
32
32
  flex: none;
33
- margin: 0 auto;
33
+ margin: var(--spacing-none) auto;
34
34
  }
35
35
 
36
36
  :host([thumbnail]) {
@@ -43,8 +43,8 @@ export class DataListField extends LitElement {
43
43
  object-fit: contain;
44
44
  width: 100%;
45
45
  height: 100%;
46
- padding: 0;
47
- margin: 0;
46
+ padding: var(--spacing-none)
47
+ margin: var(--spacing-none)
48
48
  }
49
49
 
50
50
  label {
@@ -23,7 +23,7 @@ export class DataListGutter extends LitElement {
23
23
  text-overflow: ellipsis;
24
24
  color: var(--grid-record-color);
25
25
 
26
- padding-right: 10px;
26
+ padding-right: var(--spacing-medium);
27
27
  }
28
28
 
29
29
  :host-context(.expand)::after {
@@ -38,12 +38,12 @@ export class DataListGutter extends LitElement {
38
38
 
39
39
  * {
40
40
  flex: 1;
41
- margin: 0;
41
+ margin: var(--spacing-none);
42
42
  }
43
43
 
44
44
  *[center] {
45
45
  flex: none;
46
- margin: 0 auto;
46
+ margin: var(--spacing-none) auto;
47
47
  }
48
48
  `
49
49
  ]
@@ -17,7 +17,7 @@ export class DataList extends DataManipulator {
17
17
  }
18
18
 
19
19
  ox-record-partial:nth-child(even) {
20
- background-color: var(--theme-white-color);
20
+ background-color: var(--grid-record-odd-background-color);
21
21
  }
22
22
 
23
23
  [selected-row] {
@@ -25,15 +25,15 @@ export class DataList extends DataManipulator {
25
25
  }
26
26
 
27
27
  #upward {
28
- --md-icon-size: 26px;
28
+ --md-icon-size: var(--icon-size-large);
29
29
  position: absolute;
30
30
  top: var(--data-list-fab-position-vertical);
31
31
  right: var(--data-list-fab-position-horizontal);
32
32
  background-color: rgba(255, 255, 255, 0.7);
33
- border-radius: 20px;
33
+ border-radius: var(--md-sys-shape-corner-large);
34
34
  color: var(--data-list-fab-color);
35
35
  box-shadow: var(--data-list-fab-shadow);
36
- padding: 7px;
36
+ padding: var(--spacing-small);
37
37
  }
38
38
 
39
39
  slot {
@@ -39,29 +39,29 @@ export class RecordPartial extends LitElement {
39
39
  border-bottom: var(--data-list-item-border-bottom);
40
40
  position: relative;
41
41
  min-height: 42px;
42
- padding-left: 7px;
42
+ padding-left: var(--spacing-medium);
43
43
  }
44
44
 
45
45
  :host([dirty])::before {
46
46
  content: '';
47
47
  position: absolute;
48
- left: 0;
49
- top: 0;
48
+ left: var(--spacing-none);
49
+ top: var(--spacing-none);
50
50
 
51
- width: 0px;
52
- height: 0px;
51
+ width: var(--spacing-none);
52
+ height: var(--spacing-none);
53
53
  border-top: var(--grid-record-dirty-border-top);
54
54
  border-right: var(--grid-record-dirty-border-left);
55
55
  }
56
56
 
57
57
  :host [dirty] {
58
58
  position: absolute;
59
- margin: 0;
59
+ margin: var(--spacing-none);
60
60
  height: 20px;
61
61
  font: var(--grid-record-dirty-icon-font);
62
62
  text-indent: 1px;
63
- left: 0;
64
- top: 0;
63
+ left: var(--spacing-none);
64
+ top: var(--spacing-none);
65
65
  color: var(--grid-record-dirty-color);
66
66
  }
67
67
 
@@ -72,7 +72,7 @@ export class RecordPartial extends LitElement {
72
72
  }
73
73
 
74
74
  div[tail] {
75
- margin: 0;
75
+ margin: var(--spacing-none);
76
76
  width: 100px;
77
77
  aspect-ratio: 1 / 1;
78
78
 
@@ -87,7 +87,6 @@ export class RecordPartial extends LitElement {
87
87
  }
88
88
 
89
89
  ox-list-field {
90
- padding-top: 3px;
91
90
  font: var(--data-list-item-etc-font);
92
91
  color: var(--data-list-item-etc-color);
93
92
  }
@@ -22,7 +22,7 @@ export class DataManipulator extends LitElement {
22
22
  constructor() {
23
23
  super()
24
24
 
25
- this.addEventListener('select-record-change', e => {
25
+ this.addEventListener('select-record-change', async e => {
26
26
  var {
27
27
  records: selectedRecords,
28
28
  added = [],
@@ -41,7 +41,7 @@ export class DataManipulator extends LitElement {
41
41
  })
42
42
 
43
43
  /* field change processing */
44
- this.addEventListener('field-change', e => {
44
+ this.addEventListener('field-change', async e => {
45
45
  var { after, before, column, record, row } = (e as CustomEvent).detail as {
46
46
  after: any
47
47
  before: any
@@ -50,7 +50,7 @@ export class DataManipulator extends LitElement {
50
50
  row: number
51
51
  }
52
52
 
53
- this.onFieldChange({ after, before, column, record, row })
53
+ await this.onFieldChange({ after, before, column, record, row })
54
54
  })
55
55
 
56
56
  /* record reset processing */
@@ -76,7 +76,7 @@ export class DataManipulator extends LitElement {
76
76
  this.addEventListener('add-child-node', (e: Event) => this.addChildNode((e as CustomEvent).detail as GristRecord))
77
77
  }
78
78
 
79
- onFieldChange({
79
+ async onFieldChange({
80
80
  after,
81
81
  before,
82
82
  column,
@@ -96,7 +96,7 @@ export class DataManipulator extends LitElement {
96
96
 
97
97
  var validation = column.validation
98
98
  if (validation && typeof validation == 'function') {
99
- if (!validation.call(this, after, before, record, column)) {
99
+ if (!(await validation.call(this, after, before, record, column))) {
100
100
  return
101
101
  }
102
102
  }
@@ -25,7 +25,8 @@ export class DataReportField extends LitElement {
25
25
  font-size: var(--report-record-wide-fontsize);
26
26
  text-overflow: ellipsis;
27
27
 
28
- min-height: 19px;
28
+ min-height: 30px;
29
+ box-sizing: border-box;
29
30
  }
30
31
 
31
32
  :host([gutter]) * {
@@ -73,7 +73,7 @@ class DataReportHeader extends LitElement {
73
73
 
74
74
  private throttledNotifier?: (idx: number, width: number) => void
75
75
 
76
- _onWheelEvent(e: WheelEvent) {
76
+ onWheelEvent(e: WheelEvent) {
77
77
  if (this.scrollWidth > this.clientWidth) {
78
78
  var delta = Math.max(-1, Math.min(1, e.deltaY || 0))
79
79
  this.scrollLeft = Math.max(0, this.scrollLeft - delta * 40)
@@ -94,7 +94,7 @@ class DataReportHeader extends LitElement {
94
94
  }
95
95
 
96
96
  firstUpdated() {
97
- this.addEventListener('wheel', this._onWheelEvent.bind(this))
97
+ this.addEventListener('wheel', this.onWheelEvent.bind(this))
98
98
  }
99
99
 
100
100
  async updated(changed: PropertyValues<this>) {