Skip to content

Commit

Permalink
Add standard ensembler UI (#37)
Browse files Browse the repository at this point in the history
* Add standard ensembler component

* Simplify react effects used in affected routes list panel

* Add popover to list the affected experiments

* Fix empty titles in EuiDescriptionList

* Add context menu to display affected experiments

* Fix styles in prop passing

* Add tooltip and color to affected experiments menu

* Add standard ensembler config view

* Fix lint comments

* Add help flyout to explain route name path prefix

* Update deprecated subdued EUI colour with colour hex

* Rename affected experiments and routes component to linked experiments and routes

* Reword route path prefix explanation

* Fix lint comments

* Fix incorrect language type specified for code block

* Replace style used to pass items to the list in RouteNamePathConfigGroup

* Rename misleading variable names and remove redundant tags

* Replace relative import path with absolute path

* Replace colour hexes corresponding to subdued to default

* Refactor experiments loading into a context provider

* Standardise naming of all providers to be singular wherever logical

* Make popover management distributed across each component

* Refactor LinkedRoutesTable to utilise id from list of routes to render rows

* Revert incorrect edit made to docstrings

* Refactor LinkedRoutesTable

* Consume route name path in flyout from config

* Simplify effect dependency on routes in LinkedRoutesTable
  • Loading branch information
deadlycoconuts authored Sep 26, 2022
1 parent 0419432 commit 734b0ab
Show file tree
Hide file tree
Showing 40 changed files with 606 additions and 63 deletions.
2 changes: 2 additions & 0 deletions ui/craco.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ module.exports = ({ }) => ({
"./EditExperimentEngineConfig": "./src/turing/components/form/EditExperimentEngineConfig",
"./ExperimentEngineConfigDetails": "./src/turing/components/configuration/ExperimentEngineConfigDetails",
"./ExperimentsLandingPage": "./src/experiments/ExperimentsLandingPage",
"./EditStandardEnsemblerConfig": "./src/turing/components/form/EditStandardEnsemblerConfig",
"./StandardEnsemblerConfigDetails": "./src/turing/components/configuration/StandardEnsemblerConfigDetails"
},
filename: "remoteEntry.js",
shared: {
Expand Down
1 change: 1 addition & 0 deletions ui/src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export const appConfig = {
// Padding of page template
paddingSize: "none",
},
routeNamePathPrefix: "treatment.configuration."
};

const sentryConfig = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { useDimension, useToggle } from "@gojek/mlp-ui";
import { ConfigPanel } from "components/config_section/ConfigPanel";
import { ConfigSectionFlyout } from "components/config_section/ConfigSectionFlyout";
import { ExpandableTableColumn } from "components/table/ExpandableTableColumn";
import SegmenterContext from "providers/segmenters/context";
import SegmenterContext from "providers/segmenter/context";
import { stringifySegmenterValue } from "services/experiment/Segment";

export const SegmentConfigSection = ({ experiment }) => {
Expand Down Expand Up @@ -148,5 +148,5 @@ const ExperimentSegmentTable = ({ items, projectSegmenters, buttonAction }) => {
},
];

return <EuiInMemoryTable items={items} columns={columns}></EuiInMemoryTable>;
return <EuiInMemoryTable items={items} columns={columns} />;
};
2 changes: 1 addition & 1 deletion ui/src/experiments/components/form/CreateExperimentForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { EuiLoadingChart, EuiTextAlign } from "@elastic/eui";
import { FormContext, StepsWizardHorizontal, addToast } from "@gojek/mlp-ui";

import { useXpApi } from "hooks/useXpApi";
import SegmenterContext from "providers/segmenters/context";
import SegmenterContext from "providers/segmenter/context";
import SettingsContext from "providers/settings/context";

import { GeneralStep } from "./steps/GeneralStep";
Expand Down
2 changes: 1 addition & 1 deletion ui/src/experiments/components/form/EditExperimentForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { AccordionForm, FormContext, addToast } from "@gojek/mlp-ui";

import { ConfigSectionTitle } from "components/config_section/ConfigSectionTitle";
import { useXpApi } from "hooks/useXpApi";
import SegmenterContext from "providers/segmenters/context";
import SegmenterContext from "providers/segmenter/context";
import SettingsContext from "providers/settings/context";

import { GeneralStep } from "./steps/GeneralStep";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
import { OverlayMask, get } from "@gojek/mlp-ui";

import { useXpApi } from "hooks/useXpApi";
import SegmenterContext from "providers/segmenters/context";
import SegmenterContext from "providers/segmenter/context";

import { SegmenterConfigRow } from "./SegmenterConfigRow";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
} from "@elastic/eui";

