Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 5a981d6

Browse files
committedJun 16, 2021
fix(NormalizeField): Adjust for changes from backend.
1 parent 93c1062 commit 5a981d6

File tree

3 files changed

+73
-19
lines changed

3 files changed

+73
-19
lines changed
 

‎lib/manager/components/transform/NormalizeField.js

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// @flow
22

33
import Icon from '@conveyal/woonerf/components/icon'
4+
import { isEqual } from 'lodash'
45
import React, { Component } from 'react'
56
import {
67
Button,
@@ -24,15 +25,44 @@ import type {
2425
} from '../../../types'
2526

2627
type State = {
27-
activeEditingIndex: number
28+
activeEditingIndex: number,
29+
// Holds the contents that should be shown in the SubstitutionRow component.
30+
activeSubstitution: ?Substitution,
31+
// Last edited contents.
32+
previousEditingIndex: number,
33+
previousSubstitution: ?Substitution
34+
}
35+
36+
/**
37+
* Determines whether two substitutions are equal (except for the valid field).
38+
*/
39+
function areEqual (sub1: ?Substitution, sub2: ?Substitution): boolean {
40+
if (!sub1 || !sub2) return false
41+
return isEqual(
42+
{
43+
description: sub1.description,
44+
normalizeSpace: sub1.normalizeSpace,
45+
pattern: sub1.pattern,
46+
replacement: sub1.replacement
47+
},
48+
{
49+
description: sub2.description,
50+
normalizeSpace: sub2.normalizeSpace,
51+
pattern: sub2.pattern,
52+
replacement: sub2.replacement
53+
}
54+
)
2855
}
2956

3057
/**
3158
* Component that renders input fields for the NormalizeFieldTransformation.
3259
*/
3360
export default class NormalizeField extends Component<TransformProps<NormalizeFieldFields>, State> {
3461
state = {
35-
activeEditingIndex: -1
62+
activeEditingIndex: -1,
63+
activeSubstitution: null,
64+
previousEditingIndex: -1,
65+
previousSubstitution: null
3666
}
3767

3868
componentDidMount () {
@@ -42,6 +72,21 @@ export default class NormalizeField extends Component<TransformProps<NormalizeFi
4272
componentDidUpdate (prevProps: TransformProps<NormalizeFieldFields>) {
4373
if (prevProps.transformation !== this.props.transformation) {
4474
this._updateErrors()
75+
76+
// If user entered an invalid substitution pattern and clicks save,
77+
// it will be rejected and the values entered will be lost.
78+
// To avoid that, keep the new row visible and in editing state.
79+
const { previousEditingIndex, previousSubstitution: editedSubstitution } = this.state
80+
const loadedSubstitution = this.props.transformation.substitutions[previousEditingIndex]
81+
if (previousEditingIndex !== -1 && !areEqual(editedSubstitution, loadedSubstitution)) {
82+
this.setState({
83+
activeEditingIndex: previousEditingIndex,
84+
activeSubstitution: {
85+
...editedSubstitution,
86+
valid: false
87+
}
88+
})
89+
}
4590
}
4691
}
4792

@@ -60,12 +105,17 @@ export default class NormalizeField extends Component<TransformProps<NormalizeFi
60105
_onChangeSubstitution = (substitution: Substitution, index: number) => {
61106
const newSubstitutions = [].concat(this.props.transformation.substitutions)
62107
newSubstitutions[index] = substitution
108+
this.setState({
109+
activeSubstitution: null,
110+
previousSubstitution: substitution
111+
})
63112
this._updateTransformation({substitutions: newSubstitutions})
64113
}
65114

66115
_onRemoveSubstitution = (index: number) => {
67116
const newSubstitutions = [].concat(this.props.transformation.substitutions)
68117
newSubstitutions.splice(index, 1)
118+
this.setState({ previousEditingIndex: -1 })
69119
this._updateTransformation({substitutions: newSubstitutions})
70120
}
71121

@@ -101,7 +151,11 @@ export default class NormalizeField extends Component<TransformProps<NormalizeFi
101151
}
102152

103153
_onEndEditSubstitution = () => {
104-
this.setState({ activeEditingIndex: -1 })
154+
this.setState({
155+
activeEditingIndex: -1,
156+
activeSubstitution: null,
157+
previousEditingIndex: this.state.activeEditingIndex
158+
})
105159
}
106160

107161
/**
@@ -129,7 +183,7 @@ export default class NormalizeField extends Component<TransformProps<NormalizeFi
129183

130184
render () {
131185
const { index, transformation } = this.props
132-
const { activeEditingIndex } = this.state
186+
const { activeEditingIndex, activeSubstitution } = this.state
133187
const {
134188
capitalizationExceptions,
135189
capitalize,
@@ -233,7 +287,7 @@ export default class NormalizeField extends Component<TransformProps<NormalizeFi
233287
onChange={this._onChangeSubstitution}
234288
onEndEdit={this._onEndEditSubstitution}
235289
onRemove={this._onRemoveSubstitution}
236-
substitution={s}
290+
substitution={activeEditingIndex === i ? (activeSubstitution || s) : s}
237291
/>
238292
))}
239293
{activeEditingIndex === substitutions.length &&
@@ -244,10 +298,10 @@ export default class NormalizeField extends Component<TransformProps<NormalizeFi
244298
key={activeEditingIndex}
245299
onChange={this._onChangeSubstitution}
246300
onEndEdit={this._onEndEditSubstitution}
247-
substitution={{
248-
invalid: false,
301+
substitution={activeSubstitution || {
249302
pattern: '',
250-
replacement: ''
303+
replacement: '',
304+
valid: true
251305
}}
252306
/>
253307
}

‎lib/manager/components/transform/SubstitutionRow.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ const buttonGroupStyle = { width: '60px' }
2929
* Extract just the subset of fields to build the state variable.
3030
*/
3131
function extractStateFields (props: Props): Substitution {
32-
const { description, invalid, normalizeSpace, pattern, replacement } = props.substitution
32+
const { description, normalizeSpace, pattern, replacement, valid } = props.substitution
3333
return {
3434
description: description || '',
35-
invalid,
36-
normalizeSpace,
35+
normalizeSpace: normalizeSpace || false,
3736
pattern,
38-
replacement
37+
replacement,
38+
valid
3939
}
4040
}
4141

@@ -50,7 +50,7 @@ export function isSubstitutionBlank (substitution: Substitution) {
5050
* @returns true if the given substitution is marked invalid by the backend, false otherwise.
5151
*/
5252
export function isSubstitutionInvalid (substitution: Substitution) {
53-
return substitution.invalid
53+
return !substitution.valid
5454
}
5555

5656
/**
@@ -66,7 +66,7 @@ export default class SubstitutionRow extends Component<Props, Substitution> {
6666
const { index, substitution } = this.props
6767

6868
// If a new substition is associated with this component, reset its state.
69-
if (prevProps.index !== index || !isEqual(prevProps.substitution, substitution)) {
69+
if (prevProps.index !== index || prevProps.substitution !== substitution) {
7070
this.setState(extractStateFields(this.props))
7171
}
7272
}
@@ -146,12 +146,12 @@ export default class SubstitutionRow extends Component<Props, Substitution> {
146146

147147
render () {
148148
const { activeEditingIndex, substitution: originalSubstitution } = this.props
149-
const { description, invalid, normalizeSpace, pattern, replacement } = this.state
149+
const { description, normalizeSpace, pattern, replacement, valid } = this.state
150150
const regexTestLink = `https://regexr.com/?expression=${encodeURIComponent(pattern)}&text=${STRING_FOR_REGEXR_TEST}`
151151
const isEditing = this._isEditing()
152152
const allowEdit = activeEditingIndex === -1
153153
const isPatternBlank = isSubstitutionBlank(this.state)
154-
const isPatternInvalid = invalid && pattern === originalSubstitution.pattern
154+
const isPatternInvalid = !valid && pattern === originalSubstitution.pattern
155155
const isEditingInvalid = isPatternBlank || isPatternInvalid
156156
let validationMessage = null
157157
if (isPatternBlank) {
@@ -166,7 +166,7 @@ export default class SubstitutionRow extends Component<Props, Substitution> {
166166
const rowClassName = `substitution-row ${editingClassName} ${allowEditClassName}`
167167

168168
// Override style for inputs with invalid search patterns.
169-
const patternStyleOverride = isPatternInvalid ? { borderColor: 'inherit' } : null
169+
const patternStyleOverride = isPatternInvalid ? { borderColor: '#a94442' } : null
170170

171171
return (
172172
<tr className={rowClassName}>

‎lib/types/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -301,10 +301,10 @@ export type FetchFrequency = $Values<typeof FETCH_FREQUENCIES>
301301

302302
export type Substitution = {
303303
description?: string,
304-
invalid: boolean,
305304
normalizeSpace?: boolean,
306305
pattern: string,
307-
replacement: string
306+
replacement: string,
307+
valid: boolean
308308
}
309309

310310
export type NormalizeFieldFields = {

0 commit comments

Comments
 (0)
Please sign in to comment.