This is an automated email from the ASF dual-hosted git repository. yashmayya pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/pinot.git
The following commit(s) were added to refs/heads/master by this push: new 196de1d54f [bugfix][ui] Fixes for table rebalance UI (#15511) 196de1d54f is described below commit 196de1d54f2af4550949f821b9adf99cccc3d3fc Author: Soumya Himanish Mohapatra <30361728+himanish-s...@users.noreply.github.com> AuthorDate: Fri Apr 11 14:21:24 2025 +0530 [bugfix][ui] Fixes for table rebalance UI (#15511) --- .../RebalanceServer/RebalanceResponse.tsx | 44 ++++++++++++++++++++-- .../RebalanceServerConfigurationOption.tsx | 16 ++++++-- .../RebalanceServerConfigurationOptionInteger.tsx | 8 +++- .../RebalanceServerConfigurationOptionSelect.tsx | 8 +++- ...alanceServerConfigurationOptionToggleSwitch.tsx | 8 +++- .../RebalanceServerResponseLabelValue.tsx | 2 +- .../Operations/RebalanceServerStatusOp.tsx | 36 ++++++++++-------- .../Homepage/Operations/RebalanceServerTableOp.tsx | 22 +++++++++-- .../src/main/resources/app/utils/Utils.tsx | 13 ++++++- 9 files changed, 123 insertions(+), 34 deletions(-) diff --git a/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServer/RebalanceResponse.tsx b/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServer/RebalanceResponse.tsx index b7550e7683..d9ebf9df1c 100644 --- a/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServer/RebalanceResponse.tsx +++ b/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServer/RebalanceResponse.tsx @@ -18,7 +18,7 @@ */ import {RebalanceServerSection} from "./RebalanceServerSection"; import React from 'react'; -import {Grid, Paper} from "@material-ui/core"; +import {Box, Grid, IconButton, Paper, Snackbar, Typography} from "@material-ui/core"; import CustomCodemirror from "../../../CustomCodemirror"; import { RebalanceServerSectionResponse @@ -29,7 +29,31 @@ import { RebalanceServerRebalanceSummaryResponse } from "./RebalanceServerResponses/RebalanceServerRebalanceSummaryResponse"; import {RebalanceServerResponseCard} from "./RebalanceServerResponses/RebalanceServerResponseCard"; +import {FileCopyOutlined} from "@material-ui/icons"; +const CopyJobIdToClipboardButton = ({ jobId }: { jobId: string }) => { + const [open, setOpen] = React.useState<boolean>(false); + + const handleClick = () => { + setOpen(true); + navigator.clipboard.writeText(jobId); + }; + + return ( + <> + <IconButton onClick={handleClick} color="primary"> + <FileCopyOutlined color="disabled" fontSize="small" /> + </IconButton> + <Snackbar + message="Copied job id to clibboard" + anchorOrigin={{ vertical: "top", horizontal: "center" }} + autoHideDuration={2000} + onClose={() => setOpen(false)} + open={open} + /> + </> + ); +}; export const RebalanceResponse = ({ response }) => { const responseSectionsToShow = [ { @@ -54,7 +78,15 @@ export const RebalanceResponse = ({ response }) => { <Grid container spacing={2}> <Grid item xs={6}><RebalanceServerResponseLabelValue label='Description' value={response.description} /></Grid> <Grid item xs={6}><RebalanceServerResponseLabelValue label='Status' value={response.status} /></Grid> - <Grid item xs={6}><RebalanceServerResponseLabelValue label='Job Id' value={response.jobId} /></Grid> + <Grid item xs={6}> + <Typography color='textSecondary' variant='caption'>Job Id</Typography> + <Box flexDirection="row" display="flex" alignItems="center" marginTop={-1.25}> + <Typography style={{ fontWeight: 600 }} variant='body2'> + {response.jobId} + </Typography> + <CopyJobIdToClipboardButton jobId={response.jobId} /> + </Box> + </Grid> </Grid> </RebalanceServerSection> </Paper> @@ -64,7 +96,13 @@ export const RebalanceResponse = ({ response }) => { { responseSectionsToShow.map((section) => { if (Object.keys(response).includes(section.key)) { - return <RebalanceServerSectionResponse key={section.key} sectionTitle={section.name} sectionData={response[section.key]} /> + return ( + <Grid item xs={12}> + <RebalanceServerResponseCard> + <RebalanceServerSectionResponse key={section.key} sectionTitle={section.name} sectionData={response[section.key]} /> + </RebalanceServerResponseCard> + </Grid> + ); } }) } diff --git a/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServer/RebalanceServerConfigurationOption.tsx b/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServer/RebalanceServerConfigurationOption.tsx index 180c230621..7a20f8e9ac 100644 --- a/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServer/RebalanceServerConfigurationOption.tsx +++ b/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServer/RebalanceServerConfigurationOption.tsx @@ -29,14 +29,22 @@ import { } from "./RebalanceServerConfigurationOptions/RebalanceServerConfigurationOptionSelect"; export const RebalanceServerConfigurationOption = ( - { option, handleConfigChange }: { option: RebalanceServerOption, handleConfigChange: (config: { [key: string]: string | number | boolean }) => void }) => { + { + option, + handleConfigChange, + rebalanceConfig + }: { + option: RebalanceServerOption, + handleConfigChange: (config: { [key: string]: string | number | boolean }) => void + rebalanceConfig: { [optionName: string]: string | boolean | number }, + }) => { switch (option.type) { case "BOOL": - return <RebalanceServerConfigurationOptionSwitch option={option} handleConfigChange={handleConfigChange} />; + return <RebalanceServerConfigurationOptionSwitch rebalanceConfig={rebalanceConfig} option={option} handleConfigChange={handleConfigChange} />; case "INTEGER": - return <RebalanceServerConfigurationOptionInteger option={option} handleConfigChange={handleConfigChange} />; + return <RebalanceServerConfigurationOptionInteger rebalanceConfig={rebalanceConfig} option={option} handleConfigChange={handleConfigChange} />; case "SELECT": - return <RebalanceServerConfigurationOptionSelect option={option} handleConfigChange={handleConfigChange} />; + return <RebalanceServerConfigurationOptionSelect rebalanceConfig={rebalanceConfig} option={option} handleConfigChange={handleConfigChange} />; default: return null; } diff --git a/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServer/RebalanceServerConfigurationOptions/RebalanceServerConfigurationOptionInteger.tsx b/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServer/RebalanceServerConfigurationOptions/RebalanceServerConfigurationOptionInteger.tsx index a209bdf73e..b5b99dbccc 100644 --- a/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServer/RebalanceServerConfigurationOptions/RebalanceServerConfigurationOptionInteger.tsx +++ b/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServer/RebalanceServerConfigurationOptions/RebalanceServerConfigurationOptionInteger.tsx @@ -22,15 +22,19 @@ import {RebalanceServerOption} from "../RebalanceServerOptions"; import { RebalanceServerConfigurationOptionLabel } from "./RebalanceServerConfigurationOptionLabel/RebalanceServerConfigurationOptionLabel"; +import Utils from "../../../../../utils/Utils"; type RebalanceServerConfigurationOptionIntegerProps = { option: RebalanceServerOption; handleConfigChange: (config: { [key: string]: string | number | boolean }) => void; + rebalanceConfig: { [optionName: string]: string | boolean | number }; } export const RebalanceServerConfigurationOptionInteger = ( - { option, handleConfigChange }: RebalanceServerConfigurationOptionIntegerProps + { option, handleConfigChange, rebalanceConfig }: RebalanceServerConfigurationOptionIntegerProps ) => { - const [value, setValue] = useState<number>(option.defaultValue as number); + const [value, setValue] = useState<number>( + Utils.getRebalanceConfigValue(rebalanceConfig, option) as number + ); return ( <Box display='flex' flexDirection='column'> <FormControl fullWidth> diff --git a/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServer/RebalanceServerConfigurationOptions/RebalanceServerConfigurationOptionSelect.tsx b/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServer/RebalanceServerConfigurationOptions/RebalanceServerConfigurationOptionSelect.tsx index 5ed6e83478..adc1dcc5cb 100644 --- a/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServer/RebalanceServerConfigurationOptions/RebalanceServerConfigurationOptionSelect.tsx +++ b/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServer/RebalanceServerConfigurationOptions/RebalanceServerConfigurationOptionSelect.tsx @@ -24,15 +24,19 @@ import {RebalanceServerOption} from "../RebalanceServerOptions"; import { RebalanceServerConfigurationOptionLabel } from "./RebalanceServerConfigurationOptionLabel/RebalanceServerConfigurationOptionLabel"; +import Utils from "../../../../../utils/Utils"; type RebalanceServerConfigurationOptionSelectProps = { option: RebalanceServerOption; handleConfigChange: (config: { [key: string]: string | number | boolean }) => void; + rebalanceConfig: { [optionName: string]: string | boolean | number }; } export const RebalanceServerConfigurationOptionSelect = ( - { option, handleConfigChange }: RebalanceServerConfigurationOptionSelectProps + { option, handleConfigChange, rebalanceConfig }: RebalanceServerConfigurationOptionSelectProps ) => { - const [value, setValue] = useState<string>(option.defaultValue as string); + const [value, setValue] = useState<string>( + Utils.getRebalanceConfigValue(rebalanceConfig, option) as string + ); return ( <Box display='flex' flexDirection='column'> <FormControl fullWidth={true}> diff --git a/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServer/RebalanceServerConfigurationOptions/RebalanceServerConfigurationOptionToggleSwitch.tsx b/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServer/RebalanceServerConfigurationOptions/RebalanceServerConfigurationOptionToggleSwitch.tsx index e4f2f06448..40671437dc 100644 --- a/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServer/RebalanceServerConfigurationOptions/RebalanceServerConfigurationOptionToggleSwitch.tsx +++ b/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServer/RebalanceServerConfigurationOptions/RebalanceServerConfigurationOptionToggleSwitch.tsx @@ -22,14 +22,18 @@ import {RebalanceServerOption} from "../RebalanceServerOptions"; import { RebalanceServerConfigurationOptionLabel } from "./RebalanceServerConfigurationOptionLabel/RebalanceServerConfigurationOptionLabel"; +import Utils from "../../../../../utils/Utils"; type RebalanceServerConfigurationOptionSwitchProps = { option: RebalanceServerOption; handleConfigChange: (config: { [key: string]: string | number | boolean }) => void; + rebalanceConfig: { [optionName: string]: string | boolean | number }; } export const RebalanceServerConfigurationOptionSwitch = ( - { option, handleConfigChange }: RebalanceServerConfigurationOptionSwitchProps) => { - const [isChecked, setIsChecked] = useState<boolean>(option.defaultValue as boolean); + { option, handleConfigChange, rebalanceConfig }: RebalanceServerConfigurationOptionSwitchProps) => { + const [isChecked, setIsChecked] = useState<boolean>( + Utils.getRebalanceConfigValue(rebalanceConfig, option) as boolean + ); return ( <Box display='flex' flexDirection='column'> <FormControlLabel diff --git a/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServer/RebalanceServerResponses/RebalanceServerResponseLabelValue.tsx b/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServer/RebalanceServerResponses/RebalanceServerResponseLabelValue.tsx index 093185de4e..d12027da41 100644 --- a/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServer/RebalanceServerResponses/RebalanceServerResponseLabelValue.tsx +++ b/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServer/RebalanceServerResponses/RebalanceServerResponseLabelValue.tsx @@ -25,7 +25,7 @@ export const RebalanceServerResponseLabelValue = ( return ( <Box> <Typography color='textSecondary' variant='caption'>{label}</Typography> - <Typography style={{ fontWeight: 600 }} variant='body2'>{value}</Typography> + <Typography style={{ fontWeight: 600, whiteSpace: "pre" }} variant='body2'>{value}</Typography> </Box> ); } diff --git a/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServerStatusOp.tsx b/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServerStatusOp.tsx index d5a8cc910e..0effe8e0c0 100644 --- a/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServerStatusOp.tsx +++ b/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServerStatusOp.tsx @@ -29,16 +29,17 @@ import CustomizedTables from "../../Table"; import Utils from "../../../utils/Utils"; import PinotMethodUtils from "../../../utils/PinotMethodUtils"; +type RebalanceTableSegmentJob = { + jobId: string; + messageCount: number; + submissionTimeMs: number; + jobType: string; + tableName: string; + REBALANCE_PROGRESS_STATS: string; + REBALANCE_CONTEXT: string; +} export type RebalanceTableSegmentJobs = { - [key: string]: { - jobId: string, - messageCount: number, - submissionTimeMs: number, - jobType: string, - tableName: string, - REBALANCE_PROGRESS_STATS: string, - REBALANCE_CONTEXT: string; - } + [key: string]: RebalanceTableSegmentJob; } type RebalanceServerStatusOpProps = { @@ -49,7 +50,7 @@ type RebalanceServerStatusOpProps = { export const RebalanceServerStatusOp = ( { tableName, hideModal } : RebalanceServerStatusOpProps ) => { - const [rebalanceServerJobs, setRebalanceServerJobs] = React.useState<RebalanceTableSegmentJobs>({}) + const [rebalanceServerJobs, setRebalanceServerJobs] = React.useState<RebalanceTableSegmentJob[]>([]) const [jobSelected, setJobSelected] = useState<string | null>(null); const [rebalanceContext, setRebalanceContext] = useState<{}>({}); const [rebalanceProgressStats, setRebalanceProgressStats] = useState<{}>({}); @@ -63,7 +64,10 @@ export const RebalanceServerStatusOp = ( if (jobs.error) { return; } - setRebalanceServerJobs(jobs as RebalanceTableSegmentJobs) + const sortedJobs: RebalanceTableSegmentJob[] = Object.keys(jobs as RebalanceTableSegmentJobs) + .map(jobId => jobs[jobId] as RebalanceTableSegmentJob) + .sort((j1, j2) => j1.submissionTimeMs < j2.submissionTimeMs ? 1 : -1); + setRebalanceServerJobs(sortedJobs); }) .finally(() => setLoading(false)); }, []); @@ -137,13 +141,13 @@ export const RebalanceServerStatusOp = ( setJobSelected(cell); }} data={{ - records: Object.keys(rebalanceServerJobs).map(jobId => { - const progressStats = JSON.parse(rebalanceServerJobs[jobId].REBALANCE_PROGRESS_STATS); + records: rebalanceServerJobs.map(rebalanceServerJob => { + const progressStats = JSON.parse(rebalanceServerJob.REBALANCE_PROGRESS_STATS); return [ - rebalanceServerJobs[jobId].jobId, - rebalanceServerJobs[jobId].tableName, + rebalanceServerJob.jobId, + rebalanceServerJob.tableName, progressStats.status, - Utils.formatTime(+rebalanceServerJobs[jobId].submissionTimeMs) + Utils.formatTime(+rebalanceServerJob.submissionTimeMs) ]; }), columns: ['Job id', 'Table name', 'Status', 'Started at'] diff --git a/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServerTableOp.tsx b/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServerTableOp.tsx index 5fb17fd4eb..ff85fa3b52 100644 --- a/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServerTableOp.tsx +++ b/pinot-controller/src/main/resources/app/components/Homepage/Operations/RebalanceServerTableOp.tsx @@ -47,6 +47,14 @@ const DryRunAction = ({ handleOnRun, disabled }: { handleOnRun: () => void, disa ); } +const BackAction = ({ onClick }: { onClick: () => void }) => { + return ( + <Button onClick={onClick} variant="outlined" color="primary"> + Back + </Button> + ); +} + export default function RebalanceServerTableOp({ hideModal, tableName, @@ -127,6 +135,10 @@ export default function RebalanceServerTableOp({ ) } + const handleBackBtnOnClick = () => { + setRebalanceResponse(null); + } + return ( <Dialog showTitleDivider @@ -139,7 +151,11 @@ export default function RebalanceServerTableOp({ handleSave={handleSave} btnOkText='Rebalance' showOkBtn={!rebalanceResponse} - moreActions={!rebalanceResponse ? <DryRunAction disabled={pending} handleOnRun={handleDryRun} /> : null} + moreActions={ + !rebalanceResponse ? + <DryRunAction disabled={pending} handleOnRun={handleDryRun} /> : + <BackAction onClick={handleBackBtnOnClick} /> + } > {!rebalanceResponse ? <Box flexDirection="column"> @@ -156,7 +172,7 @@ export default function RebalanceServerTableOp({ <Grid container spacing={2}> {rebalanceServerOptions.filter(option => !option.isAdvancedConfig && !option.isStatsGatheringConfig).map((option) => ( <Grid item xs={12} key={`basic-options-${option.name}`}> - <RebalanceServerConfigurationOption option={option} handleConfigChange={handleConfigChange} /> + <RebalanceServerConfigurationOption rebalanceConfig={rebalanceConfig} option={option} handleConfigChange={handleConfigChange} /> </Grid> ))} </Grid> @@ -166,7 +182,7 @@ export default function RebalanceServerTableOp({ <Grid container spacing={2}> {rebalanceServerOptions.filter(option => option.isAdvancedConfig).map((option) => ( <Grid item xs={12} key={`advanced-options-${option.name}`}> - <RebalanceServerConfigurationOption option={option} handleConfigChange={handleConfigChange} /> + <RebalanceServerConfigurationOption rebalanceConfig={rebalanceConfig} option={option} handleConfigChange={handleConfigChange} /> </Grid> ))} </Grid> diff --git a/pinot-controller/src/main/resources/app/utils/Utils.tsx b/pinot-controller/src/main/resources/app/utils/Utils.tsx index 30904765fd..35023694a1 100644 --- a/pinot-controller/src/main/resources/app/utils/Utils.tsx +++ b/pinot-controller/src/main/resources/app/utils/Utils.tsx @@ -32,6 +32,16 @@ import { } from 'Models'; import Loading from '../components/Loading'; import moment from "moment"; +import {RebalanceServerOption} from "../components/Homepage/Operations/RebalanceServer/RebalanceServerOptions"; + +const getRebalanceConfigValue = ( + rebalanceConfig: { [optionName: string]: string | boolean | number }, + option: RebalanceServerOption +) => { + return ( + Object.keys(rebalanceConfig).includes(option.name) ? rebalanceConfig[option.name] : option.defaultValue + ); +} const sortArray = function (sortingArr, keyName, ascendingFlag) { if (ascendingFlag) { @@ -483,5 +493,6 @@ export default { pinotTableDetailsFormat, pinotTableDetailsFromArray, getLoadingTableData, - formatTime + formatTime, + getRebalanceConfigValue }; --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org For additional commands, e-mail: commits-h...@pinot.apache.org