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

add protocol for prediction_context display #49

Merged
merged 4 commits into from
Nov 4, 2022
Merged
Show file tree
Hide file tree
Changes from 2 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
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { ConfigProvider } from "config";
import { ExperimentsConfigGroup } from "./experiments_config/ExperimentsConfigGroup";
import { VariablesConfigGroup } from "./variables_config/VariablesConfigGroup";

const ExperimentEngineConfigDetails = ({ projectId, config }) => (
const ExperimentEngineConfigDetails = ({ projectId, protocol, config }) => (
<ConfigProvider>
<EuiFlexGroup direction="row" wrap>
<EuiFlexItem grow={1} className="euiFlexItem--smallPanel">
Expand All @@ -20,8 +20,12 @@ const ExperimentEngineConfigDetails = ({ projectId, config }) => (
<EuiFlexItem grow={2} className="euiFlexItem--smallPanel">
<ConfigSectionPanel
title="Variables"
className="experimentVariablesPanel">
<VariablesConfigGroup variables={config.variables} />
className="experimentVariablesPanel"
>
<VariablesConfigGroup
variables={config.variables}
protocol={protocol}
/>
</ConfigSectionPanel>
</EuiFlexItem>
</EuiFlexGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import React from "react";

import { EuiBasicTable, EuiTextColor, EuiTitle } from "@elastic/eui";
import { EuiBasicTable, EuiText, EuiTextColor, EuiTitle } from "@elastic/eui";

export const VariablesConfigGroup = ({ variables }) => {
import { mapProtocolLabel } from "turing/components/utils/helper";

export const VariablesConfigGroup = ({ variables, protocol }) => {
const columns = [
{
field: "name",
Expand All @@ -28,6 +30,9 @@ export const VariablesConfigGroup = ({ variables }) => {
field: "field_source",
name: "Source",
width: "30%",
render: (value) => (
<EuiText size="s">{mapProtocolLabel(protocol, value)}</EuiText>
),
},
];

Expand Down
5 changes: 4 additions & 1 deletion ui/src/turing/components/form/EditExperimentEngineConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { VariablesConfigPanel } from "./variables_config/VariablesConfigPanel";

const EditExperimentEngineConfigComponent = ({
projectId,
protocol,
config = {},
onChangeHandler,
errors = {},
Expand Down Expand Up @@ -41,6 +42,7 @@ const EditExperimentEngineConfigComponent = ({
<VariablesConfigPanel
projectId={projectId}
variables={config.variables}
protocol={protocol}
onChangeHandler={onChange("variables")}
errors={get(errors, "variables")}
/>
Expand All @@ -50,7 +52,8 @@ const EditExperimentEngineConfigComponent = ({
<EuiCallOut
title="Project not onboarded to Experiments"
color="danger"
iconType="alert">
iconType="alert"
>
<p>
{
"Please complete onboarding to Turing experiments to configure the router."
Expand Down
29 changes: 22 additions & 7 deletions ui/src/turing/components/form/EditStandardEnsemblerConfig.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import React, { useContext, useRef } from "react";

import { EuiCallOut, EuiFlexItem, EuiLoadingChart, EuiHorizontalRule } from "@elastic/eui";
import {
EuiCallOut,
EuiFlexItem,
EuiHorizontalRule,
EuiLoadingChart,
} from "@elastic/eui";
import { OverlayMask } from "@gojek/mlp-ui";

import { Panel } from "components/panel/Panel";
import { ConfigProvider, useConfig } from "config";
import ProjectContext, { ProjectContextProvider } from "providers/project/context";
import { ExperimentContextProvider } from "providers/experiment/context";
import ProjectContext, {
ProjectContextProvider,
} from "providers/project/context";

import { LinkedRoutesTable } from "./standard_ensembler/LinkedRoutesTable";
import { RouteNamePathRow } from "./standard_ensembler/RouteNamePathRow";

Expand All @@ -17,7 +25,9 @@ const EditStandardEnsemblerConfigComponent = ({
onChange,
errors,
}) => {
const { appConfig: { routeNamePathPrefix } } = useConfig();
const {
appConfig: { routeNamePathPrefix },
} = useConfig();

const { isProjectOnboarded, isLoaded } = useContext(ProjectContext);
const overlayRef = useRef();
Expand All @@ -40,7 +50,9 @@ const EditStandardEnsemblerConfigComponent = ({
<LinkedRoutesTable
projectId={projectId}
routes={routes}
treatmentConfigRouteNamePath={routeNamePath.slice(routeNamePathPrefix.length)}
treatmentConfigRouteNamePath={routeNamePath.slice(
routeNamePathPrefix.length
)}
/>
</ExperimentContextProvider>
</Panel>
Expand All @@ -49,9 +61,12 @@ const EditStandardEnsemblerConfigComponent = ({
<EuiCallOut
title={"Project not onboarded to Experiments"}
color={"danger"}
iconType={"alert"}>
iconType={"alert"}
>
<p>
{"Please complete onboarding to Turing experiments to configure the standard ensembler."}
{
"Please complete onboarding to Turing experiments to configure the standard ensembler."
}
</p>
</EuiCallOut>
</Panel>
Expand All @@ -74,7 +89,7 @@ const EditStandardEnsemblerConfig = (props) => {
<EditStandardEnsemblerConfigComponent {...props} />
</ProjectContextProvider>
</ConfigProvider>
)
);
};

export default EditStandardEnsemblerConfig;
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import React from "react";

import {
EuiContextMenu,
EuiPopover,
EuiButtonEmpty,
EuiContextMenu,
EuiIcon,
EuiLink,
EuiIcon
EuiPopover,
} from "@elastic/eui";
import { useToggle } from "@gojek/mlp-ui";

export const LinkedExperimentsContextMenu = ({
projectId,
linkedExperiments,
experimentStatus
experimentStatus,
}) => {
const [isPopoverOpen, togglePopover] = useToggle();

Expand Down Expand Up @@ -41,28 +41,32 @@ export const LinkedExperimentsContextMenu = ({
>
<EuiContextMenu
initialPanelId={0}
panels={
[
{
id: 0,
title: `Linked ${experimentStatus[0].toUpperCase() + experimentStatus.slice(1)} Experiments`,
items: Object.values(linkedExperiments[experimentStatus]).map(e => (
{
name: (
<EuiLink href={`/turing/projects/${projectId}/experiments/${e.id}/details`} external={false} target={"_blank"}>
{e.name}
</EuiLink>
),
icon: <EuiIcon type={"popout"} size={"m"} color={"primary"} />,
size: "s",
toolTipContent: "Open experiment details page",
toolTipPosition: "right",
}
))
}
]
}
panels={[
{
id: 0,
title: `Linked ${
experimentStatus[0].toUpperCase() + experimentStatus.slice(1)
} Experiments`,
items: Object.values(linkedExperiments[experimentStatus]).map(
(e) => ({
name: (
<EuiLink
href={`/turing/projects/${projectId}/experiments/${e.id}/details`}
external={false}
target={"_blank"}
>
{e.name}
</EuiLink>
),
icon: <EuiIcon type={"popout"} size={"m"} color={"primary"} />,
size: "s",
toolTipContent: "Open experiment details page",
toolTipPosition: "right",
})
),
},
]}
/>
</EuiPopover>
);
};
};
111 changes: 73 additions & 38 deletions ui/src/turing/components/form/standard_ensembler/LinkedRoutesTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,56 +2,83 @@ import React, { useContext, useEffect, useState } from "react";

import {
EuiFlexItem,
EuiIcon,
EuiInMemoryTable,
EuiLoadingChart,
EuiTextAlign,
EuiInMemoryTable,
EuiIcon,
EuiTextColor,
} from "@elastic/eui";

import ExperimentContext from "providers/experiment/context";
import { getExperimentStatus } from "services/experiment/ExperimentStatus";

import { LinkedExperimentsContextMenu } from "./LinkedExperimentsContextMenu";
import ExperimentContext from "providers/experiment/context";

export const LinkedRoutesTable = ({
projectId,
routes,
treatmentConfigRouteNamePath,
}) => {
const { allExperiments, isAllExperimentsLoaded } = useContext(ExperimentContext)
const { allExperiments, isAllExperimentsLoaded } =
useContext(ExperimentContext);

const [routeToExperimentMappings, setRouteToExperimentMappings] = useState(routes.reduce((m, r) => {m[r.id] = {running: {}, scheduled: {}}; return m}, {}));
const [routeToExperimentMappings, setRouteToExperimentMappings] = useState(
routes.reduce((m, r) => {
m[r.id] = { running: {}, scheduled: {} };
return m;
}, {})
);

const getRouteName = (config, path) => path.split('.').reduce((obj, key) => obj && obj[key], config);
const getRouteName = (config, path) =>
path.split(".").reduce((obj, key) => obj && obj[key], config);

// this stringified value of routes below allows the React effect below to mimic a deep comparison when changes to the
// array routes are made
const stringifiedRoutes = routes.map(e => e.id).join();
const stringifiedRoutes = routes.map((e) => e.id).join();

// reset loaded routeToExperimentMappings if treatmentConfigRouteNamePath or routes changes
useEffect(() => {
if (isAllExperimentsLoaded) {
let newRouteToExperimentMappings = routes.reduce((m, r) => {m[r.id] = {running: {}, scheduled: {}}; return m}, {});
let newRouteToExperimentMappings = routes.reduce((m, r) => {
m[r.id] = { running: {}, scheduled: {} };
return m;
}, {});
for (let experiment of allExperiments) {
for (let treatment of experiment.treatments) {
let configRouteName = getRouteName(treatment.configuration, treatmentConfigRouteNamePath);
if (typeof configRouteName === 'string' && configRouteName in newRouteToExperimentMappings) {
newRouteToExperimentMappings[configRouteName][getExperimentStatus(experiment).label.toLowerCase()][experiment.id] = experiment;
let configRouteName = getRouteName(
treatment.configuration,
treatmentConfigRouteNamePath
);
if (
typeof configRouteName === "string" &&
configRouteName in newRouteToExperimentMappings
) {
newRouteToExperimentMappings[configRouteName][
getExperimentStatus(experiment).label.toLowerCase()
][experiment.id] = experiment;
}
}
}
setRouteToExperimentMappings(newRouteToExperimentMappings);
}
}, [treatmentConfigRouteNamePath, stringifiedRoutes, routes, isAllExperimentsLoaded, allExperiments]);
}, [
treatmentConfigRouteNamePath,
stringifiedRoutes,
routes,
isAllExperimentsLoaded,
allExperiments,
]);

const columns = [
{
field: "id",
width: "5px",
render: (id) => {
const isAssigned = routeToExperimentMappings[id] ?
Object.keys(routeToExperimentMappings[id].running).length +
Object.keys(routeToExperimentMappings[id].scheduled).length > 0 : false;
const isAssigned = routeToExperimentMappings[id]
? Object.keys(routeToExperimentMappings[id].running).length +
Object.keys(routeToExperimentMappings[id].scheduled).length >
0
: false;
return (
<EuiIcon
type={isAssigned ? "check" : "cross"}
Expand All @@ -67,35 +94,43 @@ export const LinkedRoutesTable = ({
width: "20%",
name: "Route Name",
render: (id) => {
const isAssigned = routeToExperimentMappings[id] ?
Object.keys(routeToExperimentMappings[id].running).length +
Object.keys(routeToExperimentMappings[id].scheduled).length > 0 : false;
return (<EuiTextColor color={isAssigned ? "success" : "danger"}>{id}</EuiTextColor>);
const isAssigned = routeToExperimentMappings[id]
? Object.keys(routeToExperimentMappings[id].running).length +
Object.keys(routeToExperimentMappings[id].scheduled).length >
0
: false;
return (
<EuiTextColor color={isAssigned ? "success" : "danger"}>
{id}
</EuiTextColor>
);
},
},
{
field: "id",
width: "35%",
name: "Running Experiments",
render: (id) => routeToExperimentMappings[id] && (
<LinkedExperimentsContextMenu
projectId={projectId}
linkedExperiments={routeToExperimentMappings[id]}
experimentStatus={"running"}
/>
),
render: (id) =>
routeToExperimentMappings[id] && (
<LinkedExperimentsContextMenu
projectId={projectId}
linkedExperiments={routeToExperimentMappings[id]}
experimentStatus={"running"}
/>
),
},
{
field: "id",
width: "35%",
name: "Scheduled Experiments",
render: (id) => routeToExperimentMappings[id] && (
<LinkedExperimentsContextMenu
projectId={projectId}
linkedExperiments={routeToExperimentMappings[id]}
experimentStatus={"scheduled"}
/>
)
render: (id) =>
routeToExperimentMappings[id] && (
<LinkedExperimentsContextMenu
projectId={projectId}
linkedExperiments={routeToExperimentMappings[id]}
experimentStatus={"scheduled"}
/>
),
},
];

Expand All @@ -108,9 +143,9 @@ export const LinkedRoutesTable = ({
isSelectable={false}
/>
</EuiFlexItem>
) : (
<EuiTextAlign textAlign={"center"}>
<EuiLoadingChart size={"xl"} mono />
</EuiTextAlign>
);
) : (
<EuiTextAlign textAlign={"center"}>
<EuiLoadingChart size={"xl"} mono />
</EuiTextAlign>
);
};
Loading