Merge pull request #521 from mz8i/feature/517-prevent-copy-empty
Feature 517: prevent copying empty values
This commit is contained in:
commit
56b1aafb98
@ -14,7 +14,7 @@ const CheckboxDataEntry: React.FunctionComponent<CheckboxDataEntryProps> = (prop
|
||||
slug={props.slug}
|
||||
title={props.title}
|
||||
tooltip={props.tooltip}
|
||||
disabled={props.disabled}
|
||||
disabled={props.disabled || props.value == undefined}
|
||||
copy={props.copy}
|
||||
/>
|
||||
<div className="form-check">
|
||||
|
@ -28,7 +28,7 @@ const DataEntry: React.FunctionComponent<DataEntryProps> = (props) => {
|
||||
slug={props.slug}
|
||||
title={props.title}
|
||||
tooltip={props.tooltip}
|
||||
disabled={props.disabled}
|
||||
disabled={props.disabled || props.value == undefined || props.value == ''}
|
||||
copy={props.copy}
|
||||
/>
|
||||
<input className="form-control" type="text"
|
||||
|
@ -57,7 +57,7 @@ class MultiDataEntry extends Component<MultiDataEntryProps> {
|
||||
slug={props.slug}
|
||||
title={props.title}
|
||||
tooltip={props.tooltip}
|
||||
disabled={props.disabled}
|
||||
disabled={props.disabled || props.value == undefined || props.value.length === 0}
|
||||
/>
|
||||
{
|
||||
(props.mode === 'view')?
|
||||
|
@ -19,7 +19,7 @@ const NumericDataEntry: React.FunctionComponent<NumericDataEntryProps> = (props)
|
||||
slug={props.slug}
|
||||
title={props.title}
|
||||
tooltip={props.tooltip}
|
||||
disabled={props.disabled}
|
||||
disabled={props.disabled || props.value == undefined}
|
||||
copy={props.copy}
|
||||
/>
|
||||
<input
|
||||
|
@ -17,7 +17,7 @@ const SelectDataEntry: React.FunctionComponent<SelectDataEntryProps> = (props) =
|
||||
slug={props.slug}
|
||||
title={props.title}
|
||||
tooltip={props.tooltip}
|
||||
disabled={props.disabled}
|
||||
disabled={props.disabled || props.value == undefined}
|
||||
copy={props.copy}
|
||||
/>
|
||||
<select className="form-control"
|
||||
|
@ -16,7 +16,7 @@ const TextboxDataEntry: React.FunctionComponent<TextboxDataEntryProps> = (props)
|
||||
slug={props.slug}
|
||||
title={props.title}
|
||||
tooltip={props.tooltip}
|
||||
disabled={props.disabled}
|
||||
disabled={props.disabled || props.value == undefined}
|
||||
copy={props.copy}
|
||||
/>
|
||||
<textarea
|
||||
|
@ -2,6 +2,8 @@ import { parse } from 'query-string';
|
||||
import React from 'react';
|
||||
import { Link, Redirect, RouteComponentProps } from 'react-router-dom';
|
||||
|
||||
import { parseJsonOrDefault } from '../../helpers';
|
||||
import ErrorBox from '../components/error-box';
|
||||
import { BackIcon } from '../components/icons';
|
||||
import InfoBox from '../components/info-box';
|
||||
import { dataFields } from '../data_fields';
|
||||
@ -10,25 +12,22 @@ import { User } from '../models/user';
|
||||
import DataEntry from './data-components/data-entry';
|
||||
import Sidebar from './sidebar';
|
||||
|
||||
interface MultiEditRouteParams {
|
||||
cat: string;
|
||||
}
|
||||
|
||||
interface MultiEditProps extends RouteComponentProps<MultiEditRouteParams> {
|
||||
interface MultiEditProps {
|
||||
user?: User;
|
||||
category: string;
|
||||
dataString: string;
|
||||
}
|
||||
|
||||
const MultiEdit: React.FC<MultiEditProps> = (props) => {
|
||||
if (!props.user){
|
||||
return <Redirect to="/sign-up.html" />;
|
||||
}
|
||||
const cat = props.match.params.cat;
|
||||
if (cat === 'like') {
|
||||
if (props.category === 'like') {
|
||||
// special case for likes
|
||||
return (
|
||||
<Sidebar>
|
||||
<section className='data-section'>
|
||||
<header className={`section-header view ${cat} background-${cat}`}>
|
||||
<header className={`section-header view ${props.category} background-${props.category}`}>
|
||||
<h2 className="h2">Like me!</h2>
|
||||
</header>
|
||||
<form className='buttons-container'>
|
||||
@ -42,34 +41,34 @@ const MultiEdit: React.FC<MultiEditProps> = (props) => {
|
||||
);
|
||||
}
|
||||
|
||||
const q = parse(props.location.search);
|
||||
let data = parseJsonOrDefault(props.dataString);
|
||||
|
||||
let data: object;
|
||||
if (cat === 'like'){
|
||||
data = { like: true };
|
||||
} else {
|
||||
try {
|
||||
// TODO: verify what happens if data is string[]
|
||||
data = JSON.parse(q.data as string);
|
||||
} catch (error) {
|
||||
console.error(error, q);
|
||||
data = {};
|
||||
}
|
||||
let error: string;
|
||||
if(data == null) {
|
||||
error = 'Invalid parameters supplied';
|
||||
data = {};
|
||||
} else if(Object.values(data).some(x => x == undefined)) {
|
||||
error = 'Cannot copy empty values';
|
||||
data = {};
|
||||
}
|
||||
|
||||
return (
|
||||
<Sidebar>
|
||||
<section className='data-section'>
|
||||
<header className={`section-header view ${cat} background-${cat}`}>
|
||||
<header className={`section-header view ${props.category} background-${props.category}`}>
|
||||
<Link
|
||||
className="icon-button back"
|
||||
to={`/edit/${cat}`}>
|
||||
to={`/edit/${props.category}`}>
|
||||
<BackIcon />
|
||||
</Link>
|
||||
<h2 className="h2">Copy {cat} data</h2>
|
||||
<h2 className="h2">Copy {props.category} data</h2>
|
||||
</header>
|
||||
<form>
|
||||
<InfoBox msg='Click buildings one at a time to colour using the data below' />
|
||||
{
|
||||
error ?
|
||||
<ErrorBox msg={error} /> :
|
||||
<InfoBox msg='Click buildings one at a time to colour using the data below' />
|
||||
}
|
||||
{
|
||||
Object.keys(data).map((key => {
|
||||
const info = dataFields[key] || {};
|
||||
@ -85,8 +84,8 @@ const MultiEdit: React.FC<MultiEditProps> = (props) => {
|
||||
}
|
||||
</form>
|
||||
<form className='buttons-container'>
|
||||
<Link to={`/view/${cat}`} className='btn btn-secondary'>Back to view</Link>
|
||||
<Link to={`/edit/${cat}`} className='btn btn-secondary'>Back to edit</Link>
|
||||
<Link to={`/view/${props.category}`} className='btn btn-secondary'>Back to view</Link>
|
||||
<Link to={`/edit/${props.category}`} className='btn btn-secondary'>Back to edit</Link>
|
||||
</form>
|
||||
</section>
|
||||
</Sidebar>
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { parse } from 'query-string';
|
||||
import { parse as parseQuery } from 'query-string';
|
||||
import React, { Fragment } from 'react';
|
||||
import { Redirect, Route, RouteComponentProps, Switch } from 'react-router-dom';
|
||||
|
||||
import { parseJsonOrDefault } from '../helpers';
|
||||
import { strictParseInt } from '../parse';
|
||||
|
||||
import BuildingView from './building/building-view';
|
||||
@ -130,6 +131,13 @@ class MapApp extends React.Component<MapAppProps, MapAppState> {
|
||||
return category;
|
||||
}
|
||||
|
||||
getMultiEditDataString(): string {
|
||||
const q = parseQuery(this.props.location.search);
|
||||
if(Array.isArray(q.data)) {
|
||||
throw new Error('Invalid format');
|
||||
} else return q.data;
|
||||
}
|
||||
|
||||
increaseRevision(revisionId) {
|
||||
revisionId = +revisionId;
|
||||
// bump revision id, only ever increasing
|
||||
@ -199,21 +207,19 @@ class MapApp extends React.Component<MapAppProps, MapAppState> {
|
||||
*
|
||||
* Pulls data from URL to form update
|
||||
*
|
||||
* @param {object} building
|
||||
* @param {Building} building
|
||||
*/
|
||||
colourBuilding(building) {
|
||||
colourBuilding(building: Building) {
|
||||
const cat = this.props.match.params.category;
|
||||
const q = parse(window.location.search);
|
||||
|
||||
|
||||
if (cat === 'like') {
|
||||
this.likeBuilding(building.building_id);
|
||||
} else {
|
||||
try {
|
||||
// TODO: verify what happens if data is string[]
|
||||
const data = JSON.parse(q.data as string);
|
||||
const data = parseJsonOrDefault(this.getMultiEditDataString());
|
||||
|
||||
|
||||
if (data != undefined && !Object.values(data).some(x => x == undefined)) {
|
||||
this.updateBuilding(building.building_id, data);
|
||||
} catch (error) {
|
||||
console.error(error, q);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -281,7 +287,8 @@ class MapApp extends React.Component<MapAppProps, MapAppState> {
|
||||
</Route>
|
||||
<Route exact path="/multi-edit/:cat" render={(props) => (
|
||||
<MultiEdit
|
||||
{...props}
|
||||
category={category}
|
||||
dataString={this.getMultiEditDataString()}
|
||||
user={this.props.user}
|
||||
/>
|
||||
)} />
|
||||
|
@ -13,3 +13,13 @@ export function dateReviver(name, value) {
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
export function parseJsonOrDefault(jsonString: string) {
|
||||
try {
|
||||
return JSON.parse(jsonString);
|
||||
} catch(error) {
|
||||
console.error(error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user