@operato/data-grist 1.0.0-beta.8 → 1.0.1

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 (203) hide show
  1. package/.storybook/main.js +3 -0
  2. package/.storybook/server.mjs +8 -0
  3. package/CHANGELOG.md +411 -0
  4. package/demo/data-grist-test.html +1 -1
  5. package/demo/index.html +13 -2
  6. package/demo/report-test.html +1 -1
  7. package/dist/src/configure/zero-config.d.ts +2 -0
  8. package/dist/src/configure/zero-config.js +3 -1
  9. package/dist/src/configure/zero-config.js.map +1 -1
  10. package/dist/src/data-card/data-card-field.d.ts +1 -1
  11. package/dist/src/data-card/data-card-field.js +3 -2
  12. package/dist/src/data-card/data-card-field.js.map +1 -1
  13. package/dist/src/data-card/data-card.js +1 -0
  14. package/dist/src/data-card/data-card.js.map +1 -1
  15. package/dist/src/data-grid/data-grid-body.d.ts +4 -2
  16. package/dist/src/data-grid/data-grid-body.js +74 -40
  17. package/dist/src/data-grid/data-grid-body.js.map +1 -1
  18. package/dist/src/data-grid/data-grid-field.d.ts +1 -1
  19. package/dist/src/data-grid/data-grid-field.js +1 -1
  20. package/dist/src/data-grid/data-grid-field.js.map +1 -1
  21. package/dist/src/data-grid/data-grid-footer.d.ts +2 -2
  22. package/dist/src/data-grid/data-grid-footer.js +9 -10
  23. package/dist/src/data-grid/data-grid-footer.js.map +1 -1
  24. package/dist/src/data-grid/data-grid-header.d.ts +4 -6
  25. package/dist/src/data-grid/data-grid-header.js +39 -48
  26. package/dist/src/data-grid/data-grid-header.js.map +1 -1
  27. package/dist/src/data-grid/data-grid.d.ts +2 -2
  28. package/dist/src/data-grid/data-grid.js +4 -3
  29. package/dist/src/data-grid/data-grid.js.map +1 -1
  30. package/dist/src/data-grid/event-handlers/data-grid-body-click-handler.js +9 -11
  31. package/dist/src/data-grid/event-handlers/data-grid-body-click-handler.js.map +1 -1
  32. package/dist/src/data-grist.d.ts +7 -5
  33. package/dist/src/data-grist.js +154 -112
  34. package/dist/src/data-grist.js.map +1 -1
  35. package/dist/src/data-list/record-partial.js +1 -5
  36. package/dist/src/data-list/record-partial.js.map +1 -1
  37. package/dist/src/data-manipulator.d.ts +4 -1
  38. package/dist/src/data-manipulator.js +12 -0
  39. package/dist/src/data-manipulator.js.map +1 -1
  40. package/dist/src/data-provider.d.ts +4 -6
  41. package/dist/src/data-provider.js +12 -23
  42. package/dist/src/data-provider.js.map +1 -1
  43. package/dist/src/data-report/data-report-body.d.ts +1 -1
  44. package/dist/src/data-report/data-report-body.js +4 -4
  45. package/dist/src/data-report/data-report-body.js.map +1 -1
  46. package/dist/src/data-report/data-report-header.js +4 -4
  47. package/dist/src/data-report/data-report-header.js.map +1 -1
  48. package/dist/src/editors/ox-grist-editor.d.ts +1 -1
  49. package/dist/src/editors/ox-grist-editor.js +7 -4
  50. package/dist/src/editors/ox-grist-editor.js.map +1 -1
  51. package/dist/src/filters/filter-checkbox.d.ts +1 -1
  52. package/dist/src/filters/filter-checkbox.js +1 -1
  53. package/dist/src/filters/filter-checkbox.js.map +1 -1
  54. package/dist/src/filters/filter-input-barcode.d.ts +3 -0
  55. package/dist/src/filters/filter-input-barcode.js +27 -0
  56. package/dist/src/filters/filter-input-barcode.js.map +1 -0
  57. package/dist/src/filters/filter-input.js +1 -1
  58. package/dist/src/filters/filter-input.js.map +1 -1
  59. package/dist/src/filters/filter-styles.js +65 -17
  60. package/dist/src/filters/filter-styles.js.map +1 -1
  61. package/dist/src/filters/filters-form.js +16 -15
  62. package/dist/src/filters/filters-form.js.map +1 -1
  63. package/dist/src/filters/registry.d.ts +1 -1
  64. package/dist/src/filters/registry.js +10 -7
  65. package/dist/src/filters/registry.js.map +1 -1
  66. package/dist/src/gutters/gutter-button.js +5 -4
  67. package/dist/src/gutters/gutter-button.js.map +1 -1
  68. package/dist/src/gutters/gutter-dirty.d.ts +5 -1
  69. package/dist/src/gutters/gutter-dirty.js +17 -2
  70. package/dist/src/gutters/gutter-dirty.js.map +1 -1
  71. package/dist/src/gutters/gutter-row-selector.js +2 -1
  72. package/dist/src/gutters/gutter-row-selector.js.map +1 -1
  73. package/dist/src/gutters/gutter-sequence.js +15 -0
  74. package/dist/src/gutters/gutter-sequence.js.map +1 -1
  75. package/dist/src/record-view/event-handlers/record-view-body-click-handler.js +2 -4
  76. package/dist/src/record-view/event-handlers/record-view-body-click-handler.js.map +1 -1
  77. package/dist/src/record-view/event-handlers/record-view-body-keydown-handler.js +2 -2
  78. package/dist/src/record-view/event-handlers/record-view-body-keydown-handler.js.map +1 -1
  79. package/dist/src/record-view/record-creator.js +0 -2
  80. package/dist/src/record-view/record-creator.js.map +1 -1
  81. package/dist/src/record-view/record-view-body.d.ts +0 -1
  82. package/dist/src/record-view/record-view-body.js +0 -5
  83. package/dist/src/record-view/record-view-body.js.map +1 -1
  84. package/dist/src/record-view/record-view-handler.d.ts +1 -1
  85. package/dist/src/record-view/record-view.d.ts +0 -1
  86. package/dist/src/record-view/record-view.js +1 -10
  87. package/dist/src/record-view/record-view.js.map +1 -1
  88. package/dist/src/renderers/ox-grist-renderer-color.js +1 -1
  89. package/dist/src/renderers/ox-grist-renderer-color.js.map +1 -1
  90. package/dist/src/renderers/ox-grist-renderer-json5.js +1 -1
  91. package/dist/src/renderers/ox-grist-renderer-json5.js.map +1 -1
  92. package/dist/src/renderers/ox-grist-renderer-link.js +1 -1
  93. package/dist/src/renderers/ox-grist-renderer-link.js.map +1 -1
  94. package/dist/src/renderers/ox-grist-renderer-select.js +2 -2
  95. package/dist/src/renderers/ox-grist-renderer-select.js.map +1 -1
  96. package/dist/src/renderers/ox-grist-renderer-text.js +6 -2
  97. package/dist/src/renderers/ox-grist-renderer-text.js.map +1 -1
  98. package/dist/src/sorters/sorters-control.d.ts +1 -1
  99. package/dist/src/sorters/sorters-control.js +5 -7
  100. package/dist/src/sorters/sorters-control.js.map +1 -1
  101. package/dist/src/types.d.ts +7 -4
  102. package/dist/src/types.js.map +1 -1
  103. package/dist/stories/{index.stories.d.ts → barcode-input-filter.stories.d.ts} +9 -13
  104. package/dist/stories/barcode-input-filter.stories.js +200 -0
  105. package/dist/stories/barcode-input-filter.stories.js.map +1 -0
  106. package/dist/stories/default-filters.stories.d.ts +20 -0
  107. package/dist/stories/default-filters.stories.js +187 -0
  108. package/dist/stories/default-filters.stories.js.map +1 -0
  109. package/dist/stories/empty-sorters.stories.d.ts +20 -0
  110. package/dist/stories/empty-sorters.stories.js +180 -0
  111. package/dist/stories/empty-sorters.stories.js.map +1 -0
  112. package/dist/stories/explicit-fetch.stories.d.ts +25 -0
  113. package/dist/stories/explicit-fetch.stories.js +186 -0
  114. package/dist/stories/explicit-fetch.stories.js.map +1 -0
  115. package/dist/stories/grist-modes.stories.d.ts +36 -0
  116. package/dist/stories/grist-modes.stories.js +448 -0
  117. package/dist/stories/grist-modes.stories.js.map +1 -0
  118. package/dist/tsconfig.tsbuildinfo +1 -1
  119. package/package.json +11 -11
  120. package/src/configure/zero-config.ts +4 -1
  121. package/src/data-card/data-card-field.ts +5 -3
  122. package/src/data-card/data-card.ts +1 -0
  123. package/src/data-grid/data-grid-body.ts +96 -49
  124. package/src/data-grid/data-grid-field.ts +3 -2
  125. package/src/data-grid/data-grid-footer.ts +8 -9
  126. package/src/data-grid/data-grid-header.ts +38 -47
  127. package/src/data-grid/data-grid.ts +8 -6
  128. package/src/data-grid/event-handlers/data-grid-body-click-handler.ts +11 -13
  129. package/src/data-grist.ts +179 -130
  130. package/src/data-list/record-partial.ts +1 -5
  131. package/src/data-manipulator.ts +12 -1
  132. package/src/data-provider.ts +13 -29
  133. package/src/data-report/data-report-body.ts +5 -5
  134. package/src/data-report/data-report-header.ts +5 -5
  135. package/src/editors/ox-grist-editor.ts +8 -5
  136. package/src/filters/filter-checkbox.ts +3 -3
  137. package/src/filters/filter-input-barcode.ts +33 -0
  138. package/src/filters/filter-input.ts +3 -3
  139. package/src/filters/filter-styles.ts +65 -17
  140. package/src/filters/filters-form.ts +19 -15
  141. package/src/filters/registry.ts +11 -8
  142. package/src/gutters/gutter-button.ts +5 -4
  143. package/src/gutters/gutter-dirty.ts +21 -3
  144. package/src/gutters/gutter-row-selector.ts +2 -1
  145. package/src/gutters/gutter-sequence.ts +18 -2
  146. package/src/record-view/event-handlers/record-view-body-click-handler.ts +2 -4
  147. package/src/record-view/event-handlers/record-view-body-keydown-handler.ts +2 -2
  148. package/src/record-view/record-creator.ts +0 -2
  149. package/src/record-view/record-view-body.ts +0 -2
  150. package/src/record-view/record-view.ts +1 -7
  151. package/src/renderers/ox-grist-renderer-color.ts +3 -2
  152. package/src/renderers/ox-grist-renderer-json5.ts +3 -2
  153. package/src/renderers/ox-grist-renderer-link.ts +3 -2
  154. package/src/renderers/ox-grist-renderer-select.ts +2 -2
  155. package/src/renderers/ox-grist-renderer-text.ts +8 -2
  156. package/src/sorters/sorters-control.ts +6 -9
  157. package/src/types.ts +8 -4
  158. package/stories/barcode-input-filter.stories.ts +220 -0
  159. package/stories/default-filters.stories.ts +204 -0
  160. package/stories/empty-sorters.stories.ts +197 -0
  161. package/stories/explicit-fetch.stories.ts +205 -0
  162. package/stories/grist-modes.stories.ts +488 -0
  163. package/themes/form-theme.css +75 -0
  164. package/themes/grist-theme.css +1 -1
  165. package/dist/src/editors/image-input.d.ts +0 -7
  166. package/dist/src/editors/image-input.js +0 -31
  167. package/dist/src/editors/image-input.js.map +0 -1
  168. package/dist/src/editors/input-editors.d.ts +0 -68
  169. package/dist/src/editors/input-editors.js +0 -329
  170. package/dist/src/editors/input-editors.js.map +0 -1
  171. package/dist/src/renderers/boolean-renderer.d.ts +0 -2
  172. package/dist/src/renderers/boolean-renderer.js +0 -30
  173. package/dist/src/renderers/boolean-renderer.js.map +0 -1
  174. package/dist/src/renderers/color-renderer.d.ts +0 -2
  175. package/dist/src/renderers/color-renderer.js +0 -6
  176. package/dist/src/renderers/color-renderer.js.map +0 -1
  177. package/dist/src/renderers/date-renderer.d.ts +0 -2
  178. package/dist/src/renderers/date-renderer.js +0 -52
  179. package/dist/src/renderers/date-renderer.js.map +0 -1
  180. package/dist/src/renderers/image-renderer.d.ts +0 -2
  181. package/dist/src/renderers/image-renderer.js +0 -24
  182. package/dist/src/renderers/image-renderer.js.map +0 -1
  183. package/dist/src/renderers/json5-renderer.d.ts +0 -2
  184. package/dist/src/renderers/json5-renderer.js +0 -7
  185. package/dist/src/renderers/json5-renderer.js.map +0 -1
  186. package/dist/src/renderers/link-renderer.d.ts +0 -2
  187. package/dist/src/renderers/link-renderer.js +0 -12
  188. package/dist/src/renderers/link-renderer.js.map +0 -1
  189. package/dist/src/renderers/password-renderer.d.ts +0 -2
  190. package/dist/src/renderers/password-renderer.js +0 -4
  191. package/dist/src/renderers/password-renderer.js.map +0 -1
  192. package/dist/src/renderers/progress-renderer.d.ts +0 -2
  193. package/dist/src/renderers/progress-renderer.js +0 -68
  194. package/dist/src/renderers/progress-renderer.js.map +0 -1
  195. package/dist/src/renderers/select-renderer.d.ts +0 -2
  196. package/dist/src/renderers/select-renderer.js +0 -15
  197. package/dist/src/renderers/select-renderer.js.map +0 -1
  198. package/dist/src/renderers/text-renderer.d.ts +0 -2
  199. package/dist/src/renderers/text-renderer.js +0 -6
  200. package/dist/src/renderers/text-renderer.js.map +0 -1
  201. package/dist/stories/index.stories.js +0 -33
  202. package/dist/stories/index.stories.js.map +0 -1
  203. package/stories/index.stories.ts +0 -52
