Skip to content

Commit 6ec5fb4

Browse files
committed
EditComboField: add support for relation references
1 parent 09a90ec commit 6ec5fb4

4 files changed

Lines changed: 55 additions & 22 deletions

File tree

components/EditComboField.jsx

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import PropTypes from 'prop-types';
1212

1313
import {KeyValCache} from '../utils/EditingUtils';
1414
import LocaleUtils from '../utils/LocaleUtils';
15+
import Icon from './Icon';
16+
import ComboBox from './widgets/ComboBox';
1517

1618
import './style/EditComboField.css';
1719

@@ -22,12 +24,16 @@ export default class EditComboField extends React.Component {
2224
fieldId: PropTypes.string,
2325
filterExpr: PropTypes.array,
2426
keyvalrel: PropTypes.string,
27+
mapPrefix: PropTypes.string,
2528
multiSelect: PropTypes.bool,
2629
name: PropTypes.string,
2730
placeholder: PropTypes.string,
2831
readOnly: PropTypes.bool,
2932
required: PropTypes.bool,
33+
showAdd: PropTypes.bool,
34+
showEdit: PropTypes.bool,
3035
style: PropTypes.object,
36+
switchEditContext: PropTypes.func,
3137
updateField: PropTypes.func,
3238
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
3339
values: PropTypes.array
@@ -40,14 +46,14 @@ export default class EditComboField extends React.Component {
4046
if (this.props.values) {
4147
this.setState({values: this.props.values, showPlaceholder: !this.hasEmptyValue(this.props.values)});
4248
} else if (this.props.keyvalrel) {
43-
KeyValCache.get(this.props.editIface, this.props.keyvalrel, this.props.filterExpr ?? null).then(values => {
49+
KeyValCache.get(this.props.editIface, this.props.mapPrefix + "." + this.props.keyvalrel, this.props.filterExpr ?? null).then(values => {
4450
this.setState({values, showPlaceholder: !this.hasEmptyValue(values)});
4551
});
4652
}
4753
}
4854
componentDidUpdate(prevProps) {
4955
if (this.props.keyvalrel && this.props.filterExpr !== prevProps.filterExpr) {
50-
KeyValCache.get(this.props.editIface, this.props.keyvalrel, this.props.filterExpr ?? null).then(values => {
56+
KeyValCache.get(this.props.editIface, this.props.mapPrefix + "." + this.props.keyvalrel, this.props.filterExpr ?? null).then(values => {
5157
this.setState({values, showPlaceholder: !this.hasEmptyValue(values)});
5258
});
5359
}
@@ -106,22 +112,26 @@ export default class EditComboField extends React.Component {
106112
};
107113
renderComboSelect = () => {
108114
return (
109-
<select disabled={this.props.readOnly} name={this.props.name}
110-
onChange={ev => this.props.updateField(this.props.fieldId, ev.target.selectedIndex === 0 && this.state.showPlaceholder ? null : ev.target.value)}
111-
required={this.props.required} style={this.props.style} value={String(this.props.value)}
112-
>
113-
{this.state.showPlaceholder ? (
114-
<option disabled={this.props.required} value="">
115-
{this.props.placeholder ?? LocaleUtils.tr("common.select")}
116-
</option>
115+
<div className="edit-single-select controlgroup">
116+
<ComboBox className="controlgroup-expanditem" name={this.props.name}
117+
onChange={value => this.props.updateField(this.props.fieldId, value)}
118+
placeholder={this.state.showPlaceholder ? (this.props.placeholder ?? LocaleUtils.tr("common.select")) : undefined}
119+
required={this.props.required} style={this.props.style} value={String(this.props.value)}
120+
>
121+
{this.state.values.map((item, index) => {
122+
const {value, label} = this.itemValueLabel(item);
123+
return (
124+
<div key={this.props.fieldId + index} value={String(value)}>{label}</div>
125+
);
126+
})}
127+
</ComboBox>
128+
{this.props.showEdit ? (
129+
<button className="button" onClick={this.onEdit} type="button"><Icon icon="draw" /></button>
117130
) : null}
118-
{this.state.values.map((item, index) => {
119-
const {value, label} = this.itemValueLabel(item);
120-
return (
121-
<option key={this.props.fieldId + index} value={String(value)}>{label}</option>
122-
);
123-
})}
124-
</select>
131+
{this.props.showAdd ? (
132+
<button className="button" onClick={this.onAdd} type="button"><Icon icon="plus" /></button>
133+
) : null}
134+
</div>
125135
);
126136
};
127137
itemValueLabel = (item) => {
@@ -135,4 +145,19 @@ export default class EditComboField extends React.Component {
135145
}
136146
return {value, label};
137147
};
148+
onAdd = () => {
149+
const parts = this.props.keyvalrel.split(":");
150+
this.props.switchEditContext("Create", parts[0], null, this.childContextDone, parts[2]);
151+
};
152+
onEdit = () => {
153+
const parts = this.props.keyvalrel.split(":");
154+
this.props.switchEditContext("Edit", parts[0], this.props.value, this.childContextDone, parts[2]);
155+
};
156+
childContextDone = (feature) => {
157+
const parts = this.props.keyvalrel.split(":");
158+
KeyValCache.get(this.props.editIface, this.props.mapPrefix + "." + this.props.keyvalrel, this.props.filterExpr ?? null, true).then(values => {
159+
this.setState({values, showPlaceholder: !this.hasEmptyValue(values)});
160+
this.props.updateField(this.props.fieldId, feature.properties[parts[1]]);
161+
});
162+
};
138163
}

components/QtDesignerForm.jsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -416,19 +416,22 @@ class QtDesignerForm extends React.Component {
416416
const count = parts.length;
417417
const fieldId = parts.slice(1, count - 3).join("__");
418418
value = (feature.properties || [])[fieldId] ?? "";
419-
const keyvalrel = this.props.mapPrefix + "." + parts[count - 3] + ":" + parts[count - 2] + ":" + parts[count - 1];
419+
const keyvalrel = parts[count - 3] + ":" + parts[count - 2] + ":" + parts[count - 1];
420420
let filterExpr = null;
421421
if (field?.filterExpression) {
422422
filterExpr = parseExpression(field.filterExpression, feature, editConfig, this.props.iface, this.props.mapPrefix, this.props.mapCrs, () => this.setState({reevaluate: +new Date}), true);
423423
}
424424
return (
425425
<EditComboField
426426
editIface={this.props.iface} fieldId={fieldId} filterExpr={filterExpr} key={fieldId}
427-
keyvalrel={keyvalrel} multiSelect={widget.property.allowMulti === true || widget.allowMulti === "true"}
427+
keyvalrel={keyvalrel} mapPrefix={this.props.mapPrefix}
428+
multiSelect={widget.property.allowMulti === true || widget.allowMulti === "true"}
428429
name={nametransform(fieldId)} placeholder={inputConstraints.placeholder}
429430
readOnly={inputConstraints.readOnly || fieldConstraints.readOnly}
430431
required={inputConstraints.required || fieldConstraints.required}
431-
style={fontStyle} updateField={updateField} value={value} />
432+
showAdd={fieldConstraints.showAdd} showEdit={fieldConstraints.showEdit}
433+
style={fontStyle} switchEditContext={this.props.switchEditContext}
434+
updateField={updateField} value={value} />
432435
);
433436
} else {
434437
const values = MiscUtils.ensureArray(widget.item || []).map((item) => ({

components/style/EditComboField.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
div.edit-single-select {
2+
display: flex;
3+
align-items: center;
4+
}
5+
16
div.edit-multi-select {
27
border: 1px solid var(--border-color);
38
padding: 0.25em;

utils/EditingUtils.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ export class FeatureCache {
6666
export class KeyValCache {
6767
static store = {};
6868
static requestPromises = {};
69-
static get = (editIface, keyvalrel, filterExpr) => {
69+
static get = (editIface, keyvalrel, filterExpr, forceReload = false) => {
7070
const key = keyvalrel + uuidv5(JSON.stringify(filterExpr ?? null), UUID_NS);
71-
if (key in this.store) {
71+
if (key in this.store && !forceReload) {
7272
return new Promise(resolve => resolve(this.store[key]));
7373
} else if (key in this.requestPromises) {
7474
return this.requestPromises[key];

0 commit comments

Comments
 (0)