Skip to content

Commit

Permalink
feat(field): add a new property autorefresh (#136)
Browse files Browse the repository at this point in the history
  • Loading branch information
ecarreras authored Dec 12, 2024
1 parent d53e07f commit e3cd82c
Show file tree
Hide file tree
Showing 9 changed files with 217 additions and 15 deletions.
25 changes: 25 additions & 0 deletions src/Field.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Widget from "./Widget";
import { replaceEntities, isTrue } from "./helpers/attributeParser";
import { parseBoolAttribute } from "./helpers/nodeParser";

class Field extends Widget {
/**
Expand Down Expand Up @@ -125,6 +126,27 @@ class Field extends Widget {
this._selectionValues = value;
}

_autoRefresh?: boolean = false;
get autoRefresh(): boolean {
return this._autoRefresh ?? false;
}

set autoRefresh(value: boolean) {
this._autoRefresh = value;
}

get readOnly(): boolean | undefined {
if (this.autoRefresh) {
return true;
} else {
return super.readOnly;
}
}

set readOnly(value: boolean | undefined) {
super.readOnly = value;
}

constructor(props: any) {
super(props);

Expand Down Expand Up @@ -176,6 +198,9 @@ class Field extends Widget {
if (props.help_inline) {
this.tooltipInline = isTrue(props.help_inline);
}
if (props.autorefresh) {
this.autoRefresh = parseBoolAttribute(props.autorefresh);
}
}
}

Expand Down
13 changes: 13 additions & 0 deletions src/Form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,14 @@ class Form {
this._invisibleFields = value;
}

/**
* List of autorefreshable fields
*/
_autorefreshableFields: string[] = [];
get autorefreshableFields(): string[] {
return this._autorefreshableFields;
}

/**
* Context for each field in the form
*/
Expand Down Expand Up @@ -170,6 +178,11 @@ class Form {
this._contextForFields[unknownWidget._id] = widget._context;
}
});

// Also we store all the autorefreshables fields in a list
this._autorefreshableFields = allWidgets
.filter((widget) => widget instanceof Field && widget.autoRefresh)
.map((field) => (field as Field)._id);
}

parseNode({
Expand Down
14 changes: 13 additions & 1 deletion src/Tree.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import WidgetFactory from "./WidgetFactory";
import Widget from "./Widget";
import { replaceEntities } from "./helpers/attributeParser";
import { ParsedNode } from "./helpers/nodeParser";
import { parseBoolAttribute, ParsedNode } from "./helpers/nodeParser";
import * as txml from "txml";
import { parseContext } from "./helpers/contextParser";

Expand Down Expand Up @@ -67,6 +67,14 @@ class Tree {
this._contextForFields = value;
}

/**
* List of autorefreshable fields
*/
_autorefreshableFields: string[] = [];
get autorefreshableFields(): string[] {
return this._autorefreshableFields;
}

/**
* Is infinite
*/
Expand Down Expand Up @@ -145,6 +153,10 @@ class Tree {
const widget = widgetFactory.createWidget(widgetType, mergedAttrs);
this._columns.push(widget);
}

if (parseBoolAttribute(mergedAttrs.autorefresh)) {
this._autorefreshableFields.push(name);
}
}
});
}
Expand Down
15 changes: 2 additions & 13 deletions src/Widget.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { replaceEntities, parseWidgetProps } from "./helpers/attributeParser";
import { parseBoolAttribute } from "./helpers/nodeParser";

abstract class Widget {
/**
Expand Down Expand Up @@ -132,19 +133,7 @@ abstract class Widget {
this._colspan = +props.colspan;
}
if (props.readonly !== undefined) {
if (
props.readonly === "1" ||
props.readonly === 1 ||
props.readonly === true
) {
this._readOnly = true;
} else if (
props.readonly === "0" ||
props.readonly === 0 ||
props.readonly === false
) {
this._readOnly = false;
}
this._readOnly = parseBoolAttribute(props.readonly);
}
if (props.invisible) {
if (
Expand Down
8 changes: 7 additions & 1 deletion src/helpers/nodeParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ type ParsedNode = {
};

const parseBoolAttribute = (attr: any): boolean => {
if (attr === 1 || attr === "1" || attr === true || attr === "True") {
if (
attr === 1 ||
attr === "1" ||
attr === true ||
attr === "True" ||
attr === "true"
) {
return true;
} else {
return false;
Expand Down
35 changes: 35 additions & 0 deletions src/spec/Field.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { describe, it, expect } from "vitest";
import Field from "../Field";

describe("Field", () => {
describe("with the autoRefresh property", () => {
it("should be false as default", () => {
const props = {};
const field = new Field(props);
expect(field.autoRefresh).toBe(false);
});
it("should work with text", () => {
const props = {
autorefresh: "1",
};
const field = new Field(props);
expect(field.autoRefresh).toBe(true);
});
describe("if autorefresh is not a valid boold", () => {
it("should return false", () => {
const props = {
autorefresh: "abc",
};
const field = new Field(props);
expect(field.autoRefresh).toBe(false);
});
});
it("should return true for readOnly if autoRefresh is set", () => {
const props = {
autorefresh: true,
};
const field = new Field(props);
expect(field.readOnly).toBe(true);
});
});
});
50 changes: 50 additions & 0 deletions src/spec/Form.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6015,6 +6015,56 @@ describe("A Form", () => {
expect(field_char?.type).toBe("arrow_steps");
expect(field_char?.id).toBe("field_char");
});
it("a field with autorefresh evaluated in attrs should be present in form autorefreshable fields property", () => {
const fields = {
field_char: {
string: "Etapa",
type: "char",
},
state: {
readonly: true,
required: true,
selection: [
["esborrany", "Borrador"],
["validar", "Validar"],
["pendent", "Pendiente"],
["activa", "Activa"],
["cancelada", "Cancelada"],
["contracte", "Activación Contrato"],
["novapolissa", "Creación nuevo contrato"],
["modcontractual", "Modificación Contractual"],
["impagament", "Impago"],
["tall", "Corte"],
["running", "En ejecución"],
["baixa", "Baja"],
["facturacio", "Facturación"],
],
string: "Estado",
type: "selection",
views: {},
},
};

const xmlViewForm = `<?xml version="1.0"?>
<form string="Form1">
<field name="field_char" widget="arrow_steps" colspan="4" nolabel="1" attrs="{'autorefresh':[('state', '=', 'running')]}" />
</form>`;

const form = new Form(fields);
form.parse(xmlViewForm, {
values: {
field_char: "test",
state: "running",
},
});

const field_char = form.findById("field_char") as Field;
expect(field_char).toBeDefined();
expect(field_char?.autoRefresh).toBeTruthy();
expect(field_char?.readOnly).toBeTruthy();
expect(form.autorefreshableFields.length).toBe(1);
expect(form.autorefreshableFields[0]).toBe("field_char");
});
describe("If the field has widget_props", () => {
it("should merge widget_props from fields definition and xml", () => {
const fields = {
Expand Down
19 changes: 19 additions & 0 deletions src/spec/Tree.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -377,4 +377,23 @@ describe("A Tree", () => {
const nameWidget = tree.findById("name") as Char;
expect(nameWidget.isFunction).toBeTruthy();
});
it("Should parse autorefreshable fields", () => {
const tree = new Tree({
name: {
required: true,
select: true,
size: 128,
string: "Pot&#232;ncia contractada (kW)",
type: "char",
views: {},
},
});
tree.parse(
`<tree string="Partners" colors="red:type=='updated'"><field name="name" sum="Pot&#232;ncia contractada (kW)" autorefresh="1"/></tree>`,
);

const nameWidget = tree.findById("name") as Char;
expect(nameWidget.autoRefresh).toBeTruthy();
expect(tree._autorefreshableFields.length).toBe(1);
});
});
53 changes: 53 additions & 0 deletions src/spec/nodeParser.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { describe, it, expect } from "vitest";
import { parseBoolAttribute } from "../helpers/nodeParser";

describe("parseBoolAttribute", () => {
it("returns true for numeric 1", () => {
expect(parseBoolAttribute(1)).toBe(true);
});

it('returns true for string "1"', () => {
expect(parseBoolAttribute("1")).toBe(true);
});

it("returns true for boolean true", () => {
expect(parseBoolAttribute(true)).toBe(true);
});

it('returns true for string "True"', () => {
expect(parseBoolAttribute("True")).toBe(true);
});

it('returns true for string "true"', () => {
expect(parseBoolAttribute("true")).toBe(true);
});

it("returns false for numeric 0", () => {
expect(parseBoolAttribute(0)).toBe(false);
});

it('returns false for string "0"', () => {
expect(parseBoolAttribute("0")).toBe(false);
});

it("returns false for boolean false", () => {
expect(parseBoolAttribute(false)).toBe(false);
});

it('returns false for string "False"', () => {
expect(parseBoolAttribute("False")).toBe(false);
});

it("returns false for null", () => {
expect(parseBoolAttribute(null)).toBe(false);
});

it("returns false for undefined", () => {
expect(parseBoolAttribute(undefined)).toBe(false);
});

it("returns false for non-boolean strings", () => {
expect(parseBoolAttribute("yes")).toBe(false);
expect(parseBoolAttribute("no")).toBe(false);
});
});

0 comments on commit e3cd82c

Please sign in to comment.