diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 0a759278..f0ec3a57 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -153,7 +153,7 @@ jobs: gptDeploymentCapacity="30" \ aiServiceLocation="${{ env.AZURE_LOCATION }}" \ imageTag="latest" \ - tags="{'CreatedBy':'Pipeline', 'SecurityControl':'Ignore','Purpose':'Deploying and Cleaning Up Resources for Validation','CreatedDate':'$current_date'}" \ + tags="{'CreatedBy':'Pipeline', 'Purpose':'Deploying and Cleaning Up Resources for Validation','CreatedDate':'$current_date'}" \ --query "properties.outputs" -o json); then echo "❌ Deployment failed. See logs above." exit 1 diff --git a/docs/DeploymentGuide.md b/docs/DeploymentGuide.md index ab3d316d..026b69d0 100644 --- a/docs/DeploymentGuide.md +++ b/docs/DeploymentGuide.md @@ -132,7 +132,7 @@ You can run this solution in [VS Code Dev Containers](https://code.visualstudio.
- Option 3:Deploy in Visual Studio Code (WEB) + Option 3: Deploy in Visual Studio Code (WEB) ### Visual Studio Code (WEB) @@ -313,7 +313,7 @@ When creating your environment name, follow these rules: - **No special characters** (-, _, spaces, etc.) - **Examples:** `cpsapp01`, `mycontentapp`, `devtest123` -> **💡 Tip:** Use a descriptive prefix + environment + suffix to form a a unique string +> **💡 Tip:** Use a descriptive prefix + environment + suffix to form a unique string #### Deployment Steps @@ -435,47 +435,6 @@ When creating your environment name, follow these rules: 2. **Add Authentication Provider** - Follow steps in [App Authentication](./ConfigureAppAuthentication.md) to configure authentication in app service. Note that Authentication changes can take up to 10 minutes. -## Known Issues - -**Unable to update/add environment variables in Azure Container Apps** - -You may encounter issues when attempting to modify environment variables or container configuration in Azure Container Apps: - -**Affected Scenarios:** -- **App Authentication Setup:** When adding authentication-related environment variables (CRUD operations on env variables) -- **Container Configuration:** When trying to edit ACR name, image, or tag information for Container Apps - -**Root Cause:** -This is an ongoing issue in Azure that affects the Azure Portal's ability to update Container Apps configurations. - -**Workaround - Use Azure CLI:** - -Until this issue is resolved, use Azure CLI commands to add or update environment variables and container configurations: - -**For Environment Variables:** -```bash -# Update environment variables -az containerapp update \ - --name \ - --resource-group \ - --set-env-vars "KEY1=value1" "KEY2=value2" -``` - -**For Container Image Updates:** -```bash -# Update container image -az containerapp update \ - --name \ - --resource-group \ - --image /: -``` - -📖 **Detailed CLI Documentation:** -- [Manage environment variables](https://learn.microsoft.com/en-us/azure/container-apps/environment-variables?tabs=cli) -- [Manage revisions](https://learn.microsoft.com/en-us/azure/container-apps/revisions-manage?tabs=bash) - -> **Note:** This is a temporary workaround. The documentation will be updated once the Azure Portal issue is resolved. - ## Deployment Success Validation After deployment completes, use this checklist to verify everything is working correctly: diff --git a/src/ContentProcessor/src/libs/azure_helper/model/content_understanding.py b/src/ContentProcessor/src/libs/azure_helper/model/content_understanding.py index 4ddf96af..87a7d9a5 100644 --- a/src/ContentProcessor/src/libs/azure_helper/model/content_understanding.py +++ b/src/ContentProcessor/src/libs/azure_helper/model/content_understanding.py @@ -19,6 +19,7 @@ class Word(BaseModel): polygon: Optional[List[float]] = None @field_validator("polygon", mode="after") + @classmethod def parse_polygon(cls, value, info: ValidationInfo): """ Providing comparability with Azure Documenent Document Intelligence Service API result. @@ -51,6 +52,7 @@ class Line(BaseModel): polygon: Optional[List[float]] = None @field_validator("polygon", mode="after") + @classmethod def parse_polygon(cls, value, info: ValidationInfo): source_str = info.data.get("source", "") if source_str.startswith("D(") and source_str.endswith(")"): @@ -73,6 +75,7 @@ class Paragraph(BaseModel): polygon: Optional[List[float]] = None @field_validator("polygon", mode="after") + @classmethod def parse_polygon(cls, value, info: ValidationInfo): source_str = info.data.get("source", "") if source_str.startswith("D(") and source_str.endswith(")"): diff --git a/src/ContentProcessor/src/libs/pipeline/entities/pipeline_file.py b/src/ContentProcessor/src/libs/pipeline/entities/pipeline_file.py index 5928ad44..33190eb6 100644 --- a/src/ContentProcessor/src/libs/pipeline/entities/pipeline_file.py +++ b/src/ContentProcessor/src/libs/pipeline/entities/pipeline_file.py @@ -81,7 +81,7 @@ def download_file(self, account_url: str, container_name: str, file_path: str): StorageBlobHelper( account_url=account_url, container_name=container_name ).download_file( - container_name=self.process_id, blob_name=self.name, file_path=file_path + container_name=self.process_id, blob_name=self.name, download_path=file_path ) def upload_stream(self, account_url: str, container_name: str, stream: bytes): diff --git a/src/ContentProcessor/src/libs/pipeline/entities/pipeline_message_base.py b/src/ContentProcessor/src/libs/pipeline/entities/pipeline_message_base.py index 1642aef4..66dca280 100644 --- a/src/ContentProcessor/src/libs/pipeline/entities/pipeline_message_base.py +++ b/src/ContentProcessor/src/libs/pipeline/entities/pipeline_message_base.py @@ -69,7 +69,7 @@ def add_exception(self, exception: BaseException): ) @abstractmethod - def save_to_persistent_storage(self): + def save_to_persistent_storage(self, account_url: str, container_name: str): raise NotImplementedError("Method not implemented") class Config: diff --git a/src/ContentProcessor/src/libs/pipeline/entities/pipeline_status.py b/src/ContentProcessor/src/libs/pipeline/entities/pipeline_status.py index 24b0bbc8..38520e2a 100644 --- a/src/ContentProcessor/src/libs/pipeline/entities/pipeline_status.py +++ b/src/ContentProcessor/src/libs/pipeline/entities/pipeline_status.py @@ -90,7 +90,6 @@ def get_previous_step_result(self, current_step_name: str) -> Optional[StepResul return self.get_step_result(previous_step) def save_to_persistent_storage(self, account_url: str, container_name: str): - pass # raise NotImplementedError """ Save the current PipelineStatus to persistent storage. @@ -131,7 +130,6 @@ def _move_to_next_step(self, step_name: str): self.last_updated_time = datetime.datetime.now( datetime.timezone.utc ).strftime("%Y-%m-%dT%H:%M:%S.%fZ") - pass self.completed_steps.append(step_name) # Remove current step from the remaining steps diff --git a/src/ContentProcessor/src/libs/pipeline/queue_handler_base.py b/src/ContentProcessor/src/libs/pipeline/queue_handler_base.py index a36f20f7..afc512fe 100644 --- a/src/ContentProcessor/src/libs/pipeline/queue_handler_base.py +++ b/src/ContentProcessor/src/libs/pipeline/queue_handler_base.py @@ -190,16 +190,6 @@ def _get_artifact_type(step_name: str) -> ArtifactType: else: return ArtifactType.Undefined - def _find_process_result(step_name: str): - return next( - ( - result - for result in self._current_message_context.data_pipeline.pipeline_status.process_results - if result.step_name == step_name - ), - None, - ) - # Save the exception to the status object if self._current_message_context is not None: # Add Exception Information diff --git a/src/ContentProcessor/src/libs/utils/remote_module_loader.py b/src/ContentProcessor/src/libs/utils/remote_module_loader.py index 956ccea9..5f546f4b 100644 --- a/src/ContentProcessor/src/libs/utils/remote_module_loader.py +++ b/src/ContentProcessor/src/libs/utils/remote_module_loader.py @@ -18,7 +18,6 @@ def load_schema_from_blob( blob_content = _download_blob_content(container_name, blob_name, account_url) # Execute the script content - module_name = module_name module = _execute_script(blob_content, module_name) loaded_class = getattr(module, module_name) diff --git a/src/ContentProcessorAPI/app/dependencies.py b/src/ContentProcessorAPI/app/dependencies.py index 723c9228..8cee3c57 100644 --- a/src/ContentProcessorAPI/app/dependencies.py +++ b/src/ContentProcessorAPI/app/dependencies.py @@ -9,12 +9,10 @@ # Placeholder for the actual implementation async def get_token_header(x_token: Annotated[str, Header()]): """it should be registered in the app as a dependency""" - pass raise HTTPException(status_code=400, detail="X-Token header invalid") # Placeholder for the actual implementation async def get_query_token(token: str): """it should be registered in the app as a dependency""" - pass raise HTTPException(status_code=400, detail="No ... token provided") diff --git a/src/ContentProcessorAPI/app/main.py b/src/ContentProcessorAPI/app/main.py index 7c0bf241..5514b508 100644 --- a/src/ContentProcessorAPI/app/main.py +++ b/src/ContentProcessorAPI/app/main.py @@ -16,10 +16,6 @@ app.include_router(schemavault.router) -# class Hello(BaseModel): -# message: str - - @app.get("/health") async def ImAlive(response: Response): # Add Header Name is Custom-Header diff --git a/src/ContentProcessorWeb/src/App.tsx b/src/ContentProcessorWeb/src/App.tsx index 11b53f8e..35c044b1 100644 --- a/src/ContentProcessorWeb/src/App.tsx +++ b/src/ContentProcessorWeb/src/App.tsx @@ -16,7 +16,7 @@ import { } from "react-router-dom"; import Spinner from "./Components/Spinner/Spinner.tsx"; -import { useDispatch, useSelector, shallowEqual } from 'react-redux'; +import { useSelector, shallowEqual } from 'react-redux'; import { RootState } from './store'; diff --git a/src/ContentProcessorWeb/src/Components/DocumentViewer/DocumentViewer.tsx b/src/ContentProcessorWeb/src/Components/DocumentViewer/DocumentViewer.tsx index 89e60a9b..bcb28678 100644 --- a/src/ContentProcessorWeb/src/Components/DocumentViewer/DocumentViewer.tsx +++ b/src/ContentProcessorWeb/src/Components/DocumentViewer/DocumentViewer.tsx @@ -22,9 +22,6 @@ const DocumentViewer = ({ className, metadata, urlWithSasToken, iframeKey }: IIF setImageError(false) }, [urlWithSasToken]) - // Ref for the container div where the Dialog will be rendered - const containerRef = React.useRef(null); - const getContentComponent = () => { if (!metadata || !urlWithSasToken) { return

{t("components.document.none", "No document available")}

; diff --git a/src/ContentProcessorWeb/src/Components/Header/Header.tsx b/src/ContentProcessorWeb/src/Components/Header/Header.tsx index 5abbbe2d..ec8c7140 100644 --- a/src/ContentProcessorWeb/src/Components/Header/Header.tsx +++ b/src/ContentProcessorWeb/src/Components/Header/Header.tsx @@ -1,6 +1,6 @@ import React from "react"; import { useNavigate, useLocation } from "react-router-dom"; -import { Header, useHeaderHooks } from "../../Hooks/useHeaderHooks.tsx"; +import { useHeaderHooks, Header } from "../../Hooks/useHeaderHooks.tsx"; import { TabList, Tab, @@ -9,24 +9,14 @@ import { MenuTrigger, MenuPopover, MenuList, - MenuGroup, MenuItem, MenuDivider, Avatar, - Button, } from "@fluentui/react-components"; -import { - Flow, - WeatherSunny, - WeatherMoon, - Person, - ArrowExit, - Share, - Cube, -} from "../../Imports/bundleIcons.tsx"; +import { ArrowExit } from "../../Imports/bundleIcons.tsx"; import MainLogo from "../../Imports/MainLogo.svg"; import "./Header.css"; -import { DocumentBulletListCubeRegular, InfoRegular, DocumentData16Regular } from "@fluentui/react-icons" +import { DocumentBulletListCubeRegular, InfoRegular } from "@fluentui/react-icons" import useAuth from "../../msal-auth/useAuth.ts"; import { useSelector, shallowEqual } from 'react-redux'; @@ -54,8 +44,7 @@ const tabConfigs = [ ]; const HeaderPage: React.FC = ({ toggleTheme, isDarkMode }) => { - const { shortcutLabel } = useHeaderHooks({ toggleTheme, isDarkMode }); - const { user, logout, getToken } = useAuth(); + const { user, logout } = useAuth(); const authEnabled = process.env.REACT_APP_AUTH_ENABLED?.toLowerCase() !== 'false'; // Defaults to true if not set diff --git a/src/ContentProcessorWeb/src/Components/JSONEditor/JSONEditor.tsx b/src/ContentProcessorWeb/src/Components/JSONEditor/JSONEditor.tsx index dcb39a93..f97697f3 100644 --- a/src/ContentProcessorWeb/src/Components/JSONEditor/JSONEditor.tsx +++ b/src/ContentProcessorWeb/src/Components/JSONEditor/JSONEditor.tsx @@ -4,7 +4,7 @@ import './JSONEditor.styles.scss' import { useDispatch, useSelector, shallowEqual } from 'react-redux'; import { AppDispatch, RootState } from '../../store'; -import { fetchContentJsonData, setModifiedResult } from '../../store/slices/centerPanelSlice'; +import { setModifiedResult } from '../../store/slices/centerPanelSlice'; import { SearchBox } from "@fluentui/react-components"; diff --git a/src/ContentProcessorWeb/src/Components/UploadContent/UploadFilesModal.tsx b/src/ContentProcessorWeb/src/Components/UploadContent/UploadFilesModal.tsx index 80f7f0a6..48215a37 100644 --- a/src/ContentProcessorWeb/src/Components/UploadContent/UploadFilesModal.tsx +++ b/src/ContentProcessorWeb/src/Components/UploadContent/UploadFilesModal.tsx @@ -1,4 +1,4 @@ -import React, { useState, useRef, useEffect } from "react"; +import React, { useState, useRef } from "react"; import { Dialog, DialogSurface, @@ -7,9 +7,9 @@ import { DialogActions, } from "@fluentui/react-dialog"; import { Button } from "@fluentui/react-button"; -import { Field, ProgressBar, makeStyles } from "@fluentui/react-components"; +import { ProgressBar, makeStyles } from "@fluentui/react-components"; import { useDispatch, useSelector, shallowEqual } from "react-redux"; -import { fetchContentTableData, setRefreshGrid, uploadFile } from "../../store/slices/leftPanelSlice"; +import { setRefreshGrid, uploadFile } from "../../store/slices/leftPanelSlice"; import { AppDispatch, RootState } from "../../store"; import "./UploadFilesModal.styles.scss"; @@ -20,7 +20,6 @@ import { MessageBarTitle, MessageBarBody, MessageBarIntent, - Link, } from "@fluentui/react-components"; const useStyles = makeStyles({ @@ -215,7 +214,7 @@ const UploadFilesModal: React.FC = ({ open, onClose }) => const onCloseHandler = () => { resetState(); onClose(); - } + }; return ( diff --git a/src/ContentProcessorWeb/src/Hooks/usePanelHooks.tsx b/src/ContentProcessorWeb/src/Hooks/usePanelHooks.tsx index 62ec70ac..d503b19c 100644 --- a/src/ContentProcessorWeb/src/Hooks/usePanelHooks.tsx +++ b/src/ContentProcessorWeb/src/Hooks/usePanelHooks.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { Button, Body1Strong } from "@fluentui/react-components"; +import { Body1Strong } from "@fluentui/react-components"; interface PanelToolbarProps { icon: React.ReactNode; diff --git a/src/ContentProcessorWeb/src/Pages/DefaultPage/Components/ProcessQueueGrid/ProcessQueueGrid.tsx b/src/ContentProcessorWeb/src/Pages/DefaultPage/Components/ProcessQueueGrid/ProcessQueueGrid.tsx index bef346ff..911aa55c 100644 --- a/src/ContentProcessorWeb/src/Pages/DefaultPage/Components/ProcessQueueGrid/ProcessQueueGrid.tsx +++ b/src/ContentProcessorWeb/src/Pages/DefaultPage/Components/ProcessQueueGrid/ProcessQueueGrid.tsx @@ -1,11 +1,11 @@ import React, { useState, useEffect } from "react"; -import { FixedSizeList as List, ListChildComponentProps } from "react-window"; +import { FixedSizeList as List } from "react-window"; import { DocumentQueueAdd20Regular, DocumentPdfRegular, ImageRegular } from "@fluentui/react-icons"; -import { TableCellActions, Tooltip } from "@fluentui/react-components"; +import { Tooltip } from "@fluentui/react-components"; import { - PresenceBadgeStatus, Avatar, useScrollbarWidth, useFluent, TableBody, TableCell, TableRow, Table, - TableHeader, TableHeaderCell, TableCellLayout, TableSelectionCell, createTableColumn, useTableFeatures, - useTableSelection, useTableSort, TableColumnId, useTableColumnSizing_unstable, + useScrollbarWidth, useFluent, TableBody, TableCell, TableRow, Table, + TableHeader, TableHeaderCell, TableCellLayout, createTableColumn, useTableFeatures, + useTableSelection, useTableSort, TableColumnId, TableRowId } from "@fluentui/react-components"; import './ProcessQueueGrid.styles.scss'; @@ -80,8 +80,7 @@ const ProcessQueueGrid: React.FC = () => { ); const { targetDocument } = useFluent(); - const scrollbarWidth = useScrollbarWidth({ targetDocument }); - + const [sortState, setSortState] = useState<{ sortDirection: "ascending" | "descending"; sortColumn: TableColumnId | undefined; @@ -91,7 +90,7 @@ const ProcessQueueGrid: React.FC = () => { }); const [items, setItems] = useState([]); // State to store fetched items - const { fileType, getMimeType } = useFileType(null); + const { getMimeType } = useFileType(null); const [selectedRows, setSelectedRows] = React.useState( () => new Set([0]) diff --git a/src/ContentProcessorWeb/src/Pages/DefaultPage/Components/ProcessQueueGrid/ProcessQueueGridTypes.ts b/src/ContentProcessorWeb/src/Pages/DefaultPage/Components/ProcessQueueGrid/ProcessQueueGridTypes.ts index 2cdc6eaf..0b33ffe0 100644 --- a/src/ContentProcessorWeb/src/Pages/DefaultPage/Components/ProcessQueueGrid/ProcessQueueGridTypes.ts +++ b/src/ContentProcessorWeb/src/Pages/DefaultPage/Components/ProcessQueueGrid/ProcessQueueGridTypes.ts @@ -1,4 +1,4 @@ -import { TableRowId, TableRowData as RowStateBase, } from "@fluentui/react-components"; +import { TableRowData as RowStateBase, } from "@fluentui/react-components"; import { ListChildComponentProps } from "react-window"; export interface Item { diff --git a/src/ContentProcessorWeb/src/Pages/DefaultPage/Components/ProcessSteps/ProcessSteps.tsx b/src/ContentProcessorWeb/src/Pages/DefaultPage/Components/ProcessSteps/ProcessSteps.tsx index e7e4fd3a..9ae6c6bf 100644 --- a/src/ContentProcessorWeb/src/Pages/DefaultPage/Components/ProcessSteps/ProcessSteps.tsx +++ b/src/ContentProcessorWeb/src/Pages/DefaultPage/Components/ProcessSteps/ProcessSteps.tsx @@ -1,7 +1,7 @@ import React, { useCallback, useEffect, useState, useRef } from "react"; -import { Accordion, AccordionItem, AccordionHeader, AccordionPanel, tokens } from "@fluentui/react-components"; -import { useDispatch, useSelector, shallowEqual } from 'react-redux'; -import { RootState, AppDispatch } from '../../../../store/index.ts'; +import { Accordion, AccordionItem, AccordionHeader, AccordionPanel } from "@fluentui/react-components"; +import { useSelector, shallowEqual } from 'react-redux'; +import { RootState } from '../../../../store/index.ts'; import { JsonEditor } from "json-edit-react"; import { CheckmarkCircleFilled } from "@fluentui/react-icons"; import { Spinner } from "@fluentui/react-components"; diff --git a/src/ContentProcessorWeb/src/Pages/DefaultPage/Components/SchemaDropdown/SchemaDropdown.tsx b/src/ContentProcessorWeb/src/Pages/DefaultPage/Components/SchemaDropdown/SchemaDropdown.tsx index 925a73c5..d6de4413 100644 --- a/src/ContentProcessorWeb/src/Pages/DefaultPage/Components/SchemaDropdown/SchemaDropdown.tsx +++ b/src/ContentProcessorWeb/src/Pages/DefaultPage/Components/SchemaDropdown/SchemaDropdown.tsx @@ -5,7 +5,7 @@ import './SchemaDropdown.styles.scss'; import { useDispatch, useSelector, shallowEqual } from 'react-redux'; import { RootState } from '../../../../store'; import { setSchemaSelectedOption } from '../../../../store/slices/leftPanelSlice'; -import { OptionList, SchemaItem, StoreState } from './SchemaDropdownTypes'; +import { OptionList, SchemaItem } from './SchemaDropdownTypes'; const useStyles = makeStyles({ root: {