Skip to content

Commit bd151f8

Browse files
Bug fix(#17041) US (#17042,17138)
1 parent ed1eea1 commit bd151f8

11 files changed

Lines changed: 242 additions & 171 deletions

File tree

infra/deploy_container_registry.bicep

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,49 +3,31 @@
33
targetScope = 'resourceGroup'
44

55
param environmentName string
6-
6+
77
var uniqueId = toLower(uniqueString(subscription().id, environmentName, resourceGroup().location))
88
var solutionName = 'cps-${padLeft(take(uniqueId, 12), 12, '0')}'
9-
9+
1010
var containerNameCleaned = replace('cr${solutionName }', '-', '')
11-
11+
1212
@description('Provide a location for the registry.')
1313
param location string = resourceGroup().location
14-
14+
1515
@description('Provide a tier of your Azure Container Registry.')
1616
param acrSku string = 'Basic'
17-
17+
1818
resource containerRegistry 'Microsoft.ContainerRegistry/registries@2021-09-01' = {
1919
name: containerNameCleaned
2020
location: location
2121
sku: {
2222
name: acrSku
2323
}
2424
properties: {
25-
adminUserEnabled: true
26-
dataEndpointEnabled: false
27-
networkRuleBypassOptions: 'AzureServices'
28-
networkRuleSet: {
29-
defaultAction: 'Allow'
30-
}
31-
policies: {
32-
quarantinePolicy: {
33-
status: 'disabled'
34-
}
35-
retentionPolicy: {
36-
status: 'enabled'
37-
days: 7
38-
}
39-
trustPolicy: {
40-
status: 'disabled'
41-
type: 'Notary'
42-
}
43-
}
4425
publicNetworkAccess: 'Enabled'
4526
zoneRedundancy: 'Disabled'
4627
}
4728
}
48-
29+
4930
output createdAcrName string = containerNameCleaned
5031
output createdAcrId string = containerRegistry.id
5132
output acrEndpoint string = containerRegistry.properties.loginServer
33+

src/ContentProcessorAPI/app/routers/contentprocessor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -517,5 +517,5 @@ async def delete_processed_file(
517517
return ContentResultDelete(
518518
status="Success" if deleted_file else "Failed",
519519
process_id=deleted_file.process_id if deleted_file else "",
520-
message="" if deleted_file else "This record no longer exists. Please refresh the page."
520+
message="" if deleted_file else "This record no longer exists. Please refresh."
521521
)

src/ContentProcessorWeb/config-overrides.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
const { override, addWebpackModuleRule, addWebpackResolve } = require('customize-cra');
22

3-
console.log('Applying config-overrides.js...');
4-
53
module.exports = override(
64
addWebpackModuleRule({
75
test: /\.md$/,

src/ContentProcessorWeb/src/Components/UploadContent/UploadFilesModal.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
import { Button } from "@fluentui/react-button";
1010
import { Field, ProgressBar, makeStyles } from "@fluentui/react-components";
1111
import { useDispatch, useSelector, shallowEqual } from "react-redux";
12-
import { fetchContentTableData, uploadFile } from "../../store/slices/leftPanelSlice";
12+
import { fetchContentTableData, setRefreshGrid, uploadFile } from "../../store/slices/leftPanelSlice";
1313
import { AppDispatch, RootState } from "../../store";
1414
import "./UploadFilesModal.styles.scss";
1515

@@ -164,6 +164,7 @@ const UploadFilesModal: React.FC<UploadFilesModalProps> = ({ open, onClose }) =>
164164
// Upload files
165165
const handleUpload = async () => {
166166
setUploading(true);
167+
let uploadCount = 0;
167168
try {
168169
const schema = store.schemaSelectedOption?.optionValue ?? "defaultSchema";
169170

@@ -172,12 +173,13 @@ const UploadFilesModal: React.FC<UploadFilesModalProps> = ({ open, onClose }) =>
172173

173174
try {
174175
await dispatch(uploadFile({ file, schema })).unwrap();
176+
uploadCount++;
175177
setUploadProgress((prev) => ({ ...prev, [file.name]: 100 })); // Set progress to 100% after upload
176178
} catch (error: any) {
177179
// Capture and log the error specific to the file
178180
setFileErrors((prev) => ({
179181
...prev,
180-
[file.name]: { message: error.message }
182+
[file.name]: { message: error }
181183
}));
182184
setUploadProgress((prev) => ({ ...prev, [file.name]: -1 })); // Optional: Indicate failure with -1 or another value
183185
}
@@ -186,17 +188,16 @@ const UploadFilesModal: React.FC<UploadFilesModalProps> = ({ open, onClose }) =>
186188
//console.error("Overall upload failed:", error);
187189
} finally {
188190
setUploading(false);
189-
// setFiles([]) // If you want to clear the files after upload
190191
setStartUpload(false);
191192
setUploadCompleted(true);
192193
if (fileInputRef.current) {
193194
fileInputRef.current.value = ''; // Reset the file input
194195
}
195-
dispatch(fetchContentTableData({ pageSize: store.pageSize, pageNumber: 1 })).unwrap();
196+
if (uploadCount > 0)
197+
dispatch(setRefreshGrid(true));
196198
}
197199
};
198200

199-
200201
const handleButtonClick = () => {
201202
fileInputRef.current?.click(); // Open file selector
202203
};

src/ContentProcessorWeb/src/Hooks/useConsoleSuppression.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,25 @@ import { useEffect } from "react";
22

33
// Custom hook to suppress console logs, warnings, and errors in localhost
44
const useConsoleSuppression = () => {
5+
6+
function toBoolean(value: unknown): boolean {
7+
return (window.location.hostname === "localhost") ? true : String(value).toLowerCase() === "true";
8+
}
9+
510
useEffect(() => {
6-
if (window.location.hostname !== "localhost" && process.env.REACT_APP_CONSOLE_LOG_ENABLED?.toLocaleLowerCase() != "true" ) {
11+
const isConsoleFlag = toBoolean(process.env.REACT_APP_CONSOLE_LOG_ENABLED);
12+
if (isConsoleFlag !== true) {
713
// Save the original console methods
814
const originalConsoleError = console.error;
915
const originalConsoleWarn = console.warn;
1016
const originalConsoleLog = console.log;
1117
const originalConsoleInfo = console.info;
1218

1319
// Suppress console methods
14-
console.error = () => {};
15-
console.warn = () => {};
16-
console.log = () => {};
17-
console.info = () => {};
20+
console.error = () => { };
21+
console.warn = () => { };
22+
console.log = () => { };
23+
console.info = () => { };
1824

1925
// Clean up when component unmounts
2026
return () => {

src/ContentProcessorWeb/src/Pages/DefaultPage/Components/ProcessQueueGrid/ProcessQueueGrid.tsx

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import AutoSizer from "react-virtualized-auto-sizer";
1313
import CustomCellRender from "./CustomCellRender";
1414
import { useDispatch, useSelector, shallowEqual } from 'react-redux';
1515
import { RootState, AppDispatch } from '../../../../store';
16-
import { setSelectedGridRow, deleteProcessedFile, fetchContentTableData } from '../../../../store/slices/leftPanelSlice';
16+
import { setSelectedGridRow, deleteProcessedFile } from '../../../../store/slices/leftPanelSlice';
1717
import useFileType from "../../../../Hooks/useFileType";
1818
import { Confirmation } from "../../../../Components/DialogComponent/DialogComponent.tsx";
1919
import { Item, TableRowData, ReactWindowRenderFnProps, GridComponentProps } from './ProcessQueueGridTypes.ts';
@@ -140,15 +140,13 @@ const ProcessQueueGrid: React.FC<GridComponentProps> = () => {
140140
}, [store.gridData])
141141

142142
useEffect(() => {
143-
console.log("selectedRows", selectedRows, items);
144143
if (items.length > 0 && selectedRows.size > 0) {
145144
const selectedRow = [...selectedRows][0];
146145
if (typeof selectedRow === 'number') {
147146
let selectedItem = items[selectedRow];
148147
if (!selectedItem) {
149148
setSelectedRows(new Set<TableRowId>([0]));
150149
} else {
151-
console.log("selectedItem", selectedItem);
152150
const findItem = getSelectedItem(selectedItem?.processId.label ?? '');
153151
dispatch(setSelectedGridRow({ processId: selectedItem?.processId.label, item: findItem }));
154152
}
@@ -289,9 +287,7 @@ const ProcessQueueGrid: React.FC<GridComponentProps> = () => {
289287
toggleDialog();
290288
await dispatch(deleteProcessedFile({ processId: selectedDeleteItem.processId.label ?? null }));
291289
} catch (error: any) {
292-
293-
} finally {
294-
dispatch(fetchContentTableData({ pageSize: store.pageSize, pageNumber: 1 })).unwrap();
290+
console.log("error : ", error)
295291
}
296292
}
297293
};
@@ -315,7 +311,7 @@ const ProcessQueueGrid: React.FC<GridComponentProps> = () => {
315311
size="medium"
316312
aria-label="Table with selection"
317313
aria-rowcount={rows.length}
318-
className="gridTable"
314+
className="gridTable"
319315
>
320316
<TableHeader>
321317
<TableRow aria-rowindex={1}>

src/ContentProcessorWeb/src/Pages/DefaultPage/PanelCenter.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,11 +167,13 @@ const PanelCenter: React.FC<PanelCenterProps> = ({ togglePanel }) => {
167167
try {
168168
dispatch(startLoader("1"));
169169
dispatch(setUpdateComments(comment))
170-
await dispatch(saveContentJson({ 'processId': store.activeProcessId, 'contentJson': store.modified_result.extracted_result, 'comments': comment, 'savedComments': store.comments }))
170+
const result = await dispatch(saveContentJson({ 'processId': store.activeProcessId, 'contentJson': store.modified_result.extracted_result, 'comments': comment, 'savedComments': store.comments }))
171+
if (result?.type === 'SaveContentJSON-Comments/fulfilled') {
172+
dispatch(setRefreshGrid(true));
173+
}
171174
} catch (error) {
172175
console.error('API Error:', error);
173176
} finally {
174-
dispatch(setRefreshGrid(true));
175177
dispatch(stopLoader("1"));
176178
}
177179
}

src/ContentProcessorWeb/src/Services/httpUtility.ts

Lines changed: 59 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
const api: string = process.env.REACT_APP_API_BASE_URL as string; // base API URL
44

55
// Define the types for the response
6-
interface ApiResponse<T = any> {
7-
data: T;
6+
interface FetchResponse<T> {
7+
data: T | null;
8+
status: number;
89
}
910

1011
interface FetchOptions {
@@ -13,47 +14,81 @@ interface FetchOptions {
1314
body?: string | FormData | null;
1415
}
1516

17+
export const handleApiThunk = async <T>(
18+
apiCall: Promise<{ data: T | null; status: number }>,
19+
rejectWithValue: (reason: any) => any,
20+
errorMessage = 'Request failed'
21+
): Promise<T | any> => {
22+
try {
23+
const response = await apiCall;
24+
console.log("API Response : ", response);
25+
if (response.status === 200 || response.status === 202) {
26+
return response.data;
27+
} else {
28+
return rejectWithValue(`${errorMessage}. Status: ${response.status}`);
29+
}
30+
} catch (error: any) {
31+
if (error.status == 415 || error.status == 404)
32+
return rejectWithValue(error.data.message || `Unexpected error: ${errorMessage}`);
33+
return rejectWithValue(error.message || `Unexpected error: ${errorMessage}`);
34+
}
35+
};
36+
37+
1638
// Fetch with JWT Authentication
17-
const fetchWithAuth = async <T>(url: string, method: string = 'GET', body: any = null): Promise<T | null> => {
18-
const token = localStorage.getItem('token'); // Get the token from localStorage
39+
40+
const fetchWithAuth = async <T>(
41+
url: string,
42+
method: string = 'GET',
43+
body: any = null
44+
): Promise<FetchResponse<T>> => {
45+
const token = localStorage.getItem('token');
1946

2047
const headers: HeadersInit = {
21-
'Authorization': `Bearer ${token}`, // Add the token to the Authorization header
22-
'Content-Type': 'application/json',
48+
'Authorization': `Bearer ${token}`,
2349
'Accept': 'application/json',
2450
'Cache-Control': 'no-cache',
2551
};
2652

27-
// If body is FormData, do not set Content-Type header
28-
if (body instanceof FormData) {
29-
delete headers['Content-Type'];
30-
} else {
53+
if (!(body instanceof FormData)) {
3154
headers['Content-Type'] = 'application/json';
3255
body = body ? JSON.stringify(body) : null;
3356
}
3457

35-
const options: FetchOptions = {
58+
const options: RequestInit = {
3659
method,
3760
headers,
3861
};
3962

4063
if (body) {
41-
options.body = body; // Add the body only if it exists (for POST, PUT)
64+
options.body = body;
4265
}
4366

4467
try {
4568
const response = await fetch(`${api}${url}`, options);
4669

70+
const status = response.status;
71+
const isJson = response.headers.get('content-type')?.includes('application/json');
72+
73+
const data = isJson ? await response.json() : null;
74+
4775
if (!response.ok) {
48-
const errorText = await response.text();
49-
throw new Error(errorText || 'Something went wrong');
76+
throw { data, status };
5077
}
5178

52-
const isJson = response.headers.get('content-type')?.includes('application/json');
53-
return isJson ? (await response.json()) as T : null;
79+
return { data, status };
5480
} catch (error: any) {
55-
//console.error('API Error:', error.message);
56-
throw error;
81+
if (error?.status !== undefined) {
82+
throw error;
83+
}
84+
const isNetworkError = error instanceof TypeError && error.message === 'Failed to fetch';
85+
const isOffline = !navigator.onLine; //isNetworkError ||
86+
87+
const message = isOffline
88+
? 'No internet connection. Please check your network and try again.'
89+
: 'Unable to connect to the server. Please try again later.';
90+
91+
throw { data: null, status: 0, message };
5792
}
5893
};
5994

@@ -133,13 +168,13 @@ const fetchWithoutAuth = async <T>(url: string, method: string = 'POST', body: a
133168

134169
// Authenticated requests (with token) and login (without token)
135170
export const httpUtility = {
136-
get: <T>(url: string): Promise<T | null> => fetchWithAuth<T>(url, 'GET'),
137-
post: <T>(url: string, body: any): Promise<T | null> => fetchWithAuth<T>(url, 'POST', body),
138-
put: <T>(url: string, body: any): Promise<T | null> => fetchWithAuth<T>(url, 'PUT', body),
139-
delete: <T>(url: string): Promise<T | null> => fetchWithAuth<T>(url, 'DELETE'),
140-
upload: <T>(url: string, formData: FormData): Promise<T | null> => fetchWithAuth<T>(url, 'POST', formData),
171+
get: <T>(url: string): Promise<{ data: T | null; status: number }> => fetchWithAuth<T>(url, 'GET'),
172+
post: <T>(url: string, body: any): Promise<{ data: T | null; status: number }> => fetchWithAuth<T>(url, 'POST', body),
173+
put: <T>(url: string, body: any): Promise<{ data: T | null; status: number }> => fetchWithAuth<T>(url, 'PUT', body),
174+
delete: <T>(url: string): Promise<{ data: T | null; status: number }> => fetchWithAuth<T>(url, 'DELETE'),
175+
upload: <T>(url: string, formData: FormData): Promise<{ data: T | null; status: number }> => fetchWithAuth<T>(url, 'POST', formData),
141176
login: <T>(url: string, body: any): Promise<T | null> => fetchWithoutAuth<T>(url, 'POST', body), // For login without auth
142-
headers : <T>(url: string): Promise<any> => fetchHeadersWithAuth<T>(url, 'GET'),
177+
headers: <T>(url: string): Promise<any> => fetchHeadersWithAuth<T>(url, 'GET'),
143178
};
144179

145180
export default httpUtility;

0 commit comments

Comments
 (0)