@hashtagcms/admin-ui-kit 1.0.6

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 (79) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +83 -0
  3. package/dist/admin-ui-kit.min.css +14 -0
  4. package/dist/admin-ui-kit.min.js +2 -0
  5. package/dist/admin-ui-kit.min.js.LICENSE.txt +175 -0
  6. package/package.json +53 -0
  7. package/packages/components/README.md +92 -0
  8. package/packages/components/package.json +28 -0
  9. package/packages/components/src/action-bar.vue +237 -0
  10. package/packages/components/src/category-platform.vue +97 -0
  11. package/packages/components/src/category-settings.vue +815 -0
  12. package/packages/components/src/cms-module-dropdown.vue +78 -0
  13. package/packages/components/src/downlods.vue +21 -0
  14. package/packages/components/src/file-uploader.vue +188 -0
  15. package/packages/components/src/frontend-module-creator.vue +599 -0
  16. package/packages/components/src/global-site-button.vue +94 -0
  17. package/packages/components/src/homepage.vue +1087 -0
  18. package/packages/components/src/html-slot.vue +23 -0
  19. package/packages/components/src/image-gallery.vue +144 -0
  20. package/packages/components/src/index.js +53 -0
  21. package/packages/components/src/info-boxes.vue +68 -0
  22. package/packages/components/src/info-popup.vue +121 -0
  23. package/packages/components/src/language-button.vue +80 -0
  24. package/packages/components/src/language-copier.vue +177 -0
  25. package/packages/components/src/left-nav.vue +159 -0
  26. package/packages/components/src/library/copy-paste.vue +186 -0
  27. package/packages/components/src/library/info-box.vue +102 -0
  28. package/packages/components/src/library/left-menu-show-hide.vue +47 -0
  29. package/packages/components/src/library/loader.vue +141 -0
  30. package/packages/components/src/library/modal-box.vue +136 -0
  31. package/packages/components/src/library/split-button.vue +127 -0
  32. package/packages/components/src/library/timer-button.vue +43 -0
  33. package/packages/components/src/library/toast-box.vue +53 -0
  34. package/packages/components/src/menu-sorter.vue +265 -0
  35. package/packages/components/src/module-creator.vue +650 -0
  36. package/packages/components/src/module-permission.vue +334 -0
  37. package/packages/components/src/pagination.vue +125 -0
  38. package/packages/components/src/platform-button.vue +118 -0
  39. package/packages/components/src/search-bar.vue +144 -0
  40. package/packages/components/src/site-button.vue +42 -0
  41. package/packages/components/src/site-cloner.vue +150 -0
  42. package/packages/components/src/sitewise-copier.vue +234 -0
  43. package/packages/components/src/sitewise-data.vue +347 -0
  44. package/packages/components/src/sorter.vue +239 -0
  45. package/packages/components/src/tabular-view.vue +824 -0
  46. package/packages/components/src/title-bar.vue +76 -0
  47. package/packages/components/src/top-nav.vue +96 -0
  48. package/packages/helpers/README.md +88 -0
  49. package/packages/helpers/package.json +20 -0
  50. package/packages/helpers/src/admin-config.js +9 -0
  51. package/packages/helpers/src/common.js +89 -0
  52. package/packages/helpers/src/dashboard.js +16 -0
  53. package/packages/helpers/src/editor.js +163 -0
  54. package/packages/helpers/src/error-message-handler.js +50 -0
  55. package/packages/helpers/src/event-bus.js +4 -0
  56. package/packages/helpers/src/form.js +4 -0
  57. package/packages/helpers/src/fx.js +106 -0
  58. package/packages/helpers/src/humanize.js +14 -0
  59. package/packages/helpers/src/map.js +3 -0
  60. package/packages/styles/README.md +37 -0
  61. package/packages/styles/package.json +15 -0
  62. package/packages/styles/src/_action-bar.scss +35 -0
  63. package/packages/styles/src/_admin.scss +22 -0
  64. package/packages/styles/src/_animate.scss +1579 -0
  65. package/packages/styles/src/_badges.scss +34 -0
  66. package/packages/styles/src/_category-list.scss +14 -0
  67. package/packages/styles/src/_common.scss +163 -0
  68. package/packages/styles/src/_info-box.scss +96 -0
  69. package/packages/styles/src/_left-nav.scss +59 -0
  70. package/packages/styles/src/_loader.scss +82 -0
  71. package/packages/styles/src/_menu-sorter.scss +39 -0
  72. package/packages/styles/src/_model-creator.scss +48 -0
  73. package/packages/styles/src/_module-permission.scss +25 -0
  74. package/packages/styles/src/_page-manager.scss +63 -0
  75. package/packages/styles/src/_popover-modal.scss +20 -0
  76. package/packages/styles/src/_table-grid.scss +39 -0
  77. package/packages/styles/src/_toast.scss +20 -0
  78. package/packages/styles/src/_variables.scss +37 -0
  79. package/packages/styles/src/app.scss +2 -0
