Enable multi-copy for edit
This commit is contained in:
parent
4a185b372e
commit
ce10a2adc4
@ -50,18 +50,52 @@ BuildingEdit.propTypes = {
|
|||||||
class EditForm extends Component {
|
class EditForm extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {}
|
this.state = {
|
||||||
|
error: this.props.error || undefined,
|
||||||
|
like: this.props.like || undefined,
|
||||||
|
copying: false,
|
||||||
|
keys_to_copy: {}
|
||||||
|
}
|
||||||
for (const field of props.fields) {
|
for (const field of props.fields) {
|
||||||
this.state[field.slug] = props[field.slug]
|
this.state[field.slug] = props[field.slug]
|
||||||
}
|
}
|
||||||
this.state.error = this.props.error || undefined;
|
|
||||||
this.state.like = this.props.like || undefined;
|
|
||||||
|
|
||||||
this.handleChange = this.handleChange.bind(this);
|
this.handleChange = this.handleChange.bind(this);
|
||||||
this.handleCheck = this.handleCheck.bind(this);
|
this.handleCheck = this.handleCheck.bind(this);
|
||||||
this.handleLike = this.handleLike.bind(this);
|
this.handleLike = this.handleLike.bind(this);
|
||||||
this.handleSubmit = this.handleSubmit.bind(this);
|
this.handleSubmit = this.handleSubmit.bind(this);
|
||||||
this.handleUpdate = this.handleUpdate.bind(this);
|
this.handleUpdate = this.handleUpdate.bind(this);
|
||||||
|
|
||||||
|
this.toggleCopying = this.toggleCopying.bind(this);
|
||||||
|
this.toggleCopyAttribute = this.toggleCopyAttribute.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enter or exit "copying" state - allow user to select attributes to copy
|
||||||
|
*/
|
||||||
|
toggleCopying() {
|
||||||
|
this.setState({
|
||||||
|
copying: !this.state.copying
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keep track of data to copy (accumulate while in "copying" state)
|
||||||
|
*
|
||||||
|
* Note that we track keys only - values are already held in state
|
||||||
|
*
|
||||||
|
* @param {string} key
|
||||||
|
*/
|
||||||
|
toggleCopyAttribute(key) {
|
||||||
|
const keys = this.state.keys_to_copy;
|
||||||
|
if(this.state.keys_to_copy[key]){
|
||||||
|
delete keys[key];
|
||||||
|
} else {
|
||||||
|
keys[key] = true;
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
keys_to_copy: keys
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -175,6 +209,12 @@ class EditForm extends Component {
|
|||||||
const cat = this.props.cat;
|
const cat = this.props.cat;
|
||||||
const buildingLike = this.props.building_like;
|
const buildingLike = this.props.building_like;
|
||||||
|
|
||||||
|
const values_to_copy = {}
|
||||||
|
for (const key of Object.keys(this.state.keys_to_copy)) {
|
||||||
|
values_to_copy[key] = this.state[key]
|
||||||
|
}
|
||||||
|
const data_string = JSON.stringify(values_to_copy);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={(this.props.inactive)? 'data-section inactive': 'data-section'}>
|
<section className={(this.props.inactive)? 'data-section inactive': 'data-section'}>
|
||||||
<header className={`section-header edit ${this.props.slug} ${(match? 'active' : '')}`}>
|
<header className={`section-header edit ${this.props.slug} ${(match? 'active' : '')}`}>
|
||||||
@ -187,14 +227,38 @@ class EditForm extends Component {
|
|||||||
</NavLink>
|
</NavLink>
|
||||||
<nav className="icon-buttons">
|
<nav className="icon-buttons">
|
||||||
{
|
{
|
||||||
this.props.help?
|
(match && !this.props.inactive && this.props.slug !== 'like')?
|
||||||
|
this.state.copying?
|
||||||
|
<Fragment>
|
||||||
|
<NavLink
|
||||||
|
to={`/multi-edit/${this.props.cat}.html?data=${data_string}`}
|
||||||
|
className="icon-button copy">
|
||||||
|
Copy selected
|
||||||
|
</NavLink>
|
||||||
|
<a className="icon-button copy" onClick={this.toggleCopying}>Cancel</a>
|
||||||
|
</Fragment>
|
||||||
|
:
|
||||||
|
<a className="icon-button copy" onClick={this.toggleCopying}>Copy</a>
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
{
|
||||||
|
(match && this.props.slug === 'like')?
|
||||||
|
<NavLink
|
||||||
|
to={`/multi-edit/${this.props.cat}.html`}
|
||||||
|
className="icon-button copy">
|
||||||
|
Copy
|
||||||
|
</NavLink>
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
{
|
||||||
|
this.props.help && !this.state.copying?
|
||||||
<a className="icon-button help" title="Find out more" href={this.props.help}>
|
<a className="icon-button help" title="Find out more" href={this.props.help}>
|
||||||
Info
|
Info
|
||||||
</a>
|
</a>
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
(match && !this.props.inactive && this.props.slug !== 'like')? // special-case for likes
|
(match && !this.state.copying && !this.props.inactive && this.props.slug !== 'like')? // special-case for likes
|
||||||
<NavLink className="icon-button save" title="Save Changes"
|
<NavLink className="icon-button save" title="Save Changes"
|
||||||
onClick={this.handleSubmit}
|
onClick={this.handleSubmit}
|
||||||
to={`/edit/${this.props.slug}/building/${this.props.building_id}.html`}>
|
to={`/edit/${this.props.slug}/building/${this.props.building_id}.html`}>
|
||||||
@ -221,24 +285,45 @@ class EditForm extends Component {
|
|||||||
switch (props.type) {
|
switch (props.type) {
|
||||||
case 'text':
|
case 'text':
|
||||||
return <TextInput {...props} handleChange={this.handleChange}
|
return <TextInput {...props} handleChange={this.handleChange}
|
||||||
|
copying={this.state.copying}
|
||||||
|
toggleCopyAttribute={this.toggleCopyAttribute}
|
||||||
|
copy={this.state.keys_to_copy[props.slug]}
|
||||||
value={this.state[props.slug]} key={props.slug} cat={cat} />
|
value={this.state[props.slug]} key={props.slug} cat={cat} />
|
||||||
case 'text_list':
|
case 'text_list':
|
||||||
return <TextListInput {...props} handleChange={this.handleChange}
|
return <TextListInput {...props} handleChange={this.handleChange}
|
||||||
|
copying={this.state.copying}
|
||||||
|
toggleCopyAttribute={this.toggleCopyAttribute}
|
||||||
|
copy={this.state.keys_to_copy[props.slug]}
|
||||||
value={this.state[props.slug]} key={props.slug} cat={cat} />
|
value={this.state[props.slug]} key={props.slug} cat={cat} />
|
||||||
case 'text_long':
|
case 'text_long':
|
||||||
return <LongTextInput {...props} handleChange={this.handleChange}
|
return <LongTextInput {...props} handleChange={this.handleChange}
|
||||||
|
copying={this.state.copying}
|
||||||
|
toggleCopyAttribute={this.toggleCopyAttribute}
|
||||||
|
copy={this.state.keys_to_copy[props.slug]}
|
||||||
value={this.state[props.slug]} key={props.slug} cat={cat} />
|
value={this.state[props.slug]} key={props.slug} cat={cat} />
|
||||||
case 'number':
|
case 'number':
|
||||||
return <NumberInput {...props} handleChange={this.handleChange}
|
return <NumberInput {...props} handleChange={this.handleChange}
|
||||||
|
copying={this.state.copying}
|
||||||
|
toggleCopyAttribute={this.toggleCopyAttribute}
|
||||||
|
copy={this.state.keys_to_copy[props.slug]}
|
||||||
value={this.state[props.slug]} key={props.slug} cat={cat} />
|
value={this.state[props.slug]} key={props.slug} cat={cat} />
|
||||||
case 'year_estimator':
|
case 'year_estimator':
|
||||||
return <YearEstimator {...props} handleChange={this.handleChange}
|
return <YearEstimator {...props} handleChange={this.handleChange}
|
||||||
|
copying={this.state.copying}
|
||||||
|
toggleCopyAttribute={this.toggleCopyAttribute}
|
||||||
|
copy={this.state.keys_to_copy[props.slug]}
|
||||||
value={this.state[props.slug]} key={props.slug} cat={cat} />
|
value={this.state[props.slug]} key={props.slug} cat={cat} />
|
||||||
case 'text_multi':
|
case 'text_multi':
|
||||||
return <MultiTextInput {...props} handleChange={this.handleUpdate}
|
return <MultiTextInput {...props} handleChange={this.handleUpdate}
|
||||||
|
copying={this.state.copying}
|
||||||
|
toggleCopyAttribute={this.toggleCopyAttribute}
|
||||||
|
copy={this.state.keys_to_copy[props.slug]}
|
||||||
value={this.state[props.slug]} key={props.slug} cat={cat} />
|
value={this.state[props.slug]} key={props.slug} cat={cat} />
|
||||||
case 'checkbox':
|
case 'checkbox':
|
||||||
return <CheckboxInput {...props} handleChange={this.handleCheck}
|
return <CheckboxInput {...props} handleChange={this.handleCheck}
|
||||||
|
copying={this.state.copying}
|
||||||
|
toggleCopyAttribute={this.toggleCopyAttribute}
|
||||||
|
copy={this.state.keys_to_copy[props.slug]}
|
||||||
value={this.state[props.slug]} key={props.slug} cat={cat} />
|
value={this.state[props.slug]} key={props.slug} cat={cat} />
|
||||||
case 'like':
|
case 'like':
|
||||||
return <LikeButton {...props} handleLike={this.handleLike}
|
return <LikeButton {...props} handleLike={this.handleLike}
|
||||||
@ -285,9 +370,11 @@ EditForm.propTypes = {
|
|||||||
const TextInput = (props) => (
|
const TextInput = (props) => (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Label slug={props.slug} title={props.title} tooltip={props.tooltip}
|
<Label slug={props.slug} title={props.title} tooltip={props.tooltip}
|
||||||
cat={props.cat} disabled={props.disabled}
|
copying={props.copying}
|
||||||
value={props.value || ''}
|
toggleCopyAttribute={props.toggleCopyAttribute}
|
||||||
/>
|
copy={props.copy}
|
||||||
|
cat={props.cat}
|
||||||
|
disabled={props.disabled} />
|
||||||
<input className="form-control" type="text"
|
<input className="form-control" type="text"
|
||||||
id={props.slug} name={props.slug}
|
id={props.slug} name={props.slug}
|
||||||
value={props.value || ''}
|
value={props.value || ''}
|
||||||
@ -314,6 +401,9 @@ TextInput.propTypes = {
|
|||||||
const LongTextInput = (props) => (
|
const LongTextInput = (props) => (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Label slug={props.slug} title={props.title} cat={props.cat}
|
<Label slug={props.slug} title={props.title} cat={props.cat}
|
||||||
|
copying={props.copying}
|
||||||
|
toggleCopyAttribute={props.toggleCopyAttribute}
|
||||||
|
copy={props.copy}
|
||||||
disabled={props.disabled} tooltip={props.tooltip} />
|
disabled={props.disabled} tooltip={props.tooltip} />
|
||||||
<textarea className="form-control"
|
<textarea className="form-control"
|
||||||
id={props.slug} name={props.slug}
|
id={props.slug} name={props.slug}
|
||||||
@ -375,7 +465,12 @@ class MultiTextInput extends Component {
|
|||||||
const values = this.getValues();
|
const values = this.getValues();
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Label slug={this.props.slug} title={this.props.title} tooltip={this.props.tooltip} />
|
<Label slug={this.props.slug} title={this.props.title} tooltip={this.props.tooltip}
|
||||||
|
cat={this.props.cat}
|
||||||
|
copying={this.props.copying}
|
||||||
|
disabled={this.props.disabled}
|
||||||
|
toggleCopyAttribute={this.props.toggleCopyAttribute}
|
||||||
|
copy={this.props.copy} />
|
||||||
{
|
{
|
||||||
values.map((item, i) => (
|
values.map((item, i) => (
|
||||||
<div className="input-group" key={i}>
|
<div className="input-group" key={i}>
|
||||||
@ -409,15 +504,19 @@ MultiTextInput.propTypes = {
|
|||||||
value: PropTypes.arrayOf(PropTypes.string),
|
value: PropTypes.arrayOf(PropTypes.string),
|
||||||
placeholder: PropTypes.string,
|
placeholder: PropTypes.string,
|
||||||
disabled: PropTypes.bool,
|
disabled: PropTypes.bool,
|
||||||
handleChange: PropTypes.func
|
handleChange: PropTypes.func,
|
||||||
|
copy: PropTypes.bool,
|
||||||
|
toggleCopyAttribute: PropTypes.func,
|
||||||
|
copying: PropTypes.bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const TextListInput = (props) => (
|
const TextListInput = (props) => (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Label slug={props.slug} title={props.title} tooltip={props.tooltip}
|
<Label slug={props.slug} title={props.title} tooltip={props.tooltip}
|
||||||
cat={props.cat} disabled={props.disabled}
|
cat={props.cat} disabled={props.disabled}
|
||||||
value={props.value || ''}
|
copying={props.copying}
|
||||||
/>
|
toggleCopyAttribute={props.toggleCopyAttribute}
|
||||||
|
copy={props.copy} />
|
||||||
<select className="form-control"
|
<select className="form-control"
|
||||||
id={props.slug} name={props.slug}
|
id={props.slug} name={props.slug}
|
||||||
value={props.value || ''}
|
value={props.value || ''}
|
||||||
@ -449,8 +548,9 @@ const NumberInput = (props) => (
|
|||||||
<Fragment>
|
<Fragment>
|
||||||
<Label slug={props.slug} title={props.title} tooltip={props.tooltip}
|
<Label slug={props.slug} title={props.title} tooltip={props.tooltip}
|
||||||
cat={props.cat} disabled={props.disabled}
|
cat={props.cat} disabled={props.disabled}
|
||||||
value={props.value || ''}
|
copying={props.copying}
|
||||||
/>
|
toggleCopyAttribute={props.toggleCopyAttribute}
|
||||||
|
copy={props.copy} />
|
||||||
<input className="form-control" type="number" step={props.step}
|
<input className="form-control" type="number" step={props.step}
|
||||||
id={props.slug} name={props.slug}
|
id={props.slug} name={props.slug}
|
||||||
value={props.value || ''}
|
value={props.value || ''}
|
||||||
@ -488,6 +588,7 @@ class YearEstimator extends Component {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<NumberInput {...this.props} handleChange={this.props.handleChange}
|
<NumberInput {...this.props} handleChange={this.props.handleChange}
|
||||||
|
|
||||||
value={this.props.value} key={this.props.slug} />
|
value={this.props.value} key={this.props.slug} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -502,22 +603,32 @@ YearEstimator.propTypes = {
|
|||||||
date_lower: PropTypes.number,
|
date_lower: PropTypes.number,
|
||||||
value: PropTypes.number,
|
value: PropTypes.number,
|
||||||
disabled: PropTypes.bool,
|
disabled: PropTypes.bool,
|
||||||
handleChange: PropTypes.func
|
handleChange: PropTypes.func,
|
||||||
|
copy: PropTypes.bool,
|
||||||
|
toggleCopyAttribute: PropTypes.func,
|
||||||
|
copying: PropTypes.bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const CheckboxInput = (props) => (
|
const CheckboxInput = (props) => (
|
||||||
<div className="form-check">
|
<Fragment>
|
||||||
<input className="form-check-input" type="checkbox"
|
<Label slug={props.slug} title={props.title} tooltip={props.tooltip}
|
||||||
id={props.slug} name={props.slug}
|
cat={props.cat} disabled={props.disabled}
|
||||||
checked={!!props.value}
|
copying={props.copying}
|
||||||
disabled={props.disabled}
|
toggleCopyAttribute={props.toggleCopyAttribute}
|
||||||
onChange={props.handleChange}
|
copy={props.copy} />
|
||||||
/>
|
<div className="form-check">
|
||||||
<label htmlFor={props.slug} className="form-check-label">
|
<input className="form-check-input" type="checkbox"
|
||||||
{props.title}
|
id={props.slug} name={props.slug}
|
||||||
{ props.tooltip? <Tooltip text={ props.tooltip } /> : null }
|
checked={!!props.value}
|
||||||
</label>
|
disabled={props.disabled}
|
||||||
</div>
|
onChange={props.handleChange}
|
||||||
|
/>
|
||||||
|
<label htmlFor={props.slug} className="form-check-label">
|
||||||
|
{props.title}
|
||||||
|
{ props.tooltip? <Tooltip text={ props.tooltip } /> : null }
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</Fragment>
|
||||||
)
|
)
|
||||||
|
|
||||||
CheckboxInput.propTypes = {
|
CheckboxInput.propTypes = {
|
||||||
@ -546,7 +657,7 @@ const LikeButton = (props) => (
|
|||||||
</div>
|
</div>
|
||||||
<p>
|
<p>
|
||||||
<NavLink
|
<NavLink
|
||||||
to={`/multi-edit/${props.cat}.html?k=like&v=${true}`}>
|
to={`/multi-edit/${props.cat}.html`}>
|
||||||
Like more buildings
|
Like more buildings
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</p>
|
</p>
|
||||||
@ -565,22 +676,19 @@ LikeButton.propTypes = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Label = (props) => {
|
const Label = (props) => {
|
||||||
const data = {};
|
|
||||||
data[props.slug] = props.value;
|
|
||||||
const data_string = JSON.stringify(data);
|
|
||||||
return (
|
return (
|
||||||
<label htmlFor={props.slug}>
|
<label htmlFor={props.slug}>
|
||||||
{props.title}
|
{props.title}
|
||||||
{ props.tooltip? <Tooltip text={ props.tooltip } /> : null }
|
{ (props.copying && props.cat && props.slug && !props.disabled)?
|
||||||
{ (props.cat && props.slug && !props.disabled)?
|
|
||||||
<div className="icon-buttons">
|
<div className="icon-buttons">
|
||||||
<NavLink
|
<label className="icon-button copy">
|
||||||
to={`/multi-edit/${props.cat}.html?data=${data_string}`}
|
|
||||||
className="icon-button copy">
|
|
||||||
Copy
|
Copy
|
||||||
</NavLink>
|
<input type="checkbox" checked={props.copy}
|
||||||
|
onChange={() => props.toggleCopyAttribute(props.slug)}/>
|
||||||
|
</label>
|
||||||
</div> : null
|
</div> : null
|
||||||
}
|
}
|
||||||
|
{ props.tooltip? <Tooltip text={ props.tooltip } /> : null }
|
||||||
</label>
|
</label>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -588,7 +696,6 @@ const Label = (props) => {
|
|||||||
Label.propTypes = {
|
Label.propTypes = {
|
||||||
slug: PropTypes.string,
|
slug: PropTypes.string,
|
||||||
cat: PropTypes.string,
|
cat: PropTypes.string,
|
||||||
value: PropTypes.any,
|
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
disabled: PropTypes.bool,
|
disabled: PropTypes.bool,
|
||||||
tooltip: PropTypes.string
|
tooltip: PropTypes.string
|
||||||
|
@ -296,6 +296,9 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
.data-section label .icon-buttons .icon-button.copy {
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
.icon-button.copy:hover,
|
.icon-button.copy:hover,
|
||||||
.icon-button.help:hover {
|
.icon-button.help:hover {
|
||||||
color: rgb(0, 81, 255)
|
color: rgb(0, 81, 255)
|
||||||
|
Loading…
Reference in New Issue
Block a user