underpost 2.8.0 → 2.8.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 (119) hide show
  1. package/.dockerignore +1 -0
  2. package/.github/workflows/ghpkg.yml +19 -49
  3. package/.github/workflows/npmpkg.yml +67 -0
  4. package/.github/workflows/publish.yml +5 -5
  5. package/.github/workflows/pwa-microservices-template.page.yml +12 -4
  6. package/.github/workflows/pwa-microservices-template.test.yml +2 -2
  7. package/.vscode/extensions.json +17 -71
  8. package/.vscode/settings.json +20 -4
  9. package/AUTHORS.md +16 -5
  10. package/CHANGELOG.md +103 -3
  11. package/Dockerfile +24 -66
  12. package/README.md +1 -28
  13. package/bin/build.js +186 -0
  14. package/bin/db.js +2 -24
  15. package/bin/deploy.js +168 -157
  16. package/bin/file.js +59 -16
  17. package/bin/hwt.js +0 -10
  18. package/bin/index.js +201 -61
  19. package/bin/ssl.js +19 -11
  20. package/bin/util.js +24 -101
  21. package/bin/vs.js +26 -2
  22. package/conf.js +30 -132
  23. package/docker-compose.yml +1 -1
  24. package/manifests/deployment/mongo-express/deployment.yaml +60 -0
  25. package/manifests/deployment/phpmyadmin/deployment.yaml +54 -0
  26. package/manifests/kind-config-dev.yaml +12 -0
  27. package/manifests/kind-config.yaml +12 -0
  28. package/manifests/letsencrypt-prod.yaml +15 -0
  29. package/manifests/mariadb/config.yaml +10 -0
  30. package/manifests/mariadb/kustomization.yaml +9 -0
  31. package/manifests/mariadb/pv.yaml +12 -0
  32. package/manifests/mariadb/pvc.yaml +10 -0
  33. package/manifests/mariadb/secret.yaml +8 -0
  34. package/manifests/mariadb/service.yaml +10 -0
  35. package/manifests/mariadb/statefulset.yaml +55 -0
  36. package/manifests/mongodb/backup-access.yaml +16 -0
  37. package/manifests/mongodb/backup-cronjob.yaml +42 -0
  38. package/manifests/mongodb/backup-pv-pvc.yaml +22 -0
  39. package/manifests/mongodb/configmap.yaml +26 -0
  40. package/manifests/mongodb/headless-service.yaml +10 -0
  41. package/manifests/mongodb/kustomization.yaml +11 -0
  42. package/manifests/mongodb/pv-pvc.yaml +23 -0
  43. package/manifests/mongodb/statefulset.yaml +125 -0
  44. package/manifests/mongodb-4.4/kustomization.yaml +7 -0
  45. package/manifests/mongodb-4.4/pv-pvc.yaml +23 -0
  46. package/manifests/mongodb-4.4/service-deployment.yaml +63 -0
  47. package/manifests/valkey/kustomization.yaml +7 -0
  48. package/manifests/valkey/service.yaml +17 -0
  49. package/manifests/valkey/statefulset.yaml +39 -0
  50. package/package.json +133 -134
  51. package/src/api/core/core.service.js +1 -1
  52. package/src/api/user/user.model.js +16 -3
  53. package/src/api/user/user.service.js +1 -1
  54. package/src/cli/cluster.js +202 -0
  55. package/src/cli/cron.js +90 -0
  56. package/src/cli/db.js +212 -0
  57. package/src/cli/deploy.js +318 -0
  58. package/src/cli/env.js +52 -0
  59. package/src/cli/fs.js +149 -0
  60. package/src/cli/image.js +148 -0
  61. package/src/cli/repository.js +125 -0
  62. package/src/cli/script.js +53 -0
  63. package/src/cli/secrets.js +37 -0
  64. package/src/cli/test.js +118 -0
  65. package/src/client/components/core/Account.js +4 -2
  66. package/src/client/components/core/Auth.js +24 -6
  67. package/src/client/components/core/CalendarCore.js +127 -50
  68. package/src/client/components/core/CommonJs.js +282 -19
  69. package/src/client/components/core/Css.js +2 -1
  70. package/src/client/components/core/CssCore.js +8 -4
  71. package/src/client/components/core/Docs.js +1 -1
  72. package/src/client/components/core/DropDown.js +5 -1
  73. package/src/client/components/core/Input.js +22 -6
  74. package/src/client/components/core/JoyStick.js +8 -5
  75. package/src/client/components/core/LoadingAnimation.js +8 -1
  76. package/src/client/components/core/Modal.js +47 -18
  77. package/src/client/components/core/Panel.js +93 -31
  78. package/src/client/components/core/PanelForm.js +27 -19
  79. package/src/client/components/core/Scroll.js +1 -0
  80. package/src/client/components/core/SignUp.js +4 -1
  81. package/src/client/components/core/Translate.js +61 -9
  82. package/src/client/components/core/Validator.js +9 -1
  83. package/src/client/components/core/VanillaJs.js +0 -9
  84. package/src/client/components/core/Worker.js +34 -31
  85. package/src/client/public/default/plantuml/client-conf.svg +1 -1
  86. package/src/client/public/default/plantuml/server-conf.svg +1 -1
  87. package/src/client/public/default/plantuml/server-schema.svg +1 -1
  88. package/src/client/public/default/plantuml/ssr-conf.svg +1 -1
  89. package/src/client/public/default/plantuml/ssr-schema.svg +1 -1
  90. package/src/client/services/core/core.service.js +15 -8
  91. package/src/client/services/default/default.management.js +4 -2
  92. package/src/client/ssr/Render.js +4 -1
  93. package/src/client/ssr/body/CacheControl.js +2 -2
  94. package/src/client/ssr/body/DefaultSplashScreen.js +3 -3
  95. package/src/client/ssr/offline/Maintenance.js +63 -0
  96. package/src/client/sw/default.sw.js +26 -6
  97. package/src/db/mongo/MongooseDB.js +29 -1
  98. package/src/index.js +91 -17
  99. package/src/runtime/lampp/Lampp.js +1 -13
  100. package/src/runtime/xampp/Xampp.js +0 -13
  101. package/src/server/auth.js +3 -3
  102. package/src/server/backup.js +49 -93
  103. package/src/server/client-build.js +41 -50
  104. package/src/server/client-formatted.js +6 -3
  105. package/src/server/client-icons.js +1 -1
  106. package/src/server/conf.js +207 -57
  107. package/src/server/dns.js +30 -55
  108. package/src/server/downloader.js +0 -8
  109. package/src/server/logger.js +22 -15
  110. package/src/server/network.js +17 -43
  111. package/src/server/process.js +25 -2
  112. package/src/server/proxy.js +4 -26
  113. package/src/server/runtime.js +30 -30
  114. package/src/server/ssl.js +1 -1
  115. package/src/server/valkey.js +3 -0
  116. package/test/api.test.js +0 -8
  117. package/src/dns.js +0 -22
  118. package/src/server/prompt-optimizer.js +0 -28
  119. package/startup.js +0 -11
