Commit e50ed7d4 authored by Markus Scheidgen's avatar Markus Scheidgen
Browse files

Merge branch 'migration' into worker_routing

parents 74198011 da14d737
Pipeline #45223 passed with stages
in 26 minutes and 50 seconds
......@@ -8,6 +8,7 @@
"@navjobs/upload": "^3.1.3",
"base-64": "^0.1.0",
"chroma-js": "^2.0.3",
"d3": "^5.9.1",
"fetch": "^1.1.0",
"file-saver": "^2.0.0",
"html-to-react": "^1.3.3",
......
import React from 'react'
import PropTypes from 'prop-types'
import { withStyles, Typography } from '@material-ui/core'
import * as d3 from 'd3'
import { scaleBand, scalePow } from 'd3-scale'
import chroma from 'chroma-js'
import repoColor from '@material-ui/core/colors/deepPurple'
class QuantityHistogram extends React.Component {
static propTypes = {
classes: PropTypes.object.isRequired,
title: PropTypes.string.isRequired,
width: PropTypes.number.isRequired,
data: PropTypes.object,
onSelectionChanged: PropTypes.func.isRequired
}
static styles = theme => ({
root: {
}
})
constructor(props) {
super(props)
this.container = React.createRef()
this.svgEl = React.createRef()
}
state = {
selected: undefined
}
componentDidMount() {
this.updateChart()
}
componentDidUpdate() {
this.updateChart()
}
handleItemClicked(item) {
const isSelected = this.state.selected === item.name
let selected
if (isSelected) {
selected = undefined
} else {
selected = item.name
}
this.setState({selected: selected})
this.props.onSelectionChanged(selected)
}
updateChart() {
if (!this.props.data) {
return
}
const { selected } = this.state
const width = this.container.current.offsetWidth
const height = Object.keys(this.props.data).length * 32
const data = Object.keys(this.props.data).map(key => ({
name: key,
value: this.props.data[key]
}))
const y = scaleBand().rangeRound([0, height]).padding(0.1)
const x = scalePow().range([0, width]).exponent(0.5)
const heatmapScale = chroma.scale(['#ffcdd2', '#d50000'])
x.domain([0, d3.max(data, d => d.value)])
y.domain(data.map(d => d.name))
heatmapScale.domain([0, d3.max(data, d => d.value)], 10, 'log')
let svg = d3.select(this.svgEl.current)
svg.attr('width', width)
svg.attr('height', height)
let withData = svg
.selectAll('g')
.data(data, data => data.name)
withData.exit().remove()
const rectColor = d => selected === d.name ? repoColor[500] : heatmapScale(d.value)
const textColor = d => selected === d.name ? '#FFF' : '#000'
let item = withData.enter()
.append('g')
item
.append('rect')
.attr('x', x(0))
.attr('y', d => y(d.name))
.attr('width', d => x(d.value) - x(0))
.attr('height', y.bandwidth())
.style('fill', rectColor)
.style('stroke', '#000')
.style('stroke-width', '1px')
.style('shape-rendering', 'geometricPrecision')
item
.append('text')
.attr('class', 'name')
.attr('dy', '.75em')
.attr('x', x(0) + 4)
.attr('y', d => y(d.name) + 4)
.attr('text-anchor', 'start')
.style('fill', textColor)
.text(d => d.name)
item
.append('text')
.attr('class', 'value')
.attr('dy', y.bandwidth())
.attr('y', d => y(d.name) - 4)
.attr('x', d => x(d.value) - 4)
.attr('text-anchor', 'end')
.style('fill', textColor)
.text(d => '' + d.value)
item
.style('cursor', 'pointer')
.on('click', d => this.handleItemClicked(d))
const t = d3.transition().duration(500)
item = withData.transition(t)
item
.select('rect')
.attr('y', d => y(d.name))
.attr('width', d => x(d.value) - x(0))
.attr('height', y.bandwidth())
.style('fill', rectColor)
item
.select('.name')
.text(d => d.name)
.attr('y', d => y(d.name) + 4)
.style('fill', textColor)
item
.select('.value')
.text(d => '' + d.value)
.attr('y', d => y(d.name) - 4)
.attr('x', d => x(d.value) - 4)
.style('fill', textColor)
}
render() {
const { classes, title } = this.props
return (
<div className={classes.root} ref={this.container}>
<Typography variant="body1">{title}</Typography>
<svg ref={this.svgEl} />
</div>
)
}
}
export default withStyles(QuantityHistogram.styles)(QuantityHistogram)
......@@ -8,7 +8,7 @@ import TablePagination from '@material-ui/core/TablePagination'
import TableRow from '@material-ui/core/TableRow'
import Paper from '@material-ui/core/Paper'
import { TableHead, LinearProgress, FormControl, FormControlLabel, Checkbox, FormGroup,
FormLabel, IconButton, MuiThemeProvider, Typography, Tooltip, TableSortLabel, ExpansionPanelDetails, ExpansionPanelSummary, ExpansionPanel } from '@material-ui/core'
FormLabel, IconButton, MuiThemeProvider, Typography, Tooltip, TableSortLabel, ExpansionPanelDetails, ExpansionPanelSummary, ExpansionPanel, Grid } from '@material-ui/core'
import { compose } from 'recompose'
import { withErrors } from './errors'
import AnalyticsIcon from '@material-ui/icons/Settings'
......@@ -18,6 +18,7 @@ import { withApi } from './api'
import CalcDialog from './CalcDialog'
import PeriodicTable from './PeriodicTable'
import ExpandMoreIcon from '@material-ui/icons/ExpandMore'
import QuantityHistogram from './QuantityHistogram'
class Repo extends React.Component {
static propTypes = {
......@@ -60,17 +61,54 @@ class Repo extends React.Component {
},
clickableRow: {
cursor: 'pointer'
},
quantityGrid: {
minWidth: 524,
maxWidth: 924,
margin: 'auto',
width: '100%'
},
quantity: {
marginTop: theme.spacing.unit * 2
}
})
static rowConfig = {
formula: 'Formula',
code_name: 'Code',
basis_set: 'Basis set',
system: 'System',
crystal_system: 'Crystal system',
spacegroup: 'Spacegroup',
xc_functional: 'XT treatment'
formula: {
label: 'Formula'
},
code_name: {
label: 'Code'
},
basis_set: {
label: 'Basis set'
},
xc_functional: {
label: 'XT treatment'
},
system: {
label: 'System'
},
crystal_system: {
label: 'Crystal system'
},
spacegroup_symbol: {
label: 'Spacegroup'
},
authors: {
label: 'Authors',
render: (authors) => authors.map(author => author.name).join('; ')
},
references: {
label: 'References',
render: (references) => {
if (references) {
return references.map((reference, index) => <a key={index} href={reference}>{reference}</a>)
} else {
return <i>no references</i>
}
}
}
}
state = {
......@@ -88,7 +126,7 @@ class Repo extends React.Component {
update(changes) {
changes = changes || {}
const { page, rowsPerPage, owner, sortedBy, sortOrder, atoms } = {...this.state, ...changes}
const { page, rowsPerPage, owner, sortedBy, sortOrder, atoms, system, crystal_system, code_name, xc_functional, basis_set } = {...this.state, ...changes}
this.setState({loading: true, ...changes})
this.props.api.search({
......@@ -97,7 +135,12 @@ class Repo extends React.Component {
owner: owner || 'all',
order_by: sortedBy,
order: (sortOrder === 'asc') ? 1 : -1,
atoms: atoms
atoms: atoms,
system: system,
crystal_system: crystal_system,
code_name: code_name,
xc_functional: xc_functional,
basis_set: basis_set
}).then(data => {
const { pagination: { total, page, per_page }, results, aggregations } = data
this.setState({
......@@ -156,11 +199,33 @@ class Repo extends React.Component {
this.update({atoms: selection})
}
handleQuantitySelectionChanged(quantity, selection) {
const update = {}
update[quantity] = selection
this.update(update)
}
renderCell(key, rowConfig, calc) {
const value = calc[key]
if (rowConfig.render) {
return rowConfig.render(value)
} else {
return value
}
}
render() {
const { classes, user } = this.props
const { data, aggregations, rowsPerPage, page, total, loading, sortedBy, sortOrder, openCalc } = this.state
const { data, rowsPerPage, page, total, loading, sortedBy, sortOrder, openCalc } = this.state
const emptyRows = rowsPerPage - Math.min(rowsPerPage, total - (page - 1) * rowsPerPage)
const aggregations = this.state.aggregations || {}
const quantity = (key, title) => (<QuantityHistogram
classes={{root: classes.quantity}} title={title || key} width={300}
data={aggregations[key]}
onSelectionChanged={(selection) => this.handleQuantitySelectionChanged(key, selection)}/>)
const ownerLabel = {
all: 'All calculations',
user: 'Your calculations',
......@@ -195,6 +260,20 @@ class Repo extends React.Component {
aggregations={aggregations ? aggregations.atoms : null}
onSelectionChanged={(selection) => this.handleElementSelectionChanged(selection)}
/>
<Grid container spacing={24} className={classes.quantityGrid}>
<Grid item xs={4}>
{quantity('system')}
{quantity('crystal_system', 'crystal system')}
</Grid>
<Grid item xs={4}>
{quantity('basis_set', 'basis set')}
{quantity('xc_functional', 'XC functionals')}
</Grid>
<Grid item xs={4}>
{quantity('code_name', 'code')}
</Grid>
</Grid>
</ExpansionPanelDetails>
</ExpansionPanel>
......@@ -229,7 +308,7 @@ class Repo extends React.Component {
direction={sortOrder}
onClick={() => this.handleSort(key)}
>
{Repo.rowConfig[key]}
{Repo.rowConfig[key].label}
</TableSortLabel>
</Tooltip>
</TableCell>
......@@ -241,7 +320,7 @@ class Repo extends React.Component {
<TableRow hover tabIndex={-1} key={index} className={classes.clickableRow}>
{Object.keys(Repo.rowConfig).map((key, rowIndex) => (
<TableCell padding="dense" key={rowIndex} onClick={() => this.handleClickCalc(calc)} >
{calc[key]}
{this.renderCell(key, Repo.rowConfig[key], calc)}
</TableCell>
))}
</TableRow>
......
......@@ -1843,14 +1843,14 @@ combined-stream@^1.0.5, combined-stream@^1.0.6, combined-stream@~1.0.6:
dependencies:
delayed-stream "~1.0.0"
commander@2, commander@^2.11.0:
version "2.19.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
commander@2.17.x, commander@~2.17.1:
version "2.17.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
commander@^2.11.0:
version "2.19.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
commondir@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
......@@ -2170,6 +2170,222 @@ currently-unhandled@^0.4.1:
dependencies:
array-find-index "^1.0.1"
d3-array@1, d3-array@^1.1.1, d3-array@^1.2.0:
version "1.2.4"
resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.4.tgz#635ce4d5eea759f6f605863dbcfc30edc737f71f"
d3-axis@1:
version "1.0.12"
resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-1.0.12.tgz#cdf20ba210cfbb43795af33756886fb3638daac9"
d3-brush@1:
version "1.0.6"
resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-1.0.6.tgz#33691f2032d9db6c5d8cb684ff255a9883629e21"
dependencies:
d3-dispatch "1"
d3-drag "1"
d3-interpolate "1"
d3-selection "1"
d3-transition "1"
d3-chord@1:
version "1.0.6"
resolved "https://registry.yarnpkg.com/d3-chord/-/d3-chord-1.0.6.tgz#309157e3f2db2c752f0280fedd35f2067ccbb15f"
dependencies:
d3-array "1"
d3-path "1"
d3-collection@1:
version "1.0.7"
resolved "https://registry.yarnpkg.com/d3-collection/-/d3-collection-1.0.7.tgz#349bd2aa9977db071091c13144d5e4f16b5b310e"
d3-color@1:
version "1.2.3"
resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-1.2.3.tgz#6c67bb2af6df3cc8d79efcc4d3a3e83e28c8048f"
d3-contour@1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/d3-contour/-/d3-contour-1.3.2.tgz#652aacd500d2264cb3423cee10db69f6f59bead3"
dependencies:
d3-array "^1.1.1"
d3-dispatch@1:
version "1.0.5"
resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-1.0.5.tgz#e25c10a186517cd6c82dd19ea018f07e01e39015"
d3-drag@1:
version "1.2.3"
resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-1.2.3.tgz#46e206ad863ec465d88c588098a1df444cd33c64"
dependencies:
d3-dispatch "1"
d3-selection "1"
d3-dsv@1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-1.1.1.tgz#aaa830ecb76c4b5015572c647cc6441e3c7bb701"
dependencies:
commander "2"
iconv-lite "0.4"
rw "1"
d3-ease@1:
version "1.0.5"
resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-1.0.5.tgz#8ce59276d81241b1b72042d6af2d40e76d936ffb"
d3-fetch@1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/d3-fetch/-/d3-fetch-1.1.2.tgz#957c8fbc6d4480599ba191b1b2518bf86b3e1be2"
dependencies:
d3-dsv "1"
d3-force@1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-1.2.0.tgz#60713f7efe8764f53e685d69433c06914dc4ea4c"
dependencies:
d3-collection "1"
d3-dispatch "1"
d3-quadtree "1"
d3-timer "1"
d3-format@1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.3.2.tgz#6a96b5e31bcb98122a30863f7d92365c00603562"
d3-geo@1:
version "1.11.3"
resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-1.11.3.tgz#5bb08388f45e4b281491faa72d3abd43215dbd1c"
dependencies:
d3-array "1"
d3-hierarchy@1:
version "1.1.8"
resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-1.1.8.tgz#7a6317bd3ed24e324641b6f1e76e978836b008cc"
d3-interpolate@1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-1.3.2.tgz#417d3ebdeb4bc4efcc8fd4361c55e4040211fd68"
dependencies:
d3-color "1"
d3-path@1:
version "1.0.7"
resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.7.tgz#8de7cd693a75ac0b5480d3abaccd94793e58aae8"
d3-polygon@1:
version "1.0.5"
resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-1.0.5.tgz#9a645a0a64ff6cbf9efda96ee0b4a6909184c363"
d3-quadtree@1:
version "1.0.6"
resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-1.0.6.tgz#d1ab2a95a7f27bbde88582c94166f6ae35f32056"
d3-random@1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-1.1.2.tgz#2833be7c124360bf9e2d3fd4f33847cfe6cab291"
d3-scale-chromatic@1:
version "1.3.3"
resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-1.3.3.tgz#dad4366f0edcb288f490128979c3c793583ed3c0"
dependencies:
d3-color "1"
d3-interpolate "1"
d3-scale@2:
version "2.2.2"
resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-2.2.2.tgz#4e880e0b2745acaaddd3ede26a9e908a9e17b81f"
dependencies:
d3-array "^1.2.0"
d3-collection "1"
d3-format "1"
d3-interpolate "1"
d3-time "1"
d3-time-format "2"
d3-selection@1, d3-selection@^1.1.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-1.4.0.tgz#ab9ac1e664cf967ebf1b479cc07e28ce9908c474"
d3-shape@1:
version "1.3.4"
resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.3.4.tgz#358e76014645321eecc7c364e188f8ae3d2a07d4"
dependencies:
d3-path "1"
d3-time-format@2:
version "2.1.3"
resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-2.1.3.tgz#ae06f8e0126a9d60d6364eac5b1533ae1bac826b"
dependencies:
d3-time "1"
d3-time@1:
version "1.0.11"
resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.0.11.tgz#1d831a3e25cd189eb256c17770a666368762bbce"
d3-timer@1:
version "1.0.9"
resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-1.0.9.tgz#f7bb8c0d597d792ff7131e1c24a36dd471a471ba"
d3-transition@1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-1.2.0.tgz#f538c0e21b2aa1f05f3e965f8567e81284b3b2b8"
dependencies:
d3-color "1"
d3-dispatch "1"
d3-ease "1"
d3-interpolate "1"
d3-selection "^1.1.0"
d3-timer "1"
d3-voronoi@1:
version "1.1.4"
resolved "https://registry.yarnpkg.com/d3-voronoi/-/d3-voronoi-1.1.4.tgz#dd3c78d7653d2bb359284ae478645d95944c8297"
d3-zoom@1:
version "1.7.3"
resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-1.7.3.tgz#f444effdc9055c38077c4299b4df999eb1d47ccb"
dependencies:
d3-dispatch "1"
d3-drag "1"
d3-interpolate "1"
d3-selection "1"
d3-transition "1"
d3@^5.9.1:
version "5.9.1"
resolved "https://registry.yarnpkg.com/d3/-/d3-5.9.1.tgz#fde73fa9af7281d2ff0d2a32aa8f306e93a6d1cd"
dependencies:
d3-array "1"
d3-axis "1"
d3-brush "1"
d3-chord "1"
d3-collection "1"
d3-color "1"
d3-contour "1"
d3-dispatch "1"
d3-drag "1"
d3-dsv "1"
d3-ease "1"
d3-fetch "1"
d3-force "1"
d3-format "1"
d3-geo "1"
d3-hierarchy "1"
d3-interpolate "1"
d3-path "1"
d3-polygon "1"
d3-quadtree "1"
d3-random "1"
d3-scale "2"
d3-scale-chromatic "1"
d3-selection "1"
d3-shape "1"
d3-time "1"
d3-time-format "2"
d3-timer "1"
d3-transition "1"
d3-voronoi "1"
d3-zoom "1"
d@1:
version "1.0.0"
resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f"
......@@ -3843,15 +4059,15 @@ hyphenate-style-name@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz#31160a36930adaf1fc04c6074f7eb41465d4ec4b"
iconv-lite@0.4.23:
version "0.4.23"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63"
iconv-lite@0.4, iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
dependencies:
safer-buffer ">= 2.1.2 < 3"
iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
iconv-lite@0.4.23:
version "0.4.23"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63"
dependencies:
safer-buffer ">= 2.1.2 < 3"
......@@ -6822,6 +7038,10 @@ run-async@^2.2.0:
dependencies:
is-promise "^2.1.0"
rw@1:
version "1.3.3"