@guillotinaweb/react-gmi 0.20.1 → 0.22.2
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/CHANGELOG.md +17 -0
- package/README.md +18 -10
- package/dist/components/fields/editableField.d.ts +0 -2
- package/dist/components/fields/renderField.d.ts +8 -0
- package/dist/components/login.d.ts +7 -14
- package/dist/components/selected_items_actions.d.ts +5 -2
- package/dist/hooks/useConfig.d.ts +2 -0
- package/dist/hooks/useRegistry.d.ts +2 -0
- package/dist/lib/client.d.ts +5 -4
- package/dist/lib/rest.d.ts +2 -1
- package/dist/react-gmi.esm.js +2179 -2142
- package/dist/react-gmi.esm.js.map +1 -1
- package/dist/react-gmi.js +2178 -2141
- package/dist/react-gmi.js.map +1 -1
- package/dist/react-gmi.modern.js +1721 -1680
- package/dist/react-gmi.modern.js.map +1 -1
- package/dist/react-gmi.umd.js +2178 -2141
- package/dist/react-gmi.umd.js.map +1 -1
- package/package.json +2 -2
package/dist/react-gmi.modern.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { createContext, useState, useCallback, useRef, useEffect, forwardRef, createElement, Fragment, useContext, useReducer } from 'react';
|
|
2
2
|
import usePortal from 'react-useportal';
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
import jwt_decode from 'jwt-decode';
|
|
@@ -36,74 +36,140 @@ function _objectWithoutPropertiesLoose(source, excluded) {
|
|
|
36
36
|
return target;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
const AuthContext = createContext({});
|
|
40
|
+
const ClientContext = createContext({});
|
|
41
|
+
const TraversalContext = createContext({});
|
|
42
|
+
|
|
43
|
+
class Traversal {
|
|
44
|
+
constructor(_ref) {
|
|
45
|
+
let {
|
|
46
|
+
flash
|
|
47
|
+
} = _ref,
|
|
48
|
+
props = _objectWithoutPropertiesLoose(_ref, ["flash"]);
|
|
49
|
+
|
|
50
|
+
Object.assign(this, props);
|
|
51
|
+
if (typeof flash === 'function') this.flash = flash;
|
|
43
52
|
}
|
|
44
53
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
54
|
+
refresh({
|
|
55
|
+
transparent = false
|
|
56
|
+
} = {}) {
|
|
57
|
+
this.dispatch({
|
|
58
|
+
type: 'REFRESH',
|
|
59
|
+
payload: {
|
|
60
|
+
transparent
|
|
61
|
+
}
|
|
62
|
+
});
|
|
49
63
|
}
|
|
50
64
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if (!authToken) return {};
|
|
54
|
-
return {
|
|
55
|
-
Accept: 'application/json',
|
|
56
|
-
'Content-Type': 'application/json',
|
|
57
|
-
Authorization: 'Bearer ' + authToken
|
|
58
|
-
};
|
|
65
|
+
get path() {
|
|
66
|
+
return this.state.path;
|
|
59
67
|
}
|
|
60
68
|
|
|
61
|
-
|
|
62
|
-
return
|
|
63
|
-
|
|
64
|
-
|
|
69
|
+
get pathPrefix() {
|
|
70
|
+
return this.state.path.slice(1);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
get context() {
|
|
74
|
+
return this.state.context;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
get containerPath() {
|
|
78
|
+
return this.client.getContainerFromPath(this.path);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
apply(data) {
|
|
82
|
+
// apply a optimistic update to context
|
|
83
|
+
this.dispatch({
|
|
84
|
+
type: 'APPLY',
|
|
85
|
+
payload: data
|
|
65
86
|
});
|
|
66
87
|
}
|
|
67
88
|
|
|
68
|
-
|
|
69
|
-
|
|
89
|
+
flash(message, type) {
|
|
90
|
+
this.dispatch({
|
|
91
|
+
type: 'SET_FLASH',
|
|
92
|
+
payload: {
|
|
93
|
+
flash: {
|
|
94
|
+
message,
|
|
95
|
+
type
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
window.scrollTo({
|
|
100
|
+
top: 0,
|
|
101
|
+
left: 0,
|
|
102
|
+
behavior: 'smooth'
|
|
103
|
+
});
|
|
70
104
|
}
|
|
71
105
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
body: JSON.stringify(data)
|
|
106
|
+
clearFlash() {
|
|
107
|
+
this.dispatch({
|
|
108
|
+
type: 'CLEAR_FLASH'
|
|
76
109
|
});
|
|
77
110
|
}
|
|
78
111
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
112
|
+
doAction(action, params) {
|
|
113
|
+
this.dispatch({
|
|
114
|
+
type: 'SET_ACTION',
|
|
115
|
+
payload: {
|
|
116
|
+
action,
|
|
117
|
+
params
|
|
118
|
+
}
|
|
83
119
|
});
|
|
84
120
|
}
|
|
85
121
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
headers['X-UPLOAD-FILENAME'] = data.filename;
|
|
91
|
-
headers['Content-Encoding'] = 'base64';
|
|
92
|
-
return await this.request(path, {
|
|
93
|
-
method: 'PATCH',
|
|
94
|
-
body: data.data
|
|
95
|
-
}, headers);
|
|
122
|
+
cancelAction() {
|
|
123
|
+
this.dispatch({
|
|
124
|
+
type: 'CLEAR_ACTION'
|
|
125
|
+
});
|
|
96
126
|
}
|
|
97
127
|
|
|
98
|
-
|
|
99
|
-
return
|
|
100
|
-
|
|
101
|
-
|
|
128
|
+
hasPerm(permission) {
|
|
129
|
+
return this.state.permissions[permission] === true;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
filterTabs(tabs, tabsPermissions) {
|
|
133
|
+
const result = {};
|
|
134
|
+
Object.keys(tabs).forEach(item => {
|
|
135
|
+
const perm = tabsPermissions[item];
|
|
136
|
+
|
|
137
|
+
if (perm && this.hasPerm(perm)) {
|
|
138
|
+
result[item] = tabs[item];
|
|
139
|
+
} else if (!perm) {
|
|
140
|
+
result[item] = tabs[item];
|
|
141
|
+
}
|
|
102
142
|
});
|
|
143
|
+
return result;
|
|
103
144
|
}
|
|
104
145
|
|
|
105
146
|
}
|
|
106
147
|
|
|
148
|
+
function TraversalProvider(_ref2) {
|
|
149
|
+
let {
|
|
150
|
+
children
|
|
151
|
+
} = _ref2,
|
|
152
|
+
props = _objectWithoutPropertiesLoose(_ref2, ["children"]);
|
|
153
|
+
|
|
154
|
+
return /*#__PURE__*/React.createElement(TraversalContext.Provider, {
|
|
155
|
+
value: new Traversal(props)
|
|
156
|
+
}, children);
|
|
157
|
+
}
|
|
158
|
+
function useTraversal() {
|
|
159
|
+
return React.useContext(TraversalContext);
|
|
160
|
+
}
|
|
161
|
+
function ClientProvider({
|
|
162
|
+
children,
|
|
163
|
+
client
|
|
164
|
+
}) {
|
|
165
|
+
return /*#__PURE__*/React.createElement(ClientContext.Provider, {
|
|
166
|
+
value: client
|
|
167
|
+
}, children);
|
|
168
|
+
}
|
|
169
|
+
function useGuillotinaClient() {
|
|
170
|
+
return React.useContext(ClientContext);
|
|
171
|
+
}
|
|
172
|
+
|
|
107
173
|
const classnames = classNames => {
|
|
108
174
|
return classNames.filter(Boolean).join(' ').trim();
|
|
109
175
|
};
|
|
@@ -153,1604 +219,1567 @@ function sleep(ms) {
|
|
|
153
219
|
});
|
|
154
220
|
}
|
|
155
221
|
|
|
156
|
-
const
|
|
157
|
-
icon,
|
|
158
|
-
className,
|
|
159
|
-
align
|
|
160
|
-
}) => {
|
|
161
|
-
const addClass = className ? className.split(' ') : [className];
|
|
162
|
-
align = align || 'is-right';
|
|
163
|
-
return /*#__PURE__*/React.createElement("span", {
|
|
164
|
-
className: classnames(['icon', align, ...addClass])
|
|
165
|
-
}, /*#__PURE__*/React.createElement("i", {
|
|
166
|
-
className: icon
|
|
167
|
-
}));
|
|
168
|
-
};
|
|
222
|
+
const noop$1 = () => {};
|
|
169
223
|
|
|
170
|
-
const
|
|
171
|
-
let
|
|
224
|
+
const Button = (_ref) => {
|
|
225
|
+
let {
|
|
226
|
+
children,
|
|
227
|
+
className = 'is-primary',
|
|
228
|
+
onClick,
|
|
229
|
+
type = 'submit',
|
|
230
|
+
loading = false,
|
|
231
|
+
disabled = false,
|
|
232
|
+
dataTest
|
|
233
|
+
} = _ref,
|
|
234
|
+
rest = _objectWithoutPropertiesLoose(_ref, ["children", "className", "onClick", "type", "loading", "disabled", "dataTest"]);
|
|
172
235
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
236
|
+
let css = [].concat('button', ...className.split(' '));
|
|
237
|
+
if (loading) css = css.concat('is-loading');
|
|
238
|
+
if (disabled) onClick = noop$1;
|
|
239
|
+
return /*#__PURE__*/React.createElement("p", {
|
|
240
|
+
className: "control"
|
|
241
|
+
}, /*#__PURE__*/React.createElement("button", _extends({
|
|
242
|
+
type: type,
|
|
243
|
+
className: classnames(css),
|
|
244
|
+
onClick: onClick,
|
|
245
|
+
disabled: disabled
|
|
246
|
+
}, rest, {
|
|
247
|
+
"data-test": dataTest
|
|
248
|
+
}), children));
|
|
176
249
|
};
|
|
177
250
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
className:
|
|
199
|
-
"
|
|
200
|
-
|
|
251
|
+
function Modal(props) {
|
|
252
|
+
const {
|
|
253
|
+
isActive,
|
|
254
|
+
setActive,
|
|
255
|
+
children
|
|
256
|
+
} = props;
|
|
257
|
+
const {
|
|
258
|
+
Portal
|
|
259
|
+
} = usePortal();
|
|
260
|
+
const css = 'modal ' + (isActive ? 'is-active ' : '') + props.className;
|
|
261
|
+
return /*#__PURE__*/React.createElement(Portal, null, /*#__PURE__*/React.createElement("div", {
|
|
262
|
+
className: css
|
|
263
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
264
|
+
className: "modal-background",
|
|
265
|
+
onClick: () => setActive(false)
|
|
266
|
+
}), /*#__PURE__*/React.createElement("div", {
|
|
267
|
+
className: "modal-content"
|
|
268
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
269
|
+
className: "box"
|
|
270
|
+
}, children)), /*#__PURE__*/React.createElement("button", {
|
|
271
|
+
className: "modal-close is-large",
|
|
272
|
+
"aria-label": "close",
|
|
273
|
+
onClick: () => setActive(false)
|
|
274
|
+
})));
|
|
201
275
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
276
|
+
function Confirm({
|
|
277
|
+
message,
|
|
278
|
+
onCancel,
|
|
279
|
+
onConfirm,
|
|
280
|
+
loading
|
|
207
281
|
}) {
|
|
208
|
-
|
|
209
|
-
return /*#__PURE__*/React.createElement("table", {
|
|
210
|
-
className: classnames(['table', ...className])
|
|
211
|
-
}, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, headers && headers.map((item, idx) => /*#__PURE__*/React.createElement("th", {
|
|
212
|
-
key: item + idx
|
|
213
|
-
}, item)))), /*#__PURE__*/React.createElement("tbody", null, children));
|
|
214
|
-
}
|
|
282
|
+
const setActive = () => onCancel();
|
|
215
283
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
284
|
+
return /*#__PURE__*/React.createElement(Modal, {
|
|
285
|
+
isActive: true,
|
|
286
|
+
setActive: setActive,
|
|
287
|
+
className: "confirm"
|
|
288
|
+
}, /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("h1", {
|
|
289
|
+
className: "title is-size-5"
|
|
290
|
+
}, message || 'Are you Sure?'), /*#__PURE__*/React.createElement("div", {
|
|
291
|
+
className: "level",
|
|
292
|
+
style: {
|
|
293
|
+
marginTop: 50
|
|
294
|
+
}
|
|
295
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
296
|
+
className: "level-left"
|
|
297
|
+
}), /*#__PURE__*/React.createElement("div", {
|
|
298
|
+
className: "level-right"
|
|
299
|
+
}, /*#__PURE__*/React.createElement("button", {
|
|
300
|
+
className: "button is-danger",
|
|
301
|
+
onClick: () => onCancel(),
|
|
302
|
+
"data-test": "btnCancelModalTest"
|
|
303
|
+
}, "Cancel"), "\xA0\xA0", /*#__PURE__*/React.createElement(Button, {
|
|
304
|
+
loading: loading,
|
|
305
|
+
className: "is-success",
|
|
306
|
+
onClick: () => onConfirm(),
|
|
307
|
+
dataTest: "btnConfirmModalTest"
|
|
308
|
+
}, "Confirm")))));
|
|
309
|
+
} // @todo Improve it... Replacing the inputText to a tree
|
|
310
|
+
|
|
311
|
+
function PathTree({
|
|
312
|
+
title,
|
|
313
|
+
defaultPath,
|
|
314
|
+
children,
|
|
315
|
+
onConfirm,
|
|
316
|
+
onCancel
|
|
219
317
|
}) {
|
|
220
|
-
return /*#__PURE__*/React.createElement(
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
},
|
|
318
|
+
return /*#__PURE__*/React.createElement(Modal, {
|
|
319
|
+
isActive: true,
|
|
320
|
+
setActive: onCancel
|
|
321
|
+
}, /*#__PURE__*/React.createElement("h1", null, title), /*#__PURE__*/React.createElement("form", {
|
|
322
|
+
onSubmit: e => {
|
|
323
|
+
e.preventDefault();
|
|
324
|
+
onConfirm(e.target[0].value, e.target);
|
|
325
|
+
}
|
|
326
|
+
}, /*#__PURE__*/React.createElement("small", {
|
|
327
|
+
style: {
|
|
328
|
+
display: 'block',
|
|
329
|
+
marginTop: 20
|
|
330
|
+
}
|
|
331
|
+
}, `Example: /folder (without /db/container on front)`), /*#__PURE__*/React.createElement("input", {
|
|
332
|
+
className: "input mb-3",
|
|
333
|
+
defaultValue: defaultPath,
|
|
334
|
+
type: "text",
|
|
335
|
+
"data-test": "inputPathTreeTest"
|
|
336
|
+
}), children, /*#__PURE__*/React.createElement("div", {
|
|
337
|
+
className: "level-right mt-3"
|
|
338
|
+
}, /*#__PURE__*/React.createElement("button", {
|
|
339
|
+
type: "button",
|
|
340
|
+
className: "button is-danger",
|
|
341
|
+
onClick: onCancel,
|
|
342
|
+
"data-test": "btnCancelModalTest"
|
|
343
|
+
}, "Cancel"), "\xA0\xA0", /*#__PURE__*/React.createElement("button", {
|
|
344
|
+
type: "submit",
|
|
345
|
+
className: "button is-success",
|
|
346
|
+
"data-test": "btnConfirmModalTest"
|
|
347
|
+
}, "Confirm"))));
|
|
224
348
|
}
|
|
225
349
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
const
|
|
350
|
+
function useSetState(initialState) {
|
|
351
|
+
const [state, set] = useState(initialState);
|
|
352
|
+
const setState = useCallback(patch => {
|
|
353
|
+
set(prevState => Object.assign({}, prevState, patch instanceof Function ? patch(prevState) : patch));
|
|
354
|
+
}, [set]);
|
|
355
|
+
return [state, setState];
|
|
356
|
+
}
|
|
229
357
|
|
|
230
|
-
const
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
358
|
+
const initial = {
|
|
359
|
+
loading: undefined,
|
|
360
|
+
isError: false,
|
|
361
|
+
errorMessage: undefined,
|
|
362
|
+
result: undefined,
|
|
363
|
+
response: undefined
|
|
234
364
|
};
|
|
235
365
|
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
// unfortunately, we can't rely on `path` value here, since it can be stale,
|
|
243
|
-
// that's why we store the last pathname in a ref.
|
|
244
|
-
|
|
245
|
-
const checkForUpdates = () => {
|
|
246
|
-
const pathname = currentSearchParams();
|
|
247
|
-
prevPath.current !== pathname && update(prevPath.current = pathname);
|
|
248
|
-
};
|
|
249
|
-
|
|
250
|
-
const events = ['popstate', 'pushState', 'replaceState'];
|
|
251
|
-
events.map(e => window.addEventListener(e, checkForUpdates)); // it's possible that an update has occurred between render and the effect handler,
|
|
252
|
-
// so we run additional check on mount to catch these updates. Based on:
|
|
253
|
-
// https://gist.github.com/bvaughn/e25397f70e8c65b0ae0d7c90b731b189
|
|
254
|
-
|
|
255
|
-
checkForUpdates();
|
|
256
|
-
return () => events.map(e => window.removeEventListener(e, checkForUpdates));
|
|
257
|
-
}, []); // the 2nd argument of the `useLocation` return value is a function
|
|
258
|
-
// that allows to perform a navigation.
|
|
259
|
-
//
|
|
260
|
-
// the function reference should stay the same between re-renders, so that
|
|
261
|
-
// it can be passed down as an element prop without any performance concerns.
|
|
262
|
-
|
|
263
|
-
const navigate = useCallback((to, replace) => {
|
|
264
|
-
if (replace) {
|
|
265
|
-
clean(to);
|
|
266
|
-
return;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
let current = new URLSearchParams(path.toString());
|
|
270
|
-
Object.keys(to).forEach(_key => current.set(_key, to[_key]));
|
|
271
|
-
setURLParams(current);
|
|
272
|
-
}, [path]);
|
|
273
|
-
const remove = useCallback(param => {
|
|
274
|
-
let current = new URLSearchParams(path.toString());
|
|
275
|
-
current.delete(param);
|
|
276
|
-
setURLParams(current);
|
|
277
|
-
}, [path]);
|
|
278
|
-
return [path, navigate, remove];
|
|
279
|
-
}; // While History API does have `popstate` event, the only
|
|
280
|
-
// proper way to listen to changes via `push/replaceState`
|
|
281
|
-
// is to monkey-patch these methods.
|
|
282
|
-
//
|
|
283
|
-
// See https://stackoverflow.com/a/4585031
|
|
366
|
+
const getErrorMessage = (dataError, defaultValue) => {
|
|
367
|
+
if (dataError && dataError.details) {
|
|
368
|
+
return dataError.details;
|
|
369
|
+
} else if (dataError && dataError.reason) {
|
|
370
|
+
return dataError.reason;
|
|
371
|
+
}
|
|
284
372
|
|
|
285
|
-
|
|
373
|
+
return defaultValue;
|
|
374
|
+
};
|
|
286
375
|
|
|
287
|
-
const
|
|
288
|
-
if (
|
|
289
|
-
|
|
290
|
-
|
|
376
|
+
const processResponse = async (res, ready_body = true) => {
|
|
377
|
+
if (res.status < 400) return {
|
|
378
|
+
isError: false,
|
|
379
|
+
loading: false,
|
|
380
|
+
result: ready_body ? await res.json() : res.status,
|
|
381
|
+
response: res
|
|
382
|
+
};else return {
|
|
383
|
+
isError: true,
|
|
384
|
+
loading: false,
|
|
385
|
+
errorMessage: getErrorMessage(await res.json(), res.status),
|
|
386
|
+
response: res
|
|
387
|
+
};
|
|
388
|
+
};
|
|
291
389
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
event.arguments = arguments;
|
|
296
|
-
dispatchEvent(event);
|
|
297
|
-
return result;
|
|
298
|
-
};
|
|
390
|
+
const patch = (setState, Ctx) => async (data, endpoint, body = false) => {
|
|
391
|
+
setState({
|
|
392
|
+
loading: true
|
|
299
393
|
});
|
|
300
|
-
|
|
301
|
-
};
|
|
394
|
+
let newState = {};
|
|
302
395
|
|
|
303
|
-
|
|
396
|
+
try {
|
|
397
|
+
const path = endpoint ? `${Ctx.path}${endpoint}` : Ctx.path;
|
|
398
|
+
const res = await Ctx.client.patch(path, data);
|
|
399
|
+
newState = await processResponse(res, body);
|
|
400
|
+
} catch (e) {
|
|
401
|
+
console.error('Error', e);
|
|
402
|
+
newState = {
|
|
403
|
+
isError: true,
|
|
404
|
+
errorMessage: 'unhandled exception'
|
|
405
|
+
};
|
|
406
|
+
}
|
|
304
407
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
model,
|
|
309
|
-
children
|
|
310
|
-
} = _ref,
|
|
311
|
-
props = _objectWithoutPropertiesLoose(_ref, ["aRef", "model", "children"]);
|
|
408
|
+
setState(newState);
|
|
409
|
+
return newState;
|
|
410
|
+
};
|
|
312
411
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
};
|
|
412
|
+
const del = (setState, Ctx) => async (data, endpoint, body = false) => {
|
|
413
|
+
setState({
|
|
414
|
+
loading: true
|
|
415
|
+
});
|
|
416
|
+
let newState = {};
|
|
318
417
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
418
|
+
try {
|
|
419
|
+
const path = endpoint ? `${Ctx.path}${endpoint}` : Ctx.path;
|
|
420
|
+
const res = await Ctx.client.delete(path, data);
|
|
421
|
+
newState = await processResponse(res, body);
|
|
422
|
+
} catch (e) {
|
|
423
|
+
console.error('Error', e);
|
|
424
|
+
newState = {
|
|
425
|
+
isError: true,
|
|
426
|
+
errorMessage: 'unhandled exception'
|
|
427
|
+
};
|
|
327
428
|
}
|
|
328
429
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
style: aStyle,
|
|
333
|
-
onClick: onClick
|
|
334
|
-
}), children);
|
|
335
|
-
}
|
|
430
|
+
setState(newState);
|
|
431
|
+
return newState;
|
|
432
|
+
};
|
|
336
433
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
434
|
+
const post = (setState, Ctx) => async (data, endpoint, body = true) => {
|
|
435
|
+
setState({
|
|
436
|
+
loading: true
|
|
437
|
+
});
|
|
438
|
+
let newState = {};
|
|
340
439
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
}
|
|
346
|
-
|
|
440
|
+
try {
|
|
441
|
+
const path = endpoint ? `${Ctx.path}${endpoint}` : Ctx.path;
|
|
442
|
+
const res = await Ctx.client.post(path, data);
|
|
443
|
+
newState = await processResponse(res, body);
|
|
444
|
+
} catch (e) {
|
|
445
|
+
console.error('Error', e);
|
|
446
|
+
newState = {
|
|
447
|
+
isError: true,
|
|
448
|
+
errorMessage: 'unhandled exception'
|
|
449
|
+
};
|
|
450
|
+
}
|
|
347
451
|
|
|
348
|
-
|
|
452
|
+
setState(newState);
|
|
453
|
+
return newState;
|
|
454
|
+
};
|
|
349
455
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
456
|
+
const get = (setState, Ctx) => async endpoint => {
|
|
457
|
+
setState({
|
|
458
|
+
loading: true
|
|
459
|
+
});
|
|
460
|
+
const path = endpoint ? `${Ctx.path}${endpoint}` : Ctx.path;
|
|
461
|
+
const req = await Ctx.client.get(path);
|
|
462
|
+
const data = await req.json();
|
|
463
|
+
setState({
|
|
464
|
+
loading: false,
|
|
465
|
+
result: data,
|
|
466
|
+
response: req
|
|
467
|
+
});
|
|
468
|
+
return data;
|
|
469
|
+
};
|
|
353
470
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
471
|
+
function useCrudContext() {
|
|
472
|
+
const Ctx = useTraversal();
|
|
473
|
+
const [state, setState] = useSetState(initial);
|
|
474
|
+
return _extends({}, state, {
|
|
475
|
+
Ctx,
|
|
476
|
+
patch: patch(setState, Ctx),
|
|
477
|
+
del: del(setState, Ctx),
|
|
478
|
+
post: post(setState, Ctx),
|
|
479
|
+
get: get(setState, Ctx)
|
|
480
|
+
});
|
|
360
481
|
}
|
|
361
482
|
|
|
362
|
-
|
|
363
|
-
const
|
|
364
|
-
const
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
483
|
+
function AddItem(props) {
|
|
484
|
+
const Ctx = useTraversal();
|
|
485
|
+
const {
|
|
486
|
+
post,
|
|
487
|
+
loading
|
|
488
|
+
} = useCrudContext();
|
|
489
|
+
const {
|
|
490
|
+
type
|
|
491
|
+
} = props;
|
|
492
|
+
const {
|
|
493
|
+
getForm
|
|
494
|
+
} = Ctx.registry;
|
|
495
|
+
const Form = getForm(type);
|
|
372
496
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
part = part.replace('||', ' ');
|
|
377
|
-
}
|
|
497
|
+
const setActive = () => {
|
|
498
|
+
Ctx.cancelAction();
|
|
499
|
+
};
|
|
378
500
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
501
|
+
async function doSubmit(data) {
|
|
502
|
+
const form = Object.assign({}, {
|
|
503
|
+
'@type': type
|
|
504
|
+
}, data.formData ? data.formData : data);
|
|
505
|
+
const {
|
|
506
|
+
isError,
|
|
507
|
+
errorMessage
|
|
508
|
+
} = await post(form);
|
|
382
509
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
}
|
|
388
|
-
function buildQs(parsedQuery) {
|
|
389
|
-
return parsedQuery.map(([key, val]) => `${encodeURIComponent(key)}=${encodeURIComponent(val)}`).join('&');
|
|
390
|
-
}
|
|
510
|
+
if (!isError) {
|
|
511
|
+
Ctx.flash('Content created!', 'success');
|
|
512
|
+
} else {
|
|
513
|
+
Ctx.flash(`An error has ocurred: ${errorMessage}`, 'danger');
|
|
514
|
+
}
|
|
391
515
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
class GuillotinaClient {
|
|
395
|
-
constructor(rest, isContainer) {
|
|
396
|
-
this.rest = rest;
|
|
397
|
-
this.isContainer = isContainer;
|
|
516
|
+
Ctx.cancelAction();
|
|
517
|
+
Ctx.refresh();
|
|
398
518
|
}
|
|
399
519
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
520
|
+
return /*#__PURE__*/React.createElement(Modal, {
|
|
521
|
+
isActive: true,
|
|
522
|
+
setActive: setActive
|
|
523
|
+
}, /*#__PURE__*/React.createElement(Form, {
|
|
524
|
+
loading: loading,
|
|
525
|
+
onSubmit: doSubmit,
|
|
526
|
+
onError: err => console.log(err),
|
|
527
|
+
actionName: 'Add ' + type,
|
|
528
|
+
title: 'Add ' + type,
|
|
529
|
+
type: type,
|
|
530
|
+
dataTest: `formAdd${type}Test`
|
|
531
|
+
}));
|
|
532
|
+
}
|
|
409
533
|
|
|
410
|
-
|
|
411
|
-
|
|
534
|
+
const Permissions = ['guillotina.AddContent', 'guillotina.ModifyContent', 'guillotina.ViewContent', 'guillotina.DeleteContent', 'guillotina.AccessContent', 'guillotina.SeePermissions', 'guillotina.ChangePermissions', 'guillotina.MoveContent', 'guillotina.DuplicateContent', 'guillotina.ReadConfiguration', 'guillotina.RegisterConfigurations', 'guillotina.WriteConfiguration', 'guillotina.ManageAddons', 'guillotina.swagger.View'];
|
|
535
|
+
const Config = {
|
|
536
|
+
DisabledTypes: ['UserManager', 'GroupManager'],
|
|
537
|
+
PageSize: 10,
|
|
538
|
+
DelayActions: 200,
|
|
539
|
+
Permissions: Permissions,
|
|
540
|
+
SearchEngine: 'PostreSQL',
|
|
541
|
+
// Elasticsearch
|
|
542
|
+
fieldHaveDeleteButton: schema => {
|
|
543
|
+
return (schema == null ? void 0 : schema.widget) === 'file' || (schema == null ? void 0 : schema.widget) === 'select' || (schema == null ? void 0 : schema.type) === 'array';
|
|
412
544
|
}
|
|
545
|
+
};
|
|
546
|
+
let calculated = Object.assign({}, Config);
|
|
413
547
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
548
|
+
const addConfig = (additional, original) => {
|
|
549
|
+
const rest = Object.assign({}, original);
|
|
550
|
+
Object.keys(additional).forEach(item => {
|
|
551
|
+
if (typeof Config[item] === 'object' && Array.isArray(Config[item])) {
|
|
552
|
+
rest[item] = [].concat(Config[item], additional[item]);
|
|
553
|
+
} else if (typeof Config[item] === 'object') {
|
|
554
|
+
rest[item] = Object.assign({}, Config[item], additional[item]);
|
|
555
|
+
} else {
|
|
556
|
+
rest[item] = additional[item];
|
|
417
557
|
}
|
|
558
|
+
});
|
|
559
|
+
return rest;
|
|
560
|
+
};
|
|
418
561
|
|
|
419
|
-
|
|
420
|
-
|
|
562
|
+
function useConfig(cfg) {
|
|
563
|
+
const ref = React.useRef();
|
|
421
564
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
}) {
|
|
427
|
-
|
|
428
|
-
|
|
565
|
+
if (cfg && !ref.current) {
|
|
566
|
+
console.log('cfg', cfg);
|
|
567
|
+
calculated = addConfig(cfg, calculated);
|
|
568
|
+
ref.current = calculated;
|
|
569
|
+
} // if (cfg && !ref.current) {
|
|
570
|
+
// ref.current = addConfig(cfg, ref.current);
|
|
571
|
+
// calculated = ref.current
|
|
572
|
+
// console.log("Current config", cfg)
|
|
573
|
+
// }
|
|
429
574
|
|
|
430
|
-
if (withDepth) {
|
|
431
|
-
var _parser;
|
|
432
575
|
|
|
433
|
-
|
|
434
|
-
|
|
576
|
+
return calculated;
|
|
577
|
+
}
|
|
435
578
|
|
|
436
|
-
|
|
579
|
+
const getId = item => {
|
|
580
|
+
if (item['@id']) {
|
|
581
|
+
return item['@id'];
|
|
437
582
|
}
|
|
438
583
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
pageSize = 10,
|
|
442
|
-
path,
|
|
443
|
-
withDepth = true
|
|
444
|
-
}) {
|
|
445
|
-
let result = [];
|
|
446
|
-
let containerPath = getContainerFromPath(path);
|
|
584
|
+
return item['@absolute_url'];
|
|
585
|
+
};
|
|
447
586
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
587
|
+
function RemoveItems(props) {
|
|
588
|
+
const Ctx = useTraversal();
|
|
589
|
+
const cfg = useConfig();
|
|
590
|
+
const [loading, setLoading] = React.useState(false);
|
|
591
|
+
const {
|
|
592
|
+
items = []
|
|
593
|
+
} = props;
|
|
594
|
+
const last = items[items.length - 1]['@name'];
|
|
595
|
+
const itemsNames = items.map(item => item['@name']).join(', ').replace(`, ${last}`, ` and ${last}`);
|
|
451
596
|
|
|
452
|
-
|
|
597
|
+
async function removeItems() {
|
|
598
|
+
let errors = [];
|
|
599
|
+
setLoading(true);
|
|
600
|
+
const actions = items.map(async item => {
|
|
601
|
+
console.log(item);
|
|
602
|
+
const res = await Ctx.client.delete(getId(item));
|
|
453
603
|
|
|
454
|
-
|
|
455
|
-
|
|
604
|
+
if (!res.ok) {
|
|
605
|
+
const err = await res.json();
|
|
606
|
+
errors.push(err);
|
|
607
|
+
}
|
|
608
|
+
}); // this sleep is here, to let elasticsearch, wait for
|
|
609
|
+
// index our operations... (will work 99% of use cases)
|
|
610
|
+
|
|
611
|
+
actions.push(sleep(cfg.DelayActions));
|
|
612
|
+
await Promise.all(actions);
|
|
613
|
+
|
|
614
|
+
if (errors.length === 0) {
|
|
615
|
+
Ctx.flash(`Items removed!`, 'success');
|
|
616
|
+
Ctx.refresh();
|
|
617
|
+
} else {
|
|
618
|
+
const errorstr = errors.map(err => JSON.stringify(err)).join('\n');
|
|
619
|
+
Ctx.flash(`Something went wrong!! ${errorstr}`, 'danger');
|
|
456
620
|
}
|
|
457
621
|
|
|
458
|
-
|
|
622
|
+
setLoading(false);
|
|
623
|
+
Ctx.cancelAction();
|
|
624
|
+
}
|
|
459
625
|
|
|
460
|
-
|
|
461
|
-
|
|
626
|
+
return /*#__PURE__*/React.createElement(Confirm, {
|
|
627
|
+
loading: loading,
|
|
628
|
+
onCancel: () => Ctx.cancelAction(),
|
|
629
|
+
onConfirm: removeItems,
|
|
630
|
+
message: `Are you sure to remove: ${itemsNames}?`
|
|
631
|
+
});
|
|
632
|
+
}
|
|
462
633
|
|
|
463
|
-
|
|
464
|
-
|
|
634
|
+
const Checkbox = (_ref) => {
|
|
635
|
+
let {
|
|
636
|
+
id,
|
|
637
|
+
className,
|
|
638
|
+
classNameInput,
|
|
639
|
+
loading,
|
|
640
|
+
disabled,
|
|
641
|
+
indeterminate = false,
|
|
642
|
+
value = false,
|
|
643
|
+
children,
|
|
644
|
+
placeholder,
|
|
645
|
+
onChange,
|
|
646
|
+
dataTest
|
|
647
|
+
} = _ref,
|
|
648
|
+
rest = _objectWithoutPropertiesLoose(_ref, ["id", "className", "classNameInput", "loading", "disabled", "indeterminate", "value", "color", "backgroundColor", "borderColor", "children", "placeholder", "onChange", "dataTest"]);
|
|
465
649
|
|
|
466
|
-
|
|
467
|
-
|
|
650
|
+
const inputRef = useRef(null);
|
|
651
|
+
const [state, setState] = React.useState(value);
|
|
652
|
+
useEffect(() => {
|
|
653
|
+
if (inputRef.current) {
|
|
654
|
+
inputRef.current.indeterminate = indeterminate;
|
|
468
655
|
}
|
|
656
|
+
}, [indeterminate]);
|
|
469
657
|
|
|
470
|
-
|
|
471
|
-
|
|
658
|
+
const updateState = ev => {
|
|
659
|
+
setState(ev.target.checked);
|
|
660
|
+
onChange(ev.target.checked);
|
|
661
|
+
};
|
|
472
662
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
child: m => /*#__PURE__*/React.createElement(TdLink, {
|
|
490
|
-
style: smallcss,
|
|
491
|
-
model: m
|
|
492
|
-
}, /*#__PURE__*/React.createElement("span", {
|
|
493
|
-
className: "tag"
|
|
494
|
-
}, m.type))
|
|
495
|
-
}, {
|
|
496
|
-
label: 'id/name',
|
|
497
|
-
child: (m, navigate, search) => /*#__PURE__*/React.createElement(TdLink, {
|
|
498
|
-
model: m
|
|
499
|
-
}, m.name, search && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement("span", {
|
|
500
|
-
className: "is-size-7 tag is-light"
|
|
501
|
-
}, m.path)))
|
|
502
|
-
}, {
|
|
503
|
-
label: 'created',
|
|
504
|
-
child: m => /*#__PURE__*/React.createElement("td", {
|
|
505
|
-
style: mediumcss,
|
|
506
|
-
className: "is-size-7 is-vcentered"
|
|
507
|
-
}, m.created)
|
|
508
|
-
}, {
|
|
509
|
-
label: 'modified',
|
|
510
|
-
child: m => /*#__PURE__*/React.createElement("td", {
|
|
511
|
-
style: mediumcss,
|
|
512
|
-
className: "is-size-7 is-vcentered"
|
|
513
|
-
}, m.updated)
|
|
514
|
-
}];
|
|
515
|
-
} // BBB API changes. Compat G5 and G6
|
|
663
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
664
|
+
className: "field"
|
|
665
|
+
}, /*#__PURE__*/React.createElement("label", {
|
|
666
|
+
htmlFor: id,
|
|
667
|
+
className: classnames(['checkbox', className])
|
|
668
|
+
}, /*#__PURE__*/React.createElement("input", _extends({
|
|
669
|
+
ref: inputRef,
|
|
670
|
+
disabled: disabled || loading,
|
|
671
|
+
id: id,
|
|
672
|
+
type: "checkbox",
|
|
673
|
+
className: classnames(['checkbox', classNameInput]),
|
|
674
|
+
checked: state,
|
|
675
|
+
onChange: updateState,
|
|
676
|
+
"data-test": dataTest
|
|
677
|
+
}, rest)), children || placeholder));
|
|
678
|
+
};
|
|
516
679
|
|
|
680
|
+
const ErrorZone = ({
|
|
681
|
+
children,
|
|
682
|
+
id,
|
|
683
|
+
className
|
|
684
|
+
}) => {
|
|
685
|
+
return /*#__PURE__*/React.createElement("p", {
|
|
686
|
+
className: classnames(['help is-danger', className]),
|
|
687
|
+
id: id
|
|
688
|
+
}, children);
|
|
689
|
+
};
|
|
517
690
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
691
|
+
ErrorZone.propTypes = {
|
|
692
|
+
children: PropTypes.node,
|
|
693
|
+
id: PropTypes.string,
|
|
694
|
+
className: PropTypes.string
|
|
695
|
+
};
|
|
523
696
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
697
|
+
const applyValidators = (value, validators) => {
|
|
698
|
+
let validation = Array.isArray(validators) ? validators : [validators];
|
|
699
|
+
let result = true;
|
|
700
|
+
validation.forEach(func => {
|
|
701
|
+
if (func(value) === false) {
|
|
702
|
+
result = false;
|
|
527
703
|
}
|
|
704
|
+
});
|
|
705
|
+
return result;
|
|
706
|
+
};
|
|
528
707
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
708
|
+
const useInput = (onChange, value, validator) => {
|
|
709
|
+
let [state, setState] = React.useState({
|
|
710
|
+
hasError: false,
|
|
711
|
+
value: value
|
|
712
|
+
});
|
|
532
713
|
|
|
533
|
-
|
|
534
|
-
const
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
714
|
+
const onUpdate = ev => {
|
|
715
|
+
const value = ev && ev.target ? ev.target.value : ev ? ev : '';
|
|
716
|
+
setState({
|
|
717
|
+
value,
|
|
718
|
+
hasError: false
|
|
719
|
+
});
|
|
720
|
+
if (onChange) onChange(value);
|
|
721
|
+
};
|
|
539
722
|
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
723
|
+
const onBlur = () => {
|
|
724
|
+
const hasError = applyValidators(state.value, validator) === false;
|
|
725
|
+
if (hasError) setState({
|
|
726
|
+
value: state.value,
|
|
727
|
+
hasError
|
|
728
|
+
});
|
|
729
|
+
};
|
|
544
730
|
|
|
545
|
-
|
|
546
|
-
|
|
731
|
+
const onFocus = () => {
|
|
732
|
+
if (state.hasError) {
|
|
733
|
+
setState({
|
|
734
|
+
value: state.value,
|
|
735
|
+
hasError: false
|
|
736
|
+
});
|
|
547
737
|
}
|
|
738
|
+
};
|
|
548
739
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
740
|
+
React.useEffect(() => {
|
|
741
|
+
setState({
|
|
742
|
+
value,
|
|
743
|
+
hasError: false
|
|
744
|
+
});
|
|
745
|
+
}, [value]);
|
|
746
|
+
return {
|
|
747
|
+
onChange: onUpdate,
|
|
748
|
+
onFocus,
|
|
749
|
+
onBlur,
|
|
750
|
+
state
|
|
751
|
+
};
|
|
752
|
+
};
|
|
552
753
|
|
|
553
|
-
|
|
554
|
-
return await this.rest.post(path, data);
|
|
555
|
-
}
|
|
754
|
+
// From github.com/protonmail/proton-shared
|
|
556
755
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
756
|
+
/* eslint-disable no-useless-escape */
|
|
757
|
+
const REGEX_EMAIL = /(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))/i;
|
|
758
|
+
const REGEX_URL = /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-_]*)?\??(?:[\-\+=&;%@\.\w_]*)#?(?:[\.\!\/\\\w]*))?)/;
|
|
759
|
+
const REGEX_HEX_COLOR = /^#([a-f0-9]{3,4}|[a-f0-9]{4}(?:[a-f0-9]{2}){1,2})\b$/i;
|
|
760
|
+
const REGEX_NUMBER = /^\d+$/;
|
|
761
|
+
const isEmpty = (value = '') => !value.length;
|
|
762
|
+
const maxLength = (value = '', limit = 0) => value.length <= limit;
|
|
763
|
+
const minLength = (value = '', limit = 0) => value.length >= limit;
|
|
764
|
+
const isEmail = (value = '') => REGEX_EMAIL.test(value);
|
|
765
|
+
const isURL = (value = '') => REGEX_URL.test(value);
|
|
766
|
+
const isHexColor = (value = '') => REGEX_HEX_COLOR.test(value);
|
|
767
|
+
const isNumber = (value = '') => REGEX_NUMBER.test(value);
|
|
768
|
+
const notEmpty = value => !!value.length;
|
|
561
769
|
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
return await this.rest.delete(this.cleanPath(path), data);
|
|
565
|
-
}
|
|
770
|
+
const noop$2 = () => true;
|
|
771
|
+
/** @type any */
|
|
566
772
|
|
|
567
|
-
async create(path, data) {
|
|
568
|
-
if (path.startsWith('/')) {
|
|
569
|
-
path = path.substring(1);
|
|
570
|
-
}
|
|
571
773
|
|
|
572
|
-
|
|
573
|
-
|
|
774
|
+
const Input = React.forwardRef((_ref, ref) => {
|
|
775
|
+
let {
|
|
776
|
+
icon,
|
|
777
|
+
iconPosition = 'has-icons-right',
|
|
778
|
+
error,
|
|
779
|
+
errorZoneClassName,
|
|
780
|
+
autoComplete = 'off',
|
|
781
|
+
className = '',
|
|
782
|
+
widget = 'input',
|
|
783
|
+
type = 'text',
|
|
784
|
+
loading = false,
|
|
785
|
+
required = false,
|
|
786
|
+
id,
|
|
787
|
+
placeholder,
|
|
788
|
+
value,
|
|
789
|
+
autofocus = false,
|
|
790
|
+
onChange,
|
|
791
|
+
validator = noop$2,
|
|
792
|
+
errorMessage,
|
|
793
|
+
dataTest = 'testInput'
|
|
794
|
+
} = _ref,
|
|
795
|
+
rest = _objectWithoutPropertiesLoose(_ref, ["icon", "iconPosition", "error", "errorZoneClassName", "autoComplete", "className", "widget", "type", "onPressEnter", "isSubmitted", "loading", "required", "id", "placeholder", "value", "autofocus", "onChange", "validator", "errorMessage", "dataTest"]);
|
|
574
796
|
|
|
575
|
-
|
|
576
|
-
|
|
797
|
+
if (required) {
|
|
798
|
+
validator = Array.isArray(validator) ? validator.push(notEmpty) : [validator, notEmpty];
|
|
577
799
|
}
|
|
578
800
|
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
801
|
+
const _useInput = useInput(onChange, value != null ? value : '', validator),
|
|
802
|
+
{
|
|
803
|
+
state
|
|
804
|
+
} = _useInput,
|
|
805
|
+
handlers = _objectWithoutPropertiesLoose(_useInput, ["state"]);
|
|
583
806
|
|
|
584
|
-
|
|
585
|
-
|
|
807
|
+
const [uid] = useState(generateUID('input'));
|
|
808
|
+
const [mounted, setMounted] = useState(false); // eslint-disable-next-line
|
|
586
809
|
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
810
|
+
ref = ref || React.useRef();
|
|
811
|
+
useEffect(() => {
|
|
812
|
+
setMounted(true);
|
|
813
|
+
}, []);
|
|
814
|
+
useEffect(() => {
|
|
815
|
+
if (autofocus && !error) {
|
|
816
|
+
ref.current.focus();
|
|
590
817
|
}
|
|
818
|
+
}, [mounted, autofocus, ref, error]);
|
|
819
|
+
const theError = state.hasError ? errorMessage || 'invalid field' : '';
|
|
820
|
+
const statusClasses = state.hasError ? 'is-danger' : '';
|
|
821
|
+
|
|
822
|
+
const cssControl = () => icon ? ['control', iconPosition] : ['control'];
|
|
823
|
+
|
|
824
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
825
|
+
className: "field"
|
|
826
|
+
}, id && placeholder ? /*#__PURE__*/React.createElement("label", {
|
|
827
|
+
className: "label",
|
|
828
|
+
htmlFor: id
|
|
829
|
+
}, placeholder) : null, /*#__PURE__*/React.createElement("div", {
|
|
830
|
+
className: classnames(cssControl())
|
|
831
|
+
}, /*#__PURE__*/React.createElement("input", _extends({
|
|
832
|
+
className: classnames([widget, className, statusClasses]),
|
|
833
|
+
"aria-invalid": theError,
|
|
834
|
+
"aria-describedby": uid,
|
|
835
|
+
id: id,
|
|
836
|
+
ref: ref,
|
|
837
|
+
type: type,
|
|
838
|
+
value: state.value,
|
|
839
|
+
placeholder: placeholder,
|
|
840
|
+
autoComplete: autoComplete,
|
|
841
|
+
disabled: loading || rest.disabled,
|
|
842
|
+
required: required,
|
|
843
|
+
"data-test": dataTest
|
|
844
|
+
}, handlers, rest)), icon && icon), /*#__PURE__*/React.createElement(ErrorZone, {
|
|
845
|
+
className: errorZoneClassName,
|
|
846
|
+
id: uid
|
|
847
|
+
}, state.hasError ? theError : ''));
|
|
848
|
+
});
|
|
849
|
+
Input.propTypes = {
|
|
850
|
+
icon: PropTypes.node,
|
|
851
|
+
iconPosition: PropTypes.arrayOf(PropTypes.oneOf(['has-icons-left', 'has-icons-right', ''])),
|
|
852
|
+
error: PropTypes.string,
|
|
853
|
+
errorZoneClassName: PropTypes.string,
|
|
854
|
+
autoComplete: PropTypes.string,
|
|
855
|
+
autoFocus: PropTypes.bool,
|
|
856
|
+
className: PropTypes.string,
|
|
857
|
+
disabled: PropTypes.bool,
|
|
858
|
+
loading: PropTypes.bool,
|
|
859
|
+
isSubmitted: PropTypes.bool,
|
|
860
|
+
id: PropTypes.string,
|
|
861
|
+
name: PropTypes.string,
|
|
862
|
+
onChange: PropTypes.func,
|
|
863
|
+
onKeyDown: PropTypes.func,
|
|
864
|
+
onKeyUp: PropTypes.func,
|
|
865
|
+
onPressEnter: PropTypes.func,
|
|
866
|
+
placeholder: PropTypes.string,
|
|
867
|
+
readOnly: PropTypes.bool,
|
|
868
|
+
required: PropTypes.bool,
|
|
869
|
+
type: PropTypes.string,
|
|
870
|
+
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool])
|
|
871
|
+
};
|
|
872
|
+
|
|
873
|
+
const Icon = ({
|
|
874
|
+
icon,
|
|
875
|
+
className,
|
|
876
|
+
align
|
|
877
|
+
}) => {
|
|
878
|
+
const addClass = className ? className.split(' ') : [className];
|
|
879
|
+
align = align || 'is-right';
|
|
880
|
+
return /*#__PURE__*/React.createElement("span", {
|
|
881
|
+
className: classnames(['icon', align, ...addClass])
|
|
882
|
+
}, /*#__PURE__*/React.createElement("i", {
|
|
883
|
+
className: icon
|
|
884
|
+
}));
|
|
885
|
+
};
|
|
886
|
+
|
|
887
|
+
const EmailInput = (_ref) => {
|
|
888
|
+
let {
|
|
889
|
+
value = '',
|
|
890
|
+
dataTest
|
|
891
|
+
} = _ref,
|
|
892
|
+
rest = _objectWithoutPropertiesLoose(_ref, ["value", "dataTest"]);
|
|
893
|
+
|
|
894
|
+
return /*#__PURE__*/React.createElement(Input, _extends({
|
|
895
|
+
type: "email",
|
|
896
|
+
validator: isEmail,
|
|
897
|
+
errorMessage: "Email address invalid",
|
|
898
|
+
value: value,
|
|
899
|
+
"data-test": dataTest,
|
|
900
|
+
icon: /*#__PURE__*/React.createElement(Icon, {
|
|
901
|
+
icon: "fas fa-envelope"
|
|
902
|
+
})
|
|
903
|
+
}, rest));
|
|
904
|
+
};
|
|
591
905
|
|
|
592
|
-
|
|
593
|
-
|
|
906
|
+
const Form = (_ref) => {
|
|
907
|
+
let {
|
|
908
|
+
children,
|
|
909
|
+
className = '',
|
|
910
|
+
onSubmit = noop,
|
|
911
|
+
onReset = noop,
|
|
912
|
+
autoComplete = 'off',
|
|
913
|
+
title,
|
|
914
|
+
error,
|
|
915
|
+
dataTest
|
|
916
|
+
} = _ref,
|
|
917
|
+
rest = _objectWithoutPropertiesLoose(_ref, ["children", "className", "onSubmit", "onReset", "autoComplete", "title", "error", "dataTest"]);
|
|
594
918
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
919
|
+
const handleSubmit = event => {
|
|
920
|
+
event.preventDefault();
|
|
921
|
+
onSubmit(event);
|
|
922
|
+
};
|
|
599
923
|
|
|
600
|
-
|
|
601
|
-
|
|
924
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
925
|
+
"data-test": dataTest
|
|
926
|
+
}, title && /*#__PURE__*/React.createElement("div", {
|
|
927
|
+
className: "level"
|
|
928
|
+
}, /*#__PURE__*/React.createElement("h1", {
|
|
929
|
+
className: "title is-size-4"
|
|
930
|
+
}, title)), error && /*#__PURE__*/React.createElement("div", {
|
|
931
|
+
className: "notification is-danger"
|
|
932
|
+
}, error), /*#__PURE__*/React.createElement("form", _extends({
|
|
933
|
+
onSubmit: handleSubmit,
|
|
934
|
+
onReset: onReset,
|
|
935
|
+
autoComplete: autoComplete,
|
|
936
|
+
className: classnames(['form', className])
|
|
937
|
+
}, rest), children));
|
|
938
|
+
};
|
|
939
|
+
Form.propTypes = {
|
|
940
|
+
children: PropTypes.node.isRequired,
|
|
941
|
+
className: PropTypes.string,
|
|
942
|
+
onSubmit: PropTypes.func,
|
|
943
|
+
onReset: PropTypes.func,
|
|
944
|
+
autoComplete: PropTypes.string
|
|
945
|
+
};
|
|
602
946
|
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
947
|
+
const PasswordInput = (_ref) => {
|
|
948
|
+
let {
|
|
949
|
+
value = ''
|
|
950
|
+
} = _ref,
|
|
951
|
+
rest = _objectWithoutPropertiesLoose(_ref, ["value"]);
|
|
606
952
|
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
953
|
+
return /*#__PURE__*/React.createElement(Input, _extends({
|
|
954
|
+
value: value,
|
|
955
|
+
type: "password"
|
|
956
|
+
}, rest));
|
|
957
|
+
};
|
|
610
958
|
|
|
611
|
-
|
|
612
|
-
|
|
959
|
+
const formComponents = {
|
|
960
|
+
string: Input,
|
|
961
|
+
password: PasswordInput,
|
|
962
|
+
boolean: Checkbox,
|
|
963
|
+
email: EmailInput
|
|
964
|
+
};
|
|
965
|
+
function FormBuilder(_ref) {
|
|
966
|
+
let {
|
|
967
|
+
schema,
|
|
968
|
+
formData,
|
|
969
|
+
onSubmit,
|
|
970
|
+
actionName,
|
|
971
|
+
children,
|
|
972
|
+
exclude = [],
|
|
973
|
+
remotes = [],
|
|
974
|
+
submitButton = true
|
|
975
|
+
} = _ref,
|
|
976
|
+
rest = _objectWithoutPropertiesLoose(_ref, ["schema", "formData", "title", "onSubmit", "actionName", "children", "exclude", "remotes", "submitButton"]);
|
|
613
977
|
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
978
|
+
const ref = React.useRef();
|
|
979
|
+
const {
|
|
980
|
+
properties,
|
|
981
|
+
required
|
|
982
|
+
} = schema;
|
|
983
|
+
const values = Object.assign({}, formData || {}); // build initial state
|
|
617
984
|
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
}
|
|
985
|
+
let initialState = {};
|
|
986
|
+
const fields = Object.keys(properties).filter(x => !exclude.includes(x));
|
|
987
|
+
fields.forEach(element => {
|
|
988
|
+
initialState[element] = values[element] || undefined;
|
|
989
|
+
}); // Register remotes
|
|
623
990
|
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
991
|
+
if (!ref.current) {
|
|
992
|
+
ref.current = {};
|
|
993
|
+
Object.keys(remotes).forEach(item => ref.current[item] = remotes[item]);
|
|
994
|
+
} else {
|
|
995
|
+
// apply remote changes
|
|
996
|
+
Object.keys(remotes).forEach(key => {
|
|
997
|
+
if (JSON.stringify(ref.current[key]) !== JSON.stringify(remotes[key])) {
|
|
998
|
+
ref.current[key] = remotes[key];
|
|
999
|
+
}
|
|
627
1000
|
});
|
|
628
1001
|
}
|
|
629
1002
|
|
|
630
|
-
|
|
631
|
-
const endpoint = `${getContainerFromPath(path)}@groups`;
|
|
632
|
-
return await this.rest.get(endpoint);
|
|
633
|
-
}
|
|
1003
|
+
ref.current = ref.current || {};
|
|
634
1004
|
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
}
|
|
1005
|
+
const onUpdate = field => ev => {
|
|
1006
|
+
ref.current[field] = ev.target ? ev.target.value : ev.value || ev;
|
|
1007
|
+
};
|
|
639
1008
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
const [
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
1009
|
+
const GetTag = ({
|
|
1010
|
+
field
|
|
1011
|
+
}) => {
|
|
1012
|
+
const Tag = formComponents[properties[field].widget || properties[field].type];
|
|
1013
|
+
const props = {
|
|
1014
|
+
label: properties[field].title,
|
|
1015
|
+
value: initialState[field],
|
|
1016
|
+
onChange: onUpdate(field),
|
|
1017
|
+
placeholder: properties[field].title || '',
|
|
1018
|
+
id: generateUID(),
|
|
1019
|
+
dataTest: `${field}TestInput`
|
|
647
1020
|
};
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
async getRoles(path) {
|
|
651
|
-
const endpoint = `${getContainerFromPath(path)}@available-roles`;
|
|
652
|
-
return await this.rest.get(endpoint);
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
async getAllPermissions(path) {
|
|
656
|
-
// paths used to query the API always has to start without a "/"
|
|
657
|
-
if (path.startsWith('/')) {
|
|
658
|
-
path = path.slice(1);
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
if (!path.endsWith('/')) {
|
|
662
|
-
path = `${path}/`;
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
const req = await this.rest.get(path + '@all_permissions');
|
|
666
|
-
const resp = await req.json();
|
|
667
|
-
const permissions = Array.from(new Set(extractPermissions(resp)));
|
|
668
|
-
return permissions;
|
|
669
|
-
}
|
|
670
1021
|
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
1022
|
+
if (required.includes(field)) {
|
|
1023
|
+
props.required = true;
|
|
1024
|
+
props.placeholder += ' *';
|
|
674
1025
|
}
|
|
675
1026
|
|
|
676
|
-
|
|
677
|
-
|
|
1027
|
+
Tag.displayName = `${field}Field`;
|
|
1028
|
+
return /*#__PURE__*/React.createElement(Tag, props);
|
|
1029
|
+
};
|
|
678
1030
|
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
const res = await types.json();
|
|
683
|
-
cacheTypes[path] = res;
|
|
684
|
-
}
|
|
685
|
-
}
|
|
1031
|
+
const children_ = React.Children.map(children, child => React.cloneElement(child, {
|
|
1032
|
+
onChange: onUpdate
|
|
1033
|
+
}));
|
|
686
1034
|
|
|
687
|
-
|
|
688
|
-
|
|
1035
|
+
const changes = () => {
|
|
1036
|
+
onSubmit(ref.current, values);
|
|
1037
|
+
};
|
|
689
1038
|
|
|
1039
|
+
return /*#__PURE__*/React.createElement(Form, _extends({
|
|
1040
|
+
onSubmit: changes
|
|
1041
|
+
}, rest), fields.map(field => /*#__PURE__*/React.createElement(GetTag, {
|
|
1042
|
+
field: field,
|
|
1043
|
+
key: field
|
|
1044
|
+
})), children_, submitButton && /*#__PURE__*/React.createElement(Button, null, actionName));
|
|
690
1045
|
}
|
|
691
|
-
function getClient(url, auth, isContainer = false) {
|
|
692
|
-
return new GuillotinaClient(new RestClient(url, auth), isContainer);
|
|
693
|
-
}
|
|
694
|
-
const getContainerFromPath = path => {
|
|
695
|
-
if (path.startsWith('/')) {
|
|
696
|
-
path = path.substring(1);
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
let parts = path.split('/');
|
|
700
|
-
return `${parts[0]}/${parts[1]}/`;
|
|
701
|
-
};
|
|
702
|
-
const lightFileReader = async file => {
|
|
703
|
-
return new Promise(resolve => {
|
|
704
|
-
const reader = new FileReader();
|
|
705
|
-
reader.readAsArrayBuffer(file);
|
|
706
1046
|
|
|
707
|
-
|
|
708
|
-
const fileData = e.target.result;
|
|
709
|
-
resolve({
|
|
710
|
-
filename: file.name.normalize('NFD').replace(/[\u0300-\u036f]/g, ''),
|
|
711
|
-
data: fileData,
|
|
712
|
-
'content-type': file.type
|
|
713
|
-
});
|
|
714
|
-
};
|
|
715
|
-
});
|
|
716
|
-
};
|
|
1047
|
+
/** @type any */
|
|
717
1048
|
|
|
718
|
-
const
|
|
719
|
-
let
|
|
1049
|
+
const Select = React.forwardRef((_ref, ref) => {
|
|
1050
|
+
let {
|
|
1051
|
+
options,
|
|
1052
|
+
error,
|
|
1053
|
+
errorZoneClassName,
|
|
1054
|
+
size = 1,
|
|
1055
|
+
placeholder,
|
|
1056
|
+
id,
|
|
1057
|
+
className = '',
|
|
1058
|
+
classWrap = '',
|
|
1059
|
+
multiple = false,
|
|
1060
|
+
loading = false,
|
|
1061
|
+
onChange,
|
|
1062
|
+
appendDefault = false,
|
|
1063
|
+
style = {},
|
|
1064
|
+
dataTest
|
|
1065
|
+
} = _ref,
|
|
1066
|
+
rest = _objectWithoutPropertiesLoose(_ref, ["options", "error", "errorZoneClassName", "size", "placeholder", "id", "className", "classWrap", "multiple", "loading", "isSubmitted", "onChange", "appendDefault", "style", "dataTest"]);
|
|
720
1067
|
|
|
721
|
-
|
|
722
|
-
result = result.concat([data.permission]);
|
|
723
|
-
} else if (!Array.isArray(data)) {
|
|
724
|
-
Object.keys(data).map(key => result = result.concat(extractPermissions(data[key])));
|
|
725
|
-
} else if (Array.isArray(data)) {
|
|
726
|
-
data.map(item => result = result.concat(extractPermissions(item)));
|
|
727
|
-
}
|
|
1068
|
+
const [uid] = useState(generateUID('select'));
|
|
728
1069
|
|
|
729
|
-
|
|
730
|
-
|
|
1070
|
+
const onUpdate = ev => {
|
|
1071
|
+
if (ev.target.value === '') {
|
|
1072
|
+
onChange({
|
|
1073
|
+
target: {
|
|
1074
|
+
value: undefined
|
|
1075
|
+
}
|
|
1076
|
+
});
|
|
1077
|
+
} else {
|
|
1078
|
+
onChange(ev);
|
|
1079
|
+
}
|
|
1080
|
+
};
|
|
731
1081
|
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
1082
|
+
if (appendDefault) {
|
|
1083
|
+
options = [{
|
|
1084
|
+
text: 'Choose..',
|
|
1085
|
+
value: ''
|
|
1086
|
+
}].concat(options);
|
|
1087
|
+
}
|
|
735
1088
|
|
|
736
|
-
|
|
737
|
-
|
|
1089
|
+
const statusClasses = error ? 'is-danger' : '';
|
|
1090
|
+
const cssWrap = ['select', statusClasses, multiple ? 'is-multiple' : '', classWrap];
|
|
1091
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
1092
|
+
className: "field"
|
|
1093
|
+
}, id && placeholder ? /*#__PURE__*/React.createElement("label", {
|
|
1094
|
+
className: "label",
|
|
1095
|
+
htmlFor: id
|
|
1096
|
+
}, placeholder) : null, /*#__PURE__*/React.createElement("div", {
|
|
1097
|
+
className: classnames(cssWrap)
|
|
1098
|
+
}, /*#__PURE__*/React.createElement("select", _extends({
|
|
1099
|
+
className: classnames(['', className]),
|
|
1100
|
+
size: size,
|
|
1101
|
+
multiple: multiple,
|
|
1102
|
+
disabled: loading || rest.disabled,
|
|
1103
|
+
onChange: onUpdate
|
|
1104
|
+
}, rest, {
|
|
1105
|
+
ref: ref,
|
|
1106
|
+
style: style,
|
|
1107
|
+
"data-test": dataTest
|
|
1108
|
+
}), options.map((_ref2, index) => {
|
|
738
1109
|
let {
|
|
739
|
-
|
|
740
|
-
} =
|
|
741
|
-
|
|
1110
|
+
text
|
|
1111
|
+
} = _ref2,
|
|
1112
|
+
rest = _objectWithoutPropertiesLoose(_ref2, ["text"]);
|
|
742
1113
|
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
1114
|
+
return /*#__PURE__*/React.createElement("option", _extends({
|
|
1115
|
+
key: index.toString()
|
|
1116
|
+
}, rest), text);
|
|
1117
|
+
}))), error && /*#__PURE__*/React.createElement(ErrorZone, {
|
|
1118
|
+
className: errorZoneClassName,
|
|
1119
|
+
id: uid
|
|
1120
|
+
}, error ? error : ''));
|
|
1121
|
+
});
|
|
1122
|
+
Select.propTypes = {
|
|
1123
|
+
error: PropTypes.string,
|
|
1124
|
+
disabled: PropTypes.bool,
|
|
1125
|
+
loading: PropTypes.bool,
|
|
1126
|
+
isSubmitted: PropTypes.bool,
|
|
1127
|
+
size: PropTypes.number,
|
|
1128
|
+
onChange: PropTypes.func,
|
|
1129
|
+
options: PropTypes.arrayOf(PropTypes.object),
|
|
1130
|
+
multiple: PropTypes.bool,
|
|
1131
|
+
className: PropTypes.string
|
|
1132
|
+
};
|
|
746
1133
|
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
this.
|
|
751
|
-
|
|
752
|
-
payload: {
|
|
753
|
-
transparent
|
|
754
|
-
}
|
|
755
|
-
});
|
|
1134
|
+
class RestClient {
|
|
1135
|
+
constructor(url, container, auth) {
|
|
1136
|
+
this.auth = auth;
|
|
1137
|
+
this.url = url;
|
|
1138
|
+
this.container = container;
|
|
756
1139
|
}
|
|
757
1140
|
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
1141
|
+
async request(path, data, headers) {
|
|
1142
|
+
if (path.indexOf(this.url) !== -1) {
|
|
1143
|
+
path = path.replace(this.url, '');
|
|
1144
|
+
}
|
|
761
1145
|
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
1146
|
+
if (this.container !== '/' && path.indexOf(this.container) === -1) {
|
|
1147
|
+
path = `${this.container}${path}`;
|
|
1148
|
+
}
|
|
765
1149
|
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
1150
|
+
if (!path.startsWith('/')) {
|
|
1151
|
+
path = `/${path}`;
|
|
1152
|
+
}
|
|
769
1153
|
|
|
770
|
-
|
|
771
|
-
|
|
1154
|
+
data = data || {};
|
|
1155
|
+
data.headers = headers || this.getHeaders();
|
|
1156
|
+
return await fetch(`${this.url}${path}`, data);
|
|
772
1157
|
}
|
|
773
1158
|
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
1159
|
+
getHeaders() {
|
|
1160
|
+
const authToken = this.auth.getToken();
|
|
1161
|
+
if (!authToken) return {};
|
|
1162
|
+
return {
|
|
1163
|
+
Accept: 'application/json',
|
|
1164
|
+
'Content-Type': 'application/json',
|
|
1165
|
+
Authorization: 'Bearer ' + authToken
|
|
1166
|
+
};
|
|
780
1167
|
}
|
|
781
1168
|
|
|
782
|
-
|
|
783
|
-
this.
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
flash: {
|
|
787
|
-
message,
|
|
788
|
-
type
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
});
|
|
792
|
-
window.scrollTo({
|
|
793
|
-
top: 0,
|
|
794
|
-
left: 0,
|
|
795
|
-
behavior: 'smooth'
|
|
1169
|
+
async post(path, data) {
|
|
1170
|
+
return await this.request(path, {
|
|
1171
|
+
method: 'post',
|
|
1172
|
+
body: JSON.stringify(data)
|
|
796
1173
|
});
|
|
797
1174
|
}
|
|
798
1175
|
|
|
799
|
-
|
|
800
|
-
this.
|
|
801
|
-
type: 'CLEAR_FLASH'
|
|
802
|
-
});
|
|
1176
|
+
async get(path) {
|
|
1177
|
+
return await this.request(path, {});
|
|
803
1178
|
}
|
|
804
1179
|
|
|
805
|
-
|
|
806
|
-
this.
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
action,
|
|
810
|
-
params
|
|
811
|
-
}
|
|
1180
|
+
async put(path, data) {
|
|
1181
|
+
return await this.request(path, {
|
|
1182
|
+
method: 'put',
|
|
1183
|
+
body: JSON.stringify(data)
|
|
812
1184
|
});
|
|
813
1185
|
}
|
|
814
1186
|
|
|
815
|
-
|
|
816
|
-
this.
|
|
817
|
-
|
|
1187
|
+
async patch(path, data) {
|
|
1188
|
+
return await this.request(path, {
|
|
1189
|
+
method: 'PATCH',
|
|
1190
|
+
body: JSON.stringify(data)
|
|
818
1191
|
});
|
|
819
1192
|
}
|
|
820
1193
|
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
result[item] = tabs[item];
|
|
832
|
-
} else if (!perm) {
|
|
833
|
-
result[item] = tabs[item];
|
|
834
|
-
}
|
|
835
|
-
});
|
|
836
|
-
return result;
|
|
1194
|
+
async upload(path, data) {
|
|
1195
|
+
const headers = this.getHeaders();
|
|
1196
|
+
delete headers['Content-Type'];
|
|
1197
|
+
headers['Content-Type'] = data['content-type'];
|
|
1198
|
+
headers['X-UPLOAD-FILENAME'] = data.filename;
|
|
1199
|
+
headers['Content-Encoding'] = 'base64';
|
|
1200
|
+
return await this.request(path, {
|
|
1201
|
+
method: 'PATCH',
|
|
1202
|
+
body: data.data
|
|
1203
|
+
}, headers);
|
|
837
1204
|
}
|
|
838
1205
|
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
}
|
|
845
|
-
props = _objectWithoutPropertiesLoose(_ref2, ["children"]);
|
|
846
|
-
|
|
847
|
-
return /*#__PURE__*/React.createElement(TraversalContext.Provider, {
|
|
848
|
-
value: new Traversal(props)
|
|
849
|
-
}, children);
|
|
850
|
-
}
|
|
851
|
-
function useTraversal() {
|
|
852
|
-
return React.useContext(TraversalContext);
|
|
853
|
-
}
|
|
854
|
-
function ClientProvider({
|
|
855
|
-
children,
|
|
856
|
-
client
|
|
857
|
-
}) {
|
|
858
|
-
return /*#__PURE__*/React.createElement(ClientContext.Provider, {
|
|
859
|
-
value: client
|
|
860
|
-
}, children);
|
|
861
|
-
}
|
|
862
|
-
function useGuillotinaClient() {
|
|
863
|
-
return React.useContext(ClientContext);
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
const noop$1 = () => {};
|
|
867
|
-
|
|
868
|
-
const Button = (_ref) => {
|
|
869
|
-
let {
|
|
870
|
-
children,
|
|
871
|
-
className = 'is-primary',
|
|
872
|
-
onClick,
|
|
873
|
-
type = 'submit',
|
|
874
|
-
loading = false,
|
|
875
|
-
disabled = false,
|
|
876
|
-
dataTest
|
|
877
|
-
} = _ref,
|
|
878
|
-
rest = _objectWithoutPropertiesLoose(_ref, ["children", "className", "onClick", "type", "loading", "disabled", "dataTest"]);
|
|
879
|
-
|
|
880
|
-
let css = [].concat('button', ...className.split(' '));
|
|
881
|
-
if (loading) css = css.concat('is-loading');
|
|
882
|
-
if (disabled) onClick = noop$1;
|
|
883
|
-
return /*#__PURE__*/React.createElement("p", {
|
|
884
|
-
className: "control"
|
|
885
|
-
}, /*#__PURE__*/React.createElement("button", _extends({
|
|
886
|
-
type: type,
|
|
887
|
-
className: classnames(css),
|
|
888
|
-
onClick: onClick,
|
|
889
|
-
disabled: disabled
|
|
890
|
-
}, rest, {
|
|
891
|
-
"data-test": dataTest
|
|
892
|
-
}), children));
|
|
893
|
-
};
|
|
894
|
-
|
|
895
|
-
function Modal(props) {
|
|
896
|
-
const {
|
|
897
|
-
isActive,
|
|
898
|
-
setActive,
|
|
899
|
-
children
|
|
900
|
-
} = props;
|
|
901
|
-
const {
|
|
902
|
-
Portal
|
|
903
|
-
} = usePortal();
|
|
904
|
-
const css = 'modal ' + (isActive ? 'is-active ' : '') + props.className;
|
|
905
|
-
return /*#__PURE__*/React.createElement(Portal, null, /*#__PURE__*/React.createElement("div", {
|
|
906
|
-
className: css
|
|
907
|
-
}, /*#__PURE__*/React.createElement("div", {
|
|
908
|
-
className: "modal-background",
|
|
909
|
-
onClick: () => setActive(false)
|
|
910
|
-
}), /*#__PURE__*/React.createElement("div", {
|
|
911
|
-
className: "modal-content"
|
|
912
|
-
}, /*#__PURE__*/React.createElement("div", {
|
|
913
|
-
className: "box"
|
|
914
|
-
}, children)), /*#__PURE__*/React.createElement("button", {
|
|
915
|
-
className: "modal-close is-large",
|
|
916
|
-
"aria-label": "close",
|
|
917
|
-
onClick: () => setActive(false)
|
|
918
|
-
})));
|
|
919
|
-
}
|
|
920
|
-
function Confirm({
|
|
921
|
-
message,
|
|
922
|
-
onCancel,
|
|
923
|
-
onConfirm,
|
|
924
|
-
loading
|
|
925
|
-
}) {
|
|
926
|
-
const setActive = () => onCancel();
|
|
1206
|
+
async delete(path, data = undefined) {
|
|
1207
|
+
return await this.request(path, {
|
|
1208
|
+
method: 'delete',
|
|
1209
|
+
body: JSON.stringify(data)
|
|
1210
|
+
});
|
|
1211
|
+
}
|
|
927
1212
|
|
|
928
|
-
|
|
929
|
-
isActive: true,
|
|
930
|
-
setActive: setActive,
|
|
931
|
-
className: "confirm"
|
|
932
|
-
}, /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("h1", {
|
|
933
|
-
className: "title is-size-5"
|
|
934
|
-
}, message || 'Are you Sure?'), /*#__PURE__*/React.createElement("div", {
|
|
935
|
-
className: "level",
|
|
936
|
-
style: {
|
|
937
|
-
marginTop: 50
|
|
938
|
-
}
|
|
939
|
-
}, /*#__PURE__*/React.createElement("div", {
|
|
940
|
-
className: "level-left"
|
|
941
|
-
}), /*#__PURE__*/React.createElement("div", {
|
|
942
|
-
className: "level-right"
|
|
943
|
-
}, /*#__PURE__*/React.createElement("button", {
|
|
944
|
-
className: "button is-danger",
|
|
945
|
-
onClick: () => onCancel()
|
|
946
|
-
}, "Cancel"), "\xA0\xA0", /*#__PURE__*/React.createElement(Button, {
|
|
947
|
-
loading: loading,
|
|
948
|
-
className: "is-success",
|
|
949
|
-
onClick: () => onConfirm(),
|
|
950
|
-
dataTest: "btnConfirmModalTest"
|
|
951
|
-
}, "Confirm")))));
|
|
952
|
-
} // @todo Improve it... Replacing the inputText to a tree
|
|
1213
|
+
}
|
|
953
1214
|
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
1215
|
+
const Loading = (_ref) => {
|
|
1216
|
+
let rest = _extends({}, _ref);
|
|
1217
|
+
|
|
1218
|
+
return /*#__PURE__*/React.createElement("div", _extends({
|
|
1219
|
+
className: "progress-line"
|
|
1220
|
+
}, rest));
|
|
1221
|
+
};
|
|
1222
|
+
|
|
1223
|
+
const Tag = ({
|
|
1224
|
+
name,
|
|
1225
|
+
onRemove,
|
|
1226
|
+
size: _size = 'is-medium',
|
|
1227
|
+
color: _color = 'is-warning'
|
|
1228
|
+
}) => /*#__PURE__*/React.createElement("span", {
|
|
1229
|
+
className: classnames(['tag', _color, _size])
|
|
1230
|
+
}, name, onRemove !== undefined && /*#__PURE__*/React.createElement("button", {
|
|
1231
|
+
className: "delete is-small",
|
|
1232
|
+
onClick: () => onRemove()
|
|
1233
|
+
}));
|
|
1234
|
+
|
|
1235
|
+
function Delete({
|
|
1236
|
+
onClick,
|
|
1237
|
+
className,
|
|
1238
|
+
children
|
|
960
1239
|
}) {
|
|
961
|
-
return /*#__PURE__*/React.createElement(
|
|
962
|
-
isActive: true,
|
|
963
|
-
setActive: onCancel
|
|
964
|
-
}, /*#__PURE__*/React.createElement("h1", null, title), /*#__PURE__*/React.createElement("form", {
|
|
965
|
-
onSubmit: e => {
|
|
966
|
-
e.preventDefault();
|
|
967
|
-
onConfirm(e.target[0].value, e.target);
|
|
968
|
-
}
|
|
969
|
-
}, /*#__PURE__*/React.createElement("input", {
|
|
970
|
-
className: "input",
|
|
971
|
-
placeholder: "/folder (without /db/container on front)",
|
|
972
|
-
style: {
|
|
973
|
-
margin: '20px 0'
|
|
974
|
-
},
|
|
975
|
-
defaultValue: defaultPath,
|
|
976
|
-
type: "text"
|
|
977
|
-
}), children, /*#__PURE__*/React.createElement("div", {
|
|
978
|
-
className: "level-right"
|
|
979
|
-
}, /*#__PURE__*/React.createElement("button", {
|
|
1240
|
+
return /*#__PURE__*/React.createElement("button", {
|
|
980
1241
|
type: "button",
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
className: "button is-success"
|
|
986
|
-
}, "Confirm"))));
|
|
1242
|
+
onClick: onClick,
|
|
1243
|
+
className: `delete ${className}`,
|
|
1244
|
+
"data-test": "btnDeleteTest"
|
|
1245
|
+
}, children);
|
|
987
1246
|
}
|
|
988
1247
|
|
|
989
|
-
function
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
1248
|
+
function Table({
|
|
1249
|
+
headers,
|
|
1250
|
+
children,
|
|
1251
|
+
className
|
|
1252
|
+
}) {
|
|
1253
|
+
className = className ? className.split(' ') : ' is-full is-fullwidth is-narrow'.split(' ');
|
|
1254
|
+
return /*#__PURE__*/React.createElement("table", {
|
|
1255
|
+
className: classnames(['table', ...className])
|
|
1256
|
+
}, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, headers && headers.map((item, idx) => /*#__PURE__*/React.createElement("th", {
|
|
1257
|
+
key: item + idx
|
|
1258
|
+
}, item)))), /*#__PURE__*/React.createElement("tbody", null, children));
|
|
995
1259
|
}
|
|
996
1260
|
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1261
|
+
function Notification({
|
|
1262
|
+
isColor = '',
|
|
1263
|
+
children
|
|
1264
|
+
}) {
|
|
1265
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
1266
|
+
className: 'notification is-' + isColor,
|
|
1267
|
+
"data-test": "notificationTest"
|
|
1268
|
+
}, children);
|
|
1269
|
+
}
|
|
1004
1270
|
|
|
1005
|
-
|
|
1006
|
-
if (dataError && dataError.details) {
|
|
1007
|
-
return dataError.details;
|
|
1008
|
-
} else if (dataError && dataError.reason) {
|
|
1009
|
-
return dataError.reason;
|
|
1010
|
-
}
|
|
1271
|
+
// https://github.com/molefrog/wouter
|
|
1011
1272
|
|
|
1012
|
-
|
|
1013
|
-
};
|
|
1273
|
+
const setURLParams = p => window.history['pushState'](0, 0, (window.history.pathname || '') + '?' + p.toString().replace(/%2F/g, '/'));
|
|
1014
1274
|
|
|
1015
|
-
const
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
result: ready_body ? await res.json() : res.status,
|
|
1020
|
-
response: res
|
|
1021
|
-
};else return {
|
|
1022
|
-
isError: true,
|
|
1023
|
-
loading: false,
|
|
1024
|
-
errorMessage: getErrorMessage(await res.json(), res.status),
|
|
1025
|
-
response: res
|
|
1026
|
-
};
|
|
1275
|
+
const clean = to => {
|
|
1276
|
+
const current = new URLSearchParams();
|
|
1277
|
+
Object.keys(to).forEach(_key => current.set(_key, to[_key]));
|
|
1278
|
+
setURLParams(current);
|
|
1027
1279
|
};
|
|
1028
1280
|
|
|
1029
|
-
const
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1281
|
+
const useLocation = () => {
|
|
1282
|
+
const [path, update] = useState(currentSearchParams());
|
|
1283
|
+
const prevPath = useRef(path);
|
|
1284
|
+
useEffect(() => {
|
|
1285
|
+
patchHistoryEvents(); // this function checks if the location has been changed since the
|
|
1286
|
+
// last render and updates the state only when needed.
|
|
1287
|
+
// unfortunately, we can't rely on `path` value here, since it can be stale,
|
|
1288
|
+
// that's why we store the last pathname in a ref.
|
|
1034
1289
|
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
newState = await processResponse(res, body);
|
|
1039
|
-
} catch (e) {
|
|
1040
|
-
console.error('Error', e);
|
|
1041
|
-
newState = {
|
|
1042
|
-
isError: true,
|
|
1043
|
-
errorMessage: 'unhandled exception'
|
|
1290
|
+
const checkForUpdates = () => {
|
|
1291
|
+
const pathname = currentSearchParams();
|
|
1292
|
+
prevPath.current !== pathname && update(prevPath.current = pathname);
|
|
1044
1293
|
};
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
setState(newState);
|
|
1048
|
-
return newState;
|
|
1049
|
-
};
|
|
1050
|
-
|
|
1051
|
-
const del = (setState, Ctx) => async (data, endpoint, body = false) => {
|
|
1052
|
-
setState({
|
|
1053
|
-
loading: true
|
|
1054
|
-
});
|
|
1055
|
-
let newState = {};
|
|
1056
1294
|
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
} catch (e) {
|
|
1062
|
-
console.error('Error', e);
|
|
1063
|
-
newState = {
|
|
1064
|
-
isError: true,
|
|
1065
|
-
errorMessage: 'unhandled exception'
|
|
1066
|
-
};
|
|
1067
|
-
}
|
|
1295
|
+
const events = ['popstate', 'pushState', 'replaceState'];
|
|
1296
|
+
events.map(e => window.addEventListener(e, checkForUpdates)); // it's possible that an update has occurred between render and the effect handler,
|
|
1297
|
+
// so we run additional check on mount to catch these updates. Based on:
|
|
1298
|
+
// https://gist.github.com/bvaughn/e25397f70e8c65b0ae0d7c90b731b189
|
|
1068
1299
|
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
};
|
|
1300
|
+
checkForUpdates();
|
|
1301
|
+
return () => events.map(e => window.removeEventListener(e, checkForUpdates));
|
|
1302
|
+
}, []); // the 2nd argument of the `useLocation` return value is a function
|
|
1303
|
+
// that allows to perform a navigation.
|
|
1304
|
+
//
|
|
1305
|
+
// the function reference should stay the same between re-renders, so that
|
|
1306
|
+
// it can be passed down as an element prop without any performance concerns.
|
|
1072
1307
|
|
|
1073
|
-
const
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1308
|
+
const navigate = useCallback((to, replace) => {
|
|
1309
|
+
if (replace) {
|
|
1310
|
+
clean(to);
|
|
1311
|
+
return;
|
|
1312
|
+
}
|
|
1078
1313
|
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1314
|
+
let current = new URLSearchParams(path.toString());
|
|
1315
|
+
Object.keys(to).forEach(_key => current.set(_key, to[_key]));
|
|
1316
|
+
setURLParams(current);
|
|
1317
|
+
}, [path]);
|
|
1318
|
+
const remove = useCallback(param => {
|
|
1319
|
+
let current = new URLSearchParams(path.toString());
|
|
1320
|
+
current.delete(param);
|
|
1321
|
+
setURLParams(current);
|
|
1322
|
+
}, [path]);
|
|
1323
|
+
return [path, navigate, remove];
|
|
1324
|
+
}; // While History API does have `popstate` event, the only
|
|
1325
|
+
// proper way to listen to changes via `push/replaceState`
|
|
1326
|
+
// is to monkey-patch these methods.
|
|
1327
|
+
//
|
|
1328
|
+
// See https://stackoverflow.com/a/4585031
|
|
1090
1329
|
|
|
1091
|
-
|
|
1092
|
-
return newState;
|
|
1093
|
-
};
|
|
1330
|
+
let patched = 0;
|
|
1094
1331
|
|
|
1095
|
-
const
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1332
|
+
const patchHistoryEvents = () => {
|
|
1333
|
+
if (patched) return;
|
|
1334
|
+
['pushState', 'replaceState'].map(type => {
|
|
1335
|
+
const original = window.history[type];
|
|
1336
|
+
|
|
1337
|
+
window.history[type] = function () {
|
|
1338
|
+
const result = original.apply(this, arguments);
|
|
1339
|
+
const event = new Event(type);
|
|
1340
|
+
event.arguments = arguments;
|
|
1341
|
+
dispatchEvent(event);
|
|
1342
|
+
return result;
|
|
1343
|
+
};
|
|
1106
1344
|
});
|
|
1107
|
-
return
|
|
1345
|
+
return patched = 1;
|
|
1108
1346
|
};
|
|
1109
1347
|
|
|
1110
|
-
|
|
1111
|
-
const Ctx = useTraversal();
|
|
1112
|
-
const [state, setState] = useSetState(initial);
|
|
1113
|
-
return _extends({}, state, {
|
|
1114
|
-
Ctx,
|
|
1115
|
-
patch: patch(setState, Ctx),
|
|
1116
|
-
del: del(setState, Ctx),
|
|
1117
|
-
post: post(setState, Ctx),
|
|
1118
|
-
get: get(setState, Ctx)
|
|
1119
|
-
});
|
|
1120
|
-
}
|
|
1348
|
+
const currentSearchParams = (path = window.location.search) => new URLSearchParams(path);
|
|
1121
1349
|
|
|
1122
|
-
function
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
} =
|
|
1128
|
-
|
|
1129
|
-
type
|
|
1130
|
-
} = props;
|
|
1131
|
-
const {
|
|
1132
|
-
getForm
|
|
1133
|
-
} = Ctx.registry;
|
|
1134
|
-
const Form = getForm(type);
|
|
1350
|
+
function Link(_ref) {
|
|
1351
|
+
let {
|
|
1352
|
+
aRef,
|
|
1353
|
+
model,
|
|
1354
|
+
children
|
|
1355
|
+
} = _ref,
|
|
1356
|
+
props = _objectWithoutPropertiesLoose(_ref, ["aRef", "model", "children"]);
|
|
1135
1357
|
|
|
1136
|
-
const
|
|
1137
|
-
|
|
1358
|
+
const [path, navigate] = useLocation();
|
|
1359
|
+
const aStyle = {
|
|
1360
|
+
textDecoration: 'none',
|
|
1361
|
+
color: 'currentColor'
|
|
1138
1362
|
};
|
|
1139
1363
|
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1364
|
+
function onClick(e) {
|
|
1365
|
+
e.stopPropagation();
|
|
1366
|
+
if (actAsLink(e)) return;
|
|
1367
|
+
e.preventDefault();
|
|
1368
|
+
navigate({
|
|
1369
|
+
path: model.path
|
|
1370
|
+
}, true);
|
|
1371
|
+
if (props.onClick) props.onClick(e);
|
|
1372
|
+
}
|
|
1148
1373
|
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1374
|
+
return /*#__PURE__*/React.createElement("a", _extends({}, props, {
|
|
1375
|
+
ref: aRef,
|
|
1376
|
+
href: `?${path}${model.id}/`,
|
|
1377
|
+
style: aStyle,
|
|
1378
|
+
onClick: onClick
|
|
1379
|
+
}), children);
|
|
1380
|
+
}
|
|
1154
1381
|
|
|
1155
|
-
|
|
1156
|
-
|
|
1382
|
+
function actAsLink(e) {
|
|
1383
|
+
return e.ctrlKey || e.metaKey || e.altKey || e.shiftKey || e.button !== 0;
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
function TdLink(_ref) {
|
|
1387
|
+
let {
|
|
1388
|
+
model,
|
|
1389
|
+
children
|
|
1390
|
+
} = _ref,
|
|
1391
|
+
props = _objectWithoutPropertiesLoose(_ref, ["model", "children"]);
|
|
1392
|
+
|
|
1393
|
+
const link = useRef();
|
|
1394
|
+
|
|
1395
|
+
function onClick() {
|
|
1396
|
+
link.current.click();
|
|
1157
1397
|
}
|
|
1158
1398
|
|
|
1159
|
-
return /*#__PURE__*/React.createElement(
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
onError: err => console.log(err),
|
|
1166
|
-
actionName: 'Add ' + type,
|
|
1167
|
-
title: 'Add ' + type,
|
|
1168
|
-
type: type,
|
|
1169
|
-
dataTest: `formAdd${type}Test`
|
|
1170
|
-
}));
|
|
1399
|
+
return /*#__PURE__*/React.createElement("td", _extends({}, props, {
|
|
1400
|
+
onClick: onClick
|
|
1401
|
+
}), /*#__PURE__*/React.createElement(Link, {
|
|
1402
|
+
model: model,
|
|
1403
|
+
aRef: link
|
|
1404
|
+
}, children));
|
|
1171
1405
|
}
|
|
1172
1406
|
|
|
1173
|
-
const
|
|
1174
|
-
const
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
SearchEngine: 'PostreSQL' // Elasticsearch
|
|
1407
|
+
const SEP = '=';
|
|
1408
|
+
const DEFAULT_FIELD = 'title__in';
|
|
1409
|
+
const CLEANER = '||';
|
|
1410
|
+
function parser(qs, defaultField = DEFAULT_FIELD) {
|
|
1411
|
+
let lastKey = undefined;
|
|
1412
|
+
qs.trim();
|
|
1180
1413
|
|
|
1181
|
-
|
|
1182
|
-
|
|
1414
|
+
if (qs.includes('"')) {
|
|
1415
|
+
qs = qs.replace(/"(\w+) (\w+)"/, `$1${CLEANER}$2`);
|
|
1416
|
+
}
|
|
1183
1417
|
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
rest[item] = [].concat(Config[item], additional[item]);
|
|
1189
|
-
} else if (typeof Config[item] === 'object') {
|
|
1190
|
-
rest[item] = Object.assign({}, Config[item], additional[item]);
|
|
1191
|
-
} else {
|
|
1192
|
-
rest[item] = additional[item];
|
|
1418
|
+
qs = qs.split(' ');
|
|
1419
|
+
return qs.map(part => {
|
|
1420
|
+
if (part.includes(CLEANER)) {
|
|
1421
|
+
part = part.replace('||', ' ');
|
|
1193
1422
|
}
|
|
1194
|
-
});
|
|
1195
|
-
return rest;
|
|
1196
|
-
};
|
|
1197
1423
|
|
|
1198
|
-
|
|
1199
|
-
|
|
1424
|
+
if (!part.includes(SEP)) {
|
|
1425
|
+
return !lastKey ? [defaultField, part] : [lastKey, part];
|
|
1426
|
+
}
|
|
1200
1427
|
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
// }
|
|
1428
|
+
const [key, val] = part.split(SEP);
|
|
1429
|
+
lastKey = key;
|
|
1430
|
+
return [key, val];
|
|
1431
|
+
});
|
|
1432
|
+
}
|
|
1433
|
+
function buildQs(parsedQuery) {
|
|
1434
|
+
return parsedQuery.map(([key, val]) => `${encodeURIComponent(key)}=${encodeURIComponent(val)}`).join('&');
|
|
1435
|
+
}
|
|
1210
1436
|
|
|
1437
|
+
let cacheTypes = {};
|
|
1438
|
+
let cacheSchemas = {};
|
|
1439
|
+
class GuillotinaClient {
|
|
1440
|
+
constructor(rest, pathContainsContainer) {
|
|
1441
|
+
this.getContainerFromPath = path => {
|
|
1442
|
+
if (this.pathContainsContainer) {
|
|
1443
|
+
if (path.startsWith('/')) {
|
|
1444
|
+
path = path.substring(1);
|
|
1445
|
+
}
|
|
1211
1446
|
|
|
1212
|
-
|
|
1213
|
-
}
|
|
1447
|
+
let parts = path.split('/');
|
|
1448
|
+
return `${parts[0]}/${parts[1]}/`;
|
|
1449
|
+
}
|
|
1214
1450
|
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
return item['@id'];
|
|
1218
|
-
}
|
|
1451
|
+
return '';
|
|
1452
|
+
};
|
|
1219
1453
|
|
|
1220
|
-
|
|
1221
|
-
|
|
1454
|
+
this.clearContainerFromPath = path => {
|
|
1455
|
+
if (this.pathContainsContainer) {
|
|
1456
|
+
return `/${this.cleanPath(path)}`;
|
|
1457
|
+
}
|
|
1222
1458
|
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
const cfg = useConfig();
|
|
1226
|
-
const [loading, setLoading] = React.useState(false);
|
|
1227
|
-
const {
|
|
1228
|
-
items = []
|
|
1229
|
-
} = props;
|
|
1230
|
-
const last = items[items.length - 1]['@name'];
|
|
1231
|
-
const itemsNames = items.map(item => item['@name']).join(', ').replace(`, ${last}`, ` and ${last}`);
|
|
1459
|
+
return path;
|
|
1460
|
+
};
|
|
1232
1461
|
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
const actions = items.map(async item => {
|
|
1237
|
-
console.log(item);
|
|
1238
|
-
const res = await Ctx.client.delete(getId(item));
|
|
1462
|
+
this.rest = rest;
|
|
1463
|
+
this.pathContainsContainer = pathContainsContainer;
|
|
1464
|
+
}
|
|
1239
1465
|
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
}); // this sleep is here, to let elasticsearch, wait for
|
|
1245
|
-
// index our operations... (will work 99% of use cases)
|
|
1466
|
+
async getContext(path) {
|
|
1467
|
+
switch (path) {
|
|
1468
|
+
case '/':
|
|
1469
|
+
return await this.rest.get('');
|
|
1246
1470
|
|
|
1247
|
-
|
|
1248
|
-
|
|
1471
|
+
default:
|
|
1472
|
+
if (path.startsWith('/')) {
|
|
1473
|
+
path = path.substring(1);
|
|
1474
|
+
}
|
|
1249
1475
|
|
|
1250
|
-
|
|
1251
|
-
Ctx.flash(`Items removed!`, 'success');
|
|
1252
|
-
Ctx.refresh();
|
|
1253
|
-
} else {
|
|
1254
|
-
const errorstr = errors.map(err => JSON.stringify(err)).join('\n');
|
|
1255
|
-
Ctx.flash(`Something went wrong!! ${errorstr}`, 'danger');
|
|
1476
|
+
return await this.rest.get(path);
|
|
1256
1477
|
}
|
|
1257
|
-
|
|
1258
|
-
setLoading(false);
|
|
1259
|
-
Ctx.cancelAction();
|
|
1260
1478
|
}
|
|
1261
1479
|
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
message: `Are you sure to remove: ${itemsNames}?`
|
|
1267
|
-
});
|
|
1268
|
-
}
|
|
1269
|
-
|
|
1270
|
-
const Checkbox = (_ref) => {
|
|
1271
|
-
let {
|
|
1272
|
-
id,
|
|
1273
|
-
className,
|
|
1274
|
-
classNameInput,
|
|
1275
|
-
loading,
|
|
1276
|
-
disabled,
|
|
1277
|
-
indeterminate = false,
|
|
1278
|
-
value = false,
|
|
1279
|
-
children,
|
|
1280
|
-
placeholder,
|
|
1281
|
-
onChange,
|
|
1282
|
-
dataTest
|
|
1283
|
-
} = _ref,
|
|
1284
|
-
rest = _objectWithoutPropertiesLoose(_ref, ["id", "className", "classNameInput", "loading", "disabled", "indeterminate", "value", "color", "backgroundColor", "borderColor", "children", "placeholder", "onChange", "dataTest"]);
|
|
1480
|
+
async get(path) {
|
|
1481
|
+
if (path.startsWith('/')) {
|
|
1482
|
+
path = path.slice(1);
|
|
1483
|
+
}
|
|
1285
1484
|
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1485
|
+
return await this.rest.get(path);
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
getQueryParamsPostresql({
|
|
1489
|
+
start = 0,
|
|
1490
|
+
pageSize = 10,
|
|
1491
|
+
withDepth = true
|
|
1492
|
+
}) {
|
|
1493
|
+
let result = [];
|
|
1494
|
+
result = [...parser(start.toString(), 'b_start'), ...parser(pageSize.toString(), 'b_size')];
|
|
1495
|
+
|
|
1496
|
+
if (withDepth) {
|
|
1497
|
+
var _parser;
|
|
1498
|
+
|
|
1499
|
+
result = [...result, ...((_parser = parser('1', 'depth')) != null ? _parser : [])];
|
|
1291
1500
|
}
|
|
1292
|
-
}, [indeterminate]);
|
|
1293
1501
|
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
onChange(ev.target.checked);
|
|
1297
|
-
};
|
|
1502
|
+
return result;
|
|
1503
|
+
}
|
|
1298
1504
|
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
}
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
id: id,
|
|
1308
|
-
type: "checkbox",
|
|
1309
|
-
className: classnames(['checkbox', classNameInput]),
|
|
1310
|
-
checked: state,
|
|
1311
|
-
onChange: updateState,
|
|
1312
|
-
"data-test": dataTest
|
|
1313
|
-
}, rest)), children || placeholder));
|
|
1314
|
-
};
|
|
1505
|
+
getQueryParamsElasticsearch({
|
|
1506
|
+
start = 0,
|
|
1507
|
+
pageSize = 10,
|
|
1508
|
+
path,
|
|
1509
|
+
withDepth = true
|
|
1510
|
+
}) {
|
|
1511
|
+
let result = [];
|
|
1512
|
+
let containerPath = this.getContainerFromPath(path);
|
|
1315
1513
|
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
className
|
|
1320
|
-
}) => {
|
|
1321
|
-
return /*#__PURE__*/React.createElement("p", {
|
|
1322
|
-
className: classnames(['help is-danger', className]),
|
|
1323
|
-
id: id
|
|
1324
|
-
}, children);
|
|
1325
|
-
};
|
|
1514
|
+
if (containerPath.startsWith('/')) {
|
|
1515
|
+
containerPath = containerPath.slice(1);
|
|
1516
|
+
}
|
|
1326
1517
|
|
|
1327
|
-
|
|
1328
|
-
children: PropTypes.node,
|
|
1329
|
-
id: PropTypes.string,
|
|
1330
|
-
className: PropTypes.string
|
|
1331
|
-
};
|
|
1518
|
+
let objectPath = path.replace(containerPath, '');
|
|
1332
1519
|
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
let result = true;
|
|
1336
|
-
validation.forEach(func => {
|
|
1337
|
-
if (func(value) === false) {
|
|
1338
|
-
result = false;
|
|
1520
|
+
if (objectPath.endsWith('/')) {
|
|
1521
|
+
objectPath = objectPath.slice(0, -1);
|
|
1339
1522
|
}
|
|
1340
|
-
});
|
|
1341
|
-
return result;
|
|
1342
|
-
};
|
|
1343
1523
|
|
|
1344
|
-
|
|
1345
|
-
let [state, setState] = React.useState({
|
|
1346
|
-
hasError: false,
|
|
1347
|
-
value: value
|
|
1348
|
-
});
|
|
1524
|
+
result = [...parser(start.toString(), '_from'), ...parser(pageSize.toString(), 'size')];
|
|
1349
1525
|
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
setState({
|
|
1353
|
-
value,
|
|
1354
|
-
hasError: false
|
|
1355
|
-
});
|
|
1356
|
-
if (onChange) onChange(value);
|
|
1357
|
-
};
|
|
1526
|
+
if (withDepth) {
|
|
1527
|
+
var _parser2;
|
|
1358
1528
|
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
if (hasError) setState({
|
|
1362
|
-
value: state.value,
|
|
1363
|
-
hasError
|
|
1364
|
-
});
|
|
1365
|
-
};
|
|
1529
|
+
result = [...result, ...((_parser2 = parser('1', 'depth')) != null ? _parser2 : [])];
|
|
1530
|
+
}
|
|
1366
1531
|
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
setState({
|
|
1370
|
-
value: state.value,
|
|
1371
|
-
hasError: false
|
|
1372
|
-
});
|
|
1532
|
+
if (objectPath !== '') {
|
|
1533
|
+
result = [...result, ...parser(objectPath, 'path__wildcard')];
|
|
1373
1534
|
}
|
|
1374
|
-
};
|
|
1375
1535
|
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
value,
|
|
1379
|
-
hasError: false
|
|
1380
|
-
});
|
|
1381
|
-
}, [value]);
|
|
1382
|
-
return {
|
|
1383
|
-
onChange: onUpdate,
|
|
1384
|
-
onFocus,
|
|
1385
|
-
onBlur,
|
|
1386
|
-
state
|
|
1387
|
-
};
|
|
1388
|
-
};
|
|
1536
|
+
return result;
|
|
1537
|
+
}
|
|
1389
1538
|
|
|
1390
|
-
|
|
1539
|
+
getItemsColumn() {
|
|
1540
|
+
const smallcss = {
|
|
1541
|
+
width: 25
|
|
1542
|
+
};
|
|
1543
|
+
const mediumcss = {
|
|
1544
|
+
width: 120
|
|
1545
|
+
};
|
|
1546
|
+
return [{
|
|
1547
|
+
label: '',
|
|
1548
|
+
child: m => /*#__PURE__*/React.createElement("td", {
|
|
1549
|
+
style: smallcss
|
|
1550
|
+
}, /*#__PURE__*/React.createElement(Icon, {
|
|
1551
|
+
icon: m.icon
|
|
1552
|
+
}))
|
|
1553
|
+
}, {
|
|
1554
|
+
label: 'type',
|
|
1555
|
+
child: m => /*#__PURE__*/React.createElement(TdLink, {
|
|
1556
|
+
style: smallcss,
|
|
1557
|
+
model: m
|
|
1558
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
1559
|
+
className: "tag"
|
|
1560
|
+
}, m.type))
|
|
1561
|
+
}, {
|
|
1562
|
+
label: 'id/name',
|
|
1563
|
+
child: (m, navigate, search) => /*#__PURE__*/React.createElement(TdLink, {
|
|
1564
|
+
model: m
|
|
1565
|
+
}, m.name, search && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement("span", {
|
|
1566
|
+
className: "is-size-7 tag is-light"
|
|
1567
|
+
}, m.path)))
|
|
1568
|
+
}, {
|
|
1569
|
+
label: 'created',
|
|
1570
|
+
child: m => /*#__PURE__*/React.createElement("td", {
|
|
1571
|
+
style: mediumcss,
|
|
1572
|
+
className: "is-size-7 is-vcentered"
|
|
1573
|
+
}, m.created)
|
|
1574
|
+
}, {
|
|
1575
|
+
label: 'modified',
|
|
1576
|
+
child: m => /*#__PURE__*/React.createElement("td", {
|
|
1577
|
+
style: mediumcss,
|
|
1578
|
+
className: "is-size-7 is-vcentered"
|
|
1579
|
+
}, m.updated)
|
|
1580
|
+
}];
|
|
1581
|
+
} // BBB API changes. Compat G5 and G6
|
|
1391
1582
|
|
|
1392
|
-
/* eslint-disable no-useless-escape */
|
|
1393
|
-
const REGEX_EMAIL = /(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))/i;
|
|
1394
|
-
const REGEX_URL = /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-_]*)?\??(?:[\-\+=&;%@\.\w_]*)#?(?:[\.\!\/\\\w]*))?)/;
|
|
1395
|
-
const REGEX_HEX_COLOR = /^#([a-f0-9]{3,4}|[a-f0-9]{4}(?:[a-f0-9]{2}){1,2})\b$/i;
|
|
1396
|
-
const REGEX_NUMBER = /^\d+$/;
|
|
1397
|
-
const isEmpty = (value = '') => !value.length;
|
|
1398
|
-
const maxLength = (value = '', limit = 0) => value.length <= limit;
|
|
1399
|
-
const minLength = (value = '', limit = 0) => value.length >= limit;
|
|
1400
|
-
const isEmail = (value = '') => REGEX_EMAIL.test(value);
|
|
1401
|
-
const isURL = (value = '') => REGEX_URL.test(value);
|
|
1402
|
-
const isHexColor = (value = '') => REGEX_HEX_COLOR.test(value);
|
|
1403
|
-
const isNumber = (value = '') => REGEX_NUMBER.test(value);
|
|
1404
|
-
const notEmpty = value => !!value.length;
|
|
1405
1583
|
|
|
1406
|
-
|
|
1407
|
-
|
|
1584
|
+
applyCompat(data) {
|
|
1585
|
+
data.member = data.items;
|
|
1586
|
+
data.items_count = data.items_total;
|
|
1587
|
+
return data;
|
|
1588
|
+
}
|
|
1408
1589
|
|
|
1590
|
+
async search(path, params, container = false, prepare = true) {
|
|
1591
|
+
if (path.startsWith('/')) {
|
|
1592
|
+
path = path.slice(1);
|
|
1593
|
+
}
|
|
1409
1594
|
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
iconPosition = 'has-icons-right',
|
|
1414
|
-
error,
|
|
1415
|
-
errorZoneClassName,
|
|
1416
|
-
autoComplete = 'off',
|
|
1417
|
-
className = '',
|
|
1418
|
-
widget = 'input',
|
|
1419
|
-
type = 'text',
|
|
1420
|
-
loading = false,
|
|
1421
|
-
required = false,
|
|
1422
|
-
id,
|
|
1423
|
-
placeholder,
|
|
1424
|
-
value,
|
|
1425
|
-
autofocus = false,
|
|
1426
|
-
onChange,
|
|
1427
|
-
validator = noop$2,
|
|
1428
|
-
errorMessage,
|
|
1429
|
-
dataTest = 'testInput'
|
|
1430
|
-
} = _ref,
|
|
1431
|
-
rest = _objectWithoutPropertiesLoose(_ref, ["icon", "iconPosition", "error", "errorZoneClassName", "autoComplete", "className", "widget", "type", "onPressEnter", "isSubmitted", "loading", "required", "id", "placeholder", "value", "autofocus", "onChange", "validator", "errorMessage", "dataTest"]);
|
|
1595
|
+
if (container) {
|
|
1596
|
+
path = this.getContainerFromPath(path);
|
|
1597
|
+
}
|
|
1432
1598
|
|
|
1433
|
-
|
|
1434
|
-
|
|
1599
|
+
let query = prepare ? toQueryString(params) : params;
|
|
1600
|
+
const url = `${path}@search?${query}`;
|
|
1601
|
+
let res = await this.rest.get(url);
|
|
1602
|
+
let data = await res.json();
|
|
1603
|
+
return this.applyCompat(data);
|
|
1435
1604
|
}
|
|
1436
1605
|
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1606
|
+
async canido(path, permissions) {
|
|
1607
|
+
if (path.startsWith('/')) {
|
|
1608
|
+
path = path.slice(1);
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
if (Array.isArray(permissions)) {
|
|
1612
|
+
permissions.join(',');
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
const url = `${path}@canido?permissions=${permissions}`;
|
|
1616
|
+
return await this.rest.get(url);
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
async createObject(path, data) {
|
|
1620
|
+
return await this.rest.post(path, data);
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
cleanPath(path) {
|
|
1624
|
+
let url = path.split('/').slice(3);
|
|
1625
|
+
return `${url.join('/')}`;
|
|
1626
|
+
}
|
|
1442
1627
|
|
|
1443
|
-
|
|
1444
|
-
|
|
1628
|
+
async delete(path, data) {
|
|
1629
|
+
return await this.rest.delete(path, data);
|
|
1630
|
+
}
|
|
1445
1631
|
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
}, []);
|
|
1450
|
-
useEffect(() => {
|
|
1451
|
-
if (autofocus && !error) {
|
|
1452
|
-
ref.current.focus();
|
|
1632
|
+
async create(path, data) {
|
|
1633
|
+
if (path.startsWith('/')) {
|
|
1634
|
+
path = path.substring(1);
|
|
1453
1635
|
}
|
|
1454
|
-
}, [mounted, autofocus, ref, error]);
|
|
1455
|
-
const theError = state.hasError ? errorMessage || 'invalid field' : '';
|
|
1456
|
-
const statusClasses = state.hasError ? 'is-danger' : '';
|
|
1457
1636
|
|
|
1458
|
-
|
|
1637
|
+
return await this.rest.post(path, data);
|
|
1638
|
+
}
|
|
1459
1639
|
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
}
|
|
1463
|
-
className: "label",
|
|
1464
|
-
htmlFor: id
|
|
1465
|
-
}, placeholder) : null, /*#__PURE__*/React.createElement("div", {
|
|
1466
|
-
className: classnames(cssControl())
|
|
1467
|
-
}, /*#__PURE__*/React.createElement("input", _extends({
|
|
1468
|
-
className: classnames([widget, className, statusClasses]),
|
|
1469
|
-
"aria-invalid": theError,
|
|
1470
|
-
"aria-describedby": uid,
|
|
1471
|
-
id: id,
|
|
1472
|
-
ref: ref,
|
|
1473
|
-
type: type,
|
|
1474
|
-
value: state.value,
|
|
1475
|
-
placeholder: placeholder,
|
|
1476
|
-
autoComplete: autoComplete,
|
|
1477
|
-
disabled: loading || rest.disabled,
|
|
1478
|
-
required: required,
|
|
1479
|
-
"data-test": dataTest
|
|
1480
|
-
}, handlers, rest)), icon && icon), /*#__PURE__*/React.createElement(ErrorZone, {
|
|
1481
|
-
className: errorZoneClassName,
|
|
1482
|
-
id: uid
|
|
1483
|
-
}, state.hasError ? theError : ''));
|
|
1484
|
-
});
|
|
1485
|
-
Input.propTypes = {
|
|
1486
|
-
icon: PropTypes.node,
|
|
1487
|
-
iconPosition: PropTypes.arrayOf(PropTypes.oneOf(['has-icons-left', 'has-icons-right', ''])),
|
|
1488
|
-
error: PropTypes.string,
|
|
1489
|
-
errorZoneClassName: PropTypes.string,
|
|
1490
|
-
autoComplete: PropTypes.string,
|
|
1491
|
-
autoFocus: PropTypes.bool,
|
|
1492
|
-
className: PropTypes.string,
|
|
1493
|
-
disabled: PropTypes.bool,
|
|
1494
|
-
loading: PropTypes.bool,
|
|
1495
|
-
isSubmitted: PropTypes.bool,
|
|
1496
|
-
id: PropTypes.string,
|
|
1497
|
-
name: PropTypes.string,
|
|
1498
|
-
onChange: PropTypes.func,
|
|
1499
|
-
onKeyDown: PropTypes.func,
|
|
1500
|
-
onKeyUp: PropTypes.func,
|
|
1501
|
-
onPressEnter: PropTypes.func,
|
|
1502
|
-
placeholder: PropTypes.string,
|
|
1503
|
-
readOnly: PropTypes.bool,
|
|
1504
|
-
required: PropTypes.bool,
|
|
1505
|
-
type: PropTypes.string,
|
|
1506
|
-
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool])
|
|
1507
|
-
};
|
|
1640
|
+
async post(path, data) {
|
|
1641
|
+
return await this.create(path, data);
|
|
1642
|
+
}
|
|
1508
1643
|
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
} = _ref,
|
|
1514
|
-
rest = _objectWithoutPropertiesLoose(_ref, ["value", "dataTest"]);
|
|
1644
|
+
async patch(path, data) {
|
|
1645
|
+
if (path.startsWith('/')) {
|
|
1646
|
+
path = path.substring(1);
|
|
1647
|
+
}
|
|
1515
1648
|
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
validator: isEmail,
|
|
1519
|
-
errorMessage: "Email address invalid",
|
|
1520
|
-
value: value,
|
|
1521
|
-
"data-test": dataTest,
|
|
1522
|
-
icon: /*#__PURE__*/React.createElement(Icon, {
|
|
1523
|
-
icon: "fas fa-envelope"
|
|
1524
|
-
})
|
|
1525
|
-
}, rest));
|
|
1526
|
-
};
|
|
1649
|
+
return await this.rest.patch(path, data);
|
|
1650
|
+
}
|
|
1527
1651
|
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
onSubmit = noop,
|
|
1533
|
-
onReset = noop,
|
|
1534
|
-
autoComplete = 'off',
|
|
1535
|
-
title,
|
|
1536
|
-
error,
|
|
1537
|
-
dataTest
|
|
1538
|
-
} = _ref,
|
|
1539
|
-
rest = _objectWithoutPropertiesLoose(_ref, ["children", "className", "onSubmit", "onReset", "autoComplete", "title", "error", "dataTest"]);
|
|
1652
|
+
async upload(path, file) {
|
|
1653
|
+
if (path.startsWith('/')) {
|
|
1654
|
+
path = path.substring(1);
|
|
1655
|
+
}
|
|
1540
1656
|
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
onSubmit(event);
|
|
1544
|
-
};
|
|
1657
|
+
return await this.rest.upload(path, file);
|
|
1658
|
+
}
|
|
1545
1659
|
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
}, /*#__PURE__*/React.createElement("h1", {
|
|
1551
|
-
className: "title is-size-4"
|
|
1552
|
-
}, title)), error && /*#__PURE__*/React.createElement("div", {
|
|
1553
|
-
className: "notification is-danger"
|
|
1554
|
-
}, error), /*#__PURE__*/React.createElement("form", _extends({
|
|
1555
|
-
onSubmit: handleSubmit,
|
|
1556
|
-
onReset: onReset,
|
|
1557
|
-
autoComplete: autoComplete,
|
|
1558
|
-
className: classnames(['form', className])
|
|
1559
|
-
}, rest), children));
|
|
1560
|
-
};
|
|
1561
|
-
Form.propTypes = {
|
|
1562
|
-
children: PropTypes.node.isRequired,
|
|
1563
|
-
className: PropTypes.string,
|
|
1564
|
-
onSubmit: PropTypes.func,
|
|
1565
|
-
onReset: PropTypes.func,
|
|
1566
|
-
autoComplete: PropTypes.string
|
|
1567
|
-
};
|
|
1660
|
+
async download(path) {
|
|
1661
|
+
if (path.startsWith('/')) {
|
|
1662
|
+
path = path.substring(1);
|
|
1663
|
+
}
|
|
1568
1664
|
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
value = ''
|
|
1572
|
-
} = _ref,
|
|
1573
|
-
rest = _objectWithoutPropertiesLoose(_ref, ["value"]);
|
|
1665
|
+
return await this.rest.get(path);
|
|
1666
|
+
}
|
|
1574
1667
|
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
}, rest));
|
|
1579
|
-
};
|
|
1668
|
+
async getTypeSchema(path, name) {
|
|
1669
|
+
if (!cacheSchemas[name]) {
|
|
1670
|
+
let url = this.getContainerFromPath(path); // todo: handle db case (only addable containers)
|
|
1580
1671
|
|
|
1581
|
-
const
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
boolean: Checkbox,
|
|
1585
|
-
email: EmailInput
|
|
1586
|
-
};
|
|
1587
|
-
function FormBuilder(_ref) {
|
|
1588
|
-
let {
|
|
1589
|
-
schema,
|
|
1590
|
-
formData,
|
|
1591
|
-
onSubmit,
|
|
1592
|
-
actionName,
|
|
1593
|
-
children,
|
|
1594
|
-
exclude = [],
|
|
1595
|
-
remotes = [],
|
|
1596
|
-
submitButton = true
|
|
1597
|
-
} = _ref,
|
|
1598
|
-
rest = _objectWithoutPropertiesLoose(_ref, ["schema", "formData", "title", "onSubmit", "actionName", "children", "exclude", "remotes", "submitButton"]);
|
|
1672
|
+
const res = await this.rest.get(`${url}@types/${name}`);
|
|
1673
|
+
cacheSchemas[name] = await res.json();
|
|
1674
|
+
}
|
|
1599
1675
|
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
properties,
|
|
1603
|
-
required
|
|
1604
|
-
} = schema;
|
|
1605
|
-
const values = Object.assign({}, formData || {}); // build initial state
|
|
1676
|
+
return cacheSchemas[name];
|
|
1677
|
+
}
|
|
1606
1678
|
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
initialState[element] = values[element] || undefined;
|
|
1611
|
-
}); // Register remotes
|
|
1679
|
+
async getAddons(path) {
|
|
1680
|
+
return await this.rest.get(`${path}@addons`);
|
|
1681
|
+
}
|
|
1612
1682
|
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
} else {
|
|
1617
|
-
// apply remote changes
|
|
1618
|
-
Object.keys(remotes).forEach(key => {
|
|
1619
|
-
if (JSON.stringify(ref.current[key]) !== JSON.stringify(remotes[key])) {
|
|
1620
|
-
ref.current[key] = remotes[key];
|
|
1621
|
-
}
|
|
1683
|
+
async installAddon(path, key) {
|
|
1684
|
+
return await this.rest.post(`${path}@addons`, {
|
|
1685
|
+
id: key
|
|
1622
1686
|
});
|
|
1623
1687
|
}
|
|
1624
1688
|
|
|
1625
|
-
|
|
1689
|
+
async removeAddon(path, key) {
|
|
1690
|
+
return await this.rest.delete(`${path}@addons`, {
|
|
1691
|
+
id: key
|
|
1692
|
+
});
|
|
1693
|
+
}
|
|
1626
1694
|
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1695
|
+
async getGroups(path) {
|
|
1696
|
+
const endpoint = `${this.getContainerFromPath(path)}@groups`;
|
|
1697
|
+
return await this.rest.get(endpoint);
|
|
1698
|
+
}
|
|
1630
1699
|
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1700
|
+
async getUsers(path) {
|
|
1701
|
+
const endpoint = `${this.getContainerFromPath(path)}@users`;
|
|
1702
|
+
return await this.rest.get(endpoint);
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1705
|
+
async getPrincipals(path) {
|
|
1706
|
+
const groups = this.getGroups(path);
|
|
1707
|
+
const users = this.getUsers(path);
|
|
1708
|
+
const [gr, usr] = await Promise.all([groups, users]);
|
|
1709
|
+
return {
|
|
1710
|
+
groups: gr.ok ? await gr.json() : [],
|
|
1711
|
+
users: usr.ok ? await usr.json() : []
|
|
1642
1712
|
};
|
|
1713
|
+
}
|
|
1714
|
+
|
|
1715
|
+
async getRoles(path) {
|
|
1716
|
+
const endpoint = `${this.getContainerFromPath(path)}@available-roles`;
|
|
1717
|
+
return await this.rest.get(endpoint);
|
|
1718
|
+
}
|
|
1719
|
+
|
|
1720
|
+
async getAllPermissions(path) {
|
|
1721
|
+
// paths used to query the API always has to start without a "/"
|
|
1722
|
+
if (path.startsWith('/')) {
|
|
1723
|
+
path = path.slice(1);
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
const req = await this.rest.get(path + '@all_permissions');
|
|
1727
|
+
const resp = await req.json();
|
|
1728
|
+
const permissions = Array.from(new Set(extractPermissions(resp)));
|
|
1729
|
+
return permissions;
|
|
1730
|
+
}
|
|
1643
1731
|
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1732
|
+
async getTypes(path) {
|
|
1733
|
+
if (path.startsWith('/')) {
|
|
1734
|
+
path = path.slice(1);
|
|
1647
1735
|
}
|
|
1648
1736
|
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
};
|
|
1737
|
+
if (!cacheTypes[path]) {
|
|
1738
|
+
const types = await this.rest.get(path + '@addable-types');
|
|
1652
1739
|
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1740
|
+
if (types.status === 401 || types.status === 404) {
|
|
1741
|
+
cacheTypes[path] = [];
|
|
1742
|
+
} else {
|
|
1743
|
+
const res = await types.json();
|
|
1744
|
+
cacheTypes[path] = res;
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1656
1747
|
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
};
|
|
1748
|
+
return cacheTypes[path];
|
|
1749
|
+
}
|
|
1660
1750
|
|
|
1661
|
-
return /*#__PURE__*/React.createElement(Form, _extends({
|
|
1662
|
-
onSubmit: changes
|
|
1663
|
-
}, rest), fields.map(field => /*#__PURE__*/React.createElement(GetTag, {
|
|
1664
|
-
field: field,
|
|
1665
|
-
key: field
|
|
1666
|
-
})), children_, submitButton && /*#__PURE__*/React.createElement(Button, null, actionName));
|
|
1667
1751
|
}
|
|
1752
|
+
function getClient(url, container, auth) {
|
|
1753
|
+
return new GuillotinaClient(new RestClient(url, container, auth), container === '/');
|
|
1754
|
+
}
|
|
1755
|
+
const lightFileReader = async file => {
|
|
1756
|
+
return new Promise(resolve => {
|
|
1757
|
+
const reader = new FileReader();
|
|
1758
|
+
reader.readAsArrayBuffer(file);
|
|
1668
1759
|
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
errorZoneClassName,
|
|
1676
|
-
size = 1,
|
|
1677
|
-
placeholder,
|
|
1678
|
-
id,
|
|
1679
|
-
className = '',
|
|
1680
|
-
classWrap = '',
|
|
1681
|
-
multiple = false,
|
|
1682
|
-
loading = false,
|
|
1683
|
-
onChange,
|
|
1684
|
-
appendDefault = false,
|
|
1685
|
-
style = {},
|
|
1686
|
-
dataTest
|
|
1687
|
-
} = _ref,
|
|
1688
|
-
rest = _objectWithoutPropertiesLoose(_ref, ["options", "error", "errorZoneClassName", "size", "placeholder", "id", "className", "classWrap", "multiple", "loading", "isSubmitted", "onChange", "appendDefault", "style", "dataTest"]);
|
|
1689
|
-
|
|
1690
|
-
const [uid] = useState(generateUID('select'));
|
|
1691
|
-
|
|
1692
|
-
const onUpdate = ev => {
|
|
1693
|
-
if (ev.target.value === '') {
|
|
1694
|
-
onChange({
|
|
1695
|
-
target: {
|
|
1696
|
-
value: undefined
|
|
1697
|
-
}
|
|
1760
|
+
reader.onloadend = e => {
|
|
1761
|
+
const fileData = e.target.result;
|
|
1762
|
+
resolve({
|
|
1763
|
+
filename: file.name.normalize('NFD').replace(/[\u0300-\u036f]/g, ''),
|
|
1764
|
+
data: fileData,
|
|
1765
|
+
'content-type': file.type
|
|
1698
1766
|
});
|
|
1699
|
-
}
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
};
|
|
1767
|
+
};
|
|
1768
|
+
});
|
|
1769
|
+
};
|
|
1703
1770
|
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
text: 'Choose..',
|
|
1707
|
-
value: ''
|
|
1708
|
-
}].concat(options);
|
|
1709
|
-
}
|
|
1771
|
+
const extractPermissions = data => {
|
|
1772
|
+
let result = [];
|
|
1710
1773
|
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
}
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
}, placeholder) : null, /*#__PURE__*/React.createElement("div", {
|
|
1719
|
-
className: classnames(cssWrap)
|
|
1720
|
-
}, /*#__PURE__*/React.createElement("select", _extends({
|
|
1721
|
-
className: classnames(['', className]),
|
|
1722
|
-
size: size,
|
|
1723
|
-
multiple: multiple,
|
|
1724
|
-
disabled: loading || rest.disabled,
|
|
1725
|
-
onChange: onUpdate
|
|
1726
|
-
}, rest, {
|
|
1727
|
-
ref: ref,
|
|
1728
|
-
style: style,
|
|
1729
|
-
"data-test": dataTest
|
|
1730
|
-
}), options.map((_ref2, index) => {
|
|
1731
|
-
let {
|
|
1732
|
-
text
|
|
1733
|
-
} = _ref2,
|
|
1734
|
-
rest = _objectWithoutPropertiesLoose(_ref2, ["text"]);
|
|
1774
|
+
if (typeof data !== 'object') ; else if (!Array.isArray(data) && data.permission) {
|
|
1775
|
+
result = result.concat([data.permission]);
|
|
1776
|
+
} else if (!Array.isArray(data)) {
|
|
1777
|
+
Object.keys(data).map(key => result = result.concat(extractPermissions(data[key])));
|
|
1778
|
+
} else if (Array.isArray(data)) {
|
|
1779
|
+
data.map(item => result = result.concat(extractPermissions(item)));
|
|
1780
|
+
}
|
|
1735
1781
|
|
|
1736
|
-
|
|
1737
|
-
key: index.toString()
|
|
1738
|
-
}, rest), text);
|
|
1739
|
-
}))), error && /*#__PURE__*/React.createElement(ErrorZone, {
|
|
1740
|
-
className: errorZoneClassName,
|
|
1741
|
-
id: uid
|
|
1742
|
-
}, error ? error : ''));
|
|
1743
|
-
});
|
|
1744
|
-
Select.propTypes = {
|
|
1745
|
-
error: PropTypes.string,
|
|
1746
|
-
disabled: PropTypes.bool,
|
|
1747
|
-
loading: PropTypes.bool,
|
|
1748
|
-
isSubmitted: PropTypes.bool,
|
|
1749
|
-
size: PropTypes.number,
|
|
1750
|
-
onChange: PropTypes.func,
|
|
1751
|
-
options: PropTypes.arrayOf(PropTypes.object),
|
|
1752
|
-
multiple: PropTypes.bool,
|
|
1753
|
-
className: PropTypes.string
|
|
1782
|
+
return result;
|
|
1754
1783
|
};
|
|
1755
1784
|
|
|
1756
1785
|
function FileUpload(_ref) {
|
|
@@ -2147,7 +2176,7 @@ function Dropdown(_ref) {
|
|
|
2147
2176
|
// eslint-disable-next-line jsx-a11y/anchor-is-valid
|
|
2148
2177
|
React.createElement("a", {
|
|
2149
2178
|
className: disabled ? 'dropdown-item is-active' : 'dropdown-item',
|
|
2150
|
-
"data-test": `dropdownItemTest-${option.
|
|
2179
|
+
"data-test": `dropdownItemTest-${option.value.toLowerCase()}`,
|
|
2151
2180
|
key: option.text,
|
|
2152
2181
|
onClick: disabled ? undefined : () => onChange(option.value),
|
|
2153
2182
|
style: disabled ? {
|
|
@@ -2161,57 +2190,6 @@ function Dropdown(_ref) {
|
|
|
2161
2190
|
}))));
|
|
2162
2191
|
}
|
|
2163
2192
|
|
|
2164
|
-
const plain = ['string', 'number', 'boolean'];
|
|
2165
|
-
function RenderField({
|
|
2166
|
-
value,
|
|
2167
|
-
Widget
|
|
2168
|
-
}) {
|
|
2169
|
-
if (value === null || value === undefined) return '';
|
|
2170
|
-
|
|
2171
|
-
if (Widget) {
|
|
2172
|
-
return /*#__PURE__*/React.createElement(Widget, {
|
|
2173
|
-
value: value
|
|
2174
|
-
});
|
|
2175
|
-
}
|
|
2176
|
-
|
|
2177
|
-
const type = typeof value;
|
|
2178
|
-
|
|
2179
|
-
if (plain.includes(type)) {
|
|
2180
|
-
return value;
|
|
2181
|
-
}
|
|
2182
|
-
|
|
2183
|
-
if (type === 'object') {
|
|
2184
|
-
if (Array.isArray(value)) {
|
|
2185
|
-
return value.map(item => /*#__PURE__*/React.createElement("div", {
|
|
2186
|
-
key: item
|
|
2187
|
-
}, /*#__PURE__*/React.createElement(RenderField, {
|
|
2188
|
-
value: item
|
|
2189
|
-
})));
|
|
2190
|
-
}
|
|
2191
|
-
|
|
2192
|
-
return Object.keys(value).map(key => /*#__PURE__*/React.createElement(FieldValue, {
|
|
2193
|
-
field: key,
|
|
2194
|
-
value: value[key],
|
|
2195
|
-
key: key
|
|
2196
|
-
}));
|
|
2197
|
-
}
|
|
2198
|
-
|
|
2199
|
-
return /*#__PURE__*/React.createElement("p", null, "No render for ", JSON.stringify(value));
|
|
2200
|
-
}
|
|
2201
|
-
|
|
2202
|
-
const FieldValue = ({
|
|
2203
|
-
field,
|
|
2204
|
-
value
|
|
2205
|
-
}) => /*#__PURE__*/React.createElement("div", {
|
|
2206
|
-
className: "field"
|
|
2207
|
-
}, /*#__PURE__*/React.createElement("div", {
|
|
2208
|
-
className: "label"
|
|
2209
|
-
}, field), /*#__PURE__*/React.createElement("div", {
|
|
2210
|
-
className: "value"
|
|
2211
|
-
}, /*#__PURE__*/React.createElement(RenderField, {
|
|
2212
|
-
value: value
|
|
2213
|
-
})));
|
|
2214
|
-
|
|
2215
2193
|
const formatDate = str => {
|
|
2216
2194
|
const d = new Date(str);
|
|
2217
2195
|
const minutes = d.getMinutes() < 10 ? `0${d.getMinutes()}` : d.getMinutes();
|
|
@@ -2234,74 +2212,7 @@ function getNewId(id = '') {
|
|
|
2234
2212
|
return `${suffix}${num + 1}`;
|
|
2235
2213
|
});
|
|
2236
2214
|
}
|
|
2237
|
-
|
|
2238
|
-
const DownloadField = ({
|
|
2239
|
-
value
|
|
2240
|
-
}) => {
|
|
2241
|
-
const Ctx = useTraversal();
|
|
2242
|
-
const {
|
|
2243
|
-
data,
|
|
2244
|
-
field
|
|
2245
|
-
} = value;
|
|
2246
|
-
|
|
2247
|
-
const getField = async downloadFile => {
|
|
2248
|
-
const endpoint = `${Ctx.path}@download/${field}`;
|
|
2249
|
-
const res = await Ctx.client.download(endpoint);
|
|
2250
|
-
const text = await res.blob();
|
|
2251
|
-
const blob = new Blob([text], {
|
|
2252
|
-
type: data.content_type
|
|
2253
|
-
});
|
|
2254
|
-
const url = window.URL.createObjectURL(blob); // Create blob link to download
|
|
2255
|
-
|
|
2256
|
-
const link = document.createElement('a');
|
|
2257
|
-
link.href = url;
|
|
2258
|
-
|
|
2259
|
-
if (downloadFile) {
|
|
2260
|
-
link.setAttribute('download', `${data.filename}`);
|
|
2261
|
-
} else {
|
|
2262
|
-
link.setAttribute('target', `_blank`);
|
|
2263
|
-
}
|
|
2264
|
-
|
|
2265
|
-
document.body.appendChild(link);
|
|
2266
|
-
link.click();
|
|
2267
|
-
setTimeout(function () {
|
|
2268
|
-
var _link$parentNode;
|
|
2269
|
-
|
|
2270
|
-
// For Firefox it is necessary to delay revoking the ObjectURL
|
|
2271
|
-
window.URL.revokeObjectURL(url);
|
|
2272
|
-
(_link$parentNode = link.parentNode) == null ? void 0 : _link$parentNode.removeChild(link);
|
|
2273
|
-
}, 100);
|
|
2274
|
-
};
|
|
2275
|
-
|
|
2276
|
-
return /*#__PURE__*/createElement("div", {
|
|
2277
|
-
className: "field"
|
|
2278
|
-
}, /*#__PURE__*/createElement("div", {
|
|
2279
|
-
className: "label"
|
|
2280
|
-
}, data.filename), /*#__PURE__*/createElement("div", {
|
|
2281
|
-
className: "columns"
|
|
2282
|
-
}, /*#__PURE__*/createElement("div", {
|
|
2283
|
-
className: "column"
|
|
2284
|
-
}, /*#__PURE__*/createElement("button", {
|
|
2285
|
-
className: "button is-small is-primary level-left",
|
|
2286
|
-
onClick: async event => {
|
|
2287
|
-
event.preventDefault();
|
|
2288
|
-
event.stopPropagation();
|
|
2289
|
-
getField(false);
|
|
2290
|
-
}
|
|
2291
|
-
}, "Open")), /*#__PURE__*/createElement("div", {
|
|
2292
|
-
className: "column"
|
|
2293
|
-
}, /*#__PURE__*/createElement("button", {
|
|
2294
|
-
className: "button is-small is-primary level-right",
|
|
2295
|
-
onClick: async event => {
|
|
2296
|
-
event.preventDefault();
|
|
2297
|
-
event.stopPropagation();
|
|
2298
|
-
getField(true);
|
|
2299
|
-
}
|
|
2300
|
-
}, "Download"))));
|
|
2301
|
-
};
|
|
2302
|
-
|
|
2303
|
-
const DEFAULT_VALUE_EDITABLE_FIELD = 'Click to edit';
|
|
2304
|
-
const DEFAULT_VALUE_NO_EDITABLE_FIELD = ' -- ';
|
|
2215
|
+
|
|
2305
2216
|
function EditableField({
|
|
2306
2217
|
field,
|
|
2307
2218
|
value,
|
|
@@ -2318,36 +2229,17 @@ function EditableField({
|
|
|
2318
2229
|
loading,
|
|
2319
2230
|
Ctx
|
|
2320
2231
|
} = useCrudContext();
|
|
2232
|
+
const {
|
|
2233
|
+
fieldHaveDeleteButton
|
|
2234
|
+
} = useConfig();
|
|
2321
2235
|
const EditComponent = Ctx.registry.get('components', 'EditComponent');
|
|
2236
|
+
const RenderFieldComponent = Ctx.registry.get('components', 'RenderFieldComponent');
|
|
2322
2237
|
useEffect(() => {
|
|
2323
2238
|
if (isEdit && ref.current) {
|
|
2324
2239
|
ref.current.focus();
|
|
2325
2240
|
}
|
|
2326
2241
|
});
|
|
2327
2242
|
const canModified = modifyContent && !get$1(schema, 'readonly', false);
|
|
2328
|
-
const haveDeleteBtn = (schema == null ? void 0 : schema.widget) === 'file' || (schema == null ? void 0 : schema.widget) === 'select' || (schema == null ? void 0 : schema.type) === 'array';
|
|
2329
|
-
|
|
2330
|
-
const getRenderProps = () => {
|
|
2331
|
-
const renderProps = {
|
|
2332
|
-
value: val != null ? val : modifyContent ? DEFAULT_VALUE_EDITABLE_FIELD : DEFAULT_VALUE_NO_EDITABLE_FIELD
|
|
2333
|
-
};
|
|
2334
|
-
|
|
2335
|
-
if (val && (schema == null ? void 0 : schema.widget) === 'file') {
|
|
2336
|
-
renderProps['value'] = {
|
|
2337
|
-
data: val,
|
|
2338
|
-
field: field
|
|
2339
|
-
};
|
|
2340
|
-
renderProps['Widget'] = DownloadField;
|
|
2341
|
-
} else if ((schema == null ? void 0 : schema.type) === 'boolean') {
|
|
2342
|
-
var _val$toString;
|
|
2343
|
-
|
|
2344
|
-
renderProps['value'] = (_val$toString = val == null ? void 0 : val.toString()) != null ? _val$toString : renderProps['value'];
|
|
2345
|
-
} else if (val && (schema == null ? void 0 : schema.type) === 'datetime') {
|
|
2346
|
-
renderProps['value'] = new Date(val).toLocaleString();
|
|
2347
|
-
}
|
|
2348
|
-
|
|
2349
|
-
return renderProps;
|
|
2350
|
-
};
|
|
2351
2243
|
|
|
2352
2244
|
const saveField = async ev => {
|
|
2353
2245
|
if (ev) ev.preventDefault();
|
|
@@ -2437,7 +2329,12 @@ function EditableField({
|
|
|
2437
2329
|
setEdit(!!canModified);
|
|
2438
2330
|
},
|
|
2439
2331
|
"data-test": `editableFieldTest-${field}`
|
|
2440
|
-
}, /*#__PURE__*/React.createElement(
|
|
2332
|
+
}, /*#__PURE__*/React.createElement(RenderFieldComponent, {
|
|
2333
|
+
schema: schema,
|
|
2334
|
+
field: field,
|
|
2335
|
+
val: val,
|
|
2336
|
+
modifyContent: modifyContent
|
|
2337
|
+
}), canModified && /*#__PURE__*/React.createElement(Icon, {
|
|
2441
2338
|
icon: "fas fa-edit"
|
|
2442
2339
|
})), isEdit && /*#__PURE__*/React.createElement("div", {
|
|
2443
2340
|
className: "field",
|
|
@@ -2465,7 +2362,7 @@ function EditableField({
|
|
|
2465
2362
|
className: "is-small",
|
|
2466
2363
|
onClick: () => setEdit(false),
|
|
2467
2364
|
dataTest: "editableFieldBtnCancelTest"
|
|
2468
|
-
}, "Cancel")), !required &&
|
|
2365
|
+
}, "Cancel")), !required && fieldHaveDeleteButton(schema) && /*#__PURE__*/React.createElement("div", {
|
|
2469
2366
|
className: "control"
|
|
2470
2367
|
}, /*#__PURE__*/React.createElement(Button, {
|
|
2471
2368
|
className: "is-small is-danger",
|
|
@@ -2474,6 +2371,155 @@ function EditableField({
|
|
|
2474
2371
|
}, "Delete")))));
|
|
2475
2372
|
}
|
|
2476
2373
|
|
|
2374
|
+
const DownloadField = ({
|
|
2375
|
+
value
|
|
2376
|
+
}) => {
|
|
2377
|
+
const Ctx = useTraversal();
|
|
2378
|
+
const {
|
|
2379
|
+
data,
|
|
2380
|
+
field
|
|
2381
|
+
} = value;
|
|
2382
|
+
|
|
2383
|
+
const getField = async downloadFile => {
|
|
2384
|
+
const endpoint = `${Ctx.path}@download/${field}`;
|
|
2385
|
+
const res = await Ctx.client.download(endpoint);
|
|
2386
|
+
const text = await res.blob();
|
|
2387
|
+
const blob = new Blob([text], {
|
|
2388
|
+
type: data.content_type
|
|
2389
|
+
});
|
|
2390
|
+
const url = window.URL.createObjectURL(blob); // Create blob link to download
|
|
2391
|
+
|
|
2392
|
+
const link = document.createElement('a');
|
|
2393
|
+
link.href = url;
|
|
2394
|
+
|
|
2395
|
+
if (downloadFile) {
|
|
2396
|
+
link.setAttribute('download', `${data.filename}`);
|
|
2397
|
+
} else {
|
|
2398
|
+
link.setAttribute('target', `_blank`);
|
|
2399
|
+
}
|
|
2400
|
+
|
|
2401
|
+
document.body.appendChild(link);
|
|
2402
|
+
link.click();
|
|
2403
|
+
setTimeout(function () {
|
|
2404
|
+
var _link$parentNode;
|
|
2405
|
+
|
|
2406
|
+
// For Firefox it is necessary to delay revoking the ObjectURL
|
|
2407
|
+
window.URL.revokeObjectURL(url);
|
|
2408
|
+
(_link$parentNode = link.parentNode) == null ? void 0 : _link$parentNode.removeChild(link);
|
|
2409
|
+
}, 100);
|
|
2410
|
+
};
|
|
2411
|
+
|
|
2412
|
+
return /*#__PURE__*/createElement("div", {
|
|
2413
|
+
className: "field"
|
|
2414
|
+
}, /*#__PURE__*/createElement("div", {
|
|
2415
|
+
className: "label"
|
|
2416
|
+
}, data.filename), /*#__PURE__*/createElement("div", {
|
|
2417
|
+
className: "columns"
|
|
2418
|
+
}, /*#__PURE__*/createElement("div", {
|
|
2419
|
+
className: "column"
|
|
2420
|
+
}, /*#__PURE__*/createElement("button", {
|
|
2421
|
+
className: "button is-small is-primary level-left",
|
|
2422
|
+
onClick: async event => {
|
|
2423
|
+
event.preventDefault();
|
|
2424
|
+
event.stopPropagation();
|
|
2425
|
+
getField(false);
|
|
2426
|
+
}
|
|
2427
|
+
}, "Open")), /*#__PURE__*/createElement("div", {
|
|
2428
|
+
className: "column"
|
|
2429
|
+
}, /*#__PURE__*/createElement("button", {
|
|
2430
|
+
className: "button is-small is-primary level-right",
|
|
2431
|
+
onClick: async event => {
|
|
2432
|
+
event.preventDefault();
|
|
2433
|
+
event.stopPropagation();
|
|
2434
|
+
getField(true);
|
|
2435
|
+
}
|
|
2436
|
+
}, "Download"))));
|
|
2437
|
+
};
|
|
2438
|
+
|
|
2439
|
+
const plain = ['string', 'number', 'boolean'];
|
|
2440
|
+
function RenderField({
|
|
2441
|
+
value,
|
|
2442
|
+
Widget
|
|
2443
|
+
}) {
|
|
2444
|
+
if (value === null || value === undefined) return '';
|
|
2445
|
+
|
|
2446
|
+
if (Widget) {
|
|
2447
|
+
return /*#__PURE__*/React.createElement(Widget, {
|
|
2448
|
+
value: value
|
|
2449
|
+
});
|
|
2450
|
+
}
|
|
2451
|
+
|
|
2452
|
+
const type = typeof value;
|
|
2453
|
+
|
|
2454
|
+
if (plain.includes(type)) {
|
|
2455
|
+
return value;
|
|
2456
|
+
}
|
|
2457
|
+
|
|
2458
|
+
if (type === 'object') {
|
|
2459
|
+
if (Array.isArray(value)) {
|
|
2460
|
+
return value.map(item => /*#__PURE__*/React.createElement("div", {
|
|
2461
|
+
key: item
|
|
2462
|
+
}, /*#__PURE__*/React.createElement(RenderField, {
|
|
2463
|
+
value: item
|
|
2464
|
+
})));
|
|
2465
|
+
}
|
|
2466
|
+
|
|
2467
|
+
return Object.keys(value).map(key => /*#__PURE__*/React.createElement(FieldValue, {
|
|
2468
|
+
field: key,
|
|
2469
|
+
value: value[key],
|
|
2470
|
+
key: key
|
|
2471
|
+
}));
|
|
2472
|
+
}
|
|
2473
|
+
|
|
2474
|
+
return /*#__PURE__*/React.createElement("p", null, "No render for ", JSON.stringify(value));
|
|
2475
|
+
}
|
|
2476
|
+
|
|
2477
|
+
const FieldValue = ({
|
|
2478
|
+
field,
|
|
2479
|
+
value
|
|
2480
|
+
}) => /*#__PURE__*/React.createElement("div", {
|
|
2481
|
+
className: "field"
|
|
2482
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
2483
|
+
className: "label"
|
|
2484
|
+
}, field), /*#__PURE__*/React.createElement("div", {
|
|
2485
|
+
className: "value"
|
|
2486
|
+
}, /*#__PURE__*/React.createElement(RenderField, {
|
|
2487
|
+
value: value
|
|
2488
|
+
})));
|
|
2489
|
+
|
|
2490
|
+
const DEFAULT_VALUE_EDITABLE_FIELD = 'Click to edit';
|
|
2491
|
+
const DEFAULT_VALUE_NO_EDITABLE_FIELD = ' -- ';
|
|
2492
|
+
function RenderFieldComponent({
|
|
2493
|
+
schema,
|
|
2494
|
+
field,
|
|
2495
|
+
val,
|
|
2496
|
+
modifyContent
|
|
2497
|
+
}) {
|
|
2498
|
+
const getRenderProps = () => {
|
|
2499
|
+
const renderProps = {
|
|
2500
|
+
value: val != null ? val : modifyContent ? DEFAULT_VALUE_EDITABLE_FIELD : DEFAULT_VALUE_NO_EDITABLE_FIELD
|
|
2501
|
+
};
|
|
2502
|
+
|
|
2503
|
+
if (val && (schema == null ? void 0 : schema.widget) === 'file') {
|
|
2504
|
+
renderProps['value'] = {
|
|
2505
|
+
data: val,
|
|
2506
|
+
field: field
|
|
2507
|
+
};
|
|
2508
|
+
renderProps['Widget'] = DownloadField;
|
|
2509
|
+
} else if ((schema == null ? void 0 : schema.type) === 'boolean') {
|
|
2510
|
+
var _val$toString;
|
|
2511
|
+
|
|
2512
|
+
renderProps['value'] = (_val$toString = val == null ? void 0 : val.toString()) != null ? _val$toString : renderProps['value'];
|
|
2513
|
+
} else if (val && (schema == null ? void 0 : schema.type) === 'datetime') {
|
|
2514
|
+
renderProps['value'] = new Date(val).toLocaleString();
|
|
2515
|
+
}
|
|
2516
|
+
|
|
2517
|
+
return renderProps;
|
|
2518
|
+
};
|
|
2519
|
+
|
|
2520
|
+
return /*#__PURE__*/React.createElement(RenderField, getRenderProps());
|
|
2521
|
+
}
|
|
2522
|
+
|
|
2477
2523
|
function IAttachment({
|
|
2478
2524
|
properties,
|
|
2479
2525
|
values
|
|
@@ -2916,7 +2962,9 @@ function ItemsActionsProvider({
|
|
|
2916
2962
|
* and it select/unselect all items of the page.
|
|
2917
2963
|
*/
|
|
2918
2964
|
|
|
2919
|
-
function AllItemsCheckbox(
|
|
2965
|
+
function AllItemsCheckbox({
|
|
2966
|
+
dataTest
|
|
2967
|
+
}) {
|
|
2920
2968
|
const {
|
|
2921
2969
|
onSelectAllItems,
|
|
2922
2970
|
selected
|
|
@@ -2927,7 +2975,8 @@ function AllItemsCheckbox() {
|
|
|
2927
2975
|
style: {
|
|
2928
2976
|
marginLeft: 2
|
|
2929
2977
|
},
|
|
2930
|
-
value: selected.all
|
|
2978
|
+
value: selected.all,
|
|
2979
|
+
dataTest: dataTest
|
|
2931
2980
|
});
|
|
2932
2981
|
}
|
|
2933
2982
|
/**
|
|
@@ -2935,7 +2984,8 @@ function AllItemsCheckbox() {
|
|
|
2935
2984
|
*/
|
|
2936
2985
|
|
|
2937
2986
|
function ItemCheckbox({
|
|
2938
|
-
item
|
|
2987
|
+
item,
|
|
2988
|
+
dataTest
|
|
2939
2989
|
}) {
|
|
2940
2990
|
const {
|
|
2941
2991
|
selected,
|
|
@@ -2946,7 +2996,8 @@ function ItemCheckbox({
|
|
|
2946
2996
|
return /*#__PURE__*/React.createElement(Checkbox, {
|
|
2947
2997
|
key: value,
|
|
2948
2998
|
onChange: () => onSelectOneItem(item),
|
|
2949
|
-
value: value
|
|
2999
|
+
value: value,
|
|
3000
|
+
dataTest: dataTest
|
|
2950
3001
|
});
|
|
2951
3002
|
}
|
|
2952
3003
|
/**
|
|
@@ -2970,7 +3021,9 @@ function ItemsActionsDropdown() {
|
|
|
2970
3021
|
onChange: onAction,
|
|
2971
3022
|
optionDisabledWhen: o => actions[o.value].perms.some(perm => !traversal.hasPerm(perm)),
|
|
2972
3023
|
options: options
|
|
2973
|
-
}, "
|
|
3024
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
3025
|
+
"data-test": "btnChooseActionTest"
|
|
3026
|
+
}, "Choose action..."));
|
|
2974
3027
|
}
|
|
2975
3028
|
|
|
2976
3029
|
/* eslint jsx-a11y/anchor-is-valid: "off" */
|
|
@@ -3190,7 +3243,8 @@ function RItem({
|
|
|
3190
3243
|
}, /*#__PURE__*/React.createElement("td", {
|
|
3191
3244
|
style: smallcss
|
|
3192
3245
|
}, /*#__PURE__*/React.createElement(ItemCheckbox, {
|
|
3193
|
-
item: item
|
|
3246
|
+
item: item,
|
|
3247
|
+
dataTest: "itemCheckboxRowTest"
|
|
3194
3248
|
})), columns.map(i => /*#__PURE__*/React.createElement(React.Fragment, {
|
|
3195
3249
|
key: i.label
|
|
3196
3250
|
}, i.child(model, link, search))), /*#__PURE__*/React.createElement("td", {
|
|
@@ -4734,7 +4788,7 @@ function CopyItems(props) {
|
|
|
4734
4788
|
|
|
4735
4789
|
return /*#__PURE__*/React.createElement(PathTree, {
|
|
4736
4790
|
title: "Copy to...",
|
|
4737
|
-
defaultPath:
|
|
4791
|
+
defaultPath: Ctx.client.clearContainerFromPath(Ctx.path),
|
|
4738
4792
|
onConfirm: copyItems,
|
|
4739
4793
|
onCancel: () => Ctx.cancelAction()
|
|
4740
4794
|
}, items.map(item => /*#__PURE__*/React.createElement(React.Fragment, {
|
|
@@ -4747,11 +4801,14 @@ function CopyItems(props) {
|
|
|
4747
4801
|
}, `New id for "${item.id}" copy`), /*#__PURE__*/React.createElement("input", {
|
|
4748
4802
|
type: "text",
|
|
4749
4803
|
className: "input",
|
|
4804
|
+
"data-test": `inputCopyIdTest-${item['@name']}`,
|
|
4750
4805
|
defaultValue: getNewId(item.id)
|
|
4751
4806
|
}))), "\xA0");
|
|
4752
4807
|
}
|
|
4753
4808
|
|
|
4754
4809
|
function CopyItem(props) {
|
|
4810
|
+
var _item$parent$Name;
|
|
4811
|
+
|
|
4755
4812
|
const Ctx = useTraversal();
|
|
4756
4813
|
const {
|
|
4757
4814
|
post
|
|
@@ -4782,7 +4839,7 @@ function CopyItem(props) {
|
|
|
4782
4839
|
|
|
4783
4840
|
return /*#__PURE__*/React.createElement(PathTree, {
|
|
4784
4841
|
title: "Copy to...",
|
|
4785
|
-
defaultPath: `/${item['parent']['@name']}`,
|
|
4842
|
+
defaultPath: `/${(_item$parent$Name = item['parent']['@name']) != null ? _item$parent$Name : '/'}`,
|
|
4786
4843
|
onConfirm: copyItem,
|
|
4787
4844
|
onCancel: () => Ctx.cancelAction()
|
|
4788
4845
|
}, /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("small", {
|
|
@@ -4793,6 +4850,7 @@ function CopyItem(props) {
|
|
|
4793
4850
|
}, `New id for "${item['@name']}" copy`), /*#__PURE__*/React.createElement("input", {
|
|
4794
4851
|
type: "text",
|
|
4795
4852
|
className: "input",
|
|
4853
|
+
"data-test": `inputCopyIdTest-${item['@name']}`,
|
|
4796
4854
|
defaultValue: getNewId(item['@name'])
|
|
4797
4855
|
})));
|
|
4798
4856
|
}
|
|
@@ -5196,7 +5254,7 @@ function GroupCtx() {
|
|
|
5196
5254
|
}, /*#__PURE__*/React.createElement("h3", {
|
|
5197
5255
|
className: "title is-size-6"
|
|
5198
5256
|
}, "Users"), /*#__PURE__*/React.createElement("p", null, "Add a User"), /*#__PURE__*/React.createElement(SearchInput, {
|
|
5199
|
-
path:
|
|
5257
|
+
path: Ctx.containerPath,
|
|
5200
5258
|
qs: [...searchParsed, ...sortParsed],
|
|
5201
5259
|
traversal: Ctx,
|
|
5202
5260
|
onChange: addUser,
|
|
@@ -5310,7 +5368,8 @@ function Path() {
|
|
|
5310
5368
|
key: indx
|
|
5311
5369
|
}, /*#__PURE__*/React.createElement("a", {
|
|
5312
5370
|
href: path,
|
|
5313
|
-
onClick: onClick
|
|
5371
|
+
onClick: onClick,
|
|
5372
|
+
"data-test": `breadcrumbItemTest-home`
|
|
5314
5373
|
}, /*#__PURE__*/React.createElement("span", {
|
|
5315
5374
|
className: "icon"
|
|
5316
5375
|
}, /*#__PURE__*/React.createElement("i", {
|
|
@@ -5473,7 +5532,8 @@ let registry = {
|
|
|
5473
5532
|
properties: {},
|
|
5474
5533
|
components: {
|
|
5475
5534
|
Path: Path,
|
|
5476
|
-
EditComponent: EditComponent
|
|
5535
|
+
EditComponent: EditComponent,
|
|
5536
|
+
RenderFieldComponent: RenderFieldComponent
|
|
5477
5537
|
},
|
|
5478
5538
|
searchEngineQueryParamsFunction: {
|
|
5479
5539
|
PostreSQL: 'getQueryParamsPostresql',
|
|
@@ -5815,132 +5875,113 @@ const ERRORS = {
|
|
|
5815
5875
|
failed_to_fetch: 'Failed to fetch data: Backend not running?',
|
|
5816
5876
|
invalid_credentials: 'Failed! Invalid credentials'
|
|
5817
5877
|
};
|
|
5818
|
-
|
|
5819
|
-
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
errors: undefined
|
|
5839
|
-
});
|
|
5840
|
-
|
|
5841
|
-
const {
|
|
5842
|
-
username,
|
|
5843
|
-
password,
|
|
5844
|
-
schema
|
|
5845
|
-
} = _this.state;
|
|
5846
|
-
|
|
5847
|
-
if (schema !== '') {
|
|
5848
|
-
_this.props.auth.setAccount(schema);
|
|
5849
|
-
}
|
|
5850
|
-
|
|
5851
|
-
const auth = _this.props.auth;
|
|
5852
|
-
const res = await auth.login(username, password);
|
|
5878
|
+
const initialState$4 = {
|
|
5879
|
+
username: '',
|
|
5880
|
+
password: '',
|
|
5881
|
+
loading: undefined,
|
|
5882
|
+
errors: undefined
|
|
5883
|
+
};
|
|
5884
|
+
const Login = ({
|
|
5885
|
+
currentSchema,
|
|
5886
|
+
setCurrentSchema,
|
|
5887
|
+
schemas,
|
|
5888
|
+
auth,
|
|
5889
|
+
onLogin
|
|
5890
|
+
}) => {
|
|
5891
|
+
const [state, setState] = useSetState(initialState$4);
|
|
5892
|
+
const inputRef = useRef(null);
|
|
5893
|
+
useEffect(() => {
|
|
5894
|
+
if (inputRef) {
|
|
5895
|
+
inputRef.current.focus();
|
|
5896
|
+
}
|
|
5897
|
+
}, [inputRef]);
|
|
5853
5898
|
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5899
|
+
const doLogin = async ev => {
|
|
5900
|
+
ev.preventDefault();
|
|
5901
|
+
setState({
|
|
5902
|
+
loading: true,
|
|
5903
|
+
errors: undefined
|
|
5904
|
+
});
|
|
5905
|
+
const {
|
|
5906
|
+
username,
|
|
5907
|
+
password
|
|
5908
|
+
} = state;
|
|
5859
5909
|
|
|
5860
|
-
|
|
5861
|
-
|
|
5910
|
+
if (currentSchema !== '') {
|
|
5911
|
+
auth.setAccount(currentSchema);
|
|
5912
|
+
}
|
|
5862
5913
|
|
|
5863
|
-
|
|
5864
|
-
_this.props.onLogin();
|
|
5865
|
-
}
|
|
5866
|
-
};
|
|
5914
|
+
const res = await auth.login(username, password);
|
|
5867
5915
|
|
|
5868
|
-
if (
|
|
5869
|
-
|
|
5916
|
+
if (!res) {
|
|
5917
|
+
setState({
|
|
5918
|
+
errors: auth.errors,
|
|
5919
|
+
loading: false
|
|
5920
|
+
});
|
|
5921
|
+
return;
|
|
5870
5922
|
}
|
|
5871
|
-
}
|
|
5872
|
-
|
|
5873
|
-
componentDidMount() {
|
|
5874
|
-
this.ref.current.focus();
|
|
5875
|
-
}
|
|
5876
5923
|
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
errors
|
|
5882
|
-
} = this.state;
|
|
5883
|
-
const {
|
|
5884
|
-
schemas
|
|
5885
|
-
} = this.props;
|
|
5886
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("form", {
|
|
5887
|
-
className: "login__form",
|
|
5888
|
-
action: "",
|
|
5889
|
-
onSubmit: this.doLogin,
|
|
5890
|
-
"data-test": "formLoginTest"
|
|
5891
|
-
}, /*#__PURE__*/React.createElement("div", {
|
|
5892
|
-
className: "field"
|
|
5893
|
-
}, /*#__PURE__*/React.createElement("label", {
|
|
5894
|
-
className: "label"
|
|
5895
|
-
}, "Username:"), /*#__PURE__*/React.createElement("input", {
|
|
5896
|
-
type: "text",
|
|
5897
|
-
className: "input",
|
|
5898
|
-
placeholder: "Username",
|
|
5899
|
-
onChange: e => this.setState({
|
|
5900
|
-
username: e.target.value
|
|
5901
|
-
}),
|
|
5902
|
-
value: username,
|
|
5903
|
-
ref: this.ref,
|
|
5904
|
-
"data-test": "inputUsernameLoginTest"
|
|
5905
|
-
})), /*#__PURE__*/React.createElement("div", {
|
|
5906
|
-
className: "field"
|
|
5907
|
-
}, /*#__PURE__*/React.createElement("label", {
|
|
5908
|
-
className: "label"
|
|
5909
|
-
}, "Password:"), /*#__PURE__*/React.createElement("input", {
|
|
5910
|
-
type: "password",
|
|
5911
|
-
className: "input",
|
|
5912
|
-
onChange: e => this.setState({
|
|
5913
|
-
password: e.target.value
|
|
5914
|
-
}),
|
|
5915
|
-
value: password,
|
|
5916
|
-
"data-test": "inputPasswordLoginTest"
|
|
5917
|
-
})), schemas && /*#__PURE__*/React.createElement("div", {
|
|
5918
|
-
className: "field"
|
|
5919
|
-
}, /*#__PURE__*/React.createElement("label", {
|
|
5920
|
-
className: "label"
|
|
5921
|
-
}, "Schema:"), /*#__PURE__*/React.createElement("div", {
|
|
5922
|
-
className: "select"
|
|
5923
|
-
}, /*#__PURE__*/React.createElement("select", {
|
|
5924
|
-
onChange: e => this.setState({
|
|
5925
|
-
schema: e.target.value
|
|
5926
|
-
})
|
|
5927
|
-
}, schemas.map(s => /*#__PURE__*/React.createElement("option", {
|
|
5928
|
-
value: s,
|
|
5929
|
-
key: s
|
|
5930
|
-
}, s))))), /*#__PURE__*/React.createElement("div", {
|
|
5931
|
-
className: "field"
|
|
5932
|
-
}, /*#__PURE__*/React.createElement("button", {
|
|
5933
|
-
className: "button is-warning",
|
|
5934
|
-
type: "submit",
|
|
5935
|
-
"data-test": "btnLoginTest"
|
|
5936
|
-
}, "Login")), /*#__PURE__*/React.createElement("div", {
|
|
5937
|
-
className: "field"
|
|
5938
|
-
}, errors && /*#__PURE__*/React.createElement("p", {
|
|
5939
|
-
className: "has-text-danger"
|
|
5940
|
-
}, ERRORS[errors] || 'Generic error'))));
|
|
5941
|
-
}
|
|
5924
|
+
if (onLogin) {
|
|
5925
|
+
onLogin();
|
|
5926
|
+
}
|
|
5927
|
+
};
|
|
5942
5928
|
|
|
5943
|
-
|
|
5929
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("form", {
|
|
5930
|
+
className: "login__form",
|
|
5931
|
+
action: "",
|
|
5932
|
+
onSubmit: doLogin,
|
|
5933
|
+
"data-test": "formLoginTest"
|
|
5934
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
5935
|
+
className: "field"
|
|
5936
|
+
}, /*#__PURE__*/React.createElement("label", {
|
|
5937
|
+
className: "label"
|
|
5938
|
+
}, "Username:"), /*#__PURE__*/React.createElement("input", {
|
|
5939
|
+
type: "text",
|
|
5940
|
+
className: "input",
|
|
5941
|
+
placeholder: "Username",
|
|
5942
|
+
onChange: e => setState({
|
|
5943
|
+
username: e.target.value
|
|
5944
|
+
}),
|
|
5945
|
+
value: state.username,
|
|
5946
|
+
ref: inputRef,
|
|
5947
|
+
"data-test": "inputUsernameLoginTest"
|
|
5948
|
+
})), /*#__PURE__*/React.createElement("div", {
|
|
5949
|
+
className: "field"
|
|
5950
|
+
}, /*#__PURE__*/React.createElement("label", {
|
|
5951
|
+
className: "label"
|
|
5952
|
+
}, "Password:"), /*#__PURE__*/React.createElement("input", {
|
|
5953
|
+
type: "password",
|
|
5954
|
+
className: "input",
|
|
5955
|
+
placeholder: "Password",
|
|
5956
|
+
onChange: e => setState({
|
|
5957
|
+
password: e.target.value
|
|
5958
|
+
}),
|
|
5959
|
+
value: state.password,
|
|
5960
|
+
"data-test": "inputPasswordLoginTest"
|
|
5961
|
+
})), schemas && schemas.length > 1 && /*#__PURE__*/React.createElement("div", {
|
|
5962
|
+
className: "field"
|
|
5963
|
+
}, /*#__PURE__*/React.createElement("label", {
|
|
5964
|
+
className: "label"
|
|
5965
|
+
}, "Schema:"), /*#__PURE__*/React.createElement("div", {
|
|
5966
|
+
className: "select"
|
|
5967
|
+
}, /*#__PURE__*/React.createElement("select", {
|
|
5968
|
+
"data-test": "selectSchemaTest",
|
|
5969
|
+
onChange: e => setCurrentSchema(e.target.value)
|
|
5970
|
+
}, schemas.map(s => /*#__PURE__*/React.createElement("option", {
|
|
5971
|
+
value: s,
|
|
5972
|
+
key: s
|
|
5973
|
+
}, s))))), /*#__PURE__*/React.createElement("div", {
|
|
5974
|
+
className: "field"
|
|
5975
|
+
}, /*#__PURE__*/React.createElement("button", {
|
|
5976
|
+
className: "button is-warning",
|
|
5977
|
+
type: "submit",
|
|
5978
|
+
"data-test": "btnLoginTest"
|
|
5979
|
+
}, "Login")), /*#__PURE__*/React.createElement("div", {
|
|
5980
|
+
className: "field"
|
|
5981
|
+
}, state.errors && /*#__PURE__*/React.createElement("p", {
|
|
5982
|
+
className: "has-text-danger"
|
|
5983
|
+
}, ERRORS[state.errors] || 'Generic error'))));
|
|
5984
|
+
};
|
|
5944
5985
|
|
|
5945
5986
|
const ignoreFiels = [];
|
|
5946
5987
|
const extraFields = ['title'];
|
|
@@ -6219,5 +6260,5 @@ class Auth {
|
|
|
6219
6260
|
|
|
6220
6261
|
}
|
|
6221
6262
|
|
|
6222
|
-
export { ACTIONS_OBJECT, AddItem, AddPermission, AllItemsCheckbox, ApplicationCtx, Auth, AuthContext, BaseForm, BehaviorNotImplemented, BehaviorsView, Button, Checkbox, ClientContext, ClientProvider, Config, Confirm, ContainerCtx, ContextToolbar, CreateButton, CreateContainer, DEFAULT_VALUE_EDITABLE_FIELD, DEFAULT_VALUE_NO_EDITABLE_FIELD, DatabaseCtx, Delete, DownloadField, EditableField, EmailInput, FileUpload, Flash, FolderCtx, Form, FormBuilder, GroupCtx, GroupToolbar, GroupsCtx, Guillotina, GuillotinaClient, IAttachment, IDublinCore, IMultiAttachment, Icon, Input, InputList, Item, ItemCheckbox, ItemCtx, ItemModel, ItemTitle, ItemsActionsDropdown, ItemsActionsProvider, Layout, Link, Loading, Login, Modal, NotAllowed, Notification, Pagination, PanelActions, PanelAddons, PanelBehaviors, PanelItems, PanelNotImplemented, PanelPermissions, PanelProperties, PasswordInput, Path, PathTree, PermissionPrinperm, PermissionPrinrole, PermissionRoleperm, Permissions, PropertiesButtonView, PropertiesView, REGEX_EMAIL, REGEX_HEX_COLOR, REGEX_NUMBER, REGEX_URL, RItem, RemoveItems, RenderField, RequiredFieldsForm, RestClient, SearchInput, SearchLabels, Select, Sharing, Table, TabsPanel, Tag, TagsWidget, TdLink, Textarea, TraversalContext, TraversalProvider, UserCtx, UserForm, UsersCtx, UsersToolbar, actions, base64ToArrayBuffer, buildQs, classnames, defaultComponent, formatDate, generateUID, get$1 as get, getClient,
|
|
6263
|
+
export { ACTIONS_OBJECT, AddItem, AddPermission, AllItemsCheckbox, ApplicationCtx, Auth, AuthContext, BaseForm, BehaviorNotImplemented, BehaviorsView, Button, Checkbox, ClientContext, ClientProvider, Config, Confirm, ContainerCtx, ContextToolbar, CreateButton, CreateContainer, DEFAULT_VALUE_EDITABLE_FIELD, DEFAULT_VALUE_NO_EDITABLE_FIELD, DatabaseCtx, Delete, DownloadField, EditableField, EmailInput, FileUpload, Flash, FolderCtx, Form, FormBuilder, GroupCtx, GroupToolbar, GroupsCtx, Guillotina, GuillotinaClient, IAttachment, IDublinCore, IMultiAttachment, Icon, Input, InputList, Item, ItemCheckbox, ItemCtx, ItemModel, ItemTitle, ItemsActionsDropdown, ItemsActionsProvider, Layout, Link, Loading, Login, Modal, NotAllowed, Notification, Pagination, PanelActions, PanelAddons, PanelBehaviors, PanelItems, PanelNotImplemented, PanelPermissions, PanelProperties, PasswordInput, Path, PathTree, PermissionPrinperm, PermissionPrinrole, PermissionRoleperm, Permissions, PropertiesButtonView, PropertiesView, REGEX_EMAIL, REGEX_HEX_COLOR, REGEX_NUMBER, REGEX_URL, RItem, RemoveItems, RenderField, RenderFieldComponent, RequiredFieldsForm, RestClient, SearchInput, SearchLabels, Select, Sharing, Table, TabsPanel, Tag, TagsWidget, TdLink, Textarea, TraversalContext, TraversalProvider, UserCtx, UserForm, UsersCtx, UsersToolbar, actions, base64ToArrayBuffer, buildQs, classnames, defaultComponent, formatDate, generateUID, get$1 as get, getClient, getNewId, isEmail, isEmpty, isHexColor, isNumber, isURL, lightFileReader, maxLength, minLength, noop, notEmpty, parser, sleep, stringToSlug, toQueryString, useConfig, useCrudContext, useGuillotinaClient, useLocation, useRegistry, useRemoteField, useTraversal };
|
|
6223
6264
|
//# sourceMappingURL=react-gmi.modern.js.map
|