@sprucelabs/spruce-form-utils 12.0.21 → 12.0.22

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.
@@ -0,0 +1,4 @@
1
+ declare const formAssert: {
2
+ valuesAreEqual(obj: any, form: any): void;
3
+ };
4
+ export default formAssert;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const test_utils_1 = require("@sprucelabs/test-utils");
4
+ const formAssert = {
5
+ valuesAreEqual(obj, form) {
6
+ test_utils_1.assert.isEqual(JSON.stringify(obj, (key, value) => {
7
+ return value === null ? undefined : value;
8
+ }, 2), JSON.stringify(form, (key, value) => {
9
+ return value === null ? undefined : value;
10
+ }, 2));
11
+ },
12
+ };
13
+ exports.default = formAssert;
14
+ //# sourceMappingURL=formAssert.js.map
@@ -0,0 +1,48 @@
1
+ import { AbstractViewController, FormViewController, SwipeCardViewController, ViewControllerOptions, Router } from '@sprucelabs/heartwood-view-controllers';
2
+ import { SpruceSchemas } from '@sprucelabs/spruce-core-schemas';
3
+ export default class FormPlayerCardViewController extends AbstractViewController<SpruceSchemas.HeartwoodViewControllers.v2021_02_11.Card> {
4
+ private swipeVc;
5
+ static id: string;
6
+ private onChangeHandler?;
7
+ private builderSource;
8
+ private shouldIgnoreChanges;
9
+ private router?;
10
+ constructor(options: FormPlayerCardViewControllerOptions & ViewControllerOptions);
11
+ private SwipeVc;
12
+ private handleSlideChange;
13
+ private renderFooter;
14
+ private handleClickSaveProgress;
15
+ private handleClickSaveAndDone;
16
+ private handleClickNext;
17
+ private renderHeader;
18
+ setIsBusy(isLoading: boolean): void;
19
+ private renderSlides;
20
+ private handleOnChange;
21
+ getHasCriticalError(): boolean;
22
+ getIsBusy(): boolean;
23
+ setCriticalError(err: SpruceSchemas.HeartwoodViewControllers.v2021_02_11.CriticalError): void;
24
+ getSwipeVc(): SwipeCardViewController;
25
+ load(options: PlayerLoadOptions): Promise<void>;
26
+ private updateFooter;
27
+ setValues(values: FormPlayerImportObject['values']): Promise<void>;
28
+ getValues(): Record<string, any>[];
29
+ getFormVcs(): FormViewController<any>[];
30
+ getFormVc(idx: number): FormViewController<any>;
31
+ getSourceBuilder(): Partial<FormPlayerImportObject>;
32
+ render(): SpruceSchemas.HeartwoodViewControllers.v2021_02_11.Card;
33
+ }
34
+ export declare type FormPlayerImportObject = SpruceSchemas.HeartwoodViewControllers.v2021_02_11.FormBuilderImportExportObject & {
35
+ values: Record<string, any>[];
36
+ };
37
+ declare type ChangeHandler = (options: {
38
+ values: Record<string, any>[];
39
+ }) => Promise<void> | void;
40
+ export declare type FormPlayerCardViewControllerOptions = Partial<FormPlayerImportObject> & {
41
+ onChange?: ChangeHandler;
42
+ isBusy?: boolean;
43
+ id?: string;
44
+ };
45
+ export declare type PlayerLoadOptions = Partial<FormPlayerImportObject> & {
46
+ router?: Router;
47
+ };
48
+ export {};
@@ -0,0 +1,185 @@
1
+ "use strict";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ const heartwood_view_controllers_1 = require("@sprucelabs/heartwood-view-controllers");
15
+ const schema_1 = require("@sprucelabs/schema");
16
+ class FormPlayerCardViewController extends heartwood_view_controllers_1.AbstractViewController {
17
+ constructor(options) {
18
+ super(options);
19
+ this.shouldIgnoreChanges = false;
20
+ const { onChange, isBusy, id } = options, builderSource = __rest(options, ["onChange", "isBusy", "id"]);
21
+ this.builderSource = (0, heartwood_view_controllers_1.removeUniversalViewOptions)(builderSource);
22
+ this.swipeVc = this.SwipeVc(id, builderSource);
23
+ if (!options.pages || isBusy) {
24
+ this.swipeVc.setIsBusy(true);
25
+ }
26
+ else if (options.values) {
27
+ void this.setValues(options.values);
28
+ }
29
+ this.onChangeHandler = onChange;
30
+ }
31
+ SwipeVc(id, builderSource) {
32
+ return this.Controller('swipeCard', {
33
+ id,
34
+ header: this.renderHeader(builderSource),
35
+ slides: this.renderSlides(builderSource),
36
+ footer: this.renderFooter(),
37
+ onSlideChange: this.handleSlideChange.bind(this),
38
+ });
39
+ }
40
+ handleSlideChange() {
41
+ this.updateFooter();
42
+ }
43
+ renderFooter() {
44
+ var _a, _b, _c, _d;
45
+ const totalPages = (_b = (_a = this.builderSource.pages) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
46
+ const currentPage = (_d = (_c = this.swipeVc) === null || _c === void 0 ? void 0 : _c.getPresentSlide()) !== null && _d !== void 0 ? _d : 0;
47
+ const buttons = [
48
+ {
49
+ id: 'saveProgress',
50
+ label: 'Save progress',
51
+ onClick: this.handleClickSaveProgress.bind(this),
52
+ },
53
+ ];
54
+ if (totalPages === currentPage + 1) {
55
+ buttons.push({
56
+ id: 'save',
57
+ label: 'Save and be done',
58
+ type: 'primary',
59
+ onClick: this.handleClickSaveAndDone.bind(this),
60
+ });
61
+ }
62
+ else {
63
+ buttons.push({
64
+ id: 'next',
65
+ label: 'Next page',
66
+ type: 'primary',
67
+ onClick: this.handleClickNext.bind(this),
68
+ });
69
+ }
70
+ return {
71
+ buttons,
72
+ };
73
+ }
74
+ async handleClickSaveProgress() {
75
+ await this.alert({
76
+ message: `Progress saved! 💪`,
77
+ style: 'success',
78
+ });
79
+ }
80
+ async handleClickSaveAndDone() {
81
+ var _a;
82
+ await this.alert({
83
+ message: `Progress saved, lets get outa here! 🚀`,
84
+ style: 'success',
85
+ });
86
+ await ((_a = this.router) === null || _a === void 0 ? void 0 : _a.redirect('profile.root'));
87
+ }
88
+ async handleClickNext() {
89
+ await this.swipeVc.jumpToSlide(this.swipeVc.getPresentSlide() + 1);
90
+ }
91
+ renderHeader(options) {
92
+ var _a;
93
+ return {
94
+ title: (_a = options.title) !== null && _a !== void 0 ? _a : 'Loading your form...',
95
+ subtitle: options.subtitle,
96
+ };
97
+ }
98
+ setIsBusy(isLoading) {
99
+ this.swipeVc.setIsBusy(isLoading);
100
+ }
101
+ renderSlides(options) {
102
+ var _a, _b;
103
+ return ((_b = (_a = options.pages) === null || _a === void 0 ? void 0 : _a.map((_a) => {
104
+ var { title } = _a, form = __rest(_a, ["title"]);
105
+ return ({
106
+ title,
107
+ form: this.Controller('form', Object.assign(Object.assign({}, form), { shouldShowSubmitControls: false, onChange: async () => {
108
+ await this.handleOnChange();
109
+ } })).render(),
110
+ });
111
+ })) !== null && _b !== void 0 ? _b : []);
112
+ }
113
+ async handleOnChange() {
114
+ var _a;
115
+ if (!this.shouldIgnoreChanges) {
116
+ await ((_a = this.onChangeHandler) === null || _a === void 0 ? void 0 : _a.call(this, { values: this.getValues() }));
117
+ }
118
+ }
119
+ getHasCriticalError() {
120
+ return this.swipeVc.getHasCriticalError();
121
+ }
122
+ getIsBusy() {
123
+ return this.swipeVc.isBusy();
124
+ }
125
+ setCriticalError(err) {
126
+ this.swipeVc.setCriticalError(err);
127
+ }
128
+ getSwipeVc() {
129
+ return this.swipeVc;
130
+ }
131
+ async load(options) {
132
+ const { router } = options, source = __rest(options, ["router"]);
133
+ const { title, subtitle } = this.renderHeader(source);
134
+ this.router = router;
135
+ this.swipeVc.setHeaderTitle(title !== null && title !== void 0 ? title : null);
136
+ this.swipeVc.setHeaderSubtitle(subtitle !== null && subtitle !== void 0 ? subtitle : null);
137
+ this.swipeVc.setSections(this.renderSlides(source));
138
+ if (source.values) {
139
+ await this.setValues(source.values);
140
+ }
141
+ this.builderSource = source;
142
+ this.updateFooter();
143
+ this.swipeVc.setIsBusy(false);
144
+ }
145
+ updateFooter() {
146
+ this.swipeVc.setFooter(this.router ? this.renderFooter() : null);
147
+ }
148
+ async setValues(values) {
149
+ if (!Array.isArray(values)) {
150
+ throw new Error('values must be an array!');
151
+ }
152
+ const vcs = this.getFormVcs();
153
+ this.shouldIgnoreChanges = true;
154
+ await Promise.all(values.map(async (v, idx) => vcs[idx].setValues(v)));
155
+ this.shouldIgnoreChanges = false;
156
+ await this.handleOnChange();
157
+ }
158
+ getValues() {
159
+ return this.getFormVcs().map((vc) => vc.getValues());
160
+ }
161
+ getFormVcs() {
162
+ var _a, _b;
163
+ return ((_b = (_a = this.swipeVc.getSlides()) === null || _a === void 0 ? void 0 : _a.map((s) => { var _a; return (_a = s.form) === null || _a === void 0 ? void 0 : _a.controller; })) !== null && _b !== void 0 ? _b : []);
164
+ }
165
+ getFormVc(idx) {
166
+ const formVc = this.getFormVcs()[idx];
167
+ if (!formVc) {
168
+ throw new schema_1.SchemaError({
169
+ code: 'INVALID_PARAMETERS',
170
+ friendlyMessage: `I couldn't find a form at index ${idx}.`,
171
+ parameters: ['formIdx'],
172
+ });
173
+ }
174
+ return formVc;
175
+ }
176
+ getSourceBuilder() {
177
+ return this.builderSource;
178
+ }
179
+ render() {
180
+ return this.swipeVc.render();
181
+ }
182
+ }
183
+ exports.default = FormPlayerCardViewController;
184
+ FormPlayerCardViewController.id = 'form-player-card';
185
+ //# sourceMappingURL=FormPlayerCard.vc.js.map
@@ -0,0 +1,5 @@
1
+ import { FormBuilderPage } from '@sprucelabs/heartwood-view-controllers';
2
+ declare const formCompletionCalculator: {
3
+ calculate(pages: FormBuilderPage[], values: Record<string, any>[]): number;
4
+ };
5
+ export default formCompletionCalculator;
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const schema_1 = require("@sprucelabs/schema");
4
+ function validateOptions(pages, values) {
5
+ (0, schema_1.assertOptions)({
6
+ pages,
7
+ values,
8
+ }, ['pages', 'values']);
9
+ if (!Array.isArray(pages)) {
10
+ throw new schema_1.SchemaError({
11
+ code: 'INVALID_PARAMETERS',
12
+ parameters: ['pages'],
13
+ friendlyMessage: 'pages must be an array',
14
+ });
15
+ }
16
+ if (!Array.isArray(values)) {
17
+ throw new schema_1.SchemaError({
18
+ code: 'INVALID_PARAMETERS',
19
+ parameters: ['values'],
20
+ friendlyMessage: 'values must be an array',
21
+ });
22
+ }
23
+ }
24
+ const formCompletionCalculator = {
25
+ calculate(pages, values) {
26
+ var _a, _b, _c, _d;
27
+ validateOptions(pages, values);
28
+ const requiredFields = [];
29
+ let totalFields = 0;
30
+ for (const page of pages) {
31
+ const fields = (_a = page.schema.fields) !== null && _a !== void 0 ? _a : {};
32
+ for (const section of page.sections) {
33
+ for (const field of (_b = section.fields) !== null && _b !== void 0 ? _b : []) {
34
+ const fieldKey = (_c = field.name) !== null && _c !== void 0 ? _c : field;
35
+ const f = (_d = fields[fieldKey]) !== null && _d !== void 0 ? _d : {};
36
+ if (f.isRequired) {
37
+ totalFields++;
38
+ requiredFields.push(fieldKey);
39
+ }
40
+ }
41
+ }
42
+ }
43
+ if (totalFields === 0) {
44
+ return 1;
45
+ }
46
+ let totalAnswered = 0;
47
+ for (const value of values) {
48
+ totalAnswered += Object.keys(value !== null && value !== void 0 ? value : {}).filter((k) => {
49
+ return !!value[k] && requiredFields.indexOf(k) !== -1;
50
+ }).length;
51
+ }
52
+ return parseFloat((totalAnswered / totalFields).toFixed(2));
53
+ },
54
+ };
55
+ exports.default = formCompletionCalculator;
56
+ //# sourceMappingURL=formCompletionCalculator.js.map
@@ -0,0 +1,4 @@
1
+ export { default as formAssert } from './__tests__/support/formAssert';
2
+ export { default as formCompletionCalculator } from './completing/formCompletionCalculator';
3
+ export { default as FormPlayerCardViewController } from './completing/FormPlayerCard.vc';
4
+ export * from './types/types-module';
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ var __importDefault = (this && this.__importDefault) || function (mod) {
17
+ return (mod && mod.__esModule) ? mod : { "default": mod };
18
+ };
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.FormPlayerCardViewController = exports.formCompletionCalculator = exports.formAssert = void 0;
21
+ var formAssert_1 = require("./__tests__/support/formAssert");
22
+ Object.defineProperty(exports, "formAssert", { enumerable: true, get: function () { return __importDefault(formAssert_1).default; } });
23
+ var formCompletionCalculator_1 = require("./completing/formCompletionCalculator");
24
+ Object.defineProperty(exports, "formCompletionCalculator", { enumerable: true, get: function () { return __importDefault(formCompletionCalculator_1).default; } });
25
+ var FormPlayerCard_vc_1 = require("./completing/FormPlayerCard.vc");
26
+ Object.defineProperty(exports, "FormPlayerCardViewController", { enumerable: true, get: function () { return __importDefault(FormPlayerCard_vc_1).default; } });
27
+ __exportStar(require("./types/types-module"), exports);
28
+ //# sourceMappingURL=index-module.js.map
@@ -0,0 +1,21 @@
1
+ import { Scope, SpruceSchemas, ViewController } from '@sprucelabs/heartwood-view-controllers';
2
+ import FormPlayerCardViewController, { FormPlayerCardViewControllerOptions } from '../completing/FormPlayerCard.vc';
3
+ declare type Card = SpruceSchemas.HeartwoodViewControllers.v2021_02_11.Card;
4
+ export declare type UpdateForm = SpruceSchemas.Forms.v2021_07_02.UpdateForm;
5
+ export interface RemoteFormBuilderCardLoadOptions {
6
+ scope: Scope;
7
+ formId?: string;
8
+ }
9
+ export interface RemoteFormBuilderCard extends ViewController<Card> {
10
+ load?(options: RemoteFormBuilderCardLoadOptions): Promise<void>;
11
+ didSaveForm?(form: UpdateForm): Promise<void>;
12
+ }
13
+ declare module '@sprucelabs/heartwood-view-controllers/build/types/heartwood.types' {
14
+ interface ViewControllerMap {
15
+ formPlayerCard: FormPlayerCardViewController;
16
+ }
17
+ interface ViewControllerOptionsMap {
18
+ formPlayerCard: FormPlayerCardViewControllerOptions;
19
+ }
20
+ }
21
+ export {};
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types-module.js.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sprucelabs/spruce-form-utils",
3
3
  "description": "Support for working with forms and Sprucebot. 📄",
4
- "version": "12.0.21",
4
+ "version": "12.0.22",
5
5
  "skill": {
6
6
  "namespace": "forms"
7
7
  },