@@ -0,0 +1,1087 @@
1
+ <template>
2
+ <div class="row mt-2 pb-2 border-bottom">
3
+ <div v-show="hasMicrosites" class="col-auto">
4
+ <select
5
+ v-model="microSiteId"
6
+ class="form-select select"
7
+ @change="fetchNewData()"
8
+ >
9
+ <option value="0">Select a MicroSite</option>
10
+ <option v-for="microsite in microsites" :value="microsite.id">
11
+ {{ microsite.name }}
12
+ </option>
13
+ </select>
14
+ </div>
15
+ <div class="col-auto">
16
+ <select
17
+ v-model="categoryId"
18
+ class="form-select select"
19
+ @change="fetchNewData()"
20
+ >
21
+ <option>Select a Category</option>
22
+ <option v-for="category in categories" :value="category.category_id">
23
+ {{ category.name }}
24
+ </option>
25
+ </select>
26
+ </div>
27
+ <div class="col-auto">
28
+ <select
29
+ v-show="hasPlatformMoreThanOne"
30
+ v-model="platformId"
31
+ class="form-select select"
32
+ @change="fetchNewData()"
33
+ >
34
+ <option>Select a Platform</option>
35
+ <option v-for="platform in platforms" :value="platform.id">
36
+ {{ platform.name }}
37
+ </option>
38
+ </select>
39
+ </div>
40
+ <div class="col-auto" v-show="hasTheme">
41
+ <span
42
+ class="hand"
43
+ title="Click to see theme info"
44
+ @click="showInfo('theme', themeInfo.id)"
45
+ >Theme: <u>{{ themeInfo.name }}</u></span
46
+ >
47
+ </div>
48
+ <div class="col d-flex justify-content-end">
49
+ <div v-if="hasTheme" class="btn-group">
50
+ <button
51
+ v-if="canDelete"
52
+ aria-label="Delete All Modules form this category"
53
+ class="btn btn-danger"
54
+ title="Delete All Modules form this category"
55
+ type="button"
56
+ @click="showHideDeleteAlert(true)"
57
+ >
58
+ <span aria-hidden="true" class="fa fa-trash-o"></span>
59
+ </button>
60
+ <button
61
+ aria-label="Copy Data From"
62
+ class="btn btn-outline-secondary"
63
+ title="Copy Data From"
64
+ type="button"
65
+ @click="showHideCopyAlert(true)"
66
+ >
67
+ <span aria-hidden="true" class="fa fa-copy"></span>
68
+ </button>
69
+ </div>
70
+ </div>
71
+ </div>
72
+ <div class="row mt-3" v-if="hasError">
73
+ <div class="col left-zero">
74
+ <div class="alert alert-danger col-md-8">
75
+ <ul>
76
+ <li v-for="error in errors" v-html="error.message"></li>
77
+ </ul>
78
+ </div>
79
+ </div>
80
+ </div>
81
+ <div class="row mt-3">
82
+ <div class="col col-9">
83
+ <div class="row homepage-modules">
84
+ <div v-for="hook in hooks" :ref="'panel_' + hook.info.id" class="col-4">
85
+ <div class="non-selectable shadow-sm card mb-3">
86
+ <div
87
+ class="card-header hook-header"
88
+ @dblclick="showHideHookPanel(hook.info.id)"
89
+ >
90
+ <span class="pull-right small"
91
+ ><span
92
+ :class="'fa hand fa-expand'"
93
+ title="Expand/Contract"
94
+ @click="onlyMe(hook.info.id, $event)"
95
+ ></span>
96
+ &nbsp;<span
97
+ class="fa fa-minus hand"
98
+ title="Minimize/Maximize"
99
+ @click="showHideHookPanel(hook.info.id)"
100
+ ></span
101
+ ></span>
102
+ <a
103
+ href="javascript:void(0)"
104
+ @click="showInfo('hook', hook.info.id)"
105
+ >
106
+ {{ hook.info.name }}</a
107
+ >
108
+ </div>
109
+ <div
110
+ :ref="'hook_panel_' + hook.info.id"
111
+ class="card-body hook_modules js_modules"
112
+ >
113
+ <ul
114
+ :data-hook-id="hook.info.id"
115
+ class="list-group list-group-flush modules-list js_modules js_hook_modules"
116
+ >
117
+ <template v-if="hook.modules.length > 0">
118
+ <li
119
+ v-for="module in hook.modules"
120
+ :data-module-id="module.id"
121
+ class="js_item"
122
+ >
123
+ <a
124
+ href="javascript:void(0)"
125
+ @click="showInfo('module', module.id)"
126
+ >{{ module.name }}</a
127
+ >
128
+ <span
129
+ v-if="canDelete"
130
+ :data-hook-id="hook.info.id"
131
+ class="js_delete delete hand pull-right fa fa-trash-o"
132
+ title="Delete this module from the hook"
133
+ ></span>
134
+ </li>
135
+ </template>
136
+ </ul>
137
+ </div>
138
+ <div
139
+ class="card-footer bg-gradient border-light"
140
+ v-if="hasAnyModulesInAHook(hook) && canDelete"
141
+ >
142
+ <span
143
+ @click="deleteAllModuleFromHook(hook.info.id)"
144
+ class="js_delete_from_hook hand pull-right fa fa-trash-o"
145
+ title="Delete all module from this hook"
146
+ :data-hook-id="hook.info.id"
147
+ ></span>
148
+ </div>
149
+ </div>
150
+ </div>
151
+ <div v-if="hasTheme" ref="savePanel" class="clearboth text-center pt-5">
152
+ <button :class="saveButtonCss" type="button" @click="saveModules()">
153
+ Save Now!
154
+ </button>
155
+ </div>
156
+ </div>
157
+ </div>
158
+ <div class="col col-3" v-if="!hasError">
159
+ <div class="panel-sub-heading">
160
+ <div class="input-group">
161
+ <input
162
+ v-model="searchKey"
163
+ aria-describedby="basic-addon3"
164
+ class="form-control"
165
+ placeholder="Search by id, name or alias"
166
+ type="text"
167
+ />
168
+ </div>
169
+ </div>
170
+ <ul id="draggableModules" class="modules-list all-modules-right">
171
+ <li
172
+ v-for="module in filterModules"
173
+ :data-module-id="module.id"
174
+ class="js_item"
175
+ >
176
+ <span v-html="module.name"></span>
177
+ <span class="delete hand pull-right fa fa-trash-o"></span>
178
+ </li>
179
+ </ul>
180
+ </div>
181
+ </div>
182
+
183
+ <modal-box ref="copyBox" data-show-footer="true" :data-modal-css="modalCss">
184
+ <template #title> Copy Data </template>
185
+ <template #content>
186
+ <div class="row">
187
+ <div class="col-1 p-1">
188
+ <label class="col-md-3 d-flex">From:</label>
189
+ </div>
190
+ <div class="col-auto p-1" v-if="hasSiteMoreThanOne">
191
+ <select v-model="fromData.site_id" class="form-select select-sm">
192
+ <option value="0">Select a MicroSite</option>
193
+ <option v-for="site in allSites" :value="site.id">
194
+ {{ site.name }}
195
+ </option>
196
+ </select>
197
+ </div>
198
+ <div class="col-auto p-1" v-if="hasMicrosites">
199
+ <select v-model="fromData.microsite_id" class="form-select select-sm">
200
+ <option value="0">Select a Microsite</option>
201
+ <option v-for="microsite in microsites" :value="microsite.id">
202
+ {{ microsite.name }}
203
+ </option>
204
+ </select>
205
+ </div>
206
+ <div class="col-auto p-1" v-if="hasPlatformMoreThanOne">
207
+ <select v-model="fromData.platform_id" class="form-select select-sm">
208
+ <option value="0">Select a Platform</option>
209
+ <option v-for="platform in platforms" :value="platform.id">
210
+ {{ platform.name }}
211
+ </option>
212
+ </select>
213
+ </div>
214
+ <div class="col-auto p-1">
215
+ <select class="form-select select-sm" v-model="fromData.category_id">
216
+ <option value="0">Select a Category</option>
217
+ <option
218
+ v-for="category in fromCategories"
219
+ :value="category.category_id"
220
+ >
221
+ {{ category.name }}
222
+ </option>
223
+ </select>
224
+ </div>
225
+ </div>
226
+ <div class="row mt-2">
227
+ <div class="col-1 p-1">
228
+ <label class="col-md-3 d-flex">To:</label>
229
+ </div>
230
+ <div class="col-auto p-1" v-if="hasSiteMoreThanOne">
231
+ <select v-model="toData.site_id" class="form-select select-sm">
232
+ <option value="0">Select a MicroSite</option>
233
+ <option v-for="site in allSites" :value="site.id">
234
+ {{ site.name }}
235
+ </option>
236
+ </select>
237
+ </div>
238
+ <div class="col-auto p-1" v-if="hasMicrosites">
239
+ <select v-model="toData.microsite_id" class="form-select select-sm">
240
+ <option value="0">Select a MicroSite</option>
241
+ <option v-for="microsite in microsites" :value="microsite.id">
242
+ {{ microsite.name }}
243
+ </option>
244
+ </select>
245
+ </div>
246
+ <div class="col-auto p-1" v-if="hasPlatformMoreThanOne">
247
+ <select v-model="toData.platform_id" class="form-select select-sm">
248
+ <option value="0">Select a Platform</option>
249
+ <option v-for="platform in platforms" :value="platform.id">
250
+ {{ platform.name }}
251
+ </option>
252
+ </select>
253
+ </div>
254
+ <div class="col-auto p-1">
255
+ <select v-model="toData.category_id" class="form-select select-sm">
256
+ <option value="0">Select a Category</option>
257
+ <option
258
+ v-for="category in toCategories"
259
+ :value="category.category_id"
260
+ >
261
+ {{ category.name }}
262
+ </option>
263
+ </select>
264
+ </div>
265
+ </div>
266
+ <div class="row">
267
+ <div v-show="hasPlatformMoreThanOne" class="plr5 v-space">
268
+ <div class="alert alert-info">
269
+ Please do not select <strong>source platform</strong> if you want to
270
+ copy modules in all platforms respectively.
271
+ </div>
272
+ </div>
273
+ </div>
274
+ </template>
275
+ <template #footer class="center-align">
276
+ <div v-show="isWorking" class="loader">
277
+ Please wait... <span class="fa fa-loader"></span>
278
+ </div>
279
+ <button
280
+ class="btn btn-success btn-from-submit"
281
+ @click="copyDataFromCategory()"
282
+ >
283
+ Copy Now
284
+ </button>
285
+ <button
286
+ class="btn btn-outline-secondary"
287
+ @click="showHideCopyAlert(false)"
288
+ >
289
+ Cancel
290
+ </button>
291
+ </template>
292
+ </modal-box>
293
+
294
+ <modal-box
295
+ ref="deleteBox"
296
+ data-show-footer="true"
297
+ data-title-css="alert-danger"
298
+ >
299
+ <template #title> Warning!!! </template>
300
+ <template #content>
301
+ <span class="text-danger"
302
+ >Are you sure to delete all modules from this category? Can't be
303
+ undone.</span
304
+ >
305
+ <div>
306
+ <label
307
+ v-show="hasPlatformMoreThanOne"
308
+ class="p-2"
309
+ title="Delete from other platforms too"
310
+ >
311
+ <input v-model="applicableForAllPlatforms" type="checkbox" /> Delete
312
+ from other platforms too</label
313
+ >
314
+ </div>
315
+ </template>
316
+ <template #footer class="center-align">
317
+ <button class="btn btn-danger" @click="deleteAllFromCategory()">
318
+ Yes
319
+ </button>
320
+ <button
321
+ class="btn btn-outline-secondary"
322
+ @click="showHideDeleteAlert(false)"
323
+ >
324
+ No
325
+ </button>
326
+ </template>
327
+ </modal-box>
328
+
329
+ <info-popup ref="infoPopup"></info-popup>
330
+ </template>
331
+
332
+ <script>
333
+ import AdminConfig from "@hashtagcms/helpers/admin-config";
334
+
335
+ import { Toast, Modal, Loader } from "@hashtagcms/helpers/common";
336
+ import Sortable from "sortablejs";
337
+ import InfoPopup from "./info-popup.vue";
338
+ import ModalBox from "./library/modal-box.vue";
339
+
340
+ export default {
341
+ components: {
342
+ "info-popup": InfoPopup,
343
+ "modal-box": ModalBox,
344
+ },
345
+ mounted() {
346
+ /*console.log("siteInfo", this.siteInfo);
347
+ console.log("allModules", this.allModules);
348
+ console.log("categoryModules", this.categoryModules);
349
+ console.log("categoryInfo", this.categoryInfo);
350
+ console.log("themeInfo", this.themeInfo);
351
+ */
352
+
353
+ this.init();
354
+ },
355
+ created() {
356
+ //this.initData();
357
+ },
358
+
359
+ props: [
360
+ "dataCategories",
361
+ "dataMicrosites",
362
+ "dataPlatforms",
363
+ "dataSiteId",
364
+ "dataMicrositeId",
365
+ "dataCategoryId",
366
+ "dataPlatformId",
367
+ "dataSiteInfo",
368
+ "dataHookInfo",
369
+ "dataAllModules",
370
+ "dataCategoryModules",
371
+ "dataCategoryInfo",
372
+ "dataThemeInfo",
373
+ "dataUserRights",
374
+ "dataIsModuleReadonly",
375
+ "dataAllSites",
376
+ ],
377
+ computed: {
378
+ hasSiteMoreThanOne() {
379
+ //return true;
380
+ return this.allSites.length > 1;
381
+ },
382
+ hasMicrosites() {
383
+ //return true;
384
+ return this.microsites.length > 0;
385
+ },
386
+ hasPlatformMoreThanOne() {
387
+ //return true;
388
+ return this.platforms.length > 1;
389
+ },
390
+ hasTheme() {
391
+ return this.themeInfo && this.themeInfo["id"];
392
+ },
393
+ saveButtonCss() {
394
+ let disabled = this.enableDisableSave() === true ? "" : " disabled";
395
+ return "btn btn-success btn-form-submit" + disabled;
396
+ },
397
+ canEdit() {
398
+ return (
399
+ this.userRights.indexOf("edit") >= 0 && this.isModuleReadonly === false
400
+ );
401
+ },
402
+ canDelete() {
403
+ return (
404
+ this.userRights.indexOf("delete") >= 0 &&
405
+ this.isModuleReadonly === false
406
+ );
407
+ },
408
+ modalCss() {
409
+ /* if (this.hasSiteMoreThanOne && this.hasPlatformMoreThanOne) {
410
+ return "modal-lg";
411
+ }*/
412
+ return "modal-lg";
413
+ },
414
+ fromCategories() {
415
+ return this.categoriesData[this.fromData.site_id] || [];
416
+ },
417
+ toCategories() {
418
+ return this.categoriesData[this.toData.site_id] || [];
419
+ },
420
+ hasError() {
421
+ return this.errors.length > 0;
422
+ },
423
+ filterModules() {
424
+ let key = this.searchKey;
425
+ if (key !== "" && key != null) {
426
+ key = key.toLowerCase();
427
+ return this.allModules.filter((current) => {
428
+ let alias = current.alias.toLowerCase();
429
+ let name = current.name.toLowerCase();
430
+ let id = current.id;
431
+ if (
432
+ id.toString() === key ||
433
+ alias.includes(key) ||
434
+ name.includes(key)
435
+ ) {
436
+ return true;
437
+ }
438
+ });
439
+ } else {
440
+ this.searchKey = "";
441
+ // console.log("data", this.allData.data);
442
+ return this.allModules;
443
+ }
444
+ },
445
+ },
446
+ data() {
447
+ return {
448
+ categoriesData: {},
449
+ categories:
450
+ typeof this.dataCategories == "undefined" || this.dataCategories === ""
451
+ ? []
452
+ : JSON.parse(this.dataCategories),
453
+ microsites:
454
+ typeof this.dataMicrosites == "undefined" || this.dataMicrosites === ""
455
+ ? []
456
+ : JSON.parse(this.dataMicrosites),
457
+ platforms:
458
+ typeof this.dataPlatforms == "undefined" || this.dataPlatforms === ""
459
+ ? []
460
+ : JSON.parse(this.dataPlatforms),
461
+ siteId:
462
+ typeof this.dataSiteId == "undefined" || this.dataSiteId === ""
463
+ ? 1
464
+ : parseInt(this.dataSiteId),
465
+ microSiteId:
466
+ typeof this.dataMicrositeId == "undefined" ||
467
+ this.dataMicrositeId === ""
468
+ ? 0
469
+ : parseInt(this.dataMicrositeId),
470
+ platformId:
471
+ typeof this.dataPlatformId == "undefined" || this.dataPlatformId === ""
472
+ ? 1
473
+ : parseInt(this.dataPlatformId),
474
+ categoryId:
475
+ typeof this.dataCategoryId == "undefined" || this.dataCategoryId === ""
476
+ ? 0
477
+ : parseInt(this.dataCategoryId),
478
+ siteInfo:
479
+ typeof this.dataSiteInfo == "undefined" || this.dataSiteInfo === ""
480
+ ? []
481
+ : JSON.parse(this.dataSiteInfo),
482
+ hookInfo:
483
+ typeof this.dataHookInfo == "undefined" || this.dataHookInfo === ""
484
+ ? []
485
+ : JSON.parse(this.dataHookInfo),
486
+ allModules:
487
+ typeof this.dataAllModules == "undefined" || this.dataAllModules === ""
488
+ ? []
489
+ : JSON.parse(this.dataAllModules),
490
+ categoryModules:
491
+ typeof this.dataCategoryModules == "undefined" ||
492
+ this.dataCategoryModules === ""
493
+ ? []
494
+ : JSON.parse(this.dataCategoryModules),
495
+ categoryInfo:
496
+ typeof this.dataCategoryInfo == "undefined" ||
497
+ this.dataCategoryInfo === ""
498
+ ? []
499
+ : JSON.parse(this.dataCategoryInfo),
500
+ themeInfo:
501
+ typeof this.dataThemeInfo == "undefined" || this.dataThemeInfo === ""
502
+ ? []
503
+ : JSON.parse(this.dataThemeInfo),
504
+ hooks: [],
505
+ hooksInfoCache: {},
506
+ moduleInfoCache: {},
507
+ noHookFound: false,
508
+ errors: [],
509
+ enableSave: false,
510
+ searchKey: "",
511
+ applicableForAllPlatforms: false,
512
+ fromData: { site_id: 0, microsite_id: 0, platform_id: 0, category_id: 0 },
513
+ toData: { site_id: 0, microsite_id: 0, platform_id: 0, category_id: 0 },
514
+ isWorking: false,
515
+ sortObj: { draggable: null },
516
+ userRights: this.dataUserRights ? JSON.parse(this.dataUserRights) : [],
517
+ isModuleReadonly: this.dataIsModuleReadonly === "1" ? true : false,
518
+ allSites:
519
+ typeof this.dataAllSites == "undefined" || this.dataAllSites === ""
520
+ ? []
521
+ : JSON.parse(this.dataAllSites),
522
+ copyForAllPlatforms: false,
523
+ };
524
+ },
525
+ methods: {
526
+ init() {
527
+ if (this.categories.length === 0) {
528
+ this.addErrorMessage("No category found!");
529
+ }
530
+ if (this.categoryInfo.length === 0) {
531
+ this.addErrorMessage(
532
+ "There is a mismatch in site default category. Please fix that.",
533
+ );
534
+ }
535
+ //console.log('this.themeInfo["id"] ', this.themeInfo["id"])
536
+ if (this.hasTheme) {
537
+ this.parseTheme();
538
+ this.populateModules();
539
+ this.enableSorting();
540
+ this.makeCategories();
541
+ } else {
542
+ let path = AdminConfig.admin_path("category/settings", {
543
+ platform_id: this.platformId,
544
+ });
545
+ this
546
+ .addErrorMessage(`This category/platform/theme is not available in category_site table.
547
+ You need to drag and drop in <a href='${path}'>category settings</a>.`);
548
+ this.addErrorMessage(`Dont' forget the set the theme there.`);
549
+ }
550
+ },
551
+ makeCategories() {
552
+ let totalSites = this.allSites.length;
553
+ if (totalSites > 0) {
554
+ for (let i = 0; i < totalSites; i++) {
555
+ let current = this.allSites[i];
556
+ this.categoriesData[current.id] = current.category;
557
+ }
558
+ }
559
+ this.setDefaultFromTo();
560
+ },
561
+ setDefaultFromTo() {
562
+ let totalSites = this.allSites.length;
563
+ if (totalSites > 0) {
564
+ this.fromData.site_id = this.allSites[0].id;
565
+ this.toData.site_id = this.siteId; //current site id
566
+ } else {
567
+ this.fromData.site_id = this.siteId; //current site
568
+ this.toData.site_id = this.siteId;
569
+ }
570
+
571
+ this.fromData.platform_id = this.platformId;
572
+ this.toData.platform_id = this.platformId;
573
+ this.toData.category_id = this.categoryId;
574
+ },
575
+ saveNow(url, data) {
576
+ Loader.show(this);
577
+ return new Promise((resolve, reject) => {
578
+ axios
579
+ .post(url, data)
580
+ .then((response) => {
581
+ resolve(response);
582
+ })
583
+ .catch((error) => {
584
+ reject(error.response);
585
+ })
586
+ .finally(() => {
587
+ Loader.hide(this);
588
+ });
589
+ });
590
+ },
591
+ getWhere() {
592
+ let where = {
593
+ site_id: this.siteId,
594
+ microsite_id: this.microSiteId,
595
+ platform_id: this.platformId,
596
+ category_id: this.categoryId,
597
+ };
598
+ return where;
599
+ },
600
+ saveModules() {
601
+ if (this.enableDisableSave() === false) {
602
+ return false;
603
+ }
604
+ //Save in DB
605
+ let $this = this;
606
+ //let currentData = (action == "add") ? this.allData.data : this.siteData;
607
+ let postParams = {};
608
+
609
+ //loop through all hooks
610
+ let allHooks = document.querySelectorAll(".js_hook_modules");
611
+ let datas = [];
612
+ allHooks.forEach(function (current) {
613
+ let allModules = current.querySelectorAll("li.js_item");
614
+ let hook_id = current.getAttribute("data-hook-id");
615
+ //console.log("hook_id: ", hook_id, allModules, allModules.length);
616
+ if (allModules.length > 0) {
617
+ let modules = [];
618
+ for (let i = 0; i < allModules.length; i++) {
619
+ //console.log(allModules[i]);
620
+ let currentModule = allModules[i];
621
+ let module_id = currentModule.getAttribute("data-module-id");
622
+ modules.push({ module_id: module_id, position: i + 1 });
623
+ }
624
+
625
+ let data = { hook_id: hook_id, modules: modules };
626
+ datas.push(data);
627
+ }
628
+ //console.log(datas);
629
+ });
630
+
631
+ if (datas.length > 0) {
632
+ let where = $this.getWhere();
633
+ postParams.data = datas;
634
+ postParams.where = where;
635
+ postParams.applicableForAllPlatforms = false;
636
+ this.saveNow(
637
+ AdminConfig.admin_path("homepage/saveSettings"),
638
+ postParams,
639
+ )
640
+ .then(function (res) {
641
+ //console.log(res);
642
+ Toast.show($this, "Saved...");
643
+ $this.enableDisableSave(false);
644
+ })
645
+ .catch(function (res) {
646
+ $this.showError(res);
647
+ });
648
+ }
649
+ },
650
+ populateModules() {
651
+ //Display module on init
652
+ let $this = this;
653
+ let modules = this.categoryModules;
654
+
655
+ if (modules.length > 0) {
656
+ for (let i = 0; i < modules.length; i++) {
657
+ let current = modules[i];
658
+ let hook = $this.getHookInfoCache(current.hook_id);
659
+ try {
660
+ let moduleInfo = $this.getModuleInfo(current.module_id);
661
+ this.addModule(hook.hookIndex, moduleInfo);
662
+ } catch (e) {
663
+ console.error("@populateModules: " + e.message);
664
+ $this.showError("@populateModules: " + e.message);
665
+ }
666
+ }
667
+ } else {
668
+ console.info("There is no module added for this category.");
669
+ Toast.show(
670
+ this,
671
+ "There is no module added for this category. Drag from the right panel to the left boxes. ",
672
+ 5000,
673
+ );
674
+ }
675
+ },
676
+ parseTheme() {
677
+ //console.log("this.themeInfo.length ",this.themeInfo);
678
+ if (this.hasTheme) {
679
+ let $this = this;
680
+ let theme = this.themeInfo;
681
+ let skeleton = theme.skeleton;
682
+ let regx_ske = /(%{cms.+}%)/gim; //find cms key
683
+ let conventions = skeleton.match(regx_ske);
684
+ let modules = {};
685
+ if (conventions && conventions.length > 0) {
686
+ let regx_m = /(cms.+})/;
687
+ let realIndex = 0;
688
+ conventions.forEach(function (current, index) {
689
+ let strcms = current.replace("%{cms.", "");
690
+ strcms = strcms.replace("}%", "");
691
+ let cms_arr = strcms.split(".");
692
+ let conventionType = cms_arr[0]; //can be hook or can be module;
693
+ let conventionName = cms_arr[1];
694
+
695
+ if (conventionType === "hook") {
696
+ let hookInfo = $this.getHookInfo(conventionName);
697
+ if (hookInfo !== null) {
698
+ $this.addHook({
699
+ name: conventionName,
700
+ modules: [],
701
+ info: hookInfo,
702
+ });
703
+ $this.setHookInfoCache(hookInfo.id, {
704
+ info: hookInfo,
705
+ hookIndex: realIndex,
706
+ });
707
+ realIndex++;
708
+ } else {
709
+ console.error(
710
+ "@parseTheme " +
711
+ conventionName +
712
+ ". You need to add in your site",
713
+ );
714
+ }
715
+ }
716
+ if (conventionType === "module") {
717
+ }
718
+ });
719
+ } else {
720
+ this.addErrorMessage(
721
+ `There is no hook defined in for this theme (${this.themeInfo.name}})`,
722
+ );
723
+ }
724
+ } else {
725
+ this.addErrorMessage("There is no theme available for this category");
726
+ }
727
+ },
728
+ addErrorMessage(message) {
729
+ this.errors.push({ message: message });
730
+ },
731
+ findModuleIndex(hookIndex, module) {
732
+ if (this.getHook(hookIndex) !== null) {
733
+ let modules = this.getHook(hookIndex).modules;
734
+ let found = modules.findIndex(function (current) {
735
+ return module.id === current.id;
736
+ });
737
+ return found;
738
+ }
739
+ return -1;
740
+ },
741
+ removeModules(idOrWhere, byType = "module_id", hookId = null) {
742
+ let $this = this;
743
+ let where;
744
+ if (Object.prototype.toString.call(idOrWhere) === "[object Object]") {
745
+ where = idOrWhere; // where is passed by param
746
+ } else {
747
+ where = this.getWhere();
748
+ where[byType] = parseInt(idOrWhere);
749
+ }
750
+
751
+ //hook and module
752
+ if (hookId !== null) {
753
+ where["hook_id"] = parseInt(hookId);
754
+ //remove from the hook->module array
755
+ let hookInfo = this.getHookInfoCache(hookId);
756
+ let module = this.getModuleInfo(idOrWhere);
757
+ let moduleIndex = this.findModuleIndex(hookInfo.hookIndex, module);
758
+ //remove module - refactor it
759
+ this.getHook(hookInfo.hookIndex).modules.splice(moduleIndex, 1);
760
+ }
761
+ let postParams = {};
762
+ postParams.where = where;
763
+ postParams.applicableForAllPlatforms = this.applicableForAllPlatforms;
764
+ this.enableDisableSave(true);
765
+
766
+ //Disable auto save on remove
767
+ /*return this.saveNow(AdminConfig.admin_path("homepage/removeModules"), postParams).then(function (res) {
768
+ console.log(res);
769
+ //Toast.show($this, res.message);
770
+ Toast.show($this, "Removed...");
771
+
772
+ }).catch(function (res) {
773
+ $this.showError(res, true);
774
+ });*/
775
+ },
776
+ addModule(hookIndex, module) {
777
+ //console.log("1: addModule ", hookIndex, module);
778
+ let found = this.findModuleIndex(hookIndex, module);
779
+
780
+ if (found === -1) {
781
+ let hook = this.getHook(hookIndex);
782
+ hook.modules.push(module);
783
+
784
+ //$this.refreshRightSide();
785
+ return hook.modules.length;
786
+ }
787
+
788
+ return false;
789
+ },
790
+ refreshRightSide() {
791
+ this.allModules.push(this.allModules[0]);
792
+ this.allModules.pop();
793
+ },
794
+ highlightEagerDrop(addRemove = "add") {
795
+ let js_hook_modules = document.querySelectorAll(".js_hook_modules");
796
+ js_hook_modules.forEach(function (current) {
797
+ current.classList[addRemove]("module-drop-eager");
798
+ current.closest("div.js_modules").classList[addRemove]("p-0", "m-0");
799
+ });
800
+ },
801
+ setHookInfoCache(hookId, data) {
802
+ return (this.hooksInfoCache[hookId] = data);
803
+ },
804
+ getHookInfoCache(hookId) {
805
+ return this.hooksInfoCache[hookId];
806
+ },
807
+ getHookInfo(hookValue, byKey = "alias") {
808
+ let hooks = this.hookInfo;
809
+
810
+ for (let i = 0; i < hooks.length; i++) {
811
+ let current = hooks[i];
812
+ if (current[byKey] === hookValue) {
813
+ return current;
814
+ }
815
+ }
816
+ return null;
817
+ },
818
+ addHook(data) {
819
+ this.hooks.push(data);
820
+ },
821
+ getHook(hookIndex) {
822
+ return this.hooks[hookIndex] || null;
823
+ },
824
+ getModuleInfo(module_id) {
825
+ if (this.moduleInfoCache[module_id]) {
826
+ return this.moduleInfoCache[module_id];
827
+ }
828
+ let found = null;
829
+ for (let i = 0; i < this.allModules.length; i++) {
830
+ let current = this.allModules[i];
831
+ if (current.id.toString() === module_id.toString()) {
832
+ this.moduleInfoCache[module_id] = current;
833
+ found = current;
834
+ break;
835
+ }
836
+ }
837
+ return found;
838
+ },
839
+ enableDragging() {
840
+ if (!this.canEdit) {
841
+ return false;
842
+ }
843
+ let $this = this;
844
+
845
+ //Right Side module
846
+ let draggableModules = document.getElementById("draggableModules");
847
+ this.sortObj.draggable = Sortable.create(draggableModules, {
848
+ animation: 200,
849
+ draggable: ".js_item",
850
+ group: {
851
+ name: "modulesBox" /*,
852
+ pull: 'clone',
853
+ revertClone: true*/,
854
+ },
855
+ sort: false,
856
+ ghostClass: "js_modules",
857
+ onEnd: function (/**Event*/ evt) {
858
+ let to = evt.to;
859
+ let item = evt.item; // dragged HTMLElement
860
+
861
+ let hookId = to.getAttribute("data-hook-id");
862
+ let moduleId = item.getAttribute("data-module-id");
863
+
864
+ if (hookId) {
865
+ let hookInfo = $this.getHookInfoCache(hookId);
866
+ //console.log(hookInfo);
867
+ let moduleInfo = $this.getModuleInfo(moduleId);
868
+
869
+ let isAdded = $this.addModule(hookInfo.hookIndex, moduleInfo);
870
+
871
+ //remove original dropped, because it is populated by reactive hook->modules
872
+ item.parentNode.removeChild(item);
873
+
874
+ $this.highlightEagerDrop("remove");
875
+
876
+ //we can send feedback
877
+ if (isAdded === false) {
878
+ Toast.show($this, "Module is already added in this hook...");
879
+ }
880
+ }
881
+
882
+ //Enable Drag
883
+
884
+ $this.enableDisableSave(true);
885
+ },
886
+ onStart: function (/**Event*/ evt) {
887
+ //console.log("on start");
888
+ $this.highlightEagerDrop("add");
889
+ },
890
+ });
891
+ },
892
+ enableSorting() {
893
+ if (!this.canEdit) {
894
+ return false;
895
+ }
896
+ let $this = this;
897
+ this.$nextTick(function () {
898
+ let list = document.querySelectorAll(".js_modules");
899
+ list.forEach(function (current) {
900
+ Sortable.create(current, {
901
+ animation: 200,
902
+ filter: ".js_delete",
903
+ group: {
904
+ name: "droppable",
905
+ put: "modulesBox",
906
+ },
907
+ onFilter: function (evt) {
908
+ let item = evt.item,
909
+ ctrl = evt.target;
910
+ let parent = item.parentNode;
911
+ let hookId = parent.getAttribute("data-hook-id");
912
+ let id = item.getAttribute("data-module-id");
913
+
914
+ if (Sortable.utils.is(ctrl, ".js_delete")) {
915
+ // Click on remove button
916
+ $this.removeModules(id, "module_id", hookId);
917
+ }
918
+ },
919
+ onUpdate: function (/**Event*/ evt) {
920
+ //console.log("@onUpdate: ", evt);
921
+ $this.enableDisableSave(true);
922
+ //reindex
923
+ },
924
+ });
925
+ });
926
+
927
+ $this.enableDragging(true);
928
+ });
929
+ },
930
+ deleteAllModuleFromHook(hookId) {
931
+ let hookInfo = this.getHookInfoCache(hookId);
932
+ let hook = this.getHook(hookInfo.hookIndex);
933
+ hook.modules = [];
934
+ this.removeModules(hookId, "hook_id");
935
+ },
936
+ hasAnyModulesInAHook(hook) {
937
+ return typeof hook.modules != "undefined" && hook.modules.length > 0;
938
+ },
939
+ enableDisableSave(val) {
940
+ if (val === undefined) {
941
+ return this.enableSave;
942
+ }
943
+ this.enableSave = val;
944
+ },
945
+ showHideDeleteAlert(isShow) {
946
+ if (isShow) {
947
+ Modal.open(this, "deleteBox");
948
+ } else {
949
+ Modal.close(this, "deleteBox");
950
+ }
951
+ },
952
+ deleteAllFromCategory() {
953
+ this.showHideDeleteAlert(false);
954
+
955
+ let allHooks = this.hooks;
956
+ for (let i = 0; i < allHooks.length; i++) {
957
+ allHooks[i].modules = [];
958
+ }
959
+ this.removeModules(this.categoryId, "category_id");
960
+ },
961
+ showHideCopyAlert(isShow = true) {
962
+ if (isShow) {
963
+ this.setDefaultFromTo();
964
+ Modal.open(this, "copyBox");
965
+ } else {
966
+ Modal.close(this, "copyBox");
967
+ }
968
+ },
969
+ copyDataFromCategory() {
970
+ this.isWorking = true;
971
+ let $this = this;
972
+ let fromData = this.fromData;
973
+ let toData = this.toData;
974
+ let data = {
975
+ fromData,
976
+ toData,
977
+ };
978
+ let url = AdminConfig.admin_path("homepage/copyData");
979
+ this.saveNow(url, data)
980
+ .then(function (res) {
981
+ //console.log(res)
982
+ if (res.data.error) {
983
+ Toast.show($this, res.data.message, 5000);
984
+ } else if (res.data.success) {
985
+ $this.showHideCopyAlert(false);
986
+ Toast.show($this, "Copied. Reloading...");
987
+ window.location.href = window.location.href;
988
+ }
989
+ $this.isWorking = false;
990
+ })
991
+ .catch(function (res) {
992
+ $this.showHideCopyAlert(false);
993
+ $this.isWorking = false;
994
+ $this.showError(res);
995
+ });
996
+ },
997
+ setWorking() {},
998
+ isValidModule(module) {
999
+ let isValid =
1000
+ module != null && typeof module != "undefined" && module.id > 0;
1001
+ if (isValid === false) {
1002
+ console.error(
1003
+ "There is some error in db entries for this category. " +
1004
+ "This can be fixed by deleting all modules and drag and drop again.",
1005
+ );
1006
+ }
1007
+ return isValid;
1008
+ },
1009
+ fetchNewData() {
1010
+ let where = this.getWhere();
1011
+ delete where.site_id;
1012
+ if (where.microsite_id === 0) {
1013
+ delete where.microsite_id;
1014
+ }
1015
+ let url = "homepage/ui";
1016
+ window.location.href = AdminConfig.admin_path(url, where);
1017
+ },
1018
+ showInfo(type, id) {
1019
+ this.$refs.infoPopup.showInfo(type, id);
1020
+ },
1021
+ showHideHookPanel(id) {
1022
+ //console.log(id, this.$refs["hook_panel_"+id]);
1023
+ let target = this.$refs["hook_panel_" + id][0];
1024
+ if (target.className.indexOf("hide") === -1) {
1025
+ target.classList.add("hide");
1026
+ } else {
1027
+ target.classList.remove("hide");
1028
+ }
1029
+ },
1030
+ onlyMe(id, evt) {
1031
+ let $this = this;
1032
+
1033
+ let target = this.$refs["panel_" + id][0];
1034
+ if (target.className.indexOf("fixed") === -1) {
1035
+ hideAllHooks(true);
1036
+ //show current and fixed it
1037
+ target.classList.remove("hide");
1038
+ target.classList.add("fixed");
1039
+ //evt.target.classList.add("fa-compress");
1040
+ } else {
1041
+ hideAllHooks(false);
1042
+ }
1043
+
1044
+ function hideAllHooks(shouldHide) {
1045
+ let savePanel = $this.$refs.savePanel;
1046
+
1047
+ //hide old one
1048
+ for (let i = 0; i < $this.hooks.length; i++) {
1049
+ let current = $this.hooks[i];
1050
+ let current_ele = $this.$refs["panel_" + current.info.id][0];
1051
+
1052
+ if (shouldHide === true) {
1053
+ current_ele.classList.add("hide");
1054
+ current_ele.classList.remove("fixed");
1055
+ } else {
1056
+ current_ele.classList.remove("hide");
1057
+ current_ele.classList.remove("fixed");
1058
+ }
1059
+ }
1060
+
1061
+ if (shouldHide === true) {
1062
+ savePanel.classList.add("hide");
1063
+ } else {
1064
+ savePanel.classList.remove("hide");
1065
+ }
1066
+ }
1067
+ },
1068
+ showError(response, reload = false) {
1069
+ let message = "";
1070
+ if (typeof response == "string") {
1071
+ message = response;
1072
+ } else {
1073
+ message =
1074
+ response && response["data"] && response["data"]["message"]
1075
+ ? response.data.message
1076
+ : "Unknown error!";
1077
+ }
1078
+ Toast.show(this, message, 5000);
1079
+ if (reload) {
1080
+ setTimeout(() => {
1081
+ window.location.reload();
1082
+ }, 1000);
1083
+ }
1084
+ },
1085
+ },
1086
+ };
1087
+ </script>