Skip to content

Commit

Permalink
Pull request update/240105
Browse files Browse the repository at this point in the history
53931d2 OS-7206. Fixed var name in herald
ca1bd6c OS-7206. Fixed param name in herald
d8290e0 OS-7206. Fixed typos in variable name in herald
a637663 OS-7198. Add search for leaderboard details runs table
42c6dc2 OS-7191. Cover Setup leaderboards button with permission
78890ef OS-7197. Add pagination for leaderboard details runs table
aefa0dd OS-7189. Cover leaderboard actions with permission
  • Loading branch information
maxb-hystax authored Jan 5, 2024
2 parents e03f60b + 53931d2 commit 24de390
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 75 deletions.
8 changes: 4 additions & 4 deletions herald/modules/email_generator/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,23 @@ def _generate_context(template_params, config_client):
def update_template(template, params):
for key, value in params.items():
if isinstance(value, collections.abc.Mapping):
template[k] = update_template(template.get(key, {}), value)
template[key] = update_template(template.get(key, {}), value)
else:
template[k] = value
template[key] = value
return template

def get_numbered_params(params_dict):
numbered_dict = {}
for key, value in params_dict.items():
if isinstance(value, numbers.Number):
numbered_dict[k] = value
numbered_dict[key] = value
return numbered_dict

def update_template_style(numbered_dict):
style = {}
display_visibility_name = 'element_visibility_%s'
for key, value in numbered_dict.items():
style[display_visibility_name % k] = 'table-row' if value else 'none'
style[display_visibility_name % key] = 'table-row' if value else 'none'
return style

def generate_control_panel_parameters(organization_map):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,24 @@ import LeaderboardDatasetDetailsTable from "components/MlModelLeaderboard/compon
import SubTitle from "components/SubTitle";
import TableLoader from "components/TableLoader";
import TypographyLoader from "components/TypographyLoader";
import { useIsAllowed } from "hooks/useAllowedActions";

