Skip to content

Commit

Permalink
Merge pull request #187 from pacificclimate/i85-robust-config
Browse files Browse the repository at this point in the history
Make use of config data more robust
  • Loading branch information
rod-glover authored Jun 25, 2020
2 parents 9844d33 + c49bca6 commit 9b261fc
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 44 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"start-env": "REACT_APP_VERSION=\"$(./generate-commitish.sh)\" react-scripts start",
"build": "react-scripts build",
"build-serve": "react-scripts build && serve -s build -l 3001",
"build-update": "cp ./public/external-text/default.yaml ./build/external-text/default.yaml",
"test": "react-scripts test",
"eject": "react-scripts eject",
"reinstall": "rm -rf ./node_modules; npm install"
Expand Down
59 changes: 33 additions & 26 deletions src/components/app-root/App/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export default class App extends Component {
futureTimePeriodOpt: undefined,
seasonOpt: undefined,
variableOpt: undefined,
tabKey: 'graphs',
tabKey: 'summary',
context: null,
contextJustUpdated: null, // null signals initial state; boolean thereafter
};
Expand Down Expand Up @@ -134,12 +134,11 @@ export default class App extends Component {
// since extraction means introducing extra machinery for state-setting
// callbacks, etc.

const texts = this.context;
if (!texts || this.state.metadata === null) {
console.log('### Loading ...')
if (!this.context || this.state.metadata === null) {
console.log('### App: Loading ...')
return <Loader/>;
}
console.log('### Loaded')
console.log('### App: Loaded')
const variableConfig = this.getConfig('variables');

const getVariableOptionLabel =
Expand All @@ -165,11 +164,13 @@ export default class App extends Component {
<T path='selectors.region.prefix'/>
</Col>
<Col xl={12} lg={3} md={6}>
<RegionSelector
default={T.get(texts, 'selectors.region.default', {}, 'raw')}
value={this.state.regionOpt}
onChange={this.handleChangeRegion}
/>
<ErrorBoundary>
<RegionSelector
default={this.getConfig('selectors.region.default')}
value={this.state.regionOpt}
onChange={this.handleChangeRegion}
/>
</ErrorBoundary>
</Col>
</React.Fragment>
}
Expand All @@ -180,13 +181,15 @@ export default class App extends Component {
<T path='selectors.timePeriod.prefix'/>
</Col>
<Col xl={12} lg={3} md={4}>
<TimePeriodSelector
bases={filter(m => +m.start_date >= 2010)(this.state.metadata)}
value={this.state.futureTimePeriodOpt}
default={T.get(texts, 'selectors.timePeriod.default', {}, 'raw')}
onChange={this.handleChangeTimePeriod}
debug
/>
<ErrorBoundary>
<TimePeriodSelector
bases={filter(m => +m.start_date >= 2010)(this.state.metadata)}
value={this.state.futureTimePeriodOpt}
default={this.getConfig('selectors.timePeriod.default')}
onChange={this.handleChangeTimePeriod}
debug
/>
</ErrorBoundary>
</Col>
</React.Fragment>
}
Expand All @@ -197,13 +200,15 @@ export default class App extends Component {
<T path='selectors.variable.prefix'/>
</Col>
<Col xl={12} lg={3} md={4}>
<VariableSelector
bases={this.state.metadata}
value={this.state.variableOpt}
default={this.getConfig('selectors.variable.default')}
onChange={this.handleChangeVariable}
getOptionLabel={getVariableOptionLabel}
/>
<ErrorBoundary>
<VariableSelector
bases={this.state.metadata}
value={this.state.variableOpt}
default={this.getConfig('selectors.variable.default')}
onChange={this.handleChangeVariable}
getOptionLabel={getVariableOptionLabel}
/>
</ErrorBoundary>
</Col>
</React.Fragment>
}
Expand All @@ -214,11 +219,13 @@ export default class App extends Component {
<T path='selectors.season.prefix'/>
</Col>
<Col xl={12} lg={3} md={4}>
<SeasonSelector
<ErrorBoundary>
<SeasonSelector
value={this.state.seasonOpt}
default={this.getConfig('selectors.season.default')}
onChange={this.handleChangeSeason}
/>
/>
</ErrorBoundary>
</Col>
<Col xl={12} lg={'auto'} md={'auto'} className='pr-0'>
<T path='selectors.season.postfix'/>
Expand Down
7 changes: 5 additions & 2 deletions src/components/app-root/GraphsTabBody.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col';
import get from 'lodash/fp/get';
import ChangeOverTimeGraph from '../graphs/ChangeOverTimeGraph';
import { getVariableInfo } from '../../utils/variables-and-units';
import {
getVariableDisplay,
getVariableInfo
} from '../../utils/variables-and-units';

export default class GraphsTabBody extends React.Component {
static contextType = T.contextType;
Expand Down Expand Up @@ -48,7 +51,7 @@ export default class GraphsTabBody extends React.Component {
const graphConfig = this.getConfig('graphs.config');
const variableConfig = this.getConfig('variables');
const variableId = variable.representative.variable_id;
const display = graphConfig.variables[variableId].display;
const display = getVariableDisplay(graphConfig.variables, variableId);
const variableInfo = getVariableInfo(variableConfig, variableId, display);

return (
Expand Down
2 changes: 1 addition & 1 deletion src/components/app-root/MapsTabBody/MapsTabBody.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export default class MapsTabBody extends React.Component {
handleChangePopup = this.handleChangeSelection.bind(this, 'popup');

zoomToRegion = () =>
this.setState({ bounds: regionBounds(this.props.region)});
this.setState({ bounds: regionBounds(this.props.regionOpt.value) });

render() {
if (!allDefined(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ import {
getDisplayData,
seasonIndexToPeriod
} from '../../../utils/percentile-anomaly';
import { getConvertUnits } from '../../../utils/variables-and-units';
import {
getConvertUnits,
getVariableDisplay
} from '../../../utils/variables-and-units';
import './ChangeOverTimeGraph.css';
import BarChart from '../BarChart';
import { allDefined } from '../../../utils/lodash-fp-extras';
Expand Down Expand Up @@ -180,7 +183,7 @@ class ChangeOverTimeGraphDisplay extends React.Component {


const convertToDisplayData = curry((graphConfig, variableId, season, data) => {
const display = graphConfig.variables[variableId].display;
const display = getVariableDisplay(graphConfig.variables, variableId);
return getDisplayData(data, seasonIndexToPeriod(season), display);
});

Expand Down
4 changes: 2 additions & 2 deletions src/components/maps/ClimateLayer/ClimateLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
wmsTime
} from '../map-utils';
import {
getConvertUnits,
getConvertUnits, getVariableDataUnits,
getVariableDisplayUnits
} from '../../../utils/variables-and-units';

Expand Down Expand Up @@ -44,7 +44,7 @@ export default class ClimateLayer extends React.Component {
const displayUnits =
getVariableDisplayUnits(variableConfig, variableId, 'absolute');
// TODO: dataUnits should come from metadata, not config.
const dataUnits = variableConfig[variableId].dataUnits;
const dataUnits = getVariableDataUnits(variableConfig, variableId);
const convertUnits =
getConvertUnits(unitsConversions, variableConfig, variableId);
const rangeInDataUnits = mapValues(
Expand Down
2 changes: 1 addition & 1 deletion src/components/misc/ErrorBoundary/ErrorBoundary.module.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.errorBoundary {
width: 60em;
max-width: 60em;
margin: 2em auto;
padding: 2em;
border: 1px solid darkred;
Expand Down
8 changes: 7 additions & 1 deletion src/temporary/external-text.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,13 @@ export function get(
// </div>
// ```

const item = (texts && _.has(texts, path)) ? _.get(texts, path) : placeholder;
const hasPath = texts && _.has(texts, path);

if (!hasPath && _.includes(['raw', 'string'], as)) {
throw new Error(`Path '${path}' not found in texts.`);
}

const item = hasPath ? _.get(texts, path) : placeholder;

const render = value => {
try {
Expand Down
52 changes: 43 additions & 9 deletions src/utils/variables-and-units.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,42 @@ import isUndefined from 'lodash/fp/isUndefined';
// Functions that encapsulate knowledge about the structure of variable
// configuration information.

export const getVariableLabel = (variableConfig, variable) =>
`${variableConfig[variable].label}${variableConfig[variable].derived ? '*' : ''}`;
const getConfigForId = (variableConfig, variableId) => {
const vc = variableConfig[variableId];
if (!vc) {
throw new Error(`Unconfigured variable '${variableId}'`);
}
return vc;
};

export const getVariableLabel = (variableConfig, variableId) => {
const vc = getConfigForId(variableConfig, variableId);
return `${vc.label}${vc.derived ? '*' : ''}`;
};


export const getVariableType = (variableConfig, variableId) => {
return getConfigForId(variableConfig, variableId).type;
};


export const getVariableDisplay = (variableConfig, variableId) => {
return getConfigForId(variableConfig, variableId).display;
};


export const getVariableType = (variableConfig, variable) =>
variableConfig[variable].type;
export const getVariableDataUnits = (variableConfig, variableId) => {
return getConfigForId(variableConfig, variableId).dataUnits;
};


export const getVariableDisplayUnits =
(variableConfig, variable, display = 'absolute') => {
(variableConfig, variableId, display = 'absolute') => {
const vc = getConfigForId(variableConfig, variableId);
if (display === 'relative') {
return '%';
}
return variableConfig[variable].displayUnits;
return vc.displayUnits;
};


Expand All @@ -39,9 +61,15 @@ export const getVariableInfo = (variableConfig, variableId, display) => {
};


export const getConvertUnits= (conversions, variableConfig, variable) => {
const variableType = getVariableType(variableConfig, variable);
export const getConvertUnits= (conversions, variableConfig, variableId) => {
const variableType = getVariableType(variableConfig, variableId);
if (!variableType) {
throw new Error(`Unspecified variable type for ${variableId}`);
}
const conversionGroup = conversions[variableType];
if (!conversionGroup) {
throw new Error(`No conversion group for ${variableType}`);
}
return convertUnitsInGroup(conversionGroup);
};

Expand Down Expand Up @@ -100,16 +128,22 @@ export const fromBaseUnits = curry((conversion, value) =>

export const convertUnitsInGroup = curry((conversionGroup, fromUnits, toUnits, value) => {
if (!conversionGroup) {
return undefined; // Or `value`?
throw new Error('Undefined conversion group');
}
if (fromUnits === toUnits) { // Identity
return value;
}
const fromConversion = conversionGroup[fromUnits];
if (!fromConversion) {
throw new Error(`No conversion group specified for ${fromUnits}`);
}
if (isString(fromConversion)) { // Synonym
return convertUnitsInGroup(conversionGroup, fromConversion, toUnits, value);
}
const toConversion = conversionGroup[toUnits];
if (!toConversion) {
throw new Error(`No conversion group specified for ${toUnits}`);
}
if (isString(toConversion)) { // Synonym
return convertUnitsInGroup(conversionGroup, fromUnits, toConversion, value);
}
Expand Down

0 comments on commit 9b261fc

Please sign in to comment.