Skip to content

Commit 3b0c7a9

Browse files
isuru-aotdivyav-aotdivyav-aotaurelio-aotjimin-aot
authored
RSBC - Form ID Allocation (#468)
* forms-flow-rsbcservices boilerplate initial commit, IndexedDB schema definition, staticDataApi related functions * Updated code with DBService exposed, fixed local run issues * installed formio related packages. * Updated the dbService code with fetchAndSaveStaticData() exposed * added error handling * deleted unnecessary files * updated the README.md * removed unnecesary codes * cleanedup and removed unnecessary codes * formsflow-rsbcservices initial setup and IndexedDB integration (#4) * forms-flow-rsbcservices boilerplate initial commit, IndexedDB schema definition, staticDataApi related functions * Updated code with DBService exposed, fixed local run issues * installed formio related packages. * Updated the dbService code with fetchAndSaveStaticData() exposed * added error handling * deleted unnecessary files * updated the README.md * removed unnecesary codes * cleanedup and removed unnecessary codes --------- Co-authored-by: divyav-aot <divyav-aot@github> * Updated fetchAndSaveStaticData() to only fetch and save data if the table is empty * Updated fetchAndSaveStaticData() to only fetch and save data if the table is empty (#5) * forms-flow-rsbcservices boilerplate initial commit, IndexedDB schema definition, staticDataApi related functions * Updated code with DBService exposed, fixed local run issues * installed formio related packages. * Updated the dbService code with fetchAndSaveStaticData() exposed * added error handling * deleted unnecessary files * updated the README.md * removed unnecesary codes * cleanedup and removed unnecessary codes * Updated fetchAndSaveStaticData() to only fetch and save data if the table is empty --------- Co-authored-by: divyav-aot <divyav-aot@github> * RSBCImage form.io custom component * Remove unneeded library * Updated the fetchAndSaveStaticData as it was not saving some of the static data * settings for rsbc image * Cleanup code * Add description on RSBCImage settings * Testing code to generate settings json * Add fields tracker * sample input output and settings * Update json converter * adding rsbcmapping json * RSBC mapping for VI 24Hr StageTwo * updated test data * added test data * rename sample test data * update test data * Fix code alignment. Add test data. * adding combined file * adding combined mapping with highlighting missing data * Fix bug * Update transformJson() logic * Fix RSBCImage placeholder * reverting package-lock.json in forms-flow-nav * removing hardcoded ips * removing hardcoded ips * reverting package-lock.json in forms-flow-nav * reverting package-lock.json in forms-flow-nav * updating file names * updating README.md * cleanup code * fix diff on package-lock.json * Add rsbc/7.0.0 branch to GitHub Actions and update version * Rename forms-flow-service to forms-flow-rsbcservice in GitHub Actions workflow * change folder structure * FOFR-35_Implementation_of_Keycloak_Token_Handling_in_Offline_Mode NOTE:- This PR has been created for review purposes only by the forms flow product team for inputs regarding this approach and not for any merging to any branch. Includes:- Handling token refresh while offine to avoid any page refresh which will display the "No Internet page" to the customer. * Put div with id on images * put div with id * base64 work * store svg images in this.component * fixing html issue * base64 png images * Refactor code * adding stage as a param to getBase64Images function * fixing RSBC Image Settings default \"\" emtpy quotation issue * updating invalid json error message * Add print button * Initial code on print button function * Print preview is perfect but losing image in main window * Extra page on print preview when 12Hour=true only * Fully working print button * Display Print button only in StageOne images * emit printResponse event * Refactored Printing Functionality * FOFR_35_Keycloak_fix_for_offline_page_refresh This checkin removes some redundant comments on the new code and also the commented earlier code. * FOFR-35_keycloak_offline_issue_fix Removes a comment inside the code * adding print confirmation dialog * Bug fix: images is gone when cancel button of the print confirmation dialog is clicked * Dont allow multiple instances of confirmation dialog box * Cleanup codes * Cleanup codes * Add descriptions on each functions * Update README.md * Optimize getTransformedInputData() function * Put div with id on images * put div with id * base64 work * store svg images in this.component * fixing html issue * base64 png images * Refactor code * adding stage as a param to getBase64Images function * fixing RSBC Image Settings default \"\" emtpy quotation issue * updating invalid json error message * Add print button * Initial code on print button function * Print preview is perfect but losing image in main window * Extra page on print preview when 12Hour=true only * Fully working print button * Display Print button only in StageOne images * emit printResponse event * Refactored Printing Functionality * adding print confirmation dialog * Bug fix: images is gone when cancel button of the print confirmation dialog is clicked * Dont allow multiple instances of confirmation dialog box * Cleanup codes * Cleanup codes * Add descriptions on each functions * Update README.md * Optimize getTransformedInputData() function * Address sonarqube issues * Fix sonarqube issues * Fix sonarqube issues * fixing issue 21 - member is never reassigned * fixing fill tag is not allowed issue * updating as -> AS to fix sonar issue * Fix sonarqube issues * Fix sonarqube issues * Address sonarqube issues * Fix sonarqube issues * Add .dockerignore * Fix sonarqube issues * Fix sonarqube issues * Fix sonarqube issues * Restore Dockerfile * Allow png and woff files to be uploaded to S3 * Form Definition, Draft and Submission changes related to offline (#12) * added FF related tables to indexedDB and corresponding functions * fixed reference error * initial commit: offline submission table changes * added null check for submissions and formData * updated and add functions for offline use * Split and refactor dbService.ts * Refactored, seperated out the RSBC and FF related tables * optimized the db service related codes * added index for the offlineSubmissions table, updated the code to fetch individualSubmission * fixed error related to DBService * formdefinition changes: initial commit * merge changes from rsbc/7.0.0 * refactored and fixed issues related to helper and DB services * updated README.md with new features --------- Co-authored-by: divyav-aot <divyav-aot@github> * Remove comment * brought the function comment back * adding functions for formIds * replaced math.Random() with crypto.getRandomValues to fix the security issue * files removed * removed commented lines to fix sonar cloud issues * changes to align with rsbc/7.0.0 * cleanup * addressing pr comments * updating const names * resolving pr issue * updating indexes * updating VERSION file --------- Co-authored-by: divyav-aot <divyav-aot@github> Co-authored-by: Divya Viswanath <79858022+divyav-aot@users.noreply.github.com> Co-authored-by: aurelio-aot <aurelio.pascual.jr@gmail.com> Co-authored-by: jimin-aot <jimin.byun@aot-technologies.com> Co-authored-by: sandeep-aot <89100322+sandeep-aot@users.noreply.github.com> Co-authored-by: Jimin Byun <148512774+jimin-aot@users.noreply.github.com> Co-authored-by: aurelio-aot <97022120+aurelio-aot@users.noreply.github.com> Co-authored-by: isuru <isuru.gnw@gmail.com>
1 parent 7000857 commit 3b0c7a9

File tree

8 files changed

+255
-5
lines changed

8 files changed

+255
-5
lines changed

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v7.0.0-rsbc
1+
v7.0.0-rsbc-v0.1

forms-flow-rsbcservice/src/constants/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ export const StaticResources = [
2929
'jurisdictionCountry'
3030
];
3131

32+
export const FormTypes = ["12Hour", "24Hour", "VI"];
33+
3234
export const TableMetadataMapping = Object.freeze({
3335
formList: { metadataTable: "formListMetaData", dataKey: "forms" },
3436
application: { metadataTable: "applicationMetaData", dataKey: "applications" },

forms-flow-rsbcservice/src/endpoints/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const API = {
44
GET_STATIC_DATA: `${RSBC_API_URL}/api/v1/static/<resource_name>`,
55
GET_USER_DATA: `${RSBC_API_URL}/api/v1/admin/users`,
66
GET_USER_ROLES_DATA: `${RSBC_API_URL}/api/v1/admin/users`,
7+
FORM_ID_ALLOCATION: `${RSBC_API_URL}/api/v1/forms`,
78
};
89

910
export default API;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { RequestService } from "@formsflow/service";
2+
import API from "../endpoints/index";
3+
import { createRequestHeader } from "./requestHeaders";
4+
5+
export const fetchFormIDs = async (
6+
payload: any,
7+
callback: (response: any) => void,
8+
errorHandler: (error: string) => void
9+
) => {
10+
const headers = await createRequestHeader();
11+
12+
RequestService.httpPOSTRequest(API.FORM_ID_ALLOCATION, payload)
13+
.then((res: any) => {
14+
if (res.data) {
15+
callback(res.data);
16+
} else {
17+
errorHandler(`No response received from ${API.FORM_ID_ALLOCATION}`);
18+
}
19+
})
20+
.catch((error: any) => {
21+
const errorMessage =
22+
error?.response?.data?.message || `Failed to fetch form IDs`;
23+
errorHandler(errorMessage);
24+
});
25+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const REACT_APP_FORM_ID_12HOUR_LIMIT = (window._env_ && window._env_.REACT_APP_FORM_ID_12HOUR_LIMIT) || 5;
2+
export const REACT_APP_FORM_ID_24HOUR_LIMIT = (window._env_ && window._env_.REACT_APP_FORM_ID_24HOUR_LIMIT) || 5;
3+
export const REACT_APP_FORM_ID_VI_LIMIT = (window._env_ && window._env_.REACT_APP_FORM_ID_VI_LIMIT) || 5;

forms-flow-rsbcservice/src/storage/dbFetchServices.ts

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { rsbcDb } from "./rsbcDb";
22
import { ffDb, IndividualFormDefinition } from "./ffDb";
33
import { StaticTables } from "../constants/constants";
44
import DBServiceHelper from "../helpers/helperDbServices";
5+
import { FormTypes } from "../constants/constants";
6+
57

68
class OfflineFetchService {
79

@@ -206,6 +208,115 @@ class OfflineFetchService {
206208
return { forms: [], limit: 5, pageNo: 1, totalCount: 0 };
207209
}
208210
}
209-
211+
212+
/**
213+
* Fetches the all form Ids data from the "formID" table in IndexedDB.
214+
*/
215+
public static async fetchFormIdDataFromTable(): Promise<any[]> {
216+
const tableName = "formID";
217+
try {
218+
if (!rsbcDb) throw new Error("IndexedDB is not available.");
219+
220+
await rsbcDb.open(); // Ensure the database is open
221+
222+
const table = rsbcDb[tableName];
223+
if (!table) throw new Error(`Table ${tableName} not found in IndexedDB.`);
224+
225+
const data = await table.toArray();
226+
if (!data.length) console.warn(`No data found in table ${tableName}.`);
227+
228+
return data;
229+
} catch (error) {
230+
console.error(`Error fetching data from table ${tableName}:`, error);
231+
throw error;
232+
}
233+
}
234+
235+
/**
236+
* Returns the unleased form IDs for a given form type.
237+
* @param formType - "12Hour", "24Hour", "VI"
238+
*/
239+
public static async getAvailableFormIds(formType: string): Promise<any[]> {
240+
try {
241+
if (!rsbcDb.formID) {
242+
throw new Error("FormID table is not available.");
243+
}
244+
if (!formType || !FormTypes.includes(formType)) {
245+
throw new Error(`Valid formTypes: ${FormTypes.join(", ")}`);
246+
}
247+
const unleasedForms = await rsbcDb.formID
248+
.where("form_type")
249+
.equals(formType)
250+
.filter(form => form.leased === false)
251+
.toArray();
252+
253+
return unleasedForms.map((form) => form.id);
254+
} catch (error) {
255+
console.error(`Error fetching available form IDs from IndexedDB:`, error);
256+
return [];
257+
}
258+
}
259+
260+
/**
261+
* Fetches the form availability data from the "formID" table in IndexedDB.
262+
* @param formType - "12Hour", "24Hour", "VI"
263+
*/
264+
public static async getNextAvailabeFormId(formType: string): Promise<string | null> {
265+
try {
266+
if (!rsbcDb.formID) {
267+
throw new Error("FormID table is not available.");
268+
}
269+
270+
if (!formType || !FormTypes.includes(formType)) {
271+
throw new Error(`Valid formTypes: ${FormTypes.join(", ")}`);
272+
}
273+
274+
const topUnleasedForm = await rsbcDb.formID
275+
.where("form_type")
276+
.equals(formType)
277+
.and(form => form.leased === false)
278+
.sortBy("last_updated")
279+
.then(forms => forms[0]);
280+
281+
return topUnleasedForm ? topUnleasedForm.id : null;
282+
} catch (error) {
283+
console.error(`Error fetching next available form ID from IndexedDB:`, error);
284+
return null;
285+
}
286+
}
287+
288+
/**
289+
* Fetches the form unleased Ids data from the "formID" table in IndexedDB.
290+
* @return [{"form_type": string, "count": number}]
291+
*/
292+
public static async getFormAvailability(): Promise<{ form_type: string; count: number }[]> {
293+
try {
294+
if (!rsbcDb.formID) {
295+
throw new Error("FormID table is not available.");
296+
}
297+
298+
const unleasedForms = await rsbcDb.formID
299+
.filter(form => form.leased === false)
300+
.toArray();
301+
302+
const formTypeCounts: { [key: string]: number } = {};
303+
unleasedForms.forEach(form => {
304+
formTypeCounts[form.form_type] = (formTypeCounts[form.form_type] || 0) + 1;
305+
});
306+
307+
const result = Object.entries(formTypeCounts)
308+
.map(([form_type, count]) => ({
309+
form_type,
310+
count
311+
})
312+
);
313+
314+
return result;
315+
} catch (error) {
316+
console.error(`Error fetching form availability from IndexedDB:`, error);
317+
return [];
318+
}
319+
}
320+
210321
}
211322
export default OfflineFetchService;

forms-flow-rsbcservice/src/storage/dbInsertServices.ts

Lines changed: 106 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import { handleError } from "../helpers/helperServices";
55
import { StaticResources } from "../constants/constants";
66
import OfflineFetchService from "./dbFetchServices";
77
import DBServiceHelper from "../helpers/helperDbServices";
8+
import { fetchFormIDs } from "../request/formIdApi";
9+
import { REACT_APP_FORM_ID_12HOUR_LIMIT, REACT_APP_FORM_ID_24HOUR_LIMIT, REACT_APP_FORM_ID_VI_LIMIT } from "./config";
810

911
class OfflineSaveService {
1012

@@ -211,7 +213,109 @@ class OfflineSaveService {
211213
} catch (error) {
212214
console.error(`Error processing offline submission or application data:`, error);
213215
}
214-
}
215-
216+
}
217+
218+
/**
219+
* Calculates the how many new form IDs are required and fetches them from the server
220+
* and save them to the IndexedDB with leased status as false.
221+
*/
222+
public static async fetchAndSaveFormIDs(): Promise<any> {
223+
try {
224+
if (!rsbcDb.formID) {
225+
throw new Error("IndexedDB formID table is not available.");
226+
}
227+
const existingFormIds = await rsbcDb.formID.toArray();
228+
const countByFormType = existingFormIds.reduce((acc, obj) => {
229+
if (!obj.leased) {
230+
acc[obj.form_type] = (acc[obj.form_type] || 0) + 1;
231+
}
232+
return acc;
233+
}, {});
234+
235+
const required12Hour = Math.max(0, REACT_APP_FORM_ID_12HOUR_LIMIT - (countByFormType["12Hour"] || 0));
236+
const required24Hour = Math.max(0, REACT_APP_FORM_ID_24HOUR_LIMIT - (countByFormType["24Hour"] || 0));
237+
const requiredVI = Math.max(0, REACT_APP_FORM_ID_VI_LIMIT - (countByFormType["VI"] || 0));
238+
try {
239+
const requiredIds = {
240+
"12Hour": required12Hour,
241+
"24Hour": required24Hour,
242+
"VI": requiredVI,
243+
};
244+
245+
await fetchFormIDs(
246+
requiredIds,
247+
async (data: any) => {
248+
const formIdData = data.forms.map((item: any) => ({
249+
id: item.id,
250+
form_type: item.form_type,
251+
user_guid: item.user_guid,
252+
leased: false,
253+
lease_expiry: item.lease_expiry,
254+
printed_timestamp: item.printed_timestamp,
255+
spoiled_timestamp: item.spoiled_timestamp,
256+
last_updated: new Date().toISOString(),
257+
}));
258+
if(formIdData && formIdData.length > 0){
259+
await this._saveForIdDataToIndexedDB(formIdData);
260+
}
261+
},
262+
(error: any) => {
263+
console.error("Error loading formIDs from the server:", error);
264+
return [];
265+
}
266+
);
267+
} catch (error) {
268+
console.error(`Error saving formIDs to indexed db:`, error);
269+
}
270+
if (existingFormIds.length === 0) {
271+
console.log(`No data found in table form_id.`);
272+
}
273+
const latestIds = await rsbcDb.formID.toArray();
274+
return latestIds;
275+
} catch (error) {
276+
console.error(`Error fetching data from table form_id:`, error);
277+
throw error;
278+
}
279+
}
280+
281+
/**
282+
* Marks a form as leased in IndexedDB.
283+
* @param formId - The form ID.
284+
* @param formType - The form type.
285+
*/
286+
public static async markFormAsLeased(formId: number, formType: string): Promise<void> {
287+
try {
288+
if (!rsbcDb.formID) {
289+
throw new Error("FormID table is not available.");
290+
}
291+
const form = await rsbcDb.formID.where({ id: formId, form_type: formType }).first();
292+
if (!form) {
293+
throw new Error(`Form with ID ${formId} and type ${formType} not found.`);
294+
}
295+
await rsbcDb.formID.update(form.id, { leased: true, last_updated: new Date().toISOString() });
296+
} catch (error) {
297+
console.error(`Error updating lease status in IndexedDB:`, error);
298+
}
299+
}
300+
301+
/**
302+
* private function to save formID data to IndexedDB.
303+
* @param data - list of formID data to be saved.
304+
* @private
305+
*/
306+
private static async _saveForIdDataToIndexedDB(data: any) : Promise<void> {
307+
try {
308+
if (!rsbcDb) {
309+
throw new Error("IndexedDB is not available.");
310+
}
311+
if (!data || data.length === 0) {
312+
throw new Error(`No valid data provided for formID.`);
313+
}
314+
await rsbcDb.formID.bulkPut(data);
315+
} catch (error) {
316+
console.error(`Error saving formID to IndexedDB:`, error);
317+
}
318+
}
319+
216320
}
217321
export default OfflineSaveService;

forms-flow-rsbcservice/src/storage/rsbcDb.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ interface FormID {
8383
form_type: string;
8484
user_guid: string;
8585
leased: boolean;
86+
lease_expiry: string;
87+
printed_timestamp: string;
88+
spoiled_timestamp: string;
89+
last_updated: string;
8690
}
8791

8892
interface VehicleType {
@@ -142,7 +146,7 @@ class DigitalFormsDB extends Dexie {
142146
countries: "id, objectCd, objectDsc",
143147
cities: "id, objectCd, objectDsc",
144148
agencies: "id, vjur, agency_name",
145-
formID: "id, form_type, user_guid, leased, [form_type+leased]",
149+
formID: "id, form_type, leased, [form_type+leased], last_updated, user_guid",
146150
vehicleTypes: "type_cd, description",
147151
});
148152

0 commit comments

Comments
 (0)