Skip to content

Commit

Permalink
Merge pull request #528 from microsoft/geearl/7045-show-processing-log
Browse files Browse the repository at this point in the history
Geearl/7045 show processing log
  • Loading branch information
georearl committed Mar 6, 2024
2 parents 2ecae68 + f0fbf19 commit dfdfa4c
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 21 deletions.
8 changes: 5 additions & 3 deletions app/backend/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
ResourceTypes,
generate_account_sas,
)
from shared_code.status_log import State, StatusClassification, StatusLog
from shared_code.status_log import State, StatusClassification, StatusLog, StatusQueryLevel
from shared_code.tags_helper import TagsHelper
from azure.cosmos import CosmosClient

Expand Down Expand Up @@ -279,8 +279,10 @@ async def get_all_upload_status(request: Request):
state = json_body.get("state")
folder = json_body.get("folder")
try:
results = statusLog.read_files_status_by_timeframe(timeframe, State[state],
folder, os.environ["AZURE_BLOB_STORAGE_UPLOAD_CONTAINER"])
results = statusLog.read_files_status_by_timeframe(timeframe,
State[state],
folder,
os.environ["AZURE_BLOB_STORAGE_UPLOAD_CONTAINER"])

# retrieve tags for each file
# Initialize an empty list to hold the tags
Expand Down
7 changes: 7 additions & 0 deletions app/frontend/src/api/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ export type FileUploadBasicStatus = {
start_timestamp: string;
state_description: string;
state_timestamp: string;
status_updates: StatusUpdates[];
}

export type StatusUpdates = {
status: string;
status_timestamp: string;
status_classification: string;
}

export type AllFilesUploadStatus = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,9 @@
text-overflow: clip; /* Clip text that overflows */
white-space: normal; /* Allow text to wrap */
}

