Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QOL-8650 add webhooks and update readme #16

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 180 additions & 0 deletions src/matrixHelpers/FormioLoader/FormioLoader.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,20 @@ To initiate Formio instance on page load, simply include the script in your webp
If the script is already loaded, you could init the form with an alternate method `FormioLoader.initFormioInstance`.
This is useful if you want to dynamically inject a form element. (Although the `FormioLoader.initFormio()` method will work the same)

### Options:

| Option | Description | Example |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
| projectName | Formio project name | dev-svcwlpuksmwawwk |
| formName | Formio form name | plsPlusFormDemo |
| envUrl | domain name of the Formio endpoint | api.forms.platforms.qld.gov.au |
| formConfirmation | redirect page for wizard after submission | / |
| formRevision | form revision number | 1 |
| pdfDownload | Does the form involve pdf download | no |
| namespace | Namespace of the form for creating key for token, user, etc | any string |
| createFormOptions | function that returns [options](https://help.form.io/developers/form-renderer#form-renderer-options) to be passed to the createForm function | ({ envUrl, projectName, formName, defaultOptions }) => object |
| createFormController | custom form controller function | ({ envUrl, projectName, formName, form }) => void) |

<Canvas withSource="open">
<Story name="initFormioInstanceMethod">
{() => {
Expand All @@ -86,3 +100,169 @@ This is useful if you want to dynamically inject a form element. (Although the `
}}
</Story>
</Canvas>

## Custom createForm options with `createFormOptions` hook

You can create a hook function `createFormOptions` to customise the [options](https://help.form.io/developers/form-renderer#form-renderer-options).
Within the function you could pass different options base on different project or form.

The example below will add the custom options to every forms in the page.

```jsx
const customFn = () => {
return {
readOnly: true,
};
};
FormioLoader.initFormioInstance(elem, {
projectName: "dev-svcwlpuksmwawwk",
formName: "plsPlusFormDemo",
envUrl: "api.forms.platforms.qld.gov.au",
pdfDownload: "no",
createFormOptions: customFn,
});
```

The example below only add the custom options to certain project or form with a single hook function.

```jsx
const customFn = ({ envUrl, projectName, formName }) => {
if ({ envUrl === "api.forms.platforms.qld.gov.au") {
return {
readOnly: true,
};
}
if (projectName === "project1") {
return {
readOnly: true,
};
}
if (projectName === "project2" && formName === "form2") {
return {
readOnly: true,
};
}
return {};
};
FormioLoader.initFormioInstance(elem1, {
projectName: "project1",
formName: "form1",
envUrl: "api.forms.platforms.qld.gov.au",
pdfDownload: "no",
createFormOptions: customFn
});
FormioLoader.initFormioInstance(elem2, {
projectName: "project2",
formName: "form2",
envUrl: "api.forms.platforms.qld.gov.au",
pdfDownload: "no",
createFormOptions: customFn
});
```

Please refer to https://help.form.io/developers/form-renderer#form-renderer-options for available options.

Below is a full example:

<Canvas withSource="open">
<Story name="custom CreateForm Options hook">
{() => {
const customFn = ({ defaultOptions }) => {
// you can see the defaultOptions in the browser's inspector, and possible to manipulate and return it.
console.info("defaultOptions:", defaultOptions);
return {
readOnly: true,
};
};
setTimeout(() => {
const elem = document.getElementById("formio-options");
FormioLoader.initFormioInstance(elem, {
projectName: "dev-svcwlpuksmwawwk",
formName: "testing1",
envUrl: "api.forms.platforms.qld.gov.au",
pdfDownload: "no",
createFormOptions: customFn,
});
});
return `
<div id="formio-options" class="qg-forms-v2" ></div>
`;
}}
</Story>
</Canvas>

## Controlling the Form with JavaScript with `createFormController` hook

You can create a hook function `createFormController` to customise the [form controller](https://help.form.io/developers/form-renderer#controlling-the-form-with-javascript).
Within the function you could customise the controller base on different project or form.

```jsx
const customFn = ({ form }) => {
form.on("change", (e) => {
console.info("onChange", e);
});
};
FormioLoader.initFormioInstance(elem, {
projectName: "dev-svcwlpuksmwawwk",
formName: "plsPlusFormDemo",
envUrl: "api.forms.platforms.qld.gov.au",
pdfDownload: "no",
createFormController: customFn,
});
```

The example below only control the form to certain project or form.

```jsx
const customFn = ({ envUrl, projectName, formName, form }) => {
if (projectName === "project2" && formName === "form2") {
form.on("change", (e) => {
console.info("onChange", e);
});
}
};
FormioLoader.initFormioInstance(elem1, {
projectName: "project1",
formName: "form1",
envUrl: "api.forms.platforms.qld.gov.au",
pdfDownload: "no",
createFormOptions: customFn,
});
FormioLoader.initFormioInstance(elem2, {
projectName: "project2",
formName: "form2",
envUrl: "api.forms.platforms.qld.gov.au",
pdfDownload: "no",
createFormOptions: customFn,
});
```

Please refer to https://help.form.io/developers/form-renderer#controlling-the-form-with-javascript for more examples.

Below is a full example:

<Canvas withSource="open">
<Story name="custom CreateForm controller hook">
{() => {
const customFn = ({ form }) => {
form.on("change", (e) => {
// you can see the data object in the browser's inspector whenever you change the field value.
console.info("onChange", e.data);
});
};
setTimeout(() => {
const elem = document.getElementById("formio-controller");
FormioLoader.initFormioInstance(elem, {
projectName: "dev-svcwlpuksmwawwk",
formName: "testing2",
envUrl: "api.forms.platforms.qld.gov.au",
pdfDownload: "no",
createFormController: customFn,
});
});
return `
<div id="formio-controller" class="qg-forms-v2" ></div>
`;
}}
</Story>
</Canvas>
87 changes: 87 additions & 0 deletions src/matrixHelpers/FormioLoader/FormioLoader.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import "@testing-library/jest-dom";
import userEvent from "@testing-library/user-event";
import { findByText } from "@testing-library/dom";
import * as FormioLoader from "./index";
import { testWait } from "../../utils";
Expand Down Expand Up @@ -39,3 +40,89 @@ test("FormioLoader is initiated with invalid div", async () => {
await testWait();
expect(div.innerHTML).toEqual(`<div id="formio" data-formio=""></div>`);
});

// Smoke test
test("FormioLoader with custom option hook", async () => {
window.customOptionsFn = () => {
return {
readOnly: true,
};
};

const div = document.createElement("div");
div.innerHTML = `
<div id="formio"
data-formio
data-formio-project-name="dev-svcwlpuksmwawwk"
data-formio-form-name="plsPlusFormDemo"
data-formio-form-confirmation=""
data-formio-form-revision=""
data-formio-env-url="api.forms.platforms.qld.gov.au"
data-formio-pdf-download="no"
data-formio-namespace=""
data-formio-createForm-options="customOptionsFn"
></div>
`;
document.body.append(div);
FormioLoader.initFormio();
jest.spyOn(Formio, "makeRequest").mockResolvedValueOnce(formioRes);

const label = await findByText(div, "Address");
expect(label).toBeVisible();

const autocomplete = div.querySelector("input[name='data[address]']");
expect(autocomplete).toBeVisible();
expect(autocomplete).toBeDisabled();
});

// Smoke test
test("FormioLoader with custom controller hook", async () => {
let data = {};
window.customControllerFn = ({ form }) => {
form.on("change", (e) => {
data = e.data;
});
};

const div = document.createElement("div");
div.innerHTML = `
<div id="formio"
data-formio
data-formio-project-name="dev-svcwlpuksmwawwk"
data-formio-form-name="plsPlusFormDemo"
data-formio-form-confirmation=""
data-formio-form-revision=""
data-formio-env-url="api.forms.platforms.qld.gov.au"
data-formio-pdf-download="no"
data-formio-namespace=""
data-formio-createForm-controller="customControllerFn"
></div>
`;
document.body.append(div);
FormioLoader.initFormio();
jest.spyOn(Formio, "makeRequest").mockResolvedValueOnce(formioRes);

const label = await findByText(div, "Address");
expect(label).toBeVisible();

const checkbox = div.querySelector("input[ref='modeSwitcher']");
expect(checkbox).not.toBeChecked();
await userEvent.click(checkbox);
await testWait();
expect(data).toEqual({
address: {
address: {
address1: "",
address2: "",
address3: "",
autocompleteAddress: "",
city: "",
postcode: "",
selectedAddress: "",
state: "QLD",
},
mode: "autocomplete",
},
submit: false,
});
});
50 changes: 35 additions & 15 deletions src/matrixHelpers/FormioLoader/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import createFormOptions from "../../options/createForm.options";
import defaultCreateFormOptions from "../../options/createForm.options";

const initFormioInstance = (formioElem, opts) => {
// if already initiated, reject
Expand All @@ -11,14 +11,12 @@ const initFormioInstance = (formioElem, opts) => {
);
return;
}
const bodyContainer = $("body");
const defaultRedirect = "contact-us/response/";
/*
* setup config
*/
const baseUrl = `https://${opts.envUrl.trim()}`;
const formioContainerId = formioElem.getAttribute("id");
const submitBtn = $(`#${formioContainerId} button[name='data[submit]']`);
const submitBtn = $(formioElem, `button[name='data[submit]']`);
let formName = "";
// Check if value is true/exists and is numeric
if (opts.form_revision) {
Expand All @@ -45,16 +43,24 @@ const initFormioInstance = (formioElem, opts) => {
/*
* load formio form
*/
Formio.createForm(
formioElem,
formUrl,
// form,
{
...createFormOptions,
formio,
namespace: formio.options.namespace,
}
).then((wizard) => {
const defaultOptions = {
...defaultCreateFormOptions,
formio,
namespace: formio.options.namespace,
};

const combinedOptions = {
...defaultOptions,
// combine with hook options
...(typeof opts.createFormOptions === "function" &&
opts.createFormOptions({
envUrl: opts.envUrl,
projectName: opts.projectName,
formName: opts.formName,
defaultOptions,
})),
};
Formio.createForm(formioElem, formUrl, combinedOptions).then((wizard) => {
wizard.formio = formio;
wizard.options.formio = formio;

Expand All @@ -64,7 +70,7 @@ const initFormioInstance = (formioElem, opts) => {
const formModified = wizard._form.modified;

// Force new tab on formlinks
bodyContainer.on("click", `#${formioContainerId} a`, (e) => {
$(formioElem).on("click", `a`, (e) => {
e.target.target = "_blank";
});

Expand Down Expand Up @@ -107,6 +113,16 @@ const initFormioInstance = (formioElem, opts) => {
console.debug("Submission error");
});
});

// call hook controller
if (typeof opts.createFormController === "function") {
opts.createFormController({
envUrl: opts.envUrl,
projectName: opts.projectName,
formName: opts.formName,
form: wizard,
});
}
});
};

Expand Down Expand Up @@ -168,6 +184,8 @@ const initFormio = () => {
formioFormConfirmation,
formioFormRevision,
formioNamespace,
formioCreateformOptions,
formioCreateformController,
} = formioElem.dataset;
initFormioInstance(formioElem, {
projectName: formioProjectName,
Expand All @@ -177,6 +195,8 @@ const initFormio = () => {
formConfirmation: formioFormConfirmation,
formRevision: formioFormRevision,
namespace: formioNamespace,
createFormOptions: window[formioCreateformOptions],
createFormController: window[formioCreateformController],
});
});
};
Expand Down
Loading