@panneau/app 1.0.1-alpha.0 → 1.0.3-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/css/styles.css +7 -0
- package/es/index.js +1812 -5
- package/lib/index.js +1842 -15
- package/package.json +66 -54
- package/scss/styles.scss +3 -0
- package/es/Panneau.js +0 -318
- package/es/actions/AuthActions.js +0 -16
- package/es/actions/LayoutActions.js +0 -14
- package/es/components/App.js +0 -129
- package/es/components/Layout.js +0 -68
- package/es/components/Panneau.js +0 -79
- package/es/components/index.js +0 -3
- package/es/components/pages/Account.js +0 -38
- package/es/components/pages/Home.js +0 -12
- package/es/components/pages/ResourceCreate.js +0 -44
- package/es/components/pages/ResourceDelete.js +0 -11
- package/es/components/pages/ResourceEdit.js +0 -28
- package/es/components/pages/ResourceForm.js +0 -343
- package/es/components/pages/ResourceIndex.js +0 -261
- package/es/components/pages/ResourceShow.js +0 -15
- package/es/components/partials/ResourceFormHeader.js +0 -111
- package/es/components/partials/ResourceIndexHeader.js +0 -71
- package/es/defaults/routes.json +0 -10
- package/es/lib/createStore.js +0 -30
- package/es/reducers/AuthReducer.js +0 -32
- package/es/reducers/index.js +0 -4
- package/lib/Panneau.js +0 -340
- package/lib/actions/AuthActions.js +0 -25
- package/lib/actions/LayoutActions.js +0 -25
- package/lib/components/App.js +0 -159
- package/lib/components/Layout.js +0 -87
- package/lib/components/Panneau.js +0 -103
- package/lib/components/index.js +0 -23
- package/lib/components/pages/Account.js +0 -54
- package/lib/components/pages/Home.js +0 -23
- package/lib/components/pages/ResourceCreate.js +0 -65
- package/lib/components/pages/ResourceDelete.js +0 -22
- package/lib/components/pages/ResourceEdit.js +0 -44
- package/lib/components/pages/ResourceForm.js +0 -376
- package/lib/components/pages/ResourceIndex.js +0 -289
- package/lib/components/pages/ResourceShow.js +0 -28
- package/lib/components/partials/ResourceFormHeader.js +0 -137
- package/lib/components/partials/ResourceIndexHeader.js +0 -87
- package/lib/defaults/routes.json +0 -10
- package/lib/lib/createStore.js +0 -46
- package/lib/reducers/AuthReducer.js +0 -43
- package/lib/reducers/index.js +0 -15
- package/src/Panneau.js +0 -274
- package/src/actions/AuthActions.js +0 -17
- package/src/actions/LayoutActions.js +0 -12
- package/src/components/App.jsx +0 -121
- package/src/components/Layout.jsx +0 -51
- package/src/components/Panneau.jsx +0 -95
- package/src/components/index.js +0 -7
- package/src/components/pages/Account.jsx +0 -34
- package/src/components/pages/Home.jsx +0 -19
- package/src/components/pages/ResourceCreate.jsx +0 -50
- package/src/components/pages/ResourceDelete.jsx +0 -18
- package/src/components/pages/ResourceEdit.jsx +0 -39
- package/src/components/pages/ResourceForm.jsx +0 -361
- package/src/components/pages/ResourceIndex.jsx +0 -256
- package/src/components/pages/ResourceShow.jsx +0 -23
- package/src/components/partials/ResourceFormHeader.jsx +0 -137
- package/src/components/partials/ResourceIndexHeader.jsx +0 -84
- package/src/defaults/routes.json +0 -10
- package/src/index.js +0 -9
- package/src/lib/createStore.js +0 -21
- package/src/reducers/AuthReducer.js +0 -23
- package/src/reducers/index.js +0 -5
- package/src/styles/layout.scss +0 -5
- package/src/styles/pages/resource-form.scss +0 -42
- package/src/styles/pages/resource-index.scss +0 -43
- package/src/styles/partials/resource-form-header.scss +0 -7
- package/src/styles/partials/resource-index-header.scss +0 -13
- package/src/styles/vendor.global.scss +0 -5
@@ -1,361 +0,0 @@
|
|
1
|
-
/* eslint-disable react/jsx-props-no-spreading */
|
2
|
-
import React, { useCallback, useState, useEffect, useMemo } from 'react';
|
3
|
-
import PropTypes from 'prop-types';
|
4
|
-
import isObject from 'lodash/isObject';
|
5
|
-
import classNames from 'classnames';
|
6
|
-
import { defineMessages } from 'react-intl';
|
7
|
-
import { PropTypes as PanneauPropTypes, useResourceApi } from '@panneau/core';
|
8
|
-
import { getErrorsFromResponseError } from '@panneau/core/requests';
|
9
|
-
import { Loading, Errors } from '@panneau/core/components';
|
10
|
-
import { useComponent } from '@panneau/core/contexts';
|
11
|
-
|
12
|
-
import ResourceFormHeader from '../partials/ResourceFormHeader';
|
13
|
-
|
14
|
-
import styles from '../../styles/pages/resource-form.scss';
|
15
|
-
|
16
|
-
export const messages = defineMessages({
|
17
|
-
cancel: {
|
18
|
-
id: 'app.buttons.resources.cancel',
|
19
|
-
description: 'The label of the "cancel" button',
|
20
|
-
defaultMessage: 'Cancel',
|
21
|
-
},
|
22
|
-
save: {
|
23
|
-
id: 'app.buttons.resources.save',
|
24
|
-
description: 'The label of the "save" button',
|
25
|
-
defaultMessage: 'Save',
|
26
|
-
},
|
27
|
-
title: {
|
28
|
-
id: 'app.titles.resources.default',
|
29
|
-
description: 'The title of the resource form',
|
30
|
-
defaultMessage: '{name}',
|
31
|
-
},
|
32
|
-
titleTyped: {
|
33
|
-
id: 'app.titles.resources.typed',
|
34
|
-
description: 'The title of the typed resource form',
|
35
|
-
defaultMessage: '{name} <small class="text-muted">({type})</small>',
|
36
|
-
},
|
37
|
-
successNotice: {
|
38
|
-
id: 'app.notices.resources.success',
|
39
|
-
description: 'The text of the "success" form notice',
|
40
|
-
defaultMessage: 'Success!',
|
41
|
-
},
|
42
|
-
errorNotice: {
|
43
|
-
id: 'app.notices.resources.error',
|
44
|
-
description: 'The text of the "error" form notice',
|
45
|
-
defaultMessage: 'Failed. The form contains errors.',
|
46
|
-
},
|
47
|
-
});
|
48
|
-
|
49
|
-
const propTypes = {
|
50
|
-
action: PropTypes.string,
|
51
|
-
resource: PanneauPropTypes.resource.isRequired,
|
52
|
-
resourceApi: PanneauPropTypes.resourceApi.isRequired,
|
53
|
-
itemId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
54
|
-
item: PropTypes.shape({
|
55
|
-
id: PropTypes.number,
|
56
|
-
type: PropTypes.string,
|
57
|
-
}),
|
58
|
-
query: PropTypes.shape({
|
59
|
-
type: PropTypes.string,
|
60
|
-
}),
|
61
|
-
successNoticeLabel: PanneauPropTypes.label,
|
62
|
-
errorNoticeLabel: PanneauPropTypes.label,
|
63
|
-
buttons: PanneauPropTypes.buttons,
|
64
|
-
saveButtonLabel: PanneauPropTypes.message,
|
65
|
-
confirmSwitchTypeMessage: PanneauPropTypes.message,
|
66
|
-
errors: PropTypes.arrayOf(PropTypes.string),
|
67
|
-
formValue: PropTypes.shape({}),
|
68
|
-
formErrors: PropTypes.objectOf(PropTypes.array),
|
69
|
-
readOnly: PropTypes.bool,
|
70
|
-
title: PanneauPropTypes.label,
|
71
|
-
titleTyped: PanneauPropTypes.label,
|
72
|
-
gotoResourceAction: PropTypes.func.isRequired,
|
73
|
-
onFormComplete: PropTypes.func,
|
74
|
-
};
|
75
|
-
|
76
|
-
const defaultProps = {
|
77
|
-
action: 'create',
|
78
|
-
title: messages.title,
|
79
|
-
titleTyped: messages.titleTyped,
|
80
|
-
query: null,
|
81
|
-
itemId: null,
|
82
|
-
item: null,
|
83
|
-
errors: null,
|
84
|
-
formValue: null,
|
85
|
-
formErrors: null,
|
86
|
-
readOnly: false,
|
87
|
-
successNoticeLabel: messages.successNotice,
|
88
|
-
errorNoticeLabel: messages.errorNotice,
|
89
|
-
confirmSwitchTypeMessage: messages.confirmSwitchType,
|
90
|
-
buttons: [
|
91
|
-
{
|
92
|
-
id: 'cancel',
|
93
|
-
type: 'button',
|
94
|
-
label: messages.cancel,
|
95
|
-
className: 'btn-link btn-lg',
|
96
|
-
},
|
97
|
-
{
|
98
|
-
id: 'submit',
|
99
|
-
type: 'submit',
|
100
|
-
label: messages.save,
|
101
|
-
className: 'btn-primary btn-lg',
|
102
|
-
},
|
103
|
-
],
|
104
|
-
saveButtonLabel: null,
|
105
|
-
onFormComplete: null,
|
106
|
-
};
|
107
|
-
|
108
|
-
const ResourceForm = ({
|
109
|
-
resource,
|
110
|
-
item: currentItem,
|
111
|
-
itemId,
|
112
|
-
query,
|
113
|
-
action,
|
114
|
-
readOnly,
|
115
|
-
errors: currentErrors,
|
116
|
-
formValue: initialFormValue,
|
117
|
-
formErrors: initialFormErrors,
|
118
|
-
title,
|
119
|
-
titleTyped,
|
120
|
-
buttons,
|
121
|
-
saveButtonLabel,
|
122
|
-
successNoticeLabel,
|
123
|
-
errorNoticeLabel,
|
124
|
-
onFormComplete: customOnFormComplete,
|
125
|
-
gotoResourceAction,
|
126
|
-
}) => {
|
127
|
-
const [item, setItem] = useState(currentItem);
|
128
|
-
const [isLoading, setIsLoading] = useState(false);
|
129
|
-
const [errors, setErrors] = useState(currentErrors || item);
|
130
|
-
const [formValue, setFormValue] = useState(initialFormValue || item);
|
131
|
-
const [formErrors, setFormErrors] = useState(initialFormErrors || item);
|
132
|
-
const [formSuccess, setFormSuccess] = useState(initialFormErrors !== null ? false : null);
|
133
|
-
const resourceApi = useResourceApi(resource);
|
134
|
-
const isTyped = resource.type() === 'typed';
|
135
|
-
const waitingItem = action === 'edit' && item === null;
|
136
|
-
|
137
|
-
// Load item if needed
|
138
|
-
useEffect(() => {
|
139
|
-
if (isLoading) {
|
140
|
-
return;
|
141
|
-
}
|
142
|
-
const onItemLoaded = newItem => {
|
143
|
-
setItem(newItem);
|
144
|
-
};
|
145
|
-
const onItemLoadError = newErrors => {
|
146
|
-
setErrors(newErrors);
|
147
|
-
};
|
148
|
-
const itemChanged = item !== null && `${item.id}` !== `${itemId}`;
|
149
|
-
const itemShouldReload = item === null || itemChanged;
|
150
|
-
if ((action === 'edit' || action === 'show') && itemShouldReload) {
|
151
|
-
setIsLoading(true);
|
152
|
-
resourceApi
|
153
|
-
.show(itemId)
|
154
|
-
.then(onItemLoaded)
|
155
|
-
.catch(onItemLoadError)
|
156
|
-
.then(() => {
|
157
|
-
setIsLoading(false);
|
158
|
-
});
|
159
|
-
}
|
160
|
-
}, [action, item, itemId, isLoading]);
|
161
|
-
|
162
|
-
// Get current type
|
163
|
-
const currentType = useMemo(() => {
|
164
|
-
if (!isTyped || waitingItem) {
|
165
|
-
return null;
|
166
|
-
}
|
167
|
-
|
168
|
-
const types = resource.types();
|
169
|
-
const itemTypeId = item !== null ? item.type || null : null;
|
170
|
-
const { type: queryTypeId = null } = query || {};
|
171
|
-
const typeId = itemTypeId || queryTypeId;
|
172
|
-
const definedType = typeId !== null ? types.find(it => it.id === typeId) || null : null;
|
173
|
-
if (definedType !== null) {
|
174
|
-
return definedType;
|
175
|
-
}
|
176
|
-
|
177
|
-
return types.length > 0
|
178
|
-
? types.find(({ default: isDefault = false }) => isDefault) || types[0] || null
|
179
|
-
: null;
|
180
|
-
}, [item, query, resource]);
|
181
|
-
|
182
|
-
const onClickCancel = useCallback(
|
183
|
-
e => {
|
184
|
-
e.preventDefault();
|
185
|
-
gotoResourceAction('index');
|
186
|
-
},
|
187
|
-
[gotoResourceAction],
|
188
|
-
);
|
189
|
-
|
190
|
-
const formButtons = useMemo(
|
191
|
-
() =>
|
192
|
-
readOnly
|
193
|
-
? []
|
194
|
-
: buttons.map(button => {
|
195
|
-
if (button.id === 'save' && saveButtonLabel !== null) {
|
196
|
-
return {
|
197
|
-
...button,
|
198
|
-
label: saveButtonLabel,
|
199
|
-
};
|
200
|
-
}
|
201
|
-
if (button.id === 'cancel' && typeof button.onClick === 'undefined') {
|
202
|
-
return {
|
203
|
-
...button,
|
204
|
-
onClick: onClickCancel,
|
205
|
-
};
|
206
|
-
}
|
207
|
-
return button;
|
208
|
-
}),
|
209
|
-
[buttons, readOnly],
|
210
|
-
);
|
211
|
-
|
212
|
-
const submitForm = useCallback(() => {
|
213
|
-
const data = isTyped
|
214
|
-
? {
|
215
|
-
type: currentType !== null ? currentType.id : null,
|
216
|
-
...(formValue || item),
|
217
|
-
}
|
218
|
-
: formValue;
|
219
|
-
|
220
|
-
setFormSuccess(null);
|
221
|
-
|
222
|
-
return action === 'create'
|
223
|
-
? resourceApi.store(data)
|
224
|
-
: resourceApi.update(item.id, data || item);
|
225
|
-
}, [resourceApi, action, isTyped, currentType]);
|
226
|
-
|
227
|
-
const onFormChange = useCallback(value => {
|
228
|
-
setFormValue(value);
|
229
|
-
setFormSuccess(null);
|
230
|
-
}, []);
|
231
|
-
|
232
|
-
const onFormComplete = useCallback(
|
233
|
-
newItem => {
|
234
|
-
setItem(newItem);
|
235
|
-
setFormValue(null);
|
236
|
-
setFormErrors(null);
|
237
|
-
setFormSuccess(true);
|
238
|
-
if (customOnFormComplete !== null) {
|
239
|
-
customOnFormComplete(item);
|
240
|
-
}
|
241
|
-
},
|
242
|
-
[customOnFormComplete],
|
243
|
-
);
|
244
|
-
|
245
|
-
const onFormErrors = useCallback(error => {
|
246
|
-
const newErrors = getErrorsFromResponseError(error);
|
247
|
-
setFormErrors(newErrors);
|
248
|
-
setFormSuccess(false);
|
249
|
-
}, []);
|
250
|
-
|
251
|
-
// Get form definition
|
252
|
-
const { type: formType = null, fullscreen, className = null, ...formProps } = useMemo(() => {
|
253
|
-
const { fields = [], ...form } = resource.form(action);
|
254
|
-
let finalFields;
|
255
|
-
if (waitingItem) {
|
256
|
-
finalFields = null;
|
257
|
-
} else if (currentType !== null && isObject(fields)) {
|
258
|
-
finalFields = fields[currentType.id] || fields.default || fields;
|
259
|
-
} else {
|
260
|
-
finalFields = fields;
|
261
|
-
}
|
262
|
-
return {
|
263
|
-
type: 'normal',
|
264
|
-
fullscreen: false,
|
265
|
-
fields: finalFields,
|
266
|
-
...form,
|
267
|
-
};
|
268
|
-
}, [waitingItem, resource, currentType]);
|
269
|
-
|
270
|
-
const FormComponent = useComponent(formType, 'forms');
|
271
|
-
const form =
|
272
|
-
!waitingItem && FormComponent !== null ? (
|
273
|
-
<FormComponent
|
274
|
-
{...formProps}
|
275
|
-
className={classNames([
|
276
|
-
styles.form,
|
277
|
-
{
|
278
|
-
[className]: className !== null,
|
279
|
-
},
|
280
|
-
])}
|
281
|
-
readOnly={readOnly}
|
282
|
-
buttons={formButtons}
|
283
|
-
value={formValue || item}
|
284
|
-
errors={formErrors}
|
285
|
-
notice={
|
286
|
-
formSuccess !== null
|
287
|
-
? {
|
288
|
-
type: formSuccess ? 'success' : 'error',
|
289
|
-
label: formSuccess ? successNoticeLabel : errorNoticeLabel,
|
290
|
-
}
|
291
|
-
: null
|
292
|
-
}
|
293
|
-
submitForm={submitForm}
|
294
|
-
onChange={onFormChange}
|
295
|
-
onComplete={onFormComplete}
|
296
|
-
onErrors={onFormErrors}
|
297
|
-
/>
|
298
|
-
) : null;
|
299
|
-
|
300
|
-
const header = (
|
301
|
-
<ResourceFormHeader
|
302
|
-
resource={resource}
|
303
|
-
type={currentType}
|
304
|
-
action={action}
|
305
|
-
fullscreen={fullscreen}
|
306
|
-
valueHasChanged={formValue !== null}
|
307
|
-
title={title}
|
308
|
-
titleTyped={titleTyped}
|
309
|
-
/>
|
310
|
-
);
|
311
|
-
|
312
|
-
const errorsMessages =
|
313
|
-
errors !== null && errors.length > 0 ? (
|
314
|
-
<Errors errors={errors} className={styles.errors} />
|
315
|
-
) : null;
|
316
|
-
|
317
|
-
const content =
|
318
|
-
isLoading && item === null ? (
|
319
|
-
<div className={classNames(['py-4', styles.loading])}>
|
320
|
-
<Loading loading />
|
321
|
-
</div>
|
322
|
-
) : (
|
323
|
-
form
|
324
|
-
);
|
325
|
-
|
326
|
-
return (
|
327
|
-
<div
|
328
|
-
className={classNames([
|
329
|
-
styles.container,
|
330
|
-
{
|
331
|
-
[styles.isFullscreen]: fullscreen,
|
332
|
-
},
|
333
|
-
])}
|
334
|
-
>
|
335
|
-
{fullscreen ? (
|
336
|
-
<div className={classNames([styles.inner])}>
|
337
|
-
{header}
|
338
|
-
<div className={classNames([styles.content])}>
|
339
|
-
{errorsMessages}
|
340
|
-
{content}
|
341
|
-
</div>
|
342
|
-
</div>
|
343
|
-
) : (
|
344
|
-
<div className="container">
|
345
|
-
<div className="row justify-content-md-center">
|
346
|
-
<div className="col-lg-9">
|
347
|
-
{header}
|
348
|
-
{errorsMessages}
|
349
|
-
{content}
|
350
|
-
</div>
|
351
|
-
</div>
|
352
|
-
</div>
|
353
|
-
)}
|
354
|
-
</div>
|
355
|
-
);
|
356
|
-
};
|
357
|
-
|
358
|
-
ResourceForm.propTypes = propTypes;
|
359
|
-
ResourceForm.defaultProps = defaultProps;
|
360
|
-
|
361
|
-
export default ResourceForm;
|
@@ -1,256 +0,0 @@
|
|
1
|
-
/* eslint-disable jsx-a11y/anchor-is-valid, react/no-array-index-key, react/jsx-props-no-spreading */
|
2
|
-
import React, { useCallback, useEffect, useState } from 'react';
|
3
|
-
import PropTypes from 'prop-types';
|
4
|
-
import get from 'lodash/get';
|
5
|
-
import classNames from 'classnames';
|
6
|
-
import { defineMessages, injectIntl } from 'react-intl';
|
7
|
-
import { PropTypes as PanneauPropTypes, useResourceApi } from '@panneau/core';
|
8
|
-
import { isMessage } from '@panneau/core/utils';
|
9
|
-
import { useComponent } from '@panneau/core/contexts';
|
10
|
-
import { Loading, Errors } from '@panneau/core/components';
|
11
|
-
|
12
|
-
import ResourceIndexHeader from '../partials/ResourceIndexHeader';
|
13
|
-
|
14
|
-
import styles from '../../styles/pages/resource-index.scss';
|
15
|
-
|
16
|
-
const messages = defineMessages({
|
17
|
-
add: {
|
18
|
-
id: 'core.buttons.resources.add',
|
19
|
-
description: 'The label of the "add" index button',
|
20
|
-
defaultMessage: 'Add {name}',
|
21
|
-
},
|
22
|
-
title: {
|
23
|
-
id: 'core.titles.resources.index',
|
24
|
-
description: 'The title of the resource index page',
|
25
|
-
defaultMessage: '{name}',
|
26
|
-
},
|
27
|
-
confirmDelete: {
|
28
|
-
id: 'core.resources.index.confirm_delete',
|
29
|
-
description: 'The confirm message when deleting on the resource index page',
|
30
|
-
defaultMessage: 'Are you sure you want to delete this item from {name}?',
|
31
|
-
},
|
32
|
-
});
|
33
|
-
|
34
|
-
const propTypes = {
|
35
|
-
intl: PanneauPropTypes.intl.isRequired,
|
36
|
-
resource: PanneauPropTypes.resource.isRequired,
|
37
|
-
query: PropTypes.shape({
|
38
|
-
page: PropTypes.string,
|
39
|
-
}),
|
40
|
-
title: PanneauPropTypes.message,
|
41
|
-
showAddButton: PropTypes.bool,
|
42
|
-
addButtonLabel: PanneauPropTypes.message,
|
43
|
-
confirmDeleteMessage: PanneauPropTypes.message,
|
44
|
-
getResourceActionUrl: PropTypes.func.isRequired,
|
45
|
-
gotoResourceAction: PropTypes.func.isRequired,
|
46
|
-
};
|
47
|
-
|
48
|
-
const defaultProps = {
|
49
|
-
query: null,
|
50
|
-
title: messages.title,
|
51
|
-
showAddButton: true,
|
52
|
-
addButtonLabel: messages.add,
|
53
|
-
confirmDeleteMessage: messages.confirmDelete,
|
54
|
-
};
|
55
|
-
|
56
|
-
const ResourceIndex = ({
|
57
|
-
intl,
|
58
|
-
resource,
|
59
|
-
query,
|
60
|
-
title,
|
61
|
-
addButtonLabel,
|
62
|
-
confirmDeleteMessage,
|
63
|
-
getResourceActionUrl,
|
64
|
-
gotoResourceAction,
|
65
|
-
showAddButton,
|
66
|
-
}) => {
|
67
|
-
const [request, setRequest] = useState({
|
68
|
-
isLoading: false,
|
69
|
-
query: null,
|
70
|
-
items: null,
|
71
|
-
errors: null,
|
72
|
-
pagination: null,
|
73
|
-
});
|
74
|
-
const resourceApi = useResourceApi(resource);
|
75
|
-
const { isLoading, items, pagination, errors } = request;
|
76
|
-
const { type: listType, pagination: hasPagination = false, ...listProps } = resource.list(
|
77
|
-
'index',
|
78
|
-
);
|
79
|
-
|
80
|
-
useEffect(() => {
|
81
|
-
if (isLoading) {
|
82
|
-
return null;
|
83
|
-
}
|
84
|
-
let canceled = false;
|
85
|
-
const onItemsLoaded = data => {
|
86
|
-
if (canceled) {
|
87
|
-
return;
|
88
|
-
}
|
89
|
-
if (hasPagination) {
|
90
|
-
const { data: newItems, ...newPagination } = data;
|
91
|
-
setRequest({
|
92
|
-
...request,
|
93
|
-
items: newItems,
|
94
|
-
pagination: newPagination,
|
95
|
-
isLoading: false,
|
96
|
-
});
|
97
|
-
return;
|
98
|
-
}
|
99
|
-
setRequest({
|
100
|
-
...request,
|
101
|
-
items: data,
|
102
|
-
isLoading: false,
|
103
|
-
});
|
104
|
-
};
|
105
|
-
|
106
|
-
const onItemsLoadError = newErrors => {
|
107
|
-
if (canceled) {
|
108
|
-
return;
|
109
|
-
}
|
110
|
-
setRequest({
|
111
|
-
...request,
|
112
|
-
errors: newErrors,
|
113
|
-
isLoading: false,
|
114
|
-
});
|
115
|
-
};
|
116
|
-
|
117
|
-
const { page = null } = query || {};
|
118
|
-
const params = {};
|
119
|
-
if (hasPagination && page !== null) {
|
120
|
-
params.page = page;
|
121
|
-
}
|
122
|
-
resourceApi
|
123
|
-
.index(params)
|
124
|
-
.then(onItemsLoaded)
|
125
|
-
.catch(onItemsLoadError);
|
126
|
-
|
127
|
-
setRequest({
|
128
|
-
...request,
|
129
|
-
isLoading: true,
|
130
|
-
});
|
131
|
-
|
132
|
-
return () => {
|
133
|
-
canceled = true;
|
134
|
-
};
|
135
|
-
}, [query, hasPagination]);
|
136
|
-
|
137
|
-
const deleteItem = useCallback(
|
138
|
-
id => {
|
139
|
-
const onItemDeleted = ({ id: itemId }) => {
|
140
|
-
setRequest({
|
141
|
-
...request,
|
142
|
-
items: items.filter(it => it.id !== itemId),
|
143
|
-
});
|
144
|
-
};
|
145
|
-
|
146
|
-
const { name } = resource;
|
147
|
-
const confirmMessage = resource.message('confirm_delete', confirmDeleteMessage);
|
148
|
-
const message = isMessage(confirmMessage)
|
149
|
-
? intl.formatMessage(confirmMessage, {
|
150
|
-
name,
|
151
|
-
id,
|
152
|
-
})
|
153
|
-
: confirmMessage;
|
154
|
-
// eslint-disable-next-line no-alert
|
155
|
-
if (window.confirm(message)) {
|
156
|
-
resourceApi.destroy(id).then(onItemDeleted);
|
157
|
-
}
|
158
|
-
},
|
159
|
-
[resource, request],
|
160
|
-
);
|
161
|
-
|
162
|
-
const onClickAction = useCallback(
|
163
|
-
(e, action, it) => {
|
164
|
-
const useRouter = get(action, 'useRouter', true);
|
165
|
-
|
166
|
-
switch (action.id) {
|
167
|
-
case 'edit':
|
168
|
-
case 'show':
|
169
|
-
if (useRouter) {
|
170
|
-
gotoResourceAction(action.id, it.id);
|
171
|
-
} else {
|
172
|
-
window.location.href = getResourceActionUrl(action.id);
|
173
|
-
}
|
174
|
-
break;
|
175
|
-
case 'delete': {
|
176
|
-
const hasPage = get(action, 'hasPage', false);
|
177
|
-
if (!hasPage) {
|
178
|
-
deleteItem(it.id);
|
179
|
-
} else if (useRouter) {
|
180
|
-
gotoResourceAction(action.id, it.id);
|
181
|
-
} else {
|
182
|
-
window.location.href = getResourceActionUrl(action.id);
|
183
|
-
}
|
184
|
-
break;
|
185
|
-
}
|
186
|
-
default:
|
187
|
-
break;
|
188
|
-
}
|
189
|
-
},
|
190
|
-
[deleteItem, gotoResourceAction, getResourceActionUrl],
|
191
|
-
);
|
192
|
-
|
193
|
-
// Components
|
194
|
-
const ListComponent = useComponent(listType || 'table', 'lists');
|
195
|
-
const Pagination = useComponent('pagination', 'lists');
|
196
|
-
|
197
|
-
return (
|
198
|
-
<div className={classNames([styles.container])}>
|
199
|
-
<div className="container">
|
200
|
-
<div className="row justify-content-md-center">
|
201
|
-
<div className="col-lg-8">
|
202
|
-
<ResourceIndexHeader
|
203
|
-
resource={resource}
|
204
|
-
title={title}
|
205
|
-
addButtonLabel={addButtonLabel}
|
206
|
-
showAddButton={showAddButton}
|
207
|
-
getResourceActionUrl={getResourceActionUrl}
|
208
|
-
/>
|
209
|
-
<div className={styles.listContainer}>
|
210
|
-
<Errors errors={errors} />
|
211
|
-
<div className={styles.list}>
|
212
|
-
{items !== null && ListComponent !== null ? (
|
213
|
-
<div className={styles.list}>
|
214
|
-
<ListComponent
|
215
|
-
{...listProps}
|
216
|
-
items={items || []}
|
217
|
-
onClickAction={onClickAction}
|
218
|
-
/>
|
219
|
-
</div>
|
220
|
-
) : null}
|
221
|
-
</div>
|
222
|
-
{isLoading ? (
|
223
|
-
<div
|
224
|
-
className={classNames({
|
225
|
-
[styles.loading]: true,
|
226
|
-
[styles.alone]: items === null,
|
227
|
-
})}
|
228
|
-
>
|
229
|
-
<div className={styles.inner}>
|
230
|
-
<div className={styles.middle}>
|
231
|
-
<Loading loading />
|
232
|
-
</div>
|
233
|
-
</div>
|
234
|
-
</div>
|
235
|
-
) : null}
|
236
|
-
</div>
|
237
|
-
{pagination !== null && pagination.last_page > 1 ? (
|
238
|
-
<Pagination
|
239
|
-
total={pagination.total}
|
240
|
-
perPage={pagination.per_page}
|
241
|
-
currentPage={pagination.current_page}
|
242
|
-
lastPage={pagination.last_page}
|
243
|
-
url={getResourceActionUrl('index')}
|
244
|
-
/>
|
245
|
-
) : null}
|
246
|
-
</div>
|
247
|
-
</div>
|
248
|
-
</div>
|
249
|
-
</div>
|
250
|
-
);
|
251
|
-
};
|
252
|
-
|
253
|
-
ResourceIndex.propTypes = propTypes;
|
254
|
-
ResourceIndex.defaultProps = defaultProps;
|
255
|
-
|
256
|
-
export default injectIntl(ResourceIndex);
|
@@ -1,23 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
|
3
|
-
import ResourceForm from './ResourceForm';
|
4
|
-
|
5
|
-
const propTypes = {
|
6
|
-
|
7
|
-
};
|
8
|
-
|
9
|
-
const defaultProps = {
|
10
|
-
|
11
|
-
};
|
12
|
-
|
13
|
-
const ResourceShow = props => (
|
14
|
-
<ResourceForm
|
15
|
-
readOnly
|
16
|
-
{...props}
|
17
|
-
/>
|
18
|
-
);
|
19
|
-
|
20
|
-
ResourceShow.propTypes = propTypes;
|
21
|
-
ResourceShow.defaultProps = defaultProps;
|
22
|
-
|
23
|
-
export default ResourceShow;
|