Skip to content

Commit 237acd8

Browse files
authored
Logo update and FOFR-60 (#469)
Logo update and FOFR-60 (#469)
1 parent 3b0c7a9 commit 237acd8

File tree

3 files changed

+216
-16
lines changed

3 files changed

+216
-16
lines changed

forms-flow-nav/src/sidenav/Sidebar.jsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -238,13 +238,16 @@ const Sidebar = React.memo(({ props, sidenavHeight="100%" }) => {
238238
return (
239239
<div className="sidenav" style={{ height: sidenavHeight }}>
240240
<div className="logo-container">
241-
{/* <img
242-
className=""
243-
src={Appname}
241+
{APPLICATION_NAME === "roadsafety" ? (
242+
<img
243+
width="160"
244+
height="auto"
245+
src="/RoadsafteyLogo.png"
244246
alt="applicationName"
245-
data-testid="app-logo"
246-
/> */}
247+
/>
248+
) : (
247249
<ApplicationLogo data-testid="application-logo" />
250+
)}
248251
</div>
249252
<div className="options-container" data-testid="options-container">
250253
<Accordion activeKey={activeKey} onSelect={(key) => setActiveKey(key)}>

forms-flow-nav/src/sidenav/hamburgerMenu.jsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import Sidebar from "./Sidebar";
1010
// import hamburger from "./hamburger.svg";
1111
// import closebutton from "./closebutton.svg";
1212
import { HamburgerIcon, CloseIcon, ApplicationLogo } from "@formsflow/components";
13+
import { APPLICATION_NAME } from "../constants/constants";
1314
function HamburgerMenu({ props }) {
1415
const [show, setShow] = useState(false);
1516
const handleClose = () => setShow(false);
@@ -29,8 +30,16 @@ function HamburgerMenu({ props }) {
2930
<HamburgerIcon data-testid="hamburger-button" aria-label="hamburger button" color={getComputedStyle(document.documentElement).getPropertyValue("--ff-gray-800")} />
3031
</button>
3132
<Navbar.Brand href="" className="mx-auto">
32-
{/* <img className="" src={Appname} alt="applicationName" /> */}
33-
<ApplicationLogo data-testid="application-logo" />
33+
{APPLICATION_NAME === "roadsafety" ? (
34+
<img
35+
width="160"
36+
height="auto"
37+
src="/RoadsafteyLogo.png"
38+
alt="applicationName"
39+
/>
40+
) : (
41+
<ApplicationLogo data-testid="application-logo" />
42+
)}
3443
</Navbar.Brand>
3544
<Navbar.Collapse id="basic-navbar-nav" className="order-2">
3645
<Nav className="me-auto">

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

Lines changed: 197 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@ import { StaticTables } from "../constants/constants";
44
import DBServiceHelper from "../helpers/helperDbServices";
55
import { FormTypes } from "../constants/constants";
66

7+
interface TableFilter {
8+
column: string;
9+
condition: "=" | "IN" | "LIKE";
10+
values: string | string[];
11+
}
12+
13+
interface UpdateFilter {
14+
conditions: Record<string, any>; // Object with search conditions
15+
updates: Record<string, any>; // Object with updates to make
16+
}
717

818
class OfflineFetchService {
919

@@ -12,29 +22,207 @@ class OfflineFetchService {
1222
* Ensures that the table is within the predefined static tables list.
1323
*
1424
* @param tableName - Name of the table to fetch data from.
25+
* @param filter - Optional filter object for filtering results
26+
* @param filter.column - The column name to filter on
27+
* @param filter.condition - The condition to apply ("=" | "IN" | "LIKE")
28+
* @param filter.values - The value(s) to filter by. String for "=" and "LIKE", string[] for "IN"
1529
* @returns A promise that resolves to an array of records from the table.
1630
* @throws Error if IndexedDB is unavailable, the table is inaccessible, or data retrieval fails.
1731
*/
18-
public static async fetchStaticDataFromTable(tableName: string): Promise<any[]> {
32+
public static async fetchStaticDataFromTable(
33+
tableName: string,
34+
filter?: TableFilter
35+
): Promise<any[]> {
1936
try {
2037
if (!rsbcDb) throw new Error("IndexedDB is not available.");
21-
if (!StaticTables.includes(tableName)) throw new Error(`Table ${tableName} is not accessible.`);
22-
38+
if (!StaticTables.includes(tableName))
39+
throw new Error(`Table ${tableName} is not accessible.`);
40+
2341
await rsbcDb.open(); // Ensure the database is open
24-
42+
2543
const table = rsbcDb[tableName];
26-
if (!table) throw new Error(`Table ${tableName} not found in IndexedDB.`);
27-
28-
const data = await table.toArray();
29-
if (!data.length) console.warn(`No data found in table ${tableName}.`);
30-
44+
if (!table) {
45+
throw new Error(`Table ${tableName} not found in IndexedDB.`);
46+
}
47+
48+
// Validate filter if provided
49+
if (filter) {
50+
if (!filter.column || !filter.condition) {
51+
throw new Error("Invalid filter: missing required properties");
52+
}
53+
54+
if (filter.condition === "IN" && !Array.isArray(filter.values)) {
55+
throw new Error("Values must be an array for IN condition");
56+
}
57+
}
58+
59+
let data: any[] = [];
60+
if (filter) {
61+
const { column, condition, values } = filter;
62+
63+
switch (condition) {
64+
case "=":
65+
data = await table.where(column).equals(values).toArray();
66+
break;
67+
68+
case "IN":
69+
data = await table
70+
.where(column)
71+
.anyOf(values as string[])
72+
.toArray();
73+
break;
74+
75+
case "LIKE":
76+
if (typeof values !== "string") {
77+
throw new Error("Values must be a string for LIKE condition");
78+
}
79+
const allData = await table.toArray();
80+
data = allData.filter((item) => {
81+
const itemValue = String(item[column] || "").toLowerCase();
82+
const searchValue = String(values || "").toLowerCase();
83+
return itemValue.includes(searchValue);
84+
});
85+
break;
86+
87+
default:
88+
throw new Error(`Unsupported condition: ${condition}`);
89+
}
90+
} else {
91+
data = await table.toArray();
92+
}
93+
94+
if (!data.length) {
95+
console.warn(`No data found in table ${tableName}.`);
96+
}
97+
3198
return data;
3299
} catch (error) {
33100
console.error(`Error fetching data from table ${tableName}:`, error);
34101
throw error;
35102
}
36103
}
37104

105+
/**
106+
* Updates data in a static table in IndexedDB.
107+
* Ensures that the table is within the predefined static tables list.
108+
*
109+
* @param tableName - Name of the table to update data in
110+
* @param filter - Filter object for updating records
111+
* @param filter.conditions - Object with conditions to match records (e.g., {id: 3} or {date: "1990-12-12", status: "new"})
112+
* @param filter.updates - Object with updates to make (e.g., {status: "completed"})
113+
* @returns A promise that resolves to the number of updated records
114+
* @throws Error if IndexedDB is unavailable, the table is inaccessible, or update fails.
115+
*/
116+
public static async updateStaticDataTable(
117+
tableName: string,
118+
filter: UpdateFilter
119+
): Promise<number> {
120+
try {
121+
if (!rsbcDb) {
122+
throw new Error("IndexedDB is not available.");
123+
}
124+
if (!StaticTables.includes(tableName)) {
125+
throw new Error(`Table ${tableName} is not accessible.`);
126+
}
127+
128+
await rsbcDb.open(); // Ensure the database is open
129+
130+
// Get table using Dexie's table() method
131+
const table = rsbcDb.table(tableName);
132+
if (!table) {
133+
throw new Error(`Table ${tableName} not found in IndexedDB.`);
134+
}
135+
136+
// Validate filter
137+
if (
138+
!filter?.conditions ||
139+
!filter?.updates ||
140+
Object.keys(filter.conditions).length === 0 ||
141+
Object.keys(filter.updates).length === 0
142+
) {
143+
throw new Error(
144+
"Invalid filter: conditions and updates are required and must not be empty"
145+
);
146+
}
147+
148+
// Get all records first
149+
const allRecords = await table.toArray();
150+
151+
// Filter records that match ALL conditions
152+
const recordsToUpdate = allRecords.filter((record) => {
153+
return Object.entries(filter.conditions).every(
154+
([key, value]) => record[key] === value
155+
);
156+
});
157+
158+
// Update each record with all specified updates
159+
const updatePromises = recordsToUpdate.map(async (record) => {
160+
// Apply all updates to the record
161+
Object.entries(filter.updates).forEach(([key, value]) => {
162+
record[key] = value;
163+
});
164+
return await table.put(record);
165+
});
166+
167+
await Promise.all(updatePromises);
168+
const updateCount = recordsToUpdate.length;
169+
170+
if (updateCount === 0) {
171+
console.warn(`No records updated in table ${tableName}.`);
172+
}
173+
174+
return updateCount;
175+
} catch (error) {
176+
console.error(`Error updating data in table ${tableName}:`, error);
177+
throw error;
178+
}
179+
}
180+
181+
/**
182+
* Creates a new record in a static table in IndexedDB.
183+
* Ensures that the table is within the predefined static tables list.
184+
*
185+
* @param tableName - Name of the table to create data in
186+
* @param data - The data object to insert into the table
187+
* @returns A promise that resolves to the id of the created record
188+
* @throws Error if IndexedDB is unavailable, the table is inaccessible, or creation fails.
189+
*/
190+
public static async insertStaticDataTable(
191+
tableName: string,
192+
data: any
193+
): Promise<any> {
194+
try {
195+
if (!rsbcDb) {
196+
throw new Error("IndexedDB is not available.");
197+
}
198+
if (!StaticTables.includes(tableName)) {
199+
throw new Error(`Table ${tableName} is not accessible.`);
200+
}
201+
202+
await rsbcDb.open(); // Ensure the database is open
203+
204+
const table = rsbcDb.table(tableName);
205+
if (!table) {
206+
throw new Error(`Table ${tableName} not found in IndexedDB.`);
207+
}
208+
209+
// Validate data
210+
if (!data || Object.keys(data).length === 0) {
211+
throw new Error(
212+
"Invalid data: data object is required and must not be empty"
213+
);
214+
}
215+
216+
// Add the record to the table
217+
const id = await table.add(data);
218+
219+
return id;
220+
} catch (error) {
221+
console.error(`Error creating data in table ${tableName}:`, error);
222+
throw error;
223+
}
224+
}
225+
38226
/**
39227
* Fetches a specific offline form by its ID from the formDefinition table.
40228
*

0 commit comments

Comments
 (0)