@@ -0,0 +1,33 @@
1
+ import '@operato/input/ox-input-barcode.js'
2
+
3
+ import { html } from 'lit-html'
4
+
5
+ import { FilterConfigObject, FilterSelectRenderer } from '../types.js'
6
+
7
+ export const FilterInputBarcode: FilterSelectRenderer = (column, value, owner) => {
8
+ const filter = column.filter as FilterConfigObject
9
+ const { englishOnly, selectAfterChange } = filter.options || {}
10
+
11
+ return html`
12
+ <ox-input-barcode
13
+ name=${column.name}
14
+ ?english-only=${englishOnly}
15
+ ?select-after-change=${selectAfterChange}
16
+ .value=${value == null ? '' : value}
17
+ @change=${(e: CustomEvent) => {
18
+ const input = e.target as HTMLInputElement
19
+ input.dispatchEvent(
20
+ new CustomEvent('filter-change', {
21
+ bubbles: true,
22
+ composed: true,
23
+ detail: {
24
+ name: column.name,
25
+ operator: filter.operator,
26
+ value: input.value
27
+ }
28
+ })
29
+ )
30
+ }}
31
+ />
32
+ `
33
+ }
@@ -1,7 +1,7 @@
1
- import { FilterConfigObject, FilterSelectRenderer } from '../types'
2
-
3
1
  import { html } from 'lit-html'
