diff --git a/extension/src/plots/data/index.ts b/extension/src/plots/data/index.ts index 8cbc47df35..39dc7c7d1d 100644 --- a/extension/src/plots/data/index.ts +++ b/extension/src/plots/data/index.ts @@ -59,6 +59,10 @@ export class PlotsData extends BaseData<{ ...args ) + if (!revs.includes('workspace') && args.length < 2) { + revs.push('workspace') + } + this.notifyChanged({ data, revs }) const files = this.collectFiles({ data }) diff --git a/extension/src/plots/index.ts b/extension/src/plots/index.ts index 0400ad7a6b..011bf59d02 100644 --- a/extension/src/plots/index.ts +++ b/extension/src/plots/index.ts @@ -140,8 +140,7 @@ export class Plots extends BaseRepository { this.paths.hasPaths() && definedAndNonEmpty(this.plots.getUnfetchedRevisions()) ) { - this.webviewMessages.sendCheckpointPlotsMessage() - return this.data.managedUpdate() + this.data.managedUpdate() } return this.webviewMessages.sendWebviewMessage() diff --git a/extension/src/plots/model/collect.test.ts b/extension/src/plots/model/collect.test.ts index 88dfc662e5..4d6ebd0dd2 100644 --- a/extension/src/plots/model/collect.test.ts +++ b/extension/src/plots/model/collect.test.ts @@ -9,13 +9,14 @@ import { collectTemplates, collectMetricOrder, collectWorkspaceRunningCheckpoint, - collectWorkspaceRaceConditionData + collectWorkspaceRaceConditionData, + collectOverrideRevisionDetails } from './collect' import plotsDiffFixture from '../../test/fixtures/plotsDiff/output' import expShowFixture from '../../test/fixtures/expShow/base/output' import modifiedFixture from '../../test/fixtures/expShow/modified/output' import checkpointPlotsFixture from '../../test/fixtures/expShow/base/checkpointPlots' -import { ExperimentsOutput } from '../../cli/dvc/contract' +import { ExperimentsOutput, ExperimentStatus } from '../../cli/dvc/contract' import { definedAndNonEmpty, sameContents, @@ -23,6 +24,8 @@ import { } from '../../util/array' import { TemplatePlot } from '../webview/contract' import { getCLIBranchId } from '../../test/fixtures/plotsDiff/util' +import { SelectedExperimentWithColor } from '../../experiments/model' +import { Experiment } from '../../experiments/webview/contract' const logsLossPath = join('logs', 'loss.tsv') @@ -358,3 +361,112 @@ describe('collectWorkspaceRaceConditionData', () => { ) }) }) + +describe('collectOverrideRevisionDetails', () => { + it('should override the revision details for running checkpoint tips', () => { + const runningId = 'b' + + const { overrideOrder, overrideRevisions, unfinishedRunningExperiments } = + collectOverrideRevisionDetails( + ['a', 'b', 'c', 'd'], + [ + { label: 'a' }, + { + checkpoint_tip: 'b', + displayColor: '#13adc7', + id: runningId, + label: 'b', + sha: 'b', + status: ExperimentStatus.RUNNING + }, + { label: 'c' }, + { label: 'd' } + ] as SelectedExperimentWithColor[], + new Set(['a', 'c', 'd', 'e']), + new Set(), + (id: string) => ({ [runningId]: [{ label: 'e' }] as Experiment[] }[id]) + ) + expect(overrideOrder).toStrictEqual(['a', 'e', 'c', 'd']) + expect(overrideRevisions).toStrictEqual([ + { label: 'a' }, + { + displayColor: '#13adc7', + label: 'e' + }, + { label: 'c' }, + { label: 'd' } + ]) + expect(unfinishedRunningExperiments).toStrictEqual(new Set([runningId])) + }) + + it('should override the revision details for finished but unfetched checkpoint tips', () => { + const justFinishedRunningId = 'exp-was-running' + const { overrideOrder, overrideRevisions, unfinishedRunningExperiments } = + collectOverrideRevisionDetails( + ['a', 'b', 'c', 'd'], + [ + { label: 'a' }, + { + checkpoint_tip: 'b', + displayColor: '#13adc7', + id: justFinishedRunningId, + label: 'b', + sha: 'b', + status: ExperimentStatus.SUCCESS + }, + { label: 'c' }, + { label: 'd' } + ] as SelectedExperimentWithColor[], + new Set(['a', 'c', 'd', 'e']), + new Set([justFinishedRunningId]), + (id: string) => + ({ [justFinishedRunningId]: [{ label: 'e' }] as Experiment[] }[id]) + ) + expect(overrideOrder).toStrictEqual(['a', 'e', 'c', 'd']) + expect(overrideRevisions).toStrictEqual([ + { label: 'a' }, + { + displayColor: '#13adc7', + label: 'e' + }, + { label: 'c' }, + { label: 'd' } + ]) + expect(unfinishedRunningExperiments).toStrictEqual( + new Set([justFinishedRunningId]) + ) + }) + + it('should remove the id from the unfinishedRunningExperiments set once the revision has been fetched', () => { + const justFinishedRunningId = 'exp-was-running' + const { overrideOrder, overrideRevisions, unfinishedRunningExperiments } = + collectOverrideRevisionDetails( + ['a', 'b', 'c', 'd'], + [ + { label: 'a' }, + { + checkpoint_tip: 'b', + displayColor: '#13adc7', + id: justFinishedRunningId, + label: 'b', + sha: 'b', + status: ExperimentStatus.SUCCESS + }, + { label: 'c' }, + { label: 'd' } + ] as SelectedExperimentWithColor[], + new Set(['a', 'b', 'c', 'd', 'e']), + new Set([justFinishedRunningId]), + (id: string) => + ({ [justFinishedRunningId]: [{ label: 'e' }] as Experiment[] }[id]) + ) + expect(overrideOrder).toStrictEqual(['a', 'b', 'c', 'd']) + expect(overrideRevisions).toStrictEqual([ + { label: 'a' }, + expect.objectContaining({ label: 'b' }), + { label: 'c' }, + { label: 'd' } + ]) + expect(unfinishedRunningExperiments).toStrictEqual(new Set([])) + }) +}) diff --git a/extension/src/plots/model/collect.ts b/extension/src/plots/model/collect.ts index 15d71e912e..59ce78c053 100644 --- a/extension/src/plots/model/collect.ts +++ b/extension/src/plots/model/collect.ts @@ -28,7 +28,11 @@ import { decodeColumn, appendColumnToPath } from '../../experiments/columns/paths' -import { MetricOrParamColumns } from '../../experiments/webview/contract' +import { + Experiment, + isRunning, + MetricOrParamColumns +} from '../../experiments/webview/contract' import { addToMapArray } from '../../util/map' import { TemplateOrder } from '../paths/collect' import { extendVegaSpec, isMultiViewPlot } from '../vega/util' @@ -42,6 +46,7 @@ import { unmergeConcatenatedFields } from '../multiSource/collect' import { StrokeDashEncoding } from '../multiSource/constants' +import { SelectedExperimentWithColor } from '../../experiments/model' type CheckpointPlotAccumulator = { iterations: Record @@ -711,3 +716,112 @@ export const collectBranchRevisionDetails = ( } return branchRevisions } + +const getMostRecentFetchedCheckpointRevision = ( + selectedRevision: SelectedExperimentWithColor, + fetchedRevs: Set, + checkpoints: Experiment[] | undefined +): SelectedExperimentWithColor => { + const mostRecent = + checkpoints?.find(({ label }) => fetchedRevs.has(label)) || selectedRevision + return { + ...mostRecent, + displayColor: selectedRevision.displayColor + } as SelectedExperimentWithColor +} + +const overrideRevisionDetail = ( + orderMapping: { [label: string]: string }, + selectedWithFetchedRunningCheckpointRevs: SelectedExperimentWithColor[], + selectedRevision: SelectedExperimentWithColor, + fetchedRevs: Set, + unfinishedRunningExperiments: Set, + checkpoints: Experiment[] | undefined +) => { + const { id, status, label } = selectedRevision + + if (isRunning(status)) { + unfinishedRunningExperiments.add(id) + } + + const mostRecent = getMostRecentFetchedCheckpointRevision( + selectedRevision, + fetchedRevs, + checkpoints + ) + orderMapping[label] = mostRecent.label + selectedWithFetchedRunningCheckpointRevs.push(mostRecent) +} + +const collectRevisionDetail = ( + orderMapping: { [label: string]: string }, + selectedWithFetchedRunningCheckpointRevs: SelectedExperimentWithColor[], + selectedRevision: SelectedExperimentWithColor, + fetchedRevs: Set, + unfinishedRunningExperiments: Set, + getCheckpoints: (id: string) => Experiment[] | undefined + // eslint-disable-next-line sonarjs/cognitive-complexity +) => { + const { label, status, id, checkpoint_tip, sha } = selectedRevision + + const isCheckpointTip = sha === checkpoint_tip + const running = isRunning(status) + const preventRevisionsDisappearingAtEnd = + isCheckpointTip && unfinishedRunningExperiments.has(id) + + if ( + !fetchedRevs.has(label) && + (running || preventRevisionsDisappearingAtEnd) + ) { + return overrideRevisionDetail( + orderMapping, + selectedWithFetchedRunningCheckpointRevs, + selectedRevision, + fetchedRevs, + unfinishedRunningExperiments, + getCheckpoints(id) + ) + } + + if (!running && isCheckpointTip) { + unfinishedRunningExperiments.delete(id) + } + + orderMapping[label] = label + selectedWithFetchedRunningCheckpointRevs.push(selectedRevision) +} + +export const collectOverrideRevisionDetails = ( + comparisonOrder: string[], + selectedRevisions: SelectedExperimentWithColor[], + fetchedRevs: Set, + unfinishedRunningExperiments: Set, + getCheckpoints: (id: string) => Experiment[] | undefined +): { + overrideOrder: string[] + overrideRevisions: SelectedExperimentWithColor[] + unfinishedRunningExperiments: Set +} => { + const orderMapping: { [label: string]: string } = {} + const selectedWithFetchedRunningCheckpointRevs: SelectedExperimentWithColor[] = + [] + + for (const selectedRevision of selectedRevisions) { + collectRevisionDetail( + orderMapping, + selectedWithFetchedRunningCheckpointRevs, + selectedRevision, + fetchedRevs, + unfinishedRunningExperiments, + getCheckpoints + ) + } + + return { + overrideOrder: comparisonOrder + .map(label => orderMapping[label]) + .filter(Boolean), + overrideRevisions: selectedWithFetchedRunningCheckpointRevs, + unfinishedRunningExperiments + } +} diff --git a/extension/src/plots/model/index.ts b/extension/src/plots/model/index.ts index a61ce3fb61..f349dcd8a6 100644 --- a/extension/src/plots/model/index.ts +++ b/extension/src/plots/model/index.ts @@ -11,7 +11,8 @@ import { ComparisonData, RevisionData, TemplateAccumulator, - collectBranchRevisionDetails + collectBranchRevisionDetails, + collectOverrideRevisionDetails } from './collect' import { CheckpointPlot, @@ -40,6 +41,7 @@ import { MultiSourceVariations } from '../multiSource/collect' import { isDvcError } from '../../cli/dvc/reader' +import { SelectedExperimentWithColor } from '../../experiments/model' export class PlotsModel extends ModelWithPersistence { private readonly experiments: Experiments @@ -63,6 +65,8 @@ export class PlotsModel extends ModelWithPersistence { private selectedMetrics?: string[] private metricOrder: string[] + private unfinishedRunningExperiments: Set = new Set() + constructor( dvcRoot: string, experiments: Experiments, @@ -112,11 +116,6 @@ export class PlotsModel extends ModelWithPersistence { const cliIdToLabel = this.getCLIIdToLabel() - this.fetchedRevs = new Set([ - ...this.fetchedRevs, - ...revs.map(rev => cliIdToLabel[rev]) - ]) - const [{ comparisonData, revisionData }, templates, multiSourceVariations] = await Promise.all([ collectData(data, cliIdToLabel), @@ -149,6 +148,11 @@ export class PlotsModel extends ModelWithPersistence { this.setComparisonOrder() + this.fetchedRevs = new Set([ + ...this.fetchedRevs, + ...revs.map(rev => cliIdToLabel[rev]) + ]) + this.deferred.resolve() } @@ -181,6 +185,31 @@ export class PlotsModel extends ModelWithPersistence { this.deleteRevisionData(id) } + public getOverrideRevisionDetails() { + if ( + !( + this.experiments.hasCheckpoints() && + (this.experiments.hasRunningExperiment() || + this.unfinishedRunningExperiments.size > 0) + ) + ) { + return this.getSelectedRevisionDetails() + } + + const { overrideOrder, overrideRevisions, unfinishedRunningExperiments } = + collectOverrideRevisionDetails( + this.comparisonOrder, + this.experiments.getSelectedRevisions(), + this.fetchedRevs, + this.unfinishedRunningExperiments, + id => this.experiments.getCheckpoints(id) + ) + + this.unfinishedRunningExperiments = unfinishedRunningExperiments + + return this.getSelectedRevisionDetails(overrideOrder, overrideRevisions) + } + public getUnfetchedRevisions() { return this.getSelectedRevisions().filter( revision => !this.fetchedRevs.has(revision) @@ -202,31 +231,38 @@ export class PlotsModel extends ModelWithPersistence { return this.experiments.getMutableRevisions() } - public getRevisionColors() { - return getColorScale(this.getSelectedRevisionDetails()) + public getRevisionColors(overrideRevs?: Revision[]) { + return getColorScale(overrideRevs || this.getSelectedRevisionDetails()) } - public getSelectedRevisionDetails() { + public getSelectedRevisionDetails( + overrideOrder?: string[], + overrideRevs?: SelectedExperimentWithColor[] + ) { return reorderObjectList( - this.comparisonOrder, - this.experiments - .getSelectedRevisions() - .map(({ label, displayColor, logicalGroupName, id }) => ({ + overrideOrder || this.comparisonOrder, + (overrideRevs || this.experiments.getSelectedRevisions()).map( + ({ label, displayColor, logicalGroupName, id }) => ({ displayColor, + fetched: this.fetchedRevs.has(label), group: logicalGroupName, id, revision: label - })), + }) + ), 'revision' ) } - public getTemplatePlots(order: TemplateOrder | undefined) { + public getTemplatePlots( + order: TemplateOrder | undefined, + overrideRevs?: Revision[] + ) { if (!definedAndNonEmpty(order)) { return } - const selectedRevisions = this.getSelectedRevisions() + const selectedRevisions = overrideRevs || this.getSelectedRevisionDetails() if (!definedAndNonEmpty(selectedRevisions)) { return @@ -235,12 +271,15 @@ export class PlotsModel extends ModelWithPersistence { return this.getSelectedTemplatePlots(order, selectedRevisions) } - public getComparisonPlots(paths: string[] | undefined) { + public getComparisonPlots( + paths: string[] | undefined, + overrideRevs?: string[] + ) { if (!paths) { return } - const selectedRevisions = this.getSelectedRevisions() + const selectedRevisions = overrideRevs || this.getSelectedRevisions() if (!definedAndNonEmpty(selectedRevisions)) { return } @@ -373,7 +412,7 @@ export class PlotsModel extends ModelWithPersistence { private getCLIIdToLabel() { const mapping: { [shortSha: string]: string } = {} - for (const rev of this.getSelectedRevisions()) { + for (const rev of this.experiments.getRevisions()) { mapping[this.getCLIId(rev)] = rev } @@ -444,15 +483,15 @@ export class PlotsModel extends ModelWithPersistence { private getSelectedTemplatePlots( order: TemplateOrder, - selectedRevisions: string[] + selectedRevisions: Revision[] ) { return collectSelectedTemplatePlots( order, - selectedRevisions, + selectedRevisions.map(({ revision }) => revision), this.templates, this.revisionData, this.getPlotSize(Section.TEMPLATE_PLOTS), - this.getRevisionColors(), + this.getRevisionColors(selectedRevisions), this.multiSourceEncoding ) } diff --git a/extension/src/plots/vega/util.ts b/extension/src/plots/vega/util.ts index 00ca806204..4c21493b3a 100644 --- a/extension/src/plots/vega/util.ts +++ b/extension/src/plots/vega/util.ts @@ -20,8 +20,9 @@ import { } from 'vega-lite/build/src/spec/repeat' import { TopLevelUnitSpec } from 'vega-lite/build/src/spec/unit' import isEqual from 'lodash.isequal' -import { ColorScale, PlotSizeNumber, Revision } from '../webview/contract' +import { ColorScale, PlotSizeNumber } from '../webview/contract' import { ShapeEncoding, StrokeDashEncoding } from '../multiSource/constants' +import { Color } from '../../experiments/model/status/colors' const COMMIT_FIELD = 'rev' @@ -88,7 +89,7 @@ export const isMultiViewByCommitPlot = ( ): boolean => !template || getFacetField(template) === COMMIT_FIELD export const getColorScale = ( - revisions: Revision[] + revisions: { displayColor: Color; revision: string }[] ): ColorScale | undefined => { const acc: ColorScale = { domain: [], range: [] } diff --git a/extension/src/plots/webview/contract.ts b/extension/src/plots/webview/contract.ts index 259859a52e..4b8c6f213d 100644 --- a/extension/src/plots/webview/contract.ts +++ b/extension/src/plots/webview/contract.ts @@ -40,6 +40,7 @@ export type Revision = { revision: string group?: string displayColor: Color + fetched: boolean } export interface PlotsComparisonData { diff --git a/extension/src/plots/webview/messages.ts b/extension/src/plots/webview/messages.ts index cc268c9963..676de6f8f5 100644 --- a/extension/src/plots/webview/messages.ts +++ b/extension/src/plots/webview/messages.ts @@ -3,6 +3,7 @@ import { ComparisonPlot, ComparisonRevisionData, PlotsData as TPlotsData, + Revision, Section, SectionCollapsed } from './contract' @@ -48,14 +49,17 @@ export class WebviewMessages { } public sendWebviewMessage() { + const selectedRevisions = this.plots.getOverrideRevisionDetails() + const selectedLabels = selectedRevisions.map(({ revision }) => revision) + this.getWebview()?.show({ checkpoint: this.getCheckpointPlots(), - comparison: this.getComparisonPlots(), + comparison: this.getComparisonPlots(selectedLabels), hasPlots: !!this.paths?.hasPaths(), hasSelectedPlots: definedAndNonEmpty(this.paths.getSelected()), sectionCollapsed: this.plots.getSectionCollapsed(), - selectedRevisions: this.plots.getSelectedRevisionDetails(), - template: this.getTemplatePlots() + selectedRevisions, + template: this.getTemplatePlots(selectedRevisions) }) } @@ -213,14 +217,14 @@ export class WebviewMessages { private sendSectionCollapsed() { this.getWebview()?.show({ - sectionCollapsed: this.plots?.getSectionCollapsed() + sectionCollapsed: this.plots.getSectionCollapsed() }) } private sendComparisonPlots() { this.getWebview()?.show({ comparison: this.getComparisonPlots(), - selectedRevisions: this.plots?.getSelectedRevisionDetails() + selectedRevisions: this.plots.getSelectedRevisionDetails() }) } @@ -230,11 +234,11 @@ export class WebviewMessages { }) } - private getTemplatePlots() { - const paths = this.paths?.getTemplateOrder() - const plots = this.plots?.getTemplatePlots(paths) + private getTemplatePlots(overrideRevs?: Revision[]) { + const paths = this.paths.getTemplateOrder() + const plots = this.plots.getTemplatePlots(paths, overrideRevs) - if (!this.plots || !plots || isEmpty(plots)) { + if (!plots || isEmpty(plots)) { return null } @@ -244,10 +248,10 @@ export class WebviewMessages { } } - private getComparisonPlots() { + private getComparisonPlots(overrideRevs?: string[]) { const paths = this.paths.getComparisonPaths() - const comparison = this.plots.getComparisonPlots(paths) - if (!this.plots || !comparison || isEmpty(comparison)) { + const comparison = this.plots.getComparisonPlots(paths, overrideRevs) + if (!comparison || isEmpty(comparison)) { return null } @@ -285,6 +289,6 @@ export class WebviewMessages { } private getCheckpointPlots() { - return this.plots?.getCheckpointPlots() || null + return this.plots.getCheckpointPlots() || null } } diff --git a/extension/src/test/fixtures/plotsDiff/index.ts b/extension/src/test/fixtures/plotsDiff/index.ts index dd89d8c46c..4bb6629736 100644 --- a/extension/src/test/fixtures/plotsDiff/index.ts +++ b/extension/src/test/fixtures/plotsDiff/index.ts @@ -513,22 +513,32 @@ export const getRevisions = () => { id: 'workspace', revision: 'workspace', displayColor: workspace, + fetched: true, group: undefined }, - { id: 'main', revision: 'main', displayColor: main, group: undefined }, { + fetched: true, + id: 'main', + revision: 'main', + displayColor: main, + group: undefined + }, + { + fetched: true, id: 'exp-e7a67', revision: '4fb124a', displayColor: _4fb124a, group: '[exp-e7a67]' }, { + fetched: true, id: 'test-branch', revision: '42b8736', displayColor: _42b8735, group: '[test-branch]' }, { + fetched: true, id: 'exp-83425', revision: '1ba7bcd', displayColor: _1ba7bcd, diff --git a/extension/src/test/suite/experiments/model/tree.test.ts b/extension/src/test/suite/experiments/model/tree.test.ts index 53fba711ed..c913bd7c34 100644 --- a/extension/src/test/suite/experiments/model/tree.test.ts +++ b/extension/src/test/suite/experiments/model/tree.test.ts @@ -350,42 +350,49 @@ suite('Experiments Tree Test Suite', () => { ).to.deep.equal([ { displayColor: colors[0], + fetched: true, group: undefined, id: 'workspace', revision: 'workspace' }, { displayColor: colors[2], + fetched: true, group: '[exp-e7a67]', id: 'exp-e7a67', revision: '4fb124a' }, { displayColor: colors[3], + fetched: true, group: '[test-branch]', id: 'test-branch', revision: '42b8736' }, { displayColor: colors[1], + fetched: true, group: '[exp-83425]', id: '23250b33e3d6dd0e136262d1d26a2face031cb03', revision: '23250b3' }, { displayColor: colors[4], + fetched: true, group: '[exp-e7a67]', id: 'd1343a87c6ee4a2e82d19525964d2fb2cb6756c9', revision: 'd1343a8' }, { displayColor: colors[5], + fetched: true, group: '[exp-e7a67]', id: '1ee5f2ecb0fa4d83cbf614386536344cf894dd53', revision: '1ee5f2e' }, { displayColor: colors[6], + fetched: true, group: '[test-branch]', id: '217312476f8854dda1865450b737eb6bc7a3ba1b', revision: '2173124' diff --git a/extension/src/util/array.ts b/extension/src/util/array.ts index 43c037f524..19357e825e 100644 --- a/extension/src/util/array.ts +++ b/extension/src/util/array.ts @@ -49,17 +49,6 @@ export const splitMatchedOrdered = (values: T[], existingOrder: T[]) => { export const reorderListSubset = (subset: T[], supersetOrder: T[]): T[] => splitMatchedOrdered(subset, supersetOrder)[0] -export const performOrderedUpdate = ( - order: string[], - items: { [key: string]: unknown }[], - key: string -): string[] => { - const current = reorderObjectList(order, items, key) - const added = items.filter(item => !order.includes(item[key] as string)) - - return [...current, ...added].map(item => item?.[key]) as string[] -} - export const performSimpleOrderedUpdate = ( order: string[], items: string[] diff --git a/webview/src/plots/components/App.test.tsx b/webview/src/plots/components/App.test.tsx index 0a43bd53e9..d3e678f968 100644 --- a/webview/src/plots/components/App.test.tsx +++ b/webview/src/plots/components/App.test.tsx @@ -1818,37 +1818,6 @@ describe('App', () => { type: MessageFromWebviewType.REFRESH_REVISIONS }) }) - - it('should not reorder the ribbon when comparison plots are reordered', () => { - renderAppWithOptionalData({ - comparison: comparisonTableFixture, - selectedRevisions: plotsRevisionsFixture - }) - - const expectedRevisions = plotsRevisionsFixture.map(rev => - rev.group ? rev.group.slice(1, -1) + rev.revision : rev.revision - ) - - expect(getDisplayedRevisionOrder()).toStrictEqual(expectedRevisions) - - sendSetDataMessage({ - comparison: comparisonTableFixture, - selectedRevisions: [ - { - displayColor: '#f56565', - group: undefined, - id: 'new-revision', - revision: 'new-revision' - }, - ...[...plotsRevisionsFixture].reverse() - ] - }) - - expect(getDisplayedRevisionOrder()).toStrictEqual([ - ...expectedRevisions, - 'new-revision' - ]) - }) }) describe('Vega panels', () => { diff --git a/webview/src/plots/components/comparisonTable/ComparisonTable.test.tsx b/webview/src/plots/components/comparisonTable/ComparisonTable.test.tsx index e174fe7363..167aae3525 100644 --- a/webview/src/plots/components/comparisonTable/ComparisonTable.test.tsx +++ b/webview/src/plots/components/comparisonTable/ComparisonTable.test.tsx @@ -247,7 +247,7 @@ describe('ComparisonTable', () => { const newRevName = 'newRev' const newRevisions = [ ...selectedRevisions, - { displayColor: '#000000', revision: newRevName } + { displayColor: '#000000', fetched: true, revision: newRevName } ] as Revision[] renderTable(comparisonTableFixture, newRevisions, rerender) @@ -277,6 +277,7 @@ describe('ComparisonTable', () => { ...selectedRevisions, { displayColor: '#f56565', + fetched: true, group: undefined, id: 'noData', revision: revisionWithNoData diff --git a/webview/src/plots/components/ribbon/Ribbon.tsx b/webview/src/plots/components/ribbon/Ribbon.tsx index ab21c21925..3792c67683 100644 --- a/webview/src/plots/components/ribbon/Ribbon.tsx +++ b/webview/src/plots/components/ribbon/Ribbon.tsx @@ -1,8 +1,7 @@ import cx from 'classnames' import { MessageFromWebviewType } from 'dvc/src/webview/contract' -import React, { useEffect, useState } from 'react' +import React from 'react' import { useSelector } from 'react-redux' -import { performOrderedUpdate, reorderObjectList } from 'dvc/src/util/array' import { useInView } from 'react-intersection-observer' import styles from './styles.module.scss' import { RibbonBlock } from './RibbonBlock' @@ -23,12 +22,6 @@ export const Ribbon: React.FC = () => { const revisions = useSelector( (state: PlotsState) => state.webview.selectedRevisions ) - const [order, setOrder] = useState([]) - const reorderId = 'id' - - useEffect(() => { - setOrder(pastOrder => performOrderedUpdate(pastOrder, revisions, reorderId)) - }, [revisions]) const removeRevision = (revision: string) => { sendMessage({ @@ -70,7 +63,7 @@ export const Ribbon: React.FC = () => { appearance="secondary" /> - {reorderObjectList(order, revisions, reorderId).map(revision => ( + {revisions.map(revision => ( = ({
{revision.revision}
)} +
+ {!revision.fetched && ( + + )} +