.scrollableDialogContent {
max-height: 400px; /* Adjust the height as needed */
max-width: 400px; /* Adjust the width as needed */
overflow-y: auto; /* This enables vertical scrolling */
}
118 changes: 101 additions & 17 deletions app/frontend/src/components/FileStatus/DocumentsDetailList.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import React, { useState, useEffect, useRef } from "react";
import React, { useState, useEffect, useRef, useLayoutEffect } from "react";
import { DetailsList,
DetailsListLayoutMode,
SelectionMode,
Expand Down Expand Up @@ -30,6 +30,11 @@ export interface IDocument {
state_description: string;
upload_timestamp: string;
modified_timestamp: string;
status_updates: Array<{
status: string;
status_timestamp: string;
status_classification: string;
}>;
isSelected?: boolean; // Optional property to track selection state
}

Expand Down Expand Up @@ -139,19 +144,19 @@ export const DocumentsDetailList = ({ items, onFilesSorted}: Props) => {
// *************************************************************
// Delete processing
// New state for managing dialog visibility and selected items
const [isDialogVisible, setIsDialogVisible] = useState(false);
const [isDeleteDialogVisible, setIsDeleteDialogVisible] = useState(false);
const [selectedItemsForDeletion, setSelectedItemsForDeletion] = useState<IDocument[]>([]);

// Function to open the dialog with selected items
const showDeleteConfirmation = () => {
const selectedItems = selectionRef.current.getSelection() as IDocument[];
setSelectedItemsForDeletion(selectedItems);
setIsDialogVisible(true);
setIsDeleteDialogVisible(true);
};

// Function to handle actual deletion
const handleDelete = () => {
setIsDialogVisible(false);
setIsDeleteDialogVisible(false);
console.log("Items to delete:", selectedItemsForDeletion);
selectedItemsForDeletion.forEach(item => {
console.log(`Deleting item: ${item.name}`);
Expand Down Expand Up @@ -207,7 +212,60 @@ export const DocumentsDetailList = ({ items, onFilesSorted}: Props) => {
showResubmitConfirmation();
};


// ********************************************************************
// State detail dialog
const [stateDialogVisible, setStateDialogVisible] = useState(false);
const [stateDialogContent, setStateDialogContent] = useState<React.ReactNode>(null);
const scrollableContentRef = useRef<HTMLDivElement>(null);

// const onStateColumnClick = async (item: IDocument) => {
// try {
// //const text = await getTextForState(item);
// // const text = item.status_updates[0].status;
// const text = item.status_updates.map(update => update.status).join("\n");
// setStateDialogContent(text);
// setStateDialogVisible(true);
// } catch (error) {
// console.error("Error on state column click:", error);
// // Handle error here, perhaps show an error message to the user
// }
// };


const onStateColumnClick = (item: IDocument) => {
try {
const statusElements = item.status_updates.map((update, index) => (
<div key={index}>
<b>{update.status_timestamp}</b> - {update.status}
</div>
));
setStateDialogContent(statusElements);
setStateDialogVisible(true);
} catch (error) {
console.error("Error on state column click:", error);
// Handle error here, perhaps show an error message to the user
}
};


const dialogStyles = {
main: {
width: '400px', // Set the width to 400 pixels
maxWidth: '400px', // Set the maximum width to 400 pixels
maxHeight: '400px', // Set the maximum height to 400 pixels
overflowY: 'auto', // Enable vertical scrolling for the entire dialog if needed
},
};


useEffect(() => {
// Scroll to the top when the dialog opens
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' });
}, []);

// ********************************************************************


const [columns, setColumns] = useState<IColumn[]> ([
{
key: 'file_type',
Expand Down Expand Up @@ -251,11 +309,13 @@ export const DocumentsDetailList = ({ items, onFilesSorted}: Props) => {
ariaLabel: 'Column operations for state, Press to sort by states',
onColumnClick: onColumnClick,
data: 'string',
onRender: (item: IDocument) => (
<TooltipHost content={`${item.state} `}>
<span>{item.state}</span>
{item.state === 'Error' && <a href="javascript:void(0);" onClick={() => retryErroredFile(item)}> - Retry File</a>}
</TooltipHost>
onRender: (item: IDocument) => (
<TooltipHost content={`${item.state} `}>
<span onClick={() => onStateColumnClick(item)} style={{ cursor: 'pointer' }}>
{item.state}
</span>
{item.state === 'Error' && <a href="javascript:void(0);" onClick={() => retryErroredFile(item)}> - Retry File</a>}
</TooltipHost>
),
isPadded: true,
},
Expand All @@ -269,9 +329,12 @@ export const DocumentsDetailList = ({ items, onFilesSorted}: Props) => {
ariaLabel: 'Column operations for folder, Press to sort by folder',
onColumnClick: onColumnClick,
data: 'string',
onRender: (item: IDocument) => {
return <span>{item.filePath}</span>;
},
onRender: (item: IDocument) => (
<TooltipHost content={`${item.state} `}>
<span>{item.filePath.split('/').slice(1, -1).join('/')}</span>
{item.filePath === 'Error' && <a href="javascript:void(0);" onClick={() => retryErroredFile(item)}> Retry File</a>}
</TooltipHost>
),
isPadded: true,
},
{
Expand Down Expand Up @@ -322,7 +385,9 @@ export const DocumentsDetailList = ({ items, onFilesSorted}: Props) => {
onColumnClick: onColumnClick,
onRender: (item: IDocument) => (
<TooltipHost content={`${item.state_description} `}>
<span>{item.state}</span>
<span onClick={() => onStateColumnClick(item)} style={{ cursor: 'pointer' }}>
{item.state_description}
</span>
</TooltipHost>
)
}
Expand All @@ -348,8 +413,8 @@ export const DocumentsDetailList = ({ items, onFilesSorted}: Props) => {
<Button text="Resubmit" onClick={handleResubmitClick} />
{/* Dialog for delete confirmation */}
<Dialog
hidden={!isDialogVisible}
onDismiss={() => setIsDialogVisible(false)}
hidden={!isDeleteDialogVisible}
onDismiss={() => setIsDeleteDialogVisible(false)}
dialogContentProps={{
type: DialogType.normal,
title: 'Delete Confirmation',
Expand All @@ -362,7 +427,7 @@ export const DocumentsDetailList = ({ items, onFilesSorted}: Props) => {
>
<DialogFooter>
<PrimaryButton onClick={handleDelete} text="Delete" />
<DefaultButton onClick={() => setIsDialogVisible(false)} text="Cancel" />
<DefaultButton onClick={() => setIsDeleteDialogVisible(false)} text="Cancel" />
</DialogFooter>
</Dialog>
{/* Dialog for resubmit confirmation */}
Expand All @@ -387,6 +452,25 @@ export const DocumentsDetailList = ({ items, onFilesSorted}: Props) => {
<div>
<Notification message={notification.message} />
</div>
<Dialog
hidden={!stateDialogVisible}
onDismiss={() => setStateDialogVisible(false)}
dialogContentProps={{
type: DialogType.normal,
title: 'State Details',
closeButtonAriaLabel: 'Close',
}}
modalProps={{
styles: dialogStyles,
}}
>
<div className="scrollableDialogContent" ref={scrollableContentRef}>
{stateDialogContent}
</div>
<DialogFooter>
<PrimaryButton onClick={() => setStateDialogVisible(false)} text="OK" />
</DialogFooter>
</Dialog>
</div>
);
}
5 changes: 5 additions & 0 deletions app/frontend/src/components/FileStatus/FileStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,11 @@ export const FileStatus = ({ className }: Props) => {
state_description: fileList[i].state_description,
upload_timestamp: fileList[i].start_timestamp,
modified_timestamp: fileList[i].state_timestamp,
status_updates: fileList[i].status_updates.map(su => ({
status: su.status,
status_timestamp: su.status_timestamp,
status_classification: su.status_classification,
})),
value: fileList[i].id,
});
}
Expand Down
2 changes: 1 addition & 1 deletion functions/shared_code/status_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def read_files_status_by_timeframe(self,
"""

query_string = "SELECT c.id, c.file_path, c.file_name, c.state, \
c.start_timestamp, c.state_description, c.state_timestamp \
c.start_timestamp, c.state_description, c.state_timestamp, c.status_updates \
FROM c"

conditions = []
Expand Down

0 comments on commit dfdfa4c

Please sign in to comment.