const Title = ({ leaderboard, leaderboardDataset, isLoading }) =>
isLoading ? (
<TypographyLoader />
) : (
const Title = ({ leaderboard, leaderboardDataset }) => {
const isManageLeaderboardDatasetAllowed = useIsAllowed({ requiredActions: ["EDIT_PARTNER"] });

return (
<Box display="flex" alignItems="center" flexWrap="wrap">
<SubTitle sx={{ whiteSpace: "normal", overflowWrap: "anywhere" }}>{leaderboardDataset.name}</SubTitle>
<Box>
<EditLeaderboardDatasetIconButton leaderboardDataset={leaderboardDataset} />
<CopyLeaderboardDatasetIconButton leaderboard={leaderboard} leaderboardDataset={leaderboardDataset} />
<DeleteLeaderboardDatasetButton leaderboardDataset={leaderboardDataset} />
</Box>
{isManageLeaderboardDatasetAllowed && (
<Box>
<EditLeaderboardDatasetIconButton leaderboardDataset={leaderboardDataset} />
<CopyLeaderboardDatasetIconButton leaderboard={leaderboard} leaderboardDataset={leaderboardDataset} />
<DeleteLeaderboardDatasetButton leaderboardDataset={leaderboardDataset} />
</Box>
)}
</Box>
);
};

const Datasets = ({ datasets = [], isLoading }) =>
isLoading ? (
Expand Down Expand Up @@ -54,7 +58,11 @@ const LeaderboardDatasetDetails = ({ leaderboard, leaderboardDataset, leaderboar
return (
<Stack overflow="auto" flexGrow={1} spacing={1}>
<div>
<Title leaderboard={leaderboard} leaderboardDataset={leaderboardDataset} isLoading={isGetLeaderboardDatasetLoading} />
{isGetLeaderboardDatasetLoading ? (
<TypographyLoader />
) : (
<Title leaderboard={leaderboard} leaderboardDataset={leaderboardDataset} isLoading={isGetLeaderboardDatasetLoading} />
)}
</div>
<div>
<Datasets datasets={leaderboardDataset.datasets} isLoading={isGetLeaderboardDatasetLoading} />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useMemo } from "react";
import { useCallback, useMemo } from "react";
import { Link, Stack, Typography } from "@mui/material";
import { FormattedMessage } from "react-intl";
import { Link as RouterLink } from "react-router-dom";
import CaptionedCell from "components/CaptionedCell";
import DynamicFractionDigitsValue from "components/DynamicFractionDigitsValue";
import { useFormatDynamicFractionDigitsValue } from "components/DynamicFractionDigitsValue";
import KeyValueLabel from "components/KeyValueLabel";
import SubTitle from "components/SubTitle";
import Table from "components/Table";
Expand All @@ -15,9 +15,19 @@ import { dataset } from "utils/columns";
import { SPACING_2 } from "utils/layouts";
import { formatRunFullName } from "utils/ml";

const RUNS_TABLE_ROWS_PER_PAGE = 10;

const useFormatRunTimeAgo = () => {
const formatIntervalTimeAgo = useFormatIntervalTimeAgo();

return useCallback((finish) => formatIntervalTimeAgo(finish, 1), [formatIntervalTimeAgo]);
};

const RunsTable = ({ runGroupPrimaryMetric, runGroupSecondaryMetrics, runsData }) => {
const tableData = useMemo(() => runsData, [runsData]);
const formatIntervalTimeAgo = useFormatIntervalTimeAgo();

const formatRunTimeAgo = useFormatRunTimeAgo();
const formatDynamicFractionDigitsValue = useFormatDynamicFractionDigitsValue();

const columns = useMemo(
() => [
Expand All @@ -33,10 +43,17 @@ const RunsTable = ({ runGroupPrimaryMetric, runGroupSecondaryMetrics, runsData }
const search = filterValue.toLocaleLowerCase();

const {
original: { runset_name: runsetName = "" }
original: { runset_name: runsetName, finish }
} = row;

return [runName, runsetName].some((str) => str.toLocaleLowerCase().includes(search));
const timeAgo = formatRunTimeAgo(finish);

return [
runName,
timeAgo,
// runsetName can be null
runsetName ?? ""
].some((str) => str.toLocaleLowerCase().includes(search));
},
sortingFn: "alphanumeric",
cell: ({ cell, row: { original } }) => {
Expand All @@ -46,7 +63,7 @@ const RunsTable = ({ runGroupPrimaryMetric, runGroupSecondaryMetrics, runsData }
<CaptionedCell
caption={[
{
node: <Typography variant="caption">{formatIntervalTimeAgo(finish, 1)}</Typography>,
node: <Typography variant="caption">{formatRunTimeAgo(finish)}</Typography>,
key: "timeAgo"
},
...(runsetName
Expand Down Expand Up @@ -85,11 +102,16 @@ const RunsTable = ({ runGroupPrimaryMetric, runGroupSecondaryMetrics, runsData }
...[runGroupPrimaryMetric, ...runGroupSecondaryMetrics].map(({ key, name }) => ({
header: <TextWithDataTestId dataTestId={`lbl_${key}`}>{name}</TextWithDataTestId>,
id: key,
searchFn: (value, filterValue) => {
const search = filterValue.toLocaleLowerCase();

return formatDynamicFractionDigitsValue({ value }).includes(search);
},
accessorFn: (originalRow) => originalRow.data?.[key]?.value,
cell: ({ cell }) => <DynamicFractionDigitsValue value={cell.getValue()} />
cell: ({ cell }) => formatDynamicFractionDigitsValue({ value: cell.getValue() })
}))
],
[formatIntervalTimeAgo, runGroupPrimaryMetric, runGroupSecondaryMetrics]
[formatDynamicFractionDigitsValue, formatRunTimeAgo, runGroupPrimaryMetric, runGroupSecondaryMetrics]
);

return (
Expand All @@ -99,6 +121,10 @@ const RunsTable = ({ runGroupPrimaryMetric, runGroupSecondaryMetrics, runsData }
localization={{
emptyMessageId: "noRuns"
}}
withSearch
pageSize={RUNS_TABLE_ROWS_PER_PAGE}
enablePaginationQueryParam={false}
enableSearchQueryParam={false}
/>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,79 +1,90 @@
import { Box, Typography } from "@mui/material";
import { FormattedMessage } from "react-intl";
import LeaderboardDatasetDetailsContainer from "containers/LeaderboardDatasetDetailsContainer";
import { useIsAllowed } from "hooks/useAllowedActions";
import { isEmpty as isEmptyArray } from "utils/arrays";
import AddLeaderboardCriteriaButton from "./AddLeaderboardCriteriaButton";
import LeaderboardDatasetCard from "./LeaderboardDatasetCard";

const NoLeaderboards = ({ leaderboardId }) => (
<Box>
<Typography gutterBottom>
<FormattedMessage id="noLeaderboards" />
</Typography>
<AddLeaderboardCriteriaButton leaderboardId={leaderboardId} />
</Box>
);
const NoLeaderboards = ({ leaderboardId }) => {
const isAddLeaderboardCriteriaAllowed = useIsAllowed({ requiredActions: ["EDIT_PARTNER"] });

return (
<Box>
<Typography gutterBottom>
<FormattedMessage id="noLeaderboards" />
</Typography>
{isAddLeaderboardCriteriaAllowed && <AddLeaderboardCriteriaButton leaderboardId={leaderboardId} />}
</Box>
);
};

const LeaderboardDatasetsListSection = ({
leaderboard,
leaderboardDatasets,
selectedLeaderboardDataset,
onSelectedLeaderboardDashboardChange
}) => (
<Box
sx={{
display: "flex",
gap: 1,
alignItems: "center",
flexDirection: {
xs: "row",
md: "column"
},
justifyContent: {
xs: "space-between",
md: "normal"
}
}}
>
<AddLeaderboardCriteriaButton
leaderboardId={leaderboard.id}
sx={{
width: {
md: "100%"
},
order: {
xs: 1,
md: 0
}
}}
/>
}) => {
const isAddLeaderboardCriteriaAllowed = useIsAllowed({ requiredActions: ["EDIT_PARTNER"] });

return (
<Box
sx={{
display: "flex",
gap: 1,
overflow: "auto",
minWidth: "150px",
alignItems: "center",
flexDirection: {
xs: "row",
md: "column"
},
justifyContent: {
xs: "space-between",
md: "normal"
}
}}
>
{selectedLeaderboardDataset &&
leaderboardDatasets.map((leaderboardDataset) => {
const isSelected = leaderboardDataset.id === selectedLeaderboardDataset.id;
return (
<LeaderboardDatasetCard
key={leaderboard.id}
leaderboardDataset={leaderboardDataset}
onClick={() => onSelectedLeaderboardDashboardChange(leaderboardDataset)}
selected={isSelected}
/>
);
})}
{isAddLeaderboardCriteriaAllowed && (
<AddLeaderboardCriteriaButton
leaderboardId={leaderboard.id}
sx={{
width: {
md: "100%"
},
order: {
xs: 1,
md: 0
}
}}
/>
)}
<Box
sx={{
display: "flex",
gap: 1,
overflow: "auto",
minWidth: "150px",
flexDirection: {
xs: "row",
md: "column"
}
}}
>
{selectedLeaderboardDataset &&
leaderboardDatasets.map((leaderboardDataset) => {
const isSelected = leaderboardDataset.id === selectedLeaderboardDataset.id;
return (
<LeaderboardDatasetCard
key={leaderboard.id}
leaderboardDataset={leaderboardDataset}
onClick={() => onSelectedLeaderboardDashboardChange(leaderboardDataset)}
selected={isSelected}
/>
);
})}
</Box>
</Box>
</Box>
);
);
};

const LeaderboardDatasets = ({
leaderboard,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ import { FormattedMessage, useIntl } from "react-intl";
import { useParams } from "react-router-dom";
import finopsCloudCostOptimization from "assets/ml/leaderbords.svg";
import Button from "components/Button";
import { useIsAllowed } from "hooks/useAllowedActions";
import { getMlSetupLeaderboards } from "urls";
import { SPACING_1, SPACING_2 } from "utils/layouts";

const SetupLeaderboardsInvitation = () => {
const intl = useIntl();
const { taskId } = useParams();

const isLeaderboardSetupEnabled = useIsAllowed({ requiredActions: ["EDIT_PARTNER"] });

return (
<Stack alignItems="center" spacing={SPACING_1} mt={SPACING_2}>
<img
Expand All @@ -25,7 +28,11 @@ const SetupLeaderboardsInvitation = () => {
<FormattedMessage id="nothingToShowHereYet" />
</Box>
<Box>
<Button messageId="setupLeaderboards" color="primary" variant="contained" link={getMlSetupLeaderboards(taskId)} />
{isLeaderboardSetupEnabled ? (
<Button messageId="setupLeaderboards" color="primary" variant="contained" link={getMlSetupLeaderboards(taskId)} />
) : (
<FormattedMessage id="leaderboardContactManagerMessage" />
)}
</Box>
</Stack>
);
Expand Down
1 change: 1 addition & 0 deletions ngui/ui/src/translations/en-US/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -974,6 +974,7 @@
"latest": "Latest",
"launch": "Launch",
"leaderboard": "Leaderboard",
"leaderboardContactManagerMessage": "Please contact your organization manager to setup a leadearboard.",
"leaderboardQualificationProtocol.coverDatasets": "Run should cover the following datasets:",
"leaderboardQualificationProtocol.metricRestrictions": "Run should fit the following metric restrictions:",
"leaderboards": "Leaderboards",
Expand Down
9 changes: 9 additions & 0 deletions ngui/ui/src/utils/columns/dataset.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ const dataset = ({ id, accessorFn, accessorKey }) => ({
<FormattedMessage id="dataset" />
</TextWithDataTestId>
),
searchFn: (_, filterValue, { row }) => {
const search = filterValue.toLocaleLowerCase();

const { dataset: rowDataset } = row.original;

const { name, path, labels = [] } = rowDataset;

return [name, path, labels.join(" ")].some((str) => str.toLocaleLowerCase().includes(search));
},
cell: ({ row: { original } }) => {
const { dataset: rowDataset } = original;

Expand Down

0 comments on commit 24de390

Please sign in to comment.