Skip to content

Commit b7d9b48

Browse files
authored
Merge pull request #10 from bcgov/dev
Sync main with dev
2 parents 4eb3062 + 1ebe2d5 commit b7d9b48

File tree

9 files changed

+2825
-197
lines changed

9 files changed

+2825
-197
lines changed

server/api/controllers/communications.controller.ts

Lines changed: 159 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@ import { Request, Response } from 'express';
22
import ICMService from '../services/icm.service';
33

44
export class CommunicationsController {
5-
saveData(req: Request, res: Response): void {
6-
res.json({ endpoint: 'saveForm', payload: req.body });
7-
}
8-
95
async generateForm(req: Request, res: Response): Promise<void> {
106
const originalServer = req.headers['x-original-server'] as string;
117
const { token, username, ...params } = req.body;
@@ -78,7 +74,7 @@ export class CommunicationsController {
7874
}
7975
}
8076

81-
async clearICMLockedFlag(req: Request, res: Response): Promise<void> {
77+
async unlockICMData(req: Request, res: Response): Promise<void> {
8278
const { token, username, ...params } = req.body;
8379

8480
const authHeader = req.headers.authorization;
@@ -152,6 +148,29 @@ export class CommunicationsController {
152148
}
153149
}
154150

151+
async generatePortalForm(req: Request, res: Response): Promise<void> {
152+
const originalServer = req.headers['x-original-server'] as string;
153+
const { token, username, ...params } = req.body;
154+
155+
const authHeader = req.headers.authorization;
156+
const authToken =
157+
token ||
158+
(authHeader?.startsWith('Bearer ')
159+
? authHeader.substring(7)
160+
: authHeader);
161+
162+
const result = await ICMService.generatePortalForm(
163+
{ ...params, username, originalServer },
164+
authToken
165+
);
166+
167+
if (result.success) {
168+
res.status(200).json(result.data);
169+
} else {
170+
res.status(result.status || 500).json({ error: result.error });
171+
}
172+
}
173+
155174
async loadPortalForm(req: Request, res: Response): Promise<void> {
156175
try {
157176
const requestData = req.body;
@@ -187,12 +206,143 @@ export class CommunicationsController {
187206
}
188207
}
189208

190-
generatePDFFromJson(req: Request, res: Response): void {
191-
res.json({ endpoint: 'generatePDFFromJson', payload: req.body });
209+
async loadBoundForm(req: Request, res: Response): Promise<void> {
210+
try {
211+
const originalServer = req.headers['x-original-server'] as string;
212+
const { token, username, isPortalIntegrated, ...params } = req.body;
213+
214+
const authHeader = req.headers.authorization;
215+
const authToken =
216+
token ||
217+
(authHeader?.startsWith('Bearer ')
218+
? authHeader.substring(7)
219+
: authHeader);
220+
221+
let result;
222+
if (isPortalIntegrated) {
223+
result = await ICMService.loadPortalForm(
224+
{ ...params },
225+
authToken,
226+
originalServer
227+
);
228+
} else {
229+
result = await ICMService.loadICMData(
230+
{ ...params, username, originalServer },
231+
authToken
232+
);
233+
}
234+
235+
if (result.success) {
236+
const boundData = await ICMService.bindFormData(result.data);
237+
res.status(200).json(boundData);
238+
} else {
239+
res.status(result.status || 500).json({ error: result.error });
240+
}
241+
} catch (error) {
242+
let errorMessage = 'Internal server error';
243+
if (error instanceof Error && error.message) {
244+
errorMessage = error.message;
245+
}
246+
res.status(500).json({
247+
error: errorMessage,
248+
});
249+
}
250+
}
251+
252+
async bindPreviewForm(req: Request, res: Response): Promise<void> {
253+
try {
254+
const { formData } = req.body;
255+
256+
if (!formData) {
257+
res.status(400).json({ error: 'Form data is required' });
258+
return;
259+
}
260+
261+
const boundData = await ICMService.bindFormData(formData);
262+
res.status(200).json(boundData);
263+
} catch (error) {
264+
let errorMessage = 'Internal server error';
265+
if (error instanceof Error && error.message) {
266+
errorMessage = error.message;
267+
}
268+
res.status(500).json({
269+
error: errorMessage,
270+
});
271+
}
272+
}
273+
274+
async submitForPortalAction(req: Request, res: Response): Promise<void> {
275+
try {
276+
const { tokenId, savedForm, config } = req.body;
277+
278+
// TODO: Implement authentication/authorization when available
279+
280+
const result = await ICMService.submitForPortalAction({
281+
tokenId,
282+
savedForm,
283+
config,
284+
});
285+
286+
if (result.success) {
287+
res.status(200).json(result.data);
288+
} else {
289+
res.status(result.status || 500).json({ error: result.error });
290+
}
291+
} catch (error) {
292+
let errorMessage = 'Internal server error';
293+
if (error instanceof Error && error.message) {
294+
errorMessage = error.message;
295+
}
296+
res.status(500).json({
297+
error: errorMessage,
298+
});
299+
}
192300
}
193301

194-
generateNewTemplate(req: Request, res: Response): void {
195-
res.json({ endpoint: 'generateNewTemplate', payload: req.body });
302+
async saveFormData(req: Request, res: Response): Promise<void> {
303+
try {
304+
const {
305+
action,
306+
formState,
307+
groupState,
308+
formDefinition,
309+
metadata,
310+
items,
311+
sessionParams,
312+
} = req.body;
313+
314+
const authHeader = req.headers.authorization;
315+
const token = authHeader?.startsWith('Bearer ')
316+
? authHeader.substring(7)
317+
: authHeader;
318+
319+
const result = await ICMService.saveFormData(
320+
{
321+
action,
322+
formState,
323+
groupState,
324+
formDefinition,
325+
metadata,
326+
items,
327+
sessionParams,
328+
},
329+
token
330+
);
331+
332+
if (result.success) {
333+
res.status(200).json(result.data);
334+
} else {
335+
res.status(result.status || 500).json({ error: result.error });
336+
}
337+
} catch (error) {
338+
let errorMessage = 'Internal server error';
339+
if (error instanceof Error && error.message) {
340+
errorMessage = error.message;
341+
}
342+
res.status(500).json({
343+
error: errorMessage,
344+
});
345+
}
196346
}
197347
}
198348

server/api/controllers/router.ts

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@ const router = express.Router();
1212
router.post('/saveICMData', (req, res) =>
1313
CommunicationsController.saveICMData(req, res)
1414
);
15-
router.post('/saveForm', (req, res) =>
16-
CommunicationsController.saveData(req, res)
17-
);
1815
router.post('/generateForm', (req, res) =>
1916
CommunicationsController.generateForm(req, res)
2017
);
@@ -24,24 +21,33 @@ router.post('/editForm', (req, res) =>
2421
router.post('/loadICMData', (req, res) =>
2522
CommunicationsController.loadICMData(req, res)
2623
);
27-
router.post('/clearICMLockedFlag', (req, res) =>
28-
CommunicationsController.clearICMLockedFlag(req, res)
24+
router.post('/unlockICMData', (req, res) =>
25+
CommunicationsController.unlockICMData(req, res)
2926
);
3027
router.post('/loadSavedJson', (req, res) =>
3128
CommunicationsController.loadSavedJson(req, res)
3229
);
3330
router.post('/pdfRender/:pdfTemplateId', (req, res) =>
3431
CommunicationsController.pdfRender(req, res)
3532
);
36-
router.post('/generatePDFFromJson', (req, res) =>
37-
CommunicationsController.generatePDFFromJson(req, res)
38-
);
39-
router.post('/generateNewTemplate', (req, res) =>
40-
CommunicationsController.generateNewTemplate(req, res)
33+
router.post('/generatePortalForm', (req, res) =>
34+
CommunicationsController.generatePortalForm(req, res)
4135
);
4236
router.post('/loadPortalForm', (req, res) =>
4337
CommunicationsController.loadPortalForm(req, res)
4438
);
39+
router.post('/submitForPortalAction', (req, res) =>
40+
CommunicationsController.submitForPortalAction(req, res)
41+
);
42+
router.post('/loadBoundForm', (req, res) =>
43+
CommunicationsController.loadBoundForm(req, res)
44+
);
45+
router.post('/bindPreviewForm', (req, res) =>
46+
CommunicationsController.bindPreviewForm(req, res)
47+
);
48+
router.post('/saveFormData', (req, res) =>
49+
CommunicationsController.saveFormData(req, res)
50+
);
4551

4652
// Kiln Renderer Routes
4753
router.get('/view', (req, res) => RendererController.viewForm(req, res));

server/api/services/icm.client.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,34 @@ export class ICMClient {
252252
}
253253
}
254254

255+
async generatePortalForm(
256+
payload: Record<string, any>,
257+
originalServer?: string
258+
) {
259+
const url = (
260+
process.env.COMM_API_GENERATE_PORTAL_FORM_ENDPOINT_URL || ''
261+
).trim();
262+
if (!url) {
263+
throw new Error(
264+
'COMM_API_GENERATE_PORTAL_FORM_ENDPOINT_URL environment variable is required'
265+
);
266+
}
267+
268+
const timeout = parseInt(process.env.COMM_API_TIMEOUT || '30000', 10);
269+
270+
const headers: Record<string, string> = {
271+
'Content-Type': 'application/json',
272+
};
273+
if (originalServer) headers['X-Original-Server'] = originalServer;
274+
275+
try {
276+
const res = await axios.post(url, payload, { headers, timeout });
277+
return this.createJsonResponse(res);
278+
} catch (error) {
279+
return this.handleJsonError(error, 'generatePortalForm');
280+
}
281+
}
282+
255283
async loadPortalForm(
256284
payload: any,
257285
originalServer?: string
@@ -287,4 +315,33 @@ export class ICMClient {
287315
return this.handleJsonError(error, 'loadPortalForm');
288316
}
289317
}
318+
319+
async submitForPortalAction(payload: any): Promise<ICMJsonResponse> {
320+
try {
321+
const url = process.env.COMM_API_SUBMIT_TO_ACTION_ENDPOINT_URL;
322+
323+
if (!url) {
324+
throw new Error(
325+
'COMM_API_SUBMIT_TO_ACTION_ENDPOINT_URL environment variable is required'
326+
);
327+
}
328+
329+
const timeout = process.env.COMM_API_TIMEOUT
330+
? parseInt(process.env.COMM_API_TIMEOUT, 10)
331+
: 30000;
332+
333+
const headers: Record<string, string> = {
334+
'Content-Type': 'application/json',
335+
};
336+
337+
const response = await axios.post(url, payload, {
338+
headers,
339+
timeout,
340+
});
341+
342+
return this.createJsonResponse(response);
343+
} catch (error) {
344+
return this.handleJsonError(error, 'submitForPortalAction');
345+
}
346+
}
290347
}

0 commit comments

Comments
 (0)