import { Panel } from "components/panel/Panel";
import SegmentsContext from "providers/segment/context";
import SegmentContext from "providers/segment/context";

import { SegmentConfigPanel } from "./SegmentConfigPanel";

Expand All @@ -19,7 +19,7 @@ export const SegmentSelectionPanel = ({
onChange,
errors = [],
}) => {
const { isLoaded, segments } = useContext(SegmentsContext);
const { isLoaded, segments } = useContext(SegmentContext);

const segmentSelectionOptions = segments.map((segment) => {
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
} from "@elastic/eui";

import { useXpApi } from "hooks/useXpApi";
import TreatmentsContext from "providers/treatment/context";
import TreatmentContext from "providers/treatment/context";

import { TreatmentPanel } from "./TreatmentPanel";

Expand All @@ -25,7 +25,7 @@ export const TreatmentCard = ({
projectId,
errors = {},
}) => {
const { isLoaded, treatments } = useContext(TreatmentsContext);
const { isLoaded, treatments } = useContext(TreatmentContext);
const [treatmentId, setTreatmentId] = useState();
const [hasNewResponse, setHasNewResponse] = useState(false);

Expand Down
14 changes: 7 additions & 7 deletions ui/src/experiments/create/CreateExperimentView.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import { FormContextProvider, replaceBreadcrumbs } from "@gojek/mlp-ui";

import { PageTitle } from "components/page/PageTitle";
import { CreateExperimentForm } from "experiments/components/form/CreateExperimentForm";
import { SegmentsContextProvider } from "providers/segment/context";
import { SegmenterContextProvider } from "providers/segmenters/context";
import { SegmentContextProvider } from "providers/segment/context";
import { SegmenterContextProvider } from "providers/segmenter/context";
import { SettingsContextProvider } from "providers/settings/context";
import { TreatmentsContextProvider } from "providers/treatment/context";
import { TreatmentContextProvider } from "providers/treatment/context";
import { Experiment } from "services/experiment/Experiment";
import { useConfig } from "config";

Expand Down Expand Up @@ -39,23 +39,23 @@ const CreateExperimentView = ({ projectId, ...props }) => {

<EuiSpacer size="m" />
<EuiPageTemplate.Section color={"transparent"}>
<TreatmentsContextProvider projectId={projectId}>
<TreatmentContextProvider projectId={projectId}>
<FormContextProvider data={new Experiment()}>
<SettingsContextProvider projectId={projectId}>
<SegmenterContextProvider projectId={projectId} status="active">
<SegmentsContextProvider projectId={projectId}>
<SegmentContextProvider projectId={projectId}>
<CreateExperimentForm
projectId={projectId}
onCancel={() => window.history.back()}
onSuccess={(experimentId) =>
props.navigate(`../${experimentId}`)
}
/>
</SegmentsContextProvider>
</SegmentContextProvider>
</SegmenterContextProvider>
</SettingsContextProvider>
</FormContextProvider>
</TreatmentsContextProvider>
</TreatmentContextProvider>
</EuiPageTemplate.Section>

<EuiSpacer size="l" />
Expand Down
2 changes: 1 addition & 1 deletion ui/src/experiments/details/config/ExperimentConfigView.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { ConfigSection } from "components/config_section/ConfigSection";
import { GeneralInfoConfigSection } from "experiments/components/configuration/GeneralInfoConfigSection";
import { SegmentConfigSection } from "experiments/components/configuration/SegmentConfigSection";
import { TreatmentConfigSection } from "experiments/components/configuration/TreatmentConfigSection";
import { SegmenterContextProvider } from "providers/segmenters/context";
import { SegmenterContextProvider } from "providers/segmenter/context";

export const ExperimentConfigView = ({ experiment }) => {
const generalInfo = {
Expand Down
14 changes: 7 additions & 7 deletions ui/src/experiments/edit/EditExperimentView.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { EuiPageTemplate, EuiSpacer } from "@elastic/eui";
import { FormContextProvider, replaceBreadcrumbs } from "@gojek/mlp-ui";

import { EditExperimentForm } from "experiments/components/form/EditExperimentForm";
import { SegmentsContextProvider } from "providers/segment/context";
import { SegmenterContextProvider } from "providers/segmenters/context";
import { SegmentContextProvider } from "providers/segment/context";
import { SegmenterContextProvider } from "providers/segmenter/context";
import { SettingsContextProvider } from "providers/settings/context";
import { TreatmentsContextProvider } from "providers/treatment/context";
import { TreatmentContextProvider } from "providers/treatment/context";
import { Experiment } from "services/experiment/Experiment";
import { PageTitle } from "components/page/PageTitle";

Expand All @@ -28,23 +28,23 @@ const EditExperimentView = ({ projectId, experimentSpec, ...props }) => {
/>
<EuiSpacer size="l" />
<EuiPageTemplate.Section color={"transparent"}>
<TreatmentsContextProvider projectId={projectId}>
<TreatmentContextProvider projectId={projectId}>
<FormContextProvider data={Experiment.fromJson(experimentSpec)}>
<SettingsContextProvider projectId={projectId}>
<SegmenterContextProvider projectId={projectId} status="active">
<SegmentsContextProvider projectId={projectId}>
<SegmentContextProvider projectId={projectId}>
<EditExperimentForm
projectId={projectId}
onCancel={() => window.history.back()}
onSuccess={() =>
props.navigate("../", { state: { refresh: true } })
}
/>
</SegmentsContextProvider>
</SegmentContextProvider>
</SegmenterContextProvider>
</SettingsContextProvider>
</FormContextProvider>
</TreatmentsContextProvider>
</TreatmentContextProvider>
</EuiPageTemplate.Section>
</Fragment>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { GeneralInfoConfigSection } from "experiments/components/configuration/G
import { SegmentConfigSection } from "experiments/components/configuration/SegmentConfigSection";
import { TreatmentConfigSection } from "experiments/components/configuration/TreatmentConfigSection";
import { useXpApi } from "hooks/useXpApi";
import { SegmenterContextProvider } from "providers/segmenters/context";
import { SegmenterContextProvider } from "providers/segmenter/context";
import { useConfig } from "config";
import { VersionBadge } from "components/version_badge/VersionBadge";

Expand Down
2 changes: 1 addition & 1 deletion ui/src/experiments/list/search/SearchExperimentsFilters.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
experimentTypes,
} from "experiments/components/typeOptions";

import SegmenterContext from "providers/segmenters/context";
import SegmenterContext from "providers/segmenter/context";
import { extractErrors } from "utils/helpers";

import ExperimentDateFilter from "./components/ExperimentDateFilter";
Expand Down
2 changes: 1 addition & 1 deletion ui/src/experiments/list/search/SearchExperimentsPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from "react";

import { EuiButton, EuiFlyout, EuiFlyoutFooter } from "@elastic/eui";

import { SegmenterContextProvider } from "providers/segmenters/context";
import { SegmenterContextProvider } from "providers/segmenter/context";

import SearchExperimentsFilters from "./SearchExperimentsFilters";

Expand Down
64 changes: 64 additions & 0 deletions ui/src/providers/experiment/context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React, {useEffect, useMemo, useState} from "react";

import { useXpApi } from "hooks/useXpApi";
import moment from "moment";
import { useConfig } from "config";

const ExperimentContext = React.createContext({});

export const ExperimentContextProvider = ({ projectId, children }) => {
const { appConfig } = useConfig();

const [isAllExperimentsLoaded, setIsAllExperimentsLoaded] = useState(false);
const [pageIndex, setPageIndex] = useState(0);
const [allExperiments, setAllExperiments] = useState([]);

const { start_time, end_time } = useMemo(
() => {
let current_time = moment.utc();
let start_time = current_time.format(appConfig.datetime.format);
let end_time = current_time.add(1000, "y").format(appConfig.datetime.format);
return { start_time, end_time };
},
[appConfig]
);

const [{ data: { data: experiments, paging }, isLoaded }] = useXpApi(
`/projects/${projectId}/experiments`,
{
query: {
start_time: start_time,
end_time: end_time,
page: pageIndex + 1,
page_size: appConfig.pagination.defaultPageSize,
status: "active"
},
},
{ data: [], paging: { total: 0 } }
);

useEffect(() => {
if (isLoaded) {
if (!!experiments && !isAllExperimentsLoaded) {
setAllExperiments((curExperiments) => [...curExperiments, ...experiments]);
}
if (paging.pages > paging.page) {
setPageIndex(paging.page);
} else {
setIsAllExperimentsLoaded(true);
}
}
}, [isLoaded, experiments, paging, isAllExperimentsLoaded]);

return (
<ExperimentContext.Provider
value={{
allExperiments,
isAllExperimentsLoaded,
}}>
{children}
</ExperimentContext.Provider>
);
};

export default ExperimentContext;
10 changes: 5 additions & 5 deletions ui/src/providers/segment/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import React from "react";

import { useXpApi } from "hooks/useXpApi";

const SegmentsContext = React.createContext({});
const SegmentContext = React.createContext({});

export const SegmentsContextProvider = ({ projectId, children }) => {
export const SegmentContextProvider = ({ projectId, children }) => {
const [
{
data: { data: segments },
Expand All @@ -21,14 +21,14 @@ export const SegmentsContextProvider = ({ projectId, children }) => {
);

return (
<SegmentsContext.Provider
<SegmentContext.Provider
value={{
segments,
isLoaded: isLoaded,
}}>
{children}
</SegmentsContext.Provider>
</SegmentContext.Provider>
);
};

export default SegmentsContext;
export default SegmentContext;
File renamed without changes.
10 changes: 5 additions & 5 deletions ui/src/providers/treatment/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import React from "react";

import { useXpApi } from "hooks/useXpApi";

const TreatmentsContext = React.createContext({});
const TreatmentContext = React.createContext({});

export const TreatmentsContextProvider = ({ projectId, children }) => {
export const TreatmentContextProvider = ({ projectId, children }) => {
const [
{
data: { data: treatments },
Expand All @@ -21,14 +21,14 @@ export const TreatmentsContextProvider = ({ projectId, children }) => {
);

return (
<TreatmentsContext.Provider
<TreatmentContext.Provider
value={{
treatments,
isLoaded: isLoaded,
}}>
{children}
</TreatmentsContext.Provider>
</TreatmentContext.Provider>
);
};

export default TreatmentsContext;
export default TreatmentContext;
2 changes: 1 addition & 1 deletion ui/src/segments/components/form/CreateSegmentForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { AccordionForm, FormContext, addToast } from "@gojek/mlp-ui";

import { ConfigSectionTitle } from "components/config_section/ConfigSectionTitle";
import { useXpApi } from "hooks/useXpApi";
import SegmenterContext from "providers/segmenters/context";
import SegmenterContext from "providers/segmenter/context";

import { ConfigurationStep } from "./steps/ConfigurationStep";
import schema from "./validation/schema";
Expand Down
2 changes: 1 addition & 1 deletion ui/src/segments/components/form/EditSegmentForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { AccordionForm, FormContext, addToast } from "@gojek/mlp-ui";

import { ConfigSectionTitle } from "components/config_section/ConfigSectionTitle";
import { useXpApi } from "hooks/useXpApi";
import SegmenterContext from "providers/segmenters/context";
import SegmenterContext from "providers/segmenter/context";

import { ConfigurationStep } from "./steps/ConfigurationStep";
import schema from "./validation/schema";
Expand Down
8 changes: 4 additions & 4 deletions ui/src/segments/create/CreateSegmentView.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import {
import { FormContextProvider, replaceBreadcrumbs } from "@gojek/mlp-ui";

import { PageTitle } from "components/page/PageTitle";
import { SegmentsContextProvider } from "providers/segment/context";
import { SegmenterContextProvider } from "providers/segmenters/context";
import { SegmentContextProvider } from "providers/segment/context";
import { SegmenterContextProvider } from "providers/segmenter/context";
import { CreateSegmentForm } from "segments/components/form/CreateSegmentForm";
import { CustomSegment } from "services/segment/CustomSegment";
import { useConfig } from "config";
Expand Down Expand Up @@ -39,13 +39,13 @@ const CreateSegmentView = ({ projectId, ...props }) => {
<EuiPageTemplate.Section color={"transparent"}>
<FormContextProvider data={new CustomSegment()}>
<SegmenterContextProvider projectId={projectId} status="active">
<SegmentsContextProvider projectId={projectId}>
<SegmentContextProvider projectId={projectId}>
<CreateSegmentForm
projectId={projectId}
onCancel={() => window.history.back()}
onSuccess={(segmentId) => props.navigate(`../${segmentId}`)}
/>
</SegmentsContextProvider>
</SegmentContextProvider>
</SegmenterContextProvider>
</FormContextProvider>
<EuiSpacer size="l" />
Expand Down
2 changes: 1 addition & 1 deletion ui/src/segments/details/config/SegmentConfigView.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { replaceBreadcrumbs } from "@gojek/mlp-ui";
import { ActivityConfigSection } from "components/config_section/ActivityConfigSection";
import { ConfigSection } from "components/config_section/ConfigSection";
import { SegmentConfigSection } from "experiments/components/configuration/SegmentConfigSection";
import { SegmenterContextProvider } from "providers/segmenters/context";
import { SegmenterContextProvider } from "providers/segmenter/context";

export const SegmentConfigView = ({ segment }) => {
const activity = {
Expand Down
Loading

0 comments on commit 734b0ab

Please sign in to comment.