Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add flexible plots legends to plots tree #2452

Merged
merged 11 commits into from
Sep 28, 2022
3 changes: 3 additions & 0 deletions extension/resources/plots/circle.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions extension/resources/plots/diamond.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions extension/resources/plots/square.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions extension/resources/plots/stroke-dash-1-0.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions extension/resources/plots/stroke-dash-1-1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions extension/resources/plots/stroke-dash-2-1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions extension/resources/plots/stroke-dash-4-2.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions extension/resources/plots/stroke-dash-4-4.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions extension/resources/plots/stroke-dash-8-4.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions extension/resources/plots/stroke-dash-8-8.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions extension/resources/plots/triangle.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 16 additions & 5 deletions extension/src/experiments/columns/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,22 @@ export class ColumnsModel extends PathSelectionModel<Column> {
)
}

public filterChildren(path?: string) {
public getChildren(path: string | undefined) {
return this.filterChildren(path).map(element => {
return {
...element,
descendantStatuses: this.getTerminalNodeStatuses(element.path),
label: element.label,
status: this.status[element.path]
}
})
}

public hasNonDefaultColumns() {
return this.data.length > 1
}

private filterChildren(path?: string) {
return this.data.filter(element =>
path
? element.parentPath === path
Expand All @@ -73,10 +88,6 @@ export class ColumnsModel extends PathSelectionModel<Column> {
)
}

public hasNonDefaultColumns() {
return this.data.length > 1
}

private async transformAndSetColumns(data: ExperimentsOutput) {
const [columns, paramsFiles] = await Promise.all([
collectColumns(data),
Expand Down
5 changes: 4 additions & 1 deletion extension/src/experiments/columns/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ export class ExperimentsColumnsTree extends BasePathSelectionTree<WorkspaceExper
}

public getRepositoryChildren(dvcRoot: string, path: string) {
return this.workspace.getRepository(dvcRoot).getChildColumns(path)
return this.workspace
.getRepository(dvcRoot)
.getChildColumns(path)
.map(element => this.transformElement({ ...element, dvcRoot }))
}

public getRepositoryStatuses(dvcRoot: string) {
Expand Down
15 changes: 3 additions & 12 deletions extension/src/path/selection/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,6 @@ export abstract class PathSelectionModel<
.map(element => ({ ...element, selected: !!this.status[element.path] }))
}

public getChildren(path: string | undefined) {
return this.filterChildren(path).map(element => {
return {
...element,
descendantStatuses: this.getTerminalNodeStatuses(element.path),
label: element.label,
status: this.status[element.path]
}
})
}

public toggleStatus(path: string) {
const status = this.getNextStatus(path)
this.status[path] = status
Expand Down Expand Up @@ -153,5 +142,7 @@ export abstract class PathSelectionModel<
return this.persist(this.statusKey, this.status)
}

abstract filterChildren(path?: string): T[]
abstract getChildren(
...args: unknown[]
): (T & { descendantStatuses: Status[]; label: string; status: Status })[]
}
68 changes: 32 additions & 36 deletions extension/src/path/selection/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export type PathSelectionItem = {
collapsibleState: TreeItemCollapsibleState
label: string
path: string
iconPath: Resource
iconPath: Resource | Uri
}

export abstract class BasePathSelectionTree<
Expand All @@ -35,8 +35,7 @@ export abstract class BasePathSelectionTree<
public readonly onDidChangeTreeData: Event<PathSelectionItem | void>

protected readonly workspace: T

private readonly resourceLocator: ResourceLocator
protected readonly resourceLocator: ResourceLocator

private readonly view: TreeView<string | PathSelectionItem>

Expand Down Expand Up @@ -127,6 +126,33 @@ export abstract class BasePathSelectionTree<
}${separator}${statuses.length}`
}

protected transformElement(element: {
dvcRoot: string
descendantStatuses: Status[]
hasChildren: boolean
path: string
status: Status
label: string
}) {
const { dvcRoot, descendantStatuses, hasChildren, path, status, label } =
element

const description = this.getDescription(descendantStatuses, '/')
const iconPath = this.getIconPath(status)
const collapsibleState = hasChildren
? TreeItemCollapsibleState.Collapsed
: TreeItemCollapsibleState.None

return {
collapsibleState,
description,
dvcRoot,
iconPath,
label,
path
} as PathSelectionItem
}

private updateDescriptionOnChange() {
this.dispose.track(
this.onDidChangeTreeData(() => {
Expand Down Expand Up @@ -165,52 +191,22 @@ export abstract class BasePathSelectionTree<
}

if (this.isRoot(element)) {
return this.transformRepositoryChildren(element, undefined)
return this.getRepositoryChildren(element, undefined)
}

const { dvcRoot, path } = element

return this.transformRepositoryChildren(dvcRoot, path)
return this.getRepositoryChildren(dvcRoot, path)
}

private isRoot(element: string | PathSelectionItem): element is string {
return typeof element === 'string'
}

private transformRepositoryChildren(
dvcRoot: string,
path: string | undefined
) {
return this.getRepositoryChildren(dvcRoot, path).map(element => {
const { descendantStatuses, hasChildren, path, status, label } = element

const description = this.getDescription(descendantStatuses, '/')
const iconPath = this.getIconPath(status)
const collapsibleState = hasChildren
? TreeItemCollapsibleState.Collapsed
: TreeItemCollapsibleState.None

return {
collapsibleState,
description,
dvcRoot,
iconPath,
label,
path
} as PathSelectionItem
})
}

abstract getRepositoryStatuses(dvcRoot: string): Status[]

abstract getRepositoryChildren(
dvcRoot: string,
path: string | undefined
): {
descendantStatuses: Status[]
hasChildren: boolean
label: string
path: string
status: Status
}[]
): PathSelectionItem[]
}
12 changes: 9 additions & 3 deletions extension/src/plots/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { PlotsData as TPlotsData } from './webview/contract'
import { WebviewMessages } from './webview/messages'
import { PlotsData } from './data'
import { PlotsModel } from './model'
import { collectScale } from './paths/collect'
import { collectEncodingElements, collectScale } from './paths/collect'
import { PathsModel } from './paths/model'
import { BaseWebview } from '../webview'
import { ViewKey } from '../webview/constants'
Expand Down Expand Up @@ -127,8 +127,14 @@ export class Plots extends BaseRepository<TPlotsData> {
this.data.managedUpdate()
}

public getChildPaths(path: string) {
return this.paths?.getChildren(path) || []
public getChildPaths(path: string | undefined) {
const multiSourceEncoding = this.plots?.getMultiSourceData() || {}

if (path && multiSourceEncoding[path]) {
return collectEncodingElements(path, multiSourceEncoding)
}

return this.paths?.getChildren(path, multiSourceEncoding) || []
}

public getPathStatuses() {
Expand Down
4 changes: 4 additions & 0 deletions extension/src/plots/model/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,10 @@ export class PlotsModel extends ModelWithPersistence {
return this.sectionCollapsed
}

public getMultiSourceData() {
return this.multiSourceEncoding
}

private removeStaleData() {
return Promise.all([
this.removeStaleBranches(),
Expand Down
8 changes: 1 addition & 7 deletions extension/src/plots/multiSource/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,7 @@ export const StrokeDash = [
] as const
export type StrokeDashValue = typeof StrokeDash[number]

export const Shape = [
'square',
'circle',
'triangle',
'diamond',
'cross'
] as const
export const Shape = ['square', 'circle', 'triangle', 'diamond'] as const
export type ShapeValue = typeof Shape[number]

export type Scale<T extends StrokeDashValue | ShapeValue> = {
Expand Down
60 changes: 59 additions & 1 deletion extension/src/plots/paths/collect.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { join } from 'path'
import { VisualizationSpec } from 'react-vega'
import { collectPaths, collectTemplateOrder } from './collect'
import {
collectEncodingElements,
collectPaths,
collectTemplateOrder,
EncodingType
} from './collect'
import { TemplatePlotGroup, PlotsType } from '../webview/contract'
import plotsDiffFixture from '../../test/fixtures/plotsDiff/output'
import { Shape, StrokeDash } from '../multiSource/constants'

describe('collectPath', () => {
it('should return the expected data from the test fixture', () => {
Expand Down Expand Up @@ -380,3 +386,55 @@ describe('collectTemplateOrder', () => {
])
})
})

describe('collectEncodingElements', () => {
it('should return an empty array if there is no multi source encoding for a path', () => {
const elements = collectEncodingElements(__filename, {})
expect(elements).toStrictEqual([])
})

it('should collect encoding elements from multi source encoding', () => {
const elements = collectEncodingElements(__filename, {
[__filename]: {
shape: {
field: 'filename',
scale: { domain: ['X', 'Y'], range: [Shape[0], Shape[1]] }
},
strokeDash: {
field: 'field',
scale: {
domain: ['A', 'B', 'C'],
range: [StrokeDash[0], StrokeDash[1], StrokeDash[2]]
}
}
}
})
expect(elements).toStrictEqual([
{
label: 'A',
type: EncodingType.STROKE_DASH,
value: StrokeDash[0]
},
{
label: 'B',
type: EncodingType.STROKE_DASH,
value: StrokeDash[1]
},
{
label: 'C',
type: EncodingType.STROKE_DASH,
value: StrokeDash[2]
},
{
label: 'X',
type: EncodingType.SHAPE,
value: Shape[0]
},
{
label: 'Y',
type: EncodingType.SHAPE,
value: Shape[1]
}
])
})
})
Loading