@gisce/ooui 2.22.0 → 2.23.0-alpha.2
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/dist/Field.d.ts +7 -0
- package/dist/Field.d.ts.map +1 -1
- package/dist/Form.d.ts +5 -0
- package/dist/Form.d.ts.map +1 -1
- package/dist/Tree.d.ts +5 -0
- package/dist/Tree.d.ts.map +1 -1
- package/dist/Widget.d.ts.map +1 -1
- package/dist/helpers/attributeParser.d.ts +1 -0
- package/dist/helpers/attributeParser.d.ts.map +1 -1
- package/dist/helpers/nodeParser.d.ts.map +1 -1
- package/dist/ooui.es.js +428 -392
- package/dist/ooui.es.js.map +1 -1
- package/package.json +1 -1
- package/src/Field.ts +33 -0
- package/src/Form.ts +23 -1
- package/src/Tree.ts +13 -1
- package/src/Widget.ts +4 -25
- package/src/helpers/attributeParser.ts +16 -0
- package/src/helpers/nodeParser.ts +7 -1
- package/src/spec/Field.spec.ts +35 -0
- package/src/spec/Form.spec.ts +80 -0
- package/src/spec/Tree.spec.ts +19 -0
- package/src/spec/nodeParser.spec.ts +53 -0
package/package.json
CHANGED
package/src/Field.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Widget from "./Widget";
|
|
2
2
|
import { replaceEntities, isTrue } from "./helpers/attributeParser";
|
|
3
|
+
import { parseBoolAttribute } from "./helpers/nodeParser";
|
|
3
4
|
|
|
4
5
|
class Field extends Widget {
|
|
5
6
|
/**
|
|
@@ -105,6 +106,14 @@ class Field extends Widget {
|
|
|
105
106
|
this._sum = value;
|
|
106
107
|
}
|
|
107
108
|
|
|
109
|
+
get suffix(): string {
|
|
110
|
+
return this._parsedWidgetProps.suffix || "";
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
get prefix(): string {
|
|
114
|
+
return this._parsedWidgetProps.prefix || "";
|
|
115
|
+
}
|
|
116
|
+
|
|
108
117
|
/**
|
|
109
118
|
* Values and keys
|
|
110
119
|
*/
|
|
@@ -117,6 +126,27 @@ class Field extends Widget {
|
|
|
117
126
|
this._selectionValues = value;
|
|
118
127
|
}
|
|
119
128
|
|
|
129
|
+
_autoRefresh?: boolean = false;
|
|
130
|
+
get autoRefresh(): boolean {
|
|
131
|
+
return this._autoRefresh ?? false;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
set autoRefresh(value: boolean) {
|
|
135
|
+
this._autoRefresh = value;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
get readOnly(): boolean | undefined {
|
|
139
|
+
if (this.autoRefresh) {
|
|
140
|
+
return true;
|
|
141
|
+
} else {
|
|
142
|
+
return super.readOnly;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
set readOnly(value: boolean | undefined) {
|
|
147
|
+
super.readOnly = value;
|
|
148
|
+
}
|
|
149
|
+
|
|
120
150
|
constructor(props: any) {
|
|
121
151
|
super(props);
|
|
122
152
|
|
|
@@ -168,6 +198,9 @@ class Field extends Widget {
|
|
|
168
198
|
if (props.help_inline) {
|
|
169
199
|
this.tooltipInline = isTrue(props.help_inline);
|
|
170
200
|
}
|
|
201
|
+
if (props.autorefresh) {
|
|
202
|
+
this.autoRefresh = parseBoolAttribute(props.autorefresh);
|
|
203
|
+
}
|
|
171
204
|
}
|
|
172
205
|
}
|
|
173
206
|
|
package/src/Form.ts
CHANGED
|
@@ -3,7 +3,11 @@ import Container from "./Container";
|
|
|
3
3
|
import ContainerWidget from "./ContainerWidget";
|
|
4
4
|
import Widget from "./Widget";
|
|
5
5
|
import { ParsedNode } from "./helpers/nodeParser";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
evaluateAttributes,
|
|
8
|
+
replaceEntities,
|
|
9
|
+
parseWidgetProps,
|
|
10
|
+
} from "./helpers/attributeParser";
|
|
7
11
|
import { evaluateStates, evaluateButtonStates } from "./helpers/stateParser";
|
|
8
12
|
import { parseContext } from "./helpers/contextParser";
|
|
9
13
|
import { parseOnChange } from "./helpers/onChangeParser";
|
|
@@ -120,6 +124,14 @@ class Form {
|
|
|
120
124
|
this._invisibleFields = value;
|
|
121
125
|
}
|
|
122
126
|
|
|
127
|
+
/**
|
|
128
|
+
* List of autorefreshable fields
|
|
129
|
+
*/
|
|
130
|
+
_autorefreshableFields: string[] = [];
|
|
131
|
+
get autorefreshableFields(): string[] {
|
|
132
|
+
return this._autorefreshableFields;
|
|
133
|
+
}
|
|
134
|
+
|
|
123
135
|
/**
|
|
124
136
|
* Context for each field in the form
|
|
125
137
|
*/
|
|
@@ -166,6 +178,11 @@ class Form {
|
|
|
166
178
|
this._contextForFields[unknownWidget._id] = widget._context;
|
|
167
179
|
}
|
|
168
180
|
});
|
|
181
|
+
|
|
182
|
+
// Also we store all the autorefreshables fields in a list
|
|
183
|
+
this._autorefreshableFields = allWidgets
|
|
184
|
+
.filter((widget) => widget instanceof Field && widget.autoRefresh)
|
|
185
|
+
.map((field) => (field as Field)._id);
|
|
169
186
|
}
|
|
170
187
|
|
|
171
188
|
parseNode({
|
|
@@ -195,6 +212,11 @@ class Form {
|
|
|
195
212
|
);
|
|
196
213
|
}
|
|
197
214
|
widgetType = this._fields[name].type;
|
|
215
|
+
// Merge _fields[widget_props] with attributes[widget_props]
|
|
216
|
+
attributes.widget_props = {
|
|
217
|
+
...parseWidgetProps(attributes.widget_props),
|
|
218
|
+
...(this._fields[name].widget_props || {}),
|
|
219
|
+
};
|
|
198
220
|
}
|
|
199
221
|
tagAttributes = {
|
|
200
222
|
...this._fields[name],
|
package/src/Tree.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import WidgetFactory from "./WidgetFactory";
|
|
2
2
|
import Widget from "./Widget";
|
|
3
3
|
import { replaceEntities } from "./helpers/attributeParser";
|
|
4
|
-
import { ParsedNode } from "./helpers/nodeParser";
|
|
4
|
+
import { parseBoolAttribute, ParsedNode } from "./helpers/nodeParser";
|
|
5
5
|
import * as txml from "txml";
|
|
6
6
|
import { parseContext } from "./helpers/contextParser";
|
|
7
7
|
|
|
@@ -67,6 +67,14 @@ class Tree {
|
|
|
67
67
|
this._contextForFields = value;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
/**
|
|
71
|
+
* List of autorefreshable fields
|
|
72
|
+
*/
|
|
73
|
+
_autorefreshableFields: string[] = [];
|
|
74
|
+
get autorefreshableFields(): string[] {
|
|
75
|
+
return this._autorefreshableFields;
|
|
76
|
+
}
|
|
77
|
+
|
|
70
78
|
/**
|
|
71
79
|
* Is infinite
|
|
72
80
|
*/
|
|
@@ -145,6 +153,10 @@ class Tree {
|
|
|
145
153
|
const widget = widgetFactory.createWidget(widgetType, mergedAttrs);
|
|
146
154
|
this._columns.push(widget);
|
|
147
155
|
}
|
|
156
|
+
|
|
157
|
+
if (parseBoolAttribute(mergedAttrs.autorefresh)) {
|
|
158
|
+
this._autorefreshableFields.push(name);
|
|
159
|
+
}
|
|
148
160
|
}
|
|
149
161
|
});
|
|
150
162
|
}
|
package/src/Widget.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { replaceEntities } from "./helpers/attributeParser";
|
|
1
|
+
import { replaceEntities, parseWidgetProps } from "./helpers/attributeParser";
|
|
2
|
+
import { parseBoolAttribute } from "./helpers/nodeParser";
|
|
2
3
|
|
|
3
4
|
abstract class Widget {
|
|
4
5
|
/**
|
|
@@ -132,19 +133,7 @@ abstract class Widget {
|
|
|
132
133
|
this._colspan = +props.colspan;
|
|
133
134
|
}
|
|
134
135
|
if (props.readonly !== undefined) {
|
|
135
|
-
|
|
136
|
-
props.readonly === "1" ||
|
|
137
|
-
props.readonly === 1 ||
|
|
138
|
-
props.readonly === true
|
|
139
|
-
) {
|
|
140
|
-
this._readOnly = true;
|
|
141
|
-
} else if (
|
|
142
|
-
props.readonly === "0" ||
|
|
143
|
-
props.readonly === 0 ||
|
|
144
|
-
props.readonly === false
|
|
145
|
-
) {
|
|
146
|
-
this._readOnly = false;
|
|
147
|
-
}
|
|
136
|
+
this._readOnly = parseBoolAttribute(props.readonly);
|
|
148
137
|
}
|
|
149
138
|
if (props.invisible) {
|
|
150
139
|
if (
|
|
@@ -172,17 +161,7 @@ abstract class Widget {
|
|
|
172
161
|
this._fieldType = props.fieldsWidgetType;
|
|
173
162
|
}
|
|
174
163
|
if (props.widget_props) {
|
|
175
|
-
|
|
176
|
-
try {
|
|
177
|
-
this._parsedWidgetProps = JSON.parse(
|
|
178
|
-
props.widget_props.replace(/'/g, '"'),
|
|
179
|
-
);
|
|
180
|
-
} catch (err) {
|
|
181
|
-
console.error("Error parsing widget_props");
|
|
182
|
-
}
|
|
183
|
-
} else {
|
|
184
|
-
this._parsedWidgetProps = props.widget_props;
|
|
185
|
-
}
|
|
164
|
+
this._parsedWidgetProps = parseWidgetProps(props.widget_props);
|
|
186
165
|
}
|
|
187
166
|
if (props.key) {
|
|
188
167
|
this._key = props.key;
|
|
@@ -184,6 +184,22 @@ const parseAttributes = ({
|
|
|
184
184
|
return newAttributes;
|
|
185
185
|
};
|
|
186
186
|
|
|
187
|
+
export const parseWidgetProps = (widget_props: string | object): object => {
|
|
188
|
+
if (widget_props === undefined) {
|
|
189
|
+
return {};
|
|
190
|
+
}
|
|
191
|
+
if (typeof widget_props === "string") {
|
|
192
|
+
try {
|
|
193
|
+
return JSON.parse(widget_props.replace(/'/g, '"'));
|
|
194
|
+
} catch (err) {
|
|
195
|
+
console.error("Error parsing widget_props");
|
|
196
|
+
return {};
|
|
197
|
+
}
|
|
198
|
+
} else {
|
|
199
|
+
return widget_props;
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
|
|
187
203
|
export const parseJsonAttributes = ({
|
|
188
204
|
attrs,
|
|
189
205
|
values,
|
|
@@ -5,7 +5,13 @@ type ParsedNode = {
|
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
const parseBoolAttribute = (attr: any): boolean => {
|
|
8
|
-
if (
|
|
8
|
+
if (
|
|
9
|
+
attr === 1 ||
|
|
10
|
+
attr === "1" ||
|
|
11
|
+
attr === true ||
|
|
12
|
+
attr === "True" ||
|
|
13
|
+
attr === "true"
|
|
14
|
+
) {
|
|
9
15
|
return true;
|
|
10
16
|
} else {
|
|
11
17
|
return false;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import Field from "../Field";
|
|
3
|
+
|
|
4
|
+
describe("Field", () => {
|
|
5
|
+
describe("with the autoRefresh property", () => {
|
|
6
|
+
it("should be false as default", () => {
|
|
7
|
+
const props = {};
|
|
8
|
+
const field = new Field(props);
|
|
9
|
+
expect(field.autoRefresh).toBe(false);
|
|
10
|
+
});
|
|
11
|
+
it("should work with text", () => {
|
|
12
|
+
const props = {
|
|
13
|
+
autorefresh: "1",
|
|
14
|
+
};
|
|
15
|
+
const field = new Field(props);
|
|
16
|
+
expect(field.autoRefresh).toBe(true);
|
|
17
|
+
});
|
|
18
|
+
describe("if autorefresh is not a valid boold", () => {
|
|
19
|
+
it("should return false", () => {
|
|
20
|
+
const props = {
|
|
21
|
+
autorefresh: "abc",
|
|
22
|
+
};
|
|
23
|
+
const field = new Field(props);
|
|
24
|
+
expect(field.autoRefresh).toBe(false);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
it("should return true for readOnly if autoRefresh is set", () => {
|
|
28
|
+
const props = {
|
|
29
|
+
autorefresh: true,
|
|
30
|
+
};
|
|
31
|
+
const field = new Field(props);
|
|
32
|
+
expect(field.readOnly).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
});
|
package/src/spec/Form.spec.ts
CHANGED
|
@@ -6015,4 +6015,84 @@ describe("A Form", () => {
|
|
|
6015
6015
|
expect(field_char?.type).toBe("arrow_steps");
|
|
6016
6016
|
expect(field_char?.id).toBe("field_char");
|
|
6017
6017
|
});
|
|
6018
|
+
it("a field with autorefresh evaluated in attrs should be present in form autorefreshable fields property", () => {
|
|
6019
|
+
const fields = {
|
|
6020
|
+
field_char: {
|
|
6021
|
+
string: "Etapa",
|
|
6022
|
+
type: "char",
|
|
6023
|
+
},
|
|
6024
|
+
state: {
|
|
6025
|
+
readonly: true,
|
|
6026
|
+
required: true,
|
|
6027
|
+
selection: [
|
|
6028
|
+
["esborrany", "Borrador"],
|
|
6029
|
+
["validar", "Validar"],
|
|
6030
|
+
["pendent", "Pendiente"],
|
|
6031
|
+
["activa", "Activa"],
|
|
6032
|
+
["cancelada", "Cancelada"],
|
|
6033
|
+
["contracte", "Activación Contrato"],
|
|
6034
|
+
["novapolissa", "Creación nuevo contrato"],
|
|
6035
|
+
["modcontractual", "Modificación Contractual"],
|
|
6036
|
+
["impagament", "Impago"],
|
|
6037
|
+
["tall", "Corte"],
|
|
6038
|
+
["running", "En ejecución"],
|
|
6039
|
+
["baixa", "Baja"],
|
|
6040
|
+
["facturacio", "Facturación"],
|
|
6041
|
+
],
|
|
6042
|
+
string: "Estado",
|
|
6043
|
+
type: "selection",
|
|
6044
|
+
views: {},
|
|
6045
|
+
},
|
|
6046
|
+
};
|
|
6047
|
+
|
|
6048
|
+
const xmlViewForm = `<?xml version="1.0"?>
|
|
6049
|
+
<form string="Form1">
|
|
6050
|
+
<field name="field_char" widget="arrow_steps" colspan="4" nolabel="1" attrs="{'autorefresh':[('state', '=', 'running')]}" />
|
|
6051
|
+
</form>`;
|
|
6052
|
+
|
|
6053
|
+
const form = new Form(fields);
|
|
6054
|
+
form.parse(xmlViewForm, {
|
|
6055
|
+
values: {
|
|
6056
|
+
field_char: "test",
|
|
6057
|
+
state: "running",
|
|
6058
|
+
},
|
|
6059
|
+
});
|
|
6060
|
+
|
|
6061
|
+
const field_char = form.findById("field_char") as Field;
|
|
6062
|
+
expect(field_char).toBeDefined();
|
|
6063
|
+
expect(field_char?.autoRefresh).toBeTruthy();
|
|
6064
|
+
expect(field_char?.readOnly).toBeTruthy();
|
|
6065
|
+
expect(form.autorefreshableFields.length).toBe(1);
|
|
6066
|
+
expect(form.autorefreshableFields[0]).toBe("field_char");
|
|
6067
|
+
});
|
|
6068
|
+
describe("If the field has widget_props", () => {
|
|
6069
|
+
it("should merge widget_props from fields definition and xml", () => {
|
|
6070
|
+
const fields = {
|
|
6071
|
+
field_integer: {
|
|
6072
|
+
readonly: 1,
|
|
6073
|
+
string: "Power",
|
|
6074
|
+
type: "integer",
|
|
6075
|
+
widget_props: {
|
|
6076
|
+
suffix: "kW",
|
|
6077
|
+
},
|
|
6078
|
+
},
|
|
6079
|
+
};
|
|
6080
|
+
|
|
6081
|
+
const xmlViewForm = `<?xml version="1.0"?>
|
|
6082
|
+
<form string="Form1">
|
|
6083
|
+
<field name="field_integer" widget_props="{'prefix': 'Wow'}" />
|
|
6084
|
+
</form>`;
|
|
6085
|
+
|
|
6086
|
+
const form = new Form(fields);
|
|
6087
|
+
form.parse(xmlViewForm, {
|
|
6088
|
+
values: {
|
|
6089
|
+
field_integer: 10,
|
|
6090
|
+
},
|
|
6091
|
+
});
|
|
6092
|
+
const field = form.findById("field_integer") as Field;
|
|
6093
|
+
expect(field).toBeDefined();
|
|
6094
|
+
expect(field.suffix).toBe("kW");
|
|
6095
|
+
expect(field.prefix).toBe("Wow");
|
|
6096
|
+
});
|
|
6097
|
+
});
|
|
6018
6098
|
});
|
package/src/spec/Tree.spec.ts
CHANGED
|
@@ -377,4 +377,23 @@ describe("A Tree", () => {
|
|
|
377
377
|
const nameWidget = tree.findById("name") as Char;
|
|
378
378
|
expect(nameWidget.isFunction).toBeTruthy();
|
|
379
379
|
});
|
|
380
|
+
it("Should parse autorefreshable fields", () => {
|
|
381
|
+
const tree = new Tree({
|
|
382
|
+
name: {
|
|
383
|
+
required: true,
|
|
384
|
+
select: true,
|
|
385
|
+
size: 128,
|
|
386
|
+
string: "Potència contractada (kW)",
|
|
387
|
+
type: "char",
|
|
388
|
+
views: {},
|
|
389
|
+
},
|
|
390
|
+
});
|
|
391
|
+
tree.parse(
|
|
392
|
+
`<tree string="Partners" colors="red:type=='updated'"><field name="name" sum="Potència contractada (kW)" autorefresh="1"/></tree>`,
|
|
393
|
+
);
|
|
394
|
+
|
|
395
|
+
const nameWidget = tree.findById("name") as Char;
|
|
396
|
+
expect(nameWidget.autoRefresh).toBeTruthy();
|
|
397
|
+
expect(tree._autorefreshableFields.length).toBe(1);
|
|
398
|
+
});
|
|
380
399
|
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { parseBoolAttribute } from "../helpers/nodeParser";
|
|
3
|
+
|
|
4
|
+
describe("parseBoolAttribute", () => {
|
|
5
|
+
it("returns true for numeric 1", () => {
|
|
6
|
+
expect(parseBoolAttribute(1)).toBe(true);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it('returns true for string "1"', () => {
|
|
10
|
+
expect(parseBoolAttribute("1")).toBe(true);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("returns true for boolean true", () => {
|
|
14
|
+
expect(parseBoolAttribute(true)).toBe(true);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('returns true for string "True"', () => {
|
|
18
|
+
expect(parseBoolAttribute("True")).toBe(true);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('returns true for string "true"', () => {
|
|
22
|
+
expect(parseBoolAttribute("true")).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("returns false for numeric 0", () => {
|
|
26
|
+
expect(parseBoolAttribute(0)).toBe(false);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('returns false for string "0"', () => {
|
|
30
|
+
expect(parseBoolAttribute("0")).toBe(false);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("returns false for boolean false", () => {
|
|
34
|
+
expect(parseBoolAttribute(false)).toBe(false);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('returns false for string "False"', () => {
|
|
38
|
+
expect(parseBoolAttribute("False")).toBe(false);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("returns false for null", () => {
|
|
42
|
+
expect(parseBoolAttribute(null)).toBe(false);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("returns false for undefined", () => {
|
|
46
|
+
expect(parseBoolAttribute(undefined)).toBe(false);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("returns false for non-boolean strings", () => {
|
|
50
|
+
expect(parseBoolAttribute("yes")).toBe(false);
|
|
51
|
+
expect(parseBoolAttribute("no")).toBe(false);
|
|
52
|
+
});
|
|
53
|
+
});
|