Skip to content

Commit b426f30

Browse files
authored
Fix : #4782 , Implemented update dataset (#2149)
1 parent 7ad1fcf commit b426f30

File tree

18 files changed

+256
-105
lines changed

18 files changed

+256
-105
lines changed

geonode_mapstore_client/client/js/plugins/Operation/components/UploadPanel.jsx

Lines changed: 134 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { Alert, Glyphicon } from 'react-bootstrap';
1212
import Dropzone from 'react-dropzone';
1313

1414
import Message from '@mapstore/framework/components/I18N/Message';
15+
import ConfirmDialog from '@mapstore/framework/components/layout/ConfirmDialog';
1516
import ViewerLayout from '@js/components/ViewerLayout';
1617
import uuidv1 from 'uuid/v1';
1718
import uniq from 'lodash/uniq';
@@ -55,12 +56,14 @@ function UploadPanel({
5556
remoteTypesPlaceholder,
5657
remoteTypeErrorMessageId,
5758
remoteTypeFromUrl,
58-
isRemoteTypesDisabled
59+
isRemoteTypesDisabled,
60+
uploadActions=[{ labelId: 'gnviewer.upload' }],
5961
}) {
6062

6163
const inputFile = useRef();
6264

6365
const [uploads, setUploads] = useState([]);
66+
const [showConfirm, setShowConfirm] = useState(false);
6467

6568
useEffect(() => {
6669
setUploads(prevUploads =>
@@ -110,106 +113,145 @@ function UploadPanel({
110113
return handleAdd([getDefaultRemoteResource({ id: uuidv1(), type: 'remote', url: '' })]);
111114
};
112115

116+
117+
113118
const supportedLabels = uniq(supportedFiles.map(supportedFile => supportedFile.label)).join(', ');
114119
const uploadsList = uploads.filter(upload => upload.type === 'file' ? upload.supported : true);
115120
const supportedUploads = uploads.filter(upload => upload.supported);
116121
const readyUploads = uploads.filter(upload => upload.ready);
117122
const unsupportedLabels = uploads.filter(upload => upload.type === 'file' && !upload.supported).map((upload) => `${upload.baseName}.${upload?.ext?.[0] || ''}`).join(', ');
118123
const disabledAdd = disabled || loading || readyUploads.length === maxParallelUploads;
124+
125+
126+
const handleUpload = (confirmDialog, action) => {
127+
if (confirmDialog) {
128+
setShowConfirm(true);
129+
return;
130+
}
131+
onUpload(readyUploads, action);
132+
};
133+
119134
return (
120-
<Dropzone
121-
multiple
122-
onDrop={handleFile}
123-
className="gn-upload-panel"
124-
activeClassName="gn-dropzone-active"
125-
rejectClassName="gn-dropzone-reject"
126-
disableClick
127-
>
128-
<ViewerLayout
129-
rightColumn={rightColumn}
130-
leftColumn={<div className="gn-upload-list">
131-
<div className="gn-upload-list-header">
132-
<input disabled={disabledAdd} ref={inputFile} value="" type="file" multiple onChange={(event) => handleFile([...event?.target?.files])} style={{ display: 'none' }} />
133-
<Button disabled={disabledAdd} onClick={() => inputFile?.current?.click()}>
134-
<Glyphicon glyph="plus" /><Message msgId="gnviewer.selectFiles" />
135-
</Button>
136-
{enableRemoteUploads && <Button disabled={disabledAdd} className={"add-url"} onClick={() => handleRemote()}>
137-
<Glyphicon glyph="plus" /><Message msgId="gnviewer.addFromUrl" />
138-
</Button>}
139-
</div>
140-
{uploadsList.length > 0
141-
? (
142-
<ul>
143-
{uploadsList.map((upload) => {
144-
return (
145-
<li key={upload.id}>
146-
<PendingUploadCard
147-
data={upload}
148-
progress={progress[upload.id]}
149-
loading={loading}
150-
error={errors[upload.id]}
151-
onCancel={onCancel}
152-
remoteTypes={remoteTypes}
153-
isRemoteTypesDisabled={isRemoteTypesDisabled}
154-
remoteTypesPlaceholder={remoteTypesPlaceholder}
155-
remoteTypeErrorMessageId={remoteTypeErrorMessageId}
156-
remoteTypeFromUrl={remoteTypeFromUrl}
157-
onRemove={handleRemove}
158-
onChange={handleChange}
159-
/>
160-
</li>
161-
);
162-
})}
163-
</ul>
164-
)
165-
: (
166-
<div
167-
style={{
168-
position: 'relative',
169-
width: '100%',
170-
flex: 1,
171-
display: 'flex',
172-
alignItems: 'center',
173-
justifyContent: 'center',
174-
padding: '1rem',
175-
textAlign: 'center'
176-
}}
177-
>
178-
<div><Message msgId="gnviewer.supportedFiles" />: {supportedLabels}</div>
179-
</div>
180-
)}
181-
<div className="gn-upload-list-footer">
182-
{unsupportedLabels ? <Alert bsStyle="danger">
183-
<Message msgId="gnviewer.unsupportedFiles" />{unsupportedLabels ? `: ${unsupportedLabels}` : ''}
184-
</Alert> : null}
185-
{(uploads.length > 0 && getExceedingFileSize(uploads, maxAllowedSize)) ?
186-
<ButtonWithTooltip noTooltipWhenDisabled tooltip={<Message msgId="gnviewer.exceedingFileMsg" msgParams={{ limit: maxAllowedSize }} />} >
187-
<Message msgId="gnviewer.upload" />
188-
</ButtonWithTooltip>
189-
: supportedUploads.length > maxParallelUploads ?
190-
<ButtonWithTooltip noTooltipWhenDisabled tooltip={<Message msgId="gnviewer.parallelUploadLimit" msgParams={{ limit: maxParallelUploads }} />} >
191-
<Message msgId="gnviewer.upload" />
192-
</ButtonWithTooltip>
193-
:
194-
!loading ? <Button
195-
variant="primary"
196-
disabled={readyUploads.length === 0 || disabled}
197-
onClick={() => onUpload(readyUploads)}
135+
<>
136+
<ConfirmDialog
137+
show={showConfirm}
138+
titleId="gnviewer.replaceDatasetConfirmTitle"
139+
cancelId="cancel"
140+
confirmId="confirm"
141+
variant="danger"
142+
onCancel={() => {
143+
setShowConfirm(false);
144+
}}
145+
onConfirm={() => {
146+
onUpload(readyUploads);
147+
setShowConfirm(false);
148+
}}
149+
>
150+
<Message msgId="gnviewer.replaceDatasetConfirmMessage" />
151+
</ConfirmDialog>
152+
<Dropzone
153+
multiple
154+
onDrop={handleFile}
155+
className="gn-upload-panel"
156+
activeClassName="gn-dropzone-active"
157+
rejectClassName="gn-dropzone-reject"
158+
disableClick
159+
>
160+
<ViewerLayout
161+
rightColumn={rightColumn}
162+
leftColumn={<div className="gn-upload-list">
163+
<div className="gn-upload-list-header">
164+
<input disabled={disabledAdd} ref={inputFile} value="" type="file" multiple onChange={(event) => handleFile([...event?.target?.files])} style={{ display: 'none' }} />
165+
<Button disabled={disabledAdd} onClick={() => inputFile?.current?.click()}>
166+
<Glyphicon glyph="plus" /><Message msgId="gnviewer.selectFiles" />
167+
</Button>
168+
{enableRemoteUploads && <Button disabled={disabledAdd} className={"add-url"} onClick={() => handleRemote()}>
169+
<Glyphicon glyph="plus" /><Message msgId="gnviewer.addFromUrl" />
170+
</Button>}
171+
</div>
172+
{uploadsList.length > 0
173+
? (
174+
<ul>
175+
{uploadsList.map((upload) => {
176+
return (
177+
<li key={upload.id}>
178+
<PendingUploadCard
179+
data={upload}
180+
progress={progress[upload.id]}
181+
loading={loading}
182+
error={errors[upload.id]}
183+
onCancel={onCancel}
184+
remoteTypes={remoteTypes}
185+
isRemoteTypesDisabled={isRemoteTypesDisabled}
186+
remoteTypesPlaceholder={remoteTypesPlaceholder}
187+
remoteTypeErrorMessageId={remoteTypeErrorMessageId}
188+
remoteTypeFromUrl={remoteTypeFromUrl}
189+
onRemove={handleRemove}
190+
onChange={handleChange}
191+
/>
192+
</li>
193+
);
194+
})}
195+
</ul>
196+
)
197+
: (
198+
<div
199+
style={{
200+
position: 'relative',
201+
width: '100%',
202+
flex: 1,
203+
display: 'flex',
204+
alignItems: 'center',
205+
justifyContent: 'center',
206+
padding: '1rem',
207+
textAlign: 'center'
208+
}}
198209
>
210+
<div><Message msgId="gnviewer.supportedFiles" />: {supportedLabels}</div>
211+
</div>
212+
)}
213+
<div className="gn-upload-list-footer">
214+
{unsupportedLabels ? <Alert bsStyle="danger">
215+
<Message msgId="gnviewer.unsupportedFiles" />{unsupportedLabels ? `: ${unsupportedLabels}` : ''}
216+
</Alert> : null}
217+
{(uploads.length > 0 && getExceedingFileSize(uploads, maxAllowedSize)) ?
218+
<ButtonWithTooltip noTooltipWhenDisabled tooltip={<Message msgId="gnviewer.exceedingFileMsg" msgParams={{ limit: maxAllowedSize }} />} >
199219
<Message msgId="gnviewer.upload" />
200-
</Button> : <Button
201-
variant="primary"
202-
onClick={() => onCancel(readyUploads.map((upload) => upload.id))}
203-
>
204-
<Message msgId="gnviewer.cancelUpload" />
205-
</Button>}
206-
</div>
207-
{disabled ? <div className="gn-upload-list-cover" /> : null}
208-
</div>}
209-
>
210-
{children}
211-
</ViewerLayout>
212-
</Dropzone>
220+
</ButtonWithTooltip>
221+
: supportedUploads.length > maxParallelUploads ?
222+
<ButtonWithTooltip noTooltipWhenDisabled tooltip={<Message msgId="gnviewer.parallelUploadLimit" msgParams={{ limit: maxParallelUploads }} />} >
223+
<Message msgId="gnviewer.upload" />
224+
</ButtonWithTooltip>
225+
:
226+
!loading ? (
227+
<>
228+
{uploadActions?.map(({ labelId, variant, action, showConfirm: shouldConfirm }, id) => (
229+
<Button
230+
key={id}
231+
variant={variant ? variant : "primary"}
232+
disabled={readyUploads.length === 0 || disabled}
233+
style={{ marginRight: id < uploadActions.length - 1 ? 8 : 0 }}
234+
onClick={() => handleUpload(shouldConfirm, action)}
235+
>
236+
<Message msgId={labelId} />
237+
</Button>
238+
))}
239+
</>
240+
) : <Button
241+
variant="primary"
242+
onClick={() => onCancel(readyUploads.map((upload) => upload.id))}
243+
>
244+
<Message msgId="gnviewer.cancelUpload" />
245+
</Button>}
246+
</div>
247+
{disabled ? <div className="gn-upload-list-cover" /> : null}
248+
</div>}
249+
>
250+
{children}
251+
</ViewerLayout>
252+
</Dropzone>
253+
</>
254+
213255
);
214256
}
215257

geonode_mapstore_client/client/js/plugins/Operation/containers/OperationUpload.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ function OperationUpload({
100100
</div>}
101101
onCancel={cancelRequest}
102102
onUpload={uploadRequest}
103+
uploadActions={api.uploadActions}
103104
>
104105
<ExecutionRequestTable
105106
iconName={iconName}

geonode_mapstore_client/client/js/plugins/Operation/hooks/useUpload.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,23 @@ const useUpload = ({
2323
const [completed, setCompleted] = useState({});
2424
const [progress, setProgress] = useState({});
2525

26-
const getUploadRequestPayload = (upload) => {
26+
const getUploadRequestPayload = (upload, action) => {
2727
const bodyConfig = api?.body?.[upload?.type];
28-
const payload = Object.keys(bodyConfig).reduce((acc, key) => {
28+
let payload = Object.keys(bodyConfig).reduce((acc, key) => {
2929
return {
3030
...acc,
3131
[key]: isFunction(bodyConfig[key])
3232
? bodyConfig[key]({ upload })
3333
: bodyConfig[key]
3434
};
3535
}, {});
36+
const actionToUse = action ? action : payload?.action;
37+
const extraBody = api?.bodyExtra?.[actionToUse]?.[upload?.type] || {};
38+
payload = {
39+
...payload,
40+
...extraBody,
41+
action: actionToUse
42+
};
3643
if (upload.files) {
3744
Object.keys(upload.files).forEach((ext) => {
3845
payload[`${ext}_file`] = upload.files[ext];
@@ -64,7 +71,7 @@ const useUpload = ({
6471
}));
6572
uploadIds.forEach((uploadId) => sources[uploadId].cancel());
6673
},
67-
uploadRequest: (uploads) => {
74+
uploadRequest: (uploads, action) => {
6875
if (!loading) {
6976
setLoading(true);
7077
setErrors({});
@@ -76,7 +83,7 @@ const useUpload = ({
7683
onUploadProgress: onUploadProgress(upload.id),
7784
cancelToken: sources[upload.id].token
7885
};
79-
const payload = getUploadRequestPayload(upload);
86+
const payload = getUploadRequestPayload(upload, action);
8087
return axios[api.method || 'post'](api.url, payload, config)
8188
.then(({ data }) => ({ status: 'success', data, id: upload.id, upload }))
8289
.catch((error) => {

geonode_mapstore_client/client/js/plugins/Operation/index.jsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import epics from './epics/operation';
1818
import OperationUpload from './containers/OperationUpload';
1919
import Message from '@mapstore/framework/components/I18N/Message';
2020

21+
2122
/**
2223
* @module Operation
2324
*/
@@ -107,15 +108,19 @@ function Operation({
107108
// open the import ui if a blocking execution is still running
108109
const executions = resource?.executions;
109110
useEffect(() => {
110-
if (executions && action && blocking) {
111+
const actionsToCheck = api?.uploadActions
112+
? api.uploadActions.map(actionObj => actionObj.action)
113+
: [action];
114+
115+
if (executions && blocking && actionsToCheck) {
111116
const runningExecution = executions
112117
.find((execution) => execution.status === 'running'
113-
&& execution?.input_params?.action === action);
118+
&& actionsToCheck.includes(execution?.input_params?.action));
114119
if (runningExecution) {
115120
onSelect(id);
116121
}
117122
}
118-
}, [id, blocking, action, executions]);
123+
}, [id, blocking, action, executions, api]);
119124

120125
if (selected !== id) {
121126
return null;

0 commit comments

Comments
 (0)