Skip to content

Commit

Permalink
fix: remove overflow, allow resizing
Browse files Browse the repository at this point in the history
  • Loading branch information
mturoci authored and lo5 committed Jan 6, 2021
1 parent c7f5ff7 commit 035e56e
Show file tree
Hide file tree
Showing 13 changed files with 121 additions and 102 deletions.
2 changes: 2 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
[flake8]
# Ignore unused imports because wave apps need "main" imported eventhough it is not used (ASGI works that way).
ignore = F401
per-file-ignores =
py/demo/dashboard_*.py:F405,F403
max-line-length = 120
exclude =
py/h2o_wave/ui.py
Expand Down
4 changes: 2 additions & 2 deletions py/demo/dashboard_red.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ async def show_red_dashboard(q: Q):
zones=[
ui.zone('header', size='80px'),
ui.zone('title', size='0'),
ui.zone('top', direction=ui.ZoneDirection.ROW, size='385px', zones=[
ui.zone('top', direction=ui.ZoneDirection.ROW, zones=[
ui.zone('top_left', size='66%'),
ui.zone('top_right', zones=[
ui.zone('top_right_top', direction=ui.ZoneDirection.ROW),
Expand Down Expand Up @@ -71,7 +71,7 @@ async def show_red_dashboard(q: Q):
('B', next(audience_days2), next(audience_hits2)) for i in range(60)],
pack=True
),
height='210px',
height='390px',
)
],
)
Expand Down
4 changes: 2 additions & 2 deletions ui/src/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ const
$nest: {
'>*:first-child': {
boxSizing: 'border-box',
margin: 15,
padding: 15,
}
}
},
Expand All @@ -164,7 +164,7 @@ const
transparent: {
$nest: {
'>*:first-child': {
margin: '0 15px'
padding: '0 15px'
}
}
},
Expand Down
69 changes: 38 additions & 31 deletions ui/src/parts/microarea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,40 +36,47 @@ const curves: Record<S, d3.CurveFactory> = {
export const MicroArea = ({ value, color, data, zeroValue, curve }: Props) => {
const
ref = React.useRef<SVGSVGElement>(null),
[SVGContent, setSVGContent] = React.useState<JSX.Element | null>(null)
[minY, maxY] = React.useMemo(() => {
let [minY, maxY] = d3.extent<any, any>(data, d => d[value])

React.useLayoutEffect(() => {
let [minY, maxY] = d3.extent<any, any>(data, d => d[value])

if (zeroValue != null) {
minY = Math.min(zeroValue, minY)
maxY = Math.max(zeroValue, maxY)
if (zeroValue != null) {
minY = Math.min(zeroValue, minY)
maxY = Math.max(zeroValue, maxY)
}
return [minY, maxY]
}, [data, zeroValue]),
[SVGContent, setSVGContent] = React.useState<JSX.Element | null>(null),
renderViz = () => {
const
scaleX = d3.scaleLinear().domain([0, data.length - 1]).range([0, ref.current?.clientWidth!]),
scaleY = d3.scaleLinear().domain([minY, maxY]).range([ref.current?.clientHeight!, 2]),
fcurve = curves[curve] || d3.curveLinear,
ln = d3.line<any>()
// .curve(d3.curveBasis) // XXX add support for this
.defined(d => d && d[value] != null)
.x((_, i) => scaleX(i))
.y(d => scaleY(d[value]))
.curve(fcurve),
ar = d3.area<any>()
// .curve(d3.curveBasis) // XXX add support for this
.defined(d => d && d[value] != null)
.x((_, i) => scaleX(i))
.y0(_ => scaleY(zeroValue == null ? minY : zeroValue))
.y1(d => scaleY(d[value]))
.curve(fcurve)
setSVGContent(
<>
<path d={ar(data) as S} fill={color} fillOpacity='0.1' strokeLinejoin='round' strokeLinecap='round'></path>
<path d={ln(data) as S} fill='none' stroke={color} strokeWidth='1.5' strokeLinejoin='round' strokeLinecap='round'></path>
</>
)
}

const
scaleX = d3.scaleLinear().domain([0, data.length - 1]).range([0, ref.current?.clientWidth!]),
scaleY = d3.scaleLinear().domain([minY, maxY]).range([ref.current?.clientHeight!, 2]), // 2px less so that stroke doesn't clip at edges
fcurve = curves[curve] || d3.curveLinear,
ln = d3.line<any>()
// .curve(d3.curveBasis) // XXX add support for this
.defined(d => d && d[value] != null)
.x((_, i) => scaleX(i))
.y(d => scaleY(d[value]))
.curve(fcurve),
ar = d3.area<any>()
// .curve(d3.curveBasis) // XXX add support for this
.defined(d => d && d[value] != null)
.x((_, i) => scaleX(i))
.y0(_ => scaleY(zeroValue == null ? minY : zeroValue))
.y1(d => scaleY(d[value]))
.curve(fcurve)
setSVGContent(
<>
<path d={ar(data) as S} fill={color} fillOpacity='0.1' strokeLinejoin='round' strokeLinecap='round' ></path>
<path d={ln(data) as S} fill='none' stroke={color} strokeWidth='1.5' strokeLinejoin='round' strokeLinecap='round'></path>
</>
)
}, [value, color, data, zeroValue, curve])
React.useEffect(() => {
window.addEventListener('resize', renderViz)
return () => window.removeEventListener('resize', renderViz)
}, [])
React.useLayoutEffect(renderViz, [value, color, data, zeroValue, curve])

return <svg ref={ref} width='100%' height='100%'>{SVGContent}</svg>
}
41 changes: 24 additions & 17 deletions ui/src/parts/microbars.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,33 @@ interface Props {
export const MicroBars = ({ value, category = 'x', color, data, zeroValue }: Props) => {
const
ref = React.useRef<SVGSVGElement | null>(null),
[rects, setRects] = React.useState<JSX.Element[] | null>(null)
[rects, setRects] = React.useState<JSX.Element[] | null>(null),
[minY, maxY] = React.useMemo(() => {
let [minY, maxY] = d3.extent<any, any>(data, d => d[value])

React.useLayoutEffect(() => {
let [minY, maxY] = d3.extent<any, any>(data, d => d[value])

if (zeroValue != null) {
minY = Math.min(zeroValue, minY)
maxY = Math.max(zeroValue, maxY)
if (zeroValue != null) {
minY = Math.min(zeroValue, minY)
maxY = Math.max(zeroValue, maxY)
}
return [minY, maxY]
}, [data, zeroValue]),
renderViz = () => {
const
height = ref.current?.clientHeight!,
scaleX = d3.scaleBand().domain(data.map(d => d[category])).range([0, ref.current?.clientWidth!]).paddingInner(0.1),
scaleY = d3.scaleLinear().domain([minY, maxY]).range([height, 0]),
rects = data.map((d, i) => {
const x = scaleX(d[category]), y = scaleY(d[value])
return <rect key={i} fill={color} x={x} y={y} width={2} height={height - y} />
})
setRects(rects)
}

const
height = ref.current?.clientHeight!,
scaleX = d3.scaleBand().domain(data.map(d => d[category])).range([0, ref.current?.clientWidth!]).paddingInner(0.1),
scaleY = d3.scaleLinear().domain([minY, maxY]).range([height, 0]),
rects = data.map((d, i) => {
const x = scaleX(d[category]), y = scaleY(d[value])
return <rect key={i} fill={color} x={x} y={y} width={2} height={height - y} />
})
setRects(rects)
}, [value, category, color, data, zeroValue])
React.useEffect(() => {
window.addEventListener('resize', renderViz)
return () => window.removeEventListener('resize', renderViz)
}, [])
React.useLayoutEffect(renderViz, [value, category, color, data, zeroValue])

return <svg ref={ref} width='100%' height='100%'>{rects}</svg>
}
59 changes: 32 additions & 27 deletions ui/src/parts/progress_arc.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,34 +26,39 @@ interface Props {
export const ProgressArc = ({ thickness, color, value }: Props) => {
const
ref = React.useRef<SVGSVGElement>(null),
[SVGContent, setSVGContent] = React.useState<JSX.Element | null>(null)
[SVGContent, setSVGContent] = React.useState<JSX.Element | null>(null),
renderViz = () => {
const
width = ref.current?.clientWidth!,
height = ref.current?.clientHeight!,
size = Math.min(width, height),
outerRadius = size / 2,
innerRadius = size / 2 - thickness,
slot = d3.arc()({
outerRadius,
innerRadius,
startAngle: 0,
endAngle: 2 * Math.PI,
}),
bar = d3.arc()({
outerRadius,
innerRadius,
startAngle: 0,
endAngle: 2 * Math.PI * value,
})
setSVGContent((
<g transform={size === height ? `translate(${(width - (2 * outerRadius)) / 2}, 0)` : `translate(0, ${(height - (2 * outerRadius)) / 2})`}>
<path d={slot as S} fill={color} fillOpacity={0.15} transform={`translate(${outerRadius},${outerRadius})`} />
<path d={bar as S} fill={color} transform={`translate(${outerRadius},${outerRadius})`} />
</g>
))
}

React.useLayoutEffect(() => {
const
width = ref.current?.clientWidth!,
height = ref.current?.clientHeight!,
size = Math.min(width, height),
outerRadius = size / 2,
innerRadius = size / 2 - thickness,
slot = d3.arc()({
outerRadius,
innerRadius,
startAngle: 0,
endAngle: 2 * Math.PI,
}),
bar = d3.arc()({
outerRadius,
innerRadius,
startAngle: 0,
endAngle: 2 * Math.PI * value,
})
setSVGContent((
<g transform={size === height ? `translate(${(width - (2 * outerRadius)) / 2}, 0)` : `translate(0, ${(height - (2 * outerRadius)) / 2})`}>
<path d={slot as S} fill={color} fillOpacity={0.15} transform={`translate(${outerRadius},${outerRadius})`} />
<path d={bar as S} fill={color} transform={`translate(${outerRadius},${outerRadius})`} />
</g>
))
}, [thickness, color, value])
React.useEffect(() => {
window.addEventListener('resize', renderViz)
return () => window.removeEventListener('resize', renderViz)
}, [])
React.useLayoutEffect(renderViz, [thickness, color, value])

return <svg ref={ref} width='100%' height='100%'>{SVGContent}</svg>
}
4 changes: 1 addition & 3 deletions ui/src/section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ const
lhs: {
flexGrow: 1,
},
rhs: {
},
title: {
...theme.font.s14,
...theme.font.w6,
Expand Down Expand Up @@ -65,7 +63,7 @@ export const
{ title, subtitle, items } = state,
components = unpack<Component[]>(items), // XXX ugly
form = items && (
<div className={css.rhs}>
<div>
<XComponents items={components} alignment={XComponentAlignment.Right} />
</div>
)
Expand Down
10 changes: 5 additions & 5 deletions ui/src/small_series_stat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

import React from 'react'
import { stylesheet } from 'typestyle'
import { cards, Format } from './layout'
import { cards, Format, grid } from './layout'
import { bond, Card, unpack, F, Rec, S, Data } from './qd'
import { getTheme } from './theme'
import { MicroBars } from './parts/microbars'
Expand All @@ -32,8 +32,8 @@ const
...theme.font.s12,
},
plot: {
// 30px top/bottom padding + 17px line height of the title.
height: 'calc(100% - 47px)',
// 32px is title height.
height: `calc(100% - 32px)`,
width: '100%'
},
})
Expand Down Expand Up @@ -86,8 +86,8 @@ export const
/>
)
return (
<Fluent.Stack data-test={name} style={{ position: 'static', height: '100%' }}>
<Fluent.Stack horizontal horizontalAlign='space-between' padding={15}>
<Fluent.Stack data-test={name} style={{ position: 'static', height: '100%', padding: grid.gap }}>
<Fluent.Stack horizontal horizontalAlign='space-between' styles={{ root: { paddingBottom: grid.gap } }}>
<Format data={data} format={s.title || 'Untitled'} className={css.title} />
<Format data={data} format={s.value} className={css.value} />
</Fluent.Stack>
Expand Down
4 changes: 2 additions & 2 deletions ui/src/tall_gauge_stat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import * as Fluent from '@fluentui/react'
import React from 'react'
import { stylesheet } from 'typestyle'
import { cards, Format } from './layout'
import { cards, Format, grid } from './layout'
import { ProgressArc } from './parts/progress_arc'
import { bond, Card, F, Rec, S, unpack } from './qd'
import { getTheme } from './theme'
Expand Down Expand Up @@ -62,7 +62,7 @@ export const
const render = () => {
const data = unpack(s.data)
return (
<Fluent.Stack data-test={name} style={{ position: 'static', padding: 15, height: '100%' }}>
<Fluent.Stack data-test={name} style={{ position: 'static', height: '100%', padding: grid.gap }}>
<Format data={data} format={s.title} className={css.title} />
<Fluent.StackItem grow={1} styles={{ root: { position: 'relative', height: 'calc(100% - 17px)' } }}>
<ProgressArc thickness={2} color={theme.color(s.plot_color)} value={s.progress} />
Expand Down
10 changes: 5 additions & 5 deletions ui/src/tall_series_stat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import * as Fluent from '@fluentui/react'
import React from 'react'
import { stylesheet } from 'typestyle'
import { cards, Format } from './layout'
import { cards, Format, grid } from './layout'
import { MicroArea } from './parts/microarea'
import { MicroBars } from './parts/microbars'
import { bond, Card, Data, F, Rec, S, unpack } from './qd'
Expand All @@ -37,8 +37,8 @@ const
color: theme.colors.text7,
},
plot: {
// 98px is the height of titlebar
height: 'calc(100% - 98px)',
// 83px is the height of titlebar.
height: 'calc(100% - 83px)',
width: '100%'
}
})
Expand Down Expand Up @@ -94,8 +94,8 @@ export const
)

return (
<Fluent.Stack data-test={name} style={{ position: 'static', height: '100%' }}>
<Fluent.StackItem tokens={{ padding: 15 }}>
<Fluent.Stack data-test={name} style={{ position: 'static', height: '100%', padding: grid.gap }}>
<Fluent.StackItem styles={{ root: { paddingBottom: grid.gap } }}>
<Format data={data} format={s.title || 'Untitled'} className={css.title} />
<Format data={data} format={s.value} className={css.value} />
<Format data={data} format={s.aux_value} className={css.aux_value} />
Expand Down
4 changes: 2 additions & 2 deletions ui/src/wide_bar_stat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import * as Fluent from '@fluentui/react'
import React from 'react'
import { stylesheet } from 'typestyle'
import { cards, Format } from './layout'
import { cards, Format, grid } from './layout'
import { ProgressBar } from './parts/progress_bar'
import { bond, Card, F, Rec, S, unpack } from './qd'
import { getTheme } from './theme'
Expand Down Expand Up @@ -58,7 +58,7 @@ export const
const render = () => {
const data = unpack(s.data)
return (
<Fluent.Stack data-test={name} style={{ position: 'static', padding: 15, height: '100%' }}>
<Fluent.Stack data-test={name} style={{ position: 'static', height: '100%', padding: grid.gap }}>
<Format data={data} format={s.title} className={css.title} />
<Fluent.StackItem grow={1}>
<Fluent.Stack horizontal verticalAlign='baseline' tokens={{ childrenGap: 5 }}>
Expand Down
4 changes: 2 additions & 2 deletions ui/src/wide_gauge_stat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import * as Fluent from '@fluentui/react'
import React from 'react'
import { stylesheet } from 'typestyle'
import { cards, Format } from './layout'
import { cards, Format, grid } from './layout'
import { ProgressArc } from './parts/progress_arc'
import { bond, Card, F, Rec, S, unpack } from './qd'
import { getTheme } from './theme'
Expand Down Expand Up @@ -67,7 +67,7 @@ export const
const render = () => {
const data = unpack(s.data)
return (
<Fluent.Stack horizontal data-test={name} style={{ position: 'static', padding: 15, height: '100%' }}>
<Fluent.Stack horizontal data-test={name} style={{ position: 'static', padding: grid.gap, height: '100%' }}>
<Fluent.StackItem grow={1} styles={{ root: { position: 'relative' } }}>
<ProgressArc thickness={2} color={theme.color(s.plot_color)} value={s.progress} />
<Fluent.Stack horizontalAlign='center' verticalAlign='center' className={css.percentContainer}>
Expand Down
Loading

0 comments on commit 035e56e

Please sign in to comment.