Skip to content

Commit

Permalink
[Nu-7330] Use activities endpoint to compute ranges in counts window
Browse files Browse the repository at this point in the history
  • Loading branch information
Piotr Rudnicki committed Dec 20, 2024
1 parent 90e00a9 commit eddddc6
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 54 deletions.
8 changes: 4 additions & 4 deletions designer/client/cypress/e2e/counts.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe("Counts", () => {
cy.get("@button").click();

cy.get("[data-testid=window]").contains("Quick ranges").should("be.visible");
cy.contains(/^latest deploy$/i).should("not.exist");
cy.contains(/^latest run$/i).should("not.exist");
cy.get("[data-testid=window]").matchImage({ maxDiffThreshold });
cy.get("[data-testid=window]")
.contains(/^cancel$/i)
Expand All @@ -31,7 +31,7 @@ describe("Counts", () => {
cy.deployScenario();
cy.get("@button").click();
cy.get("[data-testid=window]").contains("Quick ranges").should("be.visible");
cy.contains(/^latest deploy$/i).should("be.visible");
cy.contains(/^latest run$/i).should("be.visible");
cy.get("[data-testid=window]").matchImage({ maxDiffThreshold });
cy.get("[data-testid=window]")
.contains(/^cancel$/i)
Expand All @@ -44,12 +44,12 @@ describe("Counts", () => {

cy.get("@button").click();
cy.get("[data-testid=window]").contains("Quick ranges").should("be.visible");
cy.contains(/^previous deployments...$/i)
cy.contains(/^previous activities...$/i)
.should("be.visible")
.click();
cy.get("[data-testid=window]").matchImage({ maxDiffThreshold });
cy.get("[data-testid=window]").contains("no refresh").should("be.visible");
cy.get("[data-testid=window]").contains("Latest deploy").click();
cy.get("[data-testid=window]").contains("Latest Run").click();
cy.get("[data-testid=window]").contains("10 seconds").should("be.visible");
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { Moment } from "moment";
import React, { useMemo } from "react";
import { useTranslation } from "react-i18next";
import { useSelector } from "react-redux";
import { getProcessName } from "../../../reducers/selectors/graph";
import { getProcessingType, getProcessName } from "../../../reducers/selectors/graph";
import { CountsRangesButtons } from "./CountsRangesButtons";
import { useDeployHistory } from "./useDeployHistory";
import { predefinedRanges } from "./utils";
import { StyledRangesWrapper } from "./CountsStyled";
import { useActivityHistory } from "./useActivityHistory";

interface RangesProps {
label: string;
Expand All @@ -16,16 +16,17 @@ interface RangesProps {
export function CountsRanges({ label, onChange }: RangesProps): JSX.Element {
const { t } = useTranslation<string>();
const processName = useSelector(getProcessName);
const deploys = useDeployHistory(processName);
const processCategory = useSelector(getProcessingType);
const activities = useActivityHistory(processName, processCategory);
const dates = useMemo(() => predefinedRanges(t), [t]);

return (
<>
<p>{label}</p>
<StyledRangesWrapper>
<CountsRangesButtons ranges={dates} onChange={onChange} />
<CountsRangesButtons ranges={deploys} onChange={onChange} limit={1}>
{t("calculateCounts.deployments", "Previous deployments...")}
<CountsRangesButtons ranges={activities} onChange={onChange} limit={1}>
{t("calculateCounts.activities", "Previous activities...")}
</CountsRangesButtons>
</StyledRangesWrapper>
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import HttpService from "../../../http/HttpService";
import { DATE_FORMAT } from "../../../config";
import { Range } from "./CountsRangesButtons";
import moment from "moment";
import { ActivityTypesRelatedToExecutions } from "../../toolbars/activities/types";

function displayableNameOfPredefinedActivityType(predefinedActivityType: ActivityTypesRelatedToExecutions) {
switch (predefinedActivityType) {
case ActivityTypesRelatedToExecutions.ScenarioCanceled:
return "Cancel";
case ActivityTypesRelatedToExecutions.ScenarioDeployed:
return "Deployment";
case ActivityTypesRelatedToExecutions.PerformedScheduledExecution:
return "Scheduled deployment";
case ActivityTypesRelatedToExecutions.PerformedSingleExecution:
return "Run now";
default:
return "Unknown activity type";
}
}
/*
In the context of batch processing, the information about a performed deployment does not provide meaningful insights for range calculations.
This is because batch processes do not execute immediately after a deployment action. To address this, deployment-related activities
(of type `ScenarioDeployed`) are excluded when computing ranges for batch processes.
Additionally, the `Cancel` activity type (`ScenarioCanceled`) plays a role in determining count ranges during internal processing,
but it is not relevant to the end user. As a result, activities with this type are filtered out at the end of the computation process
(handled using the `isOmitted` variable).
*/
export function useActivityHistory(processName: string, processingMode: string): Range[] {
const { t } = useTranslation();
const [activities, setActivities] = useState<Range[]>([]);

useEffect(() => {
HttpService.fetchActivitiesRelatedToExecutions(processName)
.then((activities) =>
processingMode.includes("batch")
? activities.filter((activity) => activity.type !== ActivityTypesRelatedToExecutions.ScenarioDeployed)
: activities,
)
.then((activities) =>
activities.map((current, i, all) => {
const from = moment(current.date);
const to = all[i - 1]?.date;
const isOmitted = current.type === ActivityTypesRelatedToExecutions.ScenarioCanceled;
return {
from: () => from,
to: () => (to ? moment(to) : moment().add(1, "day").startOf("day")),
name: t("calculateCounts.range.prevAction", "{{activity}} {{date}}", {
activity: displayableNameOfPredefinedActivityType(current.type),
date: from.format(DATE_FORMAT),
}),
isOmitted,
};
}),
)
.then((res) => res.filter((activity) => !activity.isOmitted))
.then((res) => {
res[0].name = t("calculateCounts.range.lastAction", "Latest Run");
return res;
})
.then(setActivities);
}, [t, processName]);

return activities;
}

This file was deleted.

7 changes: 7 additions & 0 deletions designer/client/src/components/toolbars/activities/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ export type ActivityType =
| "AUTOMATIC_UPDATE"
| "CUSTOM_ACTION";

export enum ActivityTypesRelatedToExecutions {
ScenarioDeployed = "SCENARIO_DEPLOYED",
ScenarioCanceled = "SCENARIO_CANCELED",
PerformedSingleExecution = "PERFORMED_SINGLE_EXECUTION",
PerformedScheduledExecution = "PERFORMED_SCHEDULED_EXECUTION",
}

export interface ActivityMetadata {
type: ActivityType;
displayableName: string;
Expand Down
27 changes: 16 additions & 11 deletions designer/client/src/http/HttpService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ import {
Scenario,
StatusDefinitionType,
} from "../components/Process/types";
import { ActivitiesResponse, ActivityMetadataResponse } from "../components/toolbars/activities/types";
import {
ActivitiesResponse,
ActivityMetadataResponse,
ActivityType,
ActivityTypesRelatedToExecutions,
} from "../components/toolbars/activities/types";
import { ToolbarsConfig } from "../components/toolbarSettings/types";
import { EventTrackingSelectorType, EventTrackingType } from "../containers/event-tracking";
import { BackendNotification } from "../containers/Notifications";
Expand Down Expand Up @@ -321,17 +326,17 @@ class HttpService {
return promise;
}

fetchProcessesDeployments(processName: string) {
fetchActivitiesRelatedToExecutions(processName: string) {
return api
.get<
{
performedAt: string;
actionName: ActionName;
}[]
>(`/processes/${encodeURIComponent(processName)}/deployments`)
.then((res) =>
res.data.filter(({ actionName }) => actionName === PredefinedActionName.Deploy).map(({ performedAt }) => performedAt),
);
.get<{ activities: { date: string; type: ActivityType }[] }>(
`/processes/${encodeURIComponent(processName)}/activity/activities`,
)
.then((res) => {
return res.data.activities.filter(({ date, type }) =>
Object.values(ActivityTypesRelatedToExecutions).includes(type as ActivityTypesRelatedToExecutions),
);
})
.then((res) => res.reverse().map((item) => ({ ...item, type: item.type as ActivityTypesRelatedToExecutions })));
}

deploy(
Expand Down

0 comments on commit eddddc6

Please sign in to comment.