@@ -117,6 +117,12 @@ const CssCommonCore = async () => {
117
117
  animation: ripple 600ms linear;
118
118
  background-color: rgba(137, 137, 137, 0.503);
119
119
  }
120
+ .slide-menu-top-bar-fix {
121
+ top: 0;
122
+ left: 0;
123
+ width: 100%;
124
+ z-index: 1;
125
+ }
120
126
  @keyframes ripple {
121
127
  to {
122
128
  transform: scale(4);
@@ -390,8 +396,7 @@ const CssCoreDark = {
390
396
  text-align: center;
391
397
  background: #1a1a1a;
392
398
  font-size: 17px;
393
- padding-top: 7px;
394
- padding-bottom: 6px;
399
+ height: 35px;
395
400
  }
396
401
  ::placeholder {
397
402
  color: #c6c4c4;
@@ -695,8 +700,7 @@ const CssCoreLight = {
695
700
  text-align: center;
696
701
  background: #eaeaea;
697
702
  font-size: 17px;
698
- padding-top: 7px;
699
- padding-bottom: 6px;
703
+ height: 35px;
700
704
  }
701
705
  ::placeholder {
702
706
  color: #333;
@@ -79,7 +79,7 @@ const Docs = {
79
79
  icon: html`<i class="fa-brands fa-osi"></i>`,
80
80
  text: 'Source Docs',
81
81
  url: function () {
82
- return `${getProxyPath()}docs/engine/2.8.0`;
82
+ return `${getProxyPath()}docs/engine/${window.renderPayload.version}`;
83
83
  },
84
84
  },
85
85
  {
@@ -16,7 +16,11 @@ const DropDown = {
16
16
  onClick: () => {
17
17
  console.log('DropDown onClick', this.value);
18
18
  if (options && options.resetOnClick) options.resetOnClick();
19
- this.Tokens[id].value = undefined;
19
+ if (options && options.type === 'checkbox')
20
+ for (const opt of DropDown.Tokens[id].value) {
21
+ s(`.dropdown-option-${id}-${opt}`).click();
22
+ }
23
+ else this.Tokens[id].value = undefined;
20
24
  },
21
25
  });
22
26
 
@@ -1,6 +1,8 @@
1
1
  import { AgGrid } from './AgGrid.js';
2
2
  import { BtnIcon } from './BtnIcon.js';
3
+ import { isValidDate } from './CommonJs.js';
3
4
  import { darkTheme } from './Css.js';
5
+ import { DropDown } from './DropDown.js';
4
6
  import { loggerFactory } from './Logger.js';
5
7
  import { RichText } from './RichText.js';
6
8
  import { ToggleSwitch } from './ToggleSwitch.js';
@@ -86,8 +88,10 @@ const Input = {
86
88
  <div class="fl input-row-${id}">
87
89
  <div class="in fll" style="width: 80%;">${inputElement}</div>
88
90
  <div class="in fll btn-eye-password btn-eye-${id}" style="width: 20%;">
89
- <i class="fas fa-eye fa-eye-${id} eye-password"></i>
90
- <i class="fas fa-eye-slash fa-eye-slash-${id} eye-password" style="display: none"></i>
91
+ <div class="abs center">
92
+ <i class="fas fa-eye fa-eye-${id} eye-password"></i>
93
+ <i class="fas fa-eye-slash fa-eye-slash-${id} eye-password" style="display: none"></i>
94
+ </div>
91
95
  </div>
92
96
  </div>
93
97
  `
@@ -98,7 +102,7 @@ const Input = {
98
102
  </div>
99
103
  </div>`;
100
104
  },
101
- parseJsonEval: (selector) => {
105
+ parseJson: (selector) => {
102
106
  try {
103
107
  return JSON.parse(s(selector).value);
104
108
  } catch (error) {
@@ -147,6 +151,10 @@ const Input = {
147
151
  htmls(`.file-name-render-${inputData.id}`, `${s(`.${inputData.id}`).fileNameInputExtDefaultContent}`);
148
152
  continue;
149
153
  break;
154
+ case 'dropdown-checkbox': {
155
+ s(`.dropdown-option-${inputData.id}-reset`).click();
156
+ break;
157
+ }
150
158
  case 'md':
151
159
  RichText.Tokens[inputData.id].easyMDE.value('');
152
160
  continue;
@@ -196,6 +204,12 @@ const Input = {
196
204
  RichText.Tokens[inputData.id].easyMDE.value(fileObj[inputData.model].mdPlain);
197
205
  continue;
198
206
  break;
207
+
208
+ case 'dropdown-checkbox': {
209
+ s(`.dropdown-option-${inputData.id}-reset`).click();
210
+ for (const opt of originObj[inputData.model]) s(`.dropdown-option-${inputData.id}-${opt}`).click();
211
+ break;
212
+ }
199
213
  case 'checkbox':
200
214
  case 'checkbox-on-off':
201
215
  if (
@@ -207,9 +221,11 @@ const Input = {
207
221
  break;
208
222
  case 'datetime-local':
209
223
  {
210
- const date = new Date(originObj[inputData.model]);
211
- date.setMinutes(date.getMinutes() - date.getTimezoneOffset());
212
- s(`.${inputData.id}`).value = date.toISOString().slice(0, 16);
224
+ if (isValidDate(originObj[inputData.model])) {
225
+ const date = new Date(originObj[inputData.model]);
226
+ // date.setMinutes(date.getMinutes() - date.getTimezoneOffset());
227
+ s(`.${inputData.id}`).value = date.toISOString().slice(0, 16);
228
+ } else s(`.${inputData.id}`).value = null;
213
229
  }
214
230
  continue;
215
231
  break;
@@ -24,13 +24,16 @@ const JoyStick = {
24
24
  z-index: 3;
25
25
  }
26
26
  .joy-img-background-${id} {
27
- width: 93%;
28
- height: 93%;
27
+ width: 50%;
28
+ height: 50%;
29
29
  opacity: 0.8;
30
+ transition: 0.1;
30
31
  }
31
- .dynamic-joystick-container-${id}:hover .joy-img-background-${id} {
32
- width: 97%;
33
- height: 97%;
32
+ .dynamic-joystick-container-${id}:hover {
33
+ }
34
+ .joy-img-background-${id}:hover {
35
+ width: 54%;
36
+ height: 54%;
34
37
  opacity: 1;
35
38
  }
36
39
  </style>
@@ -75,12 +75,17 @@ const LoadingAnimation = {
75
75
  const style = {
76
76
  'text-align': 'center',
77
77
  };
78
-
79
78
  if (s(container).classList) {
80
79
  const classes = Array.from(s(container).classList);
81
80
  if (classes.find((e) => e.match('management-table-btn-mini'))) {
82
81
  style.top = '-2px';
83
82
  style.left = '-2px';
83
+ } else if (classes.find((e) => e.match('-btn-tool'))) {
84
+ style.top = '-26px';
85
+ style.left = '-10px';
86
+ } else if (classes.find((e) => e.match('main-btn-')) && !classes.find((e) => e.match('main-btn-square-menu'))) {
87
+ style.top = '-8px';
88
+ style.left = '-10px';
84
89
  } else if (classes.find((e) => e.match('action-bar-box'))) {
85
90
  style.top = '-30px';
86
91
  style.left = '-12px';
@@ -145,6 +150,8 @@ const LoadingAnimation = {
145
150
  s(backgroundContainer).style.opacity = 0;
146
151
  setTimeout(async () => {
147
152
  s(backgroundContainer).style.display = 'none';
153
+ if (s(`.modal-menu`)) s(`.modal-menu`).classList.remove('hide');
154
+ if (s(`.main-body-btn-container`)) s(`.main-body-btn-container`).classList.remove('hide');
148
155
  if (callBack) callBack();
149
156
  }, 300);
150
157
  });
@@ -9,7 +9,6 @@ import {
9
9
  htmls,
10
10
  sa,
11
11
  getAllChildNodes,
12
- getCurrentTrace,
13
12
  isActiveElement,
14
13
  } from './VanillaJs.js';
15
14
  import { BtnIcon } from './BtnIcon.js';
@@ -50,6 +49,7 @@ const Modal = {
50
49
  mode: '' /* slide-menu */,
51
50
  RouterInstance: {},
52
51
  disableTools: [],
52
+ observer: false,
53
53
  },
54
54
  ) {
55
55
  if (options.heightBottomBar === undefined) options.heightBottomBar = 50;
@@ -65,12 +65,6 @@ const Modal = {
65
65
  options.heightTopBar = options.heightTopBar + options.heightBottomBar;
66
66
  options.heightBottomBar = 0;
67
67
  }
68
- const setCenterRestore = () => {
69
- const ResponsiveData = Responsive.getResponsiveData();
70
- top = `${ResponsiveData.height / 2 - height / 2}px`;
71
- left = `${ResponsiveData.width / 2 - width / 2}px`;
72
- };
73
- setCenterRestore();
74
68
  let transition = `opacity 0.3s, box-shadow 0.3s, bottom 0.3s`;
75
69
  const originSlideMenuWidth = 320;
76
70
  const collapseSlideMenuWidth = 50;
@@ -83,6 +77,8 @@ const Modal = {
83
77
  options,
84
78
  onCloseListener: {},
85
79
  onMenuListener: {},
80
+ onCollapseMenuListener: {},
81
+ onExtendMenuListener: {},
86
82
  onDragEndListener: {},
87
83
  onObserverListener: {},
88
84
  onClickListener: {},
@@ -91,6 +87,12 @@ const Modal = {
91
87
  onBarUiClose: {},
92
88
  query: options.query ? `${window.location.search}` : undefined,
93
89
  };
90
+ const setCenterRestore = () => {
91
+ const ResponsiveData = Responsive.getResponsiveData();
92
+ top = `${ResponsiveData.height / 2 - height / 2}px`;
93
+ left = `${ResponsiveData.width / 2 - width / 2}px`;
94
+ };
95
+ if (idModal !== 'main-body') setCenterRestore();
94
96
  if (options && 'mode' in options) {
95
97
  this.Data[idModal][options.mode] = {};
96
98
  switch (options.mode) {
@@ -157,7 +159,8 @@ const Modal = {
157
159
  };
158
160
  options.mode === 'slide-menu-right' ? (options.style.right = '0px') : (options.style.left = '0px');
159
161
  const contentIconClass = 'abs center';
160
-
162
+ if (options.class) options.class += ' hide';
163
+ else options.class = 'hide';
161
164
  options.dragDisabled = true;
162
165
  options.titleClass = 'hide';
163
166
  top = '0px';
@@ -239,7 +242,7 @@ const Modal = {
239
242
  'body',
240
243
  html`
241
244
  <div
242
- class="abs main-body-btn-container"
245
+ class="abs main-body-btn-container hide"
243
246
  style="top: ${options.heightTopBar + 50}px; z-index: 9; ${true ||
244
247
  (options.mode && options.mode.match('right'))
245
248
  ? 'right'
@@ -265,6 +268,7 @@ const Modal = {
265
268
  <i class="fas fa-caret-up main-body-btn-ui-close"></i>
266
269
  </div>
267
270
  </div>
271
+ <div class="main-body-btn-container-custom"></div>
268
272
  </div>
269
273
  `,
270
274
  );
@@ -402,6 +406,11 @@ const Modal = {
402
406
  })}
403
407
  </div>
404
408
  </div>
409
+ ${options?.slideMenuTopBarFix
410
+ ? html`<div class="abs modal slide-menu-top-bar-fix" style="height: ${options.heightTopBar}px">
411
+ ${await options.slideMenuTopBarFix()}
412
+ </div>`
413
+ : ''}
405
414
  </div>`,
406
415
  );
407
416
  EventsUI.onClick(`.action-btn-profile-log-in`, () => {
@@ -536,12 +545,12 @@ const Modal = {
536
545
  if (routerId) {
537
546
  if (
538
547
  s(`.main-btn-${routerId}`) &&
539
- (routerId.toLocaleLowerCase().match(s(`.${id}`).value.toLocaleLowerCase()) ||
548
+ (routerId.toLowerCase().match(s(`.${id}`).value.toLowerCase()) ||
540
549
  (Translate.Data[routerId] &&
541
550
  Object.keys(Translate.Data[routerId]).filter((keyLang) =>
542
551
  Translate.Data[routerId][keyLang]
543
- .toLocaleLowerCase()
544
- .match(s(`.${id}`).value.toLocaleLowerCase()),
552
+ .toLowerCase()
553
+ .match(s(`.${id}`).value.toLowerCase()),
545
554
  ).length > 0))
546
555
  ) {
547
556
  const fontAwesomeIcon = getAllChildNodes(s(`.main-btn-${routerId}`)).find((e) => {
@@ -1378,6 +1387,9 @@ const Modal = {
1378
1387
  if (options.onCollapseMenu) options.onCollapseMenu();
1379
1388
  s(`.sub-menu-title-container-${'modal-menu'}`).classList.add('hide');
1380
1389
  s(`.nav-path-container-${'modal-menu'}`).classList.add('hide');
1390
+ Object.keys(this.Data[idModal].onCollapseMenuListener).map((keyListener) =>
1391
+ this.Data[idModal].onCollapseMenuListener[keyListener](),
1392
+ );
1381
1393
  } else {
1382
1394
  slideMenuWidth = originSlideMenuWidth;
1383
1395
  setTimeout(() => {
@@ -1398,6 +1410,9 @@ const Modal = {
1398
1410
  if (options.onExtendMenu) options.onExtendMenu();
1399
1411
  s(`.sub-menu-title-container-${'modal-menu'}`).classList.remove('hide');
1400
1412
  s(`.nav-path-container-${'modal-menu'}`).classList.remove('hide');
1413
+ Object.keys(this.Data[idModal].onExtendMenuListener).map((keyListener) =>
1414
+ this.Data[idModal].onExtendMenuListener[keyListener](),
1415
+ );
1401
1416
  }
1402
1417
  // btn-bar-center-icon-menu
1403
1418
  this.actionBtnCenter();
@@ -1690,7 +1705,7 @@ const Modal = {
1690
1705
  const htmlRender = html`
1691
1706
  <br />
1692
1707
  <div class="in section-mp" style="font-size: 40px; text-align: center">
1693
- <i class="fas fa-question-circle"></i>
1708
+ ${options.icon ? options.icon : html` <i class="fas fa-question-circle"></i>`}
1694
1709
  </div>
1695
1710
  ${await options.html()}
1696
1711
  <div class="in section-mp">
@@ -1701,7 +1716,7 @@ const Modal = {
1701
1716
  style: `margin: auto`,
1702
1717
  })}
1703
1718
  </div>
1704
- <div class="in section-mp">
1719
+ <div class="in section-mp ${options.disableBtnCancel ? 'hide' : ''}">
1705
1720
  ${await BtnIcon.Render({
1706
1721
  class: `in section-mp form-button btn-cancel-${id}`,
1707
1722
  label: Translate.Render('cancel'),
@@ -1776,20 +1791,34 @@ const renderMenuLabel = ({ img, text, icon }) => {
1776
1791
  <div class="abs center main-btn-menu-text">${text}</div>`;
1777
1792
  };
1778
1793
 
1779
- const renderViewTitle = (options = { icon: '', img: '', text: '', assetFolder: '', 'ui-icons': '', dim, top }) => {
1780
- if (options.dim === undefined) options.dim = 60;
1794
+ const renderViewTitle = (
1795
+ options = { icon: '', img: '', text: '', assetFolder: '', 'ui-icons': '', dim, top, topText: '' },
1796
+ ) => {
1797
+ if (options.dim === undefined) options.dim = 30;
1781
1798
  const { img, text, icon, dim, top } = options;
1782
1799
  if (!img && !options['ui-icon']) return html`<span class="view-title-icon">${icon}</span> ${text}`;
1783
1800
  return html`<img
1784
1801
  class="abs img-btn-square-view-title"
1785
1802
  style="${renderCssAttr({
1786
- style: { width: `${dim}px`, height: `${dim}px`, top: top !== undefined ? `${top}px` : `-${dim / 2}px` },
1803
+ style: {
1804
+ width: `${dim}px`,
1805
+ height: `${dim}px`,
1806
+ top: top !== undefined ? `${top}px !important` : undefined,
1807
+ },
1787
1808
  })}"
1788
1809
  src="${options['ui-icon']
1789
1810
  ? `${getProxyPath()}assets/${options.assetFolder ? options.assetFolder : 'ui-icons'}/${options['ui-icon']}`
1790
1811
  : img}"
1791
1812
  />
1792
- <div class="in text-btn-square-view-title" style="${renderCssAttr({ style: { 'padding-left': `${dim}px` } })}">
1813
+ <div
1814
+ class="in text-btn-square-view-title"
1815
+ style="${renderCssAttr({
1816
+ style: {
1817
+ // 'padding-left': `${20 + dim}px`,
1818
+ ...(options.topText !== undefined ? { top: options.topText + 'px !important' } : {}),
1819
+ },
1820
+ })}"
1821
+ >
1793
1822
  ${text}
1794
1823
  </div>`;
1795
1824
  };
@@ -1,4 +1,4 @@
1
- import { getId } from './CommonJs.js';
1
+ import { getId, isValidDate, newInstance } from './CommonJs.js';
2
2
  import { LoadingAnimation } from '../core/LoadingAnimation.js';
3
3
  import { Validator } from '../core/Validator.js';
4
4
  import { Input } from '../core/Input.js';
@@ -26,6 +26,7 @@ const Panel = {
26
26
  idPanel: '',
27
27
  parentIdModal: '',
28
28
  scrollClassContainer: '',
29
+ htmlFormHeader: async () => '',
29
30
  formData: [],
30
31
  data: [],
31
32
  originData: () => [],
@@ -51,8 +52,6 @@ const Panel = {
51
52
  <i style="font-size: 25px" class="fa-solid fa-cloud"></i>
52
53
  </div>`;
53
54
 
54
- let editId;
55
-
56
55
  const openPanelForm = () => {
57
56
  s(`.${idPanel}-form-body`).classList.remove('hide');
58
57
  s(`.btn-${idPanel}-add`).classList.add('hide');
@@ -72,11 +71,12 @@ const Panel = {
72
71
  };
73
72
 
74
73
  const renderPanel = async (payload) => {
75
- const obj = payload;
74
+ const obj = newInstance(payload);
76
75
  if ('_id' in obj) obj.id = obj._id;
77
76
  const { id } = obj;
78
77
 
79
78
  setTimeout(async () => {
79
+ if (!s(`.${idPanel}`)) return;
80
80
  LoadingAnimation.spinner.play(`.${idPanel}-img-spinner-${id}`, 'dual-ring');
81
81
  if (options && options.callBackPanelRender)
82
82
  await options.callBackPanelRender({
@@ -97,8 +97,8 @@ const Panel = {
97
97
  });
98
98
  EventsUI.onClick(`.${idPanel}-btn-edit-${id}`, async () => {
99
99
  logger.warn('edit', obj);
100
- if (obj._id) editId = obj._id;
101
- else if (obj.id) editId = obj.id;
100
+ if (obj._id) Panel.Tokens[idPanel].editId = obj._id;
101
+ else if (obj.id) Panel.Tokens[idPanel].editId = obj.id;
102
102
 
103
103
  s(`.btn-${idPanel}-label-edit`).classList.remove('hide');
104
104
  s(`.btn-${idPanel}-label-add`).classList.add('hide');
@@ -170,6 +170,10 @@ const Panel = {
170
170
  const valueIcon = formObjData?.panel?.icon?.value ? formObjData.panel.icon.value : '';
171
171
  const keyIcon = formObjData?.panel?.icon?.key ? formObjData.panel.icon.key : '';
172
172
 
173
+ if (formObjData && ['datetime-local'].includes(formObjData.inputType) && isValidDate(obj[infoKey])) {
174
+ obj[infoKey] = `${obj[infoKey]}`.replace('T', ' ').replace('.000Z', '');
175
+ }
176
+
173
177
  if (formData.find((f) => f.model === infoKey && f.panel && f.panel.type === 'tags')) {
174
178
  setTimeout(async () => {
175
179
  let tagRender = html``;
@@ -185,22 +189,50 @@ const Panel = {
185
189
  });
186
190
  return html``;
187
191
  }
192
+ {
193
+ const formDataObj = formData.find((f) => f.model === infoKey && f.panel && f.panel.type === 'list');
194
+ if (obj[infoKey] && obj[infoKey].length > 0 && formDataObj)
195
+ return html`<div class="in ${idPanel}-row">
196
+ <span class="${idPanel}-row-key capitalize ${formObjData.label?.disabled ? 'hide' : ''}">
197
+ ${keyIcon} ${Translate.Render(infoKey)}:</span
198
+ >
199
+ <span class="${idPanel}-row-value"
200
+ >${valueIcon} ${obj[infoKey].map((k) => Translate.Render(k)).join(', ')}</span
201
+ >
202
+ </div> `;
203
+ }
188
204
 
189
- if (formData.find((f) => f.model === infoKey && f.panel && f.panel.type === 'info-row-pin'))
190
- return html`<div class="in ${idPanel}-row">
191
- <span class="${idPanel}-row-pin-key capitalize ${formObjData.label?.disabled ? 'hide' : ''}">
192
- ${keyIcon} ${infoKey}:</span
193
- >
194
- <span class="${idPanel}-row-pin-value">${valueIcon} ${obj[infoKey]}</span>
195
- </div> `;
205
+ {
206
+ const formDataObj = formData.find(
207
+ (f) => f.model === infoKey && f.panel && f.panel.type === 'info-row-pin',
208
+ );
209
+ if (obj[infoKey] && formDataObj)
210
+ return html`<div class="in ${idPanel}-row">
211
+ <span class="${idPanel}-row-pin-key capitalize ${formObjData.label?.disabled ? 'hide' : ''}">
212
+ ${keyIcon}
213
+ ${formDataObj.translateCode
214
+ ? Translate.Render(formDataObj.translateCode)
215
+ : Translate.Render(infoKey)}:</span
216
+ >
217
+ <span class="${idPanel}-row-pin-value">${valueIcon} ${obj[infoKey]}</span>
218
+ </div> `;
219
+ }
196
220
 
197
- if (formData.find((f) => f.model === infoKey && f.panel && f.panel.type === 'info-row'))
198
- return html`<div class="in ${idPanel}-row">
199
- <span class="${idPanel}-row-key capitalize ${formObjData.label?.disabled ? 'hide' : ''}">
200
- ${keyIcon} ${infoKey}:</span
201
- >
202
- <span class="${idPanel}-row-value"> ${valueIcon} ${obj[infoKey]}</span>
203
- </div> `;
221
+ {
222
+ const formDataObj = formData.find(
223
+ (f) => f.model === infoKey && f.panel && f.panel.type === 'info-row',
224
+ );
225
+ if (obj[infoKey] && formDataObj)
226
+ return html`<div class="in ${idPanel}-row">
227
+ <span class="${idPanel}-row-key capitalize ${formObjData.label?.disabled ? 'hide' : ''}">
228
+ ${keyIcon}
229
+ ${formDataObj.translateCode
230
+ ? Translate.Render(formDataObj.translateCode)
231
+ : Translate.Render(infoKey)}:</span
232
+ >
233
+ <span class="${idPanel}-row-value"> ${valueIcon} ${obj[infoKey]}</span>
234
+ </div> `;
235
+ }
204
236
 
205
237
  return html``;
206
238
  })
@@ -213,16 +245,41 @@ const Panel = {
213
245
 
214
246
  let render = '';
215
247
  let renderForm = html` <div class="in modal stq" style="top: 0px; z-index: 1; padding-bottom: 5px">
216
- ${await BtnIcon.Render({
217
- class: `section-mp btn-custom btn-${idPanel}-close`,
218
- label: html`<i class="fa-solid fa-xmark"></i> ${Translate.Render('close')}`,
219
- type: 'button',
220
- })}
221
- </div>`;
248
+ ${await BtnIcon.Render({
249
+ class: `section-mp btn-custom btn-${idPanel}-close`,
250
+ label: html`<i class="fa-solid fa-xmark"></i> ${Translate.Render('close')}`,
251
+ type: 'button',
252
+ })}
253
+ </div>
254
+ ${options?.htmlFormHeader ? await options.htmlFormHeader() : ''}`;
222
255
 
223
256
  for (const modelData of formData) {
224
257
  if (modelData.disableRender) continue;
225
258
  switch (modelData.inputType) {
259
+ case 'dropdown-checkbox': {
260
+ renderForm += html`<div class="in section-mp">
261
+ ${await DropDown.Render({
262
+ id: `${modelData.id}`,
263
+ label: html`${Translate.Render(modelData.model)}`,
264
+ type: 'checkbox',
265
+ value: modelData.dropdown.options[0],
266
+ resetOption: true,
267
+ containerClass: `${idPanel}-dropdown-checkbox`,
268
+ data: modelData.dropdown.options.map((dKey) => {
269
+ return {
270
+ value: dKey,
271
+ data: dKey,
272
+ checked: false,
273
+ display: html`${Translate.Render(dKey)}`,
274
+ onClick: function () {
275
+ logger.info('DropDown onClick', this.checked);
276
+ },
277
+ };
278
+ }),
279
+ })}
280
+ </div>`;
281
+ break;
282
+ }
226
283
  case 'dropdown':
227
284
  renderForm += html` <div class="in section-mp">
228
285
  ${await DropDown.Render({
@@ -417,21 +474,23 @@ const Panel = {
417
474
  obj.id = `${data.length}`;
418
475
  let documents;
419
476
  if (options && options.on && options.on.add) {
420
- const { status, data } = await options.on.add({ data: obj, editId });
477
+ const { status, data } = await options.on.add({ data: obj, editId: Panel.Tokens[idPanel].editId });
421
478
  if (status === 'error') return;
422
479
  documents = data;
423
480
  }
424
481
  s(`.btn-${idPanel}-clean`).click();
425
- if (editId && s(`.${idPanel}-${editId}`)) s(`.${idPanel}-${editId}`).remove();
482
+ if (Panel.Tokens[idPanel].editId && s(`.${idPanel}-${Panel.Tokens[idPanel].editId}`))
483
+ s(`.${idPanel}-${Panel.Tokens[idPanel].editId}`).remove();
426
484
  if (Array.isArray(documents)) {
427
485
  htmls(`.${idPanel}-render`, '');
428
486
  for (const doc of documents) {
429
487
  append(`.${idPanel}-render`, await renderPanel(doc));
430
488
  }
431
- } else htmls(`.${idPanel}-render`, await renderPanel(obj));
489
+ } else htmls(`.${idPanel}-render`, await renderPanel({ ...obj, ...documents }));
432
490
  Input.cleanValues(formData);
433
491
  s(`.btn-${idPanel}-close`).click();
434
492
  s(`.${scrollClassContainer}`).scrollTop = 0;
493
+ if (s(`.${scrollClassContainer}`)) s(`.${scrollClassContainer}`).style.overflow = 'auto';
435
494
  });
436
495
  s(`.btn-${idPanel}-clean`).onclick = () => {
437
496
  Input.cleanValues(formData);
@@ -457,13 +516,14 @@ const Panel = {
457
516
  s(`.btn-${idPanel}-add`).onclick = (e) => {
458
517
  e.preventDefault();
459
518
  // s(`.btn-${idPanel}-clean`).click();
460
- editId = undefined;
519
+ Panel.Tokens[idPanel].editId = undefined;
461
520
  s(`.btn-${idPanel}-label-add`).classList.remove('hide');
462
521
  s(`.btn-${idPanel}-label-edit`).classList.add('hide');
463
522
  s(`.${scrollClassContainer}`).scrollTop = 0;
464
523
 
465
524
  openPanelForm();
466
525
  };
526
+ if (s(`.${scrollClassContainer}`)) s(`.${scrollClassContainer}`).style.overflow = 'auto';
467
527
  });
468
528
 
469
529
  if (data.length > 0) for (const obj of data) render += await renderPanel(obj);
@@ -596,7 +656,9 @@ const Panel = {
596
656
  >
597
657
  <div class="in ${idPanel}-form-header">
598
658
  ${await BtnIcon.Render({
599
- class: `section-mp btn-custom btn-${idPanel}-add`,
659
+ class: `section-mp btn-custom btn-${idPanel}-add ${
660
+ options?.role?.add ? (!options.role.add() ? 'hide' : '') : ''
661
+ }`,
600
662
  label: html`<i class="fas fa-plus"></i> ${Translate.Render('add')}`,
601
663
  type: 'button',
602
664
  })}