Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
Original file line number Diff line number Diff line change
Expand Up @@ -143,21 +143,31 @@ export class DocumentProcessorController {
throw new BadRequestException(`Report with ID ${reportId} has no associated file`);
}

// Update report status to IN_PROGRESS before starting async processing
report.processingStatus = ProcessingStatus.IN_PROGRESS;
report.updatedAt = new Date().toISOString();
await this.reportsService.updateReport(report);
let message = '';

// Start async processing in background
this.processReportAsync(reportId, userId, report.filePath).catch(error => {
this.logger.error(`Async processing failed for report ${reportId}: ${error.message}`);
});
if (report.processingStatus === ProcessingStatus.IN_PROGRESS) {
message = 'Document processing is already in progress. Please check the report status.';
} else if (report.processingStatus === ProcessingStatus.PROCESSED) {
message = 'Document has already been processed. No further action is needed.';
} else {
message = 'Document processing started. Check the report status to know when it completes.';

// Update report status to IN_PROGRESS before starting async processing
report.processingStatus = ProcessingStatus.IN_PROGRESS;
report.updatedAt = new Date().toISOString();
await this.reportsService.updateReport(report);

// Start async processing in background
this.processReportAsync(reportId, userId, report.filePath).catch(error => {
this.logger.error(`Async processing failed for report ${reportId}: ${error.message}`);
});
}

return {
success: true,
reportId: report.id,
status: ProcessingStatus.IN_PROGRESS,
message: 'Document processing started. Check the report status to know when it completes.',
status: report.processingStatus,
message,
};
} catch (error: unknown) {
this.logger.error(
Expand Down
19 changes: 19 additions & 0 deletions backend/src/iac/backend-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,18 @@ export class BackendStack extends cdk.Stack {
},
});

const deleteReportIntegration = new apigateway.Integration({
type: apigateway.IntegrationType.HTTP_PROXY,
integrationHttpMethod: 'DELETE',
uri: `${serviceUrl}/api/reports/{id}`,
options: {
...integrationOptions,
requestParameters: {
'integration.request.path.id': 'method.request.path.id',
},
},
});

const patchReportStatusIntegration = new apigateway.Integration({
type: apigateway.IntegrationType.HTTP_PROXY,
integrationHttpMethod: 'PATCH',
Expand Down Expand Up @@ -517,6 +529,13 @@ export class BackendStack extends cdk.Stack {
},
});

reportIdResource.addMethod('DELETE', deleteReportIntegration, {
...methodOptions,
requestParameters: {
'method.request.path.id': true,
},
});

reportStatusResource.addMethod('PATCH', patchReportStatusIntegration, {
...methodOptions,
requestParameters: {
Expand Down
20 changes: 20 additions & 0 deletions backend/src/reports/reports.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
UnauthorizedException,
Post,
NotFoundException,
Delete,
} from '@nestjs/common';
import {
ApiTags,
Expand Down Expand Up @@ -192,6 +193,25 @@ export class ReportsController {
return this.reportsService.saveReport(filePath, userId, originalFilename, fileSize);
}

@ApiOperation({ summary: 'Delete a report' })
@ApiResponse({
status: 200,
description: 'Report deleted successfully',
})
@ApiResponse({
status: 404,
description: 'Report not found',
})
@ApiParam({
name: 'id',
description: 'Report ID',
})
@Delete(':id')
async deleteReport(@Param('id') id: string, @Req() request: RequestWithUser): Promise<void> {
const userId = this.extractUserId(request);
await this.reportsService.deleteReport(id, userId);
}

private extractUserId(request: RequestWithUser): string {
// The user object is attached to the request by our middleware
const user = request.user;
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/common/utils/i18n/resources/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@
"pages": {
"chat": {
"title": "AI Assistant"
},
"upload": {
"title": "Upload Report"
}
}
}
7 changes: 4 additions & 3 deletions frontend/src/pages/Reports/ReportDetailPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,13 @@ const ReportDetailPage: React.FC = () => {

// Handle close button
const handleClose = () => {
history.goBack();
history.push('/tabs/home');
};

// Handle action buttons
const handleDiscard = () => {
history.goBack();
const handleDiscard = async () => {
await axios.delete(`${API_URL}/api/reports/${reportId}`, await getAuthConfig());
history.push('/tabs/home');
};

const handleNewUpload = () => {
Expand Down
12 changes: 7 additions & 5 deletions frontend/src/pages/Reports/components/AiAnalysisTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,13 @@ const AiAnalysisTab: React.FC<AiAnalysisTabProps> = ({
{isLowConfidence && <LowConfidenceNotice />}

{/* Flagged values section */}
<FlaggedValuesSection
flaggedValues={flaggedValues}
isExpanded={flaggedValuesExpanded}
onToggle={toggleFlaggedValues}
/>
{flaggedValues && (
<FlaggedValuesSection
flaggedValues={flaggedValues}
isExpanded={flaggedValuesExpanded}
onToggle={toggleFlaggedValues}
/>
)}

{/* Normal values section */}
<NormalValuesSection
Expand Down
25 changes: 13 additions & 12 deletions frontend/src/pages/Upload/UploadPage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonButton } from '@ionic/react';
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar } from '@ionic/react';
import { useTranslation } from 'react-i18next';
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { useHistory } from 'react-router-dom';
import UploadModal from 'common/components/Upload/UploadModal';

Expand All @@ -10,7 +10,7 @@ import UploadModal from 'common/components/Upload/UploadModal';
*/
const UploadPage = (): JSX.Element => {
const { t } = useTranslation();
const [isModalOpen, setIsModalOpen] = useState(false);
const [isModalOpen, setIsModalOpen] = useState(true);
const history = useHistory();

const handleUploadComplete = () => {
Expand All @@ -21,6 +21,16 @@ const UploadPage = (): JSX.Element => {
history.push('/tabs/home');
};

useEffect(() => {
// Automatically open the upload modal when the component mounts
setIsModalOpen(true);

// Cleanup function to close the modal when the component unmounts
return () => {
setIsModalOpen(false);
};
}, []);

return (
<IonPage>
<IonHeader>
Expand All @@ -29,15 +39,6 @@ const UploadPage = (): JSX.Element => {
</IonToolbar>
</IonHeader>
<IonContent>
<div className="ion-padding">
<h1>{t('pages.upload.subtitle')}</h1>
<p>{t('pages.upload.description')}</p>

<IonButton expand="block" className="ion-margin-top" onClick={() => setIsModalOpen(true)}>
{t('upload.selectFile')}
</IonButton>
</div>

<UploadModal
isOpen={isModalOpen}
onClose={() => setIsModalOpen(false)}
Expand Down
Loading