Skip to content
Closed
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
26 changes: 10 additions & 16 deletions designer/client/pages/landing-page/ViewFundForms.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type Props = {
type State = {
configs: { Key: string; DisplayName: string }[];
loading?: boolean;

};

export class ViewFundForms extends Component<Props, State> {
Expand All @@ -25,30 +26,23 @@ export class ViewFundForms extends Component<Props, State> {
};
}

componentDidMount() {
formConfigurationApi.loadConfigurations().then((configs) => {
async componentDidMount() {
try {
const configs = await formConfigurationApi.loadConfigurations();
this.setState({
loading: false,
configs,
});
});
} catch (error) {
logger.error("ViewFundForms componentDidMount", error);
this.setState({ loading: false });
}
}

selectForm = async (form) => {
try {
const response = await window.fetch("/api/new", {
method: "POST",
body: JSON.stringify({
selected: {Key: form},
name: "",
}),
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
});
const responseJson = await response.json();
this.props.history.push(`/designer/${responseJson.id}`);
// Always go directly to edit the form from Pre-Award API
this.props.history.push(`/designer/${form}`);
} catch (e) {
logger.error("ChooseExisting", e);
}
Expand Down
4 changes: 3 additions & 1 deletion designer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
"static-content:dist-push": "cp -r ../designer/public/static/images dist/client/assets && cp -r ../designer/public/static/css dist/client/assets",
"build": "NODE_ENV=production && NODE_OPTIONS=--openssl-legacy-provider && webpack && yarn run static-content:dist-push",
"start:server": "node dist/server.js",
"start:local": "NODE_ENV=development PERSISTENT_BACKEND=preview ts-node-dev --inspect=0.0.0.0:9229 --respawn --transpile-only server/index.ts"
"start:local": "NODE_ENV=development PERSISTENT_BACKEND=preview ts-node-dev --inspect=0.0.0.0:9229 --respawn --transpile-only server/index.ts",
"test": "lab test/cases/server/plugins/*.test.ts -T test/.transform.js -v",
"unit-test": "lab test/cases/server/plugins/*.test.ts -T test/.transform.js -v -S -r console -o stdout -r html -o unit-test.html -I version -l"
},
"author": "Communities UK",
"license": "SEE LICENSE IN LICENSE",
Expand Down
6 changes: 6 additions & 0 deletions designer/server/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ export interface Config {
authCookieName: string,
sslKey: string,
sslCert: string,

preAwardApiUrl: string,
}

// server-side storage expiration - defaults to 20 minutes
Expand Down Expand Up @@ -65,6 +67,8 @@ const schema = joi.object({
authCookieName: joi.string().optional(),
sslKey: joi.string().optional(),
sslCert: joi.string().optional(),

preAwardApiUrl: joi.string().default("https://api.communities.gov.localhost:4004"),
});

// Build config
Expand All @@ -90,6 +94,8 @@ const config = {
authCookieName: process.env.AUTH_COOKIE_NAME,
sslKey: process.env.SSL_KEY,
sslCert: process.env.SSL_CERT,

preAwardApiUrl: process.env.PRE_AWARD_API_URL || "https://api.communities.gov.localhost:4004",
};

// Validate config
Expand Down
116 changes: 116 additions & 0 deletions designer/server/lib/preAwardApiClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import config from "../config";
import Wreck from "@hapi/wreck";

interface FormJson {
startPage: string;
pages: any[];
sections: any[];
name: string;
version?: number;
conditions?: any[];
lists?: any[];
metadata?: any;
fees?: any[];
outputs?: any[];
skipSummary?: boolean;
[key: string]: any;
}

export interface FormData {
name: string;
form_json: FormJson;
}

export interface FormResponse {
id: string;
name: string;
created_at: string;
updated_at: string;
published_at: string | null;
draft_json: FormJson;
published_json: FormJson;
is_published: boolean;
}

export class PreAwardApiClient {
private baseUrl: string;

constructor() {
this.baseUrl = config.preAwardApiUrl;
}

async createOrUpdateForm(name: string, form_json: FormJson): Promise<FormResponse>{
const payload = {
name: name,
form_json: form_json,
};

try{
const { payload: responseData } = await Wreck.post(
`${this.baseUrl}/forms`,
{
payload: JSON.stringify(payload),
headers: {
'Content-Type': 'application/json'
}
}
);

const parsedData = JSON.parse((responseData as Buffer).toString());

return parsedData as FormResponse;
}
catch (error) {

throw error;
}
}

async getAllForms(): Promise<FormResponse[]> {
try {

const { payload: responseData } = await Wreck.get(
`${this.baseUrl}/forms`,
{
headers: {
'Content-Type': 'application/json'
}
}
);




const parsedData = JSON.parse((responseData as Buffer).toString());



return parsedData as FormResponse[];
} catch (error) {

throw error;
}
}

async getFormDraft(name: string): Promise<FormJson>{
try{
const { payload: responseData } = await Wreck.get(
`${this.baseUrl}/forms/${name}/draft`,
{
headers: {
'Content-Type': 'application/json'
}
}
);
const parsedData = JSON.parse((responseData as Buffer).toString());

return parsedData as FormJson;
}
catch (error) {

throw error;
}
}
}

export const preAwardApiClient = new PreAwardApiClient();
21 changes: 12 additions & 9 deletions designer/server/plugins/DesignerRouteRegister.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import {newConfig, api, app} from "../../../digital-form-builder/designer/server/plugins/routes";
import {app} from "../../../digital-form-builder/designer/server/plugins/routes";
import {envStore, flagg} from "flagg";
import {putFormWithIdRouteRegister} from "./routes/PutFormWithIdRouteRegister";
import {registerNewFormWithRunner} from "./routes/newConfig";
import {getFormWithId, getAllPersistedConfigurations, log} from "./routes/api";
import config from "../config";
import {jwtAuthStrategyName} from "./AuthPlugin";

Expand Down Expand Up @@ -83,15 +85,15 @@ export const designerPlugin = {
// @ts-ignore
app.redirectOldUrlToDesigner.options.auth = jwtAuthStrategyName
// @ts-ignore
newConfig.registerNewFormWithRunner.options.auth = jwtAuthStrategyName
registerNewFormWithRunner.options.auth = jwtAuthStrategyName
// @ts-ignore
api.getFormWithId.options.auth = jwtAuthStrategyName
getFormWithId.options.auth = jwtAuthStrategyName
// @ts-ignore
putFormWithIdRouteRegister.options.auth = jwtAuthStrategyName
// @ts-ignore
api.getAllPersistedConfigurations.options.auth = jwtAuthStrategyName
getAllPersistedConfigurations.options.auth = jwtAuthStrategyName
// @ts-ignore
api.log.options.auth = jwtAuthStrategyName
log.options.auth = jwtAuthStrategyName
}

server.route(startRoute);
Expand All @@ -118,6 +120,7 @@ export const designerPlugin = {
store: envStore(process.env),
definitions: {
featureEditPageDuplicateButton: {default: false},

},
});

Expand All @@ -128,11 +131,11 @@ export const designerPlugin = {
},
});

