@operato/data-grist 0.3.15 → 0.3.19

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 (170) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/assets/images/no-image.png +0 -0
  3. package/custom-elements.json +1345 -770
  4. package/demo/data-grist-test.html +142 -85
  5. package/demo/index.html +62 -129
  6. package/dist/src/configure/column-builder.js +26 -2
  7. package/dist/src/configure/column-builder.js.map +1 -1
  8. package/dist/src/data-card/data-card.d.ts +3 -6
  9. package/dist/src/data-card/data-card.js +3 -131
  10. package/dist/src/data-card/data-card.js.map +1 -1
  11. package/dist/src/data-card/record-card.d.ts +0 -3
  12. package/dist/src/data-card/record-card.js +7 -62
  13. package/dist/src/data-card/record-card.js.map +1 -1
  14. package/dist/src/data-grid/data-grid-body.d.ts +7 -1
  15. package/dist/src/data-grid/data-grid-body.js +26 -5
  16. package/dist/src/data-grid/data-grid-body.js.map +1 -1
  17. package/dist/src/data-grid/data-grid-field.js +1 -1
  18. package/dist/src/data-grid/data-grid-field.js.map +1 -1
  19. package/dist/src/data-grid/data-grid-header.d.ts +1 -0
  20. package/dist/src/data-grid/data-grid-header.js +14 -4
  21. package/dist/src/data-grid/data-grid-header.js.map +1 -1
  22. package/dist/src/data-grid/data-grid.d.ts +8 -4
  23. package/dist/src/data-grid/data-grid.js +12 -132
  24. package/dist/src/data-grid/data-grid.js.map +1 -1
  25. package/dist/src/data-grist.d.ts +1 -0
  26. package/dist/src/data-grist.js +8 -0
  27. package/dist/src/data-grist.js.map +1 -1
  28. package/dist/src/data-list/data-list.d.ts +3 -6
  29. package/dist/src/data-list/data-list.js +3 -131
  30. package/dist/src/data-list/data-list.js.map +1 -1
  31. package/dist/src/data-list/record-partial.d.ts +0 -2
  32. package/dist/src/data-list/record-partial.js +7 -58
  33. package/dist/src/data-list/record-partial.js.map +1 -1
  34. package/dist/src/data-manipulator.d.ts +20 -0
  35. package/dist/src/data-manipulator.js +148 -0
  36. package/dist/src/data-manipulator.js.map +1 -0
  37. package/dist/src/editors/image-input.d.ts +7 -0
  38. package/dist/src/editors/image-input.js +31 -0
  39. package/dist/src/editors/image-input.js.map +1 -0
  40. package/dist/src/editors/index.d.ts +1 -0
  41. package/dist/src/editors/index.js +1 -0
  42. package/dist/src/editors/index.js.map +1 -1
  43. package/dist/src/editors/input-editors.d.ts +1 -8
  44. package/dist/src/editors/input-editors.js +3 -47
  45. package/dist/src/editors/input-editors.js.map +1 -1
  46. package/dist/src/editors/registry.js +2 -1
  47. package/dist/src/editors/registry.js.map +1 -1
  48. package/dist/src/filters/filter-checkbox.js +2 -2
  49. package/dist/src/filters/filter-checkbox.js.map +1 -1
  50. package/dist/src/filters/filter-input.js +1 -1
  51. package/dist/src/filters/filter-input.js.map +1 -1
  52. package/dist/src/filters/filter-range-date.js +1 -1
  53. package/dist/src/filters/filter-range-date.js.map +1 -1
  54. package/dist/src/filters/filter-range-number.js +1 -1
  55. package/dist/src/filters/filter-range-number.js.map +1 -1
  56. package/dist/src/filters/filter-select.js +2 -2
  57. package/dist/src/filters/filter-select.js.map +1 -1
  58. package/dist/src/filters/filters-form.d.ts +9 -5
  59. package/dist/src/filters/filters-form.js +63 -15
  60. package/dist/src/filters/filters-form.js.map +1 -1
  61. package/dist/src/handlers/record-view-handler.d.ts +1 -2
  62. package/dist/src/handlers/record-view-handler.js +5 -35
  63. package/dist/src/handlers/record-view-handler.js.map +1 -1
  64. package/dist/src/handlers/select-row-toggle.d.ts +1 -1
  65. package/dist/src/handlers/select-row-toggle.js.map +1 -1
  66. package/dist/src/record-view/event-handlers/record-view-body-click-handler.d.ts +7 -0
  67. package/dist/src/record-view/event-handlers/record-view-body-click-handler.js +24 -0
  68. package/dist/src/record-view/event-handlers/record-view-body-click-handler.js.map +1 -0
  69. package/dist/src/record-view/event-handlers/record-view-body-keydown-handler.d.ts +7 -0
  70. package/dist/src/record-view/event-handlers/record-view-body-keydown-handler.js +22 -0
  71. package/dist/src/record-view/event-handlers/record-view-body-keydown-handler.js.map +1 -0
  72. package/dist/src/record-view/index.d.ts +1 -0
  73. package/dist/src/record-view/index.js +1 -0
  74. package/dist/src/record-view/index.js.map +1 -1
  75. package/dist/src/record-view/record-creator.d.ts +16 -0
  76. package/dist/src/record-view/record-creator.js +145 -0
  77. package/dist/src/record-view/record-creator.js.map +1 -0
  78. package/dist/src/record-view/record-view-body.d.ts +3 -4
  79. package/dist/src/record-view/record-view-body.js +19 -41
  80. package/dist/src/record-view/record-view-body.js.map +1 -1
  81. package/dist/src/record-view/record-view-handler.d.ts +9 -0
  82. package/dist/src/record-view/record-view-handler.js +57 -0
  83. package/dist/src/record-view/record-view-handler.js.map +1 -0
  84. package/dist/src/record-view/record-view.d.ts +4 -3
  85. package/dist/src/record-view/record-view.js +20 -55
  86. package/dist/src/record-view/record-view.js.map +1 -1
  87. package/dist/src/sorters/sorters-control.d.ts +12 -0
  88. package/dist/src/sorters/sorters-control.js +120 -0
  89. package/dist/src/sorters/sorters-control.js.map +1 -0
  90. package/dist/src/types.d.ts +7 -4
  91. package/dist/src/types.js.map +1 -1
  92. package/dist/tsconfig.tsbuildinfo +1 -1
  93. package/package.json +10 -8
  94. package/src/configure/column-builder.ts +29 -3
  95. package/src/data-card/data-card.ts +4 -158
  96. package/src/data-card/record-card.ts +14 -78
  97. package/src/data-grid/data-grid-body.ts +43 -6
  98. package/src/data-grid/data-grid-field.ts +1 -1
  99. package/src/data-grid/data-grid-header.ts +18 -6
  100. package/src/data-grid/data-grid.ts +25 -143
  101. package/src/data-grist.ts +12 -0
  102. package/src/data-list/data-list.ts +4 -158
  103. package/src/data-list/record-partial.ts +14 -73
  104. package/src/data-manipulator.ts +201 -0
  105. package/src/editors/image-input.ts +29 -0
  106. package/src/editors/index.ts +1 -0
  107. package/src/editors/input-editors.ts +5 -48
  108. package/src/editors/registry.ts +1 -1
  109. package/src/filters/filter-checkbox.ts +3 -2
  110. package/src/filters/filter-input.ts +3 -3
  111. package/src/filters/filter-range-date.ts +3 -3
  112. package/src/filters/filter-range-number.ts +3 -3
  113. package/src/filters/filter-select.ts +3 -2
  114. package/src/filters/filters-form.ts +77 -41
  115. package/src/handlers/record-view-handler.ts +8 -44
  116. package/src/handlers/select-row-toggle.ts +1 -2
  117. package/src/record-view/event-handlers/record-view-body-click-handler.ts +30 -0
  118. package/src/record-view/event-handlers/record-view-body-keydown-handler.ts +26 -0
  119. package/src/record-view/index.ts +1 -0
  120. package/src/record-view/record-creator.ts +180 -0
  121. package/src/record-view/record-view-body.ts +20 -54
  122. package/src/record-view/record-view-handler.ts +86 -0
  123. package/src/record-view/record-view.ts +21 -55
  124. package/src/sorters/sorters-control.ts +125 -0
  125. package/src/types.ts +42 -31
  126. package/dist/src/data-card/event-handlers/data-card-click-handler.d.ts +0 -6
  127. package/dist/src/data-card/event-handlers/data-card-click-handler.js +0 -16
  128. package/dist/src/data-card/event-handlers/data-card-click-handler.js.map +0 -1
  129. package/dist/src/data-card/event-handlers/data-card-dblclick-handler.d.ts +0 -6
  130. package/dist/src/data-card/event-handlers/data-card-dblclick-handler.js +0 -16
  131. package/dist/src/data-card/event-handlers/data-card-dblclick-handler.js.map +0 -1
  132. package/dist/src/data-list/event-handlers/data-list-click-handler.d.ts +0 -6
  133. package/dist/src/data-list/event-handlers/data-list-click-handler.js +0 -16
  134. package/dist/src/data-list/event-handlers/data-list-click-handler.js.map +0 -1
  135. package/dist/src/data-list/event-handlers/data-list-dblclick-handler.d.ts +0 -6
  136. package/dist/src/data-list/event-handlers/data-list-dblclick-handler.js +0 -16
  137. package/dist/src/data-list/event-handlers/data-list-dblclick-handler.js.map +0 -1
  138. package/dist/src/interfaces/index.d.ts +0 -2
  139. package/dist/src/interfaces/index.js +0 -3
  140. package/dist/src/interfaces/index.js.map +0 -1
  141. package/dist/src/interfaces/ox-grist-search-form.d.ts +0 -6
  142. package/dist/src/interfaces/ox-grist-search-form.js +0 -2
  143. package/dist/src/interfaces/ox-grist-search-form.js.map +0 -1
  144. package/dist/src/interfaces/ox-search-field.d.ts +0 -39
  145. package/dist/src/interfaces/ox-search-field.js +0 -2
  146. package/dist/src/interfaces/ox-search-field.js.map +0 -1
  147. package/dist/src/search-form/index.d.ts +0 -7
  148. package/dist/src/search-form/index.js +0 -8
  149. package/dist/src/search-form/index.js.map +0 -1
  150. package/dist/src/search-form/ox-basic-field.d.ts +0 -18
  151. package/dist/src/search-form/ox-basic-field.js +0 -75
  152. package/dist/src/search-form/ox-basic-field.js.map +0 -1
  153. package/dist/src/search-form/ox-checkbox-field.d.ts +0 -11
  154. package/dist/src/search-form/ox-checkbox-field.js +0 -60
  155. package/dist/src/search-form/ox-checkbox-field.js.map +0 -1
  156. package/dist/src/search-form/ox-grist-search-form.d.ts +0 -11
  157. package/dist/src/search-form/ox-grist-search-form.js +0 -177
  158. package/dist/src/search-form/ox-grist-search-form.js.map +0 -1
  159. package/dist/src/search-form/ox-number-field.d.ts +0 -14
  160. package/dist/src/search-form/ox-number-field.js +0 -112
  161. package/dist/src/search-form/ox-number-field.js.map +0 -1
  162. package/dist/src/search-form/ox-search-form.d.ts +0 -15
  163. package/dist/src/search-form/ox-search-form.js +0 -53
  164. package/dist/src/search-form/ox-search-form.js.map +0 -1
  165. package/dist/src/search-form/ox-select-field.d.ts +0 -21
  166. package/dist/src/search-form/ox-select-field.js +0 -181
  167. package/dist/src/search-form/ox-select-field.js.map +0 -1
  168. package/dist/src/search-form/ox-text-field.d.ts +0 -11
  169. package/dist/src/search-form/ox-text-field.js +0 -60
  170. package/dist/src/search-form/ox-text-field.js.map +0 -1
@@ -4,71 +4,46 @@ import '../data-grid/data-grid-field';
4
4
  import { css, html, LitElement } from 'lit';
5
5
  import { customElement, property } from 'lit/decorators.js';
6
6
  import { ZERO_RECORD } from '../configure/zero-config';
7
- const KEY_ENTER = 13;
8
- const KEY_ESC = 27;
7
+ import { recordViewBodyClickHandler } from './event-handlers/record-view-body-click-handler';
8
+ import { recordViewBodyKeydownHandler } from './event-handlers/record-view-body-keydown-handler';
9
9
  let RecordViewBody = class RecordViewBody extends LitElement {
10
10
  constructor() {
11
11
  super(...arguments);
12
12
  this.columns = [];
13
13
  this.record = ZERO_RECORD;
14
14
  this.rowIndex = -1;
15
+ this.onlyForEdit = false;
16
+ }
17
+ connectedCallback() {
18
+ super.connectedCallback();
19
+ this.setAttribute('tabindex', '0');
20
+ this.renderRoot.addEventListener('keydown', recordViewBodyKeydownHandler.bind(this));
21
+ this.renderRoot.addEventListener('click', recordViewBodyClickHandler.bind(this));
15
22
  }
16
23
  render() {
17
- var columns = this.columns.filter(column => !column.hidden && column.type != 'gutter');
24
+ var columns = this.columns.filter(column => !column.hidden && column.type !== 'gutter');
18
25
  var record = this.record;
19
26
  var rowIndex = this.rowIndex;
20
27
  return html `
21
28
  ${columns.map(column => {
22
- let { editable } = column.record;
29
+ let { editable, mandatory } = column.record;
23
30
  let dirtyFields = record['__dirtyfields__'] || {};
24
31
  return html `
25
- <label ?editable=${editable}><span>${this._renderLabel(column)}</span> <mwc-icon>edit</mwc-icon></label>
32
+ <label ?editable=${editable}
33
+ ><span>${mandatory ? '*' : ''}${this._renderLabel(column)}</span> <mwc-icon>edit</mwc-icon></label
34
+ >
26
35
  <ox-grid-field
27
36
  .rowIndex=${rowIndex}
28
37
  .column=${column}
29
38
  .record=${record}
30
39
  .value=${record[column.name]}
31
40
  ?dirty=${!!dirtyFields[column.name]}
41
+ ?editing=${this.onlyForEdit}
32
42
  ></ox-grid-field>
33
43
  `;
34
44
  })}
35
45
  `;
36
46
  }
37
- firstUpdated() {
38
- this.renderRoot.addEventListener('click', e => {
39
- e.stopPropagation();
40
- /* target should be 'ox-grid-field' */
41
- var target = e.target;
42
- if (this.editTarget) {
43
- this.editTarget.removeAttribute('editing');
44
- this.editTarget = null;
45
- }
46
- if (target.tagName !== 'OX-GRID-FIELD' || !target.column.record.editable) {
47
- return;
48
- }
49
- this.editTarget = target;
50
- target.setAttribute('editing', 'true');
51
- });
52
- this._focusedListener = (e) => {
53
- var keyCode = e.keyCode;
54
- switch (keyCode) {
55
- case KEY_ESC:
56
- /* TODO 편집이 취소되어야 한다. */
57
- case KEY_ENTER:
58
- if (this.editTarget) {
59
- this.editTarget.removeAttribute('editing');
60
- this.editTarget = null;
61
- }
62
- break;
63
- default:
64
- }
65
- };
66
- window.addEventListener('keydown', this._focusedListener);
67
- }
68
- disconnectedCallback() {
69
- super.disconnectedCallback();
70
- window.removeEventListener('keydown', this._focusedListener);
71
- }
72
47
  _renderLabel(column) {
73
48
  var { renderer } = column.header;
74
49
  var title = renderer.call(this, column);
@@ -108,6 +83,7 @@ RecordViewBody.styles = [
108
83
  }
109
84
 
110
85
  ox-grid-field {
86
+ border-top: none;
111
87
  border-bottom: var(--record-view-border-bottom);
112
88
  font: var(--record-view-font);
113
89
  color: var(--record-view-color);
@@ -115,7 +91,6 @@ RecordViewBody.styles = [
115
91
  }
116
92
 
117
93
  ox-grid-field[editing='true'] {
118
- border-top: none;
119
94
  border-bottom: var(--record-view-edit-border-bottom);
120
95
  }
121
96
 
@@ -134,6 +109,9 @@ __decorate([
134
109
  __decorate([
135
110
  property({ type: Number })
136
111
  ], RecordViewBody.prototype, "rowIndex", void 0);
112
+ __decorate([
113
+ property({ type: Boolean, attribute: 'only-for-edit' })
114
+ ], RecordViewBody.prototype, "onlyForEdit", void 0);
137
115
  RecordViewBody = __decorate([
138
116
  customElement('ox-record-view-body')
139
117
  ], RecordViewBody);
@@ -1 +1 @@
1
- {"version":3,"file":"record-view-body.js","sourceRoot":"","sources":["../../../src/record-view/record-view-body.ts"],"names":[],"mappings":";AAAA,OAAO,oBAAoB,CAAA;AAC3B,OAAO,8BAA8B,CAAA;AAErC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE3D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAItD,MAAM,SAAS,GAAG,EAAE,CAAA;AACpB,MAAM,OAAO,GAAG,EAAE,CAAA;AAGlB,IAAa,cAAc,GAA3B,MAAa,cAAe,SAAQ,UAAU;IAA9C;;QAoD6B,YAAO,GAAmB,EAAE,CAAA;QAC3B,WAAM,GAAgB,WAAW,CAAA;QACjC,aAAQ,GAAW,CAAC,CAAC,CAAA;IA+EnD,CAAC;IA1EC,MAAM;QACJ,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,IAAI,QAAQ,CAAC,CAAA;QACtF,IAAI,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;QACxB,IAAI,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAA;QAE5B,OAAO,IAAI,CAAA;QACP,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;YACrB,IAAI,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC,MAAM,CAAA;YAChC,IAAI,WAAW,GAAG,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAA;YAEjD,OAAO,IAAI,CAAA;6BACU,QAAQ,UAAU,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;;wBAEhD,QAAQ;sBACV,MAAM;sBACN,MAAM;qBACP,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;qBACnB,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC;;SAEtC,CAAA;QACH,CAAC,CAAC;KACH,CAAA;IACH,CAAC;IAED,YAAY;QACV,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE;YAC5C,CAAC,CAAC,eAAe,EAAE,CAAA;YAEnB,sCAAsC;YACtC,IAAI,MAAM,GAAG,CAAC,CAAC,MAAuB,CAAA;YAEtC,IAAI,IAAI,CAAC,UAAU,EAAE;gBACnB,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,SAAS,CAAC,CAAA;gBAC1C,IAAI,CAAC,UAAU,GAAG,IAAI,CAAA;aACvB;YAED,IAAI,MAAM,CAAC,OAAO,KAAK,eAAe,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE;gBACxE,OAAM;aACP;YAED,IAAI,CAAC,UAAU,GAAG,MAAM,CAAA;YACxB,MAAM,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;QACxC,CAAC,CAAC,CAAA;QAEF,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAgB,EAAE,EAAE;YAC3C,IAAI,OAAO,GAAG,CAAC,CAAC,OAAO,CAAA;YACvB,QAAQ,OAAO,EAAE;gBACf,KAAK,OAAO,CAAC;gBACb,wBAAwB;gBACxB,KAAK,SAAS;oBACZ,IAAI,IAAI,CAAC,UAAU,EAAE;wBACnB,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,SAAS,CAAC,CAAA;wBAC1C,IAAI,CAAC,UAAU,GAAG,IAAI,CAAA;qBACvB;oBACD,MAAK;gBAEP,QAAQ;aACT;QACH,CAAC,CAAA;QACD,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAA;IAC3D,CAAC;IAED,oBAAoB;QAClB,KAAK,CAAC,oBAAoB,EAAE,CAAA;QAE5B,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAA;IAC9D,CAAC;IAED,YAAY,CAAC,MAAoB;QAC/B,IAAI,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC,MAAM,CAAA;QAChC,IAAI,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QAEvC,OAAO,IAAI,CAAA,IAAI,KAAK,GAAG,CAAA;IACzB,CAAC;CACF,CAAA;AApIQ,qBAAM,GAAG;IACd,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA+CF;CACF,CAAA;AAE0B;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;+CAA6B;AAC3B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;8CAAkC;AACjC;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;gDAAsB;AAtDtC,cAAc;IAD1B,aAAa,CAAC,qBAAqB,CAAC;GACxB,cAAc,CAqI1B;SArIY,cAAc","sourcesContent":["import '@material/mwc-icon'\nimport '../data-grid/data-grid-field'\n\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport { ZERO_RECORD } from '../configure/zero-config'\nimport { DataGridField } from '../data-grid/data-grid-field'\nimport { ColumnConfig, GristRecord } from '../types'\n\nconst KEY_ENTER = 13\nconst KEY_ESC = 27\n\n@customElement('ox-record-view-body')\nexport class RecordViewBody extends LitElement {\n static styles = [\n css`\n :host {\n display: grid;\n grid-template-columns: 1fr 2fr;\n grid-auto-rows: min-content;\n grid-gap: var(--record-view-gap);\n padding: var(--record-view-padding);\n }\n\n label {\n display: flex;\n align-items: center;\n position: relative;\n text-transform: capitalize;\n\n padding: var(--record-view-item-padding);\n border-bottom: var(--record-view-border-bottom);\n font: var(--record-view-label-font);\n color: var(--record-view-label-color);\n }\n\n label mwc-icon {\n display: none;\n }\n\n label[editable] mwc-icon {\n display: inline-block;\n font-size: var(--record-view-label-icon-size);\n opacity: 0.5;\n }\n\n ox-grid-field {\n border-bottom: var(--record-view-border-bottom);\n font: var(--record-view-font);\n color: var(--record-view-color);\n background-color: transparent;\n }\n\n ox-grid-field[editing='true'] {\n border-top: none;\n border-bottom: var(--record-view-edit-border-bottom);\n }\n\n :first-child + ox-grid-field {\n color: var(--record-view-focus-color);\n font-weight: bold;\n }\n `\n ]\n\n @property({ type: Array }) columns: ColumnConfig[] = []\n @property({ type: Object }) record: GristRecord = ZERO_RECORD\n @property({ type: Number }) rowIndex: number = -1\n\n private editTarget: any\n private _focusedListener: any\n\n render() {\n var columns = this.columns.filter(column => !column.hidden && column.type != 'gutter')\n var record = this.record\n var rowIndex = this.rowIndex\n\n return html`\n ${columns.map(column => {\n let { editable } = column.record\n let dirtyFields = record['__dirtyfields__'] || {}\n\n return html`\n <label ?editable=${editable}><span>${this._renderLabel(column)}</span> <mwc-icon>edit</mwc-icon></label>\n <ox-grid-field\n .rowIndex=${rowIndex}\n .column=${column}\n .record=${record}\n .value=${record[column.name]}\n ?dirty=${!!dirtyFields[column.name]}\n ></ox-grid-field>\n `\n })}\n `\n }\n\n firstUpdated() {\n this.renderRoot.addEventListener('click', e => {\n e.stopPropagation()\n\n /* target should be 'ox-grid-field' */\n var target = e.target as DataGridField\n\n if (this.editTarget) {\n this.editTarget.removeAttribute('editing')\n this.editTarget = null\n }\n\n if (target.tagName !== 'OX-GRID-FIELD' || !target.column.record.editable) {\n return\n }\n\n this.editTarget = target\n target.setAttribute('editing', 'true')\n })\n\n this._focusedListener = (e: KeyboardEvent) => {\n var keyCode = e.keyCode\n switch (keyCode) {\n case KEY_ESC:\n /* TODO 편집이 취소되어야 한다. */\n case KEY_ENTER:\n if (this.editTarget) {\n this.editTarget.removeAttribute('editing')\n this.editTarget = null\n }\n break\n\n default:\n }\n }\n window.addEventListener('keydown', this._focusedListener)\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n\n window.removeEventListener('keydown', this._focusedListener)\n }\n\n _renderLabel(column: ColumnConfig) {\n var { renderer } = column.header\n var title = renderer.call(this, column)\n\n return html` ${title} `\n }\n}\n"]}
1
+ {"version":3,"file":"record-view-body.js","sourceRoot":"","sources":["../../../src/record-view/record-view-body.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/mwc-icon'\nimport '../data-grid/data-grid-field'\n\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport { ZERO_RECORD } from '../configure/zero-config'\nimport { ColumnConfig, GristRecord } from '../types'\nimport { recordViewBodyClickHandler } from './event-handlers/record-view-body-click-handler'\nimport { recordViewBodyKeydownHandler } from './event-handlers/record-view-body-keydown-handler'\n\n@customElement('ox-record-view-body')\nexport class RecordViewBody extends LitElement {\n static styles = [\n css`\n :host {\n display: grid;\n grid-template-columns: 1fr 2fr;\n grid-auto-rows: min-content;\n grid-gap: var(--record-view-gap);\n padding: var(--record-view-padding);\n }\n\n label {\n display: flex;\n align-items: center;\n position: relative;\n text-transform: capitalize;\n\n padding: var(--record-view-item-padding);\n border-bottom: var(--record-view-border-bottom);\n font: var(--record-view-label-font);\n color: var(--record-view-label-color);\n }\n\n label mwc-icon {\n display: none;\n }\n\n label[editable] mwc-icon {\n display: inline-block;\n font-size: var(--record-view-label-icon-size);\n opacity: 0.5;\n }\n\n ox-grid-field {\n border-top: none;\n border-bottom: var(--record-view-border-bottom);\n font: var(--record-view-font);\n color: var(--record-view-color);\n background-color: transparent;\n }\n\n ox-grid-field[editing='true'] {\n border-bottom: var(--record-view-edit-border-bottom);\n }\n\n :first-child + ox-grid-field {\n color: var(--record-view-focus-color);\n font-weight: bold;\n }\n `\n ]\n\n @property({ type: Array }) columns: ColumnConfig[] = []\n @property({ type: Object }) record: GristRecord = ZERO_RECORD\n @property({ type: Number }) rowIndex: number = -1\n @property({ type: Boolean, attribute: 'only-for-edit' }) onlyForEdit: boolean = false\n\n public currentTarget: any\n\n connectedCallback() {\n super.connectedCallback()\n\n this.setAttribute('tabindex', '0')\n\n this.renderRoot.addEventListener('keydown', recordViewBodyKeydownHandler.bind(this))\n this.renderRoot.addEventListener('click', recordViewBodyClickHandler.bind(this))\n }\n\n render() {\n var columns = this.columns.filter(column => !column.hidden && column.type !== 'gutter')\n var record = this.record\n var rowIndex = this.rowIndex\n\n return html`\n ${columns.map(column => {\n let { editable, mandatory } = column.record\n let dirtyFields = record['__dirtyfields__'] || {}\n\n return html`\n <label ?editable=${editable}\n ><span>${mandatory ? '*' : ''}${this._renderLabel(column)}</span> <mwc-icon>edit</mwc-icon></label\n >\n <ox-grid-field\n .rowIndex=${rowIndex}\n .column=${column}\n .record=${record}\n .value=${record[column.name]}\n ?dirty=${!!dirtyFields[column.name]}\n ?editing=${this.onlyForEdit}\n ></ox-grid-field>\n `\n })}\n `\n }\n\n _renderLabel(column: ColumnConfig) {\n var { renderer } = column.header\n var title = renderer.call(this, column)\n\n return html` ${title} `\n }\n}\n"]}
@@ -0,0 +1,9 @@
1
+ import { RecordCard } from '../data-card/record-card';
2
+ import { DataGridBody } from '../data-grid/data-grid-body';
3
+ import { DataGridField } from '../data-grid/data-grid-field';
4
+ import { RecordPartial } from '../data-list/record-partial';
5
+ import { RecordView } from '../record-view/record-view';
6
+ import { ColumnConfig, GristRecord } from '../types';
7
+ export declare const RecordViewHandler: (columns: ColumnConfig[], record: GristRecord, rowIndex: number, field: DataGridField | RecordCard | RecordPartial | DataGridBody, popupOptions: {
8
+ [key: string]: any;
9
+ }, closeCallback?: (() => void) | undefined) => RecordView;
@@ -0,0 +1,57 @@
1
+ /*
2
+ * handler들은 ox-grid-field 로부터 호출되는 것을 전제로 하며,
3
+ * 전반적인 처리를 위해서, columns 및 data 정보를 포함해서 제공할 수 있어야 한다.
4
+ */
5
+ export const RecordViewHandler = function (columns, record, rowIndex, field, popupOptions, closeCallback) {
6
+ var recordView = document.createElement('ox-record-view');
7
+ recordView.columns = columns;
8
+ recordView.record = record;
9
+ recordView.rowIndex = rowIndex;
10
+ document.dispatchEvent(new CustomEvent('open-popup', {
11
+ detail: {
12
+ template: recordView,
13
+ options: {
14
+ backdrop: true,
15
+ size: 'large',
16
+ title: record['name'],
17
+ ...popupOptions
18
+ },
19
+ callback: (popup) => {
20
+ recordView.addEventListener('field-change', (e) => {
21
+ field.dispatchEvent(new CustomEvent('field-change', {
22
+ bubbles: true,
23
+ composed: true,
24
+ detail: e.detail
25
+ }));
26
+ });
27
+ recordView.addEventListener('reset', (e) => {
28
+ field.dispatchEvent(new CustomEvent('record-reset', {
29
+ bubbles: true,
30
+ composed: true,
31
+ detail: {
32
+ record: record,
33
+ row: rowIndex
34
+ }
35
+ }));
36
+ });
37
+ recordView.addEventListener('cancel', (e) => {
38
+ field.dispatchEvent(new CustomEvent('record-reset', {
39
+ bubbles: true,
40
+ composed: true,
41
+ detail: {
42
+ record: record,
43
+ row: rowIndex
44
+ }
45
+ }));
46
+ popup.close();
47
+ });
48
+ recordView.addEventListener('ok', (e) => {
49
+ popup.close();
50
+ });
51
+ popup.onclosed = closeCallback;
52
+ }
53
+ }
54
+ }));
55
+ return recordView;
56
+ };
57
+ //# sourceMappingURL=record-view-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"record-view-handler.js","sourceRoot":"","sources":["../../../src/record-view/record-view-handler.ts"],"names":[],"mappings":"AAOA;;;GAGG;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG,UAC/B,OAAuB,EACvB,MAAmB,EACnB,QAAgB,EAChB,KAAgE,EAChE,YAAoC,EACpC,aAA0B;IAE1B,IAAI,UAAU,GAAG,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAe,CAAA;IAEvE,UAAU,CAAC,OAAO,GAAG,OAAO,CAAA;IAC5B,UAAU,CAAC,MAAM,GAAG,MAAM,CAAA;IAC1B,UAAU,CAAC,QAAQ,GAAG,QAAQ,CAAA;IAE9B,QAAQ,CAAC,aAAa,CACpB,IAAI,WAAW,CAAC,YAAY,EAAE;QAC5B,MAAM,EAAE;YACN,QAAQ,EAAE,UAAU;YACpB,OAAO,EAAE;gBACP,QAAQ,EAAE,IAAI;gBACd,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC;gBACrB,GAAG,YAAY;aAChB;YACD,QAAQ,EAAE,CAAC,KAAU,EAAE,EAAE;gBACvB,UAAU,CAAC,gBAAgB,CAAC,cAAc,EAAE,CAAC,CAAQ,EAAE,EAAE;oBACvD,KAAK,CAAC,aAAa,CACjB,IAAI,WAAW,CAAC,cAAc,EAAE;wBAC9B,OAAO,EAAE,IAAI;wBACb,QAAQ,EAAE,IAAI;wBACd,MAAM,EAAG,CAAS,CAAC,MAAM;qBAC1B,CAAC,CACH,CAAA;gBACH,CAAC,CAAC,CAAA;gBAEF,UAAU,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,CAAQ,EAAE,EAAE;oBAChD,KAAK,CAAC,aAAa,CACjB,IAAI,WAAW,CAAC,cAAc,EAAE;wBAC9B,OAAO,EAAE,IAAI;wBACb,QAAQ,EAAE,IAAI;wBACd,MAAM,EAAE;4BACN,MAAM,EAAE,MAAM;4BACd,GAAG,EAAE,QAAQ;yBACd;qBACF,CAAC,CACH,CAAA;gBACH,CAAC,CAAC,CAAA;gBAEF,UAAU,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,CAAQ,EAAE,EAAE;oBACjD,KAAK,CAAC,aAAa,CACjB,IAAI,WAAW,CAAC,cAAc,EAAE;wBAC9B,OAAO,EAAE,IAAI;wBACb,QAAQ,EAAE,IAAI;wBACd,MAAM,EAAE;4BACN,MAAM,EAAE,MAAM;4BACd,GAAG,EAAE,QAAQ;yBACd;qBACF,CAAC,CACH,CAAA;oBACD,KAAK,CAAC,KAAK,EAAE,CAAA;gBACf,CAAC,CAAC,CAAA;gBAEF,UAAU,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAQ,EAAE,EAAE;oBAC7C,KAAK,CAAC,KAAK,EAAE,CAAA;gBACf,CAAC,CAAC,CAAA;gBAEF,KAAK,CAAC,QAAQ,GAAG,aAAa,CAAA;YAChC,CAAC;SACF;KACK,CAAC,CACV,CAAA;IAED,OAAO,UAAU,CAAA;AACnB,CAAC,CAAA","sourcesContent":["import { RecordCard } from '../data-card/record-card'\nimport { DataGridBody } from '../data-grid/data-grid-body'\nimport { DataGridField } from '../data-grid/data-grid-field'\nimport { RecordPartial } from '../data-list/record-partial'\nimport { RecordView } from '../record-view/record-view'\nimport { ColumnConfig, GristRecord } from '../types'\n\n/*\n * handler들은 ox-grid-field 로부터 호출되는 것을 전제로 하며,\n * 전반적인 처리를 위해서, columns 및 data 정보를 포함해서 제공할 수 있어야 한다.\n */\n\nexport const RecordViewHandler = function (\n columns: ColumnConfig[],\n record: GristRecord,\n rowIndex: number,\n field: DataGridField | RecordCard | RecordPartial | DataGridBody,\n popupOptions: { [key: string]: any },\n closeCallback?: () => void\n): RecordView {\n var recordView = document.createElement('ox-record-view') as RecordView\n\n recordView.columns = columns\n recordView.record = record\n recordView.rowIndex = rowIndex\n\n document.dispatchEvent(\n new CustomEvent('open-popup', {\n detail: {\n template: recordView,\n options: {\n backdrop: true,\n size: 'large',\n title: record['name'],\n ...popupOptions\n },\n callback: (popup: any) => {\n recordView.addEventListener('field-change', (e: Event) => {\n field.dispatchEvent(\n new CustomEvent('field-change', {\n bubbles: true,\n composed: true,\n detail: (e as any).detail\n })\n )\n })\n\n recordView.addEventListener('reset', (e: Event) => {\n field.dispatchEvent(\n new CustomEvent('record-reset', {\n bubbles: true,\n composed: true,\n detail: {\n record: record,\n row: rowIndex\n }\n })\n )\n })\n\n recordView.addEventListener('cancel', (e: Event) => {\n field.dispatchEvent(\n new CustomEvent('record-reset', {\n bubbles: true,\n composed: true,\n detail: {\n record: record,\n row: rowIndex\n }\n })\n )\n popup.close()\n })\n\n recordView.addEventListener('ok', (e: Event) => {\n popup.close()\n })\n\n popup.onclosed = closeCallback\n }\n }\n } as any)\n )\n\n return recordView\n}\n"]}
@@ -1,16 +1,17 @@
1
1
  import '@material/mwc-icon';
2
2
  import './record-view-body';
3
3
  import '@operato/input/ox-input-file.js';
4
+ import '../data-grid/data-grid-field';
4
5
  import { LitElement } from 'lit';
5
- import { ColumnConfig, GristConfig, GristRecord } from '../types';
6
+ import { ColumnConfig, GristRecord } from '../types';
6
7
  export declare class RecordView extends LitElement {
7
8
  static styles: import("lit").CSSResult[];
8
- config: GristConfig;
9
9
  columns: ColumnConfig[];
10
10
  record: GristRecord;
11
11
  rowIndex: number;
12
+ onlyForEdit: boolean;
12
13
  render(): import("lit-html").TemplateResult<1>;
13
- renderThumbnail(): import("lit-html").TemplateResult<1>;
14
+ firstUpdated(): void;
14
15
  onReset(): void;
15
16
  onCancel(): void;
16
17
  onOK(): void;
@@ -2,25 +2,28 @@ import { __decorate } from "tslib";
2
2
  import '@material/mwc-icon';
3
3
  import './record-view-body';
4
4
  import '@operato/input/ox-input-file.js';
5
+ import '../data-grid/data-grid-field';
5
6
  import { css, html, LitElement } from 'lit';
6
7
  import { customElement, property } from 'lit/decorators.js';
7
8
  import { ScrollbarStyles } from '@operato/styles';
8
- import { ZERO_CONFIG, ZERO_RECORD } from '../configure/zero-config';
9
+ import { ZERO_RECORD } from '../configure/zero-config';
9
10
  let RecordView = class RecordView extends LitElement {
10
11
  constructor() {
11
12
  super(...arguments);
12
- this.config = ZERO_CONFIG;
13
13
  this.columns = [];
14
14
  this.record = ZERO_RECORD;
15
15
  this.rowIndex = -1;
16
+ this.onlyForEdit = false;
16
17
  }
17
18
  render() {
18
19
  return html `
19
- <div content>
20
- <div thumbnail>${this.renderThumbnail()}</div>
21
- <ox-record-view-body .columns=${this.columns} .record=${this.record} .rowIndex=${this.rowIndex}>
22
- </ox-record-view-body>
23
- </div>
20
+ <ox-record-view-body
21
+ .columns=${this.columns}
22
+ .record=${this.record}
23
+ .rowIndex=${this.rowIndex}
24
+ ?only-for-edit=${this.onlyForEdit}
25
+ >
26
+ </ox-record-view-body>
24
27
  <div footer>
25
28
  <button @click=${this.onReset.bind(this)}><mwc-icon>refresh</mwc-icon>Reset</button>
26
29
  <button @click=${this.onCancel.bind(this)}><mwc-icon>clear</mwc-icon>Cancel</button>
@@ -28,44 +31,23 @@ let RecordView = class RecordView extends LitElement {
28
31
  </div>
29
32
  `;
30
33
  }
31
- renderThumbnail() {
32
- return html ``;
33
- // const { thumbnail } = this.config.list
34
- // const thumbnailColumn = thumbnail ? this.columns.find(column => column.name == thumbnail) : undefined
35
- // const dirtyFields = this.record['__dirtyfields__'] || {}
36
- // if (thumbnailColumn?.record.editable) {
37
- // return html`
38
- // <ox-input-file
39
- // name="image"
40
- // accept="*/*"
41
- // hide-filelist
42
- // @change=${async (e: CustomEvent) => {
43
- // // await uploader(e.detail, this.record, this.rowIndex)
44
- // }}
45
- // ></ox-input-file>
46
- // <ox-grid-field
47
- // .rowIndex=${this.rowIndex}
48
- // .column=${thumbnailColumn}
49
- // .record=${this.record}
50
- // .value=${this.record[thumbnail!]}
51
- // ?dirty=${!!dirtyFields[thumbnail!]}
52
- // ></ox-grid-field>
53
- // `
54
- // } else {
55
- // return html``
56
- // }
34
+ firstUpdated() {
35
+ this.setAttribute('tabindex', '0');
57
36
  }
58
37
  onReset() {
38
+ this.focus();
59
39
  this.dispatchEvent(new CustomEvent('reset', {
60
40
  detail: this.record
61
41
  }));
62
42
  }
63
43
  onCancel() {
44
+ this.focus();
64
45
  this.dispatchEvent(new CustomEvent('cancel', {
65
46
  detail: this.record
66
47
  }));
67
48
  }
68
49
  onOK() {
50
+ this.focus();
69
51
  this.dispatchEvent(new CustomEvent('ok', {
70
52
  detail: this.record
71
53
  }));
@@ -78,32 +60,15 @@ RecordView.styles = [
78
60
  display: flex;
79
61
  flex-direction: column;
80
62
  background-color: var(--record-view-background-color);
81
- }
82
63
 
83
- ox-record-view-body {
84
- flex: 1;
64
+ max-height: 80vh;
85
65
  }
86
66
 
87
- [content] {
67
+ ox-record-view-body {
88
68
  flex: 1;
89
-
90
- display: block;
91
69
  overflow-y: auto;
92
70
  }
93
71
 
94
- [thumbnail] {
95
- max-height: 50%;
96
- overflow: hidden;
97
-
98
- display: flex;
99
- align-content: center;
100
- justify-content: center;
101
- }
102
-
103
- ox-input-file {
104
- width: 100%;
105
- }
106
-
107
72
  [footer] {
108
73
  display: flex;
109
74
  text-align: right;
@@ -136,9 +101,6 @@ RecordView.styles = [
136
101
  }
137
102
  `
138
103
  ];
139
- __decorate([
140
- property({ type: Object })
141
- ], RecordView.prototype, "config", void 0);
142
104
  __decorate([
143
105
  property({ type: Array })
144
106
  ], RecordView.prototype, "columns", void 0);
@@ -148,6 +110,9 @@ __decorate([
148
110
  __decorate([
149
111
  property({ type: Number })
150
112
  ], RecordView.prototype, "rowIndex", void 0);
113
+ __decorate([
114
+ property({ type: Boolean, attribute: 'only-for-edit' })
115
+ ], RecordView.prototype, "onlyForEdit", void 0);
151
116
  RecordView = __decorate([
152
117
  customElement('ox-record-view')
153
118
  ], RecordView);
@@ -1 +1 @@
1
- {"version":3,"file":"record-view.js","sourceRoot":"","sources":["../../../src/record-view/record-view.ts"],"names":[],"mappings":";AAAA,OAAO,oBAAoB,CAAA;AAC3B,OAAO,oBAAoB,CAAA;AAC3B,OAAO,iCAAiC,CAAA;AAExC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE3D,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAInE,IAAa,UAAU,GAAvB,MAAa,UAAW,SAAQ,UAAU;IAA1C;;QAmE8B,WAAM,GAAgB,WAAW,CAAA;QAClC,YAAO,GAAmB,EAAE,CAAA;QAC3B,WAAM,GAAgB,WAAW,CAAA;QACjC,aAAQ,GAAW,CAAC,CAAC,CAAA;IAsEnD,CAAC;IApEC,MAAM;QACJ,OAAO,IAAI,CAAA;;yBAEU,IAAI,CAAC,eAAe,EAAE;wCACP,IAAI,CAAC,OAAO,YAAY,IAAI,CAAC,MAAM,cAAc,IAAI,CAAC,QAAQ;;;;yBAI7E,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;yBACvB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;yBACxB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;;KAExC,CAAA;IACH,CAAC;IAED,eAAe;QACb,OAAO,IAAI,CAAA,EAAE,CAAA;QAEb,yCAAyC;QACzC,wGAAwG;QACxG,2DAA2D;QAE3D,0CAA0C;QAC1C,iBAAiB;QACjB,qBAAqB;QACrB,qBAAqB;QACrB,qBAAqB;QACrB,sBAAsB;QACtB,8CAA8C;QAC9C,kEAAkE;QAClE,WAAW;QACX,wBAAwB;QACxB,qBAAqB;QACrB,mCAAmC;QACnC,mCAAmC;QACnC,+BAA+B;QAC/B,0CAA0C;QAC1C,4CAA4C;QAC5C,wBAAwB;QACxB,MAAM;QACN,WAAW;QACX,kBAAkB;QAClB,IAAI;IACN,CAAC;IAED,OAAO;QACL,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,OAAO,EAAE;YACvB,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CACH,CAAA;IACH,CAAC;IAED,QAAQ;QACN,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,QAAQ,EAAE;YACxB,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CACH,CAAA;IACH,CAAC;IAED,IAAI;QACF,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,IAAI,EAAE;YACpB,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CACH,CAAA;IACH,CAAC;CACF,CAAA;AA3IQ,iBAAM,GAAG;IACd,eAAe;IACf,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA6DF;CACF,CAAA;AAE2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;0CAAkC;AAClC;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;2CAA6B;AAC3B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;0CAAkC;AACjC;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;4CAAsB;AAtEtC,UAAU;IADtB,aAAa,CAAC,gBAAgB,CAAC;GACnB,UAAU,CA4ItB;SA5IY,UAAU","sourcesContent":["import '@material/mwc-icon'\nimport './record-view-body'\nimport '@operato/input/ox-input-file.js'\n\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport { ScrollbarStyles } from '@operato/styles'\n\nimport { ZERO_CONFIG, ZERO_RECORD } from '../configure/zero-config'\nimport { ColumnConfig, GristConfig, GristRecord } from '../types'\n\n@customElement('ox-record-view')\nexport class RecordView extends LitElement {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n background-color: var(--record-view-background-color);\n }\n\n ox-record-view-body {\n flex: 1;\n }\n\n [content] {\n flex: 1;\n\n display: block;\n overflow-y: auto;\n }\n\n [thumbnail] {\n max-height: 50%;\n overflow: hidden;\n\n display: flex;\n align-content: center;\n justify-content: center;\n }\n\n ox-input-file {\n width: 100%;\n }\n\n [footer] {\n display: flex;\n text-align: right;\n background-color: var(--record-view-footer-background);\n box-shadow: var(--context-toolbar-shadow-line);\n }\n\n [footer] button {\n flex: 1;\n background-color: transparent;\n border: var(--record-view-footer-button-border);\n border-width: var(--record-view-footer-button-border-width);\n color: var(--record-view-footer-button-color);\n font-size: var(--record-view-footer-button-font);\n line-height: 3;\n }\n\n [footer] button * {\n vertical-align: middle;\n }\n\n [footer] button mwc-icon {\n margin-top: -3px;\n margin-right: 5px;\n font-size: var(--record-view-footer-iconbutton-size);\n }\n\n [footer] button[ok] {\n background-color: var(--record-view-footer-focus-background);\n }\n `\n ]\n\n @property({ type: Object }) config: GristConfig = ZERO_CONFIG\n @property({ type: Array }) columns: ColumnConfig[] = []\n @property({ type: Object }) record: GristRecord = ZERO_RECORD\n @property({ type: Number }) rowIndex: number = -1\n\n render() {\n return html`\n <div content>\n <div thumbnail>${this.renderThumbnail()}</div>\n <ox-record-view-body .columns=${this.columns} .record=${this.record} .rowIndex=${this.rowIndex}>\n </ox-record-view-body>\n </div>\n <div footer>\n <button @click=${this.onReset.bind(this)}><mwc-icon>refresh</mwc-icon>Reset</button>\n <button @click=${this.onCancel.bind(this)}><mwc-icon>clear</mwc-icon>Cancel</button>\n <button @click=${this.onOK.bind(this)} ok><mwc-icon>radio_button_unchecked</mwc-icon>OK</button>\n </div>\n `\n }\n\n renderThumbnail() {\n return html``\n\n // const { thumbnail } = this.config.list\n // const thumbnailColumn = thumbnail ? this.columns.find(column => column.name == thumbnail) : undefined\n // const dirtyFields = this.record['__dirtyfields__'] || {}\n\n // if (thumbnailColumn?.record.editable) {\n // return html`\n // <ox-input-file\n // name=\"image\"\n // accept=\"*/*\"\n // hide-filelist\n // @change=${async (e: CustomEvent) => {\n // // await uploader(e.detail, this.record, this.rowIndex)\n // }}\n // ></ox-input-file>\n // <ox-grid-field\n // .rowIndex=${this.rowIndex}\n // .column=${thumbnailColumn}\n // .record=${this.record}\n // .value=${this.record[thumbnail!]}\n // ?dirty=${!!dirtyFields[thumbnail!]}\n // ></ox-grid-field>\n // `\n // } else {\n // return html``\n // }\n }\n\n onReset() {\n this.dispatchEvent(\n new CustomEvent('reset', {\n detail: this.record\n })\n )\n }\n\n onCancel() {\n this.dispatchEvent(\n new CustomEvent('cancel', {\n detail: this.record\n })\n )\n }\n\n onOK() {\n this.dispatchEvent(\n new CustomEvent('ok', {\n detail: this.record\n })\n )\n }\n}\n"]}
1
+ {"version":3,"file":"record-view.js","sourceRoot":"","sources":["../../../src/record-view/record-view.ts"],"names":[],"mappings":";AAAA,OAAO,oBAAoB,CAAA;AAC3B,OAAO,oBAAoB,CAAA;AAC3B,OAAO,iCAAiC,CAAA;AACxC,OAAO,8BAA8B,CAAA;AAErC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE3D,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAItD,IAAa,UAAU,GAAvB,MAAa,UAAW,SAAQ,UAAU;IAA1C;;QAkD6B,YAAO,GAAmB,EAAE,CAAA;QAC3B,WAAM,GAAgB,WAAW,CAAA;QACjC,aAAQ,GAAW,CAAC,CAAC,CAAA;QACQ,gBAAW,GAAY,KAAK,CAAA;IAoDvF,CAAC;IAlDC,MAAM;QACJ,OAAO,IAAI,CAAA;;mBAEI,IAAI,CAAC,OAAO;kBACb,IAAI,CAAC,MAAM;oBACT,IAAI,CAAC,QAAQ;yBACR,IAAI,CAAC,WAAW;;;;yBAIhB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;yBACvB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;yBACxB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;;KAExC,CAAA;IACH,CAAC;IAED,YAAY;QACV,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,GAAG,CAAC,CAAA;IACpC,CAAC;IAED,OAAO;QACL,IAAI,CAAC,KAAK,EAAE,CAAA;QAEZ,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,OAAO,EAAE;YACvB,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CACH,CAAA;IACH,CAAC;IAED,QAAQ;QACN,IAAI,CAAC,KAAK,EAAE,CAAA;QAEZ,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,QAAQ,EAAE;YACxB,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CACH,CAAA;IACH,CAAC;IAED,IAAI;QACF,IAAI,CAAC,KAAK,EAAE,CAAA;QAEZ,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,IAAI,EAAE;YACpB,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CACH,CAAA;IACH,CAAC;CACF,CAAA;AAxGQ,iBAAM,GAAG;IACd,eAAe;IACf,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA4CF;CACF,CAAA;AAE0B;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;2CAA6B;AAC3B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;0CAAkC;AACjC;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;4CAAsB;AACQ;IAAxD,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;+CAA6B;AArD1E,UAAU;IADtB,aAAa,CAAC,gBAAgB,CAAC;GACnB,UAAU,CAyGtB;SAzGY,UAAU","sourcesContent":["import '@material/mwc-icon'\nimport './record-view-body'\nimport '@operato/input/ox-input-file.js'\nimport '../data-grid/data-grid-field'\n\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport { ScrollbarStyles } from '@operato/styles'\n\nimport { ZERO_RECORD } from '../configure/zero-config'\nimport { ColumnConfig, GristRecord } from '../types'\n\n@customElement('ox-record-view')\nexport class RecordView extends LitElement {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n background-color: var(--record-view-background-color);\n\n max-height: 80vh;\n }\n\n ox-record-view-body {\n flex: 1;\n overflow-y: auto;\n }\n\n [footer] {\n display: flex;\n text-align: right;\n background-color: var(--record-view-footer-background);\n box-shadow: var(--context-toolbar-shadow-line);\n }\n\n [footer] button {\n flex: 1;\n background-color: transparent;\n border: var(--record-view-footer-button-border);\n border-width: var(--record-view-footer-button-border-width);\n color: var(--record-view-footer-button-color);\n font-size: var(--record-view-footer-button-font);\n line-height: 3;\n }\n\n [footer] button * {\n vertical-align: middle;\n }\n\n [footer] button mwc-icon {\n margin-top: -3px;\n margin-right: 5px;\n font-size: var(--record-view-footer-iconbutton-size);\n }\n\n [footer] button[ok] {\n background-color: var(--record-view-footer-focus-background);\n }\n `\n ]\n\n @property({ type: Array }) columns: ColumnConfig[] = []\n @property({ type: Object }) record: GristRecord = ZERO_RECORD\n @property({ type: Number }) rowIndex: number = -1\n @property({ type: Boolean, attribute: 'only-for-edit' }) onlyForEdit: boolean = false\n\n render() {\n return html`\n <ox-record-view-body\n .columns=${this.columns}\n .record=${this.record}\n .rowIndex=${this.rowIndex}\n ?only-for-edit=${this.onlyForEdit}\n >\n </ox-record-view-body>\n <div footer>\n <button @click=${this.onReset.bind(this)}><mwc-icon>refresh</mwc-icon>Reset</button>\n <button @click=${this.onCancel.bind(this)}><mwc-icon>clear</mwc-icon>Cancel</button>\n <button @click=${this.onOK.bind(this)} ok><mwc-icon>radio_button_unchecked</mwc-icon>OK</button>\n </div>\n `\n }\n\n firstUpdated() {\n this.setAttribute('tabindex', '0')\n }\n\n onReset() {\n this.focus()\n\n this.dispatchEvent(\n new CustomEvent('reset', {\n detail: this.record\n })\n )\n }\n\n onCancel() {\n this.focus()\n\n this.dispatchEvent(\n new CustomEvent('cancel', {\n detail: this.record\n })\n )\n }\n\n onOK() {\n this.focus()\n\n this.dispatchEvent(\n new CustomEvent('ok', {\n detail: this.record\n })\n )\n }\n}\n"]}
@@ -0,0 +1,12 @@
1
+ import { LitElement, PropertyValues, TemplateResult } from 'lit';
2
+ import { ColumnConfig, GristConfig, SorterConfig } from '../types';
3
+ export declare class SortersControl extends LitElement {
4
+ static styles: import("lit").CSSResult[];
5
+ config: GristConfig;
6
+ columns: ColumnConfig[];
7
+ sorters: SorterConfig[];
8
+ connectedCallback(): void;
9
+ updated(changes: PropertyValues<this>): void;
10
+ render(): TemplateResult;
11
+ onChangeSort(name: string): void;
12
+ }
@@ -0,0 +1,120 @@
1
+ import { __decorate } from "tslib";
2
+ import { css, html, LitElement } from 'lit';
3
+ import { customElement, state } from 'lit/decorators.js';
4
+ let SortersControl = class SortersControl extends LitElement {
5
+ constructor() {
6
+ super(...arguments);
7
+ this.columns = [];
8
+ this.sorters = [];
9
+ }
10
+ connectedCallback() {
11
+ super.connectedCallback();
12
+ const grist = this.closest('ox-grist');
13
+ if (grist) {
14
+ this.config = grist.compiledConfig;
15
+ grist.addEventListener('config-change', (e) => {
16
+ this.config = e.detail;
17
+ });
18
+ grist.addEventListener('sorters-change', e => {
19
+ this.sorters = e.detail;
20
+ });
21
+ }
22
+ }
23
+ updated(changes) {
24
+ if (changes.has('config')) {
25
+ const sorters = this.config.sorters || [];
26
+ this.columns = this.config.columns.filter(column => column.sortable);
27
+ this.sorters = this.config.sorters || [];
28
+ }
29
+ }
30
+ render() {
31
+ const columns = this.columns;
32
+ const current = this.sorters || [];
33
+ return html `
34
+ ${columns.map(column => {
35
+ const { name } = column;
36
+ var rank = current.findIndex(sorter => sorter.name === name) + 1;
37
+ var desc = rank !== 0 ? current[rank - 1].desc : null;
38
+ if (current.length <= 1) {
39
+ rank = 0;
40
+ }
41
+ return html `
42
+ <div
43
+ option
44
+ @click=${(e) => {
45
+ this.onChangeSort(name);
46
+ }}
47
+ >
48
+ <span>${column.header.renderer.call(this, column)}</span>
49
+ ${desc === null
50
+ ? html ``
51
+ : html `
52
+ <mwc-icon>${desc ? 'keyboard_arrow_up' : 'keyboard_arrow_down'}</mwc-icon>
53
+ ${rank === 0 ? html `` : html `<sub>${rank}</sub>`}
54
+ `}
55
+ </div>
56
+ `;
57
+ })}
58
+ `;
59
+ }
60
+ onChangeSort(name) {
61
+ var sorters = [...this.sorters];
62
+ var idx = sorters.findIndex(sorter => sorter.name == name);
63
+ if (idx !== -1) {
64
+ let sorter = sorters[idx];
65
+ if (sorter.desc) {
66
+ sorters.splice(idx, 1);
67
+ }
68
+ else {
69
+ sorter.desc = true;
70
+ }
71
+ }
72
+ else {
73
+ var sorter = {
74
+ name
75
+ };
76
+ sorters.push(sorter);
77
+ }
78
+ this.sorters = sorters;
79
+ this.dispatchEvent(new CustomEvent('sorters-change', {
80
+ bubbles: true,
81
+ composed: true,
82
+ detail: this.sorters
83
+ }));
84
+ }
85
+ };
86
+ SortersControl.styles = [
87
+ css `
88
+ :host {
89
+ display: flex;
90
+ flex-direction: column;
91
+ white-space: nowrap;
92
+ }
93
+
94
+ [option] {
95
+ flex: 1;
96
+
97
+ display: flex;
98
+ justify-content: center;
99
+ align-items: center;
100
+ }
101
+
102
+ [option] > span {
103
+ margin-right: auto;
104
+ }
105
+ `
106
+ ];
107
+ __decorate([
108
+ state()
109
+ ], SortersControl.prototype, "config", void 0);
110
+ __decorate([
111
+ state()
112
+ ], SortersControl.prototype, "columns", void 0);
113
+ __decorate([
114
+ state()
115
+ ], SortersControl.prototype, "sorters", void 0);
116
+ SortersControl = __decorate([
117
+ customElement('ox-sorters-control')
118
+ ], SortersControl);
119
+ export { SortersControl };
120
+ //# sourceMappingURL=sorters-control.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sorters-control.js","sourceRoot":"","sources":["../../../src/sorters/sorters-control.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAkC,MAAM,KAAK,CAAA;AAC3E,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAMxD,IAAa,cAAc,GAA3B,MAAa,cAAe,SAAQ,UAAU;IAA9C;;QAwBW,YAAO,GAAmB,EAAE,CAAA;QAC5B,YAAO,GAAmB,EAAE,CAAA;IA4FvC,CAAC;IA1FC,iBAAiB;QACf,KAAK,CAAC,iBAAiB,EAAE,CAAA;QAEzB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAc,CAAA;QAEnD,IAAI,KAAK,EAAE;YACT,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,cAAc,CAAA;YAClC,KAAK,CAAC,gBAAgB,CAAC,eAAe,EAAE,CAAC,CAAQ,EAAE,EAAE;gBACnD,IAAI,CAAC,MAAM,GAAI,CAAiB,CAAC,MAAM,CAAA;YACzC,CAAC,CAAC,CAAA;YAEF,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,EAAE,CAAC,CAAC,EAAE;gBAC3C,IAAI,CAAC,OAAO,GAAI,CAAiB,CAAC,MAAwB,CAAA;YAC5D,CAAC,CAAC,CAAA;SACH;IACH,CAAC;IAED,OAAO,CAAC,OAA6B;QACnC,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;YACzB,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAA;YAEzC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;YACpE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAA;SACzC;IACH,CAAC;IAED,MAAM;QACJ,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAA;QAE5B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAA;QAElC,OAAO,IAAI,CAAA;QACP,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;YACrB,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAA;YACvB,IAAI,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,GAAG,CAAC,CAAA;YAChE,IAAI,IAAI,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA;YAErD,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,EAAE;gBACvB,IAAI,GAAG,CAAC,CAAA;aACT;YAED,OAAO,IAAI,CAAA;;;qBAGE,CAAC,CAAa,EAAE,EAAE;gBACzB,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAA;YACzB,CAAC;;oBAEO,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC;cAC/C,IAAI,KAAK,IAAI;gBACb,CAAC,CAAC,IAAI,CAAA,EAAE;gBACR,CAAC,CAAC,IAAI,CAAA;8BACU,IAAI,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,qBAAqB;oBAC5D,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA,QAAQ,IAAI,QAAQ;iBACjD;;SAER,CAAA;QACH,CAAC,CAAC;KACH,CAAA;IACH,CAAC;IAED,YAAY,CAAC,IAAY;QACvB,IAAI,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAA;QAE/B,IAAI,GAAG,GAAG,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,CAAA;QAC1D,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE;YACd,IAAI,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;YACzB,IAAI,MAAM,CAAC,IAAI,EAAE;gBACf,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;aACvB;iBAAM;gBACL,MAAM,CAAC,IAAI,GAAG,IAAI,CAAA;aACnB;SACF;aAAM;YACL,IAAI,MAAM,GAAG;gBACX,IAAI;aACL,CAAA;YAED,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;SACrB;QAED,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QAEtB,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,gBAAgB,EAAE;YAChC,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;YACd,MAAM,EAAE,IAAI,CAAC,OAAO;SACrB,CAAC,CACH,CAAA;IACH,CAAC;CACF,CAAA;AApHQ,qBAAM,GAAG;IACd,GAAG,CAAA;;;;;;;;;;;;;;;;;;KAkBF;CACF,CAAA;AAEQ;IAAR,KAAK,EAAE;8CAAqB;AACpB;IAAR,KAAK,EAAE;+CAA6B;AAC5B;IAAR,KAAK,EAAE;+CAA6B;AAzB1B,cAAc;IAD1B,aAAa,CAAC,oBAAoB,CAAC;GACvB,cAAc,CAqH1B;SArHY,cAAc","sourcesContent":["import { css, html, LitElement, PropertyValues, TemplateResult } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\n\nimport { DataGrist } from '../data-grist'\nimport { ColumnConfig, GristConfig, SorterConfig } from '../types'\n\n@customElement('ox-sorters-control')\nexport class SortersControl extends LitElement {\n static styles = [\n css`\n :host {\n display: flex;\n flex-direction: column;\n white-space: nowrap;\n }\n\n [option] {\n flex: 1;\n\n display: flex;\n justify-content: center;\n align-items: center;\n }\n\n [option] > span {\n margin-right: auto;\n }\n `\n ]\n\n @state() config!: GristConfig\n @state() columns: ColumnConfig[] = []\n @state() sorters: SorterConfig[] = []\n\n connectedCallback(): void {\n super.connectedCallback()\n\n const grist = this.closest('ox-grist') as DataGrist\n\n if (grist) {\n this.config = grist.compiledConfig\n grist.addEventListener('config-change', (e: Event) => {\n this.config = (e as CustomEvent).detail\n })\n\n grist.addEventListener('sorters-change', e => {\n this.sorters = (e as CustomEvent).detail as SorterConfig[]\n })\n }\n }\n\n updated(changes: PropertyValues<this>) {\n if (changes.has('config')) {\n const sorters = this.config.sorters || []\n\n this.columns = this.config.columns.filter(column => column.sortable)\n this.sorters = this.config.sorters || []\n }\n }\n\n render(): TemplateResult {\n const columns = this.columns\n\n const current = this.sorters || []\n\n return html`\n ${columns.map(column => {\n const { name } = column\n var rank = current.findIndex(sorter => sorter.name === name) + 1\n var desc = rank !== 0 ? current[rank - 1].desc : null\n\n if (current.length <= 1) {\n rank = 0\n }\n\n return html`\n <div\n option\n @click=${(e: MouseEvent) => {\n this.onChangeSort(name)\n }}\n >\n <span>${column.header.renderer.call(this, column)}</span>\n ${desc === null\n ? html``\n : html`\n <mwc-icon>${desc ? 'keyboard_arrow_up' : 'keyboard_arrow_down'}</mwc-icon>\n ${rank === 0 ? html`` : html`<sub>${rank}</sub>`}\n `}\n </div>\n `\n })}\n `\n }\n\n onChangeSort(name: string) {\n var sorters = [...this.sorters]\n\n var idx = sorters.findIndex(sorter => sorter.name == name)\n if (idx !== -1) {\n let sorter = sorters[idx]\n if (sorter.desc) {\n sorters.splice(idx, 1)\n } else {\n sorter.desc = true\n }\n } else {\n var sorter = {\n name\n }\n\n sorters.push(sorter)\n }\n\n this.sorters = sorters\n\n this.dispatchEvent(\n new CustomEvent('sorters-change', {\n bubbles: true,\n composed: true,\n detail: this.sorters\n })\n )\n }\n}\n"]}
@@ -19,13 +19,15 @@ export declare type SorterConfig = {
19
19
  desc?: boolean;
20
20
  };
21
21
  export declare type SortersConfig = SorterConfig[];
22
- export declare type FilterConfig = {
22
+ export declare type FilterOperator = 'search' | 'eq' | 'between' | 'gte' | 'lte' | 'is_not_true' | 'in' | 'like' | 'i_like' | 'noteq' | 'is_empty_num_id' | 'is_blank' | 'is_present' | 'is_not_false' | 'is_true' | 'is_false' | 'is_not_null' | 'is_null' | 'notin_with_null' | 'notin' | 'gt' | 'lt' | 'i_nlike' | 'nlike';
23
+ export declare type FilterConfigObject = {
23
24
  type: string;
24
- operator?: 'eq' | 'between' | 'gte' | 'lte' | 'is_not_true' | 'in' | 'like' | 'i_like' | 'noteq' | 'is_empty_num_id' | 'is_blank' | 'is_present' | 'is_not_false' | 'is_true' | 'is_false' | 'is_not_null' | 'is_null' | 'notin_with_null' | 'notin' | 'gt' | 'lt' | 'i_nlike' | 'nlike';
25
+ operator?: FilterOperator;
25
26
  options?: {
26
27
  [key: string]: any;
27
28
  };
28
- } | boolean;
29
+ };
30
+ export declare type FilterConfig = FilterConfigObject | FilterOperator | boolean;
29
31
  export declare type PaginationConfig = {
30
32
  page?: number;
31
33
  limit?: number;
@@ -77,6 +79,7 @@ export declare type RecordConfig = {
77
79
  renderer: FieldRenderer;
78
80
  editor?: FieldEditor;
79
81
  editable?: boolean;
82
+ mandatory?: boolean;
80
83
  classifier: GristClassifier;
81
84
  align?: 'left' | 'right' | 'center';
82
85
  options: {
@@ -84,7 +87,7 @@ export declare type RecordConfig = {
84
87
  };
85
88
  rowOptionField?: string;
86
89
  };
87
- export declare type FieldRenderer = (value: any, column: ColumnConfig, record: GristRecord, rowIndex: number, owner: RecordCard | DataCardGutter | DataCardField | DataListGutter | DataListField | RecordPartial | DataReportField) => TemplateResult | string | void;
90
+ export declare type FieldRenderer = (value: any, column: ColumnConfig, record: GristRecord, rowIndex: number, owner: RecordCard | DataCardGutter | DataCardField | DataListGutter | DataListField | RecordPartial | DataReportField | Element) => TemplateResult | string | void;
88
91
  export declare type FieldEditor = (value: any, column: ColumnConfig, record: GristRecord, rowIndex: number, field: DataGridField) => Element;
89
92
  export declare type FilterSelectRenderer = (column: ColumnConfig, owner: Element) => TemplateResult | string | void;
90
93
  export declare type GristEventHandlerSet = {
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import { TemplateResult } from 'lit-html'\n\nimport { DataCardField } from './data-card/data-card-field'\nimport { DataCardGutter } from './data-card/data-card-gutter'\nimport { RecordCard } from './data-card/record-card'\nimport { DataGridField } from './data-grid/data-grid-field'\nimport { DataListField } from './data-list/data-list-field'\nimport { DataListGutter } from './data-list/data-list-gutter'\nimport { RecordPartial } from './data-list/record-partial'\nimport { DataReportField } from './data-report/data-report-field'\n\nexport type GristConfig = {\n columns: ColumnConfig[]\n rows: RowsConfig\n list: ListConfig\n pagination?: PaginationConfig\n sorters?: SortersConfig\n}\n\nexport type SorterConfig = { name: string; desc?: boolean }\nexport type SortersConfig = SorterConfig[]\nexport type FilterConfig =\n | {\n type: string\n operator?:\n | 'eq'\n | 'between'\n | 'gte'\n | 'lte'\n | 'is_not_true'\n | 'in'\n | 'like'\n | 'i_like'\n | 'noteq'\n | 'is_empty_num_id'\n | 'is_blank'\n | 'is_present'\n | 'is_not_false'\n | 'is_true'\n | 'is_false'\n | 'is_not_null'\n | 'is_null'\n | 'notin_with_null'\n | 'notin'\n | 'gt'\n | 'lt'\n | 'i_nlike'\n | 'nlike'\n options?: { [key: string]: any }\n }\n | boolean\n\nexport type PaginationConfig = {\n page?: number\n limit?: number\n pages?: number[]\n infinite?: boolean\n}\n\nexport type FetchOption = { page?: number; limit?: number; sorters?: object[]; options?: object }\nexport type FetchHandler = (param: FetchOption) => {\n page?: number\n limit?: number\n total: number\n records: object[]\n}\n\nexport type GristEventHandler = (\n columns: ColumnConfig[],\n data?: GristData,\n column?: ColumnConfig,\n record?: GristRecord,\n rowIndex?: number,\n target?: any\n) => void\n\nexport type ColumnConfig = {\n type: string\n name: string\n gutterName?: string\n header: HeaderConfig\n record: RecordConfig\n handlers: GristEventHandlerSet\n label: LabelConfig\n hidden?: boolean\n sortable?: boolean\n resizable?: boolean\n width?: number | string | ColumnWidthCallback\n forList?: boolean\n validation?: ValidationCallback\n filter?: FilterConfig\n imex?: ImexConfig\n multiple?: boolean\n}\n\nexport type ValidationCallback = (after: any, before: any, record: GristRecord, column: ColumnConfig) => boolean\n\nexport type LabelConfig =\n | string\n | boolean\n | {\n renderer: LabelRenderer\n }\n\nexport type LabelRenderer = () => void\n\nexport type ColumnWidthCallback = (column: ColumnConfig) => string\n\nexport type HeaderConfig = {\n renderer: HeaderRenderer\n}\nexport type HeaderRenderer = (column: ColumnConfig) => any\n\nexport type RecordConfig = {\n renderer: FieldRenderer\n editor?: FieldEditor\n editable?: boolean\n classifier: GristClassifier\n align?: 'left' | 'right' | 'center'\n options: { [key: string]: any }\n rowOptionField?: string\n}\n\nexport type FieldRenderer = (\n value: any,\n column: ColumnConfig,\n record: GristRecord,\n rowIndex: number,\n owner: RecordCard | DataCardGutter | DataCardField | DataListGutter | DataListField | RecordPartial | DataReportField\n) => TemplateResult | string | void\nexport type FieldEditor = (\n value: any,\n column: ColumnConfig,\n record: GristRecord,\n rowIndex: number,\n field: DataGridField\n) => Element\nexport type FilterSelectRenderer = (column: ColumnConfig, owner: Element) => TemplateResult | string | void\n\nexport type GristEventHandlerSet = {\n click?: GristEventHandler\n dblclick?: GristEventHandler\n}\n\nexport type ListConfig = {\n thumbnail?: string\n fields: string[]\n details: string[]\n}\n\nexport type ImexConfig = {\n header: string\n key: string\n width: number\n type: string\n}\n\nexport type RowsConfig = {\n appendable: boolean\n insertable: boolean\n selectable?: RowSelectableConfig\n groups: GroupConfig[]\n totals: string[]\n classifier: GristClassifier\n handlers: GristEventHandlerSet\n}\n\nexport type GristClassifier = (\n record: GristRecord,\n rowIndex: number\n) => { emphasized?: boolean | string | string[]; [key: string]: any } | void\n\nexport type GroupConfig = {\n align: string\n titleColumn?: ColumnConfig\n title: string\n value?: string\n groupName?: string\n row?: number\n column: string | number\n rowspan: number\n colspan?: number\n}\n\nexport type RowSelectableConfig = {\n multiple?: boolean\n}\n\nexport type GristRecord = {\n id?: string\n name?: string\n __seq__?: number\n __dirty__?: string\n __selected__?: boolean\n __changes__?: object[]\n __dirtyfields__?: { [key: string]: any }\n __origin__?: any\n [key: string]: any\n}\n\nexport type GristData = {\n page?: number\n total?: number\n limit?: number\n records: GristRecord[]\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import { TemplateResult } from 'lit-html'\n\nimport { DataCardField } from './data-card/data-card-field'\nimport { DataCardGutter } from './data-card/data-card-gutter'\nimport { RecordCard } from './data-card/record-card'\nimport { DataGridField } from './data-grid/data-grid-field'\nimport { DataListField } from './data-list/data-list-field'\nimport { DataListGutter } from './data-list/data-list-gutter'\nimport { RecordPartial } from './data-list/record-partial'\nimport { DataReportField } from './data-report/data-report-field'\n\nexport type GristConfig = {\n columns: ColumnConfig[]\n rows: RowsConfig\n list: ListConfig\n pagination?: PaginationConfig\n sorters?: SortersConfig\n}\n\nexport type SorterConfig = { name: string; desc?: boolean }\nexport type SortersConfig = SorterConfig[]\nexport type FilterOperator =\n | 'search'\n | 'eq'\n | 'between'\n | 'gte'\n | 'lte'\n | 'is_not_true'\n | 'in'\n | 'like'\n | 'i_like'\n | 'noteq'\n | 'is_empty_num_id'\n | 'is_blank'\n | 'is_present'\n | 'is_not_false'\n | 'is_true'\n | 'is_false'\n | 'is_not_null'\n | 'is_null'\n | 'notin_with_null'\n | 'notin'\n | 'gt'\n | 'lt'\n | 'i_nlike'\n | 'nlike'\n\nexport type FilterConfigObject = {\n type: string\n operator?: FilterOperator\n options?: { [key: string]: any }\n}\nexport type FilterConfig = FilterConfigObject | FilterOperator | boolean\n\nexport type PaginationConfig = {\n page?: number\n limit?: number\n pages?: number[]\n infinite?: boolean\n}\n\nexport type FetchOption = { page?: number; limit?: number; sorters?: object[]; options?: object }\nexport type FetchHandler = (param: FetchOption) => {\n page?: number\n limit?: number\n total: number\n records: object[]\n}\n\nexport type GristEventHandler = (\n columns: ColumnConfig[],\n data?: GristData,\n column?: ColumnConfig,\n record?: GristRecord,\n rowIndex?: number,\n target?: any\n) => void\n\nexport type ColumnConfig = {\n type: string\n name: string\n gutterName?: string\n header: HeaderConfig\n record: RecordConfig\n handlers: GristEventHandlerSet\n label: LabelConfig\n hidden?: boolean\n sortable?: boolean\n resizable?: boolean\n width?: number | string | ColumnWidthCallback\n forList?: boolean\n validation?: ValidationCallback\n filter?: FilterConfig\n imex?: ImexConfig\n multiple?: boolean\n}\n\nexport type ValidationCallback = (after: any, before: any, record: GristRecord, column: ColumnConfig) => boolean\n\nexport type LabelConfig =\n | string\n | boolean\n | {\n renderer: LabelRenderer\n }\n\nexport type LabelRenderer = () => void\n\nexport type ColumnWidthCallback = (column: ColumnConfig) => string\n\nexport type HeaderConfig = {\n renderer: HeaderRenderer\n}\nexport type HeaderRenderer = (column: ColumnConfig) => any\n\nexport type RecordConfig = {\n renderer: FieldRenderer\n editor?: FieldEditor\n editable?: boolean\n mandatory?: boolean\n classifier: GristClassifier\n align?: 'left' | 'right' | 'center'\n options: { [key: string]: any }\n rowOptionField?: string\n}\n\nexport type FieldRenderer = (\n value: any,\n column: ColumnConfig,\n record: GristRecord,\n rowIndex: number,\n owner:\n | RecordCard\n | DataCardGutter\n | DataCardField\n | DataListGutter\n | DataListField\n | RecordPartial\n | DataReportField\n | Element\n) => TemplateResult | string | void\nexport type FieldEditor = (\n value: any,\n column: ColumnConfig,\n record: GristRecord,\n rowIndex: number,\n field: DataGridField\n) => Element\nexport type FilterSelectRenderer = (column: ColumnConfig, owner: Element) => TemplateResult | string | void\n\nexport type GristEventHandlerSet = {\n click?: GristEventHandler\n dblclick?: GristEventHandler\n}\n\nexport type ListConfig = {\n thumbnail?: string\n fields: string[]\n details: string[]\n}\n\nexport type ImexConfig = {\n header: string\n key: string\n width: number\n type: string\n}\n\nexport type RowsConfig = {\n appendable: boolean\n insertable: boolean\n selectable?: RowSelectableConfig\n groups: GroupConfig[]\n totals: string[]\n classifier: GristClassifier\n handlers: GristEventHandlerSet\n}\n\nexport type GristClassifier = (\n record: GristRecord,\n rowIndex: number\n) => { emphasized?: boolean | string | string[]; [key: string]: any } | void\n\nexport type GroupConfig = {\n align: string\n titleColumn?: ColumnConfig\n title: string\n value?: string\n groupName?: string\n row?: number\n column: string | number\n rowspan: number\n colspan?: number\n}\n\nexport type RowSelectableConfig = {\n multiple?: boolean\n}\n\nexport type GristRecord = {\n id?: string\n name?: string\n __seq__?: number\n __dirty__?: string\n __selected__?: boolean\n __changes__?: object[]\n __dirtyfields__?: { [key: string]: any }\n __origin__?: any\n [key: string]: any\n}\n\nexport type GristData = {\n page?: number\n total?: number\n limit?: number\n records: GristRecord[]\n}\n"]}