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

Job view crashes for jobs with many report items #2311 #2327

Merged
merged 19 commits into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
7e7cf51
Job view crashes for jobs with many report items #2311
robertbasti Mar 20, 2024
c711b23
Job view crashes for jobs with many report items #2311
robertbasti Mar 20, 2024
5c21439
Job view crashes for jobs with many report items #2311
robertbasti Mar 20, 2024
d713f5d
Job view crashes for jobs with many report items #2311
robertbasti Mar 20, 2024
70046bd
Job view crashes for jobs with many report items #2311
robertbasti Mar 20, 2024
022b2ac
Job view crashes for jobs with many report items #2311
robertbasti Mar 20, 2024
ed04c41
Job view crashes for jobs with many report items #2311
robertbasti Mar 21, 2024
18901fd
Job view crashes for jobs with many report items #2311
robertbasti Mar 21, 2024
8e30dbf
Job view crashes for jobs with many report items #2311
robertbasti Mar 21, 2024
307ce45
Job view crashes for jobs with many report items #2311
robertbasti Mar 22, 2024
3a68863
Job view crashes for jobs with many report items #2311
robertbasti Mar 22, 2024
8c07169
Job view crashes for jobs with many report items #2311
robertbasti Mar 22, 2024
35b2c9c
Job view crashes for jobs with many report items #2311
robertbasti Mar 22, 2024
e5d3668
Update report modal test
eliasbruvik Mar 22, 2024
fe9532a
Job view crashes for jobs with many report items #2311
robertbasti Mar 22, 2024
3f5891c
Job view crashes for jobs with many report items #2311
robertbasti Mar 22, 2024
6f50176
Job view crashes for jobs with many report items #2311
robertbasti Mar 22, 2024
f1a7b09
Job view crashes for jobs with many report items #2311
robertbasti Mar 22, 2024
f215d62
Job view crashes for jobs with many report items #2311
robertbasti Mar 22, 2024
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
21 changes: 21 additions & 0 deletions Src/WitsmlExplorer.Api/HttpHandlers/JobHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using System.Linq;
using System.Threading.Tasks;

using Amazon.Runtime;
eliasbruvik marked this conversation as resolved.
Show resolved Hide resolved

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
Expand All @@ -12,6 +14,7 @@
using WitsmlExplorer.Api.Jobs;
using WitsmlExplorer.Api.Middleware;
using WitsmlExplorer.Api.Models;
using WitsmlExplorer.Api.Models.Reports;
using WitsmlExplorer.Api.Services;

namespace WitsmlExplorer.Api.HttpHandlers
Expand Down Expand Up @@ -100,5 +103,23 @@ public static IResult CancelJob(string jobId, IJobCache jobCache)
}
return TypedResults.NotFound();
}

[Produces(typeof(BaseReport))]
public static IResult GetReport(string jobId, IJobCache jobCache, HttpRequest httpRequest, IConfiguration configuration, ICredentialsService credentialsService)
{
EssentialHeaders eh = new(httpRequest);
bool useOAuth2 = StringHelpers.ToBoolean(configuration[ConfigConstants.OAuth2Enabled]);
string userName = useOAuth2 ? credentialsService.GetClaimFromToken(eh.GetBearerToken(), "upn") : eh.TargetUsername;
if (!useOAuth2)
{
credentialsService.VerifyUserIsLoggedIn(eh, ServerType.Target);
}
JobInfo job = jobCache.GetJobInfoById(jobId);
if (job.Username != userName && (!useOAuth2 || !IsAdminOrDeveloper(eh.GetBearerToken())))
{
return TypedResults.Forbid();
}
return TypedResults.Ok(jobCache.GetReportByJobId(jobId));
eliasbruvik marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
12 changes: 12 additions & 0 deletions Src/WitsmlExplorer.Api/Jobs/JobInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public JobInfo()

public double Progress { get; set; }

[JsonIgnore]
public BaseReport Report { get; set; }

public bool IsCancelable { get; internal set; } = false;
Expand All @@ -73,6 +74,17 @@ public JobStatus Status
}
}

public string LinkType
eliasbruvik marked this conversation as resolved.
Show resolved Hide resolved
{
get
{
if (Report?.DownloadImmediately == true)
{
return "Donwload file";
}
return "Report";
}
}
}