server.route(newConfig.registerNewFormWithRunner);
server.route(api.getFormWithId);
server.route(registerNewFormWithRunner);
server.route(getFormWithId);
server.route(putFormWithIdRouteRegister);
server.route(api.getAllPersistedConfigurations);
server.route(api.log);
server.route(getAllPersistedConfigurations);
server.route(log);
},
},
};
6 changes: 6 additions & 0 deletions designer/server/plugins/routes/PutFormWithIdRouteRegister.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import {ServerRoute} from "@hapi/hapi";
import {AdapterSchema} from "@communitiesuk/model";
import {publish} from "../../../../digital-form-builder/designer/server/lib/publish";
import {preAwardApiClient} from "../../lib/preAwardApiClient";
import config from "../../config";


export const putFormWithIdRouteRegister: ServerRoute = {
Expand Down Expand Up @@ -31,6 +33,10 @@ export const putFormWithIdRouteRegister: ServerRoute = {
`${id}`,
JSON.stringify(value)
);
// Save to Pre-Award API
const formWithName = { ...value, name: id};
await preAwardApiClient.createOrUpdateForm(id, formWithName);
// Publish to runner for preview
await publish(id, value);
return h.response({ok: true}).code(204);
} catch (err) {
Expand Down
60 changes: 60 additions & 0 deletions designer/server/plugins/routes/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { api as originalApi } from "../../../../digital-form-builder/designer/server/plugins/routes";
import { preAwardApiClient } from "../../lib/preAwardApiClient";
import config from "../../config";
import { ServerRoute, ResponseObject } from "@hapi/hapi";

// Extend the original getFormWithId with Pre-Award API support
export const getFormWithId: ServerRoute = {
...originalApi.getFormWithId,
options: {
...originalApi.getFormWithId.options || {},
handler: async (request, h) => {
const { id } = request.params;
const formJson = await preAwardApiClient.getFormDraft(id);
return h.response(formJson).type("application/json");
},
},
};

// Extend the original putFormWithId with Pre-Award API support
export const putFormWithId: ServerRoute = {
...originalApi.putFormWithId,
options: {
...originalApi.putFormWithId.options || {},
handler: async (request, h) => {
const { id } = request.params;
const { Schema } = await import("../../../../digital-form-builder/model/src");
const { value, error } = Schema.validate(request.payload, {
abortEarly: false,
});

if (error) {
throw new Error("Schema validation failed, reason: " + error.message);
}
const formWithName = { ...value, name: id};
await preAwardApiClient.createOrUpdateForm(id, formWithName);

return h.response({ ok: true }).code(204);
},
},
};

// Extend the original getAllPersistedConfigurations with Pre-Award API support
export const getAllPersistedConfigurations: ServerRoute = {
...originalApi.getAllPersistedConfigurations,
options: {
...originalApi.getAllPersistedConfigurations.options || {},
handler: async (request, h): Promise<ResponseObject | undefined> => {
const forms = await preAwardApiClient.getAllForms();
const response = forms.map(form => ({
Key: form.name,
DisplayName: form.name,
LastModified: form.updated_at
}));
return h.response(response).type("application/json");
},
},
};

// Use original log route as-is
export const log = originalApi.log;
42 changes: 42 additions & 0 deletions designer/server/plugins/routes/newConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { newConfig as originalNewConfig } from "../../../../digital-form-builder/designer/server/plugins/routes";
import { preAwardApiClient } from "../../lib/preAwardApiClient";
import config from "../../config";
import { ServerRoute } from "@hapi/hapi";
import { HapiRequest } from "../../../../digital-form-builder/designer/server/types";
import { nanoid } from "nanoid";
import newFormJson from "../../../../digital-form-builder/designer/new-form.json";

// Extend the original registerNewFormWithRunner with Pre-Award API support
export const registerNewFormWithRunner: ServerRoute = {
...originalNewConfig.registerNewFormWithRunner,
options: {
...originalNewConfig.registerNewFormWithRunner.options,
handler: async (request: HapiRequest, h) => {
const { selected, name } = request.payload as any;

if (name && name !== "" && !name.match(/^[a-zA-Z0-9 _-]+$/)) {
return h
.response("Form name should not contain special characters")
.type("application/json")
.code(400);
}

const newName = name === "" ? nanoid(10) : name;

if (selected.Key === "New") {
const formWithName = { ...newFormJson, name: newName };
await preAwardApiClient.createOrUpdateForm(newName, formWithName);
} else {
const existingForm = await preAwardApiClient.getFormDraft(selected.Key);
const formWithNewName = { ...existingForm, name: newName };
await preAwardApiClient.createOrUpdateForm(newName, formWithNewName);
}

const response = JSON.stringify({
id: `${newName}`,
previewUrl: config.previewUrl,
});
return h.response(response).type("application/json").code(200);
},
},
};
17 changes: 17 additions & 0 deletions designer/test/.transform.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const Babel = require("@babel/core");

module.exports = [
{
ext: ".ts",
transform: (content, filename) => {
const result = Babel.transformSync(content, {
filename,
presets: [
["@babel/preset-env", { targets: { node: "current" } }],
"@babel/preset-typescript"
]
});
return result.code;
}
}
];
Loading
Loading