x4js 2.0.33 → 2.0.35
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/package.json +1 -1
- package/src/components/dialog/dialog.module.scss +1 -0
- package/src/components/gridview/gridview.ts +6 -5
- package/src/components/messages/messages.module.scss +30 -13
- package/src/components/messages/messages.ts +32 -9
- package/src/components/sizers/sizer.module.scss +6 -1
- package/src/components/sizers/sizer.ts +26 -5
- package/src/core/core_data.ts +20 -7
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
import { Component, ComponentContent, ComponentEvents, ComponentProps, EvClick, EvContextMenu, EvDblClick, EvSelectionChange } from '../../core/component';
|
|
19
19
|
import { class_ns, isNumber, isString, setWaitCursor, UnsafeHtml } from '../../core/core_tools';
|
|
20
|
-
import { DataModel, DataStore, DataView, DataRecord, EvViewChange } from '../../core/core_data';
|
|
20
|
+
import { DataModel, DataStore, DataView, DataRecord, EvViewChange, SortCallback } from '../../core/core_data';
|
|
21
21
|
import { EventCallback } from '../../core/core_events';
|
|
22
22
|
import { kbNav } from '../../core/core_tools';
|
|
23
23
|
|
|
@@ -59,7 +59,7 @@ export interface GridColumn {
|
|
|
59
59
|
formatter?: (input: any) => string; // for "custom" type
|
|
60
60
|
type?: ColType;
|
|
61
61
|
cls?: string;
|
|
62
|
-
sortable?: boolean;
|
|
62
|
+
sortable?: boolean | SortCallback;
|
|
63
63
|
footer_val?: string;
|
|
64
64
|
classifier?: CellClassifier;
|
|
65
65
|
}
|
|
@@ -86,7 +86,7 @@ export interface GridviewProps extends ComponentProps {
|
|
|
86
86
|
contextMenu?: EventCallback<EvContextMenu>;
|
|
87
87
|
selectionChange?: EventCallback<EvSelectionChange>;
|
|
88
88
|
sort?: {
|
|
89
|
-
|
|
89
|
+
field_id: string;
|
|
90
90
|
asc?: boolean;
|
|
91
91
|
}
|
|
92
92
|
}
|
|
@@ -184,7 +184,7 @@ export class Gridview<P extends GridviewProps = GridviewProps, E extends Gridvie
|
|
|
184
184
|
this.setStore(props.store);
|
|
185
185
|
|
|
186
186
|
if( props.sort ) {
|
|
187
|
-
this.sortCol( props.sort.
|
|
187
|
+
this.sortCol( props.sort.field_id, props.sort.asc===true );
|
|
188
188
|
}
|
|
189
189
|
}
|
|
190
190
|
}
|
|
@@ -625,7 +625,8 @@ export class Gridview<P extends GridviewProps = GridviewProps, E extends Gridvie
|
|
|
625
625
|
this._dataview.sort([{
|
|
626
626
|
field: cdata.id,
|
|
627
627
|
ascending: asc,
|
|
628
|
-
numeric: num
|
|
628
|
+
numeric: num,
|
|
629
|
+
callback: cdata.sortable instanceof Function ? cdata.sortable : undefined,
|
|
629
630
|
}]);
|
|
630
631
|
|
|
631
632
|
this._update(true);
|
|
@@ -92,38 +92,55 @@
|
|
|
92
92
|
|
|
93
93
|
|
|
94
94
|
.x4progressionbox {
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
min-height: 200px;
|
|
96
|
+
min-width: 500px;
|
|
97
|
+
|
|
97
98
|
&> .x4form {
|
|
98
99
|
min-height: unset;
|
|
99
100
|
}
|
|
100
101
|
|
|
101
|
-
& > .caption,
|
|
102
|
-
& > #btnbar {
|
|
103
|
-
display: none;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
102
|
& .x4form {
|
|
107
103
|
min-width: 400px;
|
|
104
|
+
gap: 8px;
|
|
105
|
+
|
|
106
|
+
&> .x4hbox {
|
|
107
|
+
flex-grow: 1;
|
|
108
|
+
align-items: stretch;
|
|
109
|
+
.right {
|
|
110
|
+
flex-grow: 1;
|
|
111
|
+
gap: 8px;
|
|
112
|
+
display: grid;
|
|
113
|
+
grid-template-rows: auto auto 1fr;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
108
117
|
.x4icon {
|
|
109
118
|
height: 64px;
|
|
110
119
|
animation: rotating 3s linear infinite;
|
|
111
120
|
fill: var(--accent-background);
|
|
121
|
+
align-self: center;
|
|
112
122
|
}
|
|
113
123
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
padding: 16px 16px 0 16px;
|
|
124
|
+
#title {
|
|
125
|
+
padding: 4px 16px;
|
|
117
126
|
line-height: 1.8em;
|
|
118
127
|
}
|
|
119
128
|
|
|
120
129
|
.x4progress {
|
|
121
|
-
margin
|
|
130
|
+
margin: 0 16px;
|
|
122
131
|
}
|
|
123
132
|
|
|
124
133
|
#sub-text {
|
|
125
|
-
|
|
126
|
-
|
|
134
|
+
flex-grow: 1;
|
|
135
|
+
max-height: 400px;
|
|
136
|
+
overflow: auto;
|
|
137
|
+
background-color: #f5f5f5;
|
|
138
|
+
padding: 4px 8px;
|
|
139
|
+
margin: 0 16px;
|
|
140
|
+
|
|
141
|
+
.x4simpletext {
|
|
142
|
+
white-space: nowrap;
|
|
143
|
+
}
|
|
127
144
|
}
|
|
128
145
|
}
|
|
129
146
|
}
|
|
@@ -240,12 +240,13 @@ export class PromptBox extends Dialog<DialogProps>
|
|
|
240
240
|
@class_ns( "x4" )
|
|
241
241
|
export class ProgressionBox extends Dialog {
|
|
242
242
|
|
|
243
|
-
#
|
|
243
|
+
#has_errors = false;
|
|
244
244
|
|
|
245
245
|
constructor( title: string ) {
|
|
246
246
|
super( {
|
|
247
247
|
modal: true,
|
|
248
248
|
title: null,
|
|
249
|
+
sizable: true,
|
|
249
250
|
movable: true,
|
|
250
251
|
form: new Form( {
|
|
251
252
|
content: [
|
|
@@ -255,26 +256,48 @@ export class ProgressionBox extends Dialog {
|
|
|
255
256
|
new VBox( { flex: 1, cls: "right", content: [
|
|
256
257
|
new SimpleText( { id: "title", text: title } ),
|
|
257
258
|
new Progress( { id:"prog", min: 0, max: 100, value: 0 } ),
|
|
258
|
-
new
|
|
259
|
+
new VBox( { id: "sub-text" } ),
|
|
259
260
|
]})
|
|
260
261
|
]
|
|
261
262
|
}),
|
|
262
263
|
]
|
|
263
264
|
}),
|
|
264
|
-
buttons: [ "ok.outline.default"
|
|
265
|
+
buttons: [ "ok.outline.default" ]
|
|
265
266
|
});
|
|
266
267
|
|
|
267
|
-
this
|
|
268
|
+
this.query("#btnbar").show( false );
|
|
269
|
+
|
|
270
|
+
this.on("btnclick", ( ) => this.show( false ) );
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
addText( text: string | UnsafeHtml, perc: number ) {
|
|
274
|
+
this.query<Label>( "#sub-text").appendContent( new SimpleText( { text } ) );
|
|
275
|
+
this.query<Progress>( "#prog").setValue( perc );
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
addError( text: string | UnsafeHtml, perc: number ) {
|
|
279
|
+
this.query<Label>( "#sub-text").appendContent( new SimpleText( { cls:"error", text } ) );
|
|
280
|
+
this.query<Progress>( "#prog").setValue( perc );
|
|
281
|
+
|
|
282
|
+
this.#has_errors = true;
|
|
268
283
|
}
|
|
269
284
|
|
|
270
285
|
setText( text: string | UnsafeHtml, perc: number ) {
|
|
271
|
-
this
|
|
272
|
-
this.query<Label>( "#sub-text").setText( unsafeHtml(this.#log.join("<br/>")) );
|
|
286
|
+
this.query<Label>( "#sub-text").setContent( new SimpleText( { text } ) );
|
|
273
287
|
this.query<Progress>( "#prog").setValue( perc );
|
|
274
288
|
}
|
|
275
289
|
|
|
276
|
-
|
|
277
|
-
this.#
|
|
278
|
-
this.query<Label>( "#sub-text").
|
|
290
|
+
clear( ) {
|
|
291
|
+
this.#has_errors = true;
|
|
292
|
+
this.query<Label>( "#sub-text").clearContent( );
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
done( ) {
|
|
296
|
+
if( this.#has_errors ) {
|
|
297
|
+
this.query("#btnbar").show( true );
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
this.setTimeout( "close", 5000, ( ) => { this.show(false);} );
|
|
301
|
+
}
|
|
279
302
|
}
|
|
280
303
|
}
|
|
@@ -26,7 +26,8 @@
|
|
|
26
26
|
cursor: ns-resize;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
&.
|
|
29
|
+
&.vsize,
|
|
30
|
+
&.hsize {
|
|
30
31
|
position: relative;
|
|
31
32
|
align-self: stretch;
|
|
32
33
|
min-width: 4px;
|
|
@@ -37,6 +38,10 @@
|
|
|
37
38
|
}
|
|
38
39
|
}
|
|
39
40
|
|
|
41
|
+
.hsize {
|
|
42
|
+
cursor: ew-resize;
|
|
43
|
+
}
|
|
44
|
+
|
|
40
45
|
&.top {
|
|
41
46
|
@include horz;
|
|
42
47
|
top: 0;
|
|
@@ -33,7 +33,7 @@ interface CSizerEvent extends ComponentEvents {
|
|
|
33
33
|
stop: ComponentEvent;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
type SizerType = "left" | "top" | "right" | "bottom" | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "
|
|
36
|
+
type SizerType = "left" | "top" | "right" | "bottom" | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "hsize" | "vsize";
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
39
|
*
|
|
@@ -57,7 +57,7 @@ export class CSizer extends Component<ComponentProps,CSizerEvent> {
|
|
|
57
57
|
this.setCapture( e.pointerId );
|
|
58
58
|
|
|
59
59
|
let targ = target;
|
|
60
|
-
if( !targ && type=='
|
|
60
|
+
if( !targ && (type=='hsize' || type=='vsize') ) {
|
|
61
61
|
targ = this.nextElement( );
|
|
62
62
|
}
|
|
63
63
|
|
|
@@ -66,14 +66,14 @@ export class CSizer extends Component<ComponentProps,CSizerEvent> {
|
|
|
66
66
|
this._delta = {x:0,y:0};
|
|
67
67
|
const rc = this._ref.getBoundingRect();
|
|
68
68
|
|
|
69
|
-
if( this._type=="
|
|
69
|
+
if( this._type=="hsize" || this._type.includes("left") ) {
|
|
70
70
|
this._delta.x = e.pageX-rc.left;
|
|
71
71
|
}
|
|
72
72
|
else {
|
|
73
73
|
this._delta.x = e.pageX-(rc.left+rc.width);
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
if( this._type.includes("top") ) {
|
|
76
|
+
if( this._type=="vsize" || this._type.includes("top") ) {
|
|
77
77
|
this._delta.y = e.pageY-rc.top;
|
|
78
78
|
}
|
|
79
79
|
else {
|
|
@@ -110,15 +110,22 @@ export class CSizer extends Component<ComponentProps,CSizerEvent> {
|
|
|
110
110
|
nr.height = (rc.top+rc.height)-pt.y;
|
|
111
111
|
horz = false;
|
|
112
112
|
}
|
|
113
|
+
else if( this._type=="vsize" ) {
|
|
114
|
+
nr.height = (rc.top+rc.height)-pt.y;
|
|
115
|
+
horz = false;
|
|
116
|
+
}
|
|
113
117
|
else if( this._type.includes("bottom") ) {
|
|
114
118
|
//nr.top = rc.top;
|
|
115
119
|
nr.height = (pt.y-rc.top);
|
|
116
120
|
horz = false;
|
|
117
121
|
}
|
|
118
|
-
else if( this._type
|
|
122
|
+
else if( this._type.includes("left") ) {
|
|
119
123
|
nr.left = pt.x;
|
|
120
124
|
nr.width = ((rc.left+rc.width)-pt.x);
|
|
121
125
|
}
|
|
126
|
+
else if( this._type=="hsize" ) {
|
|
127
|
+
nr.width = ((rc.left+rc.width)-pt.x);
|
|
128
|
+
}
|
|
122
129
|
else if( this._type.includes("right") ) {
|
|
123
130
|
nr.width = (pt.x-rc.left);
|
|
124
131
|
}
|
|
@@ -132,4 +139,18 @@ export class CSizer extends Component<ComponentProps,CSizerEvent> {
|
|
|
132
139
|
e.preventDefault( );
|
|
133
140
|
e.stopPropagation( );
|
|
134
141
|
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
@class_ns( "x4" )
|
|
145
|
+
export class HSizer extends CSizer {
|
|
146
|
+
constructor( ) {
|
|
147
|
+
super( "hsize" );
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
@class_ns( "x4" )
|
|
152
|
+
export class VSizer extends CSizer {
|
|
153
|
+
constructor( ) {
|
|
154
|
+
super( "vsize" );
|
|
155
|
+
}
|
|
135
156
|
}
|
package/src/core/core_data.ts
CHANGED
|
@@ -25,6 +25,7 @@ export type DataFieldValue = string | Date | number | boolean;
|
|
|
25
25
|
|
|
26
26
|
export type ChangeCallback = (type: string, id?: DataRecordID) => void;
|
|
27
27
|
export type CalcCallback = () => string;
|
|
28
|
+
export type SortCallback = ( v1: any, v2: any ) => number;
|
|
28
29
|
|
|
29
30
|
export type FieldType = 'string' | 'int' | 'float' | 'date' | 'bool' | 'array' | 'object' | 'any' | 'calc';
|
|
30
31
|
export type DataIndex = Uint32Array;
|
|
@@ -935,7 +936,8 @@ export class DataStore<T = any> extends EventSource<DataStoreEventMap> {
|
|
|
935
936
|
|
|
936
937
|
interface sort_info {
|
|
937
938
|
fidx: number,
|
|
938
|
-
asc: boolean
|
|
939
|
+
asc: boolean,
|
|
940
|
+
cb: SortCallback,
|
|
939
941
|
}
|
|
940
942
|
|
|
941
943
|
let bads = 0; // unknown fields
|
|
@@ -943,7 +945,7 @@ export class DataStore<T = any> extends EventSource<DataStoreEventMap> {
|
|
|
943
945
|
|
|
944
946
|
// if no fields are given, reset sort by id
|
|
945
947
|
if ( sort===null ) {
|
|
946
|
-
fidxs.push( { fidx: 0, asc: true } );
|
|
948
|
+
fidxs.push( { fidx: 0, asc: true, cb: null } );
|
|
947
949
|
}
|
|
948
950
|
else {
|
|
949
951
|
fidxs = sort.map( (si) => {
|
|
@@ -954,7 +956,7 @@ export class DataStore<T = any> extends EventSource<DataStoreEventMap> {
|
|
|
954
956
|
bads++;
|
|
955
957
|
}
|
|
956
958
|
|
|
957
|
-
return { fidx: fi, asc: si.ascending };
|
|
959
|
+
return { fidx: fi, asc: si.ascending, cb: si.callback };
|
|
958
960
|
});
|
|
959
961
|
}
|
|
960
962
|
|
|
@@ -969,11 +971,17 @@ export class DataStore<T = any> extends EventSource<DataStoreEventMap> {
|
|
|
969
971
|
if( fidxs.length==1 ) {
|
|
970
972
|
|
|
971
973
|
const field = fidxs[0].fidx;
|
|
974
|
+
const cb = fidxs[0].cb;
|
|
972
975
|
|
|
973
976
|
index.sort( ( ia, ib ) => {
|
|
974
977
|
|
|
975
978
|
let va = m.getRaw( field, this.getByIndex(ia) ) ?? '';
|
|
976
979
|
let vb = m.getRaw( field, this.getByIndex(ib) ) ?? '';
|
|
980
|
+
|
|
981
|
+
if( cb ) {
|
|
982
|
+
return cb( va, vb );
|
|
983
|
+
}
|
|
984
|
+
|
|
977
985
|
if (va > vb) { return 1; }
|
|
978
986
|
if (va < vb) { return -1; }
|
|
979
987
|
return 0;
|
|
@@ -987,13 +995,17 @@ export class DataStore<T = any> extends EventSource<DataStoreEventMap> {
|
|
|
987
995
|
else {
|
|
988
996
|
index.sort( ( ia, ib ) => {
|
|
989
997
|
|
|
990
|
-
for(
|
|
991
|
-
|
|
992
|
-
let
|
|
993
|
-
let mul = fidxs[fi].asc ? 1 : -1;
|
|
998
|
+
for( const fi of fidxs ) {
|
|
999
|
+
let fidx = fi.fidx;
|
|
1000
|
+
let mul = fi.asc ? 1 : -1;
|
|
994
1001
|
|
|
995
1002
|
let va = m.getRaw( fidx, this.getByIndex(ia) ) ?? '';
|
|
996
1003
|
let vb = m.getRaw( fidx, this.getByIndex(ib) ) ?? '';
|
|
1004
|
+
|
|
1005
|
+
if( fi.cb ) {
|
|
1006
|
+
return fi.cb( va, vb );
|
|
1007
|
+
}
|
|
1008
|
+
|
|
997
1009
|
if (va > vb) { return mul; }
|
|
998
1010
|
if (va < vb) { return -mul; }
|
|
999
1011
|
}
|
|
@@ -1096,6 +1108,7 @@ export interface SortProp {
|
|
|
1096
1108
|
field: string; //
|
|
1097
1109
|
ascending: boolean; //
|
|
1098
1110
|
numeric?: boolean; // numeric sort
|
|
1111
|
+
callback?: SortCallback;
|
|
1099
1112
|
}
|
|
1100
1113
|
|
|
1101
1114
|
|