public enum JobStatus
Expand Down
1 change: 1 addition & 0 deletions Src/WitsmlExplorer.Api/Models/Reports/BaseReport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ public class BaseReport
public IEnumerable<object> ReportItems { get; init; }
public string WarningMessage { get; init; }
public bool DownloadImmediately { get; init; } = false;
public string ReportHeader { get; init; }
}
}
1 change: 1 addition & 0 deletions Src/WitsmlExplorer.Api/Routes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ public static void ConfigureApi(this WebApplication app, IConfiguration configur
app.MapGet("/jobs/userjobinfo/{jobId}", JobHandler.GetUserJobInfo, useOAuth2);
app.MapGet("/jobs/alljobinfos", JobHandler.GetAllJobInfos, useOAuth2, AuthorizationPolicyRoles.ADMINORDEVELOPER);
app.MapPost("/jobs/cancel/{jobId}", JobHandler.CancelJob, useOAuth2);
app.MapGet("/jobs/getreport/{jobId}", JobHandler.GetReport, useOAuth2);
eliasbruvik marked this conversation as resolved.
Show resolved Hide resolved

app.MapGet("/credentials/authorize", AuthorizeHandler.Authorize, useOAuth2);
app.MapGet("/credentials/deauthorize", AuthorizeHandler.Deauthorize, useOAuth2);
Expand Down
14 changes: 13 additions & 1 deletion Src/WitsmlExplorer.Api/Services/JobCache.cs
eliasbruvik marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Microsoft.Extensions.Logging;

using WitsmlExplorer.Api.Jobs;
using WitsmlExplorer.Api.Models.Reports;

namespace WitsmlExplorer.Api.Services
{
Expand All @@ -18,6 +19,7 @@ public interface IJobCache
ICollection<JobInfo> GetJobInfosByUser(string username);
JobInfo GetJobInfoById(string jobId);
ICollection<JobInfo> GetAllJobInfos();
BaseReport GetReportByJobId(string jobId);
}

public class JobCache : IJobCache
Expand Down Expand Up @@ -61,7 +63,17 @@ public JobInfo GetJobInfoById(string jobId)

public ICollection<JobInfo> GetAllJobInfos()
{
return _jobs.Values;
return _jobs.Values.ToList();
}

public BaseReport GetReportByJobId(string jobId)
{
var job = _jobs[jobId];
if (job != null)
{
return job.Report;
}
return null;
}

private void Cleanup()
Expand Down
21 changes: 16 additions & 5 deletions Src/WitsmlExplorer.Api/Workers/DownloadAllLogDataWorker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,26 +43,37 @@ public DownloadAllLogDataWorker(
if (job.JobInfo != null) job.JobInfo.Progress = progress;
});
var logData = await _logObjectService.ReadLogData(job.LogReference.WellUid, job.LogReference.WellboreUid, job.LogReference.Uid, job.Mnemonics.ToList(), job.StartIndexIsInclusive, job.LogReference.StartIndex, job.LogReference.EndIndex, true, cancellationToken, progressReporter);
return DownloadAllLogDataResult(job, logData.Data, job.LogReference.Uid);
return DownloadAllLogDataResult(job, logData.Data, logData.CurveSpecifications);
}

private (WorkerResult, RefreshAction) DownloadAllLogDataResult(DownloadAllLogDataJob job, ICollection<Dictionary<string, LogDataValue>> reportItems, string logUid)
private (WorkerResult, RefreshAction) DownloadAllLogDataResult(DownloadAllLogDataJob job, ICollection<Dictionary<string, LogDataValue>> reportItems, ICollection<CurveSpecification> curveSpecifications)
{
Logger.LogInformation("Download of all data is done. {jobDescription}", job.Description());
job.JobInfo.Report = DownloadAllLogDataReport(reportItems, job.LogReference);
job.JobInfo.Report = DownloadAllLogDataReport(reportItems, job.LogReference, GetReportHeader(curveSpecifications));
WorkerResult workerResult = new(GetTargetWitsmlClientOrThrow().GetServerHostname(), true, $"Download of all data is ready, jobId: ", jobId: job.JobInfo.Id);
return (workerResult, null);
}

