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

feat: allow for selecting different model-check baseline bundle in local dev mode #246

Merged
merged 14 commits into from
Sep 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/hello-world/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
baselines
sde-prep
1 change: 1 addition & 0 deletions examples/hello-world/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"scripts": {
"build": "sde bundle",
"dev": "sde dev",
"save-baseline": "sde-check baseline --save",
"serve": "sirv ./sde-prep/check-report"
},
"dependencies": {
Expand Down
4 changes: 3 additions & 1 deletion examples/sample-check-app/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ if (suiteSummaryJson) {
const checkOptions = getConfigOptions(baselineBundle() as Bundle, currentBundle() as Bundle)

// Initialize the root Svelte component
const appShell = initAppShell(checkOptions, suiteSummary)
const appShell = initAppShell(checkOptions, {
suiteSummary
})

export default appShell
1 change: 1 addition & 0 deletions examples/template-default/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
baselines
sde-prep
*.vdf
*.vdfx
Expand Down
2 changes: 1 addition & 1 deletion examples/template-default/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"scripts": {
"build": "sde bundle",
"dev": "sde dev",
"start": "sde dev"
"save-baseline": "sde-check baseline --save"
},
"workspaces": [
"packages/core",
Expand Down
1 change: 1 addition & 0 deletions examples/template-minimal/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
baselines
sde-prep
3 changes: 2 additions & 1 deletion examples/template-minimal/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"type": "module",
"scripts": {
"build": "sde bundle",
"dev": "sde dev"
"dev": "sde dev",
"save-baseline": "sde-check baseline --save"
},
"dependencies": {
"@sdeverywhere/build": "^0.2.0",
Expand Down
36 changes: 36 additions & 0 deletions packages/check-ui-shell/src/_shared/stores.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright (c) 2022 Climate Interactive / New Venture Fund

import type { Writable } from 'svelte/store'
import { writable } from 'svelte/store'

/**
* Return a Svelte writable store that is backed by local storage.
*/
export function localStorageWritableBoolean(key: string, defaultValue: boolean): Writable<boolean> {
const initialStringValue = localStorage.getItem(key)
let initialValue: boolean
if (initialStringValue !== undefined) {
initialValue = initialStringValue === '1'
} else {
initialValue = defaultValue
}

let currentValue = initialValue
const { subscribe, set } = writable(initialValue)

const _set = (newValue: boolean) => {
currentValue = newValue
localStorage.setItem(key, newValue ? '1' : '0')
set(newValue)
}

const _update = (updater: (value: boolean) => boolean) => {
_set(updater(currentValue))
}

return {
subscribe,
set: _set,
update: _update
}
}
26 changes: 19 additions & 7 deletions packages/check-ui-shell/src/app-init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ import { initAppModel } from './model/app-model'
import { default as AppShell } from './app-shell.svelte'
import { AppViewModel } from './app-vm'

export function initAppShell(
configOptions: ConfigOptions,
suiteSummary?: SuiteSummary,
containerId = 'app-shell-container'
): AppShell {
export interface AppShellOptions {
suiteSummary?: SuiteSummary
containerId?: string
bundleNames?: string[]
}

export function initAppShell(configOptions: ConfigOptions, appShellOptions?: AppShellOptions): AppShell {
// Initialize the root Svelte component
const containerId = appShellOptions?.containerId || 'app-shell-container'
const appShell = new AppShell({
target: document.getElementById(containerId),
props: {
Expand All @@ -23,8 +26,17 @@ export function initAppShell(
// Initialize the app model asynchronously
initAppModel(configOptions)
.then(appModel => {
// Create the app view model and update the AppShell component
const appViewModel = new AppViewModel(appModel, suiteSummary)
// Create the app view model
const appViewModel = new AppViewModel(appModel, appShellOptions?.suiteSummary)

if (appShellOptions?.bundleNames) {
// Set the list of available bundle names
// TODO: Pass these to AppViewModel constructor instead of setting them here
appViewModel.headerViewModel.bundleNamesL.set(appShellOptions.bundleNames)
appViewModel.headerViewModel.bundleNamesR.set(appShellOptions.bundleNames)
}

// Update the AppShell component
appShell.$set({
appViewModel
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ export function row(
rowClass: string,
status: CheckStatus,
content: string,
graphBoxViewModel?: CheckSummaryGraphBoxViewModel
graphBoxViewModel?: CheckSummaryGraphBoxViewModel,
graphVisible = false
): CheckSummaryRowViewModel {
const whitespace = '&ensp;'.repeat(2 + indent * 4)
const statusChar = charForStatus(status)
Expand All @@ -42,6 +43,6 @@ export function row(
status,
span,
graphBoxViewModel,
graphVisible: writable(false)
graphVisible: writable(graphVisible)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export function createCheckSummaryTestViewModel(
dataCoordinator: CheckDataCoordinator,
test: CheckTestReport
): CheckSummaryTestViewModel {
let expandedFirstGraph = false

const rows: CheckSummaryRowViewModel[] = []
const testRow = row(0, 'test', test.status, test.name)
for (const scenario of test.scenarios) {
Expand All @@ -32,15 +34,30 @@ export function createCheckSummaryTestViewModel(
rows.push(row(2, 'dataset', dataset.status, datasetMessage(dataset, bold)))
for (const predicate of dataset.predicates) {
let graphBoxViewModel: CheckSummaryGraphBoxViewModel
let graphVisible = false
if (scenario.checkScenario.scenario && dataset.checkDataset.datasetKey) {
graphBoxViewModel = new CheckSummaryGraphBoxViewModel(
dataCoordinator,
scenario.checkScenario.scenario,
dataset.checkDataset.datasetKey,
predicate
)
if (!expandedFirstGraph && predicate.result.status === 'failed') {
// Expand the graph for the first failing check
expandedFirstGraph = true
graphVisible = true
}
}
rows.push(row(3, 'predicate', predicate.result.status, predicateMessage(predicate, bold), graphBoxViewModel))
rows.push(
row(
3,
'predicate',
predicate.result.status,
predicateMessage(predicate, bold),
graphBoxViewModel,
graphVisible
)
)
}
}
}
Expand Down
14 changes: 13 additions & 1 deletion packages/check-ui-shell/src/components/header/header-vm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
import type { Writable } from 'svelte/store'
import { writable } from 'svelte/store'
import type { CompareConfig } from '@sdeverywhere/check-core'
import { localStorageWritableBoolean } from '../../_shared/stores'

export interface HeaderViewModel {
nameL?: string
nameR?: string
bundleNamesL: Writable<string[]>
bundleNamesR: Writable<string[]>
thresholds?: string[]
simplifyScenarios?: Writable<boolean>
}
Expand All @@ -15,7 +18,12 @@ export function createHeaderViewModel(
compareConfig: CompareConfig | undefined,
includeSimplifyScenarios: boolean
): HeaderViewModel {
const simplifyScenarios: Writable<boolean> = includeSimplifyScenarios ? writable(true) : undefined
let simplifyScenarios: Writable<boolean>
if (includeSimplifyScenarios) {
simplifyScenarios = localStorageWritableBoolean('sde-check-simplify-scenarios', true)
} else {
simplifyScenarios = undefined
}

// Only include the comparison-related header elements if the compare
// config is defined
Expand All @@ -31,11 +39,15 @@ export function createHeaderViewModel(
return {
nameL: compareConfig.bundleL.name,
nameR: compareConfig.bundleR.name,
bundleNamesL: writable([compareConfig.bundleL.name]),
bundleNamesR: writable([compareConfig.bundleR.name]),
thresholds: thresholdStrings,
simplifyScenarios
}
} else {
return {
bundleNamesL: writable([]),
bundleNamesR: writable([]),
simplifyScenarios
}
}
Expand Down
13 changes: 13 additions & 0 deletions packages/check-ui-shell/src/components/header/header.pug
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//- Copyright (c) 2021-2022 Climate Interactive / New Venture Fund

//- Note: These mixins are kept in an external pug file to work around a
//- Svelte issue related to `each` and TypeScript, see:
//- https://github.com/sveltejs/svelte-preprocess/issues/207

mixin optionsL
+each(`$bundleNamesL as name`)
option(selected!='{name === viewModel.nameL}') { name }

mixin optionsR
+each(`$bundleNamesR as name`)
option(selected!='{name === viewModel.nameR}') { name }
54 changes: 51 additions & 3 deletions packages/check-ui-shell/src/components/header/header.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,33 @@ import type { HeaderViewModel } from './header-vm'
export let viewModel: HeaderViewModel
const simplifyScenarios = viewModel.simplifyScenarios
const thresholds = viewModel.thresholds
const bundleNamesL = viewModel.bundleNamesL
const bundleNamesR = viewModel.bundleNamesR

const dispatch = createEventDispatcher()

function onHome() {
dispatch('command', { cmd: 'show-summary' })
}

function onSelectBundle(kind: string, name: string): void {
const changeEvent = new CustomEvent('sde-check-bundle', {
detail: {
kind,
name
}
})
document.dispatchEvent(changeEvent)
}

function onSelectBundleL(e: Event) {
onSelectBundle('left', (e.target as HTMLSelectElement).value)
}

function onSelectBundleR(e: Event) {
onSelectBundle('right', (e.target as HTMLSelectElement).value)
}

</script>


Expand All @@ -26,6 +46,8 @@ function onHome() {
<!-- TEMPLATE -->
<template lang='pug'>

include header.pug

.header-container
.header-content
.header-group
Expand All @@ -35,12 +57,20 @@ function onHome() {
.header-group
input.checkbox(type='checkbox' name='simplify-toggle' bind:checked!='{$simplifyScenarios}')
label(for='simplify-toggle') Simplify Scenarios
+if('viewModel.nameL')
+if('viewModel.nameL || $bundleNamesL.length > 1')
.spacer-fixed
.header-group
.label Comparing:
.label.dataset-color-0 {viewModel.nameL}
.label.dataset-color-1 {viewModel.nameR}
+if('$bundleNamesL.length > 1')
select.selector.dataset-color-0(on:change!='{onSelectBundleL}')
+optionsL
+else
.label.dataset-color-0 {viewModel.nameL}
+if('$bundleNamesR.length > 1')
select.selector.dataset-color-1(on:change!='{onSelectBundleR}')
+optionsR
+else
.label.dataset-color-1 {viewModel.nameR}
.spacer-fixed
.header-group
.label Thresholds:
Expand Down Expand Up @@ -91,6 +121,24 @@ function onHome() {
.label:not(:last-child)
margin-right: 1rem

select
margin-right: 1rem
font-family: Roboto, sans-serif
font-size: 1em
// XXX: Remove browser-provided background, but preserve arrow; based on:
// https://stackoverflow.com/a/57510283
-webkit-appearance: none
-moz-appearance: none
appearance: none
padding: .2rem 1.6rem .2rem .4rem
background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100' fill='%23555'><polygon points='0,0 100,0 50,60'/></svg>") no-repeat
background-size: .8rem
background-position: calc(100% - .4rem) 70%
background-repeat: no-repeat
background-color: #353535
border: none
border-radius: .4rem

.line
min-height: 1px
margin-bottom: 1rem
Expand Down
14 changes: 11 additions & 3 deletions packages/check-ui-shell/src/components/stats/stats-table-vm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ export function createStatsTableViewModel(
return n === 0 ? '' : `${signed(n, 1)}%`
}

function pctChange(s0: number, s1: number): number {
if (s0 !== 0) {
return ((s1 - s0) / s0) * 100
} else {
return 0
}
}

const modelSpecL = compareConfig.bundleL.model.modelSpec
const modelSpecR = compareConfig.bundleR.model.modelSpec

Expand All @@ -38,17 +46,17 @@ export function createStatsTableViewModel(
const modelSizeL = modelSpecL.modelSizeInBytes
const modelSizeR = modelSpecR.modelSizeInBytes
const modelSizeChange = modelSizeR - modelSizeL
const modelSizePctChange = ((modelSizeR - modelSizeL) / modelSizeL) * 100
const modelSizePctChange = pctChange(modelSizeL, modelSizeR)

const dataSizeL = modelSpecL.dataSizeInBytes
const dataSizeR = modelSpecR.dataSizeInBytes
const dataSizeChange = dataSizeR - dataSizeL
const dataSizePctChange = ((dataSizeR - dataSizeL) / dataSizeL) * 100
const dataSizePctChange = pctChange(dataSizeL, dataSizeR)

const avgTimeL = perfReportL.avgTime || 0
const avgTimeR = perfReportR.avgTime || 0
const avgTimeChange = avgTimeR - avgTimeL
const avgTimePctChange = avgTimeL > 0 ? ((avgTimeR - avgTimeL) / avgTimeL) * 100 : 0
const avgTimePctChange = pctChange(avgTimeL, avgTimeR)

const minTimeL = perfReportL.minTime
const minTimeR = perfReportR.minTime
Expand Down
4 changes: 2 additions & 2 deletions packages/check-ui-shell/src/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ sub {
*/

:root {
--dataset-0: deepskyblue;
--dataset-1: crimson;
--dataset-0: crimson;
--dataset-1: deepskyblue;
--bucket-0: green;
--bucket-1: orange;
--bucket-2: orangered;
Expand Down
12 changes: 7 additions & 5 deletions packages/check-ui-shell/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import type { ConfigOptions, SuiteSummary } from '@sdeverywhere/check-core'

export function initAppShell(
configOptions: ConfigOptions,
suiteSummary?: SuiteSummary,
containerId = 'app-shell-container'
): unknown
export interface AppShellOptions {
suiteSummary?: SuiteSummary
containerId?: string
bundleNames?: string[]
}

export function initAppShell(configOptions: ConfigOptions, appShellOptions?: AppShellOptions): unknown
Loading