@tager/admin-banners 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/dist/constants/menu.d.ts +4 -1
  2. package/dist/constants/paths.d.ts +8 -15
  3. package/dist/constants/routes.d.ts +3 -4
  4. package/dist/hooks/index.d.ts +2 -0
  5. package/dist/hooks/useFetchBanner.d.ts +8 -0
  6. package/dist/hooks/useFetchBanners.d.ts +6 -0
  7. package/dist/hooks/useFetchZones.d.ts +6 -0
  8. package/dist/index.esm.js +3205 -892
  9. package/dist/index.umd.js +3218 -903
  10. package/dist/locales/en.d.ts +39 -0
  11. package/dist/locales/ru.d.ts +3 -0
  12. package/dist/{index.d.ts → main.d.ts} +1 -0
  13. package/dist/router/index.d.ts +4 -0
  14. package/dist/services/requests.d.ts +19 -35
  15. package/dist/typings/banners.d.ts +40 -0
  16. package/dist/typings/common.d.ts +1 -0
  17. package/dist/typings/model.d.ts +103 -15
  18. package/dist/typings/zones.d.ts +5 -0
  19. package/dist/utils/common.d.ts +2 -0
  20. package/dist/views/Banners/BannerForm/BannerForm.helpers.d.ts +5 -0
  21. package/dist/views/Banners/BannerForm/BannerForm.vue.d.ts +81 -0
  22. package/dist/views/Banners/BannerForm/index.d.ts +1 -0
  23. package/dist/views/Banners/BannerList/BannerList.helpers.d.ts +5 -0
  24. package/dist/views/Banners/BannerList/BannerList.vue.d.ts +55 -0
  25. package/dist/views/Banners/BannerList/hooks/index.d.ts +1 -0
  26. package/dist/views/Banners/BannerList/hooks/useAdvancedSearch.d.ts +21 -0
  27. package/dist/views/Banners/BannerList/index.d.ts +1 -0
  28. package/dist/views/Zones/ZoneList/ZoneList.helpers.d.ts +5 -0
  29. package/dist/views/Zones/ZoneList/ZoneList.vue.d.ts +28 -0
  30. package/dist/views/Zones/ZoneList/index.d.ts +1 -0
  31. package/package.json +32 -23
  32. package/src/config/config.json +1 -1
  33. package/src/constants/menu.ts +24 -9
  34. package/src/constants/paths.ts +10 -27
  35. package/src/constants/routes.ts +27 -49
  36. package/src/dev.ts +22 -34
  37. package/src/hooks/index.ts +2 -0
  38. package/src/hooks/useFetchBanner.ts +41 -0
  39. package/src/hooks/useFetchBanners.ts +23 -0
  40. package/src/hooks/useFetchZones.ts +23 -0
  41. package/src/locales/en.ts +43 -0
  42. package/src/locales/ru.ts +45 -0
  43. package/src/main.ts +12 -0
  44. package/src/router/index.ts +38 -0
  45. package/src/services/requests.ts +33 -88
  46. package/src/typings/banners.ts +44 -0
  47. package/src/typings/common.ts +1 -0
  48. package/src/typings/model.ts +119 -16
  49. package/src/typings/shims-vue.d.ts +1 -0
  50. package/src/typings/translate.d.ts +10 -0
  51. package/src/typings/zones.ts +5 -0
  52. package/src/utils/common.ts +13 -0
  53. package/src/views/App.vue +7 -7
  54. package/src/views/Banners/BannerForm/BannerForm.helpers.ts +38 -0
  55. package/src/views/Banners/BannerForm/BannerForm.vue +236 -0
  56. package/src/views/Banners/BannerForm/index.ts +1 -0
  57. package/src/views/Banners/BannerList/BannerList.helpers.ts +93 -0
  58. package/src/views/Banners/BannerList/BannerList.vue +233 -0
  59. package/src/views/Banners/BannerList/hooks/index.ts +1 -0
  60. package/src/views/Banners/BannerList/hooks/useAdvancedSearch.ts +152 -0
  61. package/src/views/Banners/BannerList/index.ts +1 -0
  62. package/src/views/Home.vue +37 -0
  63. package/src/views/Zones/ZoneList/ZoneList.helpers.ts +34 -0
  64. package/src/views/Zones/ZoneList/ZoneList.vue +75 -0
  65. package/src/views/Zones/ZoneList/index.ts +1 -0
  66. package/dist/views/BannerAreaForm.vue.d.ts +0 -22
  67. package/dist/views/BannerAreaList.vue.d.ts +0 -17
  68. package/dist/views/BannerItemForm.vue.d.ts +0 -27
  69. package/dist/views/BannerItemList.vue.d.ts +0 -22
  70. package/src/index.ts +0 -3
  71. package/src/locales/en.js +0 -3
  72. package/src/locales/ru.js +0 -3
  73. package/src/views/BannerAreaForm.vue +0 -173
  74. package/src/views/BannerAreaList.vue +0 -176
  75. package/src/views/BannerItemForm.vue +0 -231
  76. package/src/views/BannerItemList.vue +0 -221
  77. package/typings/index.d.ts +0 -15
package/dist/index.esm.js CHANGED
@@ -1,178 +1,173 @@
1
- import Vue from 'vue';
2
- import { request, getMessageFromError, convertRequestErrorToMap } from '@tager/admin-services';
1
+ import { request, useResource, useResourceDelete, createId, convertRequestErrorToMap, i18n } from '@tager/admin-services';
2
+ import { defineComponent, onMounted, computed, ref, watch } from '@vue/composition-api';
3
+ import { useDataTable, getFilterParamAsStringArray, getFilterParamAsString, getFilterParams, useTranslation, FormFooter } from '@tager/admin-ui';
3
4
  import { compile } from 'path-to-regexp';
4
- import { formatBoolean } from '@tager/admin-ui';
5
5
 