private DownloadAllLogDataReport DownloadAllLogDataReport(ICollection<Dictionary<string, LogDataValue>> reportItems, LogObject logReference)
private DownloadAllLogDataReport DownloadAllLogDataReport(ICollection<Dictionary<string, LogDataValue>> reportItems, LogObject logReference, string reportHeader)
{
return new DownloadAllLogDataReport
{
Title = $"{logReference.WellboreName} - {logReference.Name}",
Summary = "You can download the report as csv file",
LogReference = logReference,
ReportItems = reportItems,
DownloadImmediately = true
DownloadImmediately = true,
ReportHeader = reportHeader
};
}

private string GetReportHeader(ICollection<CurveSpecification> curveSpecifications)
{
var listOfHeaders = new List<string>();
foreach (CurveSpecification curveSpec in curveSpecifications)
{
listOfHeaders.Add($"{curveSpec.Mnemonic}[{curveSpec.Unit}]");
}
return string.Join(',', listOfHeaders);
}
}
13 changes: 13 additions & 0 deletions Src/WitsmlExplorer.Frontend/__testUtils__/testUtils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import ObjectOnWellbore from "models/objectOnWellbore";
import ObjectSearchResult from "models/objectSearchResult";
import { ObjectType, ObjectTypeToModel } from "models/objectType";
import RefNameString from "models/refNameString";
import BaseReport from "models/reports/BaseReport";
import Rig from "models/rig";
import RiskObject from "models/riskObject";
import { Server } from "models/server";
Expand Down Expand Up @@ -194,10 +195,22 @@ export function getJobInfo(overrides?: Partial<JobInfo>): JobInfo {
report: null,
progress: 0,
isCancelable: false,
linkType: "",
...overrides
};
}

export function getReport(): BaseReport {
eliasbruvik marked this conversation as resolved.
Show resolved Hide resolved
return {
title: "testTitle",
summary: "testSummary",
reportItems: [],
warningMessage: "",
downloadImmediately: false,
reportHeader: ""
};
}

