@steroidsjs/core 2.2.29 → 2.2.32

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.
@@ -1,5 +1,11 @@
1
1
  export declare const FIELDS_SET_META = "FIELDS_SET_META";
2
+ export declare const FIELDS_DATA_PROVIDER_SET_ITEMS = "@fields/data_provider_set_items";
2
3
  export declare const setMeta: (meta: any) => {
3
4
  type: string;
4
5
  meta: any;
5
6
  };
7
+ export declare const fieldsDataProviderSetItems: (dataProviderId: any, items: any) => {
8
+ type: string;
9
+ dataProviderId: any;
10
+ items: any;
11
+ };
package/actions/fields.js CHANGED
@@ -1,9 +1,16 @@
1
1
  "use strict";
2
2
  exports.__esModule = true;
3
- exports.setMeta = exports.FIELDS_SET_META = void 0;
3
+ exports.fieldsDataProviderSetItems = exports.setMeta = exports.FIELDS_DATA_PROVIDER_SET_ITEMS = exports.FIELDS_SET_META = void 0;
4
4
  exports.FIELDS_SET_META = 'FIELDS_SET_META';
5
+ exports.FIELDS_DATA_PROVIDER_SET_ITEMS = '@fields/data_provider_set_items';
5
6
  var setMeta = function (meta) { return ({
6
7
  type: exports.FIELDS_SET_META,
7
8
  meta: meta
8
9
  }); };
9
10
  exports.setMeta = setMeta;