6
- /** Banner area */
7
- function getBannerAreaList() {
8
- return request.get({ path: '/admin/market-boards' });
9
- }
10
- function getBannerAreaById(areaId) {
11
- return request.get({ path: `/admin/market-boards/${areaId}` });
12
- }
13
- function getBannerAreaByAlias(areaAlias) {
14
- return request.get({ path: `/admin/market-boards/${areaAlias}` });
15
- }
16
- function createBannerArea(payload) {
17
- return request.post({ path: '/admin/market-boards', body: payload });
18
- }
19
- function updateBannerArea(areaId, payload) {
20
- return request.put({ path: `/admin/market-boards/${areaId}`, body: payload });
21
- }
22
- function deleteBannerArea(areaId) {
23
- return request.delete({ path: `/admin/market-boards/${areaId}` });
6
+ const EN = {
7
+ home: 'Home',
8
+ zone: 'Banner zone',
9
+ zones: 'Banner zones',
10
+ banners: 'Banners',
11
+ bannerForm: 'Banner Form',
12
+ createBanner: 'Create Banner',
13
+ updateBanner: 'Update Banner',
14
+ link: 'Link',
15
+ image: 'Image',
16
+ openNewTab: 'Open new tab',
17
+ period: 'Period',
18
+ from: 'From',
19
+ to: 'To',
20
+ disabled: 'Disabled',
21
+ comment: 'Comment',
22
+ status: 'Status',
23
+ bannerZoneIsDeleted: 'Banner zone is deleted',
24
+ newTab: 'New Tab',
25
+ yes: 'Yes',
26
+ no: 'No',
27
+ edit: 'Edit',
28
+ remove: 'Remove',
29
+ actions: 'actions',
30
+ date: 'Date',
31
+ success: 'Success',
32
+ error: 'Error',
33
+ statuses: {
34
+ waiting: 'Waiting',
35
+ archived: 'Archived',
36
+ active: 'Active',
37
+ disabled: 'Disabled',
38
+ },
39
+ bannerWasSuccessfullyCreated: 'Banner was successfully created',
40
+ bannerWasSuccessfullyUpdated: 'Banner was successfully updated',
41
+ bannerCreationWasFailed: 'Banner creation was failed',
42
+ bannerUpdateWasFailed: 'Banner update was failed',
43
+ };
44
+
45
+ const RU = {
46
+ home: 'Главная',
47
+ zone: 'Баннерная зона',
48
+ zones: 'Баннерные зоны',
49
+ banners: 'Баннеры',
50
+ bannerForm: 'Форма баннера',
51
+ createBanner: 'Добавить баннер',
52
+ updateBanner: 'Редактировать баннер',
53
+ link: 'Ссылка',
54
+ image: 'Картинка',
55
+ openNewTab: 'Открывать в новой вкладке',
56
+ period: 'Срок действия',
57
+ from: 'От',
58
+ to: 'До',
59
+ disabled: 'Выключен',
60
+ comment: 'Комментарий',
61
+ status: 'Статус',
62
+ bannerZoneIsDeleted: 'Баннерная зона удалена',
63
+ newTab: 'Новая вкладка',
64
+ yes: 'Да',
65
+ no: 'Нет',
66
+ edit: 'Редактировать',
67
+ remove: 'Удалить',
68
+ actions: 'Действия',
69
+ date: 'Дата',
70
+ success: 'Успех',
71
+ error: 'Ошибка',
72
+ statuses: {
73
+ waiting: 'В ожидании',
74
+ archived: 'Архивный',
75
+ active: 'Активный',
76
+ disabled: 'Отключен',
77
+ },
78
+ bannerWasSuccessfullyCreated: 'Баннер успешно создан',
79
+ bannerWasSuccessfullyUpdated: 'Баннер успешно обновлен',
80
+ bannerCreationWasFailed: 'Не удалось создать баннер',
81
+ bannerUpdateWasFailed: 'Не удалось обновить баннер',
82
+ };
83
+
84
+ /** Zones **/
85
+ function getZones(params) {
86
+ return request.get({ path: '/admin/adv/zones', params });
24
87
  }
25
- /** Banners */
26
- function getBannerItemList(areaId) {
27
- return request.get({ path: `/admin/market-boards/${areaId}/items` });
88
+ /** Banners **/
89
+ function getBanners(params) {
90
+ return request.get({ path: '/admin/adv', params });
28
91
  }
29
- function getBannerItemById(bannerItemId) {
30
- return request.get({ path: `/admin/market-boards/items/${bannerItemId}` });
92
+ function getBanner(bannerId) {
93
+ return request.get({ path: `/admin/adv/${bannerId}` });
31
94
  }
32
- function createBannerItem(areaId, payload) {
33
- return request.post({
34
- path: `/admin/market-boards/${areaId}/items`,
35
- body: payload,
36
- });
95
+ function createBanner(payload) {
96
+ return request.post({ path: '/admin/adv', body: payload });
37
97
  }
38
- function updateBannerItem(bannerItemId, payload) {
98
+ function updateBanner(bannerId, payload) {
39
99
  return request.put({
40
- path: `/admin/market-boards/items/${bannerItemId}`,
100
+ path: `/admin/adv/${bannerId}`,
41
101
  body: payload,
42
102
  });
43
103
  }
44
- function deleteBannerItem(bannerItemId) {
45
- return request.delete({ path: `/admin/market-boards/items/${bannerItemId}` });
46
- }
47
- function moveBannerItem(bannerItemId, direction) {
48
- return request.post({
49
- path: `/admin/market-boards/items/${bannerItemId}/${direction}`,
50
- });
104
+ function deleteBanner(bannerId) {
105
+ return request.delete({ path: `/admin/banners/${bannerId}` });
51
106
  }
52
107
 
53
- const BANNER_ROUTE_PATHS = {
54
- AREA_LIST: '/banners',
55
- AREA_FORM: '/banners/:areaId',
56
- ITEM_LIST: '/banners/:areaAlias/items',
57
- ITEM_FORM: '/banners/:areaAlias/items/:itemId',
108
+ const BANNERS_ROUTE_PATHS = {
109
+ ZONE_LIST: '/banners/zones',
110
+ BANNER_LIST: '/banners',
111
+ BANNER_FORM: '/banners/:bannerId',
58
112
  };
59
- function getBannerAreaListUrl() {
60
- return BANNER_ROUTE_PATHS.AREA_LIST;
61
- }
62
- function getBannerAreaFormUrl(params) {
63
- return compile(BANNER_ROUTE_PATHS.AREA_FORM)({
64
- areaId: params.areaId,
65
- });
113
+ function getBannersZoneListUrl() {
114
+ return BANNERS_ROUTE_PATHS.ZONE_LIST;
66
115
  }
67
- function getBannerItemListUrl(params) {
68
- return compile(BANNER_ROUTE_PATHS.ITEM_LIST)({
69
- areaAlias: params.areaAlias,
70
- });
116
+ function getBannersBannerListUrl() {
117
+ return BANNERS_ROUTE_PATHS.BANNER_LIST;
71
118
  }
72
- function getBannerItemFormUrl(params) {
73
- return compile(BANNER_ROUTE_PATHS.ITEM_FORM)({
74
- areaAlias: params.areaAlias,
75
- itemId: params.itemId,
76
- });
119
+ function getBannersBannerFormUrl(params) {
120
+ return compile(BANNERS_ROUTE_PATHS.BANNER_FORM)(params);
77
121
  }
78
122
 
79
- const COLUMN_DEFS = [
80
- {
81
- id: 1,
82
- name: 'ID',
83
- field: 'id',
84
- style: { width: '50px', textAlign: 'center' },
85
- headStyle: { width: '50px', textAlign: 'center' },
86
- },
87
- { id: 2, name: 'Alias', field: 'alias' },
88
- { id: 3, name: 'Label', field: 'label' },
89
- { id: 4, name: 'Scenario', field: 'scenario' },
90
- {
91
- id: 6,
92
- name: 'Banner Items',
93
- field: 'linkToBannerItems',
94
- style: { whiteSpace: 'nowrap', width: '120px', textAlign: 'center' },
95
- headStyle: { whiteSpace: 'nowrap', width: '120px', textAlign: 'center' },
96
- },
97
- {
98
- id: 8,
99
- name: 'Actions',
100
- field: 'actions',
101
- style: { whiteSpace: 'nowrap', width: '110px', textAlign: 'center' },
102
- headStyle: { whiteSpace: 'nowrap', width: '110px', textAlign: 'center' },
103
- },
104
- ];
105
- var script = Vue.extend({
106
- name: 'BannerAreaList',
107
- data() {
108
- return {
109
- columnDefs: COLUMN_DEFS,
110
- rowData: [],
111
- deletingBannerAreaIdList: [],
112
- isRowDataLoading: false,
113
- errorMessage: null,
114
- };
115
- },
116
- mounted() {
117
- this.refreshBannerAreaList();
118
- },
119
- methods: {
120
- getBannerAreaUrl(areaId) {
121
- return getBannerAreaFormUrl({ areaId });
122
- },
123
- refreshBannerAreaList() {
124
- this.isRowDataLoading = true;
125
- return getBannerAreaList()
126
- .then((response) => {
127
- this.rowData = response.data;
128
- this.errorMessage = null;
129
- })
130
- .catch((error) => {
131
- console.error(error);
132
- this.rowData = [];
133
- this.errorMessage = getMessageFromError(error);
134
- })
135
- .finally(() => {
136
- this.isRowDataLoading = false;
137
- });
123
+ function getColumnDefs(t) {
124
+ return [
125
+ {
126
+ id: 0,
127
+ name: 'ID',
128
+ field: 'id',
129
+ style: { width: '50px', textAlign: 'center' },
130
+ headStyle: { width: '50px', textAlign: 'center' },
138
131
  },
139
- handleBannerAreaDelete(bannerArea) {
140
- const shouldDeleteBannerArea = confirm(`Are you sure you want to delete banner area "${bannerArea.label}"`);
141
- if (!shouldDeleteBannerArea)
142
- return;
143
- this.deletingBannerAreaIdList.push(bannerArea.id);
144
- deleteBannerArea(bannerArea.id)
145
- .then((response) => {
146
- if (response.success) {
147
- this.refreshBannerAreaList().then(() => {
148
- this.deletingBannerAreaIdList.filter((id) => id !== bannerArea.id);
149
- });
150
- this.$toast({
151
- variant: 'success',
152
- title: 'Success',
153
- body: 'Banner area was successfully removed',
154
- });
155
- }
156
- else {
157
- this.$toast({
158
- variant: 'danger',
159
- title: 'Error',
160
- body: 'Banner area deletion was failed',
161
- });
162
- }
163
- })
164
- .catch((error) => {
165
- console.error(error);
166
- this.$toast({
167
- variant: 'danger',
168
- title: 'Error',
169
- body: 'Banner area deletion was failed',
170
- });
171
- });
132
+ {
133
+ id: 1,
134
+ name: t('banners:name'),
135
+ field: 'name',
136
+ type: 'name',
172
137
  },
173
- getLinkToBannerItems(areaAlias) {
174
- return getBannerItemListUrl({ areaAlias });
138
+ {
139
+ id: 2,
140
+ name: t('banners:banners'),
141
+ field: 'bannersCount',
142
+ style: { whiteSpace: 'nowrap', width: '130px' },
175
143
  },
144
+ ];
145
+ }
146
+ function getLinkToBannersByZone(zoneId) {
147
+ return `${getBannersBannerListUrl()}?filter[zone]=${zoneId}`;
148
+ }
149
+
150
+ var script = defineComponent({
151
+ name: 'ZoneList',
152
+ setup(props, context) {
153
+ const { fetchEntityList: fetchZones, isLoading: isZonesLoading, rowData, errorMessage, handleChange, } = useDataTable({
154
+ fetchEntityList: getZones,
155
+ initialValue: [],
156
+ context,
157
+ resourceName: 'Banner Zones',
158
+ });
159
+ onMounted(() => {
160
+ fetchZones();
161
+ });
162
+ const columnDefs = computed(() => getColumnDefs(context.root.$t));
163
+ return {
164
+ columnDefs,
165
+ isRowDataLoading: isZonesLoading,
166
+ rowData,
167
+ errorMessage,
168
+ handleChange,
169
+ getLinkToBannersByZone,
170
+ };
176
171
  },
177
172
  });
178
173
 
@@ -251,59 +246,6 @@ function normalizeComponent(template, style, script, scopeId, isFunctionalTempla
251
246
  return script;
252
247
  }
253
248
 
254
- const isOldIE = typeof navigator !== 'undefined' &&
255
- /msie [6-9]\\b/.test(navigator.userAgent.toLowerCase());
256
- function createInjector(context) {
257
- return (id, style) => addStyle(id, style);
258
- }
259
- let HEAD;
260
- const styles = {};
261
- function addStyle(id, css) {
262
- const group = isOldIE ? css.media || 'default' : id;
263
- const style = styles[group] || (styles[group] = { ids: new Set(), styles: [] });
264
- if (!style.ids.has(id)) {
265
- style.ids.add(id);
266
- let code = css.source;
267
- if (css.map) {
268
- // https://developer.chrome.com/devtools/docs/javascript-debugging
269
- // this makes source maps inside style tags work properly in Chrome
270
- code += '\n/*# sourceURL=' + css.map.sources[0] + ' */';
271
- // http://stackoverflow.com/a/26603875
272
- code +=
273
- '\n/*# sourceMappingURL=data:application/json;base64,' +
274
- btoa(unescape(encodeURIComponent(JSON.stringify(css.map)))) +
275
- ' */';
276
- }
277
- if (!style.element) {
278
- style.element = document.createElement('style');
279
- style.element.type = 'text/css';
280
- if (css.media)
281
- style.element.setAttribute('media', css.media);
282
- if (HEAD === undefined) {
283
- HEAD = document.head || document.getElementsByTagName('head')[0];
284
- }
285
- HEAD.appendChild(style.element);
286
- }
287
- if ('styleSheet' in style.element) {
288
- style.styles.push(code);
289
- style.element.styleSheet.cssText = style.styles
290
- .filter(Boolean)
291
- .join('\n');
292
- }
293
- else {
294
- const index = style.ids.size - 1;
295
- const textNode = document.createTextNode(code);
296
- const nodes = style.element.childNodes;
297
- if (nodes[index])
298
- style.element.removeChild(nodes[index]);
299
- if (nodes.length)
300
- style.element.insertBefore(textNode, nodes[index]);
301
- else
302
- style.element.appendChild(textNode);
303
- }
304
- }
305
- }
306
-
307
249
  /* script */
308
250
  const __vue_script__ = script;
309
251
 
@@ -313,82 +255,45 @@ var __vue_render__ = function () {
313
255
  var _h = _vm.$createElement;
314
256
  var _c = _vm._self._c || _h;
315
257
  return _c("page", {
316
- attrs: {
317
- title: "Banner Areas",
318
- "header-buttons": [
319
- { text: "New banner area", href: _vm.getBannerAreaUrl("create") },
320
- ],
321
- },
258
+ attrs: { title: _vm.$t("banners:zones") },
322
259
  scopedSlots: _vm._u([
323
260
  {
324
261
  key: "content",
325
262
  fn: function () {
326
263
  return [
327
- _c("base-table", {
264
+ _c("data-table", {
328
265
  attrs: {
329
266
  "column-defs": _vm.columnDefs,
330
267
  "row-data": _vm.rowData,
331
268
  loading: _vm.isRowDataLoading,
332
269
  "error-message": _vm.errorMessage,
270
+ "data-table": "banners-zones",
271
+ "use-search": false,
272
+ "use-pagination": false,
333
273
  },
274
+ on: { change: _vm.handleChange },
334
275
  scopedSlots: _vm._u([
335
276
  {
336
- key: "cell(link-to-banner-items)",
277
+ key: "cell(banners-count)",
337
278
  fn: function (ref) {
338
279
  var row = ref.row;
339
280
  return [
340
281
  _c(
341
- "base-button",
282
+ "count-button",
342
283
  {
343
284
  attrs: {
344
- href: _vm.getLinkToBannerItems(row.alias),
285
+ href: _vm.getLinkToBannersByZone(row.id),
345
286
  variant: "outline-secondary",
287
+ count: row.bannersCount,
346
288
  },
347
289
  },
348
- [_vm._v("\n Banner Items\n ")]
349
- ),
350
- ]
351
- },
352
- },
353
- {
354
- key: "cell(actions)",
355
- fn: function (ref) {
356
- var row = ref.row;
357
- return [
358
- _c(
359
- "base-button",
360
- {
361
- attrs: {
362
- variant: "icon",
363
- title: "Edit",
364
- disabled: _vm.deletingBannerAreaIdList.includes(
365
- row.id
366
- ),
367
- href: _vm.getBannerAreaUrl(row.id),
368
- },
369
- },
370
- [_c("svg-icon", { attrs: { name: "edit" } })],
371
- 1
372
- ),
373
- _vm._v(" "),
374
- _c(
375
- "base-button",
376
- {
377
- attrs: {
378
- variant: "icon",
379
- title: "Remove",
380
- disabled: _vm.deletingBannerAreaIdList.includes(
381
- row.id
382
- ),
383
- },
384
- on: {
385
- click: function ($event) {
386
- return _vm.handleBannerAreaDelete(row)
387
- },
388
- },
389
- },
390
- [_c("svg-icon", { attrs: { name: "delete" } })],
391
- 1
290
+ [
291
+ _vm._v(
292
+ "\n " +
293
+ _vm._s(_vm.$t("banners:banners")) +
294
+ "\n "
295
+ ),
296
+ ]
392
297
  ),
393
298
  ]
394
299
  },
@@ -406,17 +311,15 @@ var __vue_staticRenderFns__ = [];
406
311
  __vue_render__._withStripped = true;
407
312
 
408
313
  /* style */
409
- const __vue_inject_styles__ = function (inject) {
410
- if (!inject) return
411
- inject("data-v-60c3bc88_0", { source: ".actions-cell button[data-v-60c3bc88]:not(:last-child) {\n margin-right: 0.5rem;\n}\n\n/*# sourceMappingURL=BannerAreaList.vue.map */", map: {"version":3,"sources":["D:\\Work\\tager-admin-banners\\src\\views\\BannerAreaList.vue","BannerAreaList.vue"],"names":[],"mappings":"AA2KA;EACA,oBAAA;AC1KA;;AAEA,6CAA6C","file":"BannerAreaList.vue","sourcesContent":["<template>\n <page\n title=\"Banner Areas\"\n :header-buttons=\"[\n { text: 'New banner area', href: getBannerAreaUrl('create') },\n ]\"\n >\n <template v-slot:content>\n <base-table\n :column-defs=\"columnDefs\"\n :row-data=\"rowData\"\n :loading=\"isRowDataLoading\"\n :error-message=\"errorMessage\"\n >\n <template v-slot:cell(link-to-banner-items)=\"{ row }\">\n <base-button\n :href=\"getLinkToBannerItems(row.alias)\"\n variant=\"outline-secondary\"\n >\n Banner Items\n </base-button>\n </template>\n\n <template v-slot:cell(actions)=\"{ row }\">\n <base-button\n variant=\"icon\"\n title=\"Edit\"\n :disabled=\"deletingBannerAreaIdList.includes(row.id)\"\n :href=\"getBannerAreaUrl(row.id)\"\n >\n <svg-icon name=\"edit\"></svg-icon>\n </base-button>\n <base-button\n variant=\"icon\"\n title=\"Remove\"\n :disabled=\"deletingBannerAreaIdList.includes(row.id)\"\n @click=\"handleBannerAreaDelete(row)\"\n >\n <svg-icon name=\"delete\"></svg-icon>\n </base-button>\n </template>\n </base-table>\n </template>\n </page>\n</template>\n\n<script lang=\"ts\">\nimport Vue from 'vue';\nimport { ColumnDefinition } from '@tager/admin-ui';\nimport { getMessageFromError, Nullable } from '@tager/admin-services';\n\nimport { BannerArea } from '../typings/model';\nimport { deleteBannerArea, getBannerAreaList } from '../services/requests';\nimport { getBannerAreaFormUrl, getBannerItemListUrl } from '../constants/paths';\n\nconst COLUMN_DEFS: Array<ColumnDefinition<BannerArea>> = [\n {\n id: 1,\n name: 'ID',\n field: 'id',\n style: { width: '50px', textAlign: 'center' },\n headStyle: { width: '50px', textAlign: 'center' },\n },\n { id: 2, name: 'Alias', field: 'alias' },\n { id: 3, name: 'Label', field: 'label' },\n { id: 4, name: 'Scenario', field: 'scenario' },\n {\n id: 6,\n name: 'Banner Items',\n field: 'linkToBannerItems',\n style: { whiteSpace: 'nowrap', width: '120px', textAlign: 'center' },\n headStyle: { whiteSpace: 'nowrap', width: '120px', textAlign: 'center' },\n },\n {\n id: 8,\n name: 'Actions',\n field: 'actions',\n style: { whiteSpace: 'nowrap', width: '110px', textAlign: 'center' },\n headStyle: { whiteSpace: 'nowrap', width: '110px', textAlign: 'center' },\n },\n];\n\nexport default Vue.extend({\n name: 'BannerAreaList',\n data(): {\n columnDefs: Array<ColumnDefinition<BannerArea>>;\n rowData: Array<BannerArea>;\n deletingBannerAreaIdList: Array<number>;\n isRowDataLoading: boolean;\n errorMessage: Nullable<string>;\n } {\n return {\n columnDefs: COLUMN_DEFS,\n rowData: [],\n deletingBannerAreaIdList: [],\n isRowDataLoading: false,\n errorMessage: null,\n };\n },\n mounted(): void {\n this.refreshBannerAreaList();\n },\n methods: {\n getBannerAreaUrl(areaId: number | string): string {\n return getBannerAreaFormUrl({ areaId });\n },\n refreshBannerAreaList(): Promise<void> {\n this.isRowDataLoading = true;\n\n return getBannerAreaList()\n .then((response) => {\n this.rowData = response.data;\n this.errorMessage = null;\n })\n .catch((error) => {\n console.error(error);\n this.rowData = [];\n this.errorMessage = getMessageFromError(error);\n })\n .finally(() => {\n this.isRowDataLoading = false;\n });\n },\n handleBannerAreaDelete(bannerArea: BannerArea) {\n const shouldDeleteBannerArea = confirm(\n `Are you sure you want to delete banner area \"${bannerArea.label}\"`\n );\n\n if (!shouldDeleteBannerArea) return;\n\n this.deletingBannerAreaIdList.push(bannerArea.id);\n\n deleteBannerArea(bannerArea.id)\n .then((response) => {\n if (response.success) {\n this.refreshBannerAreaList().then(() => {\n this.deletingBannerAreaIdList.filter(\n (id) => id !== bannerArea.id\n );\n });\n this.$toast({\n variant: 'success',\n title: 'Success',\n body: 'Banner area was successfully removed',\n });\n } else {\n this.$toast({\n variant: 'danger',\n title: 'Error',\n body: 'Banner area deletion was failed',\n });\n }\n })\n .catch((error) => {\n console.error(error);\n this.$toast({\n variant: 'danger',\n title: 'Error',\n body: 'Banner area deletion was failed',\n });\n });\n },\n getLinkToBannerItems(areaAlias: string) {\n return getBannerItemListUrl({ areaAlias });\n },\n },\n});\n</script>\n\n<style scoped lang=\"scss\">\n.actions-cell {\n button:not(:last-child) {\n margin-right: 0.5rem;\n }\n}\n</style>\n",".actions-cell button:not(:last-child) {\n margin-right: 0.5rem;\n}\n\n/*# sourceMappingURL=BannerAreaList.vue.map */"]}, media: undefined });
412
-
413
- };
314
+ const __vue_inject_styles__ = undefined;
414
315
  /* scoped */
415
- const __vue_scope_id__ = "data-v-60c3bc88";
316
+ const __vue_scope_id__ = undefined;
416
317
  /* module identifier */
417
318
  const __vue_module_identifier__ = undefined;
418
319
  /* functional template */
419
320
  const __vue_is_functional_template__ = false;
321
+ /* style inject */
322
+
420
323
  /* style inject SSR */
421
324
 
422
325
  /* style inject shadow dom */
@@ -431,368 +334,2691 @@ __vue_render__._withStripped = true;
431
334
  __vue_is_functional_template__,
432
335
  __vue_module_identifier__,
433
336
  false,
434
- createInjector,
337
+ undefined,
435
338
  undefined,
436
339
  undefined
437
340
  );
438
341
 
439
- const initialValues = {
440
- alias: '',
441
- label: '',
442
- scenario: '',
443
- };
444
- var script$1 = Vue.extend({
445
- name: 'BannerAreaForm',
446
- data() {
447
- return {
448
- values: Object.assign({}, initialValues),
449
- errors: {},
450
- isContentLoading: false,
451
- };
452
- },
453
- computed: {
454
- areaId() {
455
- return this.$route.params.areaId;
456
- },
457
- isCreation() {
458
- return this.areaId === 'create';
459
- },
460
- },
461
- watch: {
462
- areaId() {
463
- this.updateValues();
464
- },
465
- },
466
- mounted() {
467
- this.updateValues();
468
- },
469
- methods: {
470
- convertReviewToInitialValues(bannerArea) {
471
- return {
472
- alias: bannerArea.alias,
473
- label: bannerArea.label,
474
- scenario: bannerArea.scenario,
475
- };
476
- },
477
- updateValues() {
478
- if (this.isCreation) {
479
- this.values = Object.assign({}, initialValues);
480
- }
481
- else {
482
- this.isContentLoading = true;
483
- getBannerAreaById(this.areaId)
484
- .then((response) => {
485
- this.values = this.convertReviewToInitialValues(response.data);
486
- })
487
- .catch(console.error)
488
- .finally(() => {
489
- this.isContentLoading = false;
490
- });
491
- }
492
- },
493
- submitForm() {
494
- const body = {
495
- label: this.values.label,
496
- alias: this.values.alias,
497
- scenario: this.values.scenario,
498
- };
499
- const requestPromise = this.isCreation
500
- ? createBannerArea(body)
501
- : updateBannerArea(this.areaId, body);
502
- requestPromise
503
- .then(() => {
504
- this.errors = {};
505
- this.$router.push(getBannerAreaListUrl());
506
- this.$toast({
507
- variant: 'success',
508
- title: 'Success',
509
- body: `Banner Area was successfully ${this.isCreation ? 'created' : 'updated'}`,
510
- });
511
- })
512
- .catch((error) => {
513
- console.error(error);
514
- this.errors = convertRequestErrorToMap(error);
515
- this.$toast({
516
- variant: 'danger',
517
- title: 'Error',
518
- body: `Blog bannerArea ${this.isCreation ? 'creation' : 'update'} was failed`,
519
- });
520
- });
521
- },
522
- getAreaListUrl: getBannerAreaListUrl,
523
- },
524
- });
342
+ var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
525
343
 
526
- /* script */
527
- const __vue_script__$1 = script$1;
344
+ function createCommonjsModule(fn, basedir, module) {
345
+ return module = {
346
+ path: basedir,
347
+ exports: {},
348
+ require: function (path, base) {
349
+ return commonjsRequire(path, (base === undefined || base === null) ? module.path : base);
350
+ }
351
+ }, fn(module, module.exports), module.exports;
352
+ }
528
353
 
529
- /* template */
530
- var __vue_render__$1 = function () {
531
- var _vm = this;
532
- var _h = _vm.$createElement;
533
- var _c = _vm._self._c || _h;
534
- return _c("page", {
535
- attrs: {
536
- title: _vm.isCreation ? "Create Banner Area" : "Update Banner Area",
537
- "is-content-loading": _vm.isContentLoading,
538
- footer: { onSubmit: _vm.submitForm, backHref: _vm.getAreaListUrl() },
539
- },
540
- scopedSlots: _vm._u([
541
- {
542
- key: "content",
543
- fn: function () {
544
- return [
545
- _c(
546
- "form",
547
- {
548
- attrs: { novalidate: "" },
549
- on: {
550
- submit: function ($event) {
551
- $event.preventDefault();
552
- return _vm.submitForm($event)
553
- },
554
- },
555
- },
556
- [
557
- _c("form-field", {
558
- attrs: {
559
- name: "alias",
560
- label: "Alias",
561
- error: _vm.errors.alias,
562
- },
563
- model: {
564
- value: _vm.values.alias,
565
- callback: function ($$v) {
566
- _vm.$set(_vm.values, "alias", $$v);
567
- },
568
- expression: "values.alias",
569
- },
570
- }),
571
- _vm._v(" "),
572
- _c("form-field", {
573
- attrs: {
574
- name: "label",
575
- label: "Label",
576
- error: _vm.errors.label,
577
- },
578
- model: {
579
- value: _vm.values.label,
580
- callback: function ($$v) {
581
- _vm.$set(_vm.values, "label", $$v);
582
- },
583
- expression: "values.label",
584
- },
585
- }),
586
- _vm._v(" "),
587
- _c("form-field", {
588
- attrs: {
589
- name: "scenario",
590
- label: "Scenario",
591
- error: _vm.errors.scenario,
592
- },
593
- model: {
594
- value: _vm.values.scenario,
595
- callback: function ($$v) {
596
- _vm.$set(_vm.values, "scenario", $$v);
597
- },
598
- expression: "values.scenario",
599
- },
600
- }),
601
- ],
602
- 1
603
- ),
604
- ]
605
- },
606
- proxy: true,
607
- },
608
- ]),
609
- })
610
- };
611
- var __vue_staticRenderFns__$1 = [];
612
- __vue_render__$1._withStripped = true;
354
+ function commonjsRequire () {
355
+ throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs');
356
+ }
613
357
 
614
- /* style */
615
- const __vue_inject_styles__$1 = function (inject) {
616
- if (!inject) return
617
- inject("data-v-78a20f0f_0", { source: ".bottom[data-v-78a20f0f] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n.save-button[data-v-78a20f0f] {\n min-width: 100px;\n}\n.alias-field-inner[data-v-78a20f0f] {\n display: flex;\n align-items: center;\n}\n.alias-field-inner span[data-v-78a20f0f] {\n font-size: 0.9em;\n margin-right: 10px;\n}\n\n/*# sourceMappingURL=BannerAreaForm.vue.map */", map: {"version":3,"sources":["D:\\Work\\tager-admin-banners\\src\\views\\BannerAreaForm.vue","BannerAreaForm.vue"],"names":[],"mappings":"AAyJA;EACA,aAAA;EACA,8BAAA;EACA,mBAAA;ACxJA;AD2JA;EACA,gBAAA;ACxJA;AD2JA;EACA,aAAA;EACA,mBAAA;ACxJA;AD0JA;EACA,gBAAA;EACA,kBAAA;ACxJA;;AAEA,6CAA6C","file":"BannerAreaForm.vue","sourcesContent":["<template>\n <page\n :title=\"isCreation ? 'Create Banner Area' : 'Update Banner Area'\"\n :is-content-loading=\"isContentLoading\"\n :footer=\"{ onSubmit: submitForm, backHref: getAreaListUrl() }\"\n >\n <template v-slot:content>\n <form novalidate @submit.prevent=\"submitForm\">\n <form-field\n v-model=\"values.alias\"\n name=\"alias\"\n label=\"Alias\"\n :error=\"errors.alias\"\n />\n\n <form-field\n v-model=\"values.label\"\n name=\"label\"\n label=\"Label\"\n :error=\"errors.label\"\n />\n\n <form-field\n v-model=\"values.scenario\"\n name=\"scenario\"\n label=\"Scenario\"\n :error=\"errors.scenario\"\n />\n </form>\n </template>\n </page>\n</template>\n\n<script lang=\"ts\">\nimport Vue from 'vue';\nimport { convertRequestErrorToMap } from '@tager/admin-services';\n\nimport {\n BannerAreaCreatePayload,\n createBannerArea,\n getBannerAreaById,\n updateBannerArea,\n} from '../services/requests';\nimport { BannerArea } from '../typings/model';\nimport { getBannerAreaListUrl } from '../constants/paths';\n\ntype FormValues = {\n alias: string;\n label: string;\n scenario: string;\n};\n\nconst initialValues: FormValues = {\n alias: '',\n label: '',\n scenario: '',\n};\n\nexport default Vue.extend({\n name: 'BannerAreaForm',\n data(): {\n values: FormValues;\n errors: Record<string, string>;\n isContentLoading: boolean;\n } {\n return {\n values: { ...initialValues },\n errors: {},\n isContentLoading: false,\n };\n },\n computed: {\n areaId(): string {\n return this.$route.params.areaId;\n },\n isCreation(): boolean {\n return this.areaId === 'create';\n },\n },\n watch: {\n areaId() {\n this.updateValues();\n },\n },\n mounted(): void {\n this.updateValues();\n },\n methods: {\n convertReviewToInitialValues(bannerArea: BannerArea): FormValues {\n return {\n alias: bannerArea.alias,\n label: bannerArea.label,\n scenario: bannerArea.scenario,\n };\n },\n updateValues() {\n if (this.isCreation) {\n this.values = { ...initialValues };\n } else {\n this.isContentLoading = true;\n\n getBannerAreaById(this.areaId)\n .then((response) => {\n this.values = this.convertReviewToInitialValues(response.data);\n })\n .catch(console.error)\n .finally(() => {\n this.isContentLoading = false;\n });\n }\n },\n submitForm() {\n const body: BannerAreaCreatePayload = {\n label: this.values.label,\n alias: this.values.alias,\n scenario: this.values.scenario,\n };\n\n const requestPromise = this.isCreation\n ? createBannerArea(body)\n : updateBannerArea(this.areaId, body);\n\n requestPromise\n .then(() => {\n this.errors = {};\n this.$router.push(getBannerAreaListUrl());\n\n this.$toast({\n variant: 'success',\n title: 'Success',\n body: `Banner Area was successfully ${\n this.isCreation ? 'created' : 'updated'\n }`,\n });\n })\n .catch((error) => {\n console.error(error);\n this.errors = convertRequestErrorToMap(error);\n this.$toast({\n variant: 'danger',\n title: 'Error',\n body: `Blog bannerArea ${\n this.isCreation ? 'creation' : 'update'\n } was failed`,\n });\n });\n },\n getAreaListUrl: getBannerAreaListUrl,\n },\n});\n</script>\n\n<style scoped lang=\"scss\">\n.bottom {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.save-button {\n min-width: 100px;\n}\n\n.alias-field-inner {\n display: flex;\n align-items: center;\n\n span {\n font-size: 0.9em;\n margin-right: 10px;\n }\n}\n</style>\n",".bottom {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.save-button {\n min-width: 100px;\n}\n\n.alias-field-inner {\n display: flex;\n align-items: center;\n}\n.alias-field-inner span {\n font-size: 0.9em;\n margin-right: 10px;\n}\n\n/*# sourceMappingURL=BannerAreaForm.vue.map */"]}, media: undefined });
358
+ var lodash_isequal = createCommonjsModule(function (module, exports) {
359
+ /**
360
+ * Lodash (Custom Build) <https://lodash.com/>
361
+ * Build: `lodash modularize exports="npm" -o ./`
362
+ * Copyright JS Foundation and other contributors <https://js.foundation/>
363
+ * Released under MIT license <https://lodash.com/license>
364
+ * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
365
+ * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
366
+ */
618
367
 
619
- };
620
- /* scoped */
621
- const __vue_scope_id__$1 = "data-v-78a20f0f";
622
- /* module identifier */
623
- const __vue_module_identifier__$1 = undefined;
624
- /* functional template */
625
- const __vue_is_functional_template__$1 = false;
626
- /* style inject SSR */
627
-
628
- /* style inject shadow dom */
629
-
368
+ /** Used as the size to enable large array optimizations. */
369
+ var LARGE_ARRAY_SIZE = 200;
630
370
 
631
-
632
- const __vue_component__$1 = /*#__PURE__*/normalizeComponent(
633
- { render: __vue_render__$1, staticRenderFns: __vue_staticRenderFns__$1 },
634
- __vue_inject_styles__$1,
635
- __vue_script__$1,
636
- __vue_scope_id__$1,
637
- __vue_is_functional_template__$1,
638
- __vue_module_identifier__$1,
639
- false,
640
- createInjector,
641
- undefined,
642
- undefined
643
- );
371
+ /** Used to stand-in for `undefined` hash values. */
372
+ var HASH_UNDEFINED = '__lodash_hash_undefined__';
644
373
 
645
- const COLUMN_DEFS$1 = [
646
- {
647
- id: 2,
648
- name: 'Image',
649
- field: 'image',
650
- type: 'image',
651
- },
652
- {
653
- id: 1,
654
- name: 'Title',
655
- field: 'title',
656
- },
657
- { id: 3, name: 'Text', field: 'text', type: 'html' },
658
- { id: 4, name: 'Button: Label', field: 'buttonLabel' },
659
- { id: 5, name: 'Button: Link', field: 'buttonLink' },
660
- {
661
- id: 6,
662
- name: 'Button: Is new tab?',
663
- field: 'buttonIsNewTab',
664
- format: ({ row }) => formatBoolean(row.buttonIsNewTab),
665
- },
666
- {
667
- id: 7,
668
- name: 'Actions',
669
- field: 'actions',
670
- style: { whiteSpace: 'nowrap', width: '205px' },
671
- headStyle: { whiteSpace: 'nowrap', width: '205px' },
672
- },
673
- ];
674
- var script$2 = Vue.extend({
675
- name: 'BannerItemList',
676
- data() {
677
- return {
678
- bannerArea: null,
679
- columnDefs: COLUMN_DEFS$1,
680
- rowData: [],
681
- deletingBannerItemIdList: [],
682
- isBannerItemMoving: false,
683
- isRowDataLoading: false,
684
- errorMessage: null,
685
- };
686
- },
687
- computed: {
688
- areaAlias() {
689
- return this.$route.params.areaAlias;
374
+ /** Used to compose bitmasks for value comparisons. */
375
+ var COMPARE_PARTIAL_FLAG = 1,
376
+ COMPARE_UNORDERED_FLAG = 2;
377
+
378
+ /** Used as references for various `Number` constants. */
379
+ var MAX_SAFE_INTEGER = 9007199254740991;
380
+
381
+ /** `Object#toString` result references. */
382
+ var argsTag = '[object Arguments]',
383
+ arrayTag = '[object Array]',
384
+ asyncTag = '[object AsyncFunction]',
385
+ boolTag = '[object Boolean]',
386
+ dateTag = '[object Date]',
387
+ errorTag = '[object Error]',
388
+ funcTag = '[object Function]',
389
+ genTag = '[object GeneratorFunction]',
390
+ mapTag = '[object Map]',
391
+ numberTag = '[object Number]',
392
+ nullTag = '[object Null]',
393
+ objectTag = '[object Object]',
394
+ promiseTag = '[object Promise]',
395
+ proxyTag = '[object Proxy]',
396
+ regexpTag = '[object RegExp]',
397
+ setTag = '[object Set]',
398
+ stringTag = '[object String]',
399
+ symbolTag = '[object Symbol]',
400
+ undefinedTag = '[object Undefined]',
401
+ weakMapTag = '[object WeakMap]';
402
+
403
+ var arrayBufferTag = '[object ArrayBuffer]',
404
+ dataViewTag = '[object DataView]',
405
+ float32Tag = '[object Float32Array]',
406
+ float64Tag = '[object Float64Array]',
407
+ int8Tag = '[object Int8Array]',
408
+ int16Tag = '[object Int16Array]',
409
+ int32Tag = '[object Int32Array]',
410
+ uint8Tag = '[object Uint8Array]',
411
+ uint8ClampedTag = '[object Uint8ClampedArray]',
412
+ uint16Tag = '[object Uint16Array]',
413
+ uint32Tag = '[object Uint32Array]';
414
+
415
+ /**
416
+ * Used to match `RegExp`
417
+ * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
418
+ */
419
+ var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
420
+
421
+ /** Used to detect host constructors (Safari). */
422
+ var reIsHostCtor = /^\[object .+?Constructor\]$/;
423
+
424
+ /** Used to detect unsigned integer values. */
425
+ var reIsUint = /^(?:0|[1-9]\d*)$/;
426
+
427
+ /** Used to identify `toStringTag` values of typed arrays. */
428
+ var typedArrayTags = {};
429
+ typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
430
+ typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
431
+ typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
432
+ typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
433
+ typedArrayTags[uint32Tag] = true;
434
+ typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
435
+ typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
436
+ typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
437
+ typedArrayTags[errorTag] = typedArrayTags[funcTag] =
438
+ typedArrayTags[mapTag] = typedArrayTags[numberTag] =
439
+ typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
440
+ typedArrayTags[setTag] = typedArrayTags[stringTag] =
441
+ typedArrayTags[weakMapTag] = false;
442
+
443
+ /** Detect free variable `global` from Node.js. */
444
+ var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
445
+
446
+ /** Detect free variable `self`. */
447
+ var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
448
+
449
+ /** Used as a reference to the global object. */
450
+ var root = freeGlobal || freeSelf || Function('return this')();
451
+
452
+ /** Detect free variable `exports`. */
453
+ var freeExports = exports && !exports.nodeType && exports;
454
+
455
+ /** Detect free variable `module`. */
456
+ var freeModule = freeExports && 'object' == 'object' && module && !module.nodeType && module;
457
+
458
+ /** Detect the popular CommonJS extension `module.exports`. */
459
+ var moduleExports = freeModule && freeModule.exports === freeExports;
460
+
461
+ /** Detect free variable `process` from Node.js. */
462
+ var freeProcess = moduleExports && freeGlobal.process;
463
+
464
+ /** Used to access faster Node.js helpers. */
465
+ var nodeUtil = (function() {
466
+ try {
467
+ return freeProcess && freeProcess.binding && freeProcess.binding('util');
468
+ } catch (e) {}
469
+ }());
470
+
471
+ /* Node.js helper references. */
472
+ var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
473
+
474
+ /**
475
+ * A specialized version of `_.filter` for arrays without support for
476
+ * iteratee shorthands.
477
+ *
478
+ * @private
479
+ * @param {Array} [array] The array to iterate over.
480
+ * @param {Function} predicate The function invoked per iteration.
481
+ * @returns {Array} Returns the new filtered array.
482
+ */
483
+ function arrayFilter(array, predicate) {
484
+ var index = -1,
485
+ length = array == null ? 0 : array.length,
486
+ resIndex = 0,
487
+ result = [];
488
+
489
+ while (++index < length) {
490
+ var value = array[index];
491
+ if (predicate(value, index, array)) {
492
+ result[resIndex++] = value;
493
+ }
494
+ }
495
+ return result;
496
+ }
497
+
498
+ /**
499
+ * Appends the elements of `values` to `array`.
500
+ *
501
+ * @private
502
+ * @param {Array} array The array to modify.
503
+ * @param {Array} values The values to append.
504
+ * @returns {Array} Returns `array`.
505
+ */
506
+ function arrayPush(array, values) {
507
+ var index = -1,
508
+ length = values.length,
509
+ offset = array.length;
510
+
511
+ while (++index < length) {
512
+ array[offset + index] = values[index];
513
+ }
514
+ return array;
515
+ }
516
+
517
+ /**
518
+ * A specialized version of `_.some` for arrays without support for iteratee
519
+ * shorthands.
520
+ *
521
+ * @private
522
+ * @param {Array} [array] The array to iterate over.
523
+ * @param {Function} predicate The function invoked per iteration.
524
+ * @returns {boolean} Returns `true` if any element passes the predicate check,
525
+ * else `false`.
526
+ */
527
+ function arraySome(array, predicate) {
528
+ var index = -1,
529
+ length = array == null ? 0 : array.length;
530
+
531
+ while (++index < length) {
532
+ if (predicate(array[index], index, array)) {
533
+ return true;
534
+ }
535
+ }
536
+ return false;
537
+ }
538
+
539
+ /**
540
+ * The base implementation of `_.times` without support for iteratee shorthands
541
+ * or max array length checks.
542
+ *
543
+ * @private
544
+ * @param {number} n The number of times to invoke `iteratee`.
545
+ * @param {Function} iteratee The function invoked per iteration.
546
+ * @returns {Array} Returns the array of results.
547
+ */
548
+ function baseTimes(n, iteratee) {
549
+ var index = -1,
550
+ result = Array(n);
551
+
552
+ while (++index < n) {
553
+ result[index] = iteratee(index);
554
+ }
555
+ return result;
556
+ }
557
+
558
+ /**
559
+ * The base implementation of `_.unary` without support for storing metadata.
560
+ *
561
+ * @private
562
+ * @param {Function} func The function to cap arguments for.
563
+ * @returns {Function} Returns the new capped function.
564
+ */
565
+ function baseUnary(func) {
566
+ return function(value) {
567
+ return func(value);
568
+ };
569
+ }
570
+
571
+ /**
572
+ * Checks if a `cache` value for `key` exists.
573
+ *
574
+ * @private
575
+ * @param {Object} cache The cache to query.
576
+ * @param {string} key The key of the entry to check.
577
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
578
+ */
579
+ function cacheHas(cache, key) {
580
+ return cache.has(key);
581
+ }
582
+
583
+ /**
584
+ * Gets the value at `key` of `object`.
585
+ *
586
+ * @private
587
+ * @param {Object} [object] The object to query.
588
+ * @param {string} key The key of the property to get.
589
+ * @returns {*} Returns the property value.
590
+ */
591
+ function getValue(object, key) {
592
+ return object == null ? undefined : object[key];
593
+ }
594
+
595
+ /**
596
+ * Converts `map` to its key-value pairs.
597
+ *
598
+ * @private
599
+ * @param {Object} map The map to convert.
600
+ * @returns {Array} Returns the key-value pairs.
601
+ */
602
+ function mapToArray(map) {
603
+ var index = -1,
604
+ result = Array(map.size);
605
+
606
+ map.forEach(function(value, key) {
607
+ result[++index] = [key, value];
608
+ });
609
+ return result;
610
+ }
611
+
612
+ /**
613
+ * Creates a unary function that invokes `func` with its argument transformed.
614
+ *
615
+ * @private
616
+ * @param {Function} func The function to wrap.
617
+ * @param {Function} transform The argument transform.
618
+ * @returns {Function} Returns the new function.
619
+ */
620
+ function overArg(func, transform) {
621
+ return function(arg) {
622
+ return func(transform(arg));
623
+ };
624
+ }
625
+
626
+ /**
627
+ * Converts `set` to an array of its values.
628
+ *
629
+ * @private
630
+ * @param {Object} set The set to convert.
631
+ * @returns {Array} Returns the values.
632
+ */
633
+ function setToArray(set) {
634
+ var index = -1,
635
+ result = Array(set.size);
636
+
637
+ set.forEach(function(value) {
638
+ result[++index] = value;
639
+ });
640
+ return result;
641
+ }
642
+
643
+ /** Used for built-in method references. */
644
+ var arrayProto = Array.prototype,
645
+ funcProto = Function.prototype,
646
+ objectProto = Object.prototype;
647
+
648
+ /** Used to detect overreaching core-js shims. */
649
+ var coreJsData = root['__core-js_shared__'];
650
+
651
+ /** Used to resolve the decompiled source of functions. */
652
+ var funcToString = funcProto.toString;
653
+
654
+ /** Used to check objects for own properties. */
655
+ var hasOwnProperty = objectProto.hasOwnProperty;
656
+
657
+ /** Used to detect methods masquerading as native. */
658
+ var maskSrcKey = (function() {
659
+ var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
660
+ return uid ? ('Symbol(src)_1.' + uid) : '';
661
+ }());
662
+
663
+ /**
664
+ * Used to resolve the
665
+ * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
666
+ * of values.
667
+ */
668
+ var nativeObjectToString = objectProto.toString;
669
+
670
+ /** Used to detect if a method is native. */
671
+ var reIsNative = RegExp('^' +
672
+ funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
673
+ .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
674
+ );
675
+
676
+ /** Built-in value references. */
677
+ var Buffer = moduleExports ? root.Buffer : undefined,
678
+ Symbol = root.Symbol,
679
+ Uint8Array = root.Uint8Array,
680
+ propertyIsEnumerable = objectProto.propertyIsEnumerable,
681
+ splice = arrayProto.splice,
682
+ symToStringTag = Symbol ? Symbol.toStringTag : undefined;
683
+
684
+ /* Built-in method references for those with the same name as other `lodash` methods. */
685
+ var nativeGetSymbols = Object.getOwnPropertySymbols,
686
+ nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,
687
+ nativeKeys = overArg(Object.keys, Object);
688
+
689
+ /* Built-in method references that are verified to be native. */
690
+ var DataView = getNative(root, 'DataView'),
691
+ Map = getNative(root, 'Map'),
692
+ Promise = getNative(root, 'Promise'),
693
+ Set = getNative(root, 'Set'),
694
+ WeakMap = getNative(root, 'WeakMap'),
695
+ nativeCreate = getNative(Object, 'create');
696
+
697
+ /** Used to detect maps, sets, and weakmaps. */
698
+ var dataViewCtorString = toSource(DataView),
699
+ mapCtorString = toSource(Map),
700
+ promiseCtorString = toSource(Promise),
701
+ setCtorString = toSource(Set),
702
+ weakMapCtorString = toSource(WeakMap);
703
+
704
+ /** Used to convert symbols to primitives and strings. */
705
+ var symbolProto = Symbol ? Symbol.prototype : undefined,
706
+ symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;
707
+
708
+ /**
709
+ * Creates a hash object.
710
+ *
711
+ * @private
712
+ * @constructor
713
+ * @param {Array} [entries] The key-value pairs to cache.
714
+ */
715
+ function Hash(entries) {
716
+ var index = -1,
717
+ length = entries == null ? 0 : entries.length;
718
+
719
+ this.clear();
720
+ while (++index < length) {
721
+ var entry = entries[index];
722
+ this.set(entry[0], entry[1]);
723
+ }
724
+ }
725
+
726
+ /**
727
+ * Removes all key-value entries from the hash.
728
+ *
729
+ * @private
730
+ * @name clear
731
+ * @memberOf Hash
732
+ */
733
+ function hashClear() {
734
+ this.__data__ = nativeCreate ? nativeCreate(null) : {};
735
+ this.size = 0;
736
+ }
737
+
738
+ /**
739
+ * Removes `key` and its value from the hash.
740
+ *
741
+ * @private
742
+ * @name delete
743
+ * @memberOf Hash
744
+ * @param {Object} hash The hash to modify.
745
+ * @param {string} key The key of the value to remove.
746
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
747
+ */
748
+ function hashDelete(key) {
749
+ var result = this.has(key) && delete this.__data__[key];
750
+ this.size -= result ? 1 : 0;
751
+ return result;
752
+ }
753
+
754
+ /**
755
+ * Gets the hash value for `key`.
756
+ *
757
+ * @private
758
+ * @name get
759
+ * @memberOf Hash
760
+ * @param {string} key The key of the value to get.
761
+ * @returns {*} Returns the entry value.
762
+ */
763
+ function hashGet(key) {
764
+ var data = this.__data__;
765
+ if (nativeCreate) {
766
+ var result = data[key];
767
+ return result === HASH_UNDEFINED ? undefined : result;
768
+ }
769
+ return hasOwnProperty.call(data, key) ? data[key] : undefined;
770
+ }
771
+
772
+ /**
773
+ * Checks if a hash value for `key` exists.
774
+ *
775
+ * @private
776
+ * @name has
777
+ * @memberOf Hash
778
+ * @param {string} key The key of the entry to check.
779
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
780
+ */
781
+ function hashHas(key) {
782
+ var data = this.__data__;
783
+ return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);
784
+ }
785
+
786
+ /**
787
+ * Sets the hash `key` to `value`.
788
+ *
789
+ * @private
790
+ * @name set
791
+ * @memberOf Hash
792
+ * @param {string} key The key of the value to set.
793
+ * @param {*} value The value to set.
794
+ * @returns {Object} Returns the hash instance.
795
+ */
796
+ function hashSet(key, value) {
797
+ var data = this.__data__;
798
+ this.size += this.has(key) ? 0 : 1;
799
+ data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
800
+ return this;
801
+ }
802
+
803
+ // Add methods to `Hash`.
804
+ Hash.prototype.clear = hashClear;
805
+ Hash.prototype['delete'] = hashDelete;
806
+ Hash.prototype.get = hashGet;
807
+ Hash.prototype.has = hashHas;
808
+ Hash.prototype.set = hashSet;
809
+
810
+ /**
811
+ * Creates an list cache object.
812
+ *
813
+ * @private
814
+ * @constructor
815
+ * @param {Array} [entries] The key-value pairs to cache.
816
+ */
817
+ function ListCache(entries) {
818
+ var index = -1,
819
+ length = entries == null ? 0 : entries.length;
820
+
821
+ this.clear();
822
+ while (++index < length) {
823
+ var entry = entries[index];
824
+ this.set(entry[0], entry[1]);
825
+ }
826
+ }
827
+
828
+ /**
829
+ * Removes all key-value entries from the list cache.
830
+ *
831
+ * @private
832
+ * @name clear
833
+ * @memberOf ListCache
834
+ */
835
+ function listCacheClear() {
836
+ this.__data__ = [];
837
+ this.size = 0;
838
+ }
839
+
840
+ /**
841
+ * Removes `key` and its value from the list cache.
842
+ *
843
+ * @private
844
+ * @name delete
845
+ * @memberOf ListCache
846
+ * @param {string} key The key of the value to remove.
847
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
848
+ */
849
+ function listCacheDelete(key) {
850
+ var data = this.__data__,
851
+ index = assocIndexOf(data, key);
852
+
853
+ if (index < 0) {
854
+ return false;
855
+ }
856
+ var lastIndex = data.length - 1;
857
+ if (index == lastIndex) {
858
+ data.pop();
859
+ } else {
860
+ splice.call(data, index, 1);
861
+ }
862
+ --this.size;
863
+ return true;
864
+ }
865
+
866
+ /**
867
+ * Gets the list cache value for `key`.
868
+ *
869
+ * @private
870
+ * @name get
871
+ * @memberOf ListCache
872
+ * @param {string} key The key of the value to get.
873
+ * @returns {*} Returns the entry value.
874
+ */
875
+ function listCacheGet(key) {
876
+ var data = this.__data__,
877
+ index = assocIndexOf(data, key);
878
+
879
+ return index < 0 ? undefined : data[index][1];
880
+ }
881
+
882
+ /**
883
+ * Checks if a list cache value for `key` exists.
884
+ *
885
+ * @private
886
+ * @name has
887
+ * @memberOf ListCache
888
+ * @param {string} key The key of the entry to check.
889
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
890
+ */
891
+ function listCacheHas(key) {
892
+ return assocIndexOf(this.__data__, key) > -1;
893
+ }
894
+
895
+ /**
896
+ * Sets the list cache `key` to `value`.
897
+ *
898
+ * @private
899
+ * @name set
900
+ * @memberOf ListCache
901
+ * @param {string} key The key of the value to set.
902
+ * @param {*} value The value to set.
903
+ * @returns {Object} Returns the list cache instance.
904
+ */
905
+ function listCacheSet(key, value) {
906
+ var data = this.__data__,
907
+ index = assocIndexOf(data, key);
908
+
909
+ if (index < 0) {
910
+ ++this.size;
911
+ data.push([key, value]);
912
+ } else {
913
+ data[index][1] = value;
914
+ }
915
+ return this;
916
+ }
917
+
918
+ // Add methods to `ListCache`.
919
+ ListCache.prototype.clear = listCacheClear;
920
+ ListCache.prototype['delete'] = listCacheDelete;
921
+ ListCache.prototype.get = listCacheGet;
922
+ ListCache.prototype.has = listCacheHas;
923
+ ListCache.prototype.set = listCacheSet;
924
+
925
+ /**
926
+ * Creates a map cache object to store key-value pairs.
927
+ *
928
+ * @private
929
+ * @constructor
930
+ * @param {Array} [entries] The key-value pairs to cache.
931
+ */
932
+ function MapCache(entries) {
933
+ var index = -1,
934
+ length = entries == null ? 0 : entries.length;
935
+
936
+ this.clear();
937
+ while (++index < length) {
938
+ var entry = entries[index];
939
+ this.set(entry[0], entry[1]);
940
+ }
941
+ }
942
+
943
+ /**
944
+ * Removes all key-value entries from the map.
945
+ *
946
+ * @private
947
+ * @name clear
948
+ * @memberOf MapCache
949
+ */
950
+ function mapCacheClear() {
951
+ this.size = 0;
952
+ this.__data__ = {
953
+ 'hash': new Hash,
954
+ 'map': new (Map || ListCache),
955
+ 'string': new Hash
956
+ };
957
+ }
958
+
959
+ /**
960
+ * Removes `key` and its value from the map.
961
+ *
962
+ * @private
963
+ * @name delete
964
+ * @memberOf MapCache
965
+ * @param {string} key The key of the value to remove.
966
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
967
+ */
968
+ function mapCacheDelete(key) {
969
+ var result = getMapData(this, key)['delete'](key);
970
+ this.size -= result ? 1 : 0;
971
+ return result;
972
+ }
973
+
974
+ /**
975
+ * Gets the map value for `key`.
976
+ *
977
+ * @private
978
+ * @name get
979
+ * @memberOf MapCache
980
+ * @param {string} key The key of the value to get.
981
+ * @returns {*} Returns the entry value.
982
+ */
983
+ function mapCacheGet(key) {
984
+ return getMapData(this, key).get(key);
985
+ }
986
+
987
+ /**
988
+ * Checks if a map value for `key` exists.
989
+ *
990
+ * @private
991
+ * @name has
992
+ * @memberOf MapCache
993
+ * @param {string} key The key of the entry to check.
994
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
995
+ */
996
+ function mapCacheHas(key) {
997
+ return getMapData(this, key).has(key);
998
+ }
999
+
1000
+ /**
1001
+ * Sets the map `key` to `value`.
1002
+ *
1003
+ * @private
1004
+ * @name set
1005
+ * @memberOf MapCache
1006
+ * @param {string} key The key of the value to set.
1007
+ * @param {*} value The value to set.
1008
+ * @returns {Object} Returns the map cache instance.
1009
+ */
1010
+ function mapCacheSet(key, value) {
1011
+ var data = getMapData(this, key),
1012
+ size = data.size;
1013
+
1014
+ data.set(key, value);
1015
+ this.size += data.size == size ? 0 : 1;
1016
+ return this;
1017
+ }
1018
+
1019
+ // Add methods to `MapCache`.
1020
+ MapCache.prototype.clear = mapCacheClear;
1021
+ MapCache.prototype['delete'] = mapCacheDelete;
1022
+ MapCache.prototype.get = mapCacheGet;
1023
+ MapCache.prototype.has = mapCacheHas;
1024
+ MapCache.prototype.set = mapCacheSet;
1025
+
1026
+ /**
1027
+ *
1028
+ * Creates an array cache object to store unique values.
1029
+ *
1030
+ * @private
1031
+ * @constructor
1032
+ * @param {Array} [values] The values to cache.
1033
+ */
1034
+ function SetCache(values) {
1035
+ var index = -1,
1036
+ length = values == null ? 0 : values.length;
1037
+
1038
+ this.__data__ = new MapCache;
1039
+ while (++index < length) {
1040
+ this.add(values[index]);
1041
+ }
1042
+ }
1043
+
1044
+ /**
1045
+ * Adds `value` to the array cache.
1046
+ *
1047
+ * @private
1048
+ * @name add
1049
+ * @memberOf SetCache
1050
+ * @alias push
1051
+ * @param {*} value The value to cache.
1052
+ * @returns {Object} Returns the cache instance.
1053
+ */
1054
+ function setCacheAdd(value) {
1055
+ this.__data__.set(value, HASH_UNDEFINED);
1056
+ return this;
1057
+ }
1058
+
1059
+ /**
1060
+ * Checks if `value` is in the array cache.
1061
+ *
1062
+ * @private
1063
+ * @name has
1064
+ * @memberOf SetCache
1065
+ * @param {*} value The value to search for.
1066
+ * @returns {number} Returns `true` if `value` is found, else `false`.
1067
+ */
1068
+ function setCacheHas(value) {
1069
+ return this.__data__.has(value);
1070
+ }
1071
+
1072
+ // Add methods to `SetCache`.
1073
+ SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
1074
+ SetCache.prototype.has = setCacheHas;
1075
+
1076
+ /**
1077
+ * Creates a stack cache object to store key-value pairs.
1078
+ *
1079
+ * @private
1080
+ * @constructor
1081
+ * @param {Array} [entries] The key-value pairs to cache.
1082
+ */
1083
+ function Stack(entries) {
1084
+ var data = this.__data__ = new ListCache(entries);
1085
+ this.size = data.size;
1086
+ }
1087
+
1088
+ /**
1089
+ * Removes all key-value entries from the stack.
1090
+ *
1091
+ * @private
1092
+ * @name clear
1093
+ * @memberOf Stack
1094
+ */
1095
+ function stackClear() {
1096
+ this.__data__ = new ListCache;
1097
+ this.size = 0;
1098
+ }
1099
+
1100
+ /**
1101
+ * Removes `key` and its value from the stack.
1102
+ *
1103
+ * @private
1104
+ * @name delete
1105
+ * @memberOf Stack
1106
+ * @param {string} key The key of the value to remove.
1107
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
1108
+ */
1109
+ function stackDelete(key) {
1110
+ var data = this.__data__,
1111
+ result = data['delete'](key);
1112
+
1113
+ this.size = data.size;
1114
+ return result;
1115
+ }
1116
+
1117
+ /**
1118
+ * Gets the stack value for `key`.
1119
+ *
1120
+ * @private
1121
+ * @name get
1122
+ * @memberOf Stack
1123
+ * @param {string} key The key of the value to get.
1124
+ * @returns {*} Returns the entry value.
1125
+ */
1126
+ function stackGet(key) {
1127
+ return this.__data__.get(key);
1128
+ }
1129
+
1130
+ /**
1131
+ * Checks if a stack value for `key` exists.
1132
+ *
1133
+ * @private
1134
+ * @name has
1135
+ * @memberOf Stack
1136
+ * @param {string} key The key of the entry to check.
1137
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
1138
+ */
1139
+ function stackHas(key) {
1140
+ return this.__data__.has(key);
1141
+ }
1142
+
1143
+ /**
1144
+ * Sets the stack `key` to `value`.
1145
+ *
1146
+ * @private
1147
+ * @name set
1148
+ * @memberOf Stack
1149
+ * @param {string} key The key of the value to set.
1150
+ * @param {*} value The value to set.
1151
+ * @returns {Object} Returns the stack cache instance.
1152
+ */
1153
+ function stackSet(key, value) {
1154
+ var data = this.__data__;
1155
+ if (data instanceof ListCache) {
1156
+ var pairs = data.__data__;
1157
+ if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
1158
+ pairs.push([key, value]);
1159
+ this.size = ++data.size;
1160
+ return this;
1161
+ }
1162
+ data = this.__data__ = new MapCache(pairs);
1163
+ }
1164
+ data.set(key, value);
1165
+ this.size = data.size;
1166
+ return this;
1167
+ }
1168
+
1169
+ // Add methods to `Stack`.
1170
+ Stack.prototype.clear = stackClear;
1171
+ Stack.prototype['delete'] = stackDelete;
1172
+ Stack.prototype.get = stackGet;
1173
+ Stack.prototype.has = stackHas;
1174
+ Stack.prototype.set = stackSet;
1175
+
1176
+ /**
1177
+ * Creates an array of the enumerable property names of the array-like `value`.
1178
+ *
1179
+ * @private
1180
+ * @param {*} value The value to query.
1181
+ * @param {boolean} inherited Specify returning inherited property names.
1182
+ * @returns {Array} Returns the array of property names.
1183
+ */
1184
+ function arrayLikeKeys(value, inherited) {
1185
+ var isArr = isArray(value),
1186
+ isArg = !isArr && isArguments(value),
1187
+ isBuff = !isArr && !isArg && isBuffer(value),
1188
+ isType = !isArr && !isArg && !isBuff && isTypedArray(value),
1189
+ skipIndexes = isArr || isArg || isBuff || isType,
1190
+ result = skipIndexes ? baseTimes(value.length, String) : [],
1191
+ length = result.length;
1192
+
1193
+ for (var key in value) {
1194
+ if ((inherited || hasOwnProperty.call(value, key)) &&
1195
+ !(skipIndexes && (
1196
+ // Safari 9 has enumerable `arguments.length` in strict mode.
1197
+ key == 'length' ||
1198
+ // Node.js 0.10 has enumerable non-index properties on buffers.
1199
+ (isBuff && (key == 'offset' || key == 'parent')) ||
1200
+ // PhantomJS 2 has enumerable non-index properties on typed arrays.
1201
+ (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
1202
+ // Skip index properties.
1203
+ isIndex(key, length)
1204
+ ))) {
1205
+ result.push(key);
1206
+ }
1207
+ }
1208
+ return result;
1209
+ }
1210
+
1211
+ /**
1212
+ * Gets the index at which the `key` is found in `array` of key-value pairs.
1213
+ *
1214
+ * @private
1215
+ * @param {Array} array The array to inspect.
1216
+ * @param {*} key The key to search for.
1217
+ * @returns {number} Returns the index of the matched value, else `-1`.
1218
+ */
1219
+ function assocIndexOf(array, key) {
1220
+ var length = array.length;
1221
+ while (length--) {
1222
+ if (eq(array[length][0], key)) {
1223
+ return length;
1224
+ }
1225
+ }
1226
+ return -1;
1227
+ }
1228
+
1229
+ /**
1230
+ * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
1231
+ * `keysFunc` and `symbolsFunc` to get the enumerable property names and
1232
+ * symbols of `object`.
1233
+ *
1234
+ * @private
1235
+ * @param {Object} object The object to query.
1236
+ * @param {Function} keysFunc The function to get the keys of `object`.
1237
+ * @param {Function} symbolsFunc The function to get the symbols of `object`.
1238
+ * @returns {Array} Returns the array of property names and symbols.
1239
+ */
1240
+ function baseGetAllKeys(object, keysFunc, symbolsFunc) {
1241
+ var result = keysFunc(object);
1242
+ return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
1243
+ }
1244
+
1245
+ /**
1246
+ * The base implementation of `getTag` without fallbacks for buggy environments.
1247
+ *
1248
+ * @private
1249
+ * @param {*} value The value to query.
1250
+ * @returns {string} Returns the `toStringTag`.
1251
+ */
1252
+ function baseGetTag(value) {
1253
+ if (value == null) {
1254
+ return value === undefined ? undefinedTag : nullTag;
1255
+ }
1256
+ return (symToStringTag && symToStringTag in Object(value))
1257
+ ? getRawTag(value)
1258
+ : objectToString(value);
1259
+ }
1260
+
1261
+ /**
1262
+ * The base implementation of `_.isArguments`.
1263
+ *
1264
+ * @private
1265
+ * @param {*} value The value to check.
1266
+ * @returns {boolean} Returns `true` if `value` is an `arguments` object,
1267
+ */
1268
+ function baseIsArguments(value) {
1269
+ return isObjectLike(value) && baseGetTag(value) == argsTag;
1270
+ }
1271
+
1272
+ /**
1273
+ * The base implementation of `_.isEqual` which supports partial comparisons
1274
+ * and tracks traversed objects.
1275
+ *
1276
+ * @private
1277
+ * @param {*} value The value to compare.
1278
+ * @param {*} other The other value to compare.
1279
+ * @param {boolean} bitmask The bitmask flags.
1280
+ * 1 - Unordered comparison
1281
+ * 2 - Partial comparison
1282
+ * @param {Function} [customizer] The function to customize comparisons.
1283
+ * @param {Object} [stack] Tracks traversed `value` and `other` objects.
1284
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
1285
+ */
1286
+ function baseIsEqual(value, other, bitmask, customizer, stack) {
1287
+ if (value === other) {
1288
+ return true;
1289
+ }
1290
+ if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {
1291
+ return value !== value && other !== other;
1292
+ }
1293
+ return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
1294
+ }
1295
+
1296
+ /**
1297
+ * A specialized version of `baseIsEqual` for arrays and objects which performs
1298
+ * deep comparisons and tracks traversed objects enabling objects with circular
1299
+ * references to be compared.
1300
+ *
1301
+ * @private
1302
+ * @param {Object} object The object to compare.
1303
+ * @param {Object} other The other object to compare.
1304
+ * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
1305
+ * @param {Function} customizer The function to customize comparisons.
1306
+ * @param {Function} equalFunc The function to determine equivalents of values.
1307
+ * @param {Object} [stack] Tracks traversed `object` and `other` objects.
1308
+ * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
1309
+ */
1310
+ function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
1311
+ var objIsArr = isArray(object),
1312
+ othIsArr = isArray(other),
1313
+ objTag = objIsArr ? arrayTag : getTag(object),
1314
+ othTag = othIsArr ? arrayTag : getTag(other);
1315
+
1316
+ objTag = objTag == argsTag ? objectTag : objTag;
1317
+ othTag = othTag == argsTag ? objectTag : othTag;
1318
+
1319
+ var objIsObj = objTag == objectTag,
1320
+ othIsObj = othTag == objectTag,
1321
+ isSameTag = objTag == othTag;
1322
+
1323
+ if (isSameTag && isBuffer(object)) {
1324
+ if (!isBuffer(other)) {
1325
+ return false;
1326
+ }
1327
+ objIsArr = true;
1328
+ objIsObj = false;
1329
+ }
1330
+ if (isSameTag && !objIsObj) {
1331
+ stack || (stack = new Stack);
1332
+ return (objIsArr || isTypedArray(object))
1333
+ ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)
1334
+ : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
1335
+ }
1336
+ if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
1337
+ var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
1338
+ othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
1339
+
1340
+ if (objIsWrapped || othIsWrapped) {
1341
+ var objUnwrapped = objIsWrapped ? object.value() : object,
1342
+ othUnwrapped = othIsWrapped ? other.value() : other;
1343
+
1344
+ stack || (stack = new Stack);
1345
+ return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
1346
+ }
1347
+ }
1348
+ if (!isSameTag) {
1349
+ return false;
1350
+ }
1351
+ stack || (stack = new Stack);
1352
+ return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
1353
+ }
1354
+
1355
+ /**
1356
+ * The base implementation of `_.isNative` without bad shim checks.
1357
+ *
1358
+ * @private
1359
+ * @param {*} value The value to check.
1360
+ * @returns {boolean} Returns `true` if `value` is a native function,
1361
+ * else `false`.
1362
+ */
1363
+ function baseIsNative(value) {
1364
+ if (!isObject(value) || isMasked(value)) {
1365
+ return false;
1366
+ }
1367
+ var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
1368
+ return pattern.test(toSource(value));
1369
+ }
1370
+
1371
+ /**
1372
+ * The base implementation of `_.isTypedArray` without Node.js optimizations.
1373
+ *
1374
+ * @private
1375
+ * @param {*} value The value to check.
1376
+ * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
1377
+ */
1378
+ function baseIsTypedArray(value) {
1379
+ return isObjectLike(value) &&
1380
+ isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
1381
+ }
1382
+
1383
+ /**
1384
+ * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
1385
+ *
1386
+ * @private
1387
+ * @param {Object} object The object to query.
1388
+ * @returns {Array} Returns the array of property names.
1389
+ */
1390
+ function baseKeys(object) {
1391
+ if (!isPrototype(object)) {
1392
+ return nativeKeys(object);
1393
+ }
1394
+ var result = [];
1395
+ for (var key in Object(object)) {
1396
+ if (hasOwnProperty.call(object, key) && key != 'constructor') {
1397
+ result.push(key);
1398
+ }
1399
+ }
1400
+ return result;
1401
+ }
1402
+
1403
+ /**
1404
+ * A specialized version of `baseIsEqualDeep` for arrays with support for
1405
+ * partial deep comparisons.
1406
+ *
1407
+ * @private
1408
+ * @param {Array} array The array to compare.
1409
+ * @param {Array} other The other array to compare.
1410
+ * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
1411
+ * @param {Function} customizer The function to customize comparisons.
1412
+ * @param {Function} equalFunc The function to determine equivalents of values.
1413
+ * @param {Object} stack Tracks traversed `array` and `other` objects.
1414
+ * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
1415
+ */
1416
+ function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
1417
+ var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
1418
+ arrLength = array.length,
1419
+ othLength = other.length;
1420
+
1421
+ if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
1422
+ return false;
1423
+ }
1424
+ // Assume cyclic values are equal.
1425
+ var stacked = stack.get(array);
1426
+ if (stacked && stack.get(other)) {
1427
+ return stacked == other;
1428
+ }
1429
+ var index = -1,
1430
+ result = true,
1431
+ seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;
1432
+
1433
+ stack.set(array, other);
1434
+ stack.set(other, array);
1435
+
1436
+ // Ignore non-index properties.
1437
+ while (++index < arrLength) {
1438
+ var arrValue = array[index],
1439
+ othValue = other[index];
1440
+
1441
+ if (customizer) {
1442
+ var compared = isPartial
1443
+ ? customizer(othValue, arrValue, index, other, array, stack)
1444
+ : customizer(arrValue, othValue, index, array, other, stack);
1445
+ }
1446
+ if (compared !== undefined) {
1447
+ if (compared) {
1448
+ continue;
1449
+ }
1450
+ result = false;
1451
+ break;
1452
+ }
1453
+ // Recursively compare arrays (susceptible to call stack limits).
1454
+ if (seen) {
1455
+ if (!arraySome(other, function(othValue, othIndex) {
1456
+ if (!cacheHas(seen, othIndex) &&
1457
+ (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
1458
+ return seen.push(othIndex);
1459
+ }
1460
+ })) {
1461
+ result = false;
1462
+ break;
1463
+ }
1464
+ } else if (!(
1465
+ arrValue === othValue ||
1466
+ equalFunc(arrValue, othValue, bitmask, customizer, stack)
1467
+ )) {
1468
+ result = false;
1469
+ break;
1470
+ }
1471
+ }
1472
+ stack['delete'](array);
1473
+ stack['delete'](other);
1474
+ return result;
1475
+ }
1476
+
1477
+ /**
1478
+ * A specialized version of `baseIsEqualDeep` for comparing objects of
1479
+ * the same `toStringTag`.
1480
+ *
1481
+ * **Note:** This function only supports comparing values with tags of
1482
+ * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
1483
+ *
1484
+ * @private
1485
+ * @param {Object} object The object to compare.
1486
+ * @param {Object} other The other object to compare.
1487
+ * @param {string} tag The `toStringTag` of the objects to compare.
1488
+ * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
1489
+ * @param {Function} customizer The function to customize comparisons.
1490
+ * @param {Function} equalFunc The function to determine equivalents of values.
1491
+ * @param {Object} stack Tracks traversed `object` and `other` objects.
1492
+ * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
1493
+ */
1494
+ function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
1495
+ switch (tag) {
1496
+ case dataViewTag:
1497
+ if ((object.byteLength != other.byteLength) ||
1498
+ (object.byteOffset != other.byteOffset)) {
1499
+ return false;
1500
+ }
1501
+ object = object.buffer;
1502
+ other = other.buffer;
1503
+
1504
+ case arrayBufferTag:
1505
+ if ((object.byteLength != other.byteLength) ||
1506
+ !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
1507
+ return false;
1508
+ }
1509
+ return true;
1510
+
1511
+ case boolTag:
1512
+ case dateTag:
1513
+ case numberTag:
1514
+ // Coerce booleans to `1` or `0` and dates to milliseconds.
1515
+ // Invalid dates are coerced to `NaN`.
1516
+ return eq(+object, +other);
1517
+
1518
+ case errorTag:
1519
+ return object.name == other.name && object.message == other.message;
1520
+
1521
+ case regexpTag:
1522
+ case stringTag:
1523
+ // Coerce regexes to strings and treat strings, primitives and objects,
1524
+ // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
1525
+ // for more details.
1526
+ return object == (other + '');
1527
+
1528
+ case mapTag:
1529
+ var convert = mapToArray;
1530
+
1531
+ case setTag:
1532
+ var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
1533
+ convert || (convert = setToArray);
1534
+
1535
+ if (object.size != other.size && !isPartial) {
1536
+ return false;
1537
+ }
1538
+ // Assume cyclic values are equal.
1539
+ var stacked = stack.get(object);
1540
+ if (stacked) {
1541
+ return stacked == other;
1542
+ }
1543
+ bitmask |= COMPARE_UNORDERED_FLAG;
1544
+
1545
+ // Recursively compare objects (susceptible to call stack limits).
1546
+ stack.set(object, other);
1547
+ var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
1548
+ stack['delete'](object);
1549
+ return result;
1550
+
1551
+ case symbolTag:
1552
+ if (symbolValueOf) {
1553
+ return symbolValueOf.call(object) == symbolValueOf.call(other);
1554
+ }
1555
+ }
1556
+ return false;
1557
+ }
1558
+
1559
+ /**
1560
+ * A specialized version of `baseIsEqualDeep` for objects with support for
1561
+ * partial deep comparisons.
1562
+ *
1563
+ * @private
1564
+ * @param {Object} object The object to compare.
1565
+ * @param {Object} other The other object to compare.
1566
+ * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
1567
+ * @param {Function} customizer The function to customize comparisons.
1568
+ * @param {Function} equalFunc The function to determine equivalents of values.
1569
+ * @param {Object} stack Tracks traversed `object` and `other` objects.
1570
+ * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
1571
+ */
1572
+ function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
1573
+ var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
1574
+ objProps = getAllKeys(object),
1575
+ objLength = objProps.length,
1576
+ othProps = getAllKeys(other),
1577
+ othLength = othProps.length;
1578
+
1579
+ if (objLength != othLength && !isPartial) {
1580
+ return false;
1581
+ }
1582
+ var index = objLength;
1583
+ while (index--) {
1584
+ var key = objProps[index];
1585
+ if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
1586
+ return false;
1587
+ }
1588
+ }
1589
+ // Assume cyclic values are equal.
1590
+ var stacked = stack.get(object);
1591
+ if (stacked && stack.get(other)) {
1592
+ return stacked == other;
1593
+ }
1594
+ var result = true;
1595
+ stack.set(object, other);
1596
+ stack.set(other, object);
1597
+
1598
+ var skipCtor = isPartial;
1599
+ while (++index < objLength) {
1600
+ key = objProps[index];
1601
+ var objValue = object[key],
1602
+ othValue = other[key];
1603
+
1604
+ if (customizer) {
1605
+ var compared = isPartial
1606
+ ? customizer(othValue, objValue, key, other, object, stack)
1607
+ : customizer(objValue, othValue, key, object, other, stack);
1608
+ }
1609
+ // Recursively compare objects (susceptible to call stack limits).
1610
+ if (!(compared === undefined
1611
+ ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))
1612
+ : compared
1613
+ )) {
1614
+ result = false;
1615
+ break;
1616
+ }
1617
+ skipCtor || (skipCtor = key == 'constructor');
1618
+ }
1619
+ if (result && !skipCtor) {
1620
+ var objCtor = object.constructor,
1621
+ othCtor = other.constructor;
1622
+
1623
+ // Non `Object` object instances with different constructors are not equal.
1624
+ if (objCtor != othCtor &&
1625
+ ('constructor' in object && 'constructor' in other) &&
1626
+ !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
1627
+ typeof othCtor == 'function' && othCtor instanceof othCtor)) {
1628
+ result = false;
1629
+ }
1630
+ }
1631
+ stack['delete'](object);
1632
+ stack['delete'](other);
1633
+ return result;
1634
+ }
1635
+
1636
+ /**
1637
+ * Creates an array of own enumerable property names and symbols of `object`.
1638
+ *
1639
+ * @private
1640
+ * @param {Object} object The object to query.
1641
+ * @returns {Array} Returns the array of property names and symbols.
1642
+ */
1643
+ function getAllKeys(object) {
1644
+ return baseGetAllKeys(object, keys, getSymbols);
1645
+ }
1646
+
1647
+ /**
1648
+ * Gets the data for `map`.
1649
+ *
1650
+ * @private
1651
+ * @param {Object} map The map to query.
1652
+ * @param {string} key The reference key.
1653
+ * @returns {*} Returns the map data.
1654
+ */
1655
+ function getMapData(map, key) {
1656
+ var data = map.__data__;
1657
+ return isKeyable(key)
1658
+ ? data[typeof key == 'string' ? 'string' : 'hash']
1659
+ : data.map;
1660
+ }
1661
+
1662
+ /**
1663
+ * Gets the native function at `key` of `object`.
1664
+ *
1665
+ * @private
1666
+ * @param {Object} object The object to query.
1667
+ * @param {string} key The key of the method to get.
1668
+ * @returns {*} Returns the function if it's native, else `undefined`.
1669
+ */
1670
+ function getNative(object, key) {
1671
+ var value = getValue(object, key);
1672
+ return baseIsNative(value) ? value : undefined;
1673
+ }
1674
+
1675
+ /**
1676
+ * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
1677
+ *
1678
+ * @private
1679
+ * @param {*} value The value to query.
1680
+ * @returns {string} Returns the raw `toStringTag`.
1681
+ */
1682
+ function getRawTag(value) {
1683
+ var isOwn = hasOwnProperty.call(value, symToStringTag),
1684
+ tag = value[symToStringTag];
1685
+
1686
+ try {
1687
+ value[symToStringTag] = undefined;
1688
+ var unmasked = true;
1689
+ } catch (e) {}
1690
+
1691
+ var result = nativeObjectToString.call(value);
1692
+ if (unmasked) {
1693
+ if (isOwn) {
1694
+ value[symToStringTag] = tag;
1695
+ } else {
1696
+ delete value[symToStringTag];
1697
+ }
1698
+ }
1699
+ return result;
1700
+ }
1701
+
1702
+ /**
1703
+ * Creates an array of the own enumerable symbols of `object`.
1704
+ *
1705
+ * @private
1706
+ * @param {Object} object The object to query.
1707
+ * @returns {Array} Returns the array of symbols.
1708
+ */
1709
+ var getSymbols = !nativeGetSymbols ? stubArray : function(object) {
1710
+ if (object == null) {
1711
+ return [];
1712
+ }
1713
+ object = Object(object);
1714
+ return arrayFilter(nativeGetSymbols(object), function(symbol) {
1715
+ return propertyIsEnumerable.call(object, symbol);
1716
+ });
1717
+ };
1718
+
1719
+ /**
1720
+ * Gets the `toStringTag` of `value`.
1721
+ *
1722
+ * @private
1723
+ * @param {*} value The value to query.
1724
+ * @returns {string} Returns the `toStringTag`.
1725
+ */
1726
+ var getTag = baseGetTag;
1727
+
1728
+ // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
1729
+ if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
1730
+ (Map && getTag(new Map) != mapTag) ||
1731
+ (Promise && getTag(Promise.resolve()) != promiseTag) ||
1732
+ (Set && getTag(new Set) != setTag) ||
1733
+ (WeakMap && getTag(new WeakMap) != weakMapTag)) {
1734
+ getTag = function(value) {
1735
+ var result = baseGetTag(value),
1736
+ Ctor = result == objectTag ? value.constructor : undefined,
1737
+ ctorString = Ctor ? toSource(Ctor) : '';
1738
+
1739
+ if (ctorString) {
1740
+ switch (ctorString) {
1741
+ case dataViewCtorString: return dataViewTag;
1742
+ case mapCtorString: return mapTag;
1743
+ case promiseCtorString: return promiseTag;
1744
+ case setCtorString: return setTag;
1745
+ case weakMapCtorString: return weakMapTag;
1746
+ }
1747
+ }
1748
+ return result;
1749
+ };
1750
+ }
1751
+
1752
+ /**
1753
+ * Checks if `value` is a valid array-like index.
1754
+ *
1755
+ * @private
1756
+ * @param {*} value The value to check.
1757
+ * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
1758
+ * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
1759
+ */
1760
+ function isIndex(value, length) {
1761
+ length = length == null ? MAX_SAFE_INTEGER : length;
1762
+ return !!length &&
1763
+ (typeof value == 'number' || reIsUint.test(value)) &&
1764
+ (value > -1 && value % 1 == 0 && value < length);
1765
+ }
1766
+
1767
+ /**
1768
+ * Checks if `value` is suitable for use as unique object key.
1769
+ *
1770
+ * @private
1771
+ * @param {*} value The value to check.
1772
+ * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
1773
+ */
1774
+ function isKeyable(value) {
1775
+ var type = typeof value;
1776
+ return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
1777
+ ? (value !== '__proto__')
1778
+ : (value === null);
1779
+ }
1780
+
1781
+ /**
1782
+ * Checks if `func` has its source masked.
1783
+ *
1784
+ * @private
1785
+ * @param {Function} func The function to check.
1786
+ * @returns {boolean} Returns `true` if `func` is masked, else `false`.
1787
+ */
1788
+ function isMasked(func) {
1789
+ return !!maskSrcKey && (maskSrcKey in func);
1790
+ }
1791
+
1792
+ /**
1793
+ * Checks if `value` is likely a prototype object.
1794
+ *
1795
+ * @private
1796
+ * @param {*} value The value to check.
1797
+ * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
1798
+ */
1799
+ function isPrototype(value) {
1800
+ var Ctor = value && value.constructor,
1801
+ proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
1802
+
1803
+ return value === proto;
1804
+ }
1805
+
1806
+ /**
1807
+ * Converts `value` to a string using `Object.prototype.toString`.
1808
+ *
1809
+ * @private
1810
+ * @param {*} value The value to convert.
1811
+ * @returns {string} Returns the converted string.
1812
+ */
1813
+ function objectToString(value) {
1814
+ return nativeObjectToString.call(value);
1815
+ }
1816
+
1817
+ /**
1818
+ * Converts `func` to its source code.
1819
+ *
1820
+ * @private
1821
+ * @param {Function} func The function to convert.
1822
+ * @returns {string} Returns the source code.
1823
+ */
1824
+ function toSource(func) {
1825
+ if (func != null) {
1826
+ try {
1827
+ return funcToString.call(func);
1828
+ } catch (e) {}
1829
+ try {
1830
+ return (func + '');
1831
+ } catch (e) {}
1832
+ }
1833
+ return '';
1834
+ }
1835
+
1836
+ /**
1837
+ * Performs a
1838
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
1839
+ * comparison between two values to determine if they are equivalent.
1840
+ *
1841
+ * @static
1842
+ * @memberOf _
1843
+ * @since 4.0.0
1844
+ * @category Lang
1845
+ * @param {*} value The value to compare.
1846
+ * @param {*} other The other value to compare.
1847
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
1848
+ * @example
1849
+ *
1850
+ * var object = { 'a': 1 };
1851
+ * var other = { 'a': 1 };
1852
+ *
1853
+ * _.eq(object, object);
1854
+ * // => true
1855
+ *
1856
+ * _.eq(object, other);
1857
+ * // => false
1858
+ *
1859
+ * _.eq('a', 'a');
1860
+ * // => true
1861
+ *
1862
+ * _.eq('a', Object('a'));
1863
+ * // => false
1864
+ *
1865
+ * _.eq(NaN, NaN);
1866
+ * // => true
1867
+ */
1868
+ function eq(value, other) {
1869
+ return value === other || (value !== value && other !== other);
1870
+ }
1871
+
1872
+ /**
1873
+ * Checks if `value` is likely an `arguments` object.
1874
+ *
1875
+ * @static
1876
+ * @memberOf _
1877
+ * @since 0.1.0
1878
+ * @category Lang
1879
+ * @param {*} value The value to check.
1880
+ * @returns {boolean} Returns `true` if `value` is an `arguments` object,
1881
+ * else `false`.
1882
+ * @example
1883
+ *
1884
+ * _.isArguments(function() { return arguments; }());
1885
+ * // => true
1886
+ *
1887
+ * _.isArguments([1, 2, 3]);
1888
+ * // => false
1889
+ */
1890
+ var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
1891
+ return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&
1892
+ !propertyIsEnumerable.call(value, 'callee');
1893
+ };
1894
+
1895
+ /**
1896
+ * Checks if `value` is classified as an `Array` object.
1897
+ *
1898
+ * @static
1899
+ * @memberOf _
1900
+ * @since 0.1.0
1901
+ * @category Lang
1902
+ * @param {*} value The value to check.
1903
+ * @returns {boolean} Returns `true` if `value` is an array, else `false`.
1904
+ * @example
1905
+ *
1906
+ * _.isArray([1, 2, 3]);
1907
+ * // => true
1908
+ *
1909
+ * _.isArray(document.body.children);
1910
+ * // => false
1911
+ *
1912
+ * _.isArray('abc');
1913
+ * // => false
1914
+ *
1915
+ * _.isArray(_.noop);
1916
+ * // => false
1917
+ */
1918
+ var isArray = Array.isArray;
1919
+
1920
+ /**
1921
+ * Checks if `value` is array-like. A value is considered array-like if it's
1922
+ * not a function and has a `value.length` that's an integer greater than or
1923
+ * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
1924
+ *
1925
+ * @static
1926
+ * @memberOf _
1927
+ * @since 4.0.0
1928
+ * @category Lang
1929
+ * @param {*} value The value to check.
1930
+ * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
1931
+ * @example
1932
+ *
1933
+ * _.isArrayLike([1, 2, 3]);
1934
+ * // => true
1935
+ *
1936
+ * _.isArrayLike(document.body.children);
1937
+ * // => true
1938
+ *
1939
+ * _.isArrayLike('abc');
1940
+ * // => true
1941
+ *
1942
+ * _.isArrayLike(_.noop);
1943
+ * // => false
1944
+ */
1945
+ function isArrayLike(value) {
1946
+ return value != null && isLength(value.length) && !isFunction(value);
1947
+ }
1948
+
1949
+ /**
1950
+ * Checks if `value` is a buffer.
1951
+ *
1952
+ * @static
1953
+ * @memberOf _
1954
+ * @since 4.3.0
1955
+ * @category Lang
1956
+ * @param {*} value The value to check.
1957
+ * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
1958
+ * @example
1959
+ *
1960
+ * _.isBuffer(new Buffer(2));
1961
+ * // => true
1962
+ *
1963
+ * _.isBuffer(new Uint8Array(2));
1964
+ * // => false
1965
+ */
1966
+ var isBuffer = nativeIsBuffer || stubFalse;
1967
+
1968
+ /**
1969
+ * Performs a deep comparison between two values to determine if they are
1970
+ * equivalent.
1971
+ *
1972
+ * **Note:** This method supports comparing arrays, array buffers, booleans,
1973
+ * date objects, error objects, maps, numbers, `Object` objects, regexes,
1974
+ * sets, strings, symbols, and typed arrays. `Object` objects are compared
1975
+ * by their own, not inherited, enumerable properties. Functions and DOM
1976
+ * nodes are compared by strict equality, i.e. `===`.
1977
+ *
1978
+ * @static
1979
+ * @memberOf _
1980
+ * @since 0.1.0
1981
+ * @category Lang
1982
+ * @param {*} value The value to compare.
1983
+ * @param {*} other The other value to compare.
1984
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
1985
+ * @example
1986
+ *
1987
+ * var object = { 'a': 1 };
1988
+ * var other = { 'a': 1 };
1989
+ *
1990
+ * _.isEqual(object, other);
1991
+ * // => true
1992
+ *
1993
+ * object === other;
1994
+ * // => false
1995
+ */
1996
+ function isEqual(value, other) {
1997
+ return baseIsEqual(value, other);
1998
+ }
1999
+
2000
+ /**
2001
+ * Checks if `value` is classified as a `Function` object.
2002
+ *
2003
+ * @static
2004
+ * @memberOf _
2005
+ * @since 0.1.0
2006
+ * @category Lang
2007
+ * @param {*} value The value to check.
2008
+ * @returns {boolean} Returns `true` if `value` is a function, else `false`.
2009
+ * @example
2010
+ *
2011
+ * _.isFunction(_);
2012
+ * // => true
2013
+ *
2014
+ * _.isFunction(/abc/);
2015
+ * // => false
2016
+ */
2017
+ function isFunction(value) {
2018
+ if (!isObject(value)) {
2019
+ return false;
2020
+ }
2021
+ // The use of `Object#toString` avoids issues with the `typeof` operator
2022
+ // in Safari 9 which returns 'object' for typed arrays and other constructors.
2023
+ var tag = baseGetTag(value);
2024
+ return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
2025
+ }
2026
+
2027
+ /**
2028
+ * Checks if `value` is a valid array-like length.
2029
+ *
2030
+ * **Note:** This method is loosely based on
2031
+ * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
2032
+ *
2033
+ * @static
2034
+ * @memberOf _
2035
+ * @since 4.0.0
2036
+ * @category Lang
2037
+ * @param {*} value The value to check.
2038
+ * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
2039
+ * @example
2040
+ *
2041
+ * _.isLength(3);
2042
+ * // => true
2043
+ *
2044
+ * _.isLength(Number.MIN_VALUE);
2045
+ * // => false
2046
+ *
2047
+ * _.isLength(Infinity);
2048
+ * // => false
2049
+ *
2050
+ * _.isLength('3');
2051
+ * // => false
2052
+ */
2053
+ function isLength(value) {
2054
+ return typeof value == 'number' &&
2055
+ value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
2056
+ }
2057
+
2058
+ /**
2059
+ * Checks if `value` is the
2060
+ * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
2061
+ * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
2062
+ *
2063
+ * @static
2064
+ * @memberOf _
2065
+ * @since 0.1.0
2066
+ * @category Lang
2067
+ * @param {*} value The value to check.
2068
+ * @returns {boolean} Returns `true` if `value` is an object, else `false`.
2069
+ * @example
2070
+ *
2071
+ * _.isObject({});
2072
+ * // => true
2073
+ *
2074
+ * _.isObject([1, 2, 3]);
2075
+ * // => true
2076
+ *
2077
+ * _.isObject(_.noop);
2078
+ * // => true
2079
+ *
2080
+ * _.isObject(null);
2081
+ * // => false
2082
+ */
2083
+ function isObject(value) {
2084
+ var type = typeof value;
2085
+ return value != null && (type == 'object' || type == 'function');
2086
+ }
2087
+
2088
+ /**
2089
+ * Checks if `value` is object-like. A value is object-like if it's not `null`
2090
+ * and has a `typeof` result of "object".
2091
+ *
2092
+ * @static
2093
+ * @memberOf _
2094
+ * @since 4.0.0
2095
+ * @category Lang
2096
+ * @param {*} value The value to check.
2097
+ * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
2098
+ * @example
2099
+ *
2100
+ * _.isObjectLike({});
2101
+ * // => true
2102
+ *
2103
+ * _.isObjectLike([1, 2, 3]);
2104
+ * // => true
2105
+ *
2106
+ * _.isObjectLike(_.noop);
2107
+ * // => false
2108
+ *
2109
+ * _.isObjectLike(null);
2110
+ * // => false
2111
+ */
2112
+ function isObjectLike(value) {
2113
+ return value != null && typeof value == 'object';
2114
+ }
2115
+
2116
+ /**
2117
+ * Checks if `value` is classified as a typed array.
2118
+ *
2119
+ * @static
2120
+ * @memberOf _
2121
+ * @since 3.0.0
2122
+ * @category Lang
2123
+ * @param {*} value The value to check.
2124
+ * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
2125
+ * @example
2126
+ *
2127
+ * _.isTypedArray(new Uint8Array);
2128
+ * // => true
2129
+ *
2130
+ * _.isTypedArray([]);
2131
+ * // => false
2132
+ */
2133
+ var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
2134
+
2135
+ /**
2136
+ * Creates an array of the own enumerable property names of `object`.
2137
+ *
2138
+ * **Note:** Non-object values are coerced to objects. See the
2139
+ * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
2140
+ * for more details.
2141
+ *
2142
+ * @static
2143
+ * @since 0.1.0
2144
+ * @memberOf _
2145
+ * @category Object
2146
+ * @param {Object} object The object to query.
2147
+ * @returns {Array} Returns the array of property names.
2148
+ * @example
2149
+ *
2150
+ * function Foo() {
2151
+ * this.a = 1;
2152
+ * this.b = 2;
2153
+ * }
2154
+ *
2155
+ * Foo.prototype.c = 3;
2156
+ *
2157
+ * _.keys(new Foo);
2158
+ * // => ['a', 'b'] (iteration order is not guaranteed)
2159
+ *
2160
+ * _.keys('hi');
2161
+ * // => ['0', '1']
2162
+ */
2163
+ function keys(object) {
2164
+ return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
2165
+ }
2166
+
2167
+ /**
2168
+ * This method returns a new empty array.
2169
+ *
2170
+ * @static
2171
+ * @memberOf _
2172
+ * @since 4.13.0
2173
+ * @category Util
2174
+ * @returns {Array} Returns the new empty array.
2175
+ * @example
2176
+ *
2177
+ * var arrays = _.times(2, _.stubArray);
2178
+ *
2179
+ * console.log(arrays);
2180
+ * // => [[], []]
2181
+ *
2182
+ * console.log(arrays[0] === arrays[1]);
2183
+ * // => false
2184
+ */
2185
+ function stubArray() {
2186
+ return [];
2187
+ }
2188
+
2189
+ /**
2190
+ * This method returns `false`.
2191
+ *
2192
+ * @static
2193
+ * @memberOf _
2194
+ * @since 4.13.0
2195
+ * @category Util
2196
+ * @returns {boolean} Returns `false`.
2197
+ * @example
2198
+ *
2199
+ * _.times(2, _.stubFalse);
2200
+ * // => [false, false]
2201
+ */
2202
+ function stubFalse() {
2203
+ return false;
2204
+ }
2205
+
2206
+ module.exports = isEqual;
2207
+ });
2208
+
2209
+ /**
2210
+ * lodash (Custom Build) <https://lodash.com/>
2211
+ * Build: `lodash modularize exports="npm" -o ./`
2212
+ * Copyright jQuery Foundation and other contributors <https://jquery.org/>
2213
+ * Released under MIT license <https://lodash.com/license>
2214
+ * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
2215
+ * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
2216
+ */
2217
+
2218
+ /** Used as references for various `Number` constants. */
2219
+ var INFINITY = 1 / 0,
2220
+ MAX_SAFE_INTEGER = 9007199254740991;
2221
+
2222
+ /** `Object#toString` result references. */
2223
+ var argsTag = '[object Arguments]',
2224
+ funcTag = '[object Function]',
2225
+ genTag = '[object GeneratorFunction]',
2226
+ symbolTag = '[object Symbol]';
2227
+
2228
+ /** Detect free variable `global` from Node.js. */
2229
+ var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
2230
+
2231
+ /** Detect free variable `self`. */
2232
+ var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
2233
+
2234
+ /** Used as a reference to the global object. */
2235
+ var root = freeGlobal || freeSelf || Function('return this')();
2236
+
2237
+ /**
2238
+ * A faster alternative to `Function#apply`, this function invokes `func`
2239
+ * with the `this` binding of `thisArg` and the arguments of `args`.
2240
+ *
2241
+ * @private
2242
+ * @param {Function} func The function to invoke.
2243
+ * @param {*} thisArg The `this` binding of `func`.
2244
+ * @param {Array} args The arguments to invoke `func` with.
2245
+ * @returns {*} Returns the result of `func`.
2246
+ */
2247
+ function apply(func, thisArg, args) {
2248
+ switch (args.length) {
2249
+ case 0: return func.call(thisArg);
2250
+ case 1: return func.call(thisArg, args[0]);
2251
+ case 2: return func.call(thisArg, args[0], args[1]);
2252
+ case 3: return func.call(thisArg, args[0], args[1], args[2]);
2253
+ }
2254
+ return func.apply(thisArg, args);
2255
+ }
2256
+
2257
+ /**
2258
+ * A specialized version of `_.map` for arrays without support for iteratee
2259
+ * shorthands.
2260
+ *
2261
+ * @private
2262
+ * @param {Array} [array] The array to iterate over.
2263
+ * @param {Function} iteratee The function invoked per iteration.
2264
+ * @returns {Array} Returns the new mapped array.
2265
+ */
2266
+ function arrayMap(array, iteratee) {
2267
+ var index = -1,
2268
+ length = array ? array.length : 0,
2269
+ result = Array(length);
2270
+
2271
+ while (++index < length) {
2272
+ result[index] = iteratee(array[index], index, array);
2273
+ }
2274
+ return result;
2275
+ }
2276
+
2277
+ /**
2278
+ * Appends the elements of `values` to `array`.
2279
+ *
2280
+ * @private
2281
+ * @param {Array} array The array to modify.
2282
+ * @param {Array} values The values to append.
2283
+ * @returns {Array} Returns `array`.
2284
+ */
2285
+ function arrayPush(array, values) {
2286
+ var index = -1,
2287
+ length = values.length,
2288
+ offset = array.length;
2289
+
2290
+ while (++index < length) {
2291
+ array[offset + index] = values[index];
2292
+ }
2293
+ return array;
2294
+ }
2295
+
2296
+ /** Used for built-in method references. */
2297
+ var objectProto = Object.prototype;
2298
+
2299
+ /** Used to check objects for own properties. */
2300
+ var hasOwnProperty = objectProto.hasOwnProperty;
2301
+
2302
+ /**
2303
+ * Used to resolve the
2304
+ * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
2305
+ * of values.
2306
+ */
2307
+ var objectToString = objectProto.toString;
2308
+
2309
+ /** Built-in value references. */
2310
+ var Symbol = root.Symbol,
2311
+ propertyIsEnumerable = objectProto.propertyIsEnumerable,
2312
+ spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined;
2313
+
2314
+ /* Built-in method references for those with the same name as other `lodash` methods. */
2315
+ var nativeMax = Math.max;
2316
+
2317
+ /**
2318
+ * The base implementation of `_.flatten` with support for restricting flattening.
2319
+ *
2320
+ * @private
2321
+ * @param {Array} array The array to flatten.
2322
+ * @param {number} depth The maximum recursion depth.
2323
+ * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
2324
+ * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
2325
+ * @param {Array} [result=[]] The initial result value.
2326
+ * @returns {Array} Returns the new flattened array.
2327
+ */
2328
+ function baseFlatten(array, depth, predicate, isStrict, result) {
2329
+ var index = -1,
2330
+ length = array.length;
2331
+
2332
+ predicate || (predicate = isFlattenable);
2333
+ result || (result = []);
2334
+
2335
+ while (++index < length) {
2336
+ var value = array[index];
2337
+ if (depth > 0 && predicate(value)) {
2338
+ if (depth > 1) {
2339
+ // Recursively flatten arrays (susceptible to call stack limits).
2340
+ baseFlatten(value, depth - 1, predicate, isStrict, result);
2341
+ } else {
2342
+ arrayPush(result, value);
2343
+ }
2344
+ } else if (!isStrict) {
2345
+ result[result.length] = value;
2346
+ }
2347
+ }
2348
+ return result;
2349
+ }
2350
+
2351
+ /**
2352
+ * The base implementation of `_.pick` without support for individual
2353
+ * property identifiers.
2354
+ *
2355
+ * @private
2356
+ * @param {Object} object The source object.
2357
+ * @param {string[]} props The property identifiers to pick.
2358
+ * @returns {Object} Returns the new object.
2359
+ */
2360
+ function basePick(object, props) {
2361
+ object = Object(object);
2362
+ return basePickBy(object, props, function(value, key) {
2363
+ return key in object;
2364
+ });
2365
+ }
2366
+
2367
+ /**
2368
+ * The base implementation of `_.pickBy` without support for iteratee shorthands.
2369
+ *
2370
+ * @private
2371
+ * @param {Object} object The source object.
2372
+ * @param {string[]} props The property identifiers to pick from.
2373
+ * @param {Function} predicate The function invoked per property.
2374
+ * @returns {Object} Returns the new object.
2375
+ */
2376
+ function basePickBy(object, props, predicate) {
2377
+ var index = -1,
2378
+ length = props.length,
2379
+ result = {};
2380
+
2381
+ while (++index < length) {
2382
+ var key = props[index],
2383
+ value = object[key];
2384
+
2385
+ if (predicate(value, key)) {
2386
+ result[key] = value;
2387
+ }
2388
+ }
2389
+ return result;
2390
+ }
2391
+
2392
+ /**
2393
+ * The base implementation of `_.rest` which doesn't validate or coerce arguments.
2394
+ *
2395
+ * @private
2396
+ * @param {Function} func The function to apply a rest parameter to.
2397
+ * @param {number} [start=func.length-1] The start position of the rest parameter.
2398
+ * @returns {Function} Returns the new function.
2399
+ */
2400
+ function baseRest(func, start) {
2401
+ start = nativeMax(start === undefined ? (func.length - 1) : start, 0);
2402
+ return function() {
2403
+ var args = arguments,
2404
+ index = -1,
2405
+ length = nativeMax(args.length - start, 0),
2406
+ array = Array(length);
2407
+
2408
+ while (++index < length) {
2409
+ array[index] = args[start + index];
2410
+ }
2411
+ index = -1;
2412
+ var otherArgs = Array(start + 1);
2413
+ while (++index < start) {
2414
+ otherArgs[index] = args[index];
2415
+ }
2416
+ otherArgs[start] = array;
2417
+ return apply(func, this, otherArgs);
2418
+ };
2419
+ }
2420
+
2421
+ /**
2422
+ * Checks if `value` is a flattenable `arguments` object or array.
2423
+ *
2424
+ * @private
2425
+ * @param {*} value The value to check.
2426
+ * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
2427
+ */
2428
+ function isFlattenable(value) {
2429
+ return isArray(value) || isArguments(value) ||
2430
+ !!(spreadableSymbol && value && value[spreadableSymbol]);
2431
+ }
2432
+
2433
+ /**
2434
+ * Converts `value` to a string key if it's not a string or symbol.
2435
+ *
2436
+ * @private
2437
+ * @param {*} value The value to inspect.
2438
+ * @returns {string|symbol} Returns the key.
2439
+ */
2440
+ function toKey(value) {
2441
+ if (typeof value == 'string' || isSymbol(value)) {
2442
+ return value;
2443
+ }
2444
+ var result = (value + '');
2445
+ return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
2446
+ }
2447
+
2448
+ /**
2449
+ * Checks if `value` is likely an `arguments` object.
2450
+ *
2451
+ * @static
2452
+ * @memberOf _
2453
+ * @since 0.1.0
2454
+ * @category Lang
2455
+ * @param {*} value The value to check.
2456
+ * @returns {boolean} Returns `true` if `value` is an `arguments` object,
2457
+ * else `false`.
2458
+ * @example
2459
+ *
2460
+ * _.isArguments(function() { return arguments; }());
2461
+ * // => true
2462
+ *
2463
+ * _.isArguments([1, 2, 3]);
2464
+ * // => false
2465
+ */
2466
+ function isArguments(value) {
2467
+ // Safari 8.1 makes `arguments.callee` enumerable in strict mode.
2468
+ return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&
2469
+ (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);
2470
+ }
2471
+
2472
+ /**
2473
+ * Checks if `value` is classified as an `Array` object.
2474
+ *
2475
+ * @static
2476
+ * @memberOf _
2477
+ * @since 0.1.0
2478
+ * @category Lang
2479
+ * @param {*} value The value to check.
2480
+ * @returns {boolean} Returns `true` if `value` is an array, else `false`.
2481
+ * @example
2482
+ *
2483
+ * _.isArray([1, 2, 3]);
2484
+ * // => true
2485
+ *
2486
+ * _.isArray(document.body.children);
2487
+ * // => false
2488
+ *
2489
+ * _.isArray('abc');
2490
+ * // => false
2491
+ *
2492
+ * _.isArray(_.noop);
2493
+ * // => false
2494
+ */
2495
+ var isArray = Array.isArray;
2496
+
2497
+ /**
2498
+ * Checks if `value` is array-like. A value is considered array-like if it's
2499
+ * not a function and has a `value.length` that's an integer greater than or
2500
+ * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
2501
+ *
2502
+ * @static
2503
+ * @memberOf _
2504
+ * @since 4.0.0
2505
+ * @category Lang
2506
+ * @param {*} value The value to check.
2507
+ * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
2508
+ * @example
2509
+ *
2510
+ * _.isArrayLike([1, 2, 3]);
2511
+ * // => true
2512
+ *
2513
+ * _.isArrayLike(document.body.children);
2514
+ * // => true
2515
+ *
2516
+ * _.isArrayLike('abc');
2517
+ * // => true
2518
+ *
2519
+ * _.isArrayLike(_.noop);
2520
+ * // => false
2521
+ */
2522
+ function isArrayLike(value) {
2523
+ return value != null && isLength(value.length) && !isFunction(value);
2524
+ }
2525
+
2526
+ /**
2527
+ * This method is like `_.isArrayLike` except that it also checks if `value`
2528
+ * is an object.
2529
+ *
2530
+ * @static
2531
+ * @memberOf _
2532
+ * @since 4.0.0
2533
+ * @category Lang
2534
+ * @param {*} value The value to check.
2535
+ * @returns {boolean} Returns `true` if `value` is an array-like object,
2536
+ * else `false`.
2537
+ * @example
2538
+ *
2539
+ * _.isArrayLikeObject([1, 2, 3]);
2540
+ * // => true
2541
+ *
2542
+ * _.isArrayLikeObject(document.body.children);
2543
+ * // => true
2544
+ *
2545
+ * _.isArrayLikeObject('abc');
2546
+ * // => false
2547
+ *
2548
+ * _.isArrayLikeObject(_.noop);
2549
+ * // => false
2550
+ */
2551
+ function isArrayLikeObject(value) {
2552
+ return isObjectLike(value) && isArrayLike(value);
2553
+ }
2554
+
2555
+ /**
2556
+ * Checks if `value` is classified as a `Function` object.
2557
+ *
2558
+ * @static
2559
+ * @memberOf _
2560
+ * @since 0.1.0
2561
+ * @category Lang
2562
+ * @param {*} value The value to check.
2563
+ * @returns {boolean} Returns `true` if `value` is a function, else `false`.
2564
+ * @example
2565
+ *
2566
+ * _.isFunction(_);
2567
+ * // => true
2568
+ *
2569
+ * _.isFunction(/abc/);
2570
+ * // => false
2571
+ */
2572
+ function isFunction(value) {
2573
+ // The use of `Object#toString` avoids issues with the `typeof` operator
2574
+ // in Safari 8-9 which returns 'object' for typed array and other constructors.
2575
+ var tag = isObject(value) ? objectToString.call(value) : '';
2576
+ return tag == funcTag || tag == genTag;
2577
+ }
2578
+
2579
+ /**
2580
+ * Checks if `value` is a valid array-like length.
2581
+ *
2582
+ * **Note:** This method is loosely based on
2583
+ * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
2584
+ *
2585
+ * @static
2586
+ * @memberOf _
2587
+ * @since 4.0.0
2588
+ * @category Lang
2589
+ * @param {*} value The value to check.
2590
+ * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
2591
+ * @example
2592
+ *
2593
+ * _.isLength(3);
2594
+ * // => true
2595
+ *
2596
+ * _.isLength(Number.MIN_VALUE);
2597
+ * // => false
2598
+ *
2599
+ * _.isLength(Infinity);
2600
+ * // => false
2601
+ *
2602
+ * _.isLength('3');
2603
+ * // => false
2604
+ */
2605
+ function isLength(value) {
2606
+ return typeof value == 'number' &&
2607
+ value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
2608
+ }
2609
+
2610
+ /**
2611
+ * Checks if `value` is the
2612
+ * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
2613
+ * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
2614
+ *
2615
+ * @static
2616
+ * @memberOf _
2617
+ * @since 0.1.0
2618
+ * @category Lang
2619
+ * @param {*} value The value to check.
2620
+ * @returns {boolean} Returns `true` if `value` is an object, else `false`.
2621
+ * @example
2622
+ *
2623
+ * _.isObject({});
2624
+ * // => true
2625
+ *
2626
+ * _.isObject([1, 2, 3]);
2627
+ * // => true
2628
+ *
2629
+ * _.isObject(_.noop);
2630
+ * // => true
2631
+ *
2632
+ * _.isObject(null);
2633
+ * // => false
2634
+ */
2635
+ function isObject(value) {
2636
+ var type = typeof value;
2637
+ return !!value && (type == 'object' || type == 'function');
2638
+ }
2639
+
2640
+ /**
2641
+ * Checks if `value` is object-like. A value is object-like if it's not `null`
2642
+ * and has a `typeof` result of "object".
2643
+ *
2644
+ * @static
2645
+ * @memberOf _
2646
+ * @since 4.0.0
2647
+ * @category Lang
2648
+ * @param {*} value The value to check.
2649
+ * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
2650
+ * @example
2651
+ *
2652
+ * _.isObjectLike({});
2653
+ * // => true
2654
+ *
2655
+ * _.isObjectLike([1, 2, 3]);
2656
+ * // => true
2657
+ *
2658
+ * _.isObjectLike(_.noop);
2659
+ * // => false
2660
+ *
2661
+ * _.isObjectLike(null);
2662
+ * // => false
2663
+ */
2664
+ function isObjectLike(value) {
2665
+ return !!value && typeof value == 'object';
2666
+ }
2667
+
2668
+ /**
2669
+ * Checks if `value` is classified as a `Symbol` primitive or object.
2670
+ *
2671
+ * @static
2672
+ * @memberOf _
2673
+ * @since 4.0.0
2674
+ * @category Lang
2675
+ * @param {*} value The value to check.
2676
+ * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
2677
+ * @example
2678
+ *
2679
+ * _.isSymbol(Symbol.iterator);
2680
+ * // => true
2681
+ *
2682
+ * _.isSymbol('abc');
2683
+ * // => false
2684
+ */
2685
+ function isSymbol(value) {
2686
+ return typeof value == 'symbol' ||
2687
+ (isObjectLike(value) && objectToString.call(value) == symbolTag);
2688
+ }
2689
+
2690
+ /**
2691
+ * Creates an object composed of the picked `object` properties.
2692
+ *
2693
+ * @static
2694
+ * @since 0.1.0
2695
+ * @memberOf _
2696
+ * @category Object
2697
+ * @param {Object} object The source object.
2698
+ * @param {...(string|string[])} [props] The property identifiers to pick.
2699
+ * @returns {Object} Returns the new object.
2700
+ * @example
2701
+ *
2702
+ * var object = { 'a': 1, 'b': '2', 'c': 3 };
2703
+ *
2704
+ * _.pick(object, ['a', 'c']);
2705
+ * // => { 'a': 1, 'c': 3 }
2706
+ */
2707
+ var pick = baseRest(function(object, props) {
2708
+ return object == null ? {} : basePick(object, arrayMap(baseFlatten(props, 1), toKey));
2709
+ });
2710
+
2711
+ var lodash_pick = pick;
2712
+
2713
+ function useFetchZones(params) {
2714
+ const [fetchZones, resource] = useResource({
2715
+ fetchResource: getZones,
2716
+ initialValue: [],
2717
+ context: params.context,
2718
+ resourceName: 'Banner zones',
2719
+ });
2720
+ onMounted(() => {
2721
+ fetchZones();
2722
+ });
2723
+ return resource;
2724
+ }
2725
+
2726
+ var Status;
2727
+ (function (Status) {
2728
+ Status["Waiting"] = "WAITING";
2729
+ Status["Archived"] = "ARCHIVED";
2730
+ Status["Active"] = "ACTIVE";
2731
+ Status["Disabled"] = "DISABLED";
2732
+ })(Status || (Status = {}));
2733
+
2734
+ function getStatus(type, t) {
2735
+ switch (type) {
2736
+ case Status.Waiting:
2737
+ return t('banners:statuses.waiting');
2738
+ case Status.Archived:
2739
+ return t('banners:statuses.archived');
2740
+ case Status.Active:
2741
+ return t('banners:statuses.active');
2742
+ case Status.Disabled:
2743
+ return t('banners:statuses.disabled');
2744
+ default:
2745
+ return '';
2746
+ }
2747
+ }
2748
+ function getColumnDefs$1(t) {
2749
+ return [
2750
+ {
2751
+ id: 0,
2752
+ name: '#',
2753
+ field: 'id',
2754
+ style: { width: '50px', textAlign: 'center' },
2755
+ headStyle: { width: '50px', textAlign: 'center' },
690
2756
  },
691
- pageTitle() {
692
- return this.bannerArea ? `"${this.bannerArea.label}" banners` : 'Banners';
2757
+ {
2758
+ id: 1,
2759
+ name: t('banners:zone'),
2760
+ field: 'bannerZone',
2761
+ format: ({ row }) => row.bannerZone ? row.bannerZone : t('banners:bannerZoneIsDeleted'),
693
2762
  },
694
- },
695
- watch: {
696
- areaAlias() {
697
- this.refreshBannerItemList();
2763
+ {
2764
+ id: 2,
2765
+ name: t('banners:status'),
2766
+ field: 'status',
2767
+ format: ({ row }) => getStatus(row.status, t),
2768
+ style: { width: '120px' },
2769
+ headStyle: { width: '120px' },
698
2770
  },
699
- },
700
- mounted() {
701
- this.refreshBannerItemList();
702
- },
703
- methods: {
704
- refreshBannerItemList() {
705
- this.isRowDataLoading = true;
706
- return getBannerAreaByAlias(this.areaAlias)
707
- .then((response) => {
708
- this.bannerArea = response.data;
709
- return getBannerItemList(this.bannerArea.id);
710
- })
711
- .then((response) => {
712
- this.rowData = response.data;
713
- this.errorMessage = null;
714
- })
715
- .catch((error) => {
716
- console.error(error);
717
- this.rowData = [];
718
- this.errorMessage = getMessageFromError(error);
719
- })
720
- .finally(() => {
721
- this.isRowDataLoading = false;
722
- });
2771
+ {
2772
+ id: 3,
2773
+ name: t('banners:period'),
2774
+ field: 'dateStart',
2775
+ format: ({ row }) => `${row.dateStart ? `${t('banners:from')} ${row.dateStart}` : ''} ${row.dateEnd ? `${t('banners:to')} ${row.dateEnd}` : ''}`,
723
2776
  },
724
- moveBannerItem(bannerItemId, direction) {
725
- this.isBannerItemMoving = true;
726
- moveBannerItem(bannerItemId, direction)
727
- .then((response) => {
728
- if (response.success) {
729
- return this.refreshBannerItemList();
730
- }
731
- })
732
- .catch(console.error)
733
- .finally(() => {
734
- this.isBannerItemMoving = false;
735
- });
2777
+ {
2778
+ id: 4,
2779
+ name: t('banners:image'),
2780
+ field: 'image',
2781
+ type: 'image',
736
2782
  },
737
- handleBannerItemDelete(bannerItem) {
738
- const shouldDeleteBannerItem = confirm(`Are you sure you want to delete banner item "${bannerItem.title}"`);
739
- if (shouldDeleteBannerItem) {
740
- this.deletingBannerItemIdList.push(bannerItem.id);
741
- deleteBannerItem(bannerItem.id)
742
- .then((response) => {
743
- if (response.success) {
744
- this.refreshBannerItemList().then(() => {
745
- this.deletingBannerItemIdList.filter((id) => id !== bannerItem.id);
746
- });
747
- this.$toast({
748
- variant: 'success',
749
- title: 'Success',
750
- body: 'Banner Item was successfully removed',
751
- });
752
- }
753
- else {
754
- this.$toast({
755
- variant: 'danger',
756
- title: 'Error',
757
- body: 'Banner Item deletion was failed',
758
- });
759
- }
760
- })
761
- .catch((error) => {
762
- console.error(error);
763
- this.$toast({
764
- variant: 'danger',
765
- title: 'Error',
766
- body: 'Banner Item deletion was failed',
767
- });
2783
+ {
2784
+ id: 5,
2785
+ name: t('banners:link'),
2786
+ field: 'link',
2787
+ type: 'name',
2788
+ format: ({ row }) => {
2789
+ var _a, _b;
2790
+ return ({
2791
+ adminLink: {
2792
+ url: (_a = row.link) !== null && _a !== void 0 ? _a : '',
2793
+ text: (_b = row.link) !== null && _b !== void 0 ? _b : '',
2794
+ },
2795
+ paramList: [
2796
+ {
2797
+ name: t('banners:newTab'),
2798
+ value: row.openNewTab ? t('banners:yes') : t('banners:no'),
2799
+ },
2800
+ ],
768
2801
  });
769
- }
2802
+ },
770
2803
  },
771
- getLinkToBannerItemForm(bannerItemId) {
772
- var _a, _b;
773
- return getBannerItemFormUrl({
774
- areaAlias: (_b = (_a = this.bannerArea) === null || _a === void 0 ? void 0 : _a.alias) !== null && _b !== void 0 ? _b : 'unknowm',
775
- itemId: bannerItemId,
776
- });
2804
+ {
2805
+ id: 6,
2806
+ name: t('banners:comment'),
2807
+ field: 'comment',
2808
+ },
2809
+ {
2810
+ id: 7,
2811
+ name: t('banners:actions'),
2812
+ field: 'actions',
2813
+ style: { whiteSpace: 'nowrap', width: '100px' },
2814
+ headStyle: { whiteSpace: 'nowrap', width: '100px' },
777
2815
  },
2816
+ ];
2817
+ }
2818
+
2819
+ var FilterTypes;
2820
+ (function (FilterTypes) {
2821
+ FilterTypes["Zone"] = "zone";
2822
+ FilterTypes["Date"] = "date";
2823
+ FilterTypes["Status"] = "status";
2824
+ })(FilterTypes || (FilterTypes = {}));
2825
+ function useAdvancedSearch({ context, t, zoneList }) {
2826
+ /** Zone **/
2827
+ const zonesOptionList = computed(() => zoneList.value.map(({ id, name }) => ({
2828
+ value: id,
2829
+ label: name,
2830
+ })));
2831
+ const initialZoneFilter = computed(() => {
2832
+ const queryValue = getFilterParamAsStringArray(context.root.$route.query, FilterTypes.Zone);
2833
+ return zonesOptionList.value.filter(({ value }) => queryValue.some((selected) => selected === value));
2834
+ });
2835
+ const zoneFilter = ref(initialZoneFilter.value);
2836
+ watch(initialZoneFilter, () => {
2837
+ zoneFilter.value = initialZoneFilter.value;
2838
+ });
2839
+ /** Date **/
2840
+ const initialDateFilter = computed(() => { var _a; return (_a = getFilterParamAsString(context.root.$route.query, FilterTypes.Date)) !== null && _a !== void 0 ? _a : ''; });
2841
+ const dateFilter = ref(initialDateFilter.value);
2842
+ watch(initialDateFilter, () => {
2843
+ dateFilter.value = initialDateFilter.value;
2844
+ });
2845
+ /** Status **/
2846
+ const statusesOptionList = computed(() => Object.entries(Status).map(([_, value]) => ({
2847
+ value: value,
2848
+ label: getStatus(value, t),
2849
+ })));
2850
+ const initialStatusFilter = computed(() => {
2851
+ const queryValue = getFilterParamAsStringArray(context.root.$route.query, FilterTypes.Status);
2852
+ return statusesOptionList.value.filter(({ value }) => queryValue.some((selected) => selected === value));
2853
+ });
2854
+ const statusFilter = ref(initialStatusFilter.value);
2855
+ watch(initialStatusFilter, () => {
2856
+ statusFilter.value = initialStatusFilter.value;
2857
+ });
2858
+ /** Params **/
2859
+ const filterParams = computed(() => getFilterParams({
2860
+ [FilterTypes.Zone]: zoneFilter.value.map(({ value }) => value),
2861
+ [FilterTypes.Date]: dateFilter.value,
2862
+ [FilterTypes.Status]: statusFilter.value.map(({ value }) => value),
2863
+ }));
2864
+ /** Tag removal handler **/
2865
+ const tagRemovalHandler = (event) => {
2866
+ if (event.name === FilterTypes.Zone) {
2867
+ zoneFilter.value = zoneFilter.value.filter(({ value }) => value !== event.value);
2868
+ }
2869
+ if (event.name === FilterTypes.Date) {
2870
+ dateFilter.value = '';
2871
+ }
2872
+ if (event.name === FilterTypes.Status) {
2873
+ statusFilter.value = statusFilter.value.filter(({ value }) => value !== event.value);
2874
+ }
2875
+ };
2876
+ /** Tags **/
2877
+ const tags = computed(() => []);
2878
+ return {
2879
+ zoneFilter,
2880
+ zonesOptionList,
2881
+ dateFilter,
2882
+ statusFilter,
2883
+ statusesOptionList,
2884
+ filterParams,
2885
+ tags,
2886
+ tagRemovalHandler,
2887
+ };
2888
+ }
2889
+
2890
+ var script$1 = defineComponent({
2891
+ name: 'BannerList',
2892
+ setup(props, context) {
2893
+ const { t } = useTranslation(context);
2894
+ const { loading: isZonesLoading, data: zoneList } = useFetchZones({
2895
+ context,
2896
+ });
2897
+ const { zoneFilter, zonesOptionList, dateFilter, statusFilter, statusesOptionList, filterParams, tags, tagRemovalHandler, } = useAdvancedSearch({
2898
+ context,
2899
+ t,
2900
+ zoneList,
2901
+ });
2902
+ const { fetchEntityList: fetchBanners, isLoading: isBannersLoading, rowData, errorMessage, handleChange, searchQuery, pageNumber, pageCount, pageSize, } = useDataTable({
2903
+ fetchEntityList: (params) => getBanners(Object.assign({ query: params.searchQuery, pageNumber: params.pageNumber, pageSize: params.pageSize }, filterParams.value)),
2904
+ initialValue: [],
2905
+ context,
2906
+ resourceName: 'Banners',
2907
+ });
2908
+ watch(filterParams, () => {
2909
+ if (isZonesLoading.value) {
2910
+ return;
2911
+ }
2912
+ const newQuery = Object.assign(Object.assign({}, lodash_pick(context.root.$route.query, ['query', 'pageNumber'])), filterParams.value);
2913
+ if (!lodash_isequal(context.root.$route.query, newQuery)) {
2914
+ context.root.$router.replace({ query: newQuery });
2915
+ fetchBanners();
2916
+ }
2917
+ });
2918
+ const { isDeleting, handleResourceDelete } = useResourceDelete({
2919
+ deleteResource: deleteBanner,
2920
+ resourceName: 'Banner',
2921
+ onSuccess: fetchBanners,
2922
+ context,
2923
+ });
2924
+ const isBusy = (bannerId) => {
2925
+ return isDeleting(bannerId) || isBannersLoading.value;
2926
+ };
2927
+ const columnDefs = computed(() => getColumnDefs$1(context.root.$t));
2928
+ const isRowDataLoading = computed(() => isBannersLoading.value || isZonesLoading.value);
2929
+ return {
2930
+ columnDefs,
2931
+ isRowDataLoading,
2932
+ rowData,
2933
+ errorMessage,
2934
+ handleChange,
2935
+ getBannersBannerFormUrl,
2936
+ searchQuery,
2937
+ pageNumber,
2938
+ pageCount,
2939
+ pageSize,
2940
+ isBusy,
2941
+ handleResourceDelete,
2942
+ // Advanced search
2943
+ zoneFilter,
2944
+ zonesOptionList,
2945
+ dateFilter,
2946
+ statusFilter,
2947
+ statusesOptionList,
2948
+ tags,
2949
+ tagRemovalHandler,
2950
+ };
778
2951
  },
779
2952
  });
780
2953
 
2954
+ const isOldIE = typeof navigator !== 'undefined' &&
2955
+ /msie [6-9]\\b/.test(navigator.userAgent.toLowerCase());
2956
+ function createInjector(context) {
2957
+ return (id, style) => addStyle(id, style);
2958
+ }
2959
+ let HEAD;
2960
+ const styles = {};
2961
+ function addStyle(id, css) {
2962
+ const group = isOldIE ? css.media || 'default' : id;
2963
+ const style = styles[group] || (styles[group] = { ids: new Set(), styles: [] });
2964
+ if (!style.ids.has(id)) {
2965
+ style.ids.add(id);
2966
+ let code = css.source;
2967
+ if (css.map) {
2968
+ // https://developer.chrome.com/devtools/docs/javascript-debugging
2969
+ // this makes source maps inside style tags work properly in Chrome
2970
+ code += '\n/*# sourceURL=' + css.map.sources[0] + ' */';
2971
+ // http://stackoverflow.com/a/26603875
2972
+ code +=
2973
+ '\n/*# sourceMappingURL=data:application/json;base64,' +
2974
+ btoa(unescape(encodeURIComponent(JSON.stringify(css.map)))) +
2975
+ ' */';
2976
+ }
2977
+ if (!style.element) {
2978
+ style.element = document.createElement('style');
2979
+ style.element.type = 'text/css';
2980
+ if (css.media)
2981
+ style.element.setAttribute('media', css.media);
2982
+ if (HEAD === undefined) {
2983
+ HEAD = document.head || document.getElementsByTagName('head')[0];
2984
+ }
2985
+ HEAD.appendChild(style.element);
2986
+ }
2987
+ if ('styleSheet' in style.element) {
2988
+ style.styles.push(code);
2989
+ style.element.styleSheet.cssText = style.styles
2990
+ .filter(Boolean)
2991
+ .join('\n');
2992
+ }
2993
+ else {
2994
+ const index = style.ids.size - 1;
2995
+ const textNode = document.createTextNode(code);
2996
+ const nodes = style.element.childNodes;
2997
+ if (nodes[index])
2998
+ style.element.removeChild(nodes[index]);
2999
+ if (nodes.length)
3000
+ style.element.insertBefore(textNode, nodes[index]);
3001
+ else
3002
+ style.element.appendChild(textNode);
3003
+ }
3004
+ }
3005
+ }
3006
+
781
3007
  /* script */
782
- const __vue_script__$2 = script$2;
3008
+ const __vue_script__$1 = script$1;
783
3009
 
784
3010
  /* template */
785
- var __vue_render__$2 = function () {
3011
+ var __vue_render__$1 = function () {
786
3012
  var _vm = this;
787
3013
  var _h = _vm.$createElement;
788
3014
  var _c = _vm._self._c || _h;
789
3015
  return _c("page", {
790
3016
  attrs: {
791
- title: _vm.pageTitle,
3017
+ title: _vm.$t("banners:banners"),
792
3018
  "header-buttons": [
793
3019
  {
794
- text: "New Banner Item",
795
- href: _vm.getLinkToBannerItemForm("create"),
3020
+ text: _vm.$t("banners:createBanner"),
3021
+ href: _vm.getBannersBannerFormUrl({ bannerId: "create" }),
796
3022
  },
797
3023
  ],
798
3024
  },
@@ -801,72 +3027,116 @@ var __vue_render__$2 = function () {
801
3027
  key: "content",
802
3028
  fn: function () {
803
3029
  return [
804
- _c("base-table", {
3030
+ _c("data-table", {
805
3031
  attrs: {
806
3032
  "column-defs": _vm.columnDefs,
807
3033
  "row-data": _vm.rowData,
808
3034
  loading: _vm.isRowDataLoading,
809
3035
  "error-message": _vm.errorMessage,
810
- enumerable: "",
3036
+ "data-table": "banners",
3037
+ "use-search": true,
3038
+ "use-pagination": true,
3039
+ "search-query": _vm.searchQuery,
3040
+ pagination: {
3041
+ pageNumber: _vm.pageNumber,
3042
+ pageCount: _vm.pageCount,
3043
+ pageSize: _vm.pageSize,
3044
+ disabled: _vm.isRowDataLoading,
3045
+ },
811
3046
  },
3047
+ on: { change: _vm.handleChange },
812
3048
  scopedSlots: _vm._u([
813
3049
  {
814
- key: "cell(actions)",
815
- fn: function (ref) {
816
- var row = ref.row;
817
- var rowIndex = ref.rowIndex;
3050
+ key: "filters",
3051
+ fn: function () {
818
3052
  return [
819
3053
  _c(
820
- "base-button",
821
- {
822
- attrs: {
823
- variant: "icon",
824
- title: "Edit",
825
- disabled: _vm.deletingBannerItemIdList.includes(
826
- row.id
827
- ),
828
- href: _vm.getLinkToBannerItemForm(row.id),
829
- },
830
- },
831
- [_c("svg-icon", { attrs: { name: "edit" } })],
832
- 1
833
- ),
834
- _vm._v(" "),
835
- _c(
836
- "base-button",
3054
+ "advanced-search",
837
3055
  {
838
- attrs: {
839
- variant: "icon",
840
- title: "Move up",
841
- disabled: rowIndex === 0 || _vm.isBannerItemMoving,
842
- },
843
- on: {
844
- click: function ($event) {
845
- return _vm.moveBannerItem(row.id, "up")
846
- },
847
- },
3056
+ attrs: { tags: _vm.tags },
3057
+ on: { "click:tag": _vm.tagRemovalHandler },
848
3058
  },
849
- [_c("svg-icon", { attrs: { name: "north" } })],
850
- 1
3059
+ [
3060
+ _c(
3061
+ "div",
3062
+ { staticClass: "filters" },
3063
+ [
3064
+ _c("form-field-multi-select", {
3065
+ staticClass: "filter",
3066
+ attrs: {
3067
+ options: _vm.zonesOptionList,
3068
+ name: "zoneFilter",
3069
+ searchable: true,
3070
+ label: _vm.$t("banners:zone"),
3071
+ },
3072
+ model: {
3073
+ value: _vm.zoneFilter,
3074
+ callback: function ($$v) {
3075
+ _vm.zoneFilter = $$v;
3076
+ },
3077
+ expression: "zoneFilter",
3078
+ },
3079
+ }),
3080
+ _vm._v(" "),
3081
+ _c("form-field", {
3082
+ staticClass: "filter",
3083
+ attrs: {
3084
+ label: _vm.$t("banners:date"),
3085
+ name: "dateFilter",
3086
+ type: "date",
3087
+ },
3088
+ model: {
3089
+ value: _vm.dateFilter,
3090
+ callback: function ($$v) {
3091
+ _vm.dateFilter = $$v;
3092
+ },
3093
+ expression: "dateFilter",
3094
+ },
3095
+ }),
3096
+ _vm._v(" "),
3097
+ _c("form-field-multi-select", {
3098
+ staticClass: "filter",
3099
+ attrs: {
3100
+ options: _vm.statusesOptionList,
3101
+ name: "statusFilter",
3102
+ searchable: true,
3103
+ label: _vm.$t("banners:status"),
3104
+ },
3105
+ model: {
3106
+ value: _vm.statusFilter,
3107
+ callback: function ($$v) {
3108
+ _vm.statusFilter = $$v;
3109
+ },
3110
+ expression: "statusFilter",
3111
+ },
3112
+ }),
3113
+ ],
3114
+ 1
3115
+ ),
3116
+ ]
851
3117
  ),
852
- _vm._v(" "),
3118
+ ]
3119
+ },
3120
+ proxy: true,
3121
+ },
3122
+ {
3123
+ key: "cell(actions)",
3124
+ fn: function (ref) {
3125
+ var row = ref.row;
3126
+ return [
853
3127
  _c(
854
3128
  "base-button",
855
3129
  {
856
3130
  attrs: {
857
3131
  variant: "icon",
858
- title: "Move down",
859
- disabled:
860
- rowIndex === _vm.rowData.length - 1 ||
861
- _vm.isBannerItemMoving,
862
- },
863
- on: {
864
- click: function ($event) {
865
- return _vm.moveBannerItem(row.id, "down")
866
- },
3132
+ title: _vm.$t("banners:edit"),
3133
+ disabled: _vm.isBusy(row.id),
3134
+ href: _vm.getBannersBannerFormUrl({
3135
+ bannerId: row.id,
3136
+ }),
867
3137
  },
868
3138
  },
869
- [_c("svg-icon", { attrs: { name: "south" } })],
3139
+ [_c("svg-icon", { attrs: { name: "edit" } })],
870
3140
  1
871
3141
  ),
872
3142
  _vm._v(" "),
@@ -875,14 +3145,12 @@ var __vue_render__$2 = function () {
875
3145
  {
876
3146
  attrs: {
877
3147
  variant: "icon",
878
- title: "Remove",
879
- disabled: _vm.deletingBannerItemIdList.includes(
880
- row.id
881
- ),
3148
+ title: _vm.$t("banners:remove"),
3149
+ disabled: _vm.isBusy(row.id),
882
3150
  },
883
3151
  on: {
884
3152
  click: function ($event) {
885
- return _vm.handleBannerItemDelete(row)
3153
+ return _vm.handleResourceDelete(row.id)
886
3154
  },
887
3155
  },
888
3156
  },
@@ -901,169 +3169,175 @@ var __vue_render__$2 = function () {
901
3169
  ]),
902
3170
  })
903
3171
  };
904
- var __vue_staticRenderFns__$2 = [];
905
- __vue_render__$2._withStripped = true;
3172
+ var __vue_staticRenderFns__$1 = [];
3173
+ __vue_render__$1._withStripped = true;
906
3174
 
907
3175
  /* style */
908
- const __vue_inject_styles__$2 = function (inject) {
3176
+ const __vue_inject_styles__$1 = function (inject) {
909
3177
  if (!inject) return
910
- inject("data-v-0834d29c_0", { source: "\n\n/*# sourceMappingURL=BannerItemList.vue.map */", map: {"version":3,"sources":["BannerItemList.vue"],"names":[],"mappings":";;AAEA,6CAA6C","file":"BannerItemList.vue"}, media: undefined });
3178
+ inject("data-v-92c7e846_0", { source: ".filters {\n display: flex;\n margin: 0 -10px;\n}\n.filters:not(:first-child) {\n margin-top: 10px;\n}\n.filters .filter {\n padding: 10px 10px 0;\n width: 50%;\n margin: 0;\n}\n\n/*# sourceMappingURL=BannerList.vue.map */", map: {"version":3,"sources":["/home/runner/work/tager-admin-banners/tager-admin-banners/src/views/Banners/BannerList/BannerList.vue","BannerList.vue"],"names":[],"mappings":"AA0NA;EACA,aAAA;EACA,eAAA;ACzNA;AD2NA;EACA,gBAAA;ACzNA;AD4NA;EACA,oBAAA;EACA,UAAA;EACA,SAAA;AC1NA;;AAEA,yCAAyC","file":"BannerList.vue","sourcesContent":["<template>\n <page\n :title=\"$t('banners:banners')\"\n :header-buttons=\"[\n {\n text: $t('banners:createBanner'),\n href: getBannersBannerFormUrl({ bannerId: 'create' }),\n },\n ]\"\n >\n <template v-slot:content>\n <data-table\n :column-defs=\"columnDefs\"\n :row-data=\"rowData\"\n :loading=\"isRowDataLoading\"\n :error-message=\"errorMessage\"\n data-table=\"banners\"\n :use-search=\"true\"\n :use-pagination=\"true\"\n :search-query=\"searchQuery\"\n :pagination=\"{\n pageNumber,\n pageCount,\n pageSize,\n disabled: isRowDataLoading,\n }\"\n @change=\"handleChange\"\n >\n <template v-slot:filters>\n <advanced-search :tags=\"tags\" @click:tag=\"tagRemovalHandler\">\n <div class=\"filters\">\n <form-field-multi-select\n v-model=\"zoneFilter\"\n :options=\"zonesOptionList\"\n name=\"zoneFilter\"\n :searchable=\"true\"\n :label=\"$t('banners:zone')\"\n class=\"filter\"\n />\n\n <form-field\n v-model=\"dateFilter\"\n :label=\"$t('banners:date')\"\n name=\"dateFilter\"\n type=\"date\"\n class=\"filter\"\n />\n\n <form-field-multi-select\n v-model=\"statusFilter\"\n :options=\"statusesOptionList\"\n name=\"statusFilter\"\n :searchable=\"true\"\n :label=\"$t('banners:status')\"\n class=\"filter\"\n />\n </div>\n </advanced-search>\n </template>\n\n <template v-slot:cell(actions)=\"{ row }\">\n <base-button\n variant=\"icon\"\n :title=\"$t('banners:edit')\"\n :disabled=\"isBusy(row.id)\"\n :href=\"getBannersBannerFormUrl({ bannerId: row.id })\"\n >\n <svg-icon name=\"edit\" />\n </base-button>\n\n <base-button\n variant=\"icon\"\n :title=\"$t('banners:remove')\"\n :disabled=\"isBusy(row.id)\"\n @click=\"handleResourceDelete(row.id)\"\n >\n <svg-icon name=\"delete\" />\n </base-button>\n </template>\n </data-table>\n </template>\n </page>\n</template>\n\n<script lang=\"ts\">\nimport {\n computed,\n defineComponent,\n SetupContext,\n watch,\n} from '@vue/composition-api';\nimport isEqual from 'lodash.isequal';\nimport pick from 'lodash.pick';\n\nimport {\n ColumnDefinition,\n useDataTable,\n useTranslation,\n} from '@tager/admin-ui';\nimport { useResourceDelete } from '@tager/admin-services';\n\nimport { deleteBanner, getBanners } from '../../../services/requests';\nimport { Banner } from '../../../typings/banners';\nimport { getBannersBannerFormUrl } from '../../../constants/paths';\nimport { useFetchZones } from '../../../hooks';\n\nimport { getColumnDefs } from './BannerList.helpers';\nimport { useAdvancedSearch } from './hooks';\n\nexport default defineComponent({\n name: 'BannerList',\n setup(props, context: SetupContext) {\n const { t } = useTranslation(context);\n const { loading: isZonesLoading, data: zoneList } = useFetchZones({\n context,\n });\n\n const {\n zoneFilter,\n zonesOptionList,\n dateFilter,\n statusFilter,\n statusesOptionList,\n filterParams,\n tags,\n tagRemovalHandler,\n } = useAdvancedSearch({\n context,\n t,\n zoneList,\n });\n\n const {\n fetchEntityList: fetchBanners,\n isLoading: isBannersLoading,\n rowData,\n errorMessage,\n handleChange,\n searchQuery,\n pageNumber,\n pageCount,\n pageSize,\n } = useDataTable<Banner>({\n fetchEntityList: (params) =>\n getBanners({\n query: params.searchQuery,\n pageNumber: params.pageNumber,\n pageSize: params.pageSize,\n ...filterParams.value,\n }),\n initialValue: [],\n context,\n resourceName: 'Banners',\n });\n\n watch(filterParams, () => {\n if (isZonesLoading.value) {\n return;\n }\n\n const newQuery = {\n ...pick(context.root.$route.query, ['query', 'pageNumber']),\n ...filterParams.value,\n };\n\n if (!isEqual(context.root.$route.query, newQuery)) {\n context.root.$router.replace({ query: newQuery });\n fetchBanners();\n }\n });\n\n const { isDeleting, handleResourceDelete } = useResourceDelete({\n deleteResource: deleteBanner,\n resourceName: 'Banner',\n onSuccess: fetchBanners,\n context,\n });\n\n const isBusy = (bannerId: number): boolean => {\n return isDeleting(bannerId) || isBannersLoading.value;\n };\n\n const columnDefs = computed<ColumnDefinition<Banner>[]>(() =>\n getColumnDefs(context.root.$t)\n );\n\n const isRowDataLoading = computed<boolean>(\n () => isBannersLoading.value || isZonesLoading.value\n );\n\n return {\n columnDefs,\n isRowDataLoading,\n rowData,\n errorMessage,\n handleChange,\n getBannersBannerFormUrl,\n searchQuery,\n pageNumber,\n pageCount,\n pageSize,\n isBusy,\n handleResourceDelete,\n\n // Advanced search\n zoneFilter,\n zonesOptionList,\n dateFilter,\n statusFilter,\n statusesOptionList,\n tags,\n tagRemovalHandler,\n };\n },\n});\n</script>\n\n<style lang=\"scss\">\n.filters {\n display: flex;\n margin: 0 -10px;\n\n &:not(:first-child) {\n margin-top: 10px;\n }\n\n .filter {\n padding: 10px 10px 0;\n width: 50%;\n margin: 0;\n }\n}\n</style>\n",".filters {\n display: flex;\n margin: 0 -10px;\n}\n.filters:not(:first-child) {\n margin-top: 10px;\n}\n.filters .filter {\n padding: 10px 10px 0;\n width: 50%;\n margin: 0;\n}\n\n/*# sourceMappingURL=BannerList.vue.map */"]}, media: undefined });
911
3179
 
912
3180
  };
913
3181
  /* scoped */
914
- const __vue_scope_id__$2 = "data-v-0834d29c";
3182
+ const __vue_scope_id__$1 = undefined;
915
3183
  /* module identifier */
916
- const __vue_module_identifier__$2 = undefined;
3184
+ const __vue_module_identifier__$1 = undefined;
917
3185
  /* functional template */
918
- const __vue_is_functional_template__$2 = false;
3186
+ const __vue_is_functional_template__$1 = false;
919
3187
  /* style inject SSR */
920
3188
 
921
3189
  /* style inject shadow dom */
922
3190
 
923
3191
 
924
3192
 
925
- const __vue_component__$2 = /*#__PURE__*/normalizeComponent(
926
- { render: __vue_render__$2, staticRenderFns: __vue_staticRenderFns__$2 },
927
- __vue_inject_styles__$2,
928
- __vue_script__$2,
929
- __vue_scope_id__$2,
930
- __vue_is_functional_template__$2,
931
- __vue_module_identifier__$2,
3193
+ const __vue_component__$1 = /*#__PURE__*/normalizeComponent(
3194
+ { render: __vue_render__$1, staticRenderFns: __vue_staticRenderFns__$1 },
3195
+ __vue_inject_styles__$1,
3196
+ __vue_script__$1,
3197
+ __vue_scope_id__$1,
3198
+ __vue_is_functional_template__$1,
3199
+ __vue_module_identifier__$1,
932
3200
  false,
933
3201
  createInjector,
934
3202
  undefined,
935
3203
  undefined
936
3204
  );
937
3205
 
938
- const INITIAL_VALUES = {
939
- title: '',
940
- text: '',
941
- buttonLink: '',
942
- buttonLabel: '',
943
- buttonIsNewTab: false,
944
- image: null,
945
- };
946
- var script$3 = Vue.extend({
947
- name: 'BannerItemForm',
948
- data() {
949
- return {
950
- values: Object.assign({}, INITIAL_VALUES),
951
- errors: {},
952
- isContentLoading: false,
953
- bannerArea: null,
954
- };
955
- },
956
- computed: {
957
- itemId() {
958
- return this.$route.params.itemId;
959
- },
960
- areaAlias() {
961
- return this.$route.params.areaAlias;
962
- },
963
- isCreation() {
964
- return this.itemId === 'create';
965
- },
966
- bannerItemListUrl() {
967
- var _a, _b;
968
- return getBannerItemListUrl({
969
- areaAlias: (_b = (_a = this.bannerArea) === null || _a === void 0 ? void 0 : _a.alias) !== null && _b !== void 0 ? _b : 'unknown',
970
- });
971
- },
972
- },
973
- watch: {
974
- itemId() {
975
- this.updateValues();
976
- },
977
- areaAlias() {
978
- this.updateValues();
979
- },
980
- },
981
- mounted() {
982
- this.updateValues();
983
- },
984
- methods: {
985
- updateValues() {
986
- this.isContentLoading = true;
987
- Promise.all([
988
- getBannerAreaByAlias(this.areaAlias)
989
- .then((response) => {
990
- this.bannerArea = response.data;
991
- })
992
- .catch(console.error),
993
- this.isCreation
994
- ? new Promise((resolve) => {
995
- this.values = Object.assign({}, INITIAL_VALUES);
996
- resolve();
997
- })
998
- : getBannerItemById(this.itemId)
999
- .then((response) => {
1000
- this.values = this.convertReviewToInitialValues(response.data);
1001
- })
1002
- .catch(console.error),
1003
- ]).finally(() => {
1004
- this.isContentLoading = false;
1005
- });
1006
- },
1007
- convertReviewToInitialValues(bannerItem) {
1008
- var _a;
1009
- return {
1010
- title: bannerItem.title,
1011
- text: bannerItem.text,
1012
- buttonLink: (_a = bannerItem.buttonLink) !== null && _a !== void 0 ? _a : '',
1013
- buttonLabel: bannerItem.buttonLabel,
1014
- buttonIsNewTab: bannerItem.buttonIsNewTab,
1015
- image: bannerItem.image,
1016
- };
1017
- },
1018
- submitForm() {
1019
- var _a, _b, _c, _d;
1020
- const creationBody = {
1021
- title: this.values.title,
1022
- text: this.values.text,
1023
- buttonLink: this.values.buttonLink.trim() || null,
1024
- buttonLabel: this.values.buttonLabel,
1025
- buttonIsNewTab: this.values.buttonIsNewTab,
1026
- image: (_b = (_a = this.values.image) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : null,
1027
- };
1028
- const requestPromise = this.isCreation
1029
- ? createBannerItem((_d = (_c = this.bannerArea) === null || _c === void 0 ? void 0 : _c.id) !== null && _d !== void 0 ? _d : 'unknown', creationBody)
1030
- : updateBannerItem(this.itemId, creationBody);
3206
+ function useFetchBanner({ context, bannerId, isCreation, }) {
3207
+ const [fetchBanner, resource] = useResource({
3208
+ fetchResource: () => getBanner(bannerId.value),
3209
+ initialValue: null,
3210
+ context,
3211
+ resourceName: 'Banner',
3212
+ });
3213
+ onMounted(() => {
3214
+ if (isCreation.value) {
3215
+ return;
3216
+ }
3217
+ fetchBanner();
3218
+ });
3219
+ watch(bannerId, () => {
3220
+ if (isCreation.value) {
3221
+ return;
3222
+ }
3223
+ fetchBanner();
3224
+ });
3225
+ return resource;
3226
+ }
3227
+
3228
+ function convertBannerToFormValues(banner, zonesOptionList) {
3229
+ var _a, _b, _c, _d, _e, _f;
3230
+ const foundZone = zonesOptionList.find(({ value }) => value === (banner === null || banner === void 0 ? void 0 : banner.bannerZone));
3231
+ return {
3232
+ link: (_a = banner === null || banner === void 0 ? void 0 : banner.link) !== null && _a !== void 0 ? _a : '',
3233
+ image: (banner === null || banner === void 0 ? void 0 : banner.image) ? { id: createId(), file: banner.image } : null,
3234
+ bannerZone: foundZone !== null && foundZone !== void 0 ? foundZone : null,
3235
+ openNewTab: (_b = banner === null || banner === void 0 ? void 0 : banner.openNewTab) !== null && _b !== void 0 ? _b : false,
3236
+ dateStart: (_c = banner === null || banner === void 0 ? void 0 : banner.dateStart) !== null && _c !== void 0 ? _c : '',
3237
+ dateEnd: (_d = banner === null || banner === void 0 ? void 0 : banner.dateEnd) !== null && _d !== void 0 ? _d : '',
3238
+ disabled: (_e = banner === null || banner === void 0 ? void 0 : banner.disabled) !== null && _e !== void 0 ? _e : false,
3239
+ comment: (_f = banner === null || banner === void 0 ? void 0 : banner.comment) !== null && _f !== void 0 ? _f : '',
3240
+ };
3241
+ }
3242
+ function convertBannerFormValuesToPayload(values) {
3243
+ var _a, _b, _c, _d;
3244
+ return Object.assign(Object.assign({}, values), { image: (_b = (_a = values.image) === null || _a === void 0 ? void 0 : _a.file.id) !== null && _b !== void 0 ? _b : null, bannerZone: (_d = (_c = values.bannerZone) === null || _c === void 0 ? void 0 : _c.value) !== null && _d !== void 0 ? _d : '' });
3245
+ }
3246
+
3247
+ var script$2 = defineComponent({
3248
+ name: 'BannerForm',
3249
+ components: { FormFooter },
3250
+ setup(props, context) {
3251
+ const bannerId = computed(() => context.root.$route.params.bannerId);
3252
+ const isCreation = computed(() => bannerId.value === 'create');
3253
+ /** Zones **/
3254
+ const { data: zones, loading: isZonesLoading } = useFetchZones({ context });
3255
+ const zonesOptionList = computed(() => zones.value.map((zone) => ({
3256
+ value: zone.id,
3257
+ label: zone.name,
3258
+ })));
3259
+ /** Banner **/
3260
+ const { data: banner, loading: isBannerLoading } = useFetchBanner({
3261
+ context,
3262
+ bannerId,
3263
+ isCreation,
3264
+ });
3265
+ /** Form State **/
3266
+ const isSubmitting = ref(false);
3267
+ const values = ref(convertBannerToFormValues(banner.value, zonesOptionList.value));
3268
+ const errors = ref({});
3269
+ watch([banner, zones], () => {
3270
+ values.value = convertBannerToFormValues(banner.value, zonesOptionList.value);
3271
+ });
3272
+ const submitForm = (event) => {
3273
+ isSubmitting.value = true;
3274
+ const body = convertBannerFormValuesToPayload(values.value);
3275
+ const requestPromise = isCreation.value
3276
+ ? createBanner(body)
3277
+ : updateBanner(bannerId.value, body);
1031
3278
  requestPromise
1032
- .then(() => {
1033
- this.errors = {};
1034
- this.$router.push(this.bannerItemListUrl);
1035
- this.$toast({
3279
+ .then(({ data }) => {
3280
+ errors.value = {};
3281
+ if (event.type === 'create') {
3282
+ context.root.$router.push(getBannersBannerFormUrl({ bannerId: String(data.id) }));
3283
+ }
3284
+ if (event.type === 'create_exit' || event.type === 'save_exit') {
3285
+ context.root.$router.push(getBannersBannerListUrl());
3286
+ }
3287
+ if (event.type === 'create_create-another') {
3288
+ values.value = convertBannerToFormValues(null, zonesOptionList.value);
3289
+ }
3290
+ context.root.$toast({
1036
3291
  variant: 'success',
1037
- title: 'Success',
1038
- body: `Banner item has been successfully ${this.isCreation ? 'created' : 'updated'}`,
3292
+ title: context.root.$t('banners:success'),
3293
+ body: isCreation.value
3294
+ ? context.root.$t('banners:bannerWasSuccessfullyCreated')
3295
+ : context.root.$t('banners:bannerWasSuccessfullyUpdated'),
1039
3296
  });
1040
3297
  })
1041
3298
  .catch((error) => {
1042
3299
  console.error(error);
1043
- this.errors = convertRequestErrorToMap(error);
1044
- this.$toast({
3300
+ errors.value = convertRequestErrorToMap(error);
3301
+ context.root.$toast({
1045
3302
  variant: 'danger',
1046
- title: 'Error',
1047
- body: `Banner item ${this.isCreation ? 'creation' : 'update'} has been failed`,
3303
+ title: context.root.$t('banners:error'),
3304
+ body: isCreation.value
3305
+ ? context.root.$t('banners:bannerCreationWasFailed')
3306
+ : context.root.$t('banners:bannerUpdateWasFailed'),
1048
3307
  });
3308
+ })
3309
+ .finally(() => {
3310
+ isSubmitting.value = false;
1049
3311
  });
1050
- },
3312
+ };
3313
+ const isContentLoading = computed(() => isBannerLoading.value || isZonesLoading.value);
3314
+ return {
3315
+ isCreation,
3316
+ isContentLoading,
3317
+ isSubmitting,
3318
+ values,
3319
+ errors,
3320
+ submitForm,
3321
+ bannerListUrl: getBannersBannerListUrl(),
3322
+ zonesOptionList,
3323
+ };
1051
3324
  },
1052
3325
  });
1053
3326
 
1054
3327
  /* script */
1055
- const __vue_script__$3 = script$3;
3328
+ const __vue_script__$2 = script$2;
1056
3329
 
1057
3330
  /* template */
1058
- var __vue_render__$3 = function () {
3331
+ var __vue_render__$2 = function () {
1059
3332
  var _vm = this;
1060
3333
  var _h = _vm.$createElement;
1061
3334
  var _c = _vm._self._c || _h;
1062
3335
  return _c("page", {
1063
3336
  attrs: {
1064
- title: _vm.isCreation ? "Create Banner Item" : "Update Banner Item",
3337
+ title: _vm.isCreation
3338
+ ? _vm.$t("banners:createBanner")
3339
+ : _vm.$t("banners:updateBanner"),
1065
3340
  "is-content-loading": _vm.isContentLoading,
1066
- footer: { onSubmit: _vm.submitForm, backHref: _vm.bannerItemListUrl },
1067
3341
  },
1068
3342
  scopedSlots: _vm._u([
1069
3343
  {
@@ -1077,46 +3351,33 @@ var __vue_render__$3 = function () {
1077
3351
  on: {
1078
3352
  submit: function ($event) {
1079
3353
  $event.preventDefault();
3354
+ return _vm.submitForm($event)
1080
3355
  },
1081
3356
  },
1082
3357
  },
1083
3358
  [
1084
- _c("form-field", {
1085
- attrs: {
1086
- name: "title",
1087
- label: "Title",
1088
- error: _vm.errors.title,
1089
- type: "textarea",
1090
- },
1091
- model: {
1092
- value: _vm.values.title,
1093
- callback: function ($$v) {
1094
- _vm.$set(_vm.values, "title", $$v);
1095
- },
1096
- expression: "values.title",
1097
- },
1098
- }),
1099
- _vm._v(" "),
1100
- _c("form-field-rich-text-input", {
3359
+ _c("form-field-select", {
1101
3360
  attrs: {
1102
- name: "text",
1103
- label: "Text",
1104
- error: _vm.errors.text,
3361
+ name: "bannerZone",
3362
+ label: _vm.$t("banners:zone"),
3363
+ options: _vm.zonesOptionList,
3364
+ error: _vm.errors.bannerZone,
1105
3365
  },
1106
3366
  model: {
1107
- value: _vm.values.text,
3367
+ value: _vm.values.bannerZone,
1108
3368
  callback: function ($$v) {
1109
- _vm.$set(_vm.values, "text", $$v);
3369
+ _vm.$set(_vm.values, "bannerZone", $$v);
1110
3370
  },
1111
- expression: "values.text",
3371
+ expression: "values.bannerZone",
1112
3372
  },
1113
3373
  }),
1114
3374
  _vm._v(" "),
1115
3375
  _c("form-field-file-input", {
1116
3376
  attrs: {
1117
- label: "Image",
1118
3377
  name: "image",
1119
3378
  "file-type": "image",
3379
+ label: _vm.$t("banners:image"),
3380
+ error: _vm.errors.file,
1120
3381
  },
1121
3382
  model: {
1122
3383
  value: _vm.values.image,
@@ -1129,46 +3390,103 @@ var __vue_render__$3 = function () {
1129
3390
  _vm._v(" "),
1130
3391
  _c("form-field", {
1131
3392
  attrs: {
1132
- name: "buttonLabel",
1133
- label: "Button: Label",
1134
- error: _vm.errors.buttonLabel,
3393
+ name: "link",
3394
+ label: _vm.$t("banners:link"),
3395
+ error: _vm.errors.name,
1135
3396
  },
1136
3397
  model: {
1137
- value: _vm.values.buttonLabel,
3398
+ value: _vm.values.link,
1138
3399
  callback: function ($$v) {
1139
- _vm.$set(_vm.values, "buttonLabel", $$v);
3400
+ _vm.$set(_vm.values, "link", $$v);
1140
3401
  },
1141
- expression: "values.buttonLabel",
3402
+ expression: "values.link",
1142
3403
  },
1143
3404
  }),
1144
3405
  _vm._v(" "),
1145
- _c("form-field", {
3406
+ _c("form-field-checkbox", {
1146
3407
  attrs: {
1147
- name: "buttonLink",
1148
- label: "Button: Link",
1149
- error: _vm.errors.buttonLink,
3408
+ name: "openNewTab",
3409
+ label: _vm.$t("banners:openNewTab"),
3410
+ error: _vm.errors.openNewTab,
1150
3411
  },
1151
3412
  model: {
1152
- value: _vm.values.buttonLink,
3413
+ value: _vm.values.openNewTab,
1153
3414
  callback: function ($$v) {
1154
- _vm.$set(_vm.values, "buttonLink", $$v);
3415
+ _vm.$set(_vm.values, "openNewTab", $$v);
1155
3416
  },
1156
- expression: "values.buttonLink",
3417
+ expression: "values.openNewTab",
1157
3418
  },
1158
3419
  }),
1159
3420
  _vm._v(" "),
3421
+ _c("input-label", [_vm._v(_vm._s(_vm.$t("banners:period")))]),
3422
+ _vm._v(" "),
3423
+ _c(
3424
+ "div",
3425
+ { staticClass: "date" },
3426
+ [
3427
+ _c("form-field", {
3428
+ attrs: {
3429
+ label: _vm.$t("banners:from"),
3430
+ name: "dateStart",
3431
+ type: "date",
3432
+ max: _vm.values.dateEnd,
3433
+ },
3434
+ model: {
3435
+ value: _vm.values.dateStart,
3436
+ callback: function ($$v) {
3437
+ _vm.$set(_vm.values, "dateStart", $$v);
3438
+ },
3439
+ expression: "values.dateStart",
3440
+ },
3441
+ }),
3442
+ _vm._v(" "),
3443
+ _c("form-field", {
3444
+ attrs: {
3445
+ label: _vm.$t("banners:to"),
3446
+ name: "dateEnd",
3447
+ type: "date",
3448
+ min: _vm.values.dateStart,
3449
+ },
3450
+ model: {
3451
+ value: _vm.values.dateEnd,
3452
+ callback: function ($$v) {
3453
+ _vm.$set(_vm.values, "dateEnd", $$v);
3454
+ },
3455
+ expression: "values.dateEnd",
3456
+ },
3457
+ }),
3458
+ ],
3459
+ 1
3460
+ ),
3461
+ _vm._v(" "),
1160
3462
  _c("form-field-checkbox", {
1161
3463
  attrs: {
1162
- name: "buttonIsNewTab",
1163
- label: "Button: Is new tab?",
1164
- error: _vm.errors.buttonIsNewTab,
3464
+ name: "disabled",
3465
+ label: _vm.$t("banners:disabled"),
3466
+ error: _vm.errors.disabled,
3467
+ },
3468
+ model: {
3469
+ value: _vm.values.disabled,
3470
+ callback: function ($$v) {
3471
+ _vm.$set(_vm.values, "disabled", $$v);
3472
+ },
3473
+ expression: "values.disabled",
3474
+ },
3475
+ }),
3476
+ _vm._v(" "),
3477
+ _c("form-field", {
3478
+ attrs: {
3479
+ name: "comment",
3480
+ type: "textarea",
3481
+ label: _vm.$t("banners:comment"),
3482
+ error: _vm.errors.comment,
1165
3483
  },
1166
3484
  model: {
1167
- value: _vm.values.buttonIsNewTab,
3485
+ value: _vm.values.comment,
1168
3486
  callback: function ($$v) {
1169
- _vm.$set(_vm.values, "buttonIsNewTab", $$v);
3487
+ _vm.$set(_vm.values, "comment", $$v);
1170
3488
  },
1171
- expression: "values.buttonIsNewTab",
3489
+ expression: "values.comment",
1172
3490
  },
1173
3491
  }),
1174
3492
  ],
@@ -1178,117 +3496,112 @@ var __vue_render__$3 = function () {
1178
3496
  },
1179
3497
  proxy: true,
1180
3498
  },
3499
+ {
3500
+ key: "footer",
3501
+ fn: function () {
3502
+ return [
3503
+ _c("FormFooter", {
3504
+ attrs: {
3505
+ "back-href": _vm.bannerListUrl,
3506
+ "on-submit": _vm.submitForm,
3507
+ "is-submitting": _vm.isSubmitting,
3508
+ "is-creation": _vm.isCreation,
3509
+ "can-create-another": _vm.isCreation,
3510
+ },
3511
+ }),
3512
+ ]
3513
+ },
3514
+ proxy: true,
3515
+ },
1181
3516
  ]),
1182
3517
  })
1183
3518
  };
1184
- var __vue_staticRenderFns__$3 = [];
1185
- __vue_render__$3._withStripped = true;
3519
+ var __vue_staticRenderFns__$2 = [];
3520
+ __vue_render__$2._withStripped = true;
1186
3521
 
1187
3522
  /* style */
1188
- const __vue_inject_styles__$3 = function (inject) {
3523
+ const __vue_inject_styles__$2 = function (inject) {
1189
3524
  if (!inject) return
1190
- inject("data-v-2ed0e9d3_0", { source: ".bottom[data-v-2ed0e9d3] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n.save-button[data-v-2ed0e9d3] {\n min-width: 100px;\n}\n.alias-field-inner[data-v-2ed0e9d3] {\n display: flex;\n align-items: center;\n}\n.alias-field-inner span[data-v-2ed0e9d3] {\n font-size: 0.9em;\n margin-right: 10px;\n}\n\n/*# sourceMappingURL=BannerItemForm.vue.map */", map: {"version":3,"sources":["D:\\Work\\tager-admin-banners\\src\\views\\BannerItemForm.vue","BannerItemForm.vue"],"names":[],"mappings":"AAmNA;EACA,aAAA;EACA,8BAAA;EACA,mBAAA;AClNA;ADqNA;EACA,gBAAA;AClNA;ADqNA;EACA,aAAA;EACA,mBAAA;AClNA;ADoNA;EACA,gBAAA;EACA,kBAAA;AClNA;;AAEA,6CAA6C","file":"BannerItemForm.vue","sourcesContent":["<template>\n <page\n :title=\"isCreation ? 'Create Banner Item' : 'Update Banner Item'\"\n :is-content-loading=\"isContentLoading\"\n :footer=\"{ onSubmit: submitForm, backHref: bannerItemListUrl }\"\n >\n <template v-slot:content>\n <form novalidate @submit.prevent>\n <form-field\n v-model=\"values.title\"\n name=\"title\"\n label=\"Title\"\n :error=\"errors.title\"\n type=\"textarea\"\n />\n\n <form-field-rich-text-input\n v-model=\"values.text\"\n name=\"text\"\n label=\"Text\"\n :error=\"errors.text\"\n />\n\n <form-field-file-input\n v-model=\"values.image\"\n label=\"Image\"\n name=\"image\"\n file-type=\"image\"\n />\n\n <form-field\n v-model=\"values.buttonLabel\"\n name=\"buttonLabel\"\n label=\"Button: Label\"\n :error=\"errors.buttonLabel\"\n />\n\n <form-field\n v-model=\"values.buttonLink\"\n name=\"buttonLink\"\n label=\"Button: Link\"\n :error=\"errors.buttonLink\"\n />\n\n <form-field-checkbox\n v-model=\"values.buttonIsNewTab\"\n name=\"buttonIsNewTab\"\n label=\"Button: Is new tab?\"\n :error=\"errors.buttonIsNewTab\"\n />\n </form>\n </template>\n </page>\n</template>\n\n<script lang=\"ts\">\nimport Vue from 'vue';\nimport {\n convertRequestErrorToMap,\n FileType,\n Nullable,\n} from '@tager/admin-services';\n\nimport {\n BannerItemCreatePayload,\n createBannerItem,\n getBannerAreaByAlias,\n getBannerItemById,\n updateBannerItem,\n} from '../services/requests';\nimport { BannerArea, BannerItem } from '../typings/model';\nimport { getBannerItemListUrl } from '../constants/paths';\n\ntype FormValues = {\n title: string;\n text: string;\n buttonLink: string;\n buttonLabel: string;\n buttonIsNewTab: boolean;\n image: Nullable<FileType>;\n};\n\nconst INITIAL_VALUES: FormValues = {\n title: '',\n text: '',\n buttonLink: '',\n buttonLabel: '',\n buttonIsNewTab: false,\n image: null,\n};\n\nexport default Vue.extend({\n name: 'BannerItemForm',\n data(): {\n values: FormValues;\n errors: Record<string, string>;\n isContentLoading: boolean;\n bannerArea: Nullable<BannerArea>;\n } {\n return {\n values: { ...INITIAL_VALUES },\n errors: {},\n isContentLoading: false,\n bannerArea: null,\n };\n },\n computed: {\n itemId(): string {\n return this.$route.params.itemId;\n },\n areaAlias(): string {\n return this.$route.params.areaAlias;\n },\n isCreation(): boolean {\n return this.itemId === 'create';\n },\n bannerItemListUrl(): string {\n return getBannerItemListUrl({\n areaAlias: this.bannerArea?.alias ?? 'unknown',\n });\n },\n },\n watch: {\n itemId() {\n this.updateValues();\n },\n areaAlias() {\n this.updateValues();\n },\n },\n mounted(): void {\n this.updateValues();\n },\n methods: {\n updateValues(): void {\n this.isContentLoading = true;\n\n Promise.all([\n getBannerAreaByAlias(this.areaAlias)\n .then((response) => {\n this.bannerArea = response.data;\n })\n .catch(console.error),\n this.isCreation\n ? new Promise((resolve) => {\n this.values = { ...INITIAL_VALUES };\n resolve();\n })\n : getBannerItemById(this.itemId)\n .then((response) => {\n this.values = this.convertReviewToInitialValues(response.data);\n })\n .catch(console.error),\n ]).finally(() => {\n this.isContentLoading = false;\n });\n },\n convertReviewToInitialValues(bannerItem: BannerItem): FormValues {\n return {\n title: bannerItem.title,\n text: bannerItem.text,\n buttonLink: bannerItem.buttonLink ?? '',\n buttonLabel: bannerItem.buttonLabel,\n buttonIsNewTab: bannerItem.buttonIsNewTab,\n image: bannerItem.image,\n };\n },\n submitForm() {\n const creationBody: BannerItemCreatePayload = {\n title: this.values.title,\n text: this.values.text,\n buttonLink: this.values.buttonLink.trim() || null,\n buttonLabel: this.values.buttonLabel,\n buttonIsNewTab: this.values.buttonIsNewTab,\n image: this.values.image?.id ?? null,\n };\n\n const requestPromise = this.isCreation\n ? createBannerItem(this.bannerArea?.id ?? 'unknown', creationBody)\n : updateBannerItem(this.itemId, creationBody);\n\n requestPromise\n .then(() => {\n this.errors = {};\n this.$router.push(this.bannerItemListUrl);\n\n this.$toast({\n variant: 'success',\n title: 'Success',\n body: `Banner item has been successfully ${\n this.isCreation ? 'created' : 'updated'\n }`,\n });\n })\n .catch((error) => {\n console.error(error);\n this.errors = convertRequestErrorToMap(error);\n this.$toast({\n variant: 'danger',\n title: 'Error',\n body: `Banner item ${\n this.isCreation ? 'creation' : 'update'\n } has been failed`,\n });\n });\n },\n },\n});\n</script>\n\n<style scoped lang=\"scss\">\n.bottom {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.save-button {\n min-width: 100px;\n}\n\n.alias-field-inner {\n display: flex;\n align-items: center;\n\n span {\n font-size: 0.9em;\n margin-right: 10px;\n }\n}\n</style>\n",".bottom {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.save-button {\n min-width: 100px;\n}\n\n.alias-field-inner {\n display: flex;\n align-items: center;\n}\n.alias-field-inner span {\n font-size: 0.9em;\n margin-right: 10px;\n}\n\n/*# sourceMappingURL=BannerItemForm.vue.map */"]}, media: undefined });
3525
+ inject("data-v-60ad1218_0", { source: ".date {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n column-gap: 10px;\n}\n\n/*# sourceMappingURL=BannerForm.vue.map */", map: {"version":3,"sources":["/home/runner/work/tager-admin-banners/tager-admin-banners/src/views/Banners/BannerForm/BannerForm.vue","BannerForm.vue"],"names":[],"mappings":"AAsOA;EACA,aAAA;EACA,qCAAA;EACA,gBAAA;ACrOA;;AAEA,yCAAyC","file":"BannerForm.vue","sourcesContent":["<template>\n <page\n :title=\"\n isCreation ? $t('banners:createBanner') : $t('banners:updateBanner')\n \"\n :is-content-loading=\"isContentLoading\"\n >\n <template v-slot:content>\n <form novalidate @submit.prevent=\"submitForm\">\n <form-field-select\n v-model=\"values.bannerZone\"\n name=\"bannerZone\"\n :label=\"$t('banners:zone')\"\n :options=\"zonesOptionList\"\n :error=\"errors.bannerZone\"\n />\n\n <form-field-file-input\n v-model=\"values.image\"\n name=\"image\"\n file-type=\"image\"\n :label=\"$t('banners:image')\"\n :error=\"errors.file\"\n />\n\n <form-field\n v-model=\"values.link\"\n name=\"link\"\n :label=\"$t('banners:link')\"\n :error=\"errors.name\"\n />\n\n <form-field-checkbox\n v-model=\"values.openNewTab\"\n name=\"openNewTab\"\n :label=\"$t('banners:openNewTab')\"\n :error=\"errors.openNewTab\"\n />\n\n <input-label>{{ $t('banners:period') }}</input-label>\n\n <div class=\"date\">\n <form-field\n v-model=\"values.dateStart\"\n :label=\"$t('banners:from')\"\n name=\"dateStart\"\n type=\"date\"\n :max=\"values.dateEnd\"\n />\n\n <form-field\n v-model=\"values.dateEnd\"\n :label=\"$t('banners:to')\"\n name=\"dateEnd\"\n type=\"date\"\n :min=\"values.dateStart\"\n />\n </div>\n\n <form-field-checkbox\n v-model=\"values.disabled\"\n name=\"disabled\"\n :label=\"$t('banners:disabled')\"\n :error=\"errors.disabled\"\n />\n\n <form-field\n v-model=\"values.comment\"\n name=\"comment\"\n type=\"textarea\"\n :label=\"$t('banners:comment')\"\n :error=\"errors.comment\"\n />\n </form>\n </template>\n\n <template v-slot:footer>\n <FormFooter\n :back-href=\"bannerListUrl\"\n :on-submit=\"submitForm\"\n :is-submitting=\"isSubmitting\"\n :is-creation=\"isCreation\"\n :can-create-another=\"isCreation\"\n />\n </template>\n </page>\n</template>\n\n<script lang=\"ts\">\nimport {\n computed,\n defineComponent,\n ref,\n SetupContext,\n watch,\n} from '@vue/composition-api';\n\nimport { FormFooter, OptionType, TagerFormSubmitEvent } from '@tager/admin-ui';\nimport { convertRequestErrorToMap } from '@tager/admin-services';\n\nimport { useFetchZones } from '../../../hooks';\nimport { BannerFormValues } from '../../../typings/banners';\nimport { useFetchBanner } from '../../../hooks/useFetchBanner';\nimport {\n getBannersBannerFormUrl,\n getBannersBannerListUrl,\n} from '../../../constants/paths';\nimport { createBanner, updateBanner } from '../../../services/requests';\n\nimport {\n convertBannerFormValuesToPayload,\n convertBannerToFormValues,\n} from './BannerForm.helpers';\n\nexport default defineComponent({\n name: 'BannerForm',\n components: { FormFooter },\n setup(props, context: SetupContext) {\n const bannerId = computed<string>(\n () => context.root.$route.params.bannerId\n );\n const isCreation = computed<boolean>(() => bannerId.value === 'create');\n\n /** Zones **/\n\n const { data: zones, loading: isZonesLoading } = useFetchZones({ context });\n\n const zonesOptionList = computed<OptionType[]>(() =>\n zones.value.map<OptionType>((zone) => ({\n value: zone.id,\n label: zone.name,\n }))\n );\n\n /** Banner **/\n\n const { data: banner, loading: isBannerLoading } = useFetchBanner({\n context,\n bannerId,\n isCreation,\n });\n\n /** Form State **/\n\n const isSubmitting = ref<boolean>(false);\n const values = ref<BannerFormValues>(\n convertBannerToFormValues(banner.value, zonesOptionList.value)\n );\n const errors = ref<Record<string, string>>({});\n\n watch([banner, zones], () => {\n values.value = convertBannerToFormValues(\n banner.value,\n zonesOptionList.value\n );\n });\n\n const submitForm = (event: TagerFormSubmitEvent) => {\n isSubmitting.value = true;\n\n const body = convertBannerFormValuesToPayload(values.value);\n\n const requestPromise = isCreation.value\n ? createBanner(body)\n : updateBanner(bannerId.value, body);\n\n requestPromise\n .then(({ data }) => {\n errors.value = {};\n\n if (event.type === 'create') {\n context.root.$router.push(\n getBannersBannerFormUrl({ bannerId: String(data.id) })\n );\n }\n\n if (event.type === 'create_exit' || event.type === 'save_exit') {\n context.root.$router.push(getBannersBannerListUrl());\n }\n\n if (event.type === 'create_create-another') {\n values.value = convertBannerToFormValues(\n null,\n zonesOptionList.value\n );\n }\n\n context.root.$toast({\n variant: 'success',\n title: context.root.$t('banners:success'),\n body: isCreation.value\n ? context.root.$t('banners:bannerWasSuccessfullyCreated')\n : context.root.$t('banners:bannerWasSuccessfullyUpdated'),\n });\n })\n .catch((error) => {\n console.error(error);\n errors.value = convertRequestErrorToMap(error);\n context.root.$toast({\n variant: 'danger',\n title: context.root.$t('banners:error'),\n body: isCreation.value\n ? context.root.$t('banners:bannerCreationWasFailed')\n : context.root.$t('banners:bannerUpdateWasFailed'),\n });\n })\n .finally(() => {\n isSubmitting.value = false;\n });\n };\n\n const isContentLoading = computed<boolean>(\n () => isBannerLoading.value || isZonesLoading.value\n );\n\n return {\n isCreation,\n isContentLoading,\n isSubmitting,\n values,\n errors,\n submitForm,\n bannerListUrl: getBannersBannerListUrl(),\n zonesOptionList,\n };\n },\n});\n</script>\n\n<style lang=\"scss\">\n.date {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n column-gap: 10px;\n}\n</style>\n",".date {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n column-gap: 10px;\n}\n\n/*# sourceMappingURL=BannerForm.vue.map */"]}, media: undefined });
1191
3526
 
1192
3527
  };
1193
3528
  /* scoped */
1194
- const __vue_scope_id__$3 = "data-v-2ed0e9d3";
3529
+ const __vue_scope_id__$2 = undefined;
1195
3530
  /* module identifier */
1196
- const __vue_module_identifier__$3 = undefined;
3531
+ const __vue_module_identifier__$2 = undefined;
1197
3532
  /* functional template */
1198
- const __vue_is_functional_template__$3 = false;
3533
+ const __vue_is_functional_template__$2 = false;
1199
3534
  /* style inject SSR */
1200
3535
 
1201
3536
  /* style inject shadow dom */
1202
3537
 
1203
3538
 
1204
3539
 
1205
- const __vue_component__$3 = /*#__PURE__*/normalizeComponent(
1206
- { render: __vue_render__$3, staticRenderFns: __vue_staticRenderFns__$3 },
1207
- __vue_inject_styles__$3,
1208
- __vue_script__$3,
1209
- __vue_scope_id__$3,
1210
- __vue_is_functional_template__$3,
1211
- __vue_module_identifier__$3,
3540
+ const __vue_component__$2 = /*#__PURE__*/normalizeComponent(
3541
+ { render: __vue_render__$2, staticRenderFns: __vue_staticRenderFns__$2 },
3542
+ __vue_inject_styles__$2,
3543
+ __vue_script__$2,
3544
+ __vue_scope_id__$2,
3545
+ __vue_is_functional_template__$2,
3546
+ __vue_module_identifier__$2,
1212
3547
  false,
1213
3548
  createInjector,
1214
3549
  undefined,
1215
3550
  undefined
1216
3551
  );
1217
3552
 
1218
- const HOME_BREADCRUMB = { url: '/', text: 'Home' };
1219
- const BANNER_AREA_LIST_ROUTE = {
1220
- path: BANNER_ROUTE_PATHS.AREA_LIST,
3553
+ const BANNERS_ZONE_LIST_ROUTE = {
3554
+ path: BANNERS_ROUTE_PATHS.ZONE_LIST,
1221
3555
  component: __vue_component__,
1222
- name: 'Banner Area List',
3556
+ name: 'Zones',
1223
3557
  meta: {
1224
- getBreadcrumbs: (route) => {
1225
- var _a;
1226
- return [
1227
- HOME_BREADCRUMB,
1228
- { url: route.path, text: (_a = route.name) !== null && _a !== void 0 ? _a : '' },
1229
- ];
1230
- },
3558
+ getBreadcrumbs: (route, t) => [
3559
+ { url: '/', text: t('banners:home') },
3560
+ { url: BANNERS_ROUTE_PATHS.ZONE_LIST, text: t('banners:zones') },
3561
+ ],
1231
3562
  },
1232
3563
  };
1233
- const BANNER_AREA_FORM_ROUTE = {
1234
- path: BANNER_ROUTE_PATHS.AREA_FORM,
3564
+ const BANNERS_BANNER_LIST_ROUTE = {
3565
+ path: BANNERS_ROUTE_PATHS.BANNER_LIST,
1235
3566
  component: __vue_component__$1,
1236
- name: 'Banner Area Form',
3567
+ name: 'Banners',
1237
3568
  meta: {
1238
- getBreadcrumbs: (route) => {
1239
- var _a, _b;
1240
- return [
1241
- HOME_BREADCRUMB,
1242
- {
1243
- url: BANNER_ROUTE_PATHS.AREA_LIST,
1244
- text: (_a = BANNER_AREA_LIST_ROUTE.name) !== null && _a !== void 0 ? _a : '',
1245
- },
1246
- { url: route.path, text: (_b = route.name) !== null && _b !== void 0 ? _b : '' },
1247
- ];
1248
- },
3569
+ getBreadcrumbs: (route, t) => [
3570
+ { url: '/', text: t('banners:home') },
3571
+ { url: BANNERS_ROUTE_PATHS.BANNER_LIST, text: t('banners:banners') },
3572
+ ],
1249
3573
  },
1250
3574
  };
1251
- const BANNER_ITEM_LIST_ROUTE = {
1252
- path: BANNER_ROUTE_PATHS.ITEM_LIST,
3575
+ const BANNERS_BANNER_FORM_ROUTE = {
3576
+ path: BANNERS_ROUTE_PATHS.BANNER_FORM,
1253
3577
  component: __vue_component__$2,
1254
- name: 'Banner Item List',
3578
+ name: 'Banner Form',
1255
3579
  meta: {
1256
- getBreadcrumbs: (route) => {
1257
- var _a;
1258
- return [
1259
- HOME_BREADCRUMB,
1260
- { url: route.path, text: (_a = route.name) !== null && _a !== void 0 ? _a : '' },
1261
- ];
1262
- },
1263
- },
1264
- };
1265
- const BANNER_ITEM_FORM_ROUTE = {
1266
- path: BANNER_ROUTE_PATHS.ITEM_FORM,
1267
- component: __vue_component__$3,
1268
- name: 'Banner Item Form',
1269
- meta: {
1270
- getBreadcrumbs: (route) => {
1271
- var _a, _b;
1272
- return [
1273
- HOME_BREADCRUMB,
1274
- {
1275
- url: getBannerItemListUrl({ areaAlias: route.params.areaAlias }),
1276
- text: (_a = BANNER_ITEM_LIST_ROUTE.name) !== null && _a !== void 0 ? _a : '',
1277
- },
1278
- { url: route.path, text: (_b = route.name) !== null && _b !== void 0 ? _b : '' },
1279
- ];
1280
- },
3580
+ getBreadcrumbs: (route, t) => [
3581
+ { url: '/', text: t('banners:home') },
3582
+ { url: BANNERS_ROUTE_PATHS.BANNER_LIST, text: t('banners:banners') },
3583
+ { url: route.path, text: t('banners:bannerForm') },
3584
+ ],
1281
3585
  },
1282
3586
  };
1283
3587
 
1284
- const BANNER_MENU_ITEM = {
1285
- id: 'banner',
1286
- text: 'Banners',
1287
- icon: 'viewList',
1288
- children: [
1289
- { text: 'Banner areas', url: '/banners' },
1290
- { text: 'Create banner area', url: '/banners/create' },
1291
- ],
1292
- };
3588
+ function getBannersMenuItem(params) {
3589
+ return {
3590
+ id: 'banners',
3591
+ text: params.t('banners:banners'),
3592
+ icon: 'viewList',
3593
+ children: [
3594
+ { text: params.t('banners:zones'), url: getBannersZoneListUrl() },
3595
+ { text: params.t('banners:banners'), url: getBannersBannerListUrl() },
3596
+ {
3597
+ text: params.t('banners:createBanner'),
3598
+ url: getBannersBannerFormUrl({ bannerId: 'create' }),
3599
+ },
3600
+ ],
3601
+ };
3602
+ }
3603
+
3604
+ i18n.addTranslations('en', 'blog', EN);
3605
+ i18n.addTranslations('ru', 'blog', RU);
1293
3606
 
1294
- export { BANNER_AREA_FORM_ROUTE, BANNER_AREA_LIST_ROUTE, BANNER_ITEM_FORM_ROUTE, BANNER_ITEM_LIST_ROUTE, BANNER_MENU_ITEM, BANNER_ROUTE_PATHS, getBannerAreaFormUrl, getBannerAreaListUrl, getBannerItemFormUrl, getBannerItemListUrl };
3607
+ export { BANNERS_BANNER_FORM_ROUTE, BANNERS_BANNER_LIST_ROUTE, BANNERS_ROUTE_PATHS, BANNERS_ZONE_LIST_ROUTE, createBanner, deleteBanner, getBanner, getBanners, getBannersBannerFormUrl, getBannersBannerListUrl, getBannersMenuItem, getBannersZoneListUrl, getZones, updateBanner };