Skip to content

Commit

Permalink
Improve inspections view stability
Browse files Browse the repository at this point in the history
  • Loading branch information
mrica-equinor committed Dec 17, 2024
1 parent 6b4d156 commit c1a3305
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 58 deletions.
42 changes: 6 additions & 36 deletions backend/api/Controllers/InspectionController.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Globalization;
using Api.Controllers.Models;
using Api.Controllers.Models;
using Api.Database.Models;

using Api.Services;
Expand Down Expand Up @@ -61,48 +60,19 @@ public async Task<ActionResult<TagInspectionMetadata>> Create([FromRoute] string
/// </remarks>
[HttpGet]
[Authorize(Roles = Role.User)]
[Route("{installationCode}/{taskId}/taskId")]
[Route("{installationCode}/{isarInspectionId}/isarInspectionId")]
[ProducesResponseType(typeof(Inspection), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<Inspection>> GetInspectionImageById([FromRoute] string installationCode, string taskId)
public async Task<ActionResult<Inspection>> GetInspectionImageByIsarInspectionId([FromRoute] string installationCode, string isarInspectionId)
{
Inspection? inspection;
try
{
inspection = await inspectionService.ReadByIsarTaskId(taskId, readOnly: true);
if (inspection == null) return NotFound($"Could not find inspection for task with Id {taskId}.");

}
catch (Exception e)
{
logger.LogError(e, $"Error while finding an inspection with task Id {taskId}");
return StatusCode(StatusCodes.Status500InternalServerError);
}

if (inspection.IsarInspectionId == null) return NotFound($"Could not find isar inspection Id {inspection.IsarInspectionId} for Inspection with task ID {taskId}.");

var inspectionData = await inspectionService.GetInspectionStorageInfo(inspection.IsarInspectionId);
byte[]? inspectionStream = await inspectionService.GetInspectionImage(installationCode, isarInspectionId);
if (inspectionStream == null) { return NotFound($"Could not find inspection data for inspection with isar Id {isarInspectionId}."); }

if (inspectionData == null) return NotFound($"Could not find inspection data for inspection with isar Id {inspection.IsarInspectionId}.");

if (!inspectionData.BlobContainer.ToLower(CultureInfo.CurrentCulture).Equals(installationCode.ToLower(CultureInfo.CurrentCulture), StringComparison.Ordinal))
{
return NotFound($"Could not find inspection data for inspection with isar Id {inspection.IsarInspectionId} because blob name {inspectionData.BlobName} does not match installation {installationCode}.");
}

try
{
byte[] inspectionStream = await inspectionService.FetchInpectionImage(inspectionData.BlobName, inspectionData.BlobContainer, inspectionData.StorageAccount);
return File(inspectionStream, "image/png");
}
catch (Azure.RequestFailedException)
{
return NotFound($"Could not find inspection blob {inspectionData.BlobName} in container {inspectionData.BlobContainer} and storage account {inspectionData.StorageAccount}.");
}
return File(inspectionStream, "image/png");
}
}
}
62 changes: 61 additions & 1 deletion backend/api/Services/InspectionService.cs
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Net;
using System.Text.Json;
using System.Globalization;
using Api.Controllers.Models;
using Api.Database.Context;
using Api.Database.Models;
using Api.Services.Models;
using Api.Utilities;
using Microsoft.EntityFrameworkCore;
using Microsoft.Identity.Abstractions;

namespace Api.Services

{
public interface IInspectionService
{
public Task<byte[]> FetchInpectionImage(string inpectionName, string installationCode, string storageAccount);
public Task<Inspection> UpdateInspectionStatus(string isarTaskId, IsarTaskStatus isarTaskStatus);
public Task<Inspection?> ReadByIsarTaskId(string id, bool readOnly = true);
public Task<Inspection?> ReadByIsarInspectionId(string id, bool readOnly = true);
public Task<Inspection?> AddFinding(InspectionFindingQuery inspectionFindingsQuery, string isarTaskId);
public Task<IDAInspectionDataResponse?> GetInspectionStorageInfo(string inspectionId);
public Task<byte[]?> GetInspectionImage(string installationCode, string isarInspectionId);


}

Expand Down Expand Up @@ -81,6 +86,11 @@ private async Task<Inspection> Update(Inspection inspection)
return await GetInspections(readOnly: readOnly).FirstOrDefaultAsync(inspection => inspection.IsarTaskId != null && inspection.IsarTaskId.Equals(id));
}

public async Task<Inspection?> ReadByIsarInspectionId(string id, bool readOnly = true)
{
return await GetInspections(readOnly: readOnly).FirstOrDefaultAsync(inspection => inspection.IsarInspectionId != null && inspection.IsarInspectionId.Equals(id));
}

private IQueryable<Inspection> GetInspections(bool readOnly = true)
{
if (accessRoleService.IsUserAdmin() || !accessRoleService.IsAuthenticationAvailable())
Expand Down Expand Up @@ -142,11 +152,61 @@ private IQueryable<Inspection> GetInspections(bool readOnly = true)
return null;
}

if (response.StatusCode != HttpStatusCode.OK)
{
logger.LogError("Could not get inspection data for inspection with Id {inspectionId}", inspectionId);
return null;
}

var inspectionData = await response.Content.ReadFromJsonAsync<
IDAInspectionDataResponse
>() ?? throw new JsonException("Failed to deserialize inspection data from IDA.");

return inspectionData;
}

