Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve inspections view stability #1890

Closed
Closed
Show file tree
Hide file tree
Changes from all 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
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)]
mrica-equinor marked this conversation as resolved.
Show resolved Hide resolved
[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.GetInspectionData(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");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using Enums

}
}
60 changes: 60 additions & 0 deletions backend/api/Services/InspectionService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,20 @@
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[]?> GetInspectionData(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[]?> GetInspectionData(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))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider more readable check

{
logger.LogError($"Could not find inspection data for inspection with isar Id {inspection.IsarInspectionId} because blob name {inspectionData.BlobContainer} 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
Loading