export function getNotification(
overrides?: Partial<Notification>
): Notification {
Expand Down
46 changes: 30 additions & 16 deletions Src/WitsmlExplorer.Frontend/components/ContentViews/JobsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ import JobInfoContextMenu, {
} from "components/ContextMenus/JobInfoContextMenu";
import formatDateString from "components/DateFormatter";
import { ReportModal } from "components/Modals/ReportModal";
import { generateReport } from "components/ReportCreationHelper";
import { Button } from "components/StyledComponents/Button";
import OperationContext from "contexts/operationContext";
import OperationType from "contexts/operationType";
import { refreshJobInfoQuery } from "hooks/query/queryRefreshHelpers";
import { useGetJobInfo } from "hooks/query/useGetJobInfo";
import { useGetServers } from "hooks/query/useGetServers";
import BaseReport from "models/reports/BaseReport";
import useExport from "hooks/useExport";
import { Server } from "models/server";
import {
adminRole,
Expand All @@ -26,6 +27,7 @@ import {
msalEnabled
} from "msal/MsalAuthProvider";
import React, { ChangeEvent, useContext, useMemo, useState } from "react";
import JobService from "services/jobService";
import styled from "styled-components";
import { Colors } from "styles/Colors";

Expand All @@ -44,6 +46,8 @@ export const JobsView = (): React.ReactElement => {
? new Date(dataUpdatedAt).toLocaleTimeString()
: "";

const { exportData } = useExport();

const onContextMenu = (
event: React.MouseEvent<HTMLLIElement>,
selectedItem: any
Expand All @@ -62,12 +66,25 @@ export const JobsView = (): React.ReactElement => {
});
};

const onClickReport = (report: BaseReport) => {
const reportModalProps = { report };
dispatchOperation({
type: OperationType.DisplayModal,
payload: <ReportModal {...reportModalProps} />
});
const onClickReport = async (jobId: string) => {
const report = await JobService.getReport(jobId);
if (report.downloadImmediately === true) {
const reportProperties = generateReport(
report.reportItems,
report.reportHeader
);
exportData(
report.title,
reportProperties.exportColumns,
reportProperties.data
);
} else {
const reportModalProps = { report };
dispatchOperation({
type: OperationType.DisplayModal,
payload: <ReportModal {...reportModalProps} />
});
}
};

const columns: ContentTableColumn[] = [
Expand Down Expand Up @@ -115,10 +132,6 @@ export const JobsView = (): React.ReactElement => {
wellName: jobInfo.wellName,
wellboreName: jobInfo.wellboreName,
objectName: jobInfo.objectName,
status:
eliasbruvik marked this conversation as resolved.
Show resolved Hide resolved
jobInfo.progress && jobInfo.status === "Started"
? `${Math.round(jobInfo.progress * 100)}%`
: jobInfo.status,
startTime: formatDateString(
jobInfo.startTime,
timeZone,
Expand All @@ -131,11 +144,12 @@ export const JobsView = (): React.ReactElement => {
),
targetServer: serverUrlToName(servers, jobInfo.targetServer),
sourceServer: serverUrlToName(servers, jobInfo.sourceServer),
report: jobInfo.report ? (
<ReportButton onClick={() => onClickReport(jobInfo.report)}>
Report
</ReportButton>
) : null,
report:
jobInfo.status === "Finished" ? (
<ReportButton onClick={() => onClickReport(jobInfo.id)}>
{jobInfo.linkType}
eliasbruvik marked this conversation as resolved.
Show resolved Hide resolved
</ReportButton>
) : null,
jobInfo: jobInfo
};
})
Expand Down
47 changes: 14 additions & 33 deletions Src/WitsmlExplorer.Frontend/components/Modals/ReportModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
} from "components/ContentViews/table";
import { StyledAccordionHeader } from "components/Modals/LogComparisonModal";
import ModalDialog, { ModalWidth } from "components/Modals/ModalDialog";
import { generateReport } from "components/ReportCreationHelper";
import { Banner } from "components/StyledComponents/Banner";
import { useConnectedServer } from "contexts/connectedServerContext";
import OperationContext from "contexts/operationContext";
Expand Down Expand Up @@ -161,39 +162,10 @@ export const ReportModal = (props: ReportModal): React.ReactElement => {
export const useGetReportOnJobFinished = (jobId: string): BaseReport => {
const { connectedServer } = useConnectedServer();
const [report, setReport] = useState<BaseReport>(null);
const { exportData, exportOptions } = useExport();
const { exportData } = useExport();

if (!jobId) return null;

const downloadData = (reportItems: any[], reportTitle: string) => {
if (reportItems === null) {
return;
}

const columns: ContentTableColumn[] =
reportItems.length > 0
? Object.keys(reportItems[0]).map((key) => ({
property: key,
label: key,
type: ContentType.String
}))
: [];

const exportColumns = columns
.map((column) => `${column.property}]`)
.join(exportOptions.separator);

const data = reportItems
.map((row) =>
columns
.map((col) => row[col.property] as string)
.join(exportOptions.separator)
)
.join(exportOptions.newLineCharacter);

exportData(reportTitle, exportColumns, data);
};

useEffect(() => {
const unsubscribeOnJobFinished =
NotificationService.Instance.snackbarDispatcherAsEvent.subscribe(
Expand All @@ -207,9 +179,18 @@ export const useGetReportOnJobFinished = (jobId: string): BaseReport => {
)
);
} else {
setReport(jobInfo.report);
if (jobInfo.report.downloadImmediately === true) {
downloadData(jobInfo.report.reportItems, jobInfo.report.title);
const report = await JobService.getReport(jobId);
eliasbruvik marked this conversation as resolved.
Show resolved Hide resolved
setReport(report);
if (report.downloadImmediately === true) {
const reportProperties = generateReport(
report.reportItems,
report.reportHeader
);
exportData(
report.title,
reportProperties.exportColumns,
reportProperties.data
);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
deferred,
getJobInfo,
getNotification,
getReport,
renderWithContexts
} from "__testUtils__/testUtils";
import { ReportModal } from "components/Modals/ReportModal";
Expand All @@ -20,7 +21,8 @@ jest.mock("@equinor/eds-core-react", () => mockEdsCoreReact());

jest.mock("services/jobService", () => {
return {
getUserJobInfo: () => MOCK_JOB_INFO
getUserJobInfo: () => MOCK_JOB_INFO,
getReport: () => MOCK_REPORT
};
});

Expand Down Expand Up @@ -130,3 +132,4 @@ const REPORT = createReport("testTitle", "testSummary", REPORT_ITEMS);
const EMPTY_REPORT = createReport("emptyReportTitle", "emptyReportSummary");
const MOCK_JOB_INFO = getJobInfo({ report: REPORT, id: "testJobId" });
const NOTIFICATION = getNotification({ jobId: "testJobId" });
const MOCK_REPORT = getReport();
eliasbruvik marked this conversation as resolved.
Show resolved Hide resolved
Loading
Loading