public async Task<byte[]?> GetInspectionImage(string installationCode, string isarInspectionId)
{
Inspection? inspection;
try
{
inspection = await ReadByIsarInspectionId(isarInspectionId, readOnly: true);
if (inspection == null)
{
logger.LogError($"Could not find inspection with isar inspection Id {isarInspectionId}.");
return null;
}
}
catch (Exception e)
{
logger.LogError(e, $"Error while finding an inspection with isar inspection Id {isarInspectionId}. {e.Message}");
return null;
}

var inspectionData = await GetInspectionStorageInfo(inspection.IsarInspectionId);

if (inspectionData == null)
{
logger.LogError($"Could not find inspection data for inspection with isar Id {inspection.IsarInspectionId}.");
return null;
}

if (!inspectionData.BlobContainer.ToLower(CultureInfo.CurrentCulture).Equals(installationCode.ToLower(CultureInfo.CurrentCulture), StringComparison.Ordinal))
{
logger.LogError($"Could not find inspection data for inspection with isar Id {inspection.IsarInspectionId} because blob name {inspectionData.BlobName} does not match installation {installationCode}.");
return null;
}

try
{
byte[] inspectionStream = await FetchInpectionImage(inspectionData.BlobName, inspectionData.BlobContainer, inspectionData.StorageAccount);
return inspectionStream;
}
catch (Azure.RequestFailedException e)
{
logger.LogError($"Could not find inspection blob {inspectionData.BlobName} in container {inspectionData.BlobContainer} and storage account {inspectionData.StorageAccount}. {e.Message}");
return null;
}
}
}
}
4 changes: 2 additions & 2 deletions frontend/src/api/ApiCaller.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -430,8 +430,8 @@ export class BackendAPICaller {
return result.content
}

static async getInspection(installationCode: string, taskId: string): Promise<Blob> {
const path: string = 'inspection/' + installationCode + '/' + taskId + '/taskId'
static async getInspection(installationCode: string, isarInspectionId: string): Promise<Blob> {
const path: string = 'inspection/' + installationCode + '/' + isarInspectionId + '/isarInspectionId'

return BackendAPICaller.GET<Blob>(path, 'image/png')
.then((response) => response.content)
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/Contexts/InpectionsContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ export const InspectionsProvider: FC<Props> = ({ children }) => {

useEffect(() => {
Object.values(selectedInspectionTasksToFetch).forEach((task, index) => {
if (task.isarTaskId) {
BackendAPICaller.getInspection(installationCode, task.isarTaskId!)
if (task.inspection.isarInspectionId && task.isarTaskId) {
BackendAPICaller.getInspection(installationCode, task.inspection.isarInspectionId)
.then((imageBlob) => {
imageObjectURL.current = URL.createObjectURL(imageBlob)
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,21 @@ export const TaskTable = ({ tasks }: TaskTableProps) => {
const { TranslateText } = useLanguageContext()

return (
<>
<StyledTable>
<StyledTableCaptionGray>
<StyledTypography variant="h2">{TranslateText('Tasks')}</StyledTypography>
</StyledTableCaptionGray>
<Table.Head>
<Table.Row>
<StyledTableCell>#</StyledTableCell>
<StyledTableCell>{TranslateText('Tag-ID')}</StyledTableCell>
<StyledTableCell>{TranslateText('Description')}</StyledTableCell>
<StyledTableCell>{TranslateText('Inspection Types')}</StyledTableCell>
<StyledTableCell>{TranslateText('Status')}</StyledTableCell>
</Table.Row>
</Table.Head>
<StyledTableBody>{tasks && <TaskTableRows tasks={tasks} />}</StyledTableBody>
</StyledTable>
</>
<StyledTable>
<StyledTableCaptionGray>
<StyledTypography variant="h2">{TranslateText('Tasks')}</StyledTypography>
</StyledTableCaptionGray>
<Table.Head>
<Table.Row>
<StyledTableCell>#</StyledTableCell>
<StyledTableCell>{TranslateText('Tag-ID')}</StyledTableCell>
<StyledTableCell>{TranslateText('Description')}</StyledTableCell>
<StyledTableCell>{TranslateText('Inspection Types')}</StyledTableCell>
<StyledTableCell>{TranslateText('Status')}</StyledTableCell>
</Table.Row>
</Table.Head>
<StyledTableBody>{tasks && <TaskTableRows tasks={tasks} />}</StyledTableBody>
</StyledTable>
)
}

Expand Down
1 change: 1 addition & 0 deletions frontend/src/models/Inspection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Position } from './Position'
export interface Inspection {
id: string
isarTaskId?: string
isarInspectionId?: string
status: InspectionStatus
isCompleted: boolean
inspectionType: InspectionType
Expand Down

0 comments on commit c1a3305

Please sign in to comment.