@panneau/medias 3.0.126 → 3.0.130

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.
Files changed (3) hide show
  1. package/es/index.js +510 -20
  2. package/lib/index.js +515 -18
  3. package/package.json +14 -13
package/es/index.js CHANGED
@@ -1,9 +1,23 @@
1
1
  import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties';
2
- import React, { useContext, useMemo } from 'react';
2
+ import React, { useContext, useMemo, useCallback, useState } from 'react';
3
3
  import PropTypes from 'prop-types';
4
+ import _objectSpread from '@babel/runtime/helpers/objectSpread2';
5
+ import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
4
6
  import classNames from 'classnames';
7
+ import { PropTypes as PropTypes$1 } from '@panneau/core';
8
+ import { useQuery } from '@panneau/core/hooks';
9
+ import Buttons from '@panneau/element-buttons';
10
+ import Grid from '@panneau/element-grid';
11
+ import Icon from '@panneau/element-icon';
12
+ import MediaCard from '@panneau/element-media-card';
13
+ import Pagination from '@panneau/element-pagination';
14
+ import Table from '@panneau/element-table';
15
+ import Filters from '@panneau/filter-filters';
16
+ import { FormattedMessage } from 'react-intl';
17
+ import { useItems, useData, useApi } from '@panneau/data';
18
+ import Button from '@panneau/element-button';
5
19
  import { usePanneauResource } from '@panneau/core/contexts';
6
- import { useApi } from '@panneau/data';
20
+ import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
7
21
 
8
22
  /* eslint-disable react/jsx-props-no-spreading */
9
23
  var MediasApiContext = /*#__PURE__*/React.createContext(null);
@@ -17,11 +31,11 @@ var apiPropTypes = PropTypes.shape({
17
31
  update: PropTypes.func.isRequired,
18
32
  "delete": PropTypes.func.isRequired
19
33
  });
