x4js 2.0.13 → 2.0.15
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 +258 -17
- 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 +276 -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 +40 -7
- package/lib/src/components/dialog/dialog.ts +166 -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 +2 -1
- package/lib/src/components/icon/icon.ts +4 -3
- 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 +178 -31
- 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 +526 -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 +6 -3
- 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 +10 -2
- package/lib/src/components/popup/popup.ts +141 -95
- 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 +112 -0
- package/lib/src/components/propgrid/propgrid.ts +288 -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 +10 -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 +49 -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 +47 -15
- 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 +113 -40
- package/lib/src/core/core_application.ts +223 -2
- package/lib/src/core/core_colors.ts +2 -2
- package/lib/src/{components/grid/datastore.ts → core/core_data.ts} +264 -252
- package/lib/src/core/core_dragdrop.ts +3 -3
- package/lib/src/core/core_element.ts +18 -1
- package/lib/src/core/core_events.ts +28 -0
- package/lib/src/core/core_i18n.ts +19 -3
- package/lib/src/core/core_react.ts +79 -0
- package/lib/src/core/core_router.ts +25 -9
- package/lib/src/core/core_state.ts +62 -0
- package/lib/src/core/core_styles.ts +5 -5
- package/lib/src/core/core_svg.ts +174 -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 +828 -119
- 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 +370 -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 +276 -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 +104 -0
- package/src/components/dialog/dialog.ts +229 -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 +31 -0
- package/src/components/icon/icon.ts +137 -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 +422 -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 +526 -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 +51 -0
- package/src/components/popup/popup.ts +442 -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 +112 -0
- package/src/components/propgrid/propgrid.ts +288 -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 +132 -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 +205 -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 +115 -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 +1075 -0
- package/src/core/core_application.ts +265 -0
- package/src/core/core_colors.ts +250 -0
- package/src/core/core_data.ts +1310 -0
- package/src/core/core_dom.ts +471 -0
- package/src/core/core_dragdrop.ts +201 -0
- package/src/core/core_element.ts +115 -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_state.ts +62 -0
- package/src/core/core_styles.ts +214 -0
- package/src/core/core_svg.ts +712 -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 {
|
|
@@ -76,7 +77,7 @@ const metaFields = Symbol( 'metaField' );
|
|
|
76
77
|
function _getMetas( obj: object, create = true ) : MetaInfos {
|
|
77
78
|
|
|
78
79
|
let ctor = obj.constructor as any;
|
|
79
|
-
let mfld =
|
|
80
|
+
let mfld = Object.prototype.hasOwnProperty.call(ctor,metaFields) ? ctor[metaFields] : undefined;
|
|
80
81
|
|
|
81
82
|
if( mfld===undefined ) {
|
|
82
83
|
if( !create ) {
|
|
@@ -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
|
|
|
@@ -104,14 +105,15 @@ function _getMetas( obj: object, create = true ) : MetaInfos {
|
|
|
104
105
|
return mfld;
|
|
105
106
|
}
|
|
106
107
|
|
|
108
|
+
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
107
109
|
export namespace data {
|
|
108
110
|
|
|
109
|
-
/**
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
111
|
+
/**
|
|
112
|
+
* define a model id
|
|
113
|
+
* @example
|
|
114
|
+
* \@data_id()
|
|
115
|
+
* id: string; // this field is the record id
|
|
116
|
+
**/
|
|
115
117
|
|
|
116
118
|
export function id( ) {
|
|
117
119
|
return ( ownerCls: any, fldName: string ) => {
|
|
@@ -126,110 +128,118 @@ export namespace data {
|
|
|
126
128
|
}
|
|
127
129
|
}
|
|
128
130
|
|
|
129
|
-
/**
|
|
130
|
-
|
|
131
|
-
|
|
131
|
+
/**
|
|
132
|
+
* @ignore
|
|
133
|
+
*/
|
|
132
134
|
|
|
133
135
|
export function field( data: MetaData ) {
|
|
134
136
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
137
|
+
return ( ownerCls: any, fldName: string ) => {
|
|
138
|
+
let metas = _getMetas( ownerCls );
|
|
139
|
+
metas.fields.push( {
|
|
140
|
+
name: fldName,
|
|
141
|
+
...data
|
|
142
|
+
} );
|
|
143
|
+
}
|
|
141
144
|
}
|
|
142
|
-
}
|
|
143
145
|
|
|
144
|
-
/**
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
146
|
+
/**
|
|
147
|
+
* following member is a string field
|
|
148
|
+
* @example
|
|
149
|
+
* \@data_string()
|
|
150
|
+
* my_field: string; // this field will be seen as a string
|
|
151
|
+
*/
|
|
150
152
|
|
|
151
153
|
export function string( props?: MetaData ) {
|
|
152
154
|
return field( { ...props, type: 'string' } );
|
|
153
|
-
}
|
|
155
|
+
}
|
|
154
156
|
|
|
155
|
-
/**
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
157
|
+
/**
|
|
158
|
+
* following member is an integer field
|
|
159
|
+
* @example
|
|
160
|
+
* \@data_string()
|
|
161
|
+
* my_field: number; // this field will be seen as an integer
|
|
162
|
+
*/
|
|
161
163
|
|
|
162
164
|
export function int( props?: MetaData ) {
|
|
163
165
|
return field( { ...props, type: 'int' } );
|
|
164
|
-
}
|
|
166
|
+
}
|
|
165
167
|
|
|
166
|
-
/**
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
168
|
+
/**
|
|
169
|
+
* following member is a float field
|
|
170
|
+
* @example
|
|
171
|
+
* \@data_float()
|
|
172
|
+
* my_field: number; // this field will be seen as a float
|
|
173
|
+
*/
|
|
172
174
|
|
|
173
175
|
export function float( props?: MetaData ) {
|
|
174
176
|
return field( { ...props, type: 'float' } );
|
|
175
|
-
}
|
|
177
|
+
}
|
|
176
178
|
|
|
177
|
-
/**
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
179
|
+
/**
|
|
180
|
+
* following member is a boolean field
|
|
181
|
+
* @example
|
|
182
|
+
* \@data_bool()
|
|
183
|
+
* my_field: boolean; // this field will be seen as a boolean
|
|
184
|
+
*/
|
|
183
185
|
|
|
184
186
|
export function bool( props?: MetaData ) {
|
|
185
187
|
return field( { ...props, type: 'bool' } );
|
|
186
|
-
}
|
|
188
|
+
}
|
|
187
189
|
|
|
188
|
-
/**
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
190
|
+
/**
|
|
191
|
+
* following member is a date field
|
|
192
|
+
* @example
|
|
193
|
+
* \@data_date()
|
|
194
|
+
* my_field: date; // this field will be seen as a date
|
|
195
|
+
*/
|
|
194
196
|
|
|
195
197
|
export function date( props?: MetaData ) {
|
|
196
198
|
return field( { ...props, type: 'date' } );
|
|
197
|
-
}
|
|
199
|
+
}
|
|
198
200
|
|
|
199
|
-
/**
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
201
|
+
/**
|
|
202
|
+
* following member is a calculated field
|
|
203
|
+
* @example
|
|
204
|
+
* \@data_calc( )
|
|
205
|
+
* get my_field(): string => {
|
|
206
|
+
* return 'hello';
|
|
207
|
+
* };
|
|
208
|
+
*/
|
|
207
209
|
|
|
208
210
|
export function calc( props?: MetaData ) {
|
|
209
211
|
return field( { ...props, type: 'calc'} )
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
|
|
212
|
+
}
|
|
213
213
|
|
|
214
|
-
/**
|
|
215
|
-
|
|
216
|
-
|
|
214
|
+
/**
|
|
215
|
+
*
|
|
216
|
+
*/
|
|
217
217
|
|
|
218
|
-
interface
|
|
219
|
-
|
|
220
|
-
}
|
|
218
|
+
interface ModelConstructor {
|
|
219
|
+
new ( data?: any, id?: any ): DataModel;
|
|
220
|
+
}
|
|
221
221
|
|
|
222
|
-
/**
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
222
|
+
/**
|
|
223
|
+
* following member is a record array
|
|
224
|
+
* @example
|
|
225
|
+
* \@data_array( )
|
|
226
|
+
* my_field(): TypedRecord[];
|
|
227
|
+
*/
|
|
228
228
|
|
|
229
|
-
export function array( ctor:
|
|
229
|
+
export function array( ctor: ModelConstructor, props?: MetaData ) {
|
|
230
230
|
return data.field( { ...props, type: 'array', model: ctor ? new ctor() : null } )
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
+
/**
|
|
234
|
+
* following member is unknown
|
|
235
|
+
* @example
|
|
236
|
+
* \@data.any( )
|
|
237
|
+
* my_field: TypedRecord[];
|
|
238
|
+
*/
|
|
239
|
+
|
|
240
|
+
export function any( props?: MetaData ) {
|
|
241
|
+
return field( { ...props, type: 'any' } );
|
|
242
|
+
}
|
|
233
243
|
}
|
|
234
244
|
|
|
235
245
|
|
|
@@ -239,34 +249,7 @@ interface RecordConstructor {
|
|
|
239
249
|
* record model
|
|
240
250
|
*/
|
|
241
251
|
|
|
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
|
-
}
|
|
252
|
+
export class DataModel {
|
|
270
253
|
|
|
271
254
|
/**
|
|
272
255
|
* MUST IMPLEMENT
|
|
@@ -277,18 +260,19 @@ export class Record {
|
|
|
277
260
|
let metas = _getMetas( this, false );
|
|
278
261
|
return metas.fields;
|
|
279
262
|
}
|
|
280
|
-
|
|
263
|
+
|
|
281
264
|
/**
|
|
282
265
|
*
|
|
283
266
|
*/
|
|
284
267
|
|
|
285
|
-
validate( ) : Error[] {
|
|
268
|
+
validate( record: DataRecord ) : Error[] {
|
|
286
269
|
|
|
287
270
|
let errs: Error[] = null;
|
|
288
271
|
|
|
289
272
|
let fields = this.getFields( );
|
|
273
|
+
|
|
290
274
|
fields.forEach( (fi) => {
|
|
291
|
-
if( fi.required && !this.getField(fi.name) ) {
|
|
275
|
+
if( fi.required && !this.getField(fi.name,record) ) {
|
|
292
276
|
if( errs ) {
|
|
293
277
|
errs = [];
|
|
294
278
|
}
|
|
@@ -298,15 +282,11 @@ export class Record {
|
|
|
298
282
|
})
|
|
299
283
|
|
|
300
284
|
return errs;
|
|
301
|
-
}
|
|
285
|
+
}
|
|
302
286
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
// return <FieldInfo>{ name };
|
|
307
|
-
// });
|
|
308
|
-
// }
|
|
309
|
-
//}
|
|
287
|
+
/**
|
|
288
|
+
* return the field index by name
|
|
289
|
+
*/
|
|
310
290
|
|
|
311
291
|
getFieldIndex( name: string ) : number {
|
|
312
292
|
let fields = this.getFields( );
|
|
@@ -318,17 +298,19 @@ export class Record {
|
|
|
318
298
|
* @returns an object with known record values
|
|
319
299
|
*/
|
|
320
300
|
|
|
321
|
-
serialize():
|
|
301
|
+
serialize<T = any>( input: DataRecord ): T {
|
|
322
302
|
let rec: any = {};
|
|
323
303
|
|
|
324
304
|
this.getFields().forEach((f) => {
|
|
325
305
|
if( f.calc === undefined ) {
|
|
326
|
-
rec[f.name] =
|
|
306
|
+
rec[f.name] = input[f.name];
|
|
327
307
|
}
|
|
328
308
|
});
|
|
329
309
|
|
|
330
|
-
return rec;
|
|
310
|
+
return rec as T;
|
|
331
311
|
}
|
|
312
|
+
|
|
313
|
+
|
|
332
314
|
|
|
333
315
|
/**
|
|
334
316
|
* default unserializer
|
|
@@ -336,25 +318,26 @@ export class Record {
|
|
|
336
318
|
* @returns a new Record
|
|
337
319
|
*/
|
|
338
320
|
|
|
339
|
-
unSerialize(data: any, id?:
|
|
321
|
+
unSerialize(data: any, id?: DataRecordID ) : DataRecord {
|
|
340
322
|
|
|
341
|
-
|
|
323
|
+
const fields = this.getFields();
|
|
324
|
+
const rec = new DataRecord( );
|
|
342
325
|
|
|
343
326
|
fields.forEach( (sf) => {
|
|
344
327
|
let value = data[sf.name];
|
|
345
328
|
if (value !== undefined) {
|
|
346
|
-
|
|
329
|
+
rec[sf.name] = this._convertField( sf, value );
|
|
347
330
|
}
|
|
348
331
|
});
|
|
349
332
|
|
|
350
333
|
if( id!==undefined ) {
|
|
351
|
-
|
|
334
|
+
rec[fields[0].name] = id;
|
|
352
335
|
}
|
|
353
336
|
else {
|
|
354
|
-
console.assert( this.getID()!==undefined ); // store do not have ID field
|
|
337
|
+
console.assert( this.getID(rec)!==undefined ); // store do not have ID field
|
|
355
338
|
}
|
|
356
339
|
|
|
357
|
-
return
|
|
340
|
+
return rec;
|
|
358
341
|
}
|
|
359
342
|
|
|
360
343
|
/**
|
|
@@ -389,6 +372,8 @@ export class Record {
|
|
|
389
372
|
}
|
|
390
373
|
|
|
391
374
|
case 'array': {
|
|
375
|
+
debugger;
|
|
376
|
+
/*
|
|
392
377
|
let result: any[] = [];
|
|
393
378
|
|
|
394
379
|
if( field.model ) {
|
|
@@ -398,6 +383,7 @@ export class Record {
|
|
|
398
383
|
|
|
399
384
|
return result;
|
|
400
385
|
}
|
|
386
|
+
*/
|
|
401
387
|
break;
|
|
402
388
|
}
|
|
403
389
|
}
|
|
@@ -405,18 +391,30 @@ export class Record {
|
|
|
405
391
|
return input;
|
|
406
392
|
}
|
|
407
393
|
|
|
394
|
+
/**
|
|
395
|
+
* get the record unique identifier
|
|
396
|
+
* by default the return value is the first field
|
|
397
|
+
* @return unique identifier
|
|
398
|
+
*/
|
|
399
|
+
|
|
400
|
+
getID( rec: DataRecord ): any {
|
|
401
|
+
if( !rec ) return null;
|
|
402
|
+
let metas = _getMetas( this, false );
|
|
403
|
+
return rec[metas.id];
|
|
404
|
+
}
|
|
405
|
+
|
|
408
406
|
/**
|
|
409
407
|
* get raw value of a field
|
|
410
408
|
* @param name - field name or field index
|
|
411
409
|
*/
|
|
412
410
|
|
|
413
|
-
getRaw( name: string | number ) : any {
|
|
411
|
+
getRaw( name: string | number, rec: DataRecord ) : any {
|
|
414
412
|
|
|
415
413
|
let idx;
|
|
416
414
|
let fields = this.getFields( );
|
|
417
415
|
|
|
418
416
|
if( typeof(name) === 'string' ) {
|
|
419
|
-
idx = fields.findIndex( fi => fi.name == name );
|
|
417
|
+
idx = fields.findIndex( ( fi: FieldInfo) => fi.name == name );
|
|
420
418
|
if( idx < 0 ) {
|
|
421
419
|
console.assert( false, 'unknown field: '+name);
|
|
422
420
|
return undefined;
|
|
@@ -436,20 +434,10 @@ export class Record {
|
|
|
436
434
|
|
|
437
435
|
let fld = fields[idx];
|
|
438
436
|
if( fld.calc!==undefined ) {
|
|
439
|
-
return fld.calc(
|
|
437
|
+
return fld.calc( rec );
|
|
440
438
|
}
|
|
441
439
|
|
|
442
|
-
return
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
/**
|
|
446
|
-
*
|
|
447
|
-
* @param name
|
|
448
|
-
* @param data
|
|
449
|
-
*/
|
|
450
|
-
|
|
451
|
-
setRaw( name: string, data: string ) {
|
|
452
|
-
this[name] = data;
|
|
440
|
+
return rec[fld.name];
|
|
453
441
|
}
|
|
454
442
|
|
|
455
443
|
/**
|
|
@@ -459,18 +447,50 @@ export class Record {
|
|
|
459
447
|
* let value = record.get('field1');
|
|
460
448
|
*/
|
|
461
449
|
|
|
462
|
-
getField( name: string ): string {
|
|
463
|
-
let v = this.getRaw( name );
|
|
450
|
+
getField( name: string, rec: DataRecord ): string {
|
|
451
|
+
let v = this.getRaw( name, rec );
|
|
464
452
|
return (v===undefined || v===null) ? '' : ''+v;
|
|
465
453
|
}
|
|
454
|
+
}
|
|
466
455
|
|
|
467
|
-
|
|
456
|
+
/**
|
|
457
|
+
*
|
|
458
|
+
*/
|
|
459
|
+
|
|
460
|
+
export class DataRecord {
|
|
461
|
+
[ key: string ]: DataFieldValue;
|
|
462
|
+
|
|
463
|
+
/*
|
|
464
|
+
/ **
|
|
465
|
+
* @returns fields descriptors
|
|
466
|
+
* /
|
|
467
|
+
|
|
468
|
+
getFields(): FieldInfo[] {
|
|
469
|
+
let metas = _getMetas( this, false );
|
|
470
|
+
return metas.fields;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
/ **
|
|
476
|
+
*
|
|
477
|
+
* @param name
|
|
478
|
+
* @param data
|
|
479
|
+
* /
|
|
480
|
+
|
|
481
|
+
setRaw( name: string, data: string ) {
|
|
482
|
+
this[name] = data;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
/ **
|
|
468
488
|
* set field value
|
|
469
489
|
* @param name - field name
|
|
470
490
|
* @param value - value to set
|
|
471
491
|
* @example
|
|
472
492
|
* record.set( 'field1', 7 );
|
|
473
|
-
|
|
493
|
+
* /
|
|
474
494
|
|
|
475
495
|
setField(name: string, value: any) {
|
|
476
496
|
let fields = this.getFields( );
|
|
@@ -489,65 +509,21 @@ export class Record {
|
|
|
489
509
|
|
|
490
510
|
this.setRaw( fld.name, value );
|
|
491
511
|
}
|
|
492
|
-
|
|
493
|
-
|
|
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
|
-
}
|
|
512
|
+
*/
|
|
517
513
|
|
|
518
|
-
|
|
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
|
-
}
|
|
514
|
+
|
|
540
515
|
}
|
|
541
516
|
|
|
517
|
+
|
|
542
518
|
/**
|
|
543
519
|
*
|
|
544
520
|
*/
|
|
545
521
|
|
|
546
|
-
interface DataEventMap extends
|
|
522
|
+
interface DataEventMap extends EventMap {
|
|
547
523
|
change?: EvChange;
|
|
548
524
|
}
|
|
549
525
|
|
|
550
|
-
type DataSolver = ( data: any ) =>
|
|
526
|
+
type DataSolver = ( data: any ) => DataRecord[];
|
|
551
527
|
|
|
552
528
|
export interface DataProxyProps {
|
|
553
529
|
url: string;
|
|
@@ -596,9 +572,9 @@ export class DataProxy extends CoreElement<DataEventMap> {
|
|
|
596
572
|
*
|
|
597
573
|
*/
|
|
598
574
|
|
|
599
|
-
interface DataStoreProps
|
|
600
|
-
model:
|
|
601
|
-
data?:
|
|
575
|
+
interface DataStoreProps {
|
|
576
|
+
model: DataModel;
|
|
577
|
+
data?: any[];
|
|
602
578
|
url?: string;
|
|
603
579
|
autoload?: false;
|
|
604
580
|
solver?: DataSolver;
|
|
@@ -615,16 +591,16 @@ interface DataStoreEventMap extends EventMap {
|
|
|
615
591
|
*
|
|
616
592
|
*/
|
|
617
593
|
|
|
618
|
-
export class DataStore
|
|
594
|
+
export class DataStore extends EventSource<DataStoreEventMap> {
|
|
619
595
|
|
|
620
|
-
protected m_model:
|
|
596
|
+
protected m_model: DataModel;
|
|
621
597
|
protected m_fields: FieldInfo[];
|
|
622
|
-
protected m_records:
|
|
598
|
+
protected m_records: DataRecord[];
|
|
623
599
|
|
|
624
600
|
protected m_proxy: DataProxy;
|
|
625
601
|
protected m_rec_index: DataIndex;
|
|
626
602
|
|
|
627
|
-
constructor(props: DataStoreProps
|
|
603
|
+
constructor(props: DataStoreProps ) {
|
|
628
604
|
super( );
|
|
629
605
|
|
|
630
606
|
this.m_fields = undefined;
|
|
@@ -672,10 +648,10 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
672
648
|
|
|
673
649
|
public setData( records: any[] ) {
|
|
674
650
|
|
|
675
|
-
|
|
651
|
+
const realRecords: DataRecord[] = new Array( records.length );
|
|
676
652
|
|
|
677
|
-
records.forEach( (rec) => {
|
|
678
|
-
realRecords
|
|
653
|
+
records.forEach( (rec,idx) => {
|
|
654
|
+
realRecords[idx] = this.m_model.unSerialize(rec);
|
|
679
655
|
});
|
|
680
656
|
|
|
681
657
|
this.setRawData( realRecords );
|
|
@@ -686,14 +662,13 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
686
662
|
* @param records - must be of the same type as model
|
|
687
663
|
*/
|
|
688
664
|
|
|
689
|
-
public setRawData(records:
|
|
665
|
+
public setRawData(records: DataRecord[]) {
|
|
690
666
|
|
|
691
667
|
this.m_records = records;
|
|
692
668
|
this._rebuildIndex( );
|
|
693
669
|
this.fire( 'data_change', { change_type: 'change'} );
|
|
694
670
|
}
|
|
695
671
|
|
|
696
|
-
|
|
697
672
|
private _rebuildIndex( ) {
|
|
698
673
|
this.m_rec_index = null; // null to signal that we have to run on records instead of index
|
|
699
674
|
this.m_rec_index = this.createIndex( null ); // prepare index (remove deleted)
|
|
@@ -704,8 +679,9 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
704
679
|
*
|
|
705
680
|
*/
|
|
706
681
|
|
|
707
|
-
public update( rec:
|
|
708
|
-
|
|
682
|
+
public update( rec: DataRecord ) {
|
|
683
|
+
|
|
684
|
+
let id = this.m_model.getID( rec );
|
|
709
685
|
let index = this.indexOfId(id);
|
|
710
686
|
if (index < 0) {
|
|
711
687
|
return false;
|
|
@@ -721,18 +697,18 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
721
697
|
* @param data
|
|
722
698
|
*/
|
|
723
699
|
|
|
724
|
-
public append( rec:
|
|
700
|
+
public append( rec: DataRecord | any ) {
|
|
725
701
|
|
|
726
|
-
if( !(rec instanceof
|
|
727
|
-
|
|
728
|
-
rec = nrec.unSerialize( rec );
|
|
702
|
+
if( !(rec instanceof DataRecord) ) {
|
|
703
|
+
rec = this.m_model.unSerialize( rec );
|
|
729
704
|
}
|
|
730
705
|
|
|
731
|
-
|
|
706
|
+
const id = this.m_model.getID(rec);
|
|
707
|
+
console.assert( id!==undefined );
|
|
732
708
|
|
|
733
709
|
this.m_records.push( rec );
|
|
734
710
|
this._rebuildIndex( );
|
|
735
|
-
this.fire( 'data_change', {change_type: 'create', id
|
|
711
|
+
this.fire( 'data_change', {change_type: 'create', id } );
|
|
736
712
|
}
|
|
737
713
|
|
|
738
714
|
/**
|
|
@@ -741,8 +717,10 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
741
717
|
|
|
742
718
|
getMaxId( ) {
|
|
743
719
|
let maxID: number = undefined;
|
|
720
|
+
const m = this.m_model;
|
|
721
|
+
|
|
744
722
|
this.m_records.forEach( (r) => {
|
|
745
|
-
let rid =
|
|
723
|
+
let rid = m.getID( r );
|
|
746
724
|
if( maxID===undefined || maxID<rid ) {
|
|
747
725
|
maxID = rid;
|
|
748
726
|
}
|
|
@@ -756,7 +734,7 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
756
734
|
* @param id
|
|
757
735
|
*/
|
|
758
736
|
|
|
759
|
-
public delete(id:
|
|
737
|
+
public delete(id: DataRecordID ): boolean {
|
|
760
738
|
|
|
761
739
|
let idx = this.indexOfId( id );
|
|
762
740
|
if( idx<0 ) {
|
|
@@ -792,17 +770,19 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
792
770
|
* find the index of the element with the given id
|
|
793
771
|
*/
|
|
794
772
|
|
|
795
|
-
public indexOfId(id:
|
|
773
|
+
public indexOfId(id: DataRecordID ): number {
|
|
796
774
|
|
|
797
775
|
//if( this.count<10 ) {
|
|
798
776
|
// this.forEach( (rec) => rec.getID() == id );
|
|
799
777
|
//}
|
|
800
778
|
|
|
779
|
+
const m = this.m_model;
|
|
780
|
+
|
|
801
781
|
for( let lim = this.count, base = 0; lim != 0; lim >>= 1 ) {
|
|
802
782
|
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
783
|
+
const p = base + (lim >> 1); // int conversion
|
|
784
|
+
const idx = this.m_rec_index[p];
|
|
785
|
+
const rid = m.getID( this.m_records[idx] );
|
|
806
786
|
|
|
807
787
|
if( rid==id ) {
|
|
808
788
|
return p;
|
|
@@ -822,7 +802,7 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
822
802
|
* @returns record or null
|
|
823
803
|
*/
|
|
824
804
|
|
|
825
|
-
public getById(id:
|
|
805
|
+
public getById(id: DataRecordID): DataRecord {
|
|
826
806
|
let idx = this.indexOfId( id );
|
|
827
807
|
if( idx<0 ) {
|
|
828
808
|
return null;
|
|
@@ -837,16 +817,16 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
837
817
|
* @returns record or null
|
|
838
818
|
*/
|
|
839
819
|
|
|
840
|
-
public getByIndex( index: number ):
|
|
820
|
+
public getByIndex( index: number ): DataRecord {
|
|
841
821
|
let idx = this.m_rec_index[index];
|
|
842
822
|
return this._getRecord( idx );
|
|
843
823
|
}
|
|
844
824
|
|
|
845
|
-
private _getRecord( index: number ) :
|
|
825
|
+
private _getRecord( index: number ) : DataRecord {
|
|
846
826
|
return this.m_records[index] ?? null;
|
|
847
827
|
}
|
|
848
828
|
|
|
849
|
-
public moveTo( other: DataStore
|
|
829
|
+
public moveTo( other: DataStore ) {
|
|
850
830
|
other.setRawData( this.m_records );
|
|
851
831
|
}
|
|
852
832
|
|
|
@@ -855,7 +835,7 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
855
835
|
* @param opts
|
|
856
836
|
*/
|
|
857
837
|
|
|
858
|
-
createView( opts?: DataViewProps
|
|
838
|
+
createView( opts?: DataViewProps ) : DataView {
|
|
859
839
|
let eopts = { ...opts, store: this };
|
|
860
840
|
return new DataView( eopts );
|
|
861
841
|
}
|
|
@@ -882,11 +862,10 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
882
862
|
else {
|
|
883
863
|
if( typeof(filter.op)==='function' ) {
|
|
884
864
|
|
|
885
|
-
let fn =
|
|
865
|
+
let fn = filter.op as FilterFunc;
|
|
886
866
|
|
|
887
867
|
// scan all records and append only interesting ones
|
|
888
868
|
this.forEach( (rec, idx) => {
|
|
889
|
-
|
|
890
869
|
// skip deleted
|
|
891
870
|
if( !rec ) {
|
|
892
871
|
return;
|
|
@@ -957,6 +936,8 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
957
936
|
}
|
|
958
937
|
|
|
959
938
|
// scan all records and append only interesting ones
|
|
939
|
+
const m = this.m_model;
|
|
940
|
+
|
|
960
941
|
this.forEach( (rec, idx) => {
|
|
961
942
|
|
|
962
943
|
// skip deleted
|
|
@@ -964,7 +945,7 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
964
945
|
return;
|
|
965
946
|
}
|
|
966
947
|
|
|
967
|
-
let field =
|
|
948
|
+
let field = m.getRaw( filterFld, rec );
|
|
968
949
|
if( field===null || field===undefined ) {
|
|
969
950
|
field = '';
|
|
970
951
|
}
|
|
@@ -1019,13 +1000,16 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
1019
1000
|
}
|
|
1020
1001
|
|
|
1021
1002
|
// sort only by one field : optimize it
|
|
1003
|
+
const m = this.m_model;
|
|
1004
|
+
|
|
1022
1005
|
if( fidxs.length==1 ) {
|
|
1023
1006
|
|
|
1024
|
-
|
|
1007
|
+
const field = fidxs[0].fidx;
|
|
1008
|
+
|
|
1025
1009
|
index.sort( ( ia, ib ) => {
|
|
1026
1010
|
|
|
1027
|
-
let va = this.getByIndex(ia)
|
|
1028
|
-
let vb = this.getByIndex(ib)
|
|
1011
|
+
let va = m.getRaw( field, this.getByIndex(ia) ) ?? '';
|
|
1012
|
+
let vb = m.getRaw( field, this.getByIndex(ib) ) ?? '';
|
|
1029
1013
|
if (va > vb) { return 1; }
|
|
1030
1014
|
if (va < vb) { return -1; }
|
|
1031
1015
|
return 0;
|
|
@@ -1044,8 +1028,8 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
1044
1028
|
let fidx = fidxs[fi].fidx;
|
|
1045
1029
|
let mul = fidxs[fi].asc ? 1 : -1;
|
|
1046
1030
|
|
|
1047
|
-
let va = this.getByIndex(ia)
|
|
1048
|
-
let vb = this.getByIndex(ib)
|
|
1031
|
+
let va = m.getRaw( fidx, this.getByIndex(ia) ) ?? '';
|
|
1032
|
+
let vb = m.getRaw( fidx, this.getByIndex(ib) ) ?? '';
|
|
1049
1033
|
if (va > vb) { return mul; }
|
|
1050
1034
|
if (va < vb) { return -mul; }
|
|
1051
1035
|
}
|
|
@@ -1056,12 +1040,12 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
1056
1040
|
|
|
1057
1041
|
return index
|
|
1058
1042
|
}
|
|
1059
|
-
|
|
1043
|
+
|
|
1060
1044
|
/**
|
|
1061
1045
|
*
|
|
1062
1046
|
*/
|
|
1063
1047
|
|
|
1064
|
-
forEach( cb: ( rec:
|
|
1048
|
+
forEach( cb: ( rec: DataRecord, index: number ) => any ) {
|
|
1065
1049
|
|
|
1066
1050
|
if( this.m_rec_index ) {
|
|
1067
1051
|
this.m_rec_index.some( (ri,index) => {
|
|
@@ -1088,6 +1072,10 @@ export class DataStore<T extends Record = Record> extends EventSource<DataStoreE
|
|
|
1088
1072
|
changed( ) {
|
|
1089
1073
|
this.fire( 'data_change', { change_type: 'change'} );
|
|
1090
1074
|
}
|
|
1075
|
+
|
|
1076
|
+
getModel( ) {
|
|
1077
|
+
return this.m_model;
|
|
1078
|
+
}
|
|
1091
1079
|
}
|
|
1092
1080
|
|
|
1093
1081
|
|
|
@@ -1101,13 +1089,13 @@ interface DataViewEventMap extends EventMap {
|
|
|
1101
1089
|
view_change: EvViewChange;
|
|
1102
1090
|
}
|
|
1103
1091
|
|
|
1104
|
-
interface DataViewProps
|
|
1105
|
-
store?: DataStore
|
|
1092
|
+
interface DataViewProps {
|
|
1093
|
+
store?: DataStore;
|
|
1106
1094
|
filter?: FilterInfo;
|
|
1107
1095
|
order?: string | SortProp[] | SortProp;
|
|
1108
1096
|
}
|
|
1109
1097
|
|
|
1110
|
-
export type FilterFunc = ( rec:
|
|
1098
|
+
export type FilterFunc = ( rec: DataRecord ) => boolean;
|
|
1111
1099
|
|
|
1112
1100
|
export interface FilterInfo {
|
|
1113
1101
|
op: '<' | '<=' | '=' | '>=' | '>' | '<>' | 'empty-result' | FilterFunc, // emptydb mean return an empty result always
|
|
@@ -1120,6 +1108,7 @@ export interface FilterInfo {
|
|
|
1120
1108
|
export interface SortProp {
|
|
1121
1109
|
field: string; //
|
|
1122
1110
|
ascending: boolean; //
|
|
1111
|
+
numeric?: boolean; // numeric sort
|
|
1123
1112
|
}
|
|
1124
1113
|
|
|
1125
1114
|
|
|
@@ -1130,17 +1119,18 @@ export interface SortProp {
|
|
|
1130
1119
|
* You can have multiple views for a single DataStore
|
|
1131
1120
|
*/
|
|
1132
1121
|
|
|
1133
|
-
export class DataView
|
|
1122
|
+
export class DataView extends CoreElement<DataViewEventMap>
|
|
1134
1123
|
{
|
|
1135
1124
|
protected m_index: DataIndex;
|
|
1136
|
-
protected m_store: DataStore
|
|
1125
|
+
protected m_store: DataStore;
|
|
1126
|
+
protected m_model: DataModel;
|
|
1137
1127
|
|
|
1138
1128
|
protected m_sort: SortProp[];
|
|
1139
1129
|
protected m_filter: FilterInfo;
|
|
1140
1130
|
|
|
1141
|
-
protected m_props: DataViewProps
|
|
1131
|
+
protected m_props: DataViewProps;
|
|
1142
1132
|
|
|
1143
|
-
constructor( props: DataViewProps
|
|
1133
|
+
constructor( props: DataViewProps ) {
|
|
1144
1134
|
super( );
|
|
1145
1135
|
|
|
1146
1136
|
this.m_props = props;
|
|
@@ -1148,6 +1138,7 @@ export class DataView<T extends Record = Record> extends CoreElement<DataViewEve
|
|
|
1148
1138
|
this.m_index = null;
|
|
1149
1139
|
this.m_filter = null;
|
|
1150
1140
|
this.m_sort = null;
|
|
1141
|
+
this.m_model = this.m_store.getModel();
|
|
1151
1142
|
|
|
1152
1143
|
this.filter( props.filter );
|
|
1153
1144
|
|
|
@@ -1245,7 +1236,7 @@ export class DataView<T extends Record = Record> extends CoreElement<DataViewEve
|
|
|
1245
1236
|
* @param id
|
|
1246
1237
|
*/
|
|
1247
1238
|
|
|
1248
|
-
public indexOfId(id:
|
|
1239
|
+
public indexOfId(id: DataRecordID): number {
|
|
1249
1240
|
let ridx = this.m_store.indexOfId( id );
|
|
1250
1241
|
return this.m_index.findIndex( (rid) => rid === ridx );
|
|
1251
1242
|
}
|
|
@@ -1255,7 +1246,7 @@ export class DataView<T extends Record = Record> extends CoreElement<DataViewEve
|
|
|
1255
1246
|
* @param index
|
|
1256
1247
|
*/
|
|
1257
1248
|
|
|
1258
|
-
public getByIndex(index: number):
|
|
1249
|
+
public getByIndex(index: number): DataRecord {
|
|
1259
1250
|
|
|
1260
1251
|
if (index >= 0 && index < this.m_index.length) {
|
|
1261
1252
|
let rid = this.m_index[index];
|
|
@@ -1265,15 +1256,36 @@ export class DataView<T extends Record = Record> extends CoreElement<DataViewEve
|
|
|
1265
1256
|
return null;
|
|
1266
1257
|
}
|
|
1267
1258
|
|
|
1259
|
+
public getIdByIndex( index: number ) : DataRecordID {
|
|
1260
|
+
const rec = this.getByIndex( index );
|
|
1261
|
+
return this.m_model.getID( rec );
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
public getRecId( rec: DataRecord ): DataRecordID {
|
|
1265
|
+
return this.m_model.getID( rec );
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
1268
|
/**
|
|
1269
1269
|
*
|
|
1270
1270
|
* @param id
|
|
1271
1271
|
*/
|
|
1272
1272
|
|
|
1273
|
-
public getById( id:
|
|
1273
|
+
public getById( id: DataRecordID): DataRecord {
|
|
1274
1274
|
return this.m_store.getById( id );
|
|
1275
1275
|
}
|
|
1276
1276
|
|
|
1277
|
+
/**
|
|
1278
|
+
*
|
|
1279
|
+
*/
|
|
1280
|
+
|
|
1281
|
+
getModel( ) {
|
|
1282
|
+
return this.m_model;
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
/**
|
|
1286
|
+
*
|
|
1287
|
+
*/
|
|
1288
|
+
|
|
1277
1289
|
changed( ) {
|
|
1278
1290
|
this.fire( 'view_change', {change_type:'change'} );
|
|
1279
1291
|
}
|
|
@@ -1282,7 +1294,7 @@ export class DataView<T extends Record = Record> extends CoreElement<DataViewEve
|
|
|
1282
1294
|
*
|
|
1283
1295
|
*/
|
|
1284
1296
|
|
|
1285
|
-
forEach( cb: ( rec:
|
|
1297
|
+
forEach( cb: ( rec: DataRecord, index: number ) => any ) {
|
|
1286
1298
|
this.m_index.some( ( index ) => {
|
|
1287
1299
|
let rec = this.m_store.getByIndex( index );
|
|
1288
1300
|
if( rec ) {
|