Skip to content

Commit ea80fd2

Browse files
committed
feat(config): add quick array entry
1 parent b89456c commit ea80fd2

File tree

1 file changed

+79
-5
lines changed

1 file changed

+79
-5
lines changed

src/dashboard/Data/Config/Config.react.js

Lines changed: 79 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import browserStyles from 'dashboard/Data/Browser/Browser.scss';
2323
import { CurrentApp } from 'context/currentApp';
2424
import Modal from 'components/Modal/Modal.react';
2525
import equal from 'fast-deep-equal';
26+
import Notification from 'dashboard/Data/Browser/Notification.react';
2627

2728
@subscribeTo('Config', 'config')
2829
class Config extends TableView {
@@ -41,7 +42,10 @@ class Config extends TableView {
4142
modalMasterKeyOnly: false,
4243
loading: false,
4344
confirmModalOpen: false,
45+
lastError: null,
46+
lastNote: null,
4447
};
48+
this.noteTimeout = null;
4549
}
4650

4751
componentWillMount() {
@@ -127,12 +131,24 @@ class Config extends TableView {
127131
}}
128132
>
129133
<div className={[browserStyles.confirmConfig]}>
130-
This parameter changed while you were editing it. If you continue, the latest changes will be lost and replaced with your version. Do you want to proceed?
134+
This parameter changed while you were editing it. If you continue, the latest changes
135+
will be lost and replaced with your version. Do you want to proceed?
131136
</div>
132137
</Modal>
133138
);
134139
}
135-
return extras;
140+
let notification = null;
141+
if (this.state.lastError) {
142+
notification = <Notification note={this.state.lastError} isErrorNote={true} />;
143+
} else if (this.state.lastNote) {
144+
notification = <Notification note={this.state.lastNote} isErrorNote={false} />;
145+
}
146+
return (
147+
<>
148+
{extras}
149+
{notification}
150+
</>
151+
);
136152
}
137153

138154
parseValueForModal(dataValue) {
@@ -186,7 +202,6 @@ class Config extends TableView {
186202
* Opens the modal dialog to edit the Config parameter.
187203
*/
188204
const openModal = async () => {
189-
190205
// Show dialog
191206
this.setState({
192207
loading: true,
@@ -203,7 +218,8 @@ class Config extends TableView {
203218
// Get latest param values
204219
const fetchedParams = this.props.config.data.get('params');
205220
const fetchedValue = fetchedParams.get(this.state.modalParam);
206-
const fetchedMasterKeyOnly = this.props.config.data.get('masterKeyOnly')?.get(this.state.modalParam) || false;
221+
const fetchedMasterKeyOnly =
222+
this.props.config.data.get('masterKeyOnly')?.get(this.state.modalParam) || false;
207223

208224
// Parse fetched data
209225
const { modalValue: fetchedModalValue } = this.parseValueForModal(fetchedValue);
@@ -219,6 +235,7 @@ class Config extends TableView {
219235
// Define column styles
220236
const columnStyleLarge = { width: '30%', cursor: 'pointer' };
221237
const columnStyleSmall = { width: '15%', cursor: 'pointer' };
238+
const columnStyleAction = { width: '10%', textAlign: 'center' };
222239

223240
const openModalValueColumn = () => {
224241
if (data.value instanceof Parse.File) {
@@ -244,6 +261,13 @@ class Config extends TableView {
244261
<td style={columnStyleLarge} onClick={openModalValueColumn}>
245262
{value}
246263
</td>
264+
<td style={columnStyleAction}>
265+
{type === 'Array' && (
266+
<a onClick={() => this.addArrayEntry(data.param)}>
267+
<Icon width={16} height={16} name="plus-solid" />
268+
</a>
269+
)}
270+
</td>
247271
<td style={columnStyleSmall} onClick={openModal}>
248272
{data.masterKeyOnly.toString()}
249273
</td>
@@ -264,9 +288,12 @@ class Config extends TableView {
264288
<TableHeader key="type" width={15}>
265289
Type
266290
</TableHeader>,
267-
<TableHeader key="value" width={30}>
291+
<TableHeader key="value" width={25}>
268292
Value
269293
</TableHeader>,
294+
<TableHeader key="action" width={10}>
295+
Action
296+
</TableHeader>,
270297
<TableHeader key="masterKeyOnly" width={15}>
271298
Master key only
272299
</TableHeader>,
@@ -430,6 +457,53 @@ class Config extends TableView {
430457
modalMasterKeyOnly: false,
431458
});
432459
}
460+
461+
showNote(message, isError) {
462+
if (!message) {
463+
return;
464+
}
465+
clearTimeout(this.noteTimeout);
466+
if (isError) {
467+
this.setState({ lastError: message, lastNote: null });
468+
} else {
469+
this.setState({ lastNote: message, lastError: null });
470+
}
471+
this.noteTimeout = setTimeout(() => {
472+
this.setState({ lastError: null, lastNote: null });
473+
}, 3500);
474+
}
475+
476+
async addArrayEntry(param) {
477+
const input = window.prompt('New array entry (JSON supported)');
478+
if (input === null) {
479+
return;
480+
}
481+
let value;
482+
try {
483+
value = JSON.parse(input);
484+
} catch (e) {
485+
value = input;
486+
}
487+
try {
488+
this.setState({ loading: true });
489+
await Parse._request(
490+
'PUT',
491+
'config',
492+
{
493+
params: {
494+
[param]: { __op: 'AddUnique', objects: [Parse._encode(value)] },
495+
},
496+
},
497+
{ useMasterKey: true }
498+
);
499+
await this.props.config.dispatch(ActionTypes.FETCH);
500+
this.showNote('Entry added');
501+
} catch (e) {
502+
this.showNote(`Failed to add entry: ${e.message}`, true);
503+
} finally {
504+
this.setState({ loading: false });
505+
}
506+
}
433507
}
434508

435509
export default Config;

0 commit comments

Comments
 (0)