4
2
 
3
+ import { FilterConfigObject, FilterSelectRenderer } from '../types'
4
+
5
5
  export const FilterInput: FilterSelectRenderer = (column, value, owner) => {
6
6
  const filter = column.filter as FilterConfigObject
7
7
  const type = filter?.type || column.type
@@ -10,7 +10,7 @@ export const FilterInput: FilterSelectRenderer = (column, value, owner) => {
10
10
  <input
11
11
  type=${type}
12
12
  name=${column.name}
13
- .value=${value === undefined ? '' : value}
13
+ .value=${value == null ? '' : value}
14
14
  @change=${(e: CustomEvent) => {
15
15
  const input = e.target as HTMLInputElement
16
16
  input.dispatchEvent(
@@ -6,35 +6,83 @@ export const FilterStyles = css`
6
6
 
7
7
  --ox-input-padding: var(--padding-narrow) var(--padding-default);
8
8
  --ox-input-border: 1px solid rgba(0, 0, 0, 0.2);
9
+ --ox-input-focus-border: 1px solid var(--primary-color);
9
10
  --ox-input-border-radius: var(--border-radius);
10
11
  --ox-input-font: normal 14px var(--theme-font);
11
12
  --ox-input-color: var(--primary-text-color);
13
+
14
+ --ox-filters-form-gap: var(--margin-wide);
15
+ --ox-filters-form-label-font: var(--label-font);
16
+ --ox-filters-form-label-color: var(--label-color);
17
+ --ox-select-padding: 0 var(--padding-narrow);
18
+ }
19
+
20
+ label {
21
+ font: var(--ox-filters-form-label-font);
22
+ color: var(--ox-filters-form-label-color);
23
+ }
24
+ span {
25
+ margin-right: var(--margin-narrow);
26
+ text-transform: capitalize;
12
27
  }
13
28
 
14
- [filter] input::placeholder {
29
+ input::placeholder {
15
30
  color: var(--ox-input-placeholder-color);
16
- opacity: 0.7;
31
+ opacity: 0.6;
17
32
  }
18
- [filter] input {
19
- margin: 0 10px 5px 10px;
20
- padding: var(--ox-input-padding);
21
- border: var(--ox-input-border);
22
- border-radius: var(--ox-input-border-radius);
33
+
34
+ ox-select,
35
+ input {
36
+ padding: var(--input-padding);
37
+ border: none;
38
+ border-bottom: var(--ox-input-border);
23
39
  font: var(--ox-input-font);
24
- color: var(--ox-input-color, #3a5877);
40
+ color: var(--ox-input-color);
25
41
  }
26
- [filter] input[type='number'] {
27
- padding-right: var(--padding-narrow);
28
- max-width: 100px;
42
+
43
+ ox-select:focus,
44
+ input:focus {
45
+ outline: none;
46
+ border-bottom: var(--ox-input-focus-border);
47
+ color: var(--primary-color);
48
+ }
49
+ ox-select {
50
+ padding: var(--ox-select-padding);
29
51
  }
30
- [filter] input[type='datetime-local'] {
52
+
53
+ input[type='number'] {
31
54
  padding-right: var(--padding-narrow);
32
- max-width: 170px;
55
+ max-width: 90px;
33
56
  }
34
- [filter] input[name='from'] {
35
- margin: 0 0 5px 10px;
57
+
58
+ input[type*='date'],
59
+ input[type*='time'],
60
+ input[type='week'],
61
+ input[type='month'] {
62
+ padding: 8px var(--padding-narrow) 8px var(--padding-default);
63
+ max-width: 170px;
36
64
  }
37
- [filter] input[name='to'] {
38
- margin: 0 10px 5px 0;
65
+
66
+ @media only screen and (max-width: 460px) {
67
+ :host {
68
+ --ox-filters-form-label-font: bold 13px var(--theme-font);
69
+ --ox-input-font: normal 16px var(--theme-font);
70
+ --ox-filters-form-gap: var(--margin-narrow);
71
+ }
72
+
73
+ ox-checkbox {
74
+ margin-top: var(--margin-narrow);
75
+ }
76
+
77
+ input[from],
78
+ input[to] {
79
+ max-width: 44%;
80
+ }
81
+
82
+ input[type*='datetime'][from],
83
+ input[type*='datetime'][to] {
84
+ padding-right: var(--padding-narrow);
85
+ min-width: 91%;
86
+ }
39
87
  }
40
88
  `
@@ -33,9 +33,8 @@ export class FiltersForm extends LitElement {
33
33
  flex: 1;
34
34
 
35
35
  display: flex;
36
- flex-direction: row;
37
- flex-wrap: wrap;
38
- gap: 20px;
36
+ flex-flow: row wrap;
37
+ gap: var(--ox-filters-form-gap);
39
38
  }
40
39
 
41
40
  form > * {
@@ -43,23 +42,16 @@ export class FiltersForm extends LitElement {
43
42
  align-items: center;
44
43
  }
45
44
 
46
- span {
47
- margin-right: 5px;
48
- }
49
-
50
45
  @media only screen and (max-width: 460px) {
51
46
  form {
52
- display: block;
47
+ flex-direction: column;
53
48
  }
54
49
 
55
50
  label,
51
+ label span,
56
52
  ox-select {
57
53
  display: block;
58
54
  }
59
-
60
- label * {
61
- display: block;
62
- }
63
55
  }
64
56
  `
65
57
  ]
@@ -85,7 +77,7 @@ export class FiltersForm extends LitElement {
85
77
  this.config = (e as CustomEvent).detail
86
78
  })
87
79
 
88
- grist.addEventListener('filters-change', (e: Event) => {
80
+ grist.addEventListener('fetch-params-change', (e: Event) => {
89
81
  const { filters, from } = (e as CustomEvent).detail || {}
90
82
  if (from === 'filters-form') {
91
83
  return
@@ -96,7 +88,7 @@ export class FiltersForm extends LitElement {
96
88
 
97
89
  this.renderRoot.addEventListener('change', async (e: Event) => {
98
90
  this.dispatchEvent(
99
- new CustomEvent('filters-change', {
91
+ new CustomEvent('fetch-params-change', {
100
92
  bubbles: true,
101
93
  composed: true,
102
94
  detail: {
@@ -124,6 +116,14 @@ export class FiltersForm extends LitElement {
124
116
  }
125
117
 
126
118
  render(): TemplateResult {
119
+ const { name: firstSearchFilterName } = this.searchColumns[0] || {}
120
+ const searchValue =
121
+ (firstSearchFilterName &&
122
+ (this.value?.find(filter => filter.name === firstSearchFilterName)?.value as string)?.match(
123
+ /^\%(.*)\%$/
124
+ )?.[1]) ||
125
+ ''
126
+
127
127
  return html`
128
128
  <form
129
129
  @submit=${(e: Event) => {
@@ -135,7 +135,11 @@ export class FiltersForm extends LitElement {
135
135
  grist && grist.fetch()
136
136
  }}
137
137
  >
138
- ${this.searchColumns.length === 0 ? html`` : html` <ox-input-search name="search"></ox-input-search> `}
138
+ ${this.searchColumns.length === 0
139
+ ? html``
140
+ : html`
141
+ <ox-input-search name="search" .value=${searchValue} ?autofocus=${this.autofocus}></ox-input-search>
142
+ `}
139
143
  ${this.filterColumns.map((column: ColumnConfig) => {
140
144
  const { name, header, label, filter } = column
141
145
  const labelText =
@@ -1,9 +1,10 @@
1
- import { FilterSelectRenderer } from '../types'
2
- import { FilterCheckbox } from './filter-checkbox'
3
- import { FilterInput } from './filter-input'
4
- import { FilterRangeDate } from './filter-range-date'
5
- import { FilterRangeNumber } from './filter-range-number'
6
- import { FilterSelect } from './filter-select'
1
+ import { FilterSelectRenderer } from '../types.js'
2
+ import { FilterCheckbox } from './filter-checkbox.js'
3
+ import { FilterInputBarcode } from './filter-input-barcode.js'
4
+ import { FilterInput } from './filter-input.js'
5
+ import { FilterRangeDate } from './filter-range-date.js'
6
+ import { FilterRangeNumber } from './filter-range-number.js'
7
+ import { FilterSelect } from './filter-select.js'
7
8
 
8
9
  var RENDERERS: {
9
10
  [name: string]: FilterSelectRenderer[]
@@ -27,7 +28,9 @@ var RENDERERS: {
27
28
  progress: [FilterInput, FilterRangeNumber],
28
29
  link: [FilterInput],
29
30
  image: [FilterInput],
30
- json5: [FilterInput]
31
+ json5: [FilterInput],
32
+ scanner: [FilterInputBarcode],
33
+ barcode: [FilterInputBarcode]
31
34
  }
32
35
 
33
36
  export function registerFilterRenderer(type: string, renderer: FilterSelectRenderer[]) {
@@ -43,7 +46,7 @@ export function getFilterRenderers(): { [name: string]: FilterSelectRenderer[] }
43
46
  }
44
47
 
45
48
  export function getFilterRenderer(type: string): FilterSelectRenderer[] {
46
- if (typeof type == 'function') {
49
+ if (typeof type === 'function') {
47
50
  return type
48
51
  }
49
52
 
@@ -6,7 +6,7 @@ import { FieldRenderer, HeaderRenderer } from '../types'
6
6
 
7
7
  export class GutterButton {
8
8
  static instance(config: any = {}) {
9
- var { icon = 'edit' } = config
9
+ var { icon = 'edit', title } = config
10
10
 
11
11
  var iconFn = typeof icon == 'function' ? icon : () => icon
12
12
 
@@ -23,17 +23,18 @@ export class GutterButton {
23
23
  sortable: false,
24
24
  header: {
25
25
  renderer: function (column) {
26
- return html` <mwc-icon style=${inlineHeaderStyle}>${iconFn()}</mwc-icon> `
26
+ return html` <mwc-icon style=${inlineHeaderStyle} title=${title}>${iconFn()}</mwc-icon> `
27
27
  } as HeaderRenderer
28
28
  },
29
29
  record: {
30
30
  align: 'center',
31
31
  renderer: function (value, column, record, rowIndex, field) {
32
- return html` <mwc-icon style=${inlineRecordStyle}>${iconFn(record)}</mwc-icon> `
32
+ return html` <mwc-icon style=${inlineRecordStyle} title=${title}>${iconFn(record)}</mwc-icon> `
33
33
  } as FieldRenderer
34
34
  },
35
35
  forGrid: true,
36
- forList: true
36
+ forList: true,
37
+ forCard: true
37
38
  },
38
39
  config
39
40
  )
@@ -1,9 +1,10 @@
1
1
  import '@material/mwc-icon'
2
2
 
3
- import { ColumnConfig, FieldRenderer } from '../types'
4
- import { LitElement, css, html } from 'lit'
3
+ import { css, html, LitElement } from 'lit'
5
4
  import { customElement, property } from 'lit/decorators.js'
6
5
 
6
+ import { ColumnConfig, FieldRenderer, GristEventHandler } from '../types'
7
+
7
8
  @customElement('ox-gutter-dirty-element')
8
9
  class GutterDirtyElement extends LitElement {
9
10
  static styles = css`
@@ -65,7 +66,24 @@ export class GutterDirty {
65
66
  } as FieldRenderer
66
67
  },
67
68
  forGrid: true,
68
- forList: false
69
+ forList: false,
70
+ forCard: false,
71
+ handlers: {
72
+ dblclick: ((columns, data, column, record, rowIndex, target) => {
73
+ target.dispatchEvent(
74
+ new CustomEvent('set-select-block', {
75
+ bubbles: true,
76
+ composed: true,
77
+ detail: {
78
+ startRow: rowIndex,
79
+ startColumn: 0,
80
+ endRow: rowIndex,
81
+ endColumn: -1
82
+ }
83
+ })
84
+ )
85
+ }) as GristEventHandler
86
+ }
69
87
  },
70
88
  config
71
89
  )
@@ -77,7 +77,8 @@ export class GutterRowSelector {
77
77
  } as FieldRenderer
78
78
  },
79
79
  forGrid: true,
80
- forList: true
80
+ forList: true,
81
+ forCard: true
81
82
  },
82
83
  config
83
84
  )
@@ -1,8 +1,7 @@
1
- import { ColumnWidthCallback, FieldRenderer } from '../types'
2
-
3
1
  import { DataCard } from '../data-card/data-card'
4
2
  import { DataGrid } from '../data-grid/data-grid'
5
3
  import { DataList } from '../data-list/data-list'
4
+ import { ColumnWidthCallback, FieldRenderer, GristEventHandler } from '../types'
6
5
 
7
6
  export class GutterSequence {
8
7
  static instance(config = {} as any) {
@@ -31,6 +30,23 @@ export class GutterSequence {
31
30
  },
32
31
  forGrid: true,
33
32
  forList: false,
33
+ forCard: false,
34
+ handlers: {
35
+ dblclick: ((columns, data, column, record, rowIndex, target) => {
36
+ target.dispatchEvent(
37
+ new CustomEvent('set-select-block', {
38
+ bubbles: true,
39
+ composed: true,
40
+ detail: {
41
+ startRow: rowIndex,
42
+ startColumn: 0,
43
+ endRow: rowIndex,
44
+ endColumn: -1
45
+ }
46
+ })
47
+ )
48
+ }) as GristEventHandler
49
+ },
34
50
  ...config
35
51
  }
36
52
  }
@@ -12,7 +12,7 @@ export function recordViewBodyClickHandler(this: RecordViewBody, e: Event): void
12
12
  /* target should be 'ox-grid-field' */
13
13
  var target = e.target as DataGridField
14
14
 
15
- if (!this.onlyForEdit && this.currentTarget) {
15
+ if (this.currentTarget) {
16
16
  this.focus()
17
17
  this.currentTarget.removeAttribute('editing')
18
18
  }
@@ -24,7 +24,5 @@ export function recordViewBodyClickHandler(this: RecordViewBody, e: Event): void
24
24
  }
25
25
 
26
26
  this.currentTarget = target
27
- if (!this.onlyForEdit) {
28
- target.setAttribute('editing', 'true')
29
- }
27
+ target.setAttribute('editing', 'true')
30
28
  }
@@ -12,9 +12,9 @@ export async function recordViewBodyKeydownHandler(this: RecordViewBody, e: Even
12
12
  /* TODO 편집이 취소되어야 한다. */
13
13
  case 'Enter':
14
14
  /* 먼저, focus를 옮겨놓아야, focusout 으로 인해서 popup이 닫히는 것을 방지할 수 있다. */
15
- !this.onlyForEdit && this.focus()
15
+ this.focus()
16
16
 
17
- if (!this.onlyForEdit && this.currentTarget) {
17
+ if (this.currentTarget) {
18
18
  this.currentTarget.removeAttribute('editing')
19
19
  }
20
20
 
@@ -53,7 +53,6 @@ export class RecordCreator extends LitElement {
53
53
  template: html`
54
54
  <div title>${title}</div>
55
55
  <ox-record-view
56
- only-for-edit
57
56
  @field-change=${(e: CustomEvent) => {
58
57
  const view = e.currentTarget as RecordView
59
58
 
@@ -116,7 +115,6 @@ export class RecordCreator extends LitElement {
116
115
 
117
116
  var recordView = document.createElement('ox-record-view') as RecordView
118
117
 
119
- recordView.setAttribute('only-for-edit', '')
120
118
  recordView.columns = columns
121
119
  recordView.record = record
122
120
  recordView.rowIndex = rowIndex
@@ -65,7 +65,6 @@ export class RecordViewBody extends LitElement {
65
65
  @property({ type: Array }) columns: ColumnConfig[] = []
66
66
  @property({ type: Object }) record: GristRecord = ZERO_RECORD
67
67
  @property({ type: Number }) rowIndex: number = -1
68
- @property({ type: Boolean, attribute: 'only-for-edit' }) onlyForEdit: boolean = false
69
68
 
70
69
  public currentTarget: any
71
70
 
@@ -98,7 +97,6 @@ export class RecordViewBody extends LitElement {
98
97
  .record=${record}
99
98
  .value=${record[column.name]}
100
99
  ?dirty=${!!dirtyFields[column.name]}
101
- ?editing=${this.onlyForEdit}
102
100
  ></ox-grid-field>
103
101
  `
104
102
  })}
@@ -63,16 +63,10 @@ export class RecordView extends LitElement {
63
63
  @property({ type: Array }) columns: ColumnConfig[] = []
64
64
  @property({ type: Object }) record: GristRecord = ZERO_RECORD
65
65
  @property({ type: Number }) rowIndex: number = -1
66
- @property({ type: Boolean, attribute: 'only-for-edit' }) onlyForEdit: boolean = false
67
66
 
68
67
  render() {
69
68
  return html`
70
- <ox-record-view-body
71
- .columns=${this.columns}
72
- .record=${this.record}
73
- .rowIndex=${this.rowIndex}
74
- ?only-for-edit=${this.onlyForEdit}
75
- >
69
+ <ox-record-view-body .columns=${this.columns} .record=${this.record} .rowIndex=${this.rowIndex}>
76
70
  </ox-record-view-body>
77
71
  <div footer>
78
72
  <button @click=${this.onReset.bind(this)}><mwc-icon>refresh</mwc-icon>Reset</button>
@@ -1,8 +1,9 @@
1
- import { FieldRenderer } from '../types'
2
1
  import { html } from 'lit'
3
2
 
3
+ import { FieldRenderer } from '../types'
4
+
4
5
  export const OxGristRendererColor: FieldRenderer = (value, column, record, rowIndex, field) => {
5
- value = value === undefined ? '#000' : value
6
+ value = value == null ? '#000' : value
6
7
 
7
8
  return html`
8
9
  <div
@@ -1,7 +1,8 @@
1
- import { FieldRenderer } from '../types'
2
1
  import JSON5 from 'json5'
3
2
  import { html } from 'lit'
4
3
 
4
+ import { FieldRenderer } from '../types'
5
+
5
6
  function onmouseover(e: Event) {
6
7
  const element = e.target as HTMLPreElement
7
8
  var parsed
@@ -26,6 +27,6 @@ export const OxGristRendererJson5: FieldRenderer = (value, column, record, rowIn
26
27
  } catch {}
27
28
  }
28
29
 
29
- const text = parsed === undefined || parsed === null ? '' : JSON5.stringify(parsed)
30
+ const text = parsed == null ? '' : JSON5.stringify(parsed)
30
31
  return html`<pre @mouseover=${onmouseover} @mouseout=${onmouseout}>${text}</pre>`
31
32
  }
@@ -1,10 +1,11 @@
1
- import { FieldRenderer } from '../types'
2
1
  import { html } from 'lit'
3
2
 
3
+ import { FieldRenderer } from '../types'
4
+
4
5
  export const OxGristRendererLink: FieldRenderer = (value, column, record, rowIndex, field) => {
5
6
  var { href, target } = column.record.options || {}
6
7
 
7
- value = value === undefined ? '' : value
8
+ value = value == null ? '' : value
8
9
 
9
10
  if (typeof href == 'function') {
10
11
  href = href(value, column, record, rowIndex, field)
@@ -3,7 +3,7 @@ import { html } from 'lit'
3
3
  import { FieldRenderer } from '../types'
4
4
 
5
5
  export const OxGristRendererSelect: FieldRenderer = (value, column, record, rowIndex, field) => {
6
- if (!value) {
6
+ if (value == null) {
7
7
  return ''
8
8
  }
9
9
  var rowOptionField = column.record.rowOptionField && record[column.record.rowOptionField]
@@ -15,7 +15,7 @@ export const OxGristRendererSelect: FieldRenderer = (value, column, record, rowI
15
15
  options = options.call(null, value, column, record, rowIndex, field)
16
16
  }
17
17
 
18
- var res = options ? options.filter((option: any) => option.value == value) : []
18
+ var res = options ? options.filter((option: any) => option.value == String(value == null ? '' : value)) : []
19
19
  if (res.length) {
20
20
  return html`<span>${res[0].display}</span>`
21
21
  }
@@ -1,6 +1,6 @@
1
1
  import { html } from 'lit'
2
2
 
3
- import { detectOverflow } from '@operato/utils'
3
+ import { detectOverflow, format as formatter } from '@operato/utils'
4
4
 
5
5
  import { FieldRenderer } from '../types'
6
6
 
@@ -17,6 +17,12 @@ function onmouseout(e: Event) {
17
17
  }
18
18
 
19
19
  export const OxGristRendererText: FieldRenderer = (value, column, record, rowIndex, field) => {
20
- const text = value === undefined ? '' : value
20
+ var { format } = column.record || {}
21
+
22
+ var text = value == null ? '' : value
23
+ if (format) {
24
+ text = formatter(format, text)
25
+ }
26
+
21
27
  return html`<span @mouseover=${onmouseover} @mouseout=${onmouseout}>${text}</span>`
22
28
  }
@@ -1,8 +1,8 @@
1
- import { ColumnConfig, GristConfig, SorterConfig } from '../types'
2
- import { LitElement, PropertyValues, TemplateResult, css, html } from 'lit'
1
+ import { css, html, LitElement, PropertyValues, TemplateResult } from 'lit'
3
2
  import { customElement, state } from 'lit/decorators.js'
4
3
 
5
4
  import { DataGrist } from '../data-grist'
5
+ import { ColumnConfig, GristConfig, SorterConfig } from '../types'
6
6
 
7
7
  @customElement('ox-sorters-control')
8
8
  export class SortersControl extends LitElement {
@@ -55,22 +55,19 @@ export class SortersControl extends LitElement {
55
55
  this.config = (e as CustomEvent).detail
56
56
  })
57
57
 
58
- grist.addEventListener('sorters-change', e => {
58
+ grist.addEventListener('fetch-params-change', e => {
59
59
  const { sorters, from } = (e as CustomEvent).detail || {}
60
60
  if (from === 'sorters-control') {
61
61
  return
62
62
  }
63
63
 
64
- this.sorters = sorters
64
+ sorters && (this.sorters = sorters)
65
65
  })
66
66
  }
67
67
  }
68
68
 
69
69
  updated(changes: PropertyValues<this>) {
70
- // TODO config 에 의한 sorters 설정은 제거해야 한다.
71
70
  if (changes.has('config')) {
72
- const sorters = this.config.sorters || []
73
-
74
71
  this.columns = this.config.columns.filter(column => column.sortable)
75
72
  this.sorters = this.sorters || this.config.sorters || []
76
73
  }
@@ -102,7 +99,7 @@ export class SortersControl extends LitElement {
102
99
  ${desc === null
103
100
  ? html``
104
101
  : html`
105
- <mwc-icon>${desc ? 'keyboard_arrow_up' : 'keyboard_arrow_down'}</mwc-icon>
102
+ <mwc-icon>${desc ? 'keyboard_arrow_down' : 'keyboard_arrow_up'}</mwc-icon>
106
103
  ${rank === 0 ? html`` : html`<sub>${rank}</sub>`}
107
104
  `}
108
105
  </div>
@@ -133,7 +130,7 @@ export class SortersControl extends LitElement {
133
130
  this.sorters = sorters
134
131
 
135
132
  this.dispatchEvent(
136
- new CustomEvent('sorters-change', {
133
+ new CustomEvent('fetch-params-change', {
137
134
  bubbles: true,
138
135
  composed: true,
139
136
  detail: {
package/src/types.ts CHANGED
@@ -1,14 +1,16 @@
1
+ import { TemplateResult } from 'lit-html'
2
+
1
3
  import { DataCardField } from './data-card/data-card-field'
2
4
  import { DataCardGutter } from './data-card/data-card-gutter'
5
+ import { RecordCard } from './data-card/record-card'
3
6
  import { DataGridField } from './data-grid/data-grid-field'
4
7
  import { DataListField } from './data-list/data-list-field'
5
8
  import { DataListGutter } from './data-list/data-list-gutter'
9
+ import { RecordPartial } from './data-list/record-partial'
6
10
  import { DataReportField } from './data-report/data-report-field'
7
11
  import { OxGristEditor } from './editors'
12
+ import { QueryFilter } from './filters'
8
13
  import { OxGristRenderer } from './renderers/ox-grist-renderer'
9
- import { RecordCard } from './data-card/record-card'
10
- import { RecordPartial } from './data-list/record-partial'
11
- import { TemplateResult } from 'lit-html'
12
14
 
13
15
  export type GristConfig = {
14
16
  columns: ColumnConfig[]
@@ -50,6 +52,7 @@ export type FilterConfigObject = {
50
52
  type: string
51
53
  operator?: FilterOperator
52
54
  options?: { [key: string]: any }
55
+ value?: string | number | boolean | string[] | number[] | undefined
53
56
  }
54
57
  export type FilterConfig = FilterConfigObject | FilterOperator | boolean
55
58
 
@@ -70,7 +73,8 @@ export type FetchOption = {
70
73
  page?: number
71
74
  limit?: number
72
75
  sorters?: SortersConfig
73
- filters?: FilterConfigObject[]
76
+ sortings?: SortersConfig
77
+ filters?: QueryFilter[]
74
78
  options?: object
75
79
  }
76
80
  export type FetchResult = {