From 50cae38d94f12c18db5b104e574739e79c1416af Mon Sep 17 00:00:00 2001 From: Yue Yang Date: Wed, 22 Jul 2020 15:20:49 +0800 Subject: [PATCH] chore: dashboard patch of #720 and #713 (#724) * chore: correct case of experiments state Signed-off-by: Yue Yang * chore: patch of #713 Signed-off-by: Yue Yang Co-authored-by: ti-srebot <66930949+ti-srebot@users.noreply.github.com> --- ui/src/api/experiments.ts | 12 +++---- ui/src/api/experiments.type.ts | 25 ++++++++------- ui/src/components/EventsTable/index.tsx | 2 +- ui/src/components/ExperimentPaper/index.tsx | 35 +++++---------------- ui/src/components/NewExperiment/index.tsx | 24 +++++--------- ui/src/components/StatusPanel/index.tsx | 10 +++--- ui/src/lib/d3/eventsChart.ts | 23 +++++++++----- ui/src/pages/Archives/index.tsx | 4 +-- ui/src/pages/ExperimentDetail/index.tsx | 35 ++++++++------------- ui/src/pages/Experiments/index.tsx | 12 +++---- ui/src/routes.tsx | 2 +- ui/src/slices/experiments.ts | 12 +++---- 12 files changed, 79 insertions(+), 117 deletions(-) diff --git a/ui/src/api/experiments.ts b/ui/src/api/experiments.ts index bfac05f0b0..65504630e4 100644 --- a/ui/src/api/experiments.ts +++ b/ui/src/api/experiments.ts @@ -15,14 +15,10 @@ export const experiments: ( ) => Promise> = (namespace = '', name = '', kind = '', status = '') => http.get(`/experiments?namespace=${namespace}&name=${name}&kind=${kind}&status=${status}`) -export const deleteExperiment = (namespace: string, name: string, kind: string) => - http.delete(`/experiments/${kind}/${namespace}/${name}`) +export const deleteExperiment = (uuid: uuid) => http.delete(`/experiments/${uuid}`) -export const pauseExperiment = (namespace: string, name: string, kind: string) => - http.put(`/experiments/pause/${kind}/${namespace}/${name}`) +export const pauseExperiment = (uuid: uuid) => http.put(`/experiments/pause/${uuid}`) -export const startExperiment = (namespace: string, name: string, kind: string) => - http.put(`/experiments/start/${kind}/${namespace}/${name}`) +export const startExperiment = (uuid: uuid) => http.put(`/experiments/start/${uuid}`) -export const detail = (namespace: string, name: string, kind: string) => - http.get(`/experiments/detail/${kind}/${namespace}/${name}`) +export const detail = (uuid: uuid) => http.get(`/experiments/detail/${uuid}`) diff --git a/ui/src/api/experiments.type.ts b/ui/src/api/experiments.type.ts index 81da55a98c..11a27e41f2 100644 --- a/ui/src/api/experiments.type.ts +++ b/ui/src/api/experiments.type.ts @@ -1,21 +1,21 @@ import { Event } from './events.type' export interface StateOfExperiments { - total: number - running: number - waiting: number - paused: number - failed: number - finished: number + Total: number + Running: number + Waiting: number + Paused: number + Failed: number + Finished: number } export enum StateOfExperimentsEnum { - total = 'total', - running = 'running', - waiting = 'waiting', - paused = 'paused', - failed = 'failed', - finished = 'finished', + Total = 'total', + Running = 'running', + Waiting = 'waiting', + Paused = 'paused', + Failed = 'failed', + Finished = 'finished', } export interface Experiment { @@ -24,5 +24,6 @@ export interface Experiment { Name: string created: string status: keyof StateOfExperiments + uid: uuid events?: Event[] } diff --git a/ui/src/components/EventsTable/index.tsx b/ui/src/components/EventsTable/index.tsx index a95f30648d..f44f5d906e 100644 --- a/ui/src/components/EventsTable/index.tsx +++ b/ui/src/components/EventsTable/index.tsx @@ -196,7 +196,7 @@ const EventsTableRow: React.FC = ({ event: e, detailed, noE @@ -158,7 +139,7 @@ const ExperimentPaper: React.FC = ({ {!isArchive && - ((e as Experiment).status.toLowerCase() === 'failed' ? ( + ((e as Experiment).status === 'Failed' ? ( ) : ( diff --git a/ui/src/components/NewExperiment/index.tsx b/ui/src/components/NewExperiment/index.tsx index d5722aa82b..8e0905e076 100644 --- a/ui/src/components/NewExperiment/index.tsx +++ b/ui/src/components/NewExperiment/index.tsx @@ -43,16 +43,13 @@ const Actions = ({ setInitialValues }: ActionsProps) => { // const [archiveRadio, setArchiveRadio] = useState('') const onExperimentRadioChange = (e: any) => { - const kindNamespaceName = e.target.value - const [kind, namespace, name] = kindNamespaceName.split('/') + const uuid = e.target.value - setExperimentRadio(kindNamespaceName) + setExperimentRadio(uuid) api.experiments - .detail(namespace, name, kind) - .then(({ data }) => { - setInitialValues(parseLoaded(data)) - }) + .detail(uuid) + .then(({ data }) => setInitialValues(parseLoaded(data))) .catch(console.log) } @@ -62,19 +59,17 @@ const Actions = ({ setInitialValues }: ActionsProps) => { // setArchiveRadio(uuid) // } - const fetchExperiments = () => { + const fetchExperiments = () => api.experiments .experiments() .then(({ data }) => setExperiments(data)) .catch(console.log) - } - // const fetchArchives = () => { + // const fetchArchives = () => // api.archives // .archives() // .then(({ data }) => setArchives(data)) // .catch(console.log) - // } useEffect(() => { fetchExperiments() @@ -116,12 +111,7 @@ const Actions = ({ setInitialValues }: ActionsProps) => { {experiments && experiments.length > 0 ? ( experiments.map((e) => ( - } - label={e.Name} - /> + } label={e.Name} /> )) ) : experiments?.length === 0 ? ( No experiments found. diff --git a/ui/src/components/StatusPanel/index.tsx b/ui/src/components/StatusPanel/index.tsx index 5e4482e109..d58897bea1 100644 --- a/ui/src/components/StatusPanel/index.tsx +++ b/ui/src/components/StatusPanel/index.tsx @@ -55,27 +55,27 @@ const StatusPanel = () => { const data: { [k: string]: d } = { running: { label: 'Running', - value: state.running, + value: state.Running, Icon: , }, paused: { label: 'Paused', - value: state.paused, + value: state.Paused, Icon: , }, failed: { label: 'Failed', - value: state.failed, + value: state.Failed, Icon: , }, waiting: { label: 'Waiting', - value: state.waiting, + value: state.Waiting, Icon: , }, finished: { label: 'Finished', - value: state.finished, + value: state.Finished, Icon: , }, } diff --git a/ui/src/lib/d3/eventsChart.ts b/ui/src/lib/d3/eventsChart.ts index 63d979b846..c1e3b618ed 100644 --- a/ui/src/lib/d3/eventsChart.ts +++ b/ui/src/lib/d3/eventsChart.ts @@ -45,10 +45,17 @@ export default function gen({ // Wrap long text, also used in zoom() and reGen() svg.selectAll('.tick text').call(wrapText, 30) - const allExperiments = [...new Set(events.map((d) => d.Experiment))] + const allUniqueExperiments = [...new Set(events.map((d) => d.Experiment + '/' + d.ExperimentID))].map((d) => { + const [name, uuid] = d.split('/') + + return { + name, + uuid, + } + }) const y = d3 .scaleBand() - .domain(allExperiments) + .domain(allUniqueExperiments.map((d) => d.uuid)) .range([0, height - margin.top - margin.bottom]) .padding(0.5) const yAxis = d3.axisLeft(y).tickFormat('' as any) @@ -79,11 +86,11 @@ export default function gen({ const legendsRoot = d3.select(document.createElement('div')).attr('class', 'chaos-events-legends') const legends = legendsRoot .selectAll() - .data(allExperiments) + .data(allUniqueExperiments) .enter() .append('div') .on('click', function (d) { - const _events = events.filter((e) => e.Experiment === d) + const _events = events.filter((e) => e.ExperimentID === d.uuid) const event = _events[_events.length - 1] svg @@ -100,12 +107,12 @@ export default function gen({ legends .insert('div') .attr('style', 'color: rgba(0, 0, 0, 0.72); font-size: 0.75rem;') - .text((d) => d) + .text((d) => d.name) legends .append('div') .attr( 'style', - (d) => `width: 14px; height: 14px; margin-left: 8px; background: ${colorPalette(d)}; cursor: pointer;` + (d) => `width: 14px; height: 14px; margin-left: 8px; background: ${colorPalette(d.uuid)}; cursor: pointer;` ) function genRectWidth(d: Event) { @@ -124,10 +131,10 @@ export default function gen({ .enter() .append('rect') .attr('x', (d) => x(day(d.StartTime))) - .attr('y', (d) => y(d.Experiment)! + margin.top) + .attr('y', (d) => y(d.ExperimentID)! + margin.top) .attr('width', genRectWidth) .attr('height', y.bandwidth()) - .attr('fill', (d) => colorPalette(d.Experiment)) + .attr('fill', (d) => colorPalette(d.ExperimentID)) .style('cursor', 'pointer') const zoom = d3.zoom().scaleExtent([0.1, 5]).on('zoom', zoomd) diff --git a/ui/src/pages/Archives/index.tsx b/ui/src/pages/Archives/index.tsx index af851060c4..1d3b3e3e40 100644 --- a/ui/src/pages/Archives/index.tsx +++ b/ui/src/pages/Archives/index.tsx @@ -12,9 +12,7 @@ export default function Archives() { const [loading, setLoading] = useState(false) const [archives, setArchives] = useState(null) const [selected, setSelected] = useState({ - namespace: '', - name: '', - kind: '', + uuid: '', title: '', description: '', action: 'recover', diff --git a/ui/src/pages/ExperimentDetail/index.tsx b/ui/src/pages/ExperimentDetail/index.tsx index fb7bc4d836..e3c7fd2e98 100644 --- a/ui/src/pages/ExperimentDetail/index.tsx +++ b/ui/src/pages/ExperimentDetail/index.tsx @@ -79,11 +79,10 @@ export default function ExperimentDetail() { const history = useHistory() const { search } = history.location const searchParams = new URLSearchParams(search) - const namespace = searchParams.get('namespace') - const kind = searchParams.get('kind') + const name = searchParams.get('name') const eventID = searchParams.get('event') const status = searchParams.get('status') - const { name } = useParams() + const { uuid } = useParams() const dispatch = useStoreDispatch() @@ -102,26 +101,25 @@ export default function ExperimentDetail() { description: '', action: 'delete', }) - const [paused, setPaused] = useState(status === 'paused' ? true : false) + const [paused, setPaused] = useState(status === 'Paused' ? true : false) const fetchExperimentDetail = () => { setLoading(true) api.experiments - .detail(namespace!, name!, kind!) + .detail(uuid) .then(({ data }) => setDetail(data)) .catch(console.log) } - const fetchEventsByName = (name: string) => { + const fetchEvents = () => api.events .events() - .then(({ data }) => setEvents(data.filter((d) => d.Experiment === name))) + .then(({ data }) => setEvents(data.filter((d) => d.ExperimentID === uuid))) .catch(console.log) .finally(() => { setLoading(false) }) - } const onSelectEvent = (e: Event) => { setDetailLoading(true) @@ -137,17 +135,10 @@ export default function ExperimentDetail() { } useEffect(() => { - if (namespace && kind && name) { - fetchExperimentDetail() - } + fetchExperimentDetail() + fetchEvents() // eslint-disable-next-line react-hooks/exhaustive-deps - }, [namespace, kind, name]) - - useEffect(() => { - if (detail) { - fetchEventsByName(detail.name) - } - }, [detail]) + }, []) useEffect(() => { if (prevEvents !== events && events) { @@ -228,7 +219,7 @@ export default function ExperimentDetail() { setDialogOpen(false) - actionFunc(namespace, name, kind) + actionFunc(uuid) .then(() => { dispatch( setAlert({ @@ -245,12 +236,12 @@ export default function ExperimentDetail() { if (action === 'pause') { setPaused(true) - searchParams.set('status', StateOfExperimentsEnum.paused) + searchParams.set('status', StateOfExperimentsEnum.Paused) } if (action === 'start') { setPaused(false) - searchParams.set('status', StateOfExperimentsEnum.running) + searchParams.set('status', StateOfExperimentsEnum.Running) } if (action === 'pause' || action === 'start') { @@ -344,7 +335,7 @@ export default function ExperimentDetail() { - {(!namespace || !kind || !name) && ( + {(!name || !uuid) && ( diff --git a/ui/src/pages/Experiments/index.tsx b/ui/src/pages/Experiments/index.tsx index 27739caa7e..03490cb851 100644 --- a/ui/src/pages/Experiments/index.tsx +++ b/ui/src/pages/Experiments/index.tsx @@ -22,9 +22,7 @@ export default function Experiments() { const [experiments, setExperiments] = useState(null) const [dialogOpen, setDialogOpen] = useState(false) const [selected, setSelected] = useState({ - namespace: '', - name: '', - kind: '', + uuid: '', title: '', description: '', action: 'delete', @@ -47,11 +45,11 @@ export default function Experiments() { if (data.length) { setExperiments( experiments.map((e) => { - if (e.status.toLowerCase() === 'failed') { + if (e.status === 'Failed') { return { ...e, events: [] } } else { const events = data - .filter((d) => d.Experiment === e.Name) + .filter((d) => d.ExperimentID === e.uid) .sort((a, b) => dayComparator(a.StartTime, b.StartTime)) return { @@ -111,9 +109,9 @@ export default function Experiments() { setDialogOpen(false) - const { namespace, name, kind } = selected + const { uuid } = selected - actionFunc(namespace, name, kind) + actionFunc(uuid) .then(() => { dispatch( setAlert({ diff --git a/ui/src/routes.tsx b/ui/src/routes.tsx index 7744d4b563..58a8ea0525 100644 --- a/ui/src/routes.tsx +++ b/ui/src/routes.tsx @@ -23,7 +23,7 @@ const routes: RouteProps[] = [ }, { component: ExperimentDetail, - path: '/experiments/:name', + path: '/experiments/:uuid', }, { component: Events, diff --git a/ui/src/slices/experiments.ts b/ui/src/slices/experiments.ts index cfdd47ec48..f4842d1598 100644 --- a/ui/src/slices/experiments.ts +++ b/ui/src/slices/experiments.ts @@ -5,12 +5,12 @@ import { StateOfExperiments } from 'api/experiments.type' import api from 'api' const defaultExperiments = { - total: 0, - running: 0, - waiting: 0, - paused: 0, - failed: 0, - finished: 0, + Total: 0, + Running: 0, + Waiting: 0, + Paused: 0, + Failed: 0, + Finished: 0, } export const getStateofExperiments = createAsyncThunk(