20
- var propTypes$3 = {
34
+ var propTypes$5 = {
21
35
  api: apiPropTypes,
22
36
  children: PropTypes.node.isRequired
23
37
  };
24
- var defaultProps$3 = {
38
+ var defaultProps$5 = {
25
39
  api: null
26
40
  };
27
41
  function MediasApiProvider(_ref) {
@@ -35,43 +49,519 @@ function MediasApiProvider(_ref) {
35
49
  value: api
36
50
  }, children);
37
51
  }
38
- MediasApiProvider.propTypes = propTypes$3;
39
- MediasApiProvider.defaultProps = defaultProps$3;
52
+ MediasApiProvider.propTypes = propTypes$5;
53
+ MediasApiProvider.defaultProps = defaultProps$5;
54
+
55
+ var _excluded$6 = ["items", "pageItems"];
56
+ var useMedias = function useMedias() {
57
+ var query = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
58
+ var page = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
59
+ var count = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
60
+ var opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
61
+ var api = useMediasApi();
62
+ var getItems = useCallback(function () {
63
+ var requestedPage = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
64
+ return api.get(query, requestedPage, count);
65
+ }, [api, query, count]);
66
+ var _useItems = useItems(_objectSpread({
67
+ getPage: page !== null ? getItems : null,
68
+ getItems: page === null ? getItems : null,
69
+ page: page
70
+ }, opts)),
71
+ items = _useItems.items,
72
+ pageItems = _useItems.pageItems,
73
+ request = _objectWithoutProperties(_useItems, _excluded$6);
74
+ return _objectSpread({
75
+ medias: page !== null ? pageItems : items,
76
+ allMedias: items
77
+ }, request);
78
+ };
79
+ var useMedias$1 = useMedias;
80
+
81
+ var useMediasRecent = function useMediasRecent(opts) {
82
+ var key = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'media-gallery-recent-searches';
83
+ var addSearchValue = useCallback(function (value) {
84
+ if (typeof window !== 'undefined' && typeof window.localStorage !== 'undefined' && value) {
85
+ var recent = window.localStorage.getItem(key) || null;
86
+ var current = recent !== null ? JSON.parse(recent || '[]') : [];
87
+ var encoded = JSON.stringify([value].concat(_toConsumableArray(current)));
88
+ window.localStorage.setItem(key, encoded);
89
+ return true;
90
+ }
91
+ return false;
92
+ }, [key]);
93
+ var getSearchValues = useCallback(function () {
94
+ var count = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 5;
95
+ if (typeof window !== 'undefined' && typeof window.localStorage !== 'undefined') {
96
+ var recent = window.localStorage.getItem(key) || null;
97
+ var current = recent !== null ? JSON.parse(recent || '[]') : [];
98
+ return current.slice(0, count);
99
+ }
100
+ return [];
101
+ }, [key]);
102
+ return {
103
+ addSearchValue: addSearchValue,
104
+ getSearchValues: getSearchValues
105
+ };
106
+ };
107
+ var useMediasRecent$1 = useMediasRecent;
108
+
109
+ var _excluded$5 = ["data"];
110
+ var useMedia = function useMedia(id, opts) {
111
+ var api = useMediasApi();
112
+ var loader = useCallback(function () {
113
+ return api.find(id);
114
+ }, [api, id]);
115
+ var _useData = useData(loader, opts),
116
+ data = _useData.data,
117
+ request = _objectWithoutProperties(_useData, _excluded$5);
118
+ return _objectSpread({
119
+ story: data
120
+ }, request);
121
+ };
122
+ var useMedia$1 = useMedia;
123
+
124
+ var useMediaCreate = function useMediaCreate() {
125
+ var _useState = useState(false),
126
+ _useState2 = _slicedToArray(_useState, 2),
127
+ loading = _useState2[0],
128
+ setLoading = _useState2[1];
129
+ var api = useMediasApi();
130
+ var create = useCallback(function (data) {
131
+ setLoading(true);
132
+ return api.create(data).then(function (response) {
133
+ setLoading(false);
134
+ return response;
135
+ });
136
+ }, [api, setLoading]);
137
+ return {
138
+ create: create,
139
+ loading: loading
140
+ };
141
+ };
142
+ var useMediaCreate$1 = useMediaCreate;
143
+
144
+ var useMediaUpdate = function useMediaUpdate() {
145
+ var _useState = useState(false),
146
+ _useState2 = _slicedToArray(_useState, 2),
147
+ loading = _useState2[0],
148
+ setLoading = _useState2[1];
149
+ var api = useMediasApi();
150
+ var update = useCallback(function (id, data) {
151
+ setLoading(true);
152
+ return api.update(id, data).then(function (response) {
153
+ setLoading(false);
154
+ return response;
155
+ });
156
+ }, [api, setLoading]);
157
+ return {
158
+ update: update,
159
+ loading: loading
160
+ };
161
+ };
162
+ var useMediaUpdate$1 = useMediaUpdate;
163
+
164
+ var defaultColumns = [{
165
+ id: 'name',
166
+ label: /*#__PURE__*/React.createElement(FormattedMessage, {
167
+ id: "WX83V9",
168
+ defaultMessage: [{
169
+ "type": 0,
170
+ "value": "File name"
171
+ }]
172
+ }),
173
+ component: 'text',
174
+ path: 'name',
175
+ sortable: true,
176
+ selectable: true
177
+ }, {
178
+ id: 'created_at',
179
+ label: /*#__PURE__*/React.createElement(FormattedMessage, {
180
+ id: "OzYWZz",
181
+ defaultMessage: [{
182
+ "type": 0,
183
+ "value": "Created at"
184
+ }]
185
+ }),
186
+ component: 'text',
187
+ path: 'created_at',
188
+ sortable: true
189
+ }, {
190
+ id: 'dimensions',
191
+ label: /*#__PURE__*/React.createElement(FormattedMessage, {
192
+ id: "eCe9ZY",
193
+ defaultMessage: [{
194
+ "type": 0,
195
+ "value": "Dimensions"
196
+ }]
197
+ }),
198
+ component: 'unit',
199
+ format: 'dimensions',
200
+ path: 'metadata'
201
+ }, {
202
+ id: 'size',
203
+ label: /*#__PURE__*/React.createElement(FormattedMessage, {
204
+ id: "c3hu9o",
205
+ defaultMessage: [{
206
+ "type": 0,
207
+ "value": "Size"
208
+ }]
209
+ }),
210
+ component: 'unit',
211
+ format: 'bytes',
212
+ path: 'metadata.size'
213
+ }, {
214
+ id: 'duration',
215
+ label: /*#__PURE__*/React.createElement(FormattedMessage, {
216
+ id: "002oWQ",
217
+ defaultMessage: [{
218
+ "type": 0,
219
+ "value": "Duration"
220
+ }]
221
+ }),
222
+ component: 'unit',
223
+ format: 'duration',
224
+ path: 'metadata.duration'
225
+ }, {
226
+ id: 'author',
227
+ label: /*#__PURE__*/React.createElement(FormattedMessage, {
228
+ id: "KNeQ6y",
229
+ defaultMessage: [{
230
+ "type": 0,
231
+ "value": "Added by"
232
+ }]
233
+ }),
234
+ component: 'text',
235
+ path: 'metadata.author.name'
236
+ }, {
237
+ id: 'status',
238
+ label: /*#__PURE__*/React.createElement(FormattedMessage, {
239
+ id: "lRvafH",
240
+ defaultMessage: [{
241
+ "type": 0,
242
+ "value": "Status"
243
+ }]
244
+ }),
245
+ component: 'text',
246
+ path: 'metadata.status'
247
+ }];
248
+
249
+ var defaultFilters = [{
250
+ id: 'type',
251
+ component: 'select',
252
+ name: 'type',
253
+ placeholder: /*#__PURE__*/React.createElement(FormattedMessage, {
254
+ id: "9/t5wK",
255
+ defaultMessage: [{
256
+ "type": 0,
257
+ "value": "Type"
258
+ }]
259
+ }),
260
+ options: [{
261
+ label: /*#__PURE__*/React.createElement(FormattedMessage, {
262
+ id: "yHAmDD",
263
+ defaultMessage: [{
264
+ "type": 0,
265
+ "value": "Image"
266
+ }]
267
+ }),
268
+ value: 'image'
269
+ }, {
270
+ label: /*#__PURE__*/React.createElement(FormattedMessage, {
271
+ id: "xSERPA",
272
+ defaultMessage: [{
273
+ "type": 0,
274
+ "value": "Video"
275
+ }]
276
+ }),
277
+ value: 'video'
278
+ }, {
279
+ label: /*#__PURE__*/React.createElement(FormattedMessage, {
280
+ id: "yQRtgx",
281
+ defaultMessage: [{
282
+ "type": 0,
283
+ "value": "Audio"
284
+ }]
285
+ }),
286
+ value: 'audio'
287
+ }]
288
+ }, {
289
+ id: 'author',
290
+ component: 'select',
291
+ name: 'author',
292
+ placeholder: /*#__PURE__*/React.createElement(FormattedMessage, {
293
+ id: "skmuWU",
294
+ defaultMessage: [{
295
+ "type": 0,
296
+ "value": "Author"
297
+ }]
298
+ }),
299
+ options: []
300
+ }, {
301
+ id: 'tag',
302
+ component: 'select',
303
+ name: 'tag',
304
+ placeholder: /*#__PURE__*/React.createElement(FormattedMessage, {
305
+ id: "hnLSrX",
306
+ defaultMessage: [{
307
+ "type": 0,
308
+ "value": "Tag"
309
+ }]
310
+ }),
311
+ options: []
312
+ }, {
313
+ id: 'search',
314
+ component: 'search',
315
+ name: 'search'
316
+ }];
40
317
 
41
318
  var styles = {};
42
319
 
43
- /* eslint-disable react/jsx-props-no-spreading, react/no-array-index-key */
44
- var propTypes$2 = {
320
+ var _excluded$4 = ["page", "count"];
321
+ var propTypes$4 = {
322
+ items: PropTypes$1.medias,
323
+ filters: PropTypes$1.filters,
324
+ columns: PropTypes$1.tableColumns,
325
+ query: PropTypes.shape({}),
326
+ baseUrl: PropTypes.string,
327
+ // fields: PanneauPropTypes.fields,
328
+ layout: PropTypes.string,
329
+ layouts: PropTypes.arrayOf(PropTypes.shape({})),
330
+ theme: PropTypes.string,
331
+ tableProps: PropTypes.bool,
45
332
  className: PropTypes.string
46
333
  };
47
- var defaultProps$2 = {
334
+ var defaultProps$4 = {
335
+ items: null,
336
+ filters: defaultFilters,
337
+ columns: defaultColumns,
338
+ // fields: null,
339
+ query: null,
340
+ baseUrl: null,
341
+ layout: null,
342
+ layouts: [{
343
+ id: 'table',
344
+ label: /*#__PURE__*/React.createElement(Icon, {
345
+ name: "table"
346
+ })
347
+ }, {
348
+ id: 'grid',
349
+ label: /*#__PURE__*/React.createElement(Icon, {
350
+ name: "grid"
351
+ })
352
+ }],
353
+ theme: null,
354
+ tableProps: null,
48
355
  className: null
49
356
  };
50
357
  function MediasBrowser(_ref) {
51
- var className = _ref.className;
358
+ var initialItems = _ref.items,
359
+ baseUrl = _ref.baseUrl,
360
+ filters = _ref.filters,
361
+ columns = _ref.columns,
362
+ initialQuery = _ref.query,
363
+ initialLayout = _ref.layout,
364
+ layouts = _ref.layouts,
365
+ theme = _ref.theme,
366
+ tableProps = _ref.tableProps,
367
+ className = _ref.className;
368
+ var baseQuery = useMemo(function () {
369
+ return initialQuery;
370
+ }, [initialQuery]);
371
+ var _useQuery = useQuery(baseQuery),
372
+ fullQuery = _useQuery.query,
373
+ onPageChange = _useQuery.onPageChange,
374
+ onQueryChange = _useQuery.onQueryChange,
375
+ onQueryReset = _useQuery.onQueryReset;
376
+ var _useMemo = useMemo(function () {
377
+ var _ref2 = fullQuery || {},
378
+ _ref2$page = _ref2.page,
379
+ fullQueryPage = _ref2$page === void 0 ? null : _ref2$page,
380
+ _ref2$count = _ref2.count,
381
+ fullQueryCount = _ref2$count === void 0 ? null : _ref2$count,
382
+ params = _objectWithoutProperties(_ref2, _excluded$4);
383
+ return {
384
+ page: fullQueryPage,
385
+ count: fullQueryCount,
386
+ query: params
387
+ };
388
+ }, [fullQuery]),
389
+ _useMemo$page = _useMemo.page,
390
+ page = _useMemo$page === void 0 ? null : _useMemo$page,
391
+ _useMemo$count = _useMemo.count,
392
+ count = _useMemo$count === void 0 ? null : _useMemo$count,
393
+ _useMemo$query = _useMemo.query,
394
+ query = _useMemo$query === void 0 ? null : _useMemo$query;
395
+ var _useMedias = useMedias$1(query, page, count, {
396
+ initialItems: initialItems
397
+ }),
398
+ items = _useMedias.medias,
399
+ loading = _useMedias.loading,
400
+ lastPage = _useMedias.lastPage,
401
+ total = _useMedias.total;
402
+ var _useState = useState(initialLayout || 'grid'),
403
+ _useState2 = _slicedToArray(_useState, 2),
404
+ layout = _useState2[0],
405
+ setLayout = _useState2[1];
406
+ var hasLayouts = useMemo(function () {
407
+ return layouts !== null && layouts.length > 1;
408
+ }, [layouts]);
409
+ var onClickLayout = useCallback(function (lay) {
410
+ setLayout(lay);
411
+ }, [setLayout]);
52
412
  return /*#__PURE__*/React.createElement("div", {
53
413
  className: classNames([styles.container, className])
54
- }, "gfsdgsdfg");
414
+ }, /*#__PURE__*/React.createElement(Filters, {
415
+ value: query,
416
+ filters: filters,
417
+ onChange: onQueryChange,
418
+ onReset: onQueryReset,
419
+ theme: theme
420
+ }), /*#__PURE__*/React.createElement("div", {
421
+ className: classNames(['d-flex', 'mt-1', 'mb-3', {
422
+ 'justify-content-between': hasLayouts,
423
+ 'justify-content-end': !hasLayouts
424
+ }])
425
+ }, hasLayouts ? /*#__PURE__*/React.createElement(Buttons, {
426
+ size: "sm",
427
+ theme: "primary",
428
+ outline: true,
429
+ items: (layouts || []).map(function (lay) {
430
+ return _objectSpread(_objectSpread({}, lay), {}, {
431
+ active: layout === lay.id,
432
+ onClick: function onClick() {
433
+ return onClickLayout(lay.id);
434
+ }
435
+ });
436
+ })
437
+ }) : null, /*#__PURE__*/React.createElement(Pagination, {
438
+ page: page,
439
+ lastPage: lastPage,
440
+ total: total,
441
+ url: baseUrl,
442
+ query: query,
443
+ onClickPage: onPageChange,
444
+ theme: theme,
445
+ loading: loading,
446
+ withPreviousNext: true,
447
+ alwaysShowButtons: true
448
+ })), layout === 'grid' ? /*#__PURE__*/React.createElement(Grid, Object.assign({}, tableProps, {
449
+ items: items || [],
450
+ component: MediaCard,
451
+ componentProps: {
452
+ className: 'd-flex w-100',
453
+ cardClassName: 'flex-grow-1'
454
+ }
455
+ })) : /*#__PURE__*/React.createElement(Table, Object.assign({}, tableProps, {
456
+ columns: columns,
457
+ items: items
458
+ })), /*#__PURE__*/React.createElement("div", {
459
+ className: classNames(['d-flex', 'mt-3', 'mb-1', 'justify-content-end'])
460
+ }, /*#__PURE__*/React.createElement(Pagination, {
461
+ page: page,
462
+ lastPage: lastPage,
463
+ total: total,
464
+ url: baseUrl,
465
+ query: query,
466
+ onClickPage: onPageChange,
467
+ theme: theme,
468
+ loading: loading,
469
+ withPreviousNext: true,
470
+ alwaysShowButtons: true
471
+ })));
55
472
  }
56
- MediasBrowser.propTypes = propTypes$2;
57
- MediasBrowser.defaultProps = defaultProps$2;
473
+ MediasBrowser.propTypes = propTypes$4;
474
+ MediasBrowser.defaultProps = defaultProps$4;
58
475
 
59
- var _excluded$1 = ["api"];
60
- var propTypes$1 = {
476
+ var _excluded$3 = ["api"];
477
+ var propTypes$3 = {
61
478
  api: apiPropTypes
62
479
  };
63
- var defaultProps$1 = {
480
+ var defaultProps$3 = {
64
481
  api: null
65
482
  };
66
483
  function MediasBrowserContainer(_ref) {
67
484
  var api = _ref.api,
68
- props = _objectWithoutProperties(_ref, _excluded$1);
485
+ props = _objectWithoutProperties(_ref, _excluded$3);
69
486
  return /*#__PURE__*/React.createElement(MediasApiProvider, {
70
487
  api: api
71
488
  }, /*#__PURE__*/React.createElement(MediasBrowser, props));
72
489
  }
73
- MediasBrowserContainer.propTypes = propTypes$1;
74
- MediasBrowserContainer.defaultProps = defaultProps$1;
490
+ MediasBrowserContainer.propTypes = propTypes$3;
491
+ MediasBrowserContainer.defaultProps = defaultProps$3;
492
+
493
+ var _excluded$2 = ["value", "onChange", "onConfirm", "multiple", "className"];
494
+ var propTypes$2 = {
495
+ // eslint-disable-next-line react/forbid-prop-types
496
+ value: PropTypes.any,
497
+ onChange: PropTypes.func.isRequired,
498
+ onConfirm: PropTypes.func.isRequired,
499
+ multiple: PropTypes.bool,
500
+ className: PropTypes.string
501
+ };
502
+ var defaultProps$2 = {
503
+ value: null,
504
+ multiple: false,
505
+ className: null
506
+ };
507
+ function MediasPicker(_ref) {
508
+ var value = _ref.value,
509
+ onChange = _ref.onChange,
510
+ onConfirm = _ref.onConfirm,
511
+ multiple = _ref.multiple,
512
+ className = _ref.className,
513
+ props = _objectWithoutProperties(_ref, _excluded$2);
514
+ var onSelectionChange = useCallback(function (items) {
515
+ if (onChange !== null) {
516
+ onChange(items);
517
+ }
518
+ }, [onChange]);
519
+ var disabled = value === null || value.length < 1;
520
+ return /*#__PURE__*/React.createElement("div", {
521
+ className: className
522
+ }, /*#__PURE__*/React.createElement(MediasBrowser, Object.assign({
523
+ tableProps: {
524
+ selectable: true,
525
+ multiple: multiple,
526
+ onSelectionChange: onSelectionChange
527
+ }
528
+ }, props)), multiple ? /*#__PURE__*/React.createElement(Button, {
529
+ className: "mt-2",
530
+ onClick: onConfirm,
531
+ theme: "info",
532
+ disabled: disabled,
533
+ outline: disabled
534
+ }, /*#__PURE__*/React.createElement(FormattedMessage, {
535
+ id: "UaVu03",
536
+ defaultMessage: [{
537
+ "type": 0,
538
+ "value": "Confirm"
539
+ }]
540
+ })) : null);
541
+ }
542
+ MediasPicker.propTypes = propTypes$2;
543
+ MediasPicker.defaultProps = defaultProps$2;
544
+
545
+ var _excluded$1 = ["api", "onChange"];
546
+ var propTypes$1 = {
547
+ api: apiPropTypes,
548
+ onChange: PropTypes.func.isRequired
549
+ };
550
+ var defaultProps$1 = {
551
+ api: null
552
+ };
553
+ function MediasPickerContainer(_ref) {
554
+ var api = _ref.api,
555
+ onChange = _ref.onChange,
556
+ props = _objectWithoutProperties(_ref, _excluded$1);
557
+ return /*#__PURE__*/React.createElement(MediasApiProvider, {
558
+ api: api
559
+ }, /*#__PURE__*/React.createElement(MediasPicker, Object.assign({}, props, {
560
+ onChange: onChange
561
+ })));
562
+ }
563
+ MediasPickerContainer.propTypes = propTypes$1;
564
+ MediasPickerContainer.defaultProps = defaultProps$1;
75
565
 
76
566
  var _excluded = ["resource"];
77
567
  var propTypes = {
@@ -131,4 +621,4 @@ function MediasResourceBrowser(_ref) {
131
621
  MediasResourceBrowser.propTypes = propTypes;
132
622
  MediasResourceBrowser.defaultProps = defaultProps;
133
623
 
134
- export { MediasApiProvider, MediasBrowser, MediasResourceBrowser, apiPropTypes, MediasBrowserContainer as default, useMediasApi };
624
+ export { MediasApiProvider, MediasBrowser, MediasPicker, MediasPickerContainer, MediasResourceBrowser, apiPropTypes, MediasBrowserContainer as default, useMedia$1 as useMedia, useMediaCreate$1 as useMediaCreate, useMediaUpdate$1 as useMediaUpdate, useMedias$1 as useMedias, useMediasApi, useMediasRecent$1 as useMediasRecentSearches };
package/lib/index.js CHANGED
@@ -5,9 +5,23 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProperties');
6
6
  var React = require('react');
7
7
  var PropTypes = require('prop-types');
8
+ var _objectSpread = require('@babel/runtime/helpers/objectSpread2');
9
+ var _slicedToArray = require('@babel/runtime/helpers/slicedToArray');
8
10
  var classNames = require('classnames');
9
- var contexts = require('@panneau/core/contexts');
11
+ var core = require('@panneau/core');
12
+ var hooks = require('@panneau/core/hooks');
13
+ var Buttons = require('@panneau/element-buttons');
14
+ var Grid = require('@panneau/element-grid');
15
+ var Icon = require('@panneau/element-icon');
16
+ var MediaCard = require('@panneau/element-media-card');
17
+ var Pagination = require('@panneau/element-pagination');
18
+ var Table = require('@panneau/element-table');
19
+ var Filters = require('@panneau/filter-filters');
20
+ var reactIntl = require('react-intl');
10
21
  var data = require('@panneau/data');
22
+ var Button = require('@panneau/element-button');
23
+ var contexts = require('@panneau/core/contexts');
24
+ var _toConsumableArray = require('@babel/runtime/helpers/toConsumableArray');
11
25
 
12
26
  /* eslint-disable react/jsx-props-no-spreading */
13
27
  var MediasApiContext = /*#__PURE__*/React.createContext(null);
@@ -21,11 +35,11 @@ var apiPropTypes = PropTypes.shape({
21
35
  update: PropTypes.func.isRequired,
22
36
  "delete": PropTypes.func.isRequired
23
37
  });
24
- var propTypes$3 = {
38
+ var propTypes$5 = {
25
39
  api: apiPropTypes,
26
40
  children: PropTypes.node.isRequired
27
41
  };
28
- var defaultProps$3 = {
42
+ var defaultProps$5 = {
29
43
  api: null
30
44
  };
31
45
  function MediasApiProvider(_ref) {
@@ -39,43 +53,519 @@ function MediasApiProvider(_ref) {
39
53
  value: api
40
54
  }, children);
41
55
  }
42
- MediasApiProvider.propTypes = propTypes$3;
43
- MediasApiProvider.defaultProps = defaultProps$3;
56
+ MediasApiProvider.propTypes = propTypes$5;
57
+ MediasApiProvider.defaultProps = defaultProps$5;
58
+
59
+ var _excluded$6 = ["items", "pageItems"];
60
+ var useMedias = function useMedias() {
61
+ var query = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
62
+ var page = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
63
+ var count = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
64
+ var opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
65
+ var api = useMediasApi();
66
+ var getItems = React.useCallback(function () {
67
+ var requestedPage = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
68
+ return api.get(query, requestedPage, count);
69
+ }, [api, query, count]);
70
+ var _useItems = data.useItems(_objectSpread({
71
+ getPage: page !== null ? getItems : null,
72
+ getItems: page === null ? getItems : null,
73
+ page: page
74
+ }, opts)),
75
+ items = _useItems.items,
76
+ pageItems = _useItems.pageItems,
77
+ request = _objectWithoutProperties(_useItems, _excluded$6);
78
+ return _objectSpread({
79
+ medias: page !== null ? pageItems : items,
80
+ allMedias: items
81
+ }, request);
82
+ };
83
+ var useMedias$1 = useMedias;
84
+
85
+ var useMediasRecent = function useMediasRecent(opts) {
86
+ var key = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'media-gallery-recent-searches';
87
+ var addSearchValue = React.useCallback(function (value) {
88
+ if (typeof window !== 'undefined' && typeof window.localStorage !== 'undefined' && value) {
89
+ var recent = window.localStorage.getItem(key) || null;
90
+ var current = recent !== null ? JSON.parse(recent || '[]') : [];
91
+ var encoded = JSON.stringify([value].concat(_toConsumableArray(current)));
92
+ window.localStorage.setItem(key, encoded);
93
+ return true;
94
+ }
95
+ return false;
96
+ }, [key]);
97
+ var getSearchValues = React.useCallback(function () {
98
+ var count = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 5;
99
+ if (typeof window !== 'undefined' && typeof window.localStorage !== 'undefined') {
100
+ var recent = window.localStorage.getItem(key) || null;
101
+ var current = recent !== null ? JSON.parse(recent || '[]') : [];
102
+ return current.slice(0, count);
103
+ }
104
+ return [];
105
+ }, [key]);
106
+ return {
107
+ addSearchValue: addSearchValue,
108
+ getSearchValues: getSearchValues
109
+ };
110
+ };
111
+ var useMediasRecent$1 = useMediasRecent;
112
+
113
+ var _excluded$5 = ["data"];
114
+ var useMedia = function useMedia(id, opts) {
115
+ var api = useMediasApi();
116
+ var loader = React.useCallback(function () {
117
+ return api.find(id);
118
+ }, [api, id]);
119
+ var _useData = data.useData(loader, opts),
120
+ data$1 = _useData.data,
121
+ request = _objectWithoutProperties(_useData, _excluded$5);
122
+ return _objectSpread({
123
+ story: data$1
124
+ }, request);
125
+ };
126
+ var useMedia$1 = useMedia;
127
+
128
+ var useMediaCreate = function useMediaCreate() {
129
+ var _useState = React.useState(false),
130
+ _useState2 = _slicedToArray(_useState, 2),
131
+ loading = _useState2[0],
132
+ setLoading = _useState2[1];
133
+ var api = useMediasApi();
134
+ var create = React.useCallback(function (data) {
135
+ setLoading(true);
136
+ return api.create(data).then(function (response) {
137
+ setLoading(false);
138
+ return response;
139
+ });
140
+ }, [api, setLoading]);
141
+ return {
142
+ create: create,
143
+ loading: loading
144
+ };
145
+ };
146
+ var useMediaCreate$1 = useMediaCreate;
147
+
148
+ var useMediaUpdate = function useMediaUpdate() {
149
+ var _useState = React.useState(false),
150
+ _useState2 = _slicedToArray(_useState, 2),
151
+ loading = _useState2[0],
152
+ setLoading = _useState2[1];
153
+ var api = useMediasApi();
154
+ var update = React.useCallback(function (id, data) {
155
+ setLoading(true);
156
+ return api.update(id, data).then(function (response) {
157
+ setLoading(false);
158
+ return response;
159
+ });
160
+ }, [api, setLoading]);
161
+ return {
162
+ update: update,
163
+ loading: loading
164
+ };
165
+ };
166
+ var useMediaUpdate$1 = useMediaUpdate;
167
+
168
+ var defaultColumns = [{
169
+ id: 'name',
170
+ label: /*#__PURE__*/React.createElement(reactIntl.FormattedMessage, {
171
+ id: "WX83V9",
172
+ defaultMessage: [{
173
+ "type": 0,
174
+ "value": "File name"
175
+ }]
176
+ }),
177
+ component: 'text',
178
+ path: 'name',
179
+ sortable: true,
180
+ selectable: true
181
+ }, {
182
+ id: 'created_at',
183
+ label: /*#__PURE__*/React.createElement(reactIntl.FormattedMessage, {
184
+ id: "OzYWZz",
185
+ defaultMessage: [{
186
+ "type": 0,
187
+ "value": "Created at"
188
+ }]
189
+ }),
190
+ component: 'text',
191
+ path: 'created_at',
192
+ sortable: true
193
+ }, {
194
+ id: 'dimensions',
195
+ label: /*#__PURE__*/React.createElement(reactIntl.FormattedMessage, {
196
+ id: "eCe9ZY",
197
+ defaultMessage: [{
198
+ "type": 0,
199
+ "value": "Dimensions"
200
+ }]
201
+ }),
202
+ component: 'unit',
203
+ format: 'dimensions',
204
+ path: 'metadata'
205
+ }, {
206
+ id: 'size',
207
+ label: /*#__PURE__*/React.createElement(reactIntl.FormattedMessage, {
208
+ id: "c3hu9o",
209
+ defaultMessage: [{
210
+ "type": 0,
211
+ "value": "Size"
212
+ }]
213
+ }),
214
+ component: 'unit',
215
+ format: 'bytes',
216
+ path: 'metadata.size'
217
+ }, {
218
+ id: 'duration',
219
+ label: /*#__PURE__*/React.createElement(reactIntl.FormattedMessage, {
220
+ id: "002oWQ",
221
+ defaultMessage: [{
222
+ "type": 0,
223
+ "value": "Duration"
224
+ }]
225
+ }),
226
+ component: 'unit',
227
+ format: 'duration',
228
+ path: 'metadata.duration'
229
+ }, {
230
+ id: 'author',
231
+ label: /*#__PURE__*/React.createElement(reactIntl.FormattedMessage, {
232
+ id: "KNeQ6y",
233
+ defaultMessage: [{
234
+ "type": 0,
235
+ "value": "Added by"
236
+ }]
237
+ }),
238
+ component: 'text',
239
+ path: 'metadata.author.name'
240
+ }, {
241
+ id: 'status',
242
+ label: /*#__PURE__*/React.createElement(reactIntl.FormattedMessage, {
243
+ id: "lRvafH",
244
+ defaultMessage: [{
245
+ "type": 0,
246
+ "value": "Status"
247
+ }]
248
+ }),
249
+ component: 'text',
250
+ path: 'metadata.status'
251
+ }];
252
+
253
+ var defaultFilters = [{
254
+ id: 'type',
255
+ component: 'select',
256
+ name: 'type',
257
+ placeholder: /*#__PURE__*/React.createElement(reactIntl.FormattedMessage, {
258
+ id: "9/t5wK",
259
+ defaultMessage: [{
260
+ "type": 0,
261
+ "value": "Type"
262
+ }]
263
+ }),
264
+ options: [{
265
+ label: /*#__PURE__*/React.createElement(reactIntl.FormattedMessage, {
266
+ id: "yHAmDD",
267
+ defaultMessage: [{
268
+ "type": 0,
269
+ "value": "Image"
270
+ }]
271
+ }),
272
+ value: 'image'
273
+ }, {
274
+ label: /*#__PURE__*/React.createElement(reactIntl.FormattedMessage, {
275
+ id: "xSERPA",
276
+ defaultMessage: [{
277
+ "type": 0,
278
+ "value": "Video"
279
+ }]
280
+ }),
281
+ value: 'video'
282
+ }, {
283
+ label: /*#__PURE__*/React.createElement(reactIntl.FormattedMessage, {
284
+ id: "yQRtgx",
285
+ defaultMessage: [{
286
+ "type": 0,
287
+ "value": "Audio"
288
+ }]
289
+ }),
290
+ value: 'audio'
291
+ }]
292
+ }, {
293
+ id: 'author',
294
+ component: 'select',
295
+ name: 'author',
296
+ placeholder: /*#__PURE__*/React.createElement(reactIntl.FormattedMessage, {
297
+ id: "skmuWU",
298
+ defaultMessage: [{
299
+ "type": 0,
300
+ "value": "Author"
301
+ }]
302
+ }),
303
+ options: []
304
+ }, {
305
+ id: 'tag',
306
+ component: 'select',
307
+ name: 'tag',
308
+ placeholder: /*#__PURE__*/React.createElement(reactIntl.FormattedMessage, {
309
+ id: "hnLSrX",
310
+ defaultMessage: [{
311
+ "type": 0,
312
+ "value": "Tag"
313
+ }]
314
+ }),
315
+ options: []
316
+ }, {
317
+ id: 'search',
318
+ component: 'search',
319
+ name: 'search'
320
+ }];
44
321
 
45
322
  var styles = {};
46
323
 
47
- /* eslint-disable react/jsx-props-no-spreading, react/no-array-index-key */
48
- var propTypes$2 = {
324
+ var _excluded$4 = ["page", "count"];
325
+ var propTypes$4 = {
326
+ items: core.PropTypes.medias,
327
+ filters: core.PropTypes.filters,
328
+ columns: core.PropTypes.tableColumns,
329
+ query: PropTypes.shape({}),
330
+ baseUrl: PropTypes.string,
331
+ // fields: PanneauPropTypes.fields,
332
+ layout: PropTypes.string,
333
+ layouts: PropTypes.arrayOf(PropTypes.shape({})),
334
+ theme: PropTypes.string,
335
+ tableProps: PropTypes.bool,
49
336
  className: PropTypes.string
50
337
  };
51
- var defaultProps$2 = {
338
+ var defaultProps$4 = {
339
+ items: null,
340
+ filters: defaultFilters,
341
+ columns: defaultColumns,
342
+ // fields: null,
343
+ query: null,
344
+ baseUrl: null,
345
+ layout: null,
346
+ layouts: [{
347
+ id: 'table',
348
+ label: /*#__PURE__*/React.createElement(Icon, {
349
+ name: "table"
350
+ })
351
+ }, {
352
+ id: 'grid',
353
+ label: /*#__PURE__*/React.createElement(Icon, {
354
+ name: "grid"
355
+ })
356
+ }],
357
+ theme: null,
358
+ tableProps: null,
52
359
  className: null
53
360
  };
54
361
  function MediasBrowser(_ref) {
55
- var className = _ref.className;
362
+ var initialItems = _ref.items,
363
+ baseUrl = _ref.baseUrl,
364
+ filters = _ref.filters,
365
+ columns = _ref.columns,
366
+ initialQuery = _ref.query,
367
+ initialLayout = _ref.layout,
368
+ layouts = _ref.layouts,
369
+ theme = _ref.theme,
370
+ tableProps = _ref.tableProps,
371
+ className = _ref.className;
372
+ var baseQuery = React.useMemo(function () {
373
+ return initialQuery;
374
+ }, [initialQuery]);
375
+ var _useQuery = hooks.useQuery(baseQuery),
376
+ fullQuery = _useQuery.query,
377
+ onPageChange = _useQuery.onPageChange,
378
+ onQueryChange = _useQuery.onQueryChange,
379
+ onQueryReset = _useQuery.onQueryReset;
380
+ var _useMemo = React.useMemo(function () {
381
+ var _ref2 = fullQuery || {},
382
+ _ref2$page = _ref2.page,
383
+ fullQueryPage = _ref2$page === void 0 ? null : _ref2$page,
384
+ _ref2$count = _ref2.count,
385
+ fullQueryCount = _ref2$count === void 0 ? null : _ref2$count,
386
+ params = _objectWithoutProperties(_ref2, _excluded$4);
387
+ return {
388
+ page: fullQueryPage,
389
+ count: fullQueryCount,
390
+ query: params
391
+ };
392
+ }, [fullQuery]),
393
+ _useMemo$page = _useMemo.page,
394
+ page = _useMemo$page === void 0 ? null : _useMemo$page,
395
+ _useMemo$count = _useMemo.count,
396
+ count = _useMemo$count === void 0 ? null : _useMemo$count,
397
+ _useMemo$query = _useMemo.query,
398
+ query = _useMemo$query === void 0 ? null : _useMemo$query;
399
+ var _useMedias = useMedias$1(query, page, count, {
400
+ initialItems: initialItems
401
+ }),
402
+ items = _useMedias.medias,
403
+ loading = _useMedias.loading,
404
+ lastPage = _useMedias.lastPage,
405
+ total = _useMedias.total;
406
+ var _useState = React.useState(initialLayout || 'grid'),
407
+ _useState2 = _slicedToArray(_useState, 2),
408
+ layout = _useState2[0],
409
+ setLayout = _useState2[1];
410
+ var hasLayouts = React.useMemo(function () {
411
+ return layouts !== null && layouts.length > 1;
412
+ }, [layouts]);
413
+ var onClickLayout = React.useCallback(function (lay) {
414
+ setLayout(lay);
415
+ }, [setLayout]);
56
416
  return /*#__PURE__*/React.createElement("div", {
57
417
  className: classNames([styles.container, className])
58
- }, "gfsdgsdfg");
418
+ }, /*#__PURE__*/React.createElement(Filters, {
419
+ value: query,
420
+ filters: filters,
421
+ onChange: onQueryChange,
422
+ onReset: onQueryReset,
423
+ theme: theme
424
+ }), /*#__PURE__*/React.createElement("div", {
425
+ className: classNames(['d-flex', 'mt-1', 'mb-3', {
426
+ 'justify-content-between': hasLayouts,
427
+ 'justify-content-end': !hasLayouts
428
+ }])
429
+ }, hasLayouts ? /*#__PURE__*/React.createElement(Buttons, {
430
+ size: "sm",
431
+ theme: "primary",
432
+ outline: true,
433
+ items: (layouts || []).map(function (lay) {
434
+ return _objectSpread(_objectSpread({}, lay), {}, {
435
+ active: layout === lay.id,
436
+ onClick: function onClick() {
437
+ return onClickLayout(lay.id);
438
+ }
439
+ });
440
+ })
441
+ }) : null, /*#__PURE__*/React.createElement(Pagination, {
442
+ page: page,
443
+ lastPage: lastPage,
444
+ total: total,
445
+ url: baseUrl,
446
+ query: query,
447
+ onClickPage: onPageChange,
448
+ theme: theme,
449
+ loading: loading,
450
+ withPreviousNext: true,
451
+ alwaysShowButtons: true
452
+ })), layout === 'grid' ? /*#__PURE__*/React.createElement(Grid, Object.assign({}, tableProps, {
453
+ items: items || [],
454
+ component: MediaCard,
455
+ componentProps: {
456
+ className: 'd-flex w-100',
457
+ cardClassName: 'flex-grow-1'
458
+ }
459
+ })) : /*#__PURE__*/React.createElement(Table, Object.assign({}, tableProps, {
460
+ columns: columns,
461
+ items: items
462
+ })), /*#__PURE__*/React.createElement("div", {
463
+ className: classNames(['d-flex', 'mt-3', 'mb-1', 'justify-content-end'])
464
+ }, /*#__PURE__*/React.createElement(Pagination, {
465
+ page: page,
466
+ lastPage: lastPage,
467
+ total: total,
468
+ url: baseUrl,
469
+ query: query,
470
+ onClickPage: onPageChange,
471
+ theme: theme,
472
+ loading: loading,
473
+ withPreviousNext: true,
474
+ alwaysShowButtons: true
475
+ })));
59
476
  }
60
- MediasBrowser.propTypes = propTypes$2;
61
- MediasBrowser.defaultProps = defaultProps$2;
477
+ MediasBrowser.propTypes = propTypes$4;
478
+ MediasBrowser.defaultProps = defaultProps$4;
62
479
 
63
- var _excluded$1 = ["api"];
64
- var propTypes$1 = {
480
+ var _excluded$3 = ["api"];
481
+ var propTypes$3 = {
65
482
  api: apiPropTypes
66
483
  };
67
- var defaultProps$1 = {
484
+ var defaultProps$3 = {
68
485
  api: null
69
486
  };
70
487
  function MediasBrowserContainer(_ref) {
71
488
  var api = _ref.api,
72
- props = _objectWithoutProperties(_ref, _excluded$1);
489
+ props = _objectWithoutProperties(_ref, _excluded$3);
73
490
  return /*#__PURE__*/React.createElement(MediasApiProvider, {
74
491
  api: api
75
492
  }, /*#__PURE__*/React.createElement(MediasBrowser, props));
76
493
  }
77
- MediasBrowserContainer.propTypes = propTypes$1;
78
- MediasBrowserContainer.defaultProps = defaultProps$1;
494
+ MediasBrowserContainer.propTypes = propTypes$3;
495
+ MediasBrowserContainer.defaultProps = defaultProps$3;
496
+
497
+ var _excluded$2 = ["value", "onChange", "onConfirm", "multiple", "className"];
498
+ var propTypes$2 = {
499
+ // eslint-disable-next-line react/forbid-prop-types
500
+ value: PropTypes.any,
501
+ onChange: PropTypes.func.isRequired,
502
+ onConfirm: PropTypes.func.isRequired,
503
+ multiple: PropTypes.bool,
504
+ className: PropTypes.string
505
+ };
506
+ var defaultProps$2 = {
507
+ value: null,
508
+ multiple: false,
509
+ className: null
510
+ };
511
+ function MediasPicker(_ref) {
512
+ var value = _ref.value,
513
+ onChange = _ref.onChange,
514
+ onConfirm = _ref.onConfirm,
515
+ multiple = _ref.multiple,
516
+ className = _ref.className,
517
+ props = _objectWithoutProperties(_ref, _excluded$2);
518
+ var onSelectionChange = React.useCallback(function (items) {
519
+ if (onChange !== null) {
520
+ onChange(items);
521
+ }
522
+ }, [onChange]);
523
+ var disabled = value === null || value.length < 1;
524
+ return /*#__PURE__*/React.createElement("div", {
525
+ className: className
526
+ }, /*#__PURE__*/React.createElement(MediasBrowser, Object.assign({
527
+ tableProps: {
528
+ selectable: true,
529
+ multiple: multiple,
530
+ onSelectionChange: onSelectionChange
531
+ }
532
+ }, props)), multiple ? /*#__PURE__*/React.createElement(Button, {
533
+ className: "mt-2",
534
+ onClick: onConfirm,
535
+ theme: "info",
536
+ disabled: disabled,
537
+ outline: disabled
538
+ }, /*#__PURE__*/React.createElement(reactIntl.FormattedMessage, {
539
+ id: "UaVu03",
540
+ defaultMessage: [{
541
+ "type": 0,
542
+ "value": "Confirm"
543
+ }]
544
+ })) : null);
545
+ }
546
+ MediasPicker.propTypes = propTypes$2;
547
+ MediasPicker.defaultProps = defaultProps$2;
548
+
549
+ var _excluded$1 = ["api", "onChange"];
550
+ var propTypes$1 = {
551
+ api: apiPropTypes,
552
+ onChange: PropTypes.func.isRequired
553
+ };
554
+ var defaultProps$1 = {
555
+ api: null
556
+ };
557
+ function MediasPickerContainer(_ref) {
558
+ var api = _ref.api,
559
+ onChange = _ref.onChange,
560
+ props = _objectWithoutProperties(_ref, _excluded$1);
561
+ return /*#__PURE__*/React.createElement(MediasApiProvider, {
562
+ api: api
563
+ }, /*#__PURE__*/React.createElement(MediasPicker, Object.assign({}, props, {
564
+ onChange: onChange
565
+ })));
566
+ }
567
+ MediasPickerContainer.propTypes = propTypes$1;
568
+ MediasPickerContainer.defaultProps = defaultProps$1;
79
569
 
80
570
  var _excluded = ["resource"];
81
571
  var propTypes = {
@@ -137,7 +627,14 @@ MediasResourceBrowser.defaultProps = defaultProps;
137
627
 
138
628
  exports.MediasApiProvider = MediasApiProvider;
139
629
  exports.MediasBrowser = MediasBrowser;
630
+ exports.MediasPicker = MediasPicker;
631
+ exports.MediasPickerContainer = MediasPickerContainer;
140
632
  exports.MediasResourceBrowser = MediasResourceBrowser;
141
633
  exports.apiPropTypes = apiPropTypes;
142
634
  exports.default = MediasBrowserContainer;
635
+ exports.useMedia = useMedia$1;
636
+ exports.useMediaCreate = useMediaCreate$1;
637
+ exports.useMediaUpdate = useMediaUpdate$1;
638
+ exports.useMedias = useMedias$1;
143
639
  exports.useMediasApi = useMediasApi;
640
+ exports.useMediasRecentSearches = useMediasRecent$1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@panneau/medias",
3
- "version": "3.0.126",
3
+ "version": "3.0.130",
4
4
  "description": "",
5
5
  "keywords": [
6
6
  "javascript"
@@ -22,14 +22,6 @@
22
22
  {
23
23
  "name": "Nicolas Roy-Bourdages",
24
24
  "email": "nrb@folklore.email"
25
- },
26
- {
27
- "name": "Julien Carignan",
28
- "email": "jc@folklore.email"
29
- },
30
- {
31
- "name": "Théo Gjini",
32
- "email": "tg@folklore.email"
33
25
  }
34
26
  ],
35
27
  "license": "ISC",
@@ -54,14 +46,23 @@
54
46
  },
55
47
  "dependencies": {
56
48
  "@babel/runtime": "^7.12.5",
57
- "@panneau/core": "^3.0.126",
58
- "@panneau/data": "^3.0.126",
49
+ "@panneau/core": "^3.0.130",
50
+ "@panneau/data": "^3.0.130",
51
+ "@panneau/element-button": "^3.0.130",
52
+ "@panneau/element-buttons": "^3.0.130",
53
+ "@panneau/element-grid": "^3.0.130",
54
+ "@panneau/element-icon": "^3.0.130",
55
+ "@panneau/element-media-card": "^3.0.130",
56
+ "@panneau/element-pagination": "^3.0.130",
57
+ "@panneau/element-table": "^3.0.130",
58
+ "@panneau/filter-filters": "^3.0.130",
59
59
  "classnames": "^2.2.6",
60
60
  "lodash": "^4.17.21",
61
- "prop-types": "^15.7.2"
61
+ "prop-types": "^15.7.2",
62
+ "react-intl": "^5.15.8||^6.0.0"
62
63
  },
63
64
  "publishConfig": {
64
65
  "access": "public"
65
66
  },
66
- "gitHead": "fa69ddff3f8cf22b00504093087608d5701e6f6a"
67
+ "gitHead": "e6070daacb45351ccbef67ae8006f1a293ca8e2b"
67
68
  }