11
+ var fieldsDataProviderSetItems = function (dataProviderId, items) { return ({
12
+ type: exports.FIELDS_DATA_PROVIDER_SET_ITEMS,
13
+ dataProviderId: dataProviderId,
14
+ items: items
15
+ }); };
16
+ exports.fieldsDataProviderSetItems = fieldsDataProviderSetItems;
@@ -35,6 +35,12 @@ export interface IDataProviderConfig {
35
35
  * Если dataProvider не передан, то поиск данных по запросу происходит локально.
36
36
  */
37
37
  dataProvider?: {
38
+ /**
39
+ * Уникальный (глобально) идентификатор, под которых будут храниться
40
+ * подгруженные данные в redux (при включенном флаге useRedux). Если
41
+ * не задан - данные будут храниться в локальном стейте
42
+ */
43
+ reduxId?: string;
38
44
  /**
39
45
  * URL для подгрузки новой коллекции данных
40
46
  * @example '/api/v1/search'
@@ -56,9 +56,10 @@ var isFunction_1 = __importDefault(require("lodash-es/isFunction"));
56
56
  var isEqual_1 = __importDefault(require("lodash-es/isEqual"));
57
57
  var react_1 = require("react");
58
58
  var react_use_1 = require("react-use");
59
+ var fields_1 = require("../actions/fields");
59
60
  var data_1 = require("../utils/data");
60
61
  var index_1 = require("./index");
61
- var fields_1 = require("../reducers/fields");
62
+ var fields_2 = require("../reducers/fields");
62
63
  var text_1 = require("../utils/text");
63
64
  var defaultProps = {
64
65
  autoComplete: {
@@ -75,15 +76,29 @@ var defaultProps = {
75
76
  */
76
77
  function useDataProvider(config) {
77
78
  var _this = this;
79
+ var _a;
78
80
  var components = index_1.useComponents();
81
+ var dispatch = index_1.useDispatch();
82
+ var reduxDataProviderId = (_a = config.dataProvider) === null || _a === void 0 ? void 0 : _a.reduxId;
79
83
  // Check enum
80
- var enumItems = react_redux_1.useSelector(function (state) { return isString_1["default"](config.items) ? fields_1.getEnumLabels(state, config.items) : null; });
84
+ var enumItems = react_redux_1.useSelector(function (state) { return isString_1["default"](config.items) ? fields_2.getEnumLabels(state, config.items) : null; });
81
85
  // Initial items
82
86
  var initialItems = data_1.normalizeItems(enumItems || config.items);
83
87
  // Items state
84
- var _a = react_1.useState(initialItems), sourceItems = _a[0], setSourceItems = _a[1];
85
88
  var _b = react_1.useState(initialItems), items = _b[0], setItems = _b[1];
86
89
  var _c = react_1.useState(false), isLoading = _c[0], setIsLoading = _c[1];
90
+ // Source items state (redux or local)
91
+ var _d = react_1.useState(initialItems), sourceInternalItems = _d[0], setSourceInternalItems = _d[1];
92
+ var sourceReduxItems = react_redux_1.useSelector(function (state) { return fields_2.getDataProviderItems(state, reduxDataProviderId); });
93
+ var sourceItems = reduxDataProviderId ? sourceReduxItems : sourceInternalItems;
94
+ var setSourceItems = react_1.useCallback(function (value) {
95
+ if (reduxDataProviderId) {
96
+ dispatch(fields_1.fieldsDataProviderSetItems(reduxDataProviderId, value));
97
+ }
98
+ else {
99
+ setSourceInternalItems(value);
100
+ }
101
+ }, [reduxDataProviderId, dispatch]);
87
102
  // Normalize autoComplete
88
103
  var autoComplete = react_1.useMemo(function () { return (__assign(__assign({}, defaultProps.autoComplete), (typeof config.autoComplete === 'boolean') ? { enable: config.autoComplete } : config.autoComplete)); }, [config.autoComplete]);
89
104
  var dataProvider = react_1.useMemo(function () { return (__assign({ action: '', actionMethod: 'get', params: null, onSearch: null }, config.dataProvider)); }, [config.dataProvider]);
@@ -143,7 +158,7 @@ function useDataProvider(config) {
143
158
  delayTimerRef.current = setTimeout(fetchRemote, autoComplete.delay);
144
159
  }
145
160
  }
146
- }, [autoComplete, components.api, components.http, config.autoFetch, config.dataProvider, config.initialSelectedIds, config.query, dataProvider, dataProvider.action, dataProvider.onSearch, prevQuery, sourceItems]);
161
+ }, [autoComplete, components.api, components.http, config.autoFetch, config.dataProvider, config.initialSelectedIds, config.query, dataProvider, dataProvider.action, dataProvider.onSearch, prevParams, prevQuery, prevValues, setSourceItems, sourceItems]);
147
162
  return {
148
163
  sourceItems: sourceItems,
149
164
  items: items,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@steroidsjs/core",
3
- "version": "2.2.29",
3
+ "version": "2.2.32",
4
4
  "description": "",
5
5
  "author": "Vladimir Kozhin <hello@kozhindev.com>",
6
6
  "repository": {
@@ -1,11 +1,14 @@
1
1
  declare const _default: (state: {
2
2
  props: {};
3
+ dataProvider: {};
3
4
  meta: any;
4
5
  }, action: any) => {
5
6
  props: {};
7
+ dataProvider: {};
6
8
  meta: any;
7
9
  };
8
10
  export default _default;
9
11
  export declare const isMetaFetched: (state: any) => boolean;
10
12
  export declare const getEnumLabels: (state: any, name: any) => any;
11
13
  export declare const getModel: (state: any, name: any) => any;
14
+ export declare const getDataProviderItems: (state: any, dataProviderId: any) => any;
@@ -14,16 +14,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
14
14
  return (mod && mod.__esModule) ? mod : { "default": mod };
15
15
  };
16
16
  exports.__esModule = true;
17
- exports.getModel = exports.getEnumLabels = exports.isMetaFetched = void 0;
17
+ exports.getDataProviderItems = exports.getModel = exports.getEnumLabels = exports.isMetaFetched = void 0;
18
18
  var isString_1 = __importDefault(require("lodash-es/isString"));
19
19
  var get_1 = __importDefault(require("lodash-es/get"));
20
20
  var fields_1 = require("../actions/fields");
21
21
  var initialState = {
22
22
  props: {},
23
+ dataProvider: {},
23
24
  meta: null
24
25
  };
25
26
  var normalizeName = function (name) { return name.replace(/\\/g, '.').replace(/^\./, ''); };
26
27
  exports["default"] = (function (state, action) {
28
+ var _a;
27
29
  if (state === void 0) { state = initialState; }
28
30
  switch (action.type) {
29
31
  case fields_1.FIELDS_SET_META:
@@ -31,6 +33,8 @@ exports["default"] = (function (state, action) {
31
33
  action.meta[name].className = name;
32
34
  });
33
35
  return __assign(__assign({}, state), { meta: __assign(__assign({}, state.meta), action.meta) });
36
+ case fields_1.FIELDS_DATA_PROVIDER_SET_ITEMS:
37
+ return __assign(__assign({}, state), { dataProvider: __assign(__assign({}, state.dataProvider), (_a = {}, _a[action.dataProviderId] = action.items, _a)) });
34
38
  default:
35
39
  return state;
36
40
  }
@@ -53,3 +57,5 @@ var getModel = function (state, name) {
53
57
  return name || null;
54
58
  };
55
59
  exports.getModel = getModel;
60
+ var getDataProviderItems = function (state, dataProviderId) { var _a, _b; return ((_b = (_a = state === null || state === void 0 ? void 0 : state.fields) === null || _a === void 0 ? void 0 : _a.dataProvider) === null || _b === void 0 ? void 0 : _b[dataProviderId]) || null; };
61
+ exports.getDataProviderItems = getDataProviderItems;
@@ -46,6 +46,7 @@ export interface IFieldWrapperInputProps {
46
46
  * @example 'horizontal'
47
47
  */
48
48
  layout?: FormLayout;
49
+ value?: any;
49
50
  onChange?: (...args: any[]) => any;
50
51
  /**
51
52
  * Ошибки в поле
@@ -46,8 +46,9 @@ var createDynamicField = function (componentId, Component, options) {
46
46
  var DynamicField = function (props) {
47
47
  var components = hooks_1.useComponents();
48
48
  // Get context, formId
49
- var context = react_1.useContext(Form_1.FormContext);
50
- var formId = props.formId || (context === null || context === void 0 ? void 0 : context.formId) || null;
49
+ // eslint-disable-next-line react-hooks/rules-of-hooks
50
+ var context = props.formId !== false ? react_1.useContext(Form_1.FormContext) : null;
51
+ var formId = props.formId || props.formId === false ? props.formId : ((context === null || context === void 0 ? void 0 : context.formId) || null);
51
52
  var model = props.model || (context === null || context === void 0 ? void 0 : context.model) || null;
52
53
  // Result wrapper props
53
54
  var wrapperProps = {
@@ -61,11 +62,32 @@ var createDynamicField = function (componentId, Component, options) {
61
62
  // Get full name (attribute with prefix)
62
63
  var name = [props.prefix, props[attributeKey]].filter(Boolean).join('.');
63
64
  // Register field
64
- components.ui.registerField(formId, name, componentId);
65
- // Resolve data provider
66
- var _a = (context === null || context === void 0 ? void 0 : context.provider)
67
- ? context === null || context === void 0 ? void 0 : context.provider.useField(formId, name, options.list)
68
- : form_1.providers.state.useField(props.value), errors = _a.errors, value = _a.value, setValue = _a.setValue;
65
+ if (formId) {
66
+ components.ui.registerField(formId, name, componentId);
67
+ }
68
+ var errors;
69
+ var value;
70
+ var setValue;
71
+ if (context === null || context === void 0 ? void 0 : context.provider) {
72
+ // Resolve data provider
73
+ var providerResult = context === null || context === void 0 ? void 0 : context.provider.useField(formId, name, options.list);
74
+ errors = providerResult.errors;
75
+ value = providerResult.value;
76
+ setValue = providerResult.setValue;
77
+ }
78
+ else if (has_1["default"](props, 'value') && has_1["default"](props, 'onChange')) {
79
+ // Controlled component via props
80
+ errors = null;
81
+ value = props.value;
82
+ setValue = props.onChange;
83
+ }
84
+ else {
85
+ // Uncontrolled component
86
+ var stateResult = form_1.providers.state.useField(props.value);
87
+ errors = stateResult.errors;
88
+ value = stateResult.value;
89
+ setValue = stateResult.setValue;
90
+ }
69
91
  // Set errors
70
92
  wrapperProps[errorsKey] = errors;
71
93
  // Input object
@@ -158,7 +158,7 @@ function Form(props) {
158
158
  var onSubmit = react_1.useCallback(function (e) {
159
159
  if (e === void 0) { e = null; }
160
160
  return __awaiter(_this, void 0, void 0, function () {
161
- var cleanedValues, captchaAttribute, googleCaptcha, captchaToken, options, response, _a, data;
161
+ var cleanedValues, submitResult, captchaAttribute, googleCaptcha, captchaToken, options, response, _a, data;
162
162
  var _b;
163
163
  var _this = this;
164
164
  return __generator(this, function (_c) {
@@ -181,14 +181,19 @@ function Form(props) {
181
181
  cleanedValues = form_1.cleanEmptyObject(values);
182
182
  // Event onBeforeSubmit
183
183
  if (props.onBeforeSubmit && props.onBeforeSubmit.call(null, cleanedValues) === false) {
184
+ dispatch(form_2.formSetSubmitting(props.formId, false));
184
185
  return [2 /*return*/, null];
185
186
  }
186
187
  if (props.validators) {
187
188
  validate_1["default"](cleanedValues, props.validators);
188
189
  }
189
- if (props.onSubmit) {
190
- return [2 /*return*/, props.onSubmit.call(null, cleanedValues)];
191
- }
190
+ if (!props.onSubmit) return [3 /*break*/, 2];
191
+ return [4 /*yield*/, props.onSubmit.call(null, cleanedValues)];
192
+ case 1:
193
+ submitResult = _c.sent();
194
+ dispatch(form_2.formSetSubmitting(props.formId, false));
195
+ return [2 /*return*/, submitResult];
196
+ case 2:
192
197
  captchaAttribute = null;
193
198
  Object.entries(components.ui.getRegisteredFields(props.formId) || {}).forEach(function (_a) {
194
199
  var attribute = _a[0], fieldType = _a[1];
@@ -196,20 +201,20 @@ function Form(props) {
196
201
  captchaAttribute = attribute;
197
202
  }
198
203
  });
199
- if (!(captchaAttribute && components.resource.googleCaptchaSiteKey)) return [3 /*break*/, 3];
204
+ if (!(captchaAttribute && components.resource.googleCaptchaSiteKey)) return [3 /*break*/, 5];
200
205
  return [4 /*yield*/, components.resource.loadGoogleCaptcha()];
201
- case 1:
206
+ case 3:
202
207
  googleCaptcha = _c.sent();
203
208
  return [4 /*yield*/, getCaptchaToken({
204
209
  googleCaptcha: googleCaptcha,
205
210
  siteKey: components.resource.googleCaptchaSiteKey,
206
211
  actionName: props.captchaActionName
207
212
  })];
208
- case 2:
213
+ case 4:
209
214
  captchaToken = _c.sent();
210
215
  cleanedValues = __assign(__assign({}, cleanedValues), (_b = {}, _b[captchaAttribute] = captchaToken, _b));
211
- _c.label = 3;
212
- case 3:
216
+ _c.label = 5;
217
+ case 5:
213
218
  options = {
214
219
  onTwoFactor: props.onTwoFactor
215
220
  ? function (providerName) { return __awaiter(_this, void 0, void 0, function () {
@@ -234,16 +239,16 @@ function Form(props) {
234
239
  }); }
235
240
  : undefined
236
241
  };
237
- if (!(typeof props.action === 'function')) return [3 /*break*/, 5];
242
+ if (!(typeof props.action === 'function')) return [3 /*break*/, 7];
238
243
  return [4 /*yield*/, props.action.call(null, components.api, cleanedValues, options)];
239
- case 4:
240
- _a = _c.sent();
241
- return [3 /*break*/, 7];
242
- case 5: return [4 /*yield*/, components.http.send(props.actionMethod, props.action || window.location.pathname, cleanedValues, options)];
243
244
  case 6:
244
245
  _a = _c.sent();
245
- _c.label = 7;
246
- case 7:
246
+ return [3 /*break*/, 9];
247
+ case 7: return [4 /*yield*/, components.http.send(props.actionMethod, props.action || window.location.pathname, cleanedValues, options)];
248
+ case 8:
249
+ _a = _c.sent();
250
+ _c.label = 9;
251
+ case 9:
247
252
  response = _a;
248
253
  dispatch(form_2.formSetSubmitting(props.formId, false));
249
254
  // Skip on 2fa
@@ -27,9 +27,7 @@ function Meta(props) {
27
27
  _c.map(function (attrs, index) { return (react_1["default"].createElement("style", __assign({ key: index }, attrs, { dangerouslySetInnerHTML: {
28
28
  __html: attrs.innerHtml
29
29
  } }))); }), (_d = props.scripts) === null || _d === void 0 ? void 0 :
30
- _d.map(function (attrs, index) { return (react_1["default"].createElement("script", __assign({ key: index }, attrs, { dangerouslySetInnerHTML: {
31
- __html: attrs.innerHtml
32
- } }))); }), (_e = props.noScripts) === null || _e === void 0 ? void 0 :
30
+ _d.map(function (attrs, index) { return (react_1["default"].createElement("script", __assign({ key: index }, attrs), attrs.innerHtml || '')); }), (_e = props.noScripts) === null || _e === void 0 ? void 0 :
33
31
  _e.map(function (attrs, index) { return (react_1["default"].createElement("noscript", { key: index, dangerouslySetInnerHTML: {
34
32
  __html: attrs.innerHtml
35
33
  } })); }),