@steroidsjs/core 3.0.69 → 3.0.71
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/actions/list.d.ts +2 -3
- package/actions/list.js +84 -72
- package/package.json +1 -1
- package/ui/form/FieldList/FieldList.js +24 -4
package/actions/list.d.ts
CHANGED
|
@@ -111,10 +111,9 @@ export declare const LIST_TOGGLE_ALL = "@list/toggle_all";
|
|
|
111
111
|
export declare const LIST_SET_LAYOUT = "@list/set_layout";
|
|
112
112
|
export declare const LIST_CHANGE_ACTION = "@list/change_action";
|
|
113
113
|
export declare const LIST_SELECT_ITEM = "@list/select_item";
|
|
114
|
-
export declare const httpFetchHandler: (list: IList, query: any, { http
|
|
114
|
+
export declare const httpFetchHandler: (list: IList, query: any, { http }: {
|
|
115
115
|
http: any;
|
|
116
|
-
|
|
117
|
-
}) => any;
|
|
116
|
+
}, options?: any) => any;
|
|
118
117
|
export declare const localFetchHandler: (list: IList, query: Record<string, unknown>) => {
|
|
119
118
|
items: any[];
|
|
120
119
|
total: number;
|
package/actions/list.js
CHANGED
|
@@ -62,17 +62,16 @@ var createList = function (listId, props) { return ({
|
|
|
62
62
|
sortAttribute: (0, get_1["default"])(props, '_sort.attribute') || null,
|
|
63
63
|
layoutAttribute: (0, get_1["default"])(props, '_layout.attribute') || null
|
|
64
64
|
}); };
|
|
65
|
-
var httpFetchHandler = function (list, query, _a) {
|
|
66
|
-
var http = _a.http
|
|
65
|
+
var httpFetchHandler = function (list, query, _a, options) {
|
|
66
|
+
var http = _a.http;
|
|
67
|
+
if (options === void 0) { options = {}; }
|
|
67
68
|
var url = list.action;
|
|
68
69
|
if (list.scope) {
|
|
69
|
-
url
|
|
70
|
-
+= (url.indexOf('?') !== -1 ? '&' : '?') + 'scope=' + list.scope.join(',');
|
|
70
|
+
url += (url.indexOf('?') !== -1 ? '&' : '?') + 'scope=' + list.scope.join(',');
|
|
71
71
|
}
|
|
72
|
+
// options поддерживает { cancelToken } или { signal } (если использовать AbortController)
|
|
72
73
|
return http
|
|
73
|
-
.send(list.actionMethod, url || window.location.pathname, query,
|
|
74
|
-
cancelToken: httpCancelToken
|
|
75
|
-
})
|
|
74
|
+
.send(list.actionMethod, url || window.location.pathname, query, options)
|
|
76
75
|
.then(function (response) { return response.data; })["catch"](function (error) {
|
|
77
76
|
if (typeof list.onError === 'function') {
|
|
78
77
|
list.onError(error);
|
|
@@ -155,7 +154,6 @@ var listChangeAction = function (listId, action) { return ({
|
|
|
155
154
|
action: action
|
|
156
155
|
}); };
|
|
157
156
|
exports.listChangeAction = listChangeAction;
|
|
158
|
-
var _cancelSourceByList = new Map();
|
|
159
157
|
/**
|
|
160
158
|
* Update query values and send request
|
|
161
159
|
* @param listId
|
|
@@ -180,77 +178,91 @@ var listFetch = function (listId, query) {
|
|
|
180
178
|
formValues[key] = query[key];
|
|
181
179
|
toDispatch.push((0, form_2.formChange)(list.formId, key, query[key]));
|
|
182
180
|
});
|
|
181
|
+
// Отменяем предыдущий запрос для этого listId (если есть)
|
|
182
|
+
components.http._promises = components.http._promises || {};
|
|
183
|
+
var prev = components.http._promises[listId];
|
|
184
|
+
if (prev && typeof prev.cancel === 'function') {
|
|
185
|
+
// для axios.CancelToken.source()
|
|
186
|
+
prev.cancel('Cancelled by new request for list ' + listId);
|
|
187
|
+
}
|
|
188
|
+
else if (prev && typeof prev.abort === 'function') {
|
|
189
|
+
// для AbortController
|
|
190
|
+
prev.abort();
|
|
191
|
+
}
|
|
192
|
+
// Создаем новый источник отмены
|
|
193
|
+
var source = axios_1["default"].CancelToken.source();
|
|
194
|
+
components.http._promises[listId] = source;
|
|
195
|
+
var options = { cancelToken: source.token };
|
|
196
|
+
// Set `Loading...`
|
|
183
197
|
if (list.isRemote) {
|
|
184
|
-
// Set `Loading...`
|
|
185
198
|
toDispatch.push({
|
|
186
199
|
listId: listId,
|
|
187
200
|
type: exports.LIST_BEFORE_FETCH
|
|
188
201
|
});
|
|
189
202
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
203
|
+
toDispatch.push([
|
|
204
|
+
Promise.resolve(onFetch(list, formValues, components, options))
|
|
205
|
+
.then(function (data) {
|
|
206
|
+
var _a;
|
|
207
|
+
// Skip on empty
|
|
208
|
+
if (!data) {
|
|
209
|
+
return [];
|
|
210
|
+
}
|
|
211
|
+
// Check list is not destroy
|
|
212
|
+
if (!getState().list.lists[listId]) {
|
|
213
|
+
return [];
|
|
214
|
+
}
|
|
215
|
+
if ((0, isArray_1["default"])(data)) {
|
|
216
|
+
data = {
|
|
217
|
+
items: data,
|
|
218
|
+
total: data.length,
|
|
219
|
+
meta: null
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
var items = data.items || [];
|
|
223
|
+
var total = data.total || items.length || null;
|
|
224
|
+
var page = formValues[list.pageAttribute];
|
|
225
|
+
var pageSize = formValues[list.pageSizeAttribute];
|
|
226
|
+
var totalPages = Math.ceil(((list === null || list === void 0 ? void 0 : list.total) || 0) / (pageSize || 1));
|
|
227
|
+
var hasNextPage = (_a = data === null || data === void 0 ? void 0 : data.hasNextPage) !== null && _a !== void 0 ? _a : (page !== totalPages || null);
|
|
228
|
+
return [
|
|
229
|
+
(0, form_2.formSetErrors)(list.formId, data.errors || null),
|
|
230
|
+
{
|
|
231
|
+
items: items,
|
|
232
|
+
total: total,
|
|
233
|
+
hasNextPage: hasNextPage,
|
|
234
|
+
meta: data.meta || null,
|
|
235
|
+
page: page,
|
|
236
|
+
pageSize: pageSize,
|
|
237
|
+
listId: listId,
|
|
238
|
+
defaultPageValue: list.defaultPageValue,
|
|
239
|
+
type: exports.LIST_AFTER_FETCH
|
|
240
|
+
},
|
|
241
|
+
];
|
|
242
|
+
})["catch"](function (error) {
|
|
243
|
+
// Если это отмена — просто игнорируем ошибку
|
|
244
|
+
if (axios_1["default"].isCancel && axios_1["default"].isCancel(error)) {
|
|
245
|
+
return [];
|
|
246
|
+
}
|
|
247
|
+
// Handle cancellation quietly
|
|
248
|
+
// axios v0.x: axios.isCancel(error)
|
|
249
|
+
var isAxiosCancel = typeof axios_1["default"].isCancel === 'function' && axios_1["default"].isCancel(error);
|
|
250
|
+
if (isAxiosCancel) {
|
|
251
|
+
// игнорируем, это отмена запроса
|
|
252
|
+
return [];
|
|
253
|
+
}
|
|
254
|
+
// прочие ошибки — можно пробросить или обработать
|
|
255
|
+
if (typeof list.onError === 'function') {
|
|
256
|
+
list.onError(error);
|
|
257
|
+
}
|
|
210
258
|
return [];
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
items: data,
|
|
219
|
-
total: data.length,
|
|
220
|
-
meta: null
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
var items = data.items || [];
|
|
224
|
-
var total = data.total || items.length || null;
|
|
225
|
-
var page = formValues[list.pageAttribute];
|
|
226
|
-
var pageSize = formValues[list.pageSizeAttribute];
|
|
227
|
-
var totalPages = Math.ceil(((list === null || list === void 0 ? void 0 : list.total) || 0) / (pageSize || 1));
|
|
228
|
-
var hasNextPage = (_a = data === null || data === void 0 ? void 0 : data.hasNextPage) !== null && _a !== void 0 ? _a : (page !== totalPages || null);
|
|
229
|
-
return [
|
|
230
|
-
(0, form_2.formSetErrors)(list.formId, data.errors || null),
|
|
231
|
-
{
|
|
232
|
-
items: items,
|
|
233
|
-
total: total,
|
|
234
|
-
hasNextPage: hasNextPage,
|
|
235
|
-
meta: data.meta || null,
|
|
236
|
-
page: page,
|
|
237
|
-
pageSize: pageSize,
|
|
238
|
-
listId: listId,
|
|
239
|
-
defaultPageValue: list.defaultPageValue,
|
|
240
|
-
type: exports.LIST_AFTER_FETCH
|
|
241
|
-
},
|
|
242
|
-
];
|
|
243
|
-
})["catch"](function (err) {
|
|
244
|
-
// Если это отмена через axios, просто игнорируем
|
|
245
|
-
_cancelSourceByList["delete"](listId);
|
|
246
|
-
// Если нужно — можно выставить ошибку формы или диспатчить событие
|
|
247
|
-
if (!axios_1["default"].isCancel(err)) {
|
|
248
|
-
// передаём ошибку дальше — если нужна стандартная обработка
|
|
249
|
-
throw err;
|
|
250
|
-
}
|
|
251
|
-
// при отмене просто возвращаем пустой массив действий
|
|
252
|
-
return [];
|
|
253
|
-
}));
|
|
259
|
+
})["finally"](function () {
|
|
260
|
+
// убрать сохранённый источник если он тот же
|
|
261
|
+
if (components.http._promises[listId] === source) {
|
|
262
|
+
delete components.http._promises[listId];
|
|
263
|
+
}
|
|
264
|
+
}),
|
|
265
|
+
]);
|
|
254
266
|
return dispatch(toDispatch);
|
|
255
267
|
};
|
|
256
268
|
};
|
package/package.json
CHANGED
|
@@ -53,6 +53,9 @@ var range_1 = __importDefault(require("lodash-es/range"));
|
|
|
53
53
|
var isEmpty_1 = __importDefault(require("lodash-es/isEmpty"));
|
|
54
54
|
var concat_1 = __importDefault(require("lodash-es/concat"));
|
|
55
55
|
var get_1 = __importDefault(require("lodash-es/get"));
|
|
56
|
+
var omit_1 = __importDefault(require("lodash-es/omit"));
|
|
57
|
+
var values_1 = __importDefault(require("lodash-es/values"));
|
|
58
|
+
var zipObject_1 = __importDefault(require("lodash-es/zipObject"));
|
|
56
59
|
var react_use_1 = require("react-use");
|
|
57
60
|
var hooks_1 = require("../../../hooks");
|
|
58
61
|
var Form_1 = require("../../form/Form/Form");
|
|
@@ -66,7 +69,7 @@ function FieldList(props) {
|
|
|
66
69
|
var context = (0, react_1.useContext)(Form_1.FormContext);
|
|
67
70
|
// Resolve model
|
|
68
71
|
var modelAttributes = (_a = components.meta.getModel(props.model)) === null || _a === void 0 ? void 0 : _a.attributes;
|
|
69
|
-
var
|
|
72
|
+
var reduxFormValues = (0, hooks_1.useSelector)(function (state) { return (0, get_1["default"])(state, ['form', context.formId]) || null; });
|
|
70
73
|
var dispatch = context.provider.useDispatch();
|
|
71
74
|
// Mapper for preserving the correct sequence of rows on the UI
|
|
72
75
|
var _b = (0, react_1.useState)((0, range_1["default"])(props.input.value) || []), storeToRowIndexMap = _b[0], setStoreToRowIndexMap = _b[1];
|
|
@@ -86,9 +89,26 @@ function FieldList(props) {
|
|
|
86
89
|
dispatch((0, form_1.formArrayAdd)(context.formId, props.input.name, rowsCount, props.initialValues));
|
|
87
90
|
}, [addRowIndexes, context.formId, dispatch, props.initialValues, props.input.name]);
|
|
88
91
|
var onRemove = (0, react_1.useCallback)(function (rowIndex) {
|
|
92
|
+
var _a;
|
|
89
93
|
removeRowIndex(rowIndex);
|
|
90
|
-
|
|
91
|
-
|
|
94
|
+
var actions = [
|
|
95
|
+
(0, form_1.formArrayRemove)(context.formId, props.input.name, rowIndex),
|
|
96
|
+
];
|
|
97
|
+
var listErrors = (0, get_1["default"])(reduxFormValues === null || reduxFormValues === void 0 ? void 0 : reduxFormValues.errors, props.input.name);
|
|
98
|
+
if (!(0, isEmpty_1["default"])(listErrors)) {
|
|
99
|
+
/**
|
|
100
|
+
* После удаления строки, удаляет соответствующую этой строке ошибку
|
|
101
|
+
* и обновляет индексы для последующих элементов
|
|
102
|
+
*/
|
|
103
|
+
var errorsWithoutRemoved = (0, omit_1["default"])(listErrors, String(rowIndex));
|
|
104
|
+
var errorsArray = (0, values_1["default"])(errorsWithoutRemoved);
|
|
105
|
+
var errorsForList = (0, zipObject_1["default"])((0, range_1["default"])(errorsArray.length), errorsArray);
|
|
106
|
+
var newTotalErrors = __assign(__assign({}, reduxFormValues.errors), (_a = {}, _a[props.input.name] = errorsForList, _a));
|
|
107
|
+
// @ts-ignore
|
|
108
|
+
actions.push((0, form_1.formSetErrors)(context.formId, newTotalErrors));
|
|
109
|
+
}
|
|
110
|
+
dispatch(actions);
|
|
111
|
+
}, [context.formId, dispatch, reduxFormValues === null || reduxFormValues === void 0 ? void 0 : reduxFormValues.errors, props.input.name, removeRowIndex]);
|
|
92
112
|
(0, react_use_1.useMount)(function () {
|
|
93
113
|
// Add initial rows
|
|
94
114
|
if (!props.input.value) {
|
|
@@ -140,7 +160,7 @@ function FieldList(props) {
|
|
|
140
160
|
var FieldListView = props.view || components.ui.getView('form.FieldListView');
|
|
141
161
|
var FieldListItemView = props.itemView || components.ui.getView('form.FieldListItemView');
|
|
142
162
|
return (react_1["default"].createElement(Form_1.FormContext.Provider, { value: contextValue },
|
|
143
|
-
react_1["default"].createElement(FieldListView, __assign({}, viewProps), !(0, isEmpty_1["default"])(storeToRowIndexMap) && (0, range_1["default"])(props.input.value || 0).map(function (index) { return (react_1["default"].createElement(FieldListItemView, __assign({}, itemViewProps, { key:
|
|
163
|
+
react_1["default"].createElement(FieldListView, __assign({}, viewProps), !(0, isEmpty_1["default"])(storeToRowIndexMap) && (0, range_1["default"])(props.input.value || 0).map(function (index) { return (react_1["default"].createElement(FieldListItemView, __assign({}, itemViewProps, { key: reduxFormValues ? storeToRowIndexMap[index] : index, prefix: props.input.name + '.' + index, rowIndex: index }))); }))));
|
|
144
164
|
}
|
|
145
165
|
FieldList.defaultProps = {
|
|
146
166
|
initialValues: null,
|