diff --git a/app/ui/src/analyses/experiments/comparison/view.ts b/app/ui/src/analyses/experiments/comparison/view.ts index 3ba43ec2d..92977c7e4 100644 --- a/app/ui/src/analyses/experiments/comparison/view.ts +++ b/app/ui/src/analyses/experiments/comparison/view.ts @@ -7,7 +7,7 @@ import {Weya as $, WeyaElement} from "../../../../../lib/weya/weya" import {Status} from "../../../models/status" import {DataLoader, Loader} from "../../../components/loader" import {ROUTER, SCREEN} from "../../../app" -import {BackButton, DeleteButton, EditButton} from "../../../components/buttons" +import {BackButton, DeleteButton, IconButton} from "../../../components/buttons" import {RunHeaderCard} from "../run_header/card" import {ComparisonPreferenceModel} from "../../../models/preferences" import {fillPlotPreferences} from "../../../components/charts/utils" @@ -22,6 +22,7 @@ import comparisonCache from "./cache" import {NetworkError} from "../../../network" import {RunsPickerView} from "../../../views/run_picker_view" import {SmoothingType} from "../../../components/charts/smoothing/smoothing_base" +import {RunsListItemView} from "../../../components/runs_list_item"; class ComparisonView extends ScreenView implements MetricDataStore { private readonly uuid: string @@ -52,6 +53,7 @@ class ComparisonView extends ScreenView implements MetricDataStore { private runPickerElem: HTMLDivElement private headerContainer: HTMLDivElement private saveButtonContainer: HTMLDivElement + private topButtonContainer: HTMLDivElement private loaderContainer: HTMLDivElement private actualWidth: number @@ -66,7 +68,7 @@ class ComparisonView extends ScreenView implements MetricDataStore { private baseAnalysisCache: AnalysisDataCache private missingBaseExperiment: boolean private deleteButton: DeleteButton - private editButton: EditButton + private editButton: IconButton constructor(uuid: string) { super() @@ -117,10 +119,10 @@ class ComparisonView extends ScreenView implements MetricDataStore { this.refresh = new AwesomeRefreshButton(this.onRefresh.bind(this)) this.deleteButton = new DeleteButton({onButtonClick: this.onDelete, parent: this.constructor.name}) - this.editButton = new EditButton({ + this.editButton = new IconButton({ onButtonClick: this.onEditClick, - parent: this.constructor.name - }) + parent: this.constructor.name, + }, '.fa.fa-balance-scale') } get requiresAuth(): boolean { @@ -151,8 +153,8 @@ class ComparisonView extends ScreenView implements MetricDataStore { new BackButton({text: 'Run', parent: this.constructor.name}).render($) $('div', $ => { - this.buttonContainer = $('div') this.saveButtonContainer = $('div') + this.topButtonContainer = $('div') }) this.refresh.render($) }) @@ -294,21 +296,32 @@ class ComparisonView extends ScreenView implements MetricDataStore { this.runHeaderCard.render($).then() $('span', '.compared-with', $ => { $('span', '.sub', 'Compared With ') - if (this.baseRun == null) { - $('span', '.title', 'No run selected') - } else { - $('a', '.title.clickable', `${this.baseRun.name} `, { - on: { - click: () => { - window.open(`/run/${this.baseRun.run_uuid}`, '_blank') - } - } - }) - if (this.baseRun.comment != "") { - $('span', `(${this.baseRun.comment || ''})`) - } - } + this.buttonContainer = $('div') }) + + if (this.baseRun == null) { + $('span', '.title', 'No run selected') + } else { + $('div.list.runs-list.list-group', $ => { + new RunsListItemView({ + item: { + run_uuid: this.baseRun.run_uuid, + computer_uuid: this.baseRun.computer_uuid, + run_status: null, + last_updated_time: null, + name: this.baseRun.name, + comment: this.baseRun.comment, + start_time: this.baseRun.start_time, + world_size: this.baseRun.world_size, + metric_values: [], + step: null, + tags: this.baseRun.tags + }, + width: this.actualWidth + }) + .render($) + }) + } }) } @@ -398,9 +411,13 @@ class ComparisonView extends ScreenView implements MetricDataStore { clearChildElements(this.buttonContainer) this.deleteButton.disabled = !this.baseUuid $(this.buttonContainer, $ => { - this.deleteButton.render($) this.editButton.render($) }) + + clearChildElements(this.topButtonContainer) + $(this.topButtonContainer, $ => { + this.deleteButton.render($) + }) } private async updateBaseRun(force: boolean) { diff --git a/app/ui/src/cache/cache.ts b/app/ui/src/cache/cache.ts index 12e2775da..77d6178ea 100644 --- a/app/ui/src/cache/cache.ts +++ b/app/ui/src/cache/cache.ts @@ -189,18 +189,6 @@ export class RunsListCache extends CacheObject { } } } - - getRuns(runUUIDS: Array): Array { - let runs = [] - if (this.data) { - for (let run of this.data.runs) { - if (runUUIDS.includes(run.run_uuid)) { - runs.push(run) - } - } - } - return runs - } } export class SessionsListCache extends CacheObject { diff --git a/app/ui/src/components/charts/lines/chart.ts b/app/ui/src/components/charts/lines/chart.ts index cd0a0c8bb..f91343a82 100644 --- a/app/ui/src/components/charts/lines/chart.ts +++ b/app/ui/src/components/charts/lines/chart.ts @@ -71,6 +71,9 @@ export class LineChart { this.chartWidth = windowWidth - 2 * this.margin - this.axisSize this.chartHeight = Math.round(Math.min(this.chartWidth, windowHeight) / 2) + this.baseSeries = this.baseSeries.filter((_, i) => this.basePlotIndex[i] == 1) + this.currentSeries = this.currentSeries.filter((_, i) => this.currentPlotIndex[i] == 1) + let idx: number = 0 for (let s of this.currentSeries.concat(this.baseSeries)) { if (!this.uniqueItems.has(s.name)) { @@ -78,9 +81,6 @@ export class LineChart { } } - this.baseSeries = this.baseSeries.filter((_, i) => this.basePlotIndex[i] == 1) - this.currentSeries = this.currentSeries.filter((_, i) => this.currentPlotIndex[i] == 1) - // get steps from series with at least one value const series_concat = this.baseSeries.concat(this.currentSeries).filter(s => s.trimmedSeries.length > 0) const stepExtent = getExtent(series_concat.map(s => s.trimmedSeries), d => d.step, false, true) diff --git a/app/ui/src/components/charts/spark_lines/chart.ts b/app/ui/src/components/charts/spark_lines/chart.ts index bc59b78f9..91a04ea9e 100644 --- a/app/ui/src/components/charts/spark_lines/chart.ts +++ b/app/ui/src/components/charts/spark_lines/chart.ts @@ -46,8 +46,10 @@ export class SparkLines { this.uniqueItems = new Map() this.onlySelected = opt.onlySelected ?? false + let filteredSeries = this.currentSeries.filter((s, i) => this.currentPlotIdx[i] == 1) + let filteredBaseSeries = this.baseSeries.filter((s, i) => this.basePlotIdx[i] == 1) let idx = 0 - for (let s of this.currentSeries.concat(this.baseSeries)) { + for (let s of filteredSeries.concat(filteredBaseSeries)) { if (!this.uniqueItems.has(s.name)) { this.uniqueItems.set(s.name, idx++) } @@ -87,7 +89,7 @@ export class SparkLines { stepExtent: this.stepExtent, width: this.rowWidth, onClick: onClick, - color: this.chartColors.getColor(this.uniqueItems.get(s.name)), + color: this.currentPlotIdx[i] == 1 ? this.chartColors.getColor(this.uniqueItems.get(s.name)): "", isMouseMoveOpt: this.isMouseMoveOpt, isComparison: this.baseSeries.length > 0 }) @@ -107,7 +109,7 @@ export class SparkLines { stepExtent: this.stepExtent, width: this.rowWidth, onClick: onClick, - color: this.chartColors.getSecondColor(this.uniqueItems.get(s.name)), + color: this.basePlotIdx[i] == 1 ? this.chartColors.getSecondColor(this.uniqueItems.get(s.name)) : "", isMouseMoveOpt: this.isMouseMoveOpt, isBase: true, isComparison: this.baseSeries.length > 0, diff --git a/app/ui/src/components/charts/spark_lines/spark_line.ts b/app/ui/src/components/charts/spark_lines/spark_line.ts index 5e8e98fea..fe585d985 100644 --- a/app/ui/src/components/charts/spark_lines/spark_line.ts +++ b/app/ui/src/components/charts/spark_lines/spark_line.ts @@ -98,15 +98,8 @@ export class SparkLine { render($: WeyaElementFunction) { $(`div.sparkline-list-item.list-group-item.${this.className}`, {on: {click: this.onClick}}, $ => { $(`div.sparkline-content`, {style: {width: `${Math.min(this.titleWidth * 2 + this.chartWidth, 450)}px`}}, $ => { - if (this.isComparison) { - $('i', `.fa.fa-chart-line.title.icon.chart`, '', {style: {color: this.isBase ? getBaseColor() : '#E15759'}}) - } - if (this.onClick != null) { - if (this.isSelected) { - $('span', '.fas.fa-eye.title.icon', '', {style: {color: getBaseColor()}}) - } else { - $('span', '.fas.fa-eye-slash.title.icon', '', {style: {color: getBaseColor()}}) - } + if (this.isComparison && this.isBase) { + $('i', `.fa.fa-balance-scale.title.icon.chart`, '', {style: {color: this.color}}) } let title = $('span', '.title', this.name, {style: {color: this.color}}) let sparkline = $('svg.sparkline', {style: {width: `${this.chartWidth + this.titleWidth * 2}px`}, height: 36}, $ => { diff --git a/app/ui/src/components/runs_list_item.ts b/app/ui/src/components/runs_list_item.ts index 61c2eecc3..5c7f670cb 100644 --- a/app/ui/src/components/runs_list_item.ts +++ b/app/ui/src/components/runs_list_item.ts @@ -7,7 +7,7 @@ import {TagView} from "./tag" export interface RunsListItemOptions { item: RunListItem - onClick: (elem: RunsListItemView) => void + onClick?: (elem: RunsListItemView) => void width: number } @@ -21,13 +21,19 @@ export class RunsListItemView { constructor(opt: RunsListItemOptions) { this.item = opt.item this.width = opt.width - this.onClick = (e: Event) => { - e.preventDefault() - opt.onClick(this) + if (opt.onClick) { + this.onClick = (e: Event) => { + e.preventDefault() + opt.onClick(this) + } } } private getTimeString() { + if (this.item.start_time == null || this.item.last_updated_time == null) { + return '' + } + let startDate = getDateTimeComponents(new Date(this.item.start_time * 1000)) let endDate = getDateTimeComponents(new Date(this.item.last_updated_time * 1000)) @@ -44,9 +50,11 @@ export class RunsListItemView { render($: WeyaElementFunction) { this.elem = $('a', '.list-item.list-group-item.list-group-item-action', - {href: `/run/${this.item.run_uuid}`, on: {click: this.onClick}}, + {href: `/run/${this.item.run_uuid}`, on: {click: this.onClick}, target: '_blank'}, $ => { - new StatusView({status: this.item.run_status, isDistributed: this.item.world_size>0}).render($) + if (this.item.run_status) { + new StatusView({status: this.item.run_status, isDistributed: this.item.world_size>0}).render($) + } $('div', '.spaced-row', $ => { $('div', $ => { $('p.time', this.getTimeString())