@quenk/frontend 0.20.1 → 0.20.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.
Files changed (44) hide show
  1. package/lib/app/display.d.ts +17 -10
  2. package/lib/app/display.js +22 -13
  3. package/lib/app/display.js.map +1 -1
  4. package/lib/app/index.js.map +1 -1
  5. package/lib/app/model/http.d.ts +36 -12
  6. package/lib/app/model/http.js +69 -64
  7. package/lib/app/model/http.js.map +1 -1
  8. package/lib/app/model/index.d.ts +6 -6
  9. package/lib/app/router/hash.d.ts +8 -9
  10. package/lib/app/router/hash.js +17 -24
  11. package/lib/app/router/hash.js.map +1 -1
  12. package/lib/app/router/index.d.ts +4 -5
  13. package/lib/app/scene/dialog/alert.js.map +1 -1
  14. package/lib/app/scene/dialog/confirm.d.ts +1 -1
  15. package/lib/app/scene/dialog/confirm.js +2 -2
  16. package/lib/app/scene/dialog/confirm.js.map +1 -1
  17. package/lib/app/scene/dialog/index.d.ts +2 -2
  18. package/lib/app/scene/dialog/index.js +6 -6
  19. package/lib/app/scene/dialog/index.js.map +1 -1
  20. package/lib/app/scene/director.d.ts +4 -4
  21. package/lib/app/scene/director.js +7 -11
  22. package/lib/app/scene/director.js.map +1 -1
  23. package/lib/app/scene/form/index.d.ts +183 -0
  24. package/lib/app/scene/form/index.js +142 -0
  25. package/lib/app/scene/form/index.js.map +1 -0
  26. package/lib/app/scene/form/model.d.ts +44 -0
  27. package/lib/app/scene/form/model.js +47 -0
  28. package/lib/app/scene/form/model.js.map +1 -0
  29. package/lib/app/scene/form/validator/index.d.ts +70 -0
  30. package/lib/app/scene/form/validator/index.js +31 -0
  31. package/lib/app/scene/form/validator/index.js.map +1 -0
  32. package/lib/app/scene/form/validator/strategy.d.ts +94 -0
  33. package/lib/app/scene/form/validator/strategy.js +85 -0
  34. package/lib/app/scene/form/validator/strategy.js.map +1 -0
  35. package/lib/app/scene/index.d.ts +2 -2
  36. package/lib/app/scene/index.js +5 -5
  37. package/lib/app/scene/index.js.map +1 -1
  38. package/lib/app/scene/page.d.ts +56 -0
  39. package/lib/app/scene/page.js +83 -0
  40. package/lib/app/scene/page.js.map +1 -0
  41. package/lib/app/search/filters.d.ts +2 -2
  42. package/lib/app/search/filters.js +19 -25
  43. package/lib/app/search/filters.js.map +1 -1
  44. package/package.json +1 -1
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AppFormScene = exports.FormState = exports.Save = exports.Abort = void 0;
4
+ const record_1 = require("@quenk/noni/lib/data/record");
5
+ const array_1 = require("@quenk/noni/lib/data/array");
6
+ const type_1 = require("@quenk/noni/lib/data/type");
7
+ const case_1 = require("@quenk/noni/lib/control/match/case");
8
+ const either_1 = require("@quenk/noni/lib/data/either");
9
+ const __1 = require("../");
10
+ /**
11
+ * Abort causes a FormScene to cease operations and return control to the
12
+ * actor that owns it.
13
+ */
14
+ class Abort {
15
+ }
16
+ exports.Abort = Abort;
17
+ /**
18
+ * Save causes a FormScene to trigger the "save" process for values collected.
19
+ */
20
+ class Save {
21
+ }
22
+ exports.Save = Save;
23
+ /**
24
+ * FormState indicates the state of the form when its lifecycle comes to an end.
25
+ *
26
+ * This message is used to indicate the form has either been saved or aborted
27
+ * and contains additional details of the form data up to that point.
28
+ */
29
+ class FormState {
30
+ /**
31
+ * @param form - The actor address of the form.
32
+ * @param ok - Indicates whether the form was saved (true) or aborted
33
+ * (false).
34
+ * @param data - The form data.
35
+ * @param result - The result received from saving the form.
36
+ */
37
+ constructor(form, ok, data = {}, result) {
38
+ this.form = form;
39
+ this.ok = ok;
40
+ this.data = data;
41
+ this.result = result;
42
+ }
43
+ }
44
+ exports.FormState = FormState;
45
+ /**
46
+ * AppFormScene provides an abstract implementation of the FormScene interface.
47
+ *
48
+ * Child classes provide a save() implementation to provide the logic of saving
49
+ * data. This actor is configured to process [[FormSceneMessage]]s including
50
+ * anything that looks like a InputEvent which will be passed to the set()
51
+ * method.
52
+ *
53
+ * Alternatively, values can be set directly via set() bypassing the actor
54
+ * system.
55
+ *
56
+ * @param system - The potoo System this actor belongs to.
57
+ * @param display - The address of the display to send the form's view to.
58
+ * @param owner - The address of the actor that will receive life cycle
59
+ * messages.
60
+ * @param value - Value of the AppFormScene tracked by the APIs of this
61
+ * class. This should not be modified outside of this actor.
62
+ */
63
+ class AppFormScene extends __1.AppScene {
64
+ constructor(runtime, owner, display, value = {}) {
65
+ super(runtime);
66
+ this.runtime = runtime;
67
+ this.owner = owner;
68
+ this.display = display;
69
+ this.value = value;
70
+ /**
71
+ * fieldsModified tracks the names of those fields whose values have been
72
+ * modified via this class's APIs.
73
+ */
74
+ this.fieldsModifed = [];
75
+ this.errors = {};
76
+ }
77
+ selectors() {
78
+ return [
79
+ new case_1.TypeCase(Abort, () => {
80
+ this.abort();
81
+ }),
82
+ new case_1.TypeCase(Save, () => {
83
+ this.save();
84
+ }),
85
+ new case_1.TypeCase({ name: String, value: type_1.Any }, e => {
86
+ this.set(e.name, e.value);
87
+ })
88
+ ];
89
+ }
90
+ set(name, value) {
91
+ if (!(0, array_1.contains)(this.fieldsModifed, name))
92
+ this.fieldsModifed.push(name);
93
+ this.value[name] = value;
94
+ return this;
95
+ }
96
+ getValues() {
97
+ return (0, record_1.clone)(this.value);
98
+ }
99
+ getModifiedValues() {
100
+ return ((0, record_1.filter)(this.value, (_, k) => (0, array_1.contains)(this.fieldsModifed, k)));
101
+ }
102
+ hasErrors() {
103
+ return !(0, record_1.empty)(this.errors);
104
+ }
105
+ /**
106
+ * abort by default invokes the callback and exits.
107
+ *
108
+ * The message is also sent to the display which should result in the view
109
+ * being removed.
110
+ */
111
+ async abort() {
112
+ await this.tell(this.owner, new FormState(this.self, false, this.getValues()));
113
+ await this.exit();
114
+ }
115
+ /**
116
+ * doSave executes the form saving logic.
117
+ */
118
+ async doSave() {
119
+ return either_1.Either.right('');
120
+ }
121
+ /**
122
+ * save executes the form saving operation and takes care of invoking the
123
+ * callback.
124
+ *
125
+ * Execution takes place by submitting a future to the form's actor thread.
126
+ * The life cycle message is also sent to the display which should trigger
127
+ * the removal of the view. Note: instead of overriding this method,
128
+ * override execute instead unless you want to change its behaviour.
129
+ */
130
+ async save() {
131
+ this.errors = {};
132
+ let eresult = await this.doSave();
133
+ if (eresult.isRight()) {
134
+ // Leave it to the child class to handle error cases.
135
+ let result = eresult.takeRight();
136
+ await this.tell(this.owner, new FormState(this.self, true, this.getValues(), result));
137
+ await this.exit();
138
+ }
139
+ }
140
+ }
141
+ exports.AppFormScene = AppFormScene;
142
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/app/scene/form/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ import { Value } from '@quenk/noni/lib/data/jsonx';
2
+ import { Object } from '@quenk/noni/lib/data/jsonx';
3
+ import { Except } from '@quenk/noni/lib/control/except';
4
+ import { Address } from '@quenk/potoo/lib/actor/address';
5
+ import { Runtime } from '@quenk/potoo/lib/actor/system/vm/runtime';
6
+ import { Event } from '@quenk/wml-widgets/lib/control';
7
+ import { Id, Model } from '../../model';
8
+ import { AppFormScene } from '.';
9
+ /**
10
+ * WriteMode hints what method to use to save the data.
11
+ */
12
+ export type WriteMode = string;
13
+ export declare const WRITE_MODE_CREATE = "create";
14
+ export declare const WRITE_MODE_UPDATE = "update";
15
+ /**
16
+ * ModelForm saves data using a Model.
17
+ */
18
+ export declare abstract class ModelFormScene<T extends Object> extends AppFormScene<T> {
19
+ runtime: Runtime;
20
+ owner: Address;
21
+ display: Address;
22
+ value: Partial<T>;
23
+ mode: WriteMode;
24
+ constructor(runtime: Runtime, owner: Address, display: Address, value?: Partial<T>, mode?: WriteMode);
25
+ static WRITE_MODE_CREATE: string;
26
+ static WRTIE_MODE_UPDATE: string;
27
+ /**
28
+ * model to use for saving data.
29
+ */
30
+ abstract model: Model<T>;
31
+ /**
32
+ * id assumes the id is the "id" property on the value.
33
+ */
34
+ get id(): Id;
35
+ /**
36
+ * onChange handler can be used to collect values.
37
+ */
38
+ onChange: (e: Event<Value>) => Promise<void>;
39
+ /**
40
+ * doSave either a create or update depending on the specified write
41
+ * mode.
42
+ */
43
+ doSave(): Promise<Except<Value>>;
44
+ }
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ModelFormScene = exports.WRITE_MODE_UPDATE = exports.WRITE_MODE_CREATE = void 0;
4
+ const either_1 = require("@quenk/noni/lib/data/either");
5
+ const _1 = require(".");
6
+ exports.WRITE_MODE_CREATE = 'create';
7
+ exports.WRITE_MODE_UPDATE = 'update';
8
+ /**
9
+ * ModelForm saves data using a Model.
10
+ */
11
+ class ModelFormScene extends _1.AppFormScene {
12
+ constructor(runtime, owner, display, value = {}, mode = ModelFormScene.WRITE_MODE_CREATE) {
13
+ super(runtime, owner, display, value);
14
+ this.runtime = runtime;
15
+ this.owner = owner;
16
+ this.display = display;
17
+ this.value = value;
18
+ this.mode = mode;
19
+ /**
20
+ * onChange handler can be used to collect values.
21
+ */
22
+ this.onChange = async (e) => this.tell(this.self, e);
23
+ }
24
+ /**
25
+ * id assumes the id is the "id" property on the value.
26
+ */
27
+ get id() {
28
+ return this.value.id;
29
+ }
30
+ /**
31
+ * doSave either a create or update depending on the specified write
32
+ * mode.
33
+ */
34
+ async doSave() {
35
+ if (this.mode === ModelFormScene.WRITE_MODE_CREATE) {
36
+ return this.model.create(this.getValues());
37
+ }
38
+ else {
39
+ await this.model.update(this.id, this.getModifiedValues());
40
+ return either_1.Either.right(this.id);
41
+ }
42
+ }
43
+ }
44
+ exports.ModelFormScene = ModelFormScene;
45
+ ModelFormScene.WRITE_MODE_CREATE = exports.WRITE_MODE_CREATE;
46
+ ModelFormScene.WRTIE_MODE_UPDATE = exports.WRITE_MODE_UPDATE;
47
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../../../src/app/scene/form/model.ts"],"names":[],"mappings":";;;AAGA,wDAAqD;AAQrD,wBAAiC;AAOpB,QAAA,iBAAiB,GAAG,QAAQ,CAAC;AAC7B,QAAA,iBAAiB,GAAG,QAAQ,CAAC;AAE1C;;GAEG;AACH,MAAsB,cAAiC,SAAQ,eAAe;IAC1E,YACW,OAAgB,EAChB,KAAc,EACd,OAAgB,EAChB,QAAoB,EAAE,EACtB,OAAkB,cAAc,CAAC,iBAAiB;QAEzD,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;QAN/B,YAAO,GAAP,OAAO,CAAS;QAChB,UAAK,GAAL,KAAK,CAAS;QACd,YAAO,GAAP,OAAO,CAAS;QAChB,UAAK,GAAL,KAAK,CAAiB;QACtB,SAAI,GAAJ,IAAI,CAA8C;QAqB7D;;WAEG;QACH,aAAQ,GAAG,KAAK,EAAE,CAAe,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IArB9D,CAAC;IAWD;;OAEG;IACH,IAAI,EAAE;QACF,OAAW,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;IAC7B,CAAC;IAOD;;;OAGG;IACH,KAAK,CAAC,MAAM;QACR,IAAI,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,iBAAiB,EAAE,CAAC;YACjD,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;QAC/C,CAAC;aAAM,CAAC;YACJ,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC;YAC3D,OAAO,eAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjC,CAAC;IACL,CAAC;;AA3CL,wCA4CC;AAjCU,gCAAiB,GAAG,yBAAiB,AAApB,CAAqB;AAEtC,gCAAiB,GAAG,yBAAiB,AAApB,CAAqB"}
@@ -0,0 +1,70 @@
1
+ import { Object } from '@quenk/noni/lib/data/jsonx';
2
+ import { Any } from '@quenk/noni/lib/data/type';
3
+ import { FieldName, FieldValue, FieldError, FormScene, AppFormScene } from '../';
4
+ import { ValidationStrategy } from './strategy';
5
+ import { TypeCase } from '@quenk/noni/lib/control/match/case';
6
+ /**
7
+ * ValidatorFormScene is the interface implemented by actors serving as the
8
+ * "controller" for HTML form views with validation.
9
+ *
10
+ * ValidatorFormScene differs from a regular [[FormScene]] by including client
11
+ * side validation in its design. As values are collected from the user, they
12
+ * can be validated and the feedback state of the form updated before being set.
13
+ *
14
+ * This allows for a more dynamic user experience when desirable.
15
+ */
16
+ export interface ValidatorFormScene<T extends Object> extends FormScene<T> {
17
+ /**
18
+ * strategy used for validation.
19
+ *
20
+ * This determines how data is validated and the callbacks to apply.
21
+ */
22
+ strategy: ValidationStrategy;
23
+ }
24
+ /**
25
+ * FieldStateListener indicates an ValidatorFormScene has methods for reacting
26
+ * to the result of a single field's validation.
27
+ *
28
+ * Use to implement visual feedback to the user.
29
+ */
30
+ export interface FieldStateListener<T extends Object> extends ValidatorFormScene<T> {
31
+ /**
32
+ * onFieldInvalid is applied when a field becomes invalid.
33
+ */
34
+ onFieldInvalid(name: FieldName, value: FieldValue, error: FieldError): void;
35
+ /**
36
+ * onFieldValid is applied when a field becomes valid.
37
+ */
38
+ onFieldValid(name: FieldName, value: FieldValue): void;
39
+ }
40
+ /**
41
+ * FormStateListener indicates an ValidatorFormScene has methods for reacting to
42
+ * the result of the entire form's validation.
43
+ *
44
+ * Use to provide the user with visual feedback such as enabling the save button.
45
+ */
46
+ export interface FormStateListener<T extends Object> extends FieldStateListener<T> {
47
+ /**
48
+ * onFormInvalid is applied when the entire form becomes invalid.
49
+ */
50
+ onFormInvalid(): void;
51
+ /**
52
+ * onFormValid is applied when the entire form becomes valid.
53
+ */
54
+ onFormValid(): void;
55
+ }
56
+ /**
57
+ * AppValidatorFormScene is an abstract extension to the BaseFormScene
58
+ * class to add validation and feedback features.
59
+ */
60
+ export declare abstract class AppValidatorFormScene<T extends Object> extends AppFormScene<T> implements FormStateListener<T> {
61
+ strategy: ValidationStrategy;
62
+ selectors(): (TypeCase<typeof import("../").Abort, void> | TypeCase<{
63
+ name: StringConstructor;
64
+ value: typeof Any;
65
+ }, void>)[];
66
+ onFieldInvalid(): void;
67
+ onFieldValid(): void;
68
+ onFormInvalid(): void;
69
+ onFormValid(): void;
70
+ }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AppValidatorFormScene = void 0;
4
+ const type_1 = require("@quenk/noni/lib/data/type");
5
+ const __1 = require("../");
6
+ const strategy_1 = require("./strategy");
7
+ const case_1 = require("@quenk/noni/lib/control/match/case");
8
+ /**
9
+ * AppValidatorFormScene is an abstract extension to the BaseFormScene
10
+ * class to add validation and feedback features.
11
+ */
12
+ class AppValidatorFormScene extends __1.AppFormScene {
13
+ constructor() {
14
+ super(...arguments);
15
+ this.strategy = new strategy_1.NoStrategy(this);
16
+ }
17
+ selectors() {
18
+ return [
19
+ new case_1.TypeCase({ name: String, value: type_1.Any }, e => {
20
+ return this.strategy.validate(e);
21
+ }),
22
+ ...super.selectors()
23
+ ];
24
+ }
25
+ onFieldInvalid() { }
26
+ onFieldValid() { }
27
+ onFormInvalid() { }
28
+ onFormValid() { }
29
+ }
30
+ exports.AppValidatorFormScene = AppValidatorFormScene;
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/app/scene/form/validator/index.ts"],"names":[],"mappings":";;;AACA,oDAAgD;AAEhD,2BAMa;AACb,yCAA4D;AAE5D,6DAA8D;AA2D9D;;;GAGG;AACH,MAAsB,qBAClB,SAAQ,gBAAe;IAD3B;;QAII,aAAQ,GAAuB,IAAI,qBAAU,CAAC,IAAI,CAAC,CAAC;IAmBxD,CAAC;IAjBG,SAAS;QACL,OAAO;YACH,IAAI,eAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAG,EAAE,EAAE,CAAC,CAAC,EAAE;gBAC3C,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAa,CAAC,CAAC,CAAC;YACjD,CAAC,CAAC;YAEF,GAAG,KAAK,CAAC,SAAS,EAAE;SACvB,CAAC;IACN,CAAC;IAED,cAAc,KAAI,CAAC;IAEnB,YAAY,KAAI,CAAC;IAEjB,aAAa,KAAI,CAAC;IAElB,WAAW,KAAI,CAAC;CACnB;AAvBD,sDAuBC"}
@@ -0,0 +1,94 @@
1
+ import { Either } from '@quenk/noni/lib/data/either';
2
+ import { Object } from '@quenk/noni/lib/data/jsonx';
3
+ import { FieldName, FieldValue, FieldError, FormErrors } from '../';
4
+ import { InputEvent } from '../';
5
+ import { ValidatorFormScene, FieldStateListener, FormStateListener } from './';
6
+ /**
7
+ * FieldValidator is an interface used to validate at the field level.
8
+ */
9
+ export interface FieldValidator {
10
+ /**
11
+ * validate the value value of the field.
12
+ */
13
+ validate(key: FieldName, value: FieldValue): Either<FieldError, FieldValue>;
14
+ }
15
+ /**
16
+ * FormValidator extends FieldValidator to provide form level validation.
17
+ */
18
+ export interface FormValidator<T extends Object> extends FieldValidator {
19
+ /**
20
+ * validateAll helper.
21
+ */
22
+ validateAll(value: T): Either<FormErrors, T>;
23
+ }
24
+ /**
25
+ * ValidationStrategy handles the actual validation of FieldEvents.
26
+ *
27
+ * This should also apply the relevant callbacks as desired.
28
+ */
29
+ export interface ValidationStrategy {
30
+ /**
31
+ * validate a InputEvent.
32
+ */
33
+ validate(e: InputEvent): void;
34
+ }
35
+ /**
36
+ * FieldValidator is an interface used by some ValidateStrategys to validate
37
+ * actual values.
38
+ */
39
+ export interface FieldValidator {
40
+ /**
41
+ * validate helper.
42
+ */
43
+ validate(key: FieldName, value: FieldValue): Either<FieldError, FieldValue>;
44
+ }
45
+ /**
46
+ * FormValidator extends FieldValidator to allow validation of all the values
47
+ * in an ValidatorFormScene.
48
+ */
49
+ export interface FormValidator<T extends Object> extends FieldValidator {
50
+ /**
51
+ * validateAll helper.
52
+ */
53
+ validateAll(value: T): Either<FormErrors, T>;
54
+ }
55
+ /**
56
+ * NoStrategy simply sets the captured values on the ValidatorFormScene.
57
+ *
58
+ * This is useful if all validation is done on the server side.
59
+ */
60
+ export declare class NoStrategy<T extends Object> implements ValidationStrategy {
61
+ form: ValidatorFormScene<T>;
62
+ constructor(form: ValidatorFormScene<T>);
63
+ validate({ name, value }: InputEvent): void;
64
+ }
65
+ /**
66
+ * OneForOneStrategy validates event input and triggers the respect
67
+ * onField(In)?Valid callback.
68
+ */
69
+ export declare class OneForOneStrategy<T extends Object> implements ValidationStrategy {
70
+ form: FieldStateListener<T>;
71
+ validator: FieldValidator;
72
+ constructor(form: FieldStateListener<T>, validator: FieldValidator);
73
+ validate({ name, value }: InputEvent): void;
74
+ }
75
+ /**
76
+ * AllForOneStrategy validtes InputEvent input and invokes the
77
+ * respective callbacks.
78
+ *
79
+ * Callbacks for the entire form are also invoked.
80
+ */
81
+ export declare class AllForOneStrategy<T extends Object> implements ValidationStrategy {
82
+ form: FormStateListener<T>;
83
+ validator: FormValidator<T>;
84
+ constructor(form: FormStateListener<T>, validator: FormValidator<T>);
85
+ getValues(): T;
86
+ validate({ name, value }: InputEvent): void;
87
+ }
88
+ /**
89
+ * ModifiedAllForOneStrategy is similar to AllForOneStrategy but only considers
90
+ * the values that have been modified when validating the entire form.
91
+ */
92
+ export declare class ModifiedAllForOneStrategy<T extends Object> extends AllForOneStrategy<T> {
93
+ getValues(): T;
94
+ }
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ModifiedAllForOneStrategy = exports.AllForOneStrategy = exports.OneForOneStrategy = exports.NoStrategy = void 0;
4
+ /**
5
+ * NoStrategy simply sets the captured values on the ValidatorFormScene.
6
+ *
7
+ * This is useful if all validation is done on the server side.
8
+ */
9
+ class NoStrategy {
10
+ constructor(form) {
11
+ this.form = form;
12
+ }
13
+ validate({ name, value }) {
14
+ this.form.set(name, value);
15
+ }
16
+ }
17
+ exports.NoStrategy = NoStrategy;
18
+ /**
19
+ * OneForOneStrategy validates event input and triggers the respect
20
+ * onField(In)?Valid callback.
21
+ */
22
+ class OneForOneStrategy {
23
+ constructor(form, validator) {
24
+ this.form = form;
25
+ this.validator = validator;
26
+ }
27
+ validate({ name, value }) {
28
+ let { form, validator } = this;
29
+ let eResult = validator.validate(name, value);
30
+ if (eResult.isLeft()) {
31
+ form.onFieldInvalid(name, value, eResult.takeLeft());
32
+ }
33
+ else {
34
+ let value = eResult.takeRight();
35
+ form.set(name, value);
36
+ form.onFieldValid(name, value);
37
+ }
38
+ }
39
+ }
40
+ exports.OneForOneStrategy = OneForOneStrategy;
41
+ /**
42
+ * AllForOneStrategy validtes InputEvent input and invokes the
43
+ * respective callbacks.
44
+ *
45
+ * Callbacks for the entire form are also invoked.
46
+ */
47
+ class AllForOneStrategy {
48
+ constructor(form, validator) {
49
+ this.form = form;
50
+ this.validator = validator;
51
+ }
52
+ getValues() {
53
+ return this.form.getValues();
54
+ }
55
+ validate({ name, value }) {
56
+ let { form, validator } = this;
57
+ let eResult = validator.validate(name, value);
58
+ if (eResult.isLeft()) {
59
+ form.onFieldInvalid(name, value, eResult.takeLeft());
60
+ form.onFormInvalid();
61
+ }
62
+ else {
63
+ let value = eResult.takeRight();
64
+ form.set(name, value);
65
+ form.onFieldValid(name, value);
66
+ let eAllResult = validator.validateAll(this.getValues());
67
+ if (eAllResult.isRight())
68
+ form.onFormValid();
69
+ else
70
+ form.onFormInvalid();
71
+ }
72
+ }
73
+ }
74
+ exports.AllForOneStrategy = AllForOneStrategy;
75
+ /**
76
+ * ModifiedAllForOneStrategy is similar to AllForOneStrategy but only considers
77
+ * the values that have been modified when validating the entire form.
78
+ */
79
+ class ModifiedAllForOneStrategy extends AllForOneStrategy {
80
+ getValues() {
81
+ return this.form.getModifiedValues();
82
+ }
83
+ }
84
+ exports.ModifiedAllForOneStrategy = ModifiedAllForOneStrategy;
85
+ //# sourceMappingURL=strategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strategy.js","sourceRoot":"","sources":["../../../../../src/app/scene/form/validator/strategy.ts"],"names":[],"mappings":";;;AA6DA;;;;GAIG;AACH,MAAa,UAAU;IACnB,YAAmB,IAA2B;QAA3B,SAAI,GAAJ,IAAI,CAAuB;IAAG,CAAC;IAElD,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAc;QAChC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC/B,CAAC;CACJ;AAND,gCAMC;AAED;;;GAGG;AACH,MAAa,iBAAiB;IAC1B,YACW,IAA2B,EAC3B,SAAyB;QADzB,SAAI,GAAJ,IAAI,CAAuB;QAC3B,cAAS,GAAT,SAAS,CAAgB;IACjC,CAAC;IAEJ,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAc;QAChC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;QAC/B,IAAI,OAAO,GAAG,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAE9C,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YACnB,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;QACzD,CAAC;aAAM,CAAC;YACJ,IAAI,KAAK,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;YAEhC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACtB,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACnC,CAAC;IACL,CAAC;CACJ;AAnBD,8CAmBC;AAED;;;;;GAKG;AACH,MAAa,iBAAiB;IAC1B,YACW,IAA0B,EAC1B,SAA2B;QAD3B,SAAI,GAAJ,IAAI,CAAsB;QAC1B,cAAS,GAAT,SAAS,CAAkB;IACnC,CAAC;IAEJ,SAAS;QACL,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;IACjC,CAAC;IAED,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAc;QAChC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;QAC/B,IAAI,OAAO,GAAG,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAE9C,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YACnB,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;YACrD,IAAI,CAAC,aAAa,EAAE,CAAC;QACzB,CAAC;aAAM,CAAC;YACJ,IAAI,KAAK,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;YAEhC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACtB,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAE/B,IAAI,UAAU,GAAG,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;YAEzD,IAAI,UAAU,CAAC,OAAO,EAAE;gBAAE,IAAI,CAAC,WAAW,EAAE,CAAC;;gBACxC,IAAI,CAAC,aAAa,EAAE,CAAC;QAC9B,CAAC;IACL,CAAC;CACJ;AA7BD,8CA6BC;AAED;;;GAGG;AACH,MAAa,yBAEX,SAAQ,iBAAoB;IAC1B,SAAS;QACL,OAAU,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;IAC5C,CAAC;CACJ;AAND,8DAMC"}
@@ -50,7 +50,7 @@ export interface Scene extends Api {
50
50
  display: Address;
51
51
  }
52
52
  /**
53
- * BaseAppScene that provides a basis for more specialized AppScenes.
53
+ * AppScene that provides a basis for more specialized AppScenes.
54
54
  *
55
55
  * This class only sends content to the display actor when run.
56
56
  */
@@ -61,6 +61,6 @@ export declare abstract class AppScene extends Immutable implements Scene {
61
61
  /**
62
62
  * show the AppScene by sending a message to the display.
63
63
  */
64
- show(): void;
64
+ show(): Promise<void>;
65
65
  run(): Promise<void>;
66
66
  }
@@ -29,9 +29,9 @@
29
29
  Object.defineProperty(exports, "__esModule", { value: true });
30
30
  exports.AppScene = void 0;
31
31
  const resident_1 = require("@quenk/potoo/lib/actor/framework/resident");
32
- const display_1 = require("app/display");
32
+ const display_1 = require("../display");
33
33
  /**
34
- * BaseAppScene that provides a basis for more specialized AppScenes.
34
+ * AppScene that provides a basis for more specialized AppScenes.
35
35
  *
36
36
  * This class only sends content to the display actor when run.
37
37
  */
@@ -39,11 +39,11 @@ class AppScene extends resident_1.Immutable {
39
39
  /**
40
40
  * show the AppScene by sending a message to the display.
41
41
  */
42
- show() {
43
- this.tell(this.display, new display_1.Show(this.name, this.view, this.self));
42
+ async show() {
43
+ await this.tell(this.display, new display_1.Show(this.name, this.view, this.self));
44
44
  }
45
45
  async run() {
46
- this.show();
46
+ await this.show();
47
47
  }
48
48
  }
49
49
  exports.AppScene = AppScene;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/app/scene/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;;;AAIH,wEAAsE;AAGtE,yCAAmC;AA2BnC;;;;GAIG;AACH,MAAsB,QAClB,SAAQ,oBAAS;IASjB;;OAEG;IACH,IAAI;QAEA,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,cAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAEvE,CAAC;IAED,KAAK,CAAC,GAAG;QAEL,IAAI,CAAC,IAAI,EAAE,CAAC;IAEhB,CAAC;CAEJ;AAzBD,4BAyBC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/app/scene/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;;;AAIH,wEAAsE;AAItE,wCAAkC;AAyBlC;;;;GAIG;AACH,MAAsB,QAAS,SAAQ,oBAAS;IAO5C;;OAEG;IACH,KAAK,CAAC,IAAI;QACN,MAAM,IAAI,CAAC,IAAI,CACX,IAAI,CAAC,OAAO,EACZ,IAAI,cAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAC5C,CAAC;IACN,CAAC;IAED,KAAK,CAAC,GAAG;QACL,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC;CACJ;AApBD,4BAoBC"}
@@ -0,0 +1,56 @@
1
+ import { TypeCase } from '@quenk/noni/lib/control/match/case';
2
+ import { Runtime } from '@quenk/potoo/lib/actor/system/vm/runtime';
3
+ import { Spawnable } from '@quenk/potoo/lib/actor/template';
4
+ import { Address } from '@quenk/potoo/lib/actor/address';
5
+ import { Pop, Push, ViewRemoved, ViewShown, DisplayListener } from '../display';
6
+ import { Focus } from './director';
7
+ import { FormState } from './form';
8
+ import { AppScene } from './';
9
+ /**
10
+ * Page is an actor used to provide one of the primary activity views of an
11
+ * application.
12
+ *
13
+ * These actors are meant to be used in combination with a [[Director]] instance
14
+ * which can spawn them on demand in response to the app's "route" changing.
15
+ *
16
+ * The [[Resume]] parameter serves as proof that the Page is allowed by the
17
+ * Director to send content to the user (by sending a [[Show]] message to the
18
+ * director).
19
+ *
20
+ * When the Director decides it's time for another actor to be given that right,
21
+ * the Page is terminiated but will receive a [[Suspend]] message which can
22
+ * be used to clean up.
23
+ *
24
+ * Page is intentionally basic to allow for the flexibility needed when
25
+ * composing the complex main activities of a routed application. However, to
26
+ * make working with [[FormScene]]s and [[Dialog]]s easier, it contains Case
27
+ * classes for redirecting content received to the Director.
28
+ */
29
+ export declare abstract class Page extends AppScene implements DisplayListener {
30
+ runtime: Runtime;
31
+ focus: Focus;
32
+ constructor(runtime: Runtime, focus: Focus);
33
+ afterViewShown(_: ViewShown): Promise<void>;
34
+ afterViewRemoved(_: ViewRemoved): Promise<void>;
35
+ get display(): string;
36
+ selectors(): (TypeCase<typeof Push, Promise<void>> | TypeCase<typeof Pop, Promise<void>> | TypeCase<typeof ViewShown, Promise<void>>)[];
37
+ /**
38
+ * reload the AppScene by sending a Reload request to the Director.
39
+ *
40
+ * This will end this instance and spawn a new one.
41
+ */
42
+ reload(): Promise<void>;
43
+ /**
44
+ * spawnForm spawns a FormScene and returns a promise that resolves when the
45
+ * form has been saved or aborted.
46
+ *
47
+ * This method exists as an alternative to having the Page implement
48
+ * case classes to handle the form's life cycle messages.
49
+ *
50
+ * @param tmpl - The function that will be used to get the form actor's
51
+ * template. Note that the address of the actor created to
52
+ * spawn the form is passed so it has the correct owner.
53
+ */
54
+ spawnForm(tmpl: (addr: Address) => Spawnable): Promise<FormState>;
55
+ run(): Promise<void>;
56
+ }