x4js 2.0.13 → 2.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/launch.json +14 -0
- package/README.md +5 -0
- package/{lib/src/demo → demo}/main.scss +3 -1
- package/{lib/src/demo/main.tsx → demo/main.ts} +37 -36
- package/demo/package.json +26 -0
- package/demo/scss.d.ts +4 -0
- package/demo/svg.d.ts +1 -0
- package/demo/tsconfig.json +14 -0
- package/lib/README.txt +5 -0
- package/lib/cjs/x4.css +1 -1
- package/lib/cjs/x4.js +2 -1
- package/lib/esm/x4.css +1 -1
- package/lib/esm/x4.mjs +2 -1
- package/lib/src/components/boxes/boxes.module.scss +17 -0
- package/lib/src/components/boxes/boxes.ts +162 -13
- package/lib/src/components/breadcrumb/breadcrumb.scss +56 -28
- package/lib/src/components/breadcrumb/breadcrumb.ts +93 -84
- package/lib/src/components/btngroup/btngroup.module.scss +12 -0
- package/lib/src/components/btngroup/btngroup.ts +41 -8
- package/lib/src/components/button/button.module.scss +23 -5
- package/lib/src/components/button/button.ts +72 -4
- package/lib/src/components/canvas/canvas.module.scss +25 -0
- package/lib/src/components/canvas/canvas.ts +189 -0
- package/lib/src/components/canvas/canvas_ex.ts +269 -0
- package/lib/src/components/checkbox/checkbox.ts +18 -4
- package/lib/src/components/combobox/combobox.module.scss +24 -15
- package/lib/src/components/combobox/combobox.ts +107 -24
- package/lib/src/components/components.ts +7 -0
- package/lib/src/components/dialog/dialog.module.scss +37 -3
- package/lib/src/components/dialog/dialog.ts +149 -31
- package/lib/src/components/filedrop/cloud-arrow-up.svg +1 -0
- package/lib/src/components/filedrop/filedrop.module.scss +70 -0
- package/lib/src/components/filedrop/filedrop.ts +131 -0
- package/lib/src/components/form/form.module.scss +4 -0
- package/lib/src/components/form/form.ts +137 -6
- package/lib/src/components/gridview/arrow-down-light.svg +1 -0
- package/lib/src/components/gridview/arrow-up-light.svg +1 -0
- package/lib/src/components/gridview/gridview.module.scss +324 -0
- package/lib/src/components/gridview/gridview.ts +1175 -0
- package/lib/src/components/icon/icon.module.scss +1 -1
- package/lib/src/components/icon/icon.ts +4 -1
- package/lib/src/components/image/image.module.scss +8 -1
- package/lib/src/components/image/image.ts +105 -6
- package/lib/src/components/input/input.module.scss +8 -3
- package/lib/src/components/input/input.ts +137 -14
- package/lib/src/components/keyboard/arrow-up.svg +1 -0
- package/lib/src/components/keyboard/delete-left.svg +1 -0
- package/lib/src/components/keyboard/eye-slash.svg +1 -0
- package/lib/src/components/keyboard/keyboard.module.scss +134 -0
- package/lib/src/components/keyboard/keyboard.ts +525 -0
- package/lib/src/components/label/label.module.scss +22 -4
- package/lib/src/components/label/label.ts +33 -0
- package/lib/src/components/link/link.ts +81 -78
- package/lib/src/components/listbox/listbox.module.scss +61 -3
- package/lib/src/components/listbox/listbox.ts +164 -56
- package/lib/src/components/menu/menu.module.scss +10 -1
- package/lib/src/components/menu/menu.ts +4 -1
- package/lib/src/components/messages/messages.module.scss +44 -0
- package/lib/src/components/messages/messages.ts +164 -18
- package/lib/src/components/messages/pen-field.svg +1 -0
- package/lib/src/components/normalize.scss +5 -0
- package/lib/src/components/notification/notification.module.scss +4 -2
- package/lib/src/components/notification/notification.ts +2 -4
- package/lib/src/components/panel/panel.module.scss +12 -0
- package/lib/src/components/popup/popup.module.scss +4 -2
- package/lib/src/components/popup/popup.ts +136 -92
- package/lib/src/components/propgrid/folder-closed.svg +1 -0
- package/lib/src/components/propgrid/folder-open.svg +1 -0
- package/lib/src/components/propgrid/progrid.module.scss +108 -0
- package/lib/src/components/propgrid/propgrid.ts +271 -0
- package/lib/src/components/propgrid/updown.svg +4 -0
- package/lib/src/components/radio/radio.module.scss +147 -0
- package/lib/src/components/radio/radio.svg +4 -0
- package/lib/src/components/radio/radio.ts +142 -0
- package/lib/src/components/select/select.module.scss +9 -0
- package/lib/src/components/select/select.ts +134 -0
- package/lib/src/components/shared.scss +47 -0
- package/lib/src/components/sizers/sizer.ts +9 -2
- package/lib/src/components/slider/slider.module.scss +77 -30
- package/lib/src/components/slider/slider.ts +72 -22
- package/lib/src/components/tabs/tabs.module.scss +1 -2
- package/lib/src/components/tabs/tabs.ts +43 -12
- package/lib/src/components/textarea/textarea.module.scss +6 -2
- package/lib/src/components/textarea/textarea.ts +73 -8
- package/lib/src/components/textedit/textedit.module.scss +3 -1
- package/lib/src/components/textedit/textedit.ts +31 -4
- package/lib/src/components/themes.scss +7 -0
- package/lib/src/components/tickline/tickline.module.scss +26 -0
- package/lib/src/components/tickline/tickline.ts +82 -0
- package/lib/src/components/tooltips/comments-question.svg +1 -0
- package/lib/src/components/tooltips/tooltips.scss +30 -9
- package/lib/src/components/tooltips/tooltips.ts +10 -5
- package/lib/src/components/treeview/treeview.module.scss +129 -60
- package/lib/src/components/treeview/treeview.ts +47 -12
- package/lib/src/components/viewport/viewport.module.scss +7 -0
- package/lib/src/core/component.ts +102 -32
- package/lib/src/core/core_application.ts +222 -2
- package/lib/src/core/core_colors.ts +2 -2
- package/lib/src/{components/grid/datastore.ts → core/core_data.ts} +261 -250
- package/lib/src/core/core_dragdrop.ts +3 -3
- package/lib/src/core/core_element.ts +13 -1
- package/lib/src/core/core_events.ts +28 -0
- package/lib/src/core/core_i18n.ts +18 -2
- package/lib/src/core/core_react.ts +79 -0
- package/lib/src/core/core_router.ts +23 -7
- package/lib/src/core/core_styles.ts +5 -5
- package/lib/src/core/core_svg.ts +173 -12
- package/lib/src/core/core_tools.ts +305 -87
- package/lib/src/x4tsx.d.ts +25 -0
- package/lib/styles/x4.css +1 -1
- package/lib/types/x4js.d.ts +767 -92
- package/package.json +4 -4
- package/scripts/build.mjs +378 -0
- package/scripts/prepack.mjs +346 -0
- package/src/components/base.scss +25 -0
- package/src/components/boxes/boxes.module.scss +54 -0
- package/src/components/boxes/boxes.ts +278 -0
- package/src/components/breadcrumb/breadcrumb.scss +56 -0
- package/src/components/breadcrumb/breadcrumb.ts +93 -0
- package/src/components/breadcrumb/chevron-right.svg +1 -0
- package/src/components/btngroup/btngroup.module.scss +41 -0
- package/src/components/btngroup/btngroup.ts +153 -0
- package/src/components/button/button.module.scss +173 -0
- package/src/components/button/button.ts +185 -0
- package/src/components/calendar/calendar-check-sharp-light.svg +1 -0
- package/src/components/calendar/calendar.module.scss +163 -0
- package/src/components/calendar/calendar.ts +327 -0
- package/src/components/calendar/chevron-left-sharp-light.svg +1 -0
- package/src/components/calendar/chevron-right-sharp-light.svg +1 -0
- package/src/components/canvas/canvas.module.scss +25 -0
- package/src/components/canvas/canvas.ts +189 -0
- package/src/components/canvas/canvas_ex.ts +269 -0
- package/src/components/checkbox/check.svg +4 -0
- package/src/components/checkbox/checkbox.module.scss +142 -0
- package/src/components/checkbox/checkbox.ts +140 -0
- package/src/components/colorinput/colorinput.module.scss +65 -0
- package/src/components/colorinput/colorinput.ts +91 -0
- package/src/components/colorinput/crosshairs-simple-sharp-light.svg +1 -0
- package/src/components/colorpicker/colorpicker.module.scss +133 -0
- package/src/components/colorpicker/colorpicker.ts +482 -0
- package/src/components/combobox/combobox.module.scss +133 -0
- package/src/components/combobox/combobox.ts +275 -0
- package/src/components/combobox/updown.svg +4 -0
- package/src/components/components.ts +41 -0
- package/src/components/dialog/dialog.module.scss +105 -0
- package/src/components/dialog/dialog.ts +212 -0
- package/src/components/dialog/xmark-sharp-light.svg +1 -0
- package/src/components/filedrop/cloud-arrow-up.svg +1 -0
- package/src/components/filedrop/filedrop.module.scss +70 -0
- package/src/components/filedrop/filedrop.ts +131 -0
- package/src/components/form/form.module.scss +38 -0
- package/src/components/form/form.ts +172 -0
- package/src/components/gridview/arrow-down-light.svg +1 -0
- package/src/components/gridview/arrow-up-light.svg +1 -0
- package/src/components/gridview/gridview.module.scss +324 -0
- package/src/components/gridview/gridview.ts +1175 -0
- package/src/components/header/header.module.scss +40 -0
- package/src/components/header/header.ts +130 -0
- package/src/components/icon/icon.module.scss +30 -0
- package/src/components/icon/icon.ts +139 -0
- package/src/components/image/image.module.scss +28 -0
- package/src/components/image/image.ts +168 -0
- package/src/components/input/input.module.scss +74 -0
- package/src/components/input/input.ts +398 -0
- package/src/components/keyboard/arrow-up.svg +1 -0
- package/src/components/keyboard/delete-left.svg +1 -0
- package/src/components/keyboard/eye-slash.svg +1 -0
- package/src/components/keyboard/keyboard.module.scss +134 -0
- package/src/components/keyboard/keyboard.ts +525 -0
- package/src/components/label/label.module.scss +76 -0
- package/src/components/label/label.ts +97 -0
- package/src/components/link/link.ts +81 -0
- package/src/components/listbox/listbox.module.scss +161 -0
- package/src/components/listbox/listbox.ts +539 -0
- package/src/components/menu/caret-right-solid.svg +1 -0
- package/src/components/menu/menu.module.scss +117 -0
- package/src/components/menu/menu.ts +174 -0
- package/src/components/messages/circle-exclamation.svg +1 -0
- package/src/components/messages/messages.module.scss +92 -0
- package/src/components/messages/messages.ts +215 -0
- package/src/components/messages/pen-field.svg +1 -0
- package/src/components/normalize.scss +391 -0
- package/src/components/notification/circle-check-solid.svg +1 -0
- package/src/components/notification/circle-exclamation-solid.svg +1 -0
- package/src/components/notification/circle-notch-light.svg +1 -0
- package/src/components/notification/notification.module.scss +84 -0
- package/src/components/notification/notification.ts +107 -0
- package/src/components/notification/xmark-sharp-light.svg +1 -0
- package/src/components/panel/panel.module.scss +60 -0
- package/src/components/panel/panel.ts +58 -0
- package/src/components/popup/popup.module.scss +45 -0
- package/src/components/popup/popup.ts +440 -0
- package/src/components/progress/progress.module.scss +57 -0
- package/src/components/progress/progress.ts +44 -0
- package/src/components/propgrid/folder-closed.svg +1 -0
- package/src/components/propgrid/folder-open.svg +1 -0
- package/src/components/propgrid/progrid.module.scss +108 -0
- package/src/components/propgrid/propgrid.ts +271 -0
- package/src/components/propgrid/updown.svg +4 -0
- package/src/components/radio/radio.module.scss +147 -0
- package/src/components/radio/radio.svg +4 -0
- package/src/components/radio/radio.ts +142 -0
- package/src/components/rating/rating.module.scss +23 -0
- package/src/components/rating/rating.ts +131 -0
- package/src/components/rating/star-sharp-light.svg +1 -0
- package/src/components/rating/star-sharp-solid.svg +1 -0
- package/src/components/select/select.module.scss +9 -0
- package/src/components/select/select.ts +134 -0
- package/src/components/shared.scss +137 -0
- package/src/components/sizers/sizer.module.scss +90 -0
- package/src/components/sizers/sizer.ts +131 -0
- package/src/components/slider/slider.module.scss +118 -0
- package/src/components/slider/slider.ts +198 -0
- package/src/components/switch/switch.module.scss +127 -0
- package/src/components/switch/switch.ts +62 -0
- package/src/components/tabs/tabs.module.scss +45 -0
- package/src/components/tabs/tabs.ts +199 -0
- package/src/components/textarea/textarea.module.scss +63 -0
- package/src/components/textarea/textarea.ts +125 -0
- package/src/components/textedit/textedit.module.scss +116 -0
- package/src/components/textedit/textedit.ts +110 -0
- package/src/components/themes.scss +88 -0
- package/src/components/tickline/tickline.module.scss +26 -0
- package/src/components/tickline/tickline.ts +82 -0
- package/src/components/tooltips/circle-info-sharp-light.svg +1 -0
- package/src/components/tooltips/comments-question.svg +1 -0
- package/src/components/tooltips/tooltips.scss +72 -0
- package/src/components/tooltips/tooltips.ts +109 -0
- package/src/components/treeview/chevron-down-light.svg +1 -0
- package/src/components/treeview/treeview.module.scss +185 -0
- package/src/components/treeview/treeview.ts +445 -0
- package/src/components/viewport/viewport.module.scss +32 -0
- package/src/components/viewport/viewport.ts +41 -0
- package/src/core/component.ts +1072 -0
- package/src/core/core_application.ts +264 -0
- package/src/core/core_colors.ts +250 -0
- package/src/core/core_data.ts +1309 -0
- package/src/core/core_dom.ts +471 -0
- package/src/core/core_dragdrop.ts +201 -0
- package/src/core/core_element.ts +110 -0
- package/src/core/core_events.ts +177 -0
- package/src/core/core_i18n.ts +393 -0
- package/src/core/core_react.ts +79 -0
- package/src/core/core_router.ts +237 -0
- package/src/core/core_styles.ts +214 -0
- package/src/core/core_svg.ts +711 -0
- package/src/core/core_tools.ts +906 -0
- package/src/types/scss.d.ts +4 -0
- package/src/types/svg.d.ts +1 -0
- package/src/types/x4react.d.ts +9 -0
- package/src/x4.scss +19 -0
- package/src/x4tsx.d.ts +25 -0
- package/tsconfig.json +14 -0
- package/lib/src/components/grid/gridview.ts +0 -1108
- package/lib/src/components/grid/memdb.ts +0 -325
- /package/{lib/src/demo → demo}/assets/house-light.svg +0 -0
- /package/{lib/src/demo → demo}/assets/radio.svg +0 -0
- /package/{lib/src/demo → demo}/index.html +0 -0
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* / \____ _|
|
|
6
6
|
* /__/\__\ |_|
|
|
7
7
|
*
|
|
8
|
-
* @file
|
|
8
|
+
* @file core_data.ts
|
|
9
9
|
* @author Etienne Cochard
|
|
10
10
|
*
|
|
11
11
|
* @copyright (c) 2024 R-libre ingenierie
|
|
@@ -14,15 +14,16 @@
|
|
|
14
14
|
* that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.
|
|
15
15
|
**/
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
|
|
18
|
+
import { EvChange } from '@core/component.js';
|
|
18
19
|
import { CoreElement } from '@core/core_element.js';
|
|
19
20
|
import { CoreEvent, EventCallback, EventMap, EventSource } from '@core/core_events.js';
|
|
20
21
|
import { isArray, isString } from '@core/core_tools.js';
|
|
21
|
-
import { Component } from 'x4js';
|
|
22
|
-
|
|
23
22
|
|
|
23
|
+
export type DataRecordID = any;
|
|
24
|
+
export type DataFieldValue = string | Date | number | boolean;
|
|
24
25
|
|
|
25
|
-
export type ChangeCallback = (type: string, id?:
|
|
26
|
+
export type ChangeCallback = (type: string, id?: DataRecordID) => void;
|
|
26
27
|
export type CalcCallback = () => string;
|
|
27
28
|
|
|
28
29
|
export type FieldType = 'string' | 'int' | 'float' | 'date' | 'bool' | 'array' | 'object' | 'any' | 'calc';
|
|
@@ -30,7 +31,7 @@ export type DataIndex = Uint32Array;
|
|
|
30
31
|
|
|
31
32
|
export interface EvDataChange extends CoreEvent {
|
|
32
33
|
change_type: 'create' | 'update' | 'delete' | 'data' | 'change';
|
|
33
|
-
id?:
|
|
34
|
+
id?: DataRecordID;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
|
|
@@ -47,8 +48,8 @@ export interface MetaData {
|
|
|
47
48
|
type?: FieldType;
|
|
48
49
|
prec?: number;
|
|
49
50
|
required?: boolean;
|
|
50
|
-
calc?: (rec:
|
|
51
|
-
model?:
|
|
51
|
+
calc?: (rec: DataRecord) => any;
|
|
52
|
+
model?: DataModel; // in case of array of subtypes, the model
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
export interface FieldInfo extends MetaData {
|
|
@@ -88,7 +89,7 @@ function _getMetas( obj: object, create = true ) : MetaInfos {
|
|
|
88
89
|
|
|
89
90
|
// merge with parent class metas
|
|
90
91
|
let pctor = Object.getPrototypeOf(ctor);
|
|
91
|
-
if( pctor!=
|
|
92
|
+
if( pctor!=DataModel ) {
|
|
92
93
|
let pmetas = pctor[metaFields];
|
|
93
94
|
mfld.fields = [...pmetas.fields, ...mfld.fields ]
|
|
94
95
|
|
|
@@ -106,12 +107,12 @@ function _getMetas( obj: object, create = true ) : MetaInfos {
|
|
|
106
107
|
|
|
107
108
|
export namespace data {
|
|
108
109
|
|
|
109
|
-
/**
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
110
|
+
/**
|
|
111
|
+
* define a model id
|
|
112
|
+
* @example
|
|
113
|
+
* \@data_id()
|
|
114
|
+
* id: string; // this field is the record id
|
|
115
|
+
**/
|
|
115
116
|
|
|
116
117
|
export function id( ) {
|
|
117
118
|
return ( ownerCls: any, fldName: string ) => {
|
|
@@ -126,110 +127,118 @@ export namespace data {
|
|
|
126
127
|
}
|
|
127
128
|
}
|
|
128
129
|
|
|
129
|
-
/**
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
/**
|
|
131
|
+
* @ignore
|
|
132
|
+
*/
|
|
132
133
|
|
|
133
134
|
export function field( data: MetaData ) {
|
|
134
135
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
136
|
+
return ( ownerCls: any, fldName: string ) => {
|
|
137
|
+
let metas = _getMetas( ownerCls );
|
|
138
|
+
metas.fields.push( {
|
|
139
|
+
name: fldName,
|
|
140
|
+
...data
|
|
141
|
+
} );
|
|
142
|
+
}
|
|
141
143
|
}
|
|
142
|
-
}
|
|
143
144
|
|
|
144
|
-
/**
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
145
|
+
/**
|
|
146
|
+
* following member is a string field
|
|
147
|
+
* @example
|
|
148
|
+
* \@data_string()
|
|
149
|
+
* my_field: string; // this field will be seen as a string
|
|
150
|
+
*/
|
|
150
151
|
|
|
151
152
|
export function string( props?: MetaData ) {
|
|
152
153
|
return field( { ...props, type: 'string' } );
|
|
153
|
-
}
|
|
154
|
+
}
|
|
154
155
|
|
|
155
|
-
/**
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
156
|
+
/**
|
|
157
|
+
* following member is an integer field
|
|
158
|
+
* @example
|
|
159
|
+
* \@data_string()
|
|
160
|
+
* my_field: number; // this field will be seen as an integer
|
|
161
|
+
*/
|
|
161
162
|
|
|
162
163
|
export function int( props?: MetaData ) {
|
|
163
164
|
return field( { ...props, type: 'int' } );
|
|
164
|
-
}
|
|
165
|
+
}
|
|
165
166
|
|
|
166
|
-
/**
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
167
|
+
/**
|
|
168
|
+
* following member is a float field
|
|
169
|
+
* @example
|
|
170
|
+
* \@data_float()
|
|
171
|
+
* my_field: number; // this field will be seen as a float
|
|
172
|
+
*/
|
|
172
173
|
|
|
173
174
|
export function float( props?: MetaData ) {
|
|
174
175
|
return field( { ...props, type: 'float' } );
|
|
175
|
-
}
|
|
176
|
+
}
|
|
176
177
|
|
|
177
|
-
/**
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
178
|
+
/**
|
|
179
|
+
* following member is a boolean field
|
|
180
|
+
* @example
|
|
181
|
+
* \@data_bool()
|
|
182
|
+
* my_field: boolean; // this field will be seen as a boolean
|
|
183
|
+
*/
|
|
183
184
|
|
|
184
185
|
export function bool( props?: MetaData ) {
|
|
185
186
|
return field( { ...props, type: 'bool' } );
|
|
186
|
-
}
|
|
187
|
+
}
|
|
187
188
|
|
|
188
|
-
/**
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
189
|
+
/**
|
|
190
|
+
* following member is a date field
|
|
191
|
+
* @example
|
|
192
|
+
* \@data_date()
|
|
193
|
+
* my_field: date; // this field will be seen as a date
|
|
194
|
+
*/
|
|
194
195
|
|
|
195
196
|
export function date( props?: MetaData ) {
|
|
196
197
|
return field( { ...props, type: 'date' } );
|
|
197
|
-
}
|
|
198
|
+
}
|
|
198
199
|
|
|
199
|
-
/**
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
200
|
+
/**
|
|
201
|
+
* following member is a calculated field
|
|
202
|
+
* @example
|
|
203
|
+
* \@data_calc( )
|
|
204
|
+
* get my_field(): string => {
|
|
205
|
+
* return 'hello';
|
|
206
|
+
* };
|
|
207
|
+
*/
|
|
207
208
|
|
|
208
209
|
export function calc( props?: MetaData ) {
|
|
209
210
|
return field( { ...props, type: 'calc'} )
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
|
|
211
|
+
}
|
|
213
212
|
|
|
214
|
-
/**
|
|
215
|
-
|
|
216
|
-
|
|
213
|
+
/**
|
|
214
|
+
*
|
|
215
|
+
*/
|
|
217
216
|
|
|
218
|
-
interface
|
|
219
|
-
|
|
220
|
-
}
|
|
217
|
+
interface ModelConstructor {
|
|
218
|
+
new ( data?: any, id?: any ): DataModel;
|
|
219
|
+
}
|
|
221
220
|
|
|
222
|
-
/**
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
221
|
+
/**
|
|
222
|
+
* following member is a record array
|
|
223
|
+
* @example
|
|
224
|
+
* \@data_array( )
|
|
225
|
+
* my_field(): TypedRecord[];
|
|
226
|
+
*/
|
|
228
227
|
|
|
229
|
-
export function array( ctor:
|
|
228
|
+
export function array( ctor: ModelConstructor, props?: MetaData ) {
|
|
230
229
|
return data.field( { ...props, type: 'array', model: ctor ? new ctor() : null } )
|
|
231
230
|
}
|
|
232
231
|
|
|
232
|
+
/**
|
|
233
|
+
* following member is unknown
|
|
234
|
+
* @example
|
|
235
|
+
* \@data.any( )
|
|
236
|
+
* my_field: TypedRecord[];
|
|
237
|
+
*/
|
|
238
|
+
|
|
239
|
+
export function any( props?: MetaData ) {
|
|
240
|
+
return field( { ...props, type: 'any' } );
|
|
241
|
+
}
|
|
233
242
|
}
|
|
234
243
|
|
|
235
244
|
|
|
@@ -239,34 +248,7 @@ interface RecordConstructor {
|
|
|
239
248
|
* record model
|
|
240
249
|
*/
|
|
241
250
|
|
|
242
|
-
export class
|
|
243
|
-
[ key: string ]: any;
|
|
244
|
-
|
|
245
|
-
constructor( data?: any, id?: any ) {
|
|
246
|
-
|
|
247
|
-
if( data!==undefined ) {
|
|
248
|
-
this.unSerialize( data, id );
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
clone( source?: any ) {
|
|
253
|
-
let rec = new (this.constructor as any)( );
|
|
254
|
-
if( source ) {
|
|
255
|
-
rec.unSerialize( source );
|
|
256
|
-
}
|
|
257
|
-
return rec;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* get the record unique identifier
|
|
262
|
-
* by default the return value is the first field
|
|
263
|
-
* @return unique identifier
|
|
264
|
-
*/
|
|
265
|
-
|
|
266
|
-
getID(): any {
|
|
267
|
-
let metas = _getMetas( this, false );
|
|
268
|
-
return this[metas.id];
|
|
269
|
-
}
|
|
251
|
+
export class DataModel {
|
|
270
252
|
|
|
271
253
|
/**
|
|
272
254
|
* MUST IMPLEMENT
|
|
@@ -277,18 +259,19 @@ export class Record {
|
|
|
277
259
|
let metas = _getMetas( this, false );
|
|
278
260
|
return metas.fields;
|
|
279
261
|
}
|
|
280
|
-
|
|
262
|
+
|
|
281
263
|
/**
|
|
282
264
|
*
|
|
283
265
|
*/
|
|
284
266
|
|
|
285
|
-
validate( ) : Error[] {
|
|
267
|
+
validate( record: DataRecord ) : Error[] {
|
|
286
268
|
|
|
287
269
|
let errs: Error[] = null;
|
|
288
270
|
|
|
289
271
|
let fields = this.getFields( );
|
|
272
|
+
|
|
290
273
|
fields.forEach( (fi) => {
|
|
291
|
-
if( fi.required && !this.getField(fi.name) ) {
|
|
274
|
+
if( fi.required && !this.getField(fi.name,record) ) {
|
|
292
275
|
if( errs ) {
|
|
293
276
|
errs = [];
|
|
294
277
|
}
|
|
@@ -298,15 +281,11 @@ export class Record {
|
|
|
298
281
|
})
|
|
299
282
|
|
|
300
283
|
return errs;
|
|
301
|
-
}
|
|
284
|
+
}
|
|
302
285
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
// return <FieldInfo>{ name };
|
|
307
|
-
// });
|
|
308
|
-
// }
|
|
309
|
-
//}
|
|
286
|
+
/**
|
|
287
|
+
* return the field index by name
|
|
288
|
+
*/
|
|
310
289
|
|
|
311
290
|
getFieldIndex( name: string ) : number {
|
|
312
291
|
let fields = this.getFields( );
|
|
@@ -318,12 +297,12 @@ export class Record {
|
|
|
318
297
|
* @returns an object with known record values
|
|
319
298
|
*/
|
|
320
299
|
|
|
321
|
-
serialize(): any {
|
|
300
|
+
serialize( input: DataRecord ): any {
|
|
322
301
|
let rec: any = {};
|
|
323
302
|
|
|
324
303
|
this.getFields().forEach((f) => {
|
|
325
304
|
if( f.calc === undefined ) {
|
|
326
|
-
rec[f.name] =
|
|
305
|
+
rec[f.name] = input[f.name];
|
|
327
306
|
}
|
|
328
307
|
});
|
|
329
308
|
|
|
@@ -336,25 +315,26 @@ export class Record {
|
|
|
336
315
|
* @returns a new Record
|
|
337
316
|
*/
|
|
338
317
|
|
|
339
|
-
unSerialize(data: any, id?:
|
|
318
|
+
unSerialize(data: any, id?: DataRecordID ) : DataRecord {
|
|
340
319
|
|
|
341
|
-
|
|
320
|
+
const fields = this.getFields();
|
|
321
|
+
const rec = new DataRecord( );
|
|
342
322
|
|
|
343
323
|
fields.forEach( (sf) => {
|
|
344
324
|
let value = data[sf.name];
|
|
345
325
|
if (value !== undefined) {
|
|
346
|
-
|
|
326
|
+
rec[sf.name] = this._convertField( sf, value );
|
|
347
327
|
}
|
|
348
328
|
});
|
|
349
329
|
|
|
350
330
|
if( id!==undefined ) {
|
|
351
|
-
|
|
331
|
+
rec[fields[0].name] = id;
|
|
352
332
|
}
|
|
353
333
|
else {
|
|
354
|
-
console.assert( this.getID()!==undefined ); // store do not have ID field
|
|
334
|
+
console.assert( this.getID(rec)!==undefined ); // store do not have ID field
|
|
355
335
|
}
|
|
356
336
|
|
|
357
|
-
return
|
|
337
|
+
return rec;
|
|
358
338
|
}
|
|
359
339
|
|
|
360
340
|
/**
|
|
@@ -389,6 +369,8 @@ export class Record {
|
|
|
389
369
|
}
|
|
390
370
|
|
|
391
371
|
case 'array': {
|
|
372
|
+
debugger;
|
|
373
|
+
/*
|
|
392
374
|
let result: any[] = [];
|
|
393
375
|
|
|
394
376
|
if( field.model ) {
|
|
@@ -398,6 +380,7 @@ export class Record {
|
|
|
398
380
|
|
|
399
381
|
return result;
|
|
400
382
|
}
|
|
383
|
+
*/
|
|
401
384
|
break;
|
|
402
385
|
}
|
|
403
386
|
}
|
|
@@ -405,18 +388,30 @@ export class Record {
|
|
|
405
388
|
return input;
|
|
406
389
|
}
|
|
407
390
|
|
|
391
|
+
/**
|
|
392
|
+
* get the record unique identifier
|
|
393
|
+
* by default the return value is the first field
|
|
394
|
+
* @return unique identifier
|
|
395
|
+
*/
|
|
396
|
+
|
|
397
|
+
getID( rec: DataRecord ): any {
|
|
398
|
+
if( !rec ) return null;
|
|
399
|
+
let metas = _getMetas( this, false );
|
|
400
|
+
return rec[metas.id];
|
|
401
|
+
}
|
|
402
|
+
|
|
408
403
|
/**
|
|
409
404
|
* get raw value of a field
|
|
410
405
|
* @param name - field name or field index
|
|
411
406
|
*/
|
|
412
407
|
|
|
413
|
-
getRaw( name: string | number ) : any {
|
|
408
|
+
getRaw( name: string | number, rec: DataRecord ) : any {
|
|
414
409
|
|
|
415
410
|
let idx;
|
|
416
411
|
let fields = this.getFields( );
|
|
417
412
|
|
|
418
413
|
if( typeof(name) === 'string' ) {
|
|
419
|
-
idx = fields.findIndex( fi => fi.name == name );
|
|
414
|
+
idx = fields.findIndex( ( fi: FieldInfo) => fi.name == name );
|
|
420
415
|
if( idx < 0 ) {
|
|
421
416
|
console.assert( false, 'unknown field: '+name);
|
|
422
417
|
return undefined;
|
|
@@ -436,20 +431,10 @@ export class Record {
|
|
|
436
431
|
|
|
437
432
|
let fld = fields[idx];
|
|
438
433
|
if( fld.calc!==undefined ) {
|
|
439
|
-
return fld.calc(
|
|
434
|
+
return fld.calc( rec );
|
|
440
435
|
}
|
|
441
436
|
|
|
442
|
-
return
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
/**
|
|
446
|
-
*
|
|
447
|
-
* @param name
|
|
448
|
-
* @param data
|
|
449
|
-
*/
|
|
450
|
-
|
|
451
|
-
setRaw( name: string, data: string ) {
|
|
452
|
-
this[name] = data;
|
|
437
|
+
return rec[fld.name];
|
|
453
438
|
}
|
|
454
439
|
|
|
455
440
|
/**
|
|
@@ -459,18 +444,54 @@ export class Record {
|
|
|
459
444
|
* let value = record.get('field1');
|
|
460
445
|
*/
|
|
461
446
|
|
|
462
|
-
getField( name: string ): string {
|
|
463
|
-
let v = this.getRaw( name );
|
|
447
|
+
getField( name: string, rec: DataRecord ): string {
|
|
448
|
+
let v = this.getRaw( name, rec );
|
|
464
449
|
return (v===undefined || v===null) ? '' : ''+v;
|
|
465
450
|
}
|
|
451
|
+
}
|
|
466
452
|
|
|
467
|
-
|
|
453
|
+
/**
|
|
454
|
+
*
|
|
455
|
+
*/
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
const $model = Symbol( "model" )
|
|
460
|
+
|
|
461
|
+
export class DataRecord {
|
|
462
|
+
[ key: string ]: DataFieldValue;
|
|
463
|
+
|
|
464
|
+
/*
|
|
465
|
+
/ **
|
|
466
|
+
* @returns fields descriptors
|
|
467
|
+
* /
|
|
468
|
+
|
|
469
|
+
getFields(): FieldInfo[] {
|
|
470
|
+
let metas = _getMetas( this, false );
|
|
471
|
+
return metas.fields;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
/ **
|
|
477
|
+
*
|
|
478
|
+
* @param name
|
|
479
|
+
* @param data
|
|
480
|
+
* /
|
|
481
|
+
|
|
482
|
+
setRaw( name: string, data: string ) {
|
|
483
|
+
this[name] = data;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
/ **
|
|
468
489
|
* set field value
|
|
469
490
|
* @param name - field name
|
|
470
491
|
* @param value - value to set
|
|
471
492
|
* @example
|
|
472
493
|
* record.set( 'field1', 7 );
|
|
473
|
-
|
|
494
|
+
* /
|
|
474
495
|
|
|
475
496
|
setField(name: string, value: any) {
|
|
476
497
|
let fields = this.getFields( );
|
|
@@ -489,65 +510,19 @@ export class Record {
|
|
|
489
510
|
|
|
490
511
|
this.setRaw( fld.name, value );
|
|
491
512
|
}
|
|
513
|
+
*/
|
|
492
514
|
}
|
|
493
515
|
|
|
494
|
-
/**
|
|
495
|
-
* by default, the field id is rhe first member or the record
|
|
496
|
-
*/
|
|
497
|
-
|
|
498
|
-
export class AutoRecord extends Record {
|
|
499
|
-
|
|
500
|
-
private m_data;
|
|
501
|
-
private m_fid: string;
|
|
502
|
-
|
|
503
|
-
constructor( data: any ) {
|
|
504
|
-
super( );
|
|
505
|
-
|
|
506
|
-
this.m_data = data;
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
getID( ) {
|
|
510
|
-
if( !this.m_fid ) {
|
|
511
|
-
let fnames = Object.keys( this.m_data );
|
|
512
|
-
this.m_fid = fnames[0];
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
return this.m_data[this.m_fid];
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
getFields( ) : FieldInfo[] {
|
|
519
|
-
let fnames = Object.keys( this.m_data );
|
|
520
|
-
let fields: FieldInfo[] = fnames.map( (n) => {
|
|
521
|
-
return {
|
|
522
|
-
name: n
|
|
523
|
-
};
|
|
524
|
-
})
|
|
525
|
-
|
|
526
|
-
return fields;
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
getRaw( name: string ) : string {
|
|
530
|
-
return this.m_data[name];
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
setRaw( name: string, data: string ) {
|
|
534
|
-
this.m_data[name] = data;
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
clone( data: any ) {
|
|
538
|
-
return new AutoRecord( {...data} );
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
516
|
|
|
542
517
|
/**
|
|
543
518
|
*
|
|
544
519
|
*/
|
|
545
520
|
|
|
546
|
-
interface DataEventMap extends
|
|
521
|
+
interface DataEventMap extends EventMap {
|
|
547
522
|
change?: EvChange;
|
|
548
523
|
}
|
|
549
524
|
|
|
550
|
-
type DataSolver = ( data: any ) =>
|
|
525
|
+
type DataSolver = ( data: any ) => DataRecord[];
|
|
551
526
|
|
|
552
527
|
export interface DataProxyProps {
|
|
553
528
|
url: string;
|
|
@@ -596,9 +571,9 @@ export class DataProxy extends CoreElement<DataEventMap> {
|
|
|
596
571
|
*
|
|
597
572
|
*/
|
|
598
573
|
|
|
599
|
-
interface DataStoreProps
|
|
600
|
-
model:
|
|
601
|
-
data?:
|
|
574
|
+
interface DataStoreProps {
|
|
575
|
+
model: DataModel;
|
|
576
|
+
data?: any[];
|
|
602
577
|
url?: string;
|
|
603
578
|
autoload?: false;
|
|
604
579
|
solver?: DataSolver;
|
|
@@ -615,16 +590,16 @@ interface DataStoreEventMap extends EventMap {
|
|
|
615
590
|
*
|
|
616
591
|
*/
|
|
617
592
|
|
|
618
|
-
export class DataStore
|
|
593
|
+
export class DataStore extends EventSource<DataStoreEventMap> {
|
|
619
594
|
|
|
620
|
-
protected m_model:
|
|
595
|
+
protected m_model: DataModel;
|
|
621
596
|
protected m_fields: FieldInfo[];
|
|
622
|
-
protected m_records:
|
|
597
|
+
protected m_records: DataRecord[];
|
|
623
598
|
|
|
624
599
|
protected m_proxy: DataProxy;
|
|
625
600
|
protected m_rec_index: DataIndex;
|
|
626
601
|
|
|
627
|
-
constructor(props: DataStoreProps
|
|
602
|
+
constructor(props: DataStoreProps ) {
|
|
628
603
|
super( );
|
|
629
604
|
|
|
630
605
|
this.m_fields = undefined;
|
|
@@ -672,10 +647,10 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
672
647
|
|
|
673
648
|
public setData( records: any[] ) {
|
|
674
649
|
|
|
675
|
-
|
|
650
|
+
const realRecords: DataRecord[] = new Array( records.length );
|
|
676
651
|
|
|
677
|
-
records.forEach( (rec) => {
|
|
678
|
-
realRecords
|
|
652
|
+
records.forEach( (rec,idx) => {
|
|
653
|
+
realRecords[idx] = this.m_model.unSerialize(rec);
|
|
679
654
|
});
|
|
680
655
|
|
|
681
656
|
this.setRawData( realRecords );
|
|
@@ -686,14 +661,13 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
686
661
|
* @param records - must be of the same type as model
|
|
687
662
|
*/
|
|
688
663
|
|
|
689
|
-
public setRawData(records:
|
|
664
|
+
public setRawData(records: DataRecord[]) {
|
|
690
665
|
|
|
691
666
|
this.m_records = records;
|
|
692
667
|
this._rebuildIndex( );
|
|
693
668
|
this.fire( 'data_change', { change_type: 'change'} );
|
|
694
669
|
}
|
|
695
670
|
|
|
696
|
-
|
|
697
671
|
private _rebuildIndex( ) {
|
|
698
672
|
this.m_rec_index = null; // null to signal that we have to run on records instead of index
|
|
699
673
|
this.m_rec_index = this.createIndex( null ); // prepare index (remove deleted)
|
|
@@ -704,8 +678,9 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
704
678
|
*
|
|
705
679
|
*/
|
|
706
680
|
|
|
707
|
-
public update( rec:
|
|
708
|
-
|
|
681
|
+
public update( rec: DataRecord ) {
|
|
682
|
+
|
|
683
|
+
let id = this.m_model.getID( rec );
|
|
709
684
|
let index = this.indexOfId(id);
|
|
710
685
|
if (index < 0) {
|
|
711
686
|
return false;
|
|
@@ -721,18 +696,18 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
721
696
|
* @param data
|
|
722
697
|
*/
|
|
723
698
|
|
|
724
|
-
public append( rec:
|
|
699
|
+
public append( rec: DataRecord | any ) {
|
|
725
700
|
|
|
726
|
-
if( !(rec instanceof
|
|
727
|
-
|
|
728
|
-
rec = nrec.unSerialize( rec );
|
|
701
|
+
if( !(rec instanceof DataRecord) ) {
|
|
702
|
+
rec = this.m_model.unSerialize( rec );
|
|
729
703
|
}
|
|
730
704
|
|
|
731
|
-
|
|
705
|
+
const id = this.m_model.getID(rec);
|
|
706
|
+
console.assert( id!==undefined );
|
|
732
707
|
|
|
733
708
|
this.m_records.push( rec );
|
|
734
709
|
this._rebuildIndex( );
|
|
735
|
-
this.fire( 'data_change', {change_type: 'create', id
|
|
710
|
+
this.fire( 'data_change', {change_type: 'create', id } );
|
|
736
711
|
}
|
|
737
712
|
|
|
738
713
|
/**
|
|
@@ -741,8 +716,10 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
741
716
|
|
|
742
717
|
getMaxId( ) {
|
|
743
718
|
let maxID: number = undefined;
|
|
719
|
+
const m = this.m_model;
|
|
720
|
+
|
|
744
721
|
this.m_records.forEach( (r) => {
|
|
745
|
-
let rid =
|
|
722
|
+
let rid = m.getID( r );
|
|
746
723
|
if( maxID===undefined || maxID<rid ) {
|
|
747
724
|
maxID = rid;
|
|
748
725
|
}
|
|
@@ -756,7 +733,7 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
756
733
|
* @param id
|
|
757
734
|
*/
|
|
758
735
|
|
|
759
|
-
public delete(id:
|
|
736
|
+
public delete(id: DataRecordID ): boolean {
|
|
760
737
|
|
|
761
738
|
let idx = this.indexOfId( id );
|
|
762
739
|
if( idx<0 ) {
|
|
@@ -792,17 +769,19 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
792
769
|
* find the index of the element with the given id
|
|
793
770
|
*/
|
|
794
771
|
|
|
795
|
-
public indexOfId(id:
|
|
772
|
+
public indexOfId(id: DataRecordID ): number {
|
|
796
773
|
|
|
797
774
|
//if( this.count<10 ) {
|
|
798
775
|
// this.forEach( (rec) => rec.getID() == id );
|
|
799
776
|
//}
|
|
800
777
|
|
|
778
|
+
const m = this.m_model;
|
|
779
|
+
|
|
801
780
|
for( let lim = this.count, base = 0; lim != 0; lim >>= 1 ) {
|
|
802
781
|
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
782
|
+
const p = base + (lim >> 1); // int conversion
|
|
783
|
+
const idx = this.m_rec_index[p];
|
|
784
|
+
const rid = m.getID( this.m_records[idx] );
|
|
806
785
|
|
|
807
786
|
if( rid==id ) {
|
|
808
787
|
return p;
|
|
@@ -822,7 +801,7 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
822
801
|
* @returns record or null
|
|
823
802
|
*/
|
|
824
803
|
|
|
825
|
-
public getById(id:
|
|
804
|
+
public getById(id: DataRecordID): DataRecord {
|
|
826
805
|
let idx = this.indexOfId( id );
|
|
827
806
|
if( idx<0 ) {
|
|
828
807
|
return null;
|
|
@@ -837,16 +816,16 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
837
816
|
* @returns record or null
|
|
838
817
|
*/
|
|
839
818
|
|
|
840
|
-
public getByIndex( index: number ):
|
|
819
|
+
public getByIndex( index: number ): DataRecord {
|
|
841
820
|
let idx = this.m_rec_index[index];
|
|
842
821
|
return this._getRecord( idx );
|
|
843
822
|
}
|
|
844
823
|
|
|
845
|
-
private _getRecord( index: number ) :
|
|
824
|
+
private _getRecord( index: number ) : DataRecord {
|
|
846
825
|
return this.m_records[index] ?? null;
|
|
847
826
|
}
|
|
848
827
|
|
|
849
|
-
public moveTo( other: DataStore
|
|
828
|
+
public moveTo( other: DataStore ) {
|
|
850
829
|
other.setRawData( this.m_records );
|
|
851
830
|
}
|
|
852
831
|
|
|
@@ -855,7 +834,7 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
855
834
|
* @param opts
|
|
856
835
|
*/
|
|
857
836
|
|
|
858
|
-
createView( opts?: DataViewProps
|
|
837
|
+
createView( opts?: DataViewProps ) : DataView {
|
|
859
838
|
let eopts = { ...opts, store: this };
|
|
860
839
|
return new DataView( eopts );
|
|
861
840
|
}
|
|
@@ -882,11 +861,10 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
882
861
|
else {
|
|
883
862
|
if( typeof(filter.op)==='function' ) {
|
|
884
863
|
|
|
885
|
-
let fn =
|
|
864
|
+
let fn = filter.op as FilterFunc;
|
|
886
865
|
|
|
887
866
|
// scan all records and append only interesting ones
|
|
888
867
|
this.forEach( (rec, idx) => {
|
|
889
|
-
|
|
890
868
|
// skip deleted
|
|
891
869
|
if( !rec ) {
|
|
892
870
|
return;
|
|
@@ -957,6 +935,8 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
957
935
|
}
|
|
958
936
|
|
|
959
937
|
// scan all records and append only interesting ones
|
|
938
|
+
const m = this.m_model;
|
|
939
|
+
|
|
960
940
|
this.forEach( (rec, idx) => {
|
|
961
941
|
|
|
962
942
|
// skip deleted
|
|
@@ -964,7 +944,7 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
964
944
|
return;
|
|
965
945
|
}
|
|
966
946
|
|
|
967
|
-
let field =
|
|
947
|
+
let field = m.getRaw( filterFld, rec );
|
|
968
948
|
if( field===null || field===undefined ) {
|
|
969
949
|
field = '';
|
|
970
950
|
}
|
|
@@ -1019,13 +999,16 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
1019
999
|
}
|
|
1020
1000
|
|
|
1021
1001
|
// sort only by one field : optimize it
|
|
1002
|
+
const m = this.m_model;
|
|
1003
|
+
|
|
1022
1004
|
if( fidxs.length==1 ) {
|
|
1023
1005
|
|
|
1024
|
-
|
|
1006
|
+
const field = fidxs[0].fidx;
|
|
1007
|
+
|
|
1025
1008
|
index.sort( ( ia, ib ) => {
|
|
1026
1009
|
|
|
1027
|
-
let va = this.getByIndex(ia)
|
|
1028
|
-
let vb = this.getByIndex(ib)
|
|
1010
|
+
let va = m.getRaw( field, this.getByIndex(ia) ) ?? '';
|
|
1011
|
+
let vb = m.getRaw( field, this.getByIndex(ib) ) ?? '';
|
|
1029
1012
|
if (va > vb) { return 1; }
|
|
1030
1013
|
if (va < vb) { return -1; }
|
|
1031
1014
|
return 0;
|
|
@@ -1044,8 +1027,8 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
1044
1027
|
let fidx = fidxs[fi].fidx;
|
|
1045
1028
|
let mul = fidxs[fi].asc ? 1 : -1;
|
|
1046
1029
|
|
|
1047
|
-
let va = this.getByIndex(ia)
|
|
1048
|
-
let vb = this.getByIndex(ib)
|
|
1030
|
+
let va = m.getRaw( fidx, this.getByIndex(ia) ) ?? '';
|
|
1031
|
+
let vb = m.getRaw( fidx, this.getByIndex(ib) ) ?? '';
|
|
1049
1032
|
if (va > vb) { return mul; }
|
|
1050
1033
|
if (va < vb) { return -mul; }
|
|
1051
1034
|
}
|
|
@@ -1056,12 +1039,12 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
1056
1039
|
|
|
1057
1040
|
return index
|
|
1058
1041
|
}
|
|
1059
|
-
|
|
1042
|
+
|
|
1060
1043
|
/**
|
|
1061
1044
|
*
|
|
1062
1045
|
*/
|
|
1063
1046
|
|
|
1064
|
-
forEach( cb: ( rec:
|
|
1047
|
+
forEach( cb: ( rec: DataRecord, index: number ) => any ) {
|
|
1065
1048
|
|
|
1066
1049
|
if( this.m_rec_index ) {
|
|
1067
1050
|
this.m_rec_index.some( (ri,index) => {
|
|
@@ -1088,6 +1071,10 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
1088
1071
|
changed( ) {
|
|
1089
1072
|
this.fire( 'data_change', { change_type: 'change'} );
|
|
1090
1073
|
}
|
|
1074
|
+
|
|
1075
|
+
getModel( ) {
|
|
1076
|
+
return this.m_model;
|
|
1077
|
+
}
|
|
1091
1078
|
}
|
|
1092
1079
|
|
|
1093
1080
|
|
|
@@ -1101,13 +1088,13 @@ interface DataViewEventMap extends EventMap {
|
|
|
1101
1088
|
view_change: EvViewChange;
|
|
1102
1089
|
}
|
|
1103
1090
|
|
|
1104
|
-
interface DataViewProps
|
|
1105
|
-
store?: DataStore
|
|
1091
|
+
interface DataViewProps {
|
|
1092
|
+
store?: DataStore;
|
|
1106
1093
|
filter?: FilterInfo;
|
|
1107
1094
|
order?: string | SortProp[] | SortProp;
|
|
1108
1095
|
}
|
|
1109
1096
|
|
|
1110
|
-
export type FilterFunc = ( rec:
|
|
1097
|
+
export type FilterFunc = ( rec: DataRecord ) => boolean;
|
|
1111
1098
|
|
|
1112
1099
|
export interface FilterInfo {
|
|
1113
1100
|
op: '<' | '<=' | '=' | '>=' | '>' | '<>' | 'empty-result' | FilterFunc, // emptydb mean return an empty result always
|
|
@@ -1120,6 +1107,7 @@ export interface FilterInfo {
|
|
|
1120
1107
|
export interface SortProp {
|
|
1121
1108
|
field: string; //
|
|
1122
1109
|
ascending: boolean; //
|
|
1110
|
+
numeric?: boolean; // numeric sort
|
|
1123
1111
|
}
|
|
1124
1112
|
|
|
1125
1113
|
|
|
@@ -1130,17 +1118,18 @@ export interface SortProp {
|
|
|
1130
1118
|
* You can have multiple views for a single DataStore
|
|
1131
1119
|
*/
|
|
1132
1120
|
|
|
1133
|
-
export class DataView
|
|
1121
|
+
export class DataView extends CoreElement<DataViewEventMap>
|
|
1134
1122
|
{
|
|
1135
1123
|
protected m_index: DataIndex;
|
|
1136
|
-
protected m_store: DataStore
|
|
1124
|
+
protected m_store: DataStore;
|
|
1125
|
+
protected m_model: DataModel;
|
|
1137
1126
|
|
|
1138
1127
|
protected m_sort: SortProp[];
|
|
1139
1128
|
protected m_filter: FilterInfo;
|
|
1140
1129
|
|
|
1141
|
-
protected m_props: DataViewProps
|
|
1130
|
+
protected m_props: DataViewProps;
|
|
1142
1131
|
|
|
1143
|
-
constructor( props: DataViewProps
|
|
1132
|
+
constructor( props: DataViewProps ) {
|
|
1144
1133
|
super( );
|
|
1145
1134
|
|
|
1146
1135
|
this.m_props = props;
|
|
@@ -1148,6 +1137,7 @@ export class DataView<T extends Record = Record> extends CoreElement<DataViewEve
|
|
|
1148
1137
|
this.m_index = null;
|
|
1149
1138
|
this.m_filter = null;
|
|
1150
1139
|
this.m_sort = null;
|
|
1140
|
+
this.m_model = this.m_store.getModel();
|
|
1151
1141
|
|
|
1152
1142
|
this.filter( props.filter );
|
|
1153
1143
|
|
|
@@ -1245,7 +1235,7 @@ export class DataView<T extends Record = Record> extends CoreElement<DataViewEve
|
|
|
1245
1235
|
* @param id
|
|
1246
1236
|
*/
|
|
1247
1237
|
|
|
1248
|
-
public indexOfId(id:
|
|
1238
|
+
public indexOfId(id: DataRecordID): number {
|
|
1249
1239
|
let ridx = this.m_store.indexOfId( id );
|
|
1250
1240
|
return this.m_index.findIndex( (rid) => rid === ridx );
|
|
1251
1241
|
}
|
|
@@ -1255,7 +1245,7 @@ export class DataView<T extends Record = Record> extends CoreElement<DataViewEve
|
|
|
1255
1245
|
* @param index
|
|
1256
1246
|
*/
|
|
1257
1247
|
|
|
1258
|
-
public getByIndex(index: number):
|
|
1248
|
+
public getByIndex(index: number): DataRecord {
|
|
1259
1249
|
|
|
1260
1250
|
if (index >= 0 && index < this.m_index.length) {
|
|
1261
1251
|
let rid = this.m_index[index];
|
|
@@ -1265,15 +1255,36 @@ export class DataView<T extends Record = Record> extends CoreElement<DataViewEve
|
|
|
1265
1255
|
return null;
|
|
1266
1256
|
}
|
|
1267
1257
|
|
|
1258
|
+
public getIdByIndex( index: number ) : DataRecordID {
|
|
1259
|
+
const rec = this.getByIndex( index );
|
|
1260
|
+
return this.m_model.getID( rec );
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
public getRecId( rec: DataRecord ): DataRecordID {
|
|
1264
|
+
return this.m_model.getID( rec );
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1268
1267
|
/**
|
|
1269
1268
|
*
|
|
1270
1269
|
* @param id
|
|
1271
1270
|
*/
|
|
1272
1271
|
|
|
1273
|
-
public getById( id:
|
|
1272
|
+
public getById( id: DataRecordID): DataRecord {
|
|
1274
1273
|
return this.m_store.getById( id );
|
|
1275
1274
|
}
|
|
1276
1275
|
|
|
1276
|
+
/**
|
|
1277
|
+
*
|
|
1278
|
+
*/
|
|
1279
|
+
|
|
1280
|
+
getModel( ) {
|
|
1281
|
+
return this.m_model;
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
/**
|
|
1285
|
+
*
|
|
1286
|
+
*/
|
|
1287
|
+
|
|
1277
1288
|
changed( ) {
|
|
1278
1289
|
this.fire( 'view_change', {change_type:'change'} );
|
|
1279
1290
|
}
|
|
@@ -1282,7 +1293,7 @@ export class DataView<T extends Record = Record> extends CoreElement<DataViewEve
|
|
|
1282
1293
|
*
|
|
1283
1294
|
*/
|
|
1284
1295
|
|
|
1285
|
-
forEach( cb: ( rec:
|
|
1296
|
+
forEach( cb: ( rec: DataRecord, index: number ) => any ) {
|
|
1286
1297
|
this.m_index.some( ( index ) => {
|
|
1287
1298
|
let rec = this.m_store.getByIndex( index );
|
|
1288
1299
|
if( rec ) {
|