@underpostnet/underpost 2.8.1 → 2.8.5

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 (105) hide show
  1. package/.dockerignore +1 -0
  2. package/.github/workflows/ghpkg.yml +20 -50
  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 +13 -5
  6. package/.github/workflows/pwa-microservices-template.test.yml +2 -2
  7. package/.vscode/extensions.json +17 -71
  8. package/.vscode/settings.json +14 -3
  9. package/AUTHORS.md +16 -5
  10. package/CHANGELOG.md +79 -3
  11. package/Dockerfile +24 -66
  12. package/README.md +1 -28
  13. package/bin/build.js +161 -0
  14. package/bin/db.js +2 -24
  15. package/bin/deploy.js +111 -82
  16. package/bin/file.js +59 -16
  17. package/bin/index.js +168 -58
  18. package/bin/ssl.js +19 -11
  19. package/bin/util.js +9 -97
  20. package/bin/vs.js +25 -2
  21. package/conf.js +31 -138
  22. package/docker-compose.yml +1 -1
  23. package/manifests/core/kustomization.yaml +11 -0
  24. package/manifests/core/underpost-engine-backup-access.yaml +16 -0
  25. package/manifests/core/underpost-engine-backup-pv-pvc.yaml +22 -0
  26. package/manifests/core/underpost-engine-headless-service.yaml +10 -0
  27. package/manifests/core/underpost-engine-mongodb-backup-cronjob.yaml +40 -0
  28. package/manifests/core/underpost-engine-mongodb-configmap.yaml +26 -0
  29. package/manifests/core/underpost-engine-pv-pvc.yaml +23 -0
  30. package/manifests/core/underpost-engine-statefulset.yaml +91 -0
  31. package/manifests/deployment/mongo-express/deployment.yaml +60 -0
  32. package/manifests/deployment/phpmyadmin/deployment.yaml +54 -0
  33. package/manifests/kind-config.yaml +12 -0
  34. package/manifests/letsencrypt-prod.yaml +15 -0
  35. package/manifests/mariadb/config.yaml +10 -0
  36. package/manifests/mariadb/kustomization.yaml +9 -0
  37. package/manifests/mariadb/pv.yaml +12 -0
  38. package/manifests/mariadb/pvc.yaml +10 -0
  39. package/manifests/mariadb/secret.yaml +8 -0
  40. package/manifests/mariadb/service.yaml +10 -0
  41. package/manifests/mariadb/statefulset.yaml +55 -0
  42. package/manifests/mongodb/backup-access.yaml +16 -0
  43. package/manifests/mongodb/backup-cronjob.yaml +42 -0
  44. package/manifests/mongodb/backup-pv-pvc.yaml +22 -0
  45. package/manifests/mongodb/configmap.yaml +26 -0
  46. package/manifests/mongodb/headless-service.yaml +10 -0
  47. package/manifests/mongodb/kustomization.yaml +11 -0
  48. package/manifests/mongodb/pv-pvc.yaml +23 -0
  49. package/manifests/mongodb/statefulset.yaml +125 -0
  50. package/manifests/valkey/kustomization.yaml +7 -0
  51. package/manifests/valkey/service.yaml +17 -0
  52. package/manifests/valkey/statefulset.yaml +39 -0
  53. package/manifests/valkey/underpost-engine-valkey-service.yaml +17 -0
  54. package/manifests/valkey/underpost-engine-valkey-statefulset.yaml +39 -0
  55. package/package.json +26 -31
  56. package/src/api/core/core.service.js +1 -1
  57. package/src/api/user/user.model.js +16 -3
  58. package/src/api/user/user.service.js +1 -1
  59. package/src/cli/cluster.js +154 -0
  60. package/src/cli/cron.js +90 -0
  61. package/src/cli/db.js +148 -0
  62. package/src/cli/deploy.js +277 -0
  63. package/src/cli/env.js +52 -0
  64. package/src/cli/image.js +125 -0
  65. package/src/cli/repository.js +104 -0
  66. package/src/cli/script.js +29 -0
  67. package/src/cli/secrets.js +37 -0
  68. package/src/cli/test.js +83 -0
  69. package/src/client/components/core/Auth.js +22 -4
  70. package/src/client/components/core/CalendarCore.js +115 -49
  71. package/src/client/components/core/CommonJs.js +231 -19
  72. package/src/client/components/core/Css.js +1 -0
  73. package/src/client/components/core/CssCore.js +6 -0
  74. package/src/client/components/core/DropDown.js +5 -1
  75. package/src/client/components/core/Input.js +18 -4
  76. package/src/client/components/core/Modal.js +10 -6
  77. package/src/client/components/core/Panel.js +84 -25
  78. package/src/client/components/core/PanelForm.js +4 -18
  79. package/src/client/components/core/Scroll.js +1 -0
  80. package/src/client/components/core/Translate.js +47 -9
  81. package/src/client/components/core/Validator.js +9 -1
  82. package/src/client/components/core/VanillaJs.js +0 -9
  83. package/src/client/components/core/Worker.js +34 -31
  84. package/src/client/services/default/default.management.js +4 -2
  85. package/src/client/ssr/body/CacheControl.js +2 -2
  86. package/src/db/mongo/MongooseDB.js +13 -1
  87. package/src/index.js +77 -19
  88. package/src/runtime/lampp/Lampp.js +1 -13
  89. package/src/runtime/xampp/Xampp.js +0 -13
  90. package/src/server/auth.js +3 -3
  91. package/src/server/backup.js +49 -93
  92. package/src/server/client-build.js +4 -23
  93. package/src/server/client-formatted.js +5 -3
  94. package/src/server/conf.js +193 -45
  95. package/src/server/dns.js +49 -67
  96. package/src/server/logger.js +15 -10
  97. package/src/server/network.js +17 -43
  98. package/src/server/process.js +25 -2
  99. package/src/server/proxy.js +4 -26
  100. package/src/server/runtime.js +14 -29
  101. package/src/server/ssl.js +1 -1
  102. package/src/server/valkey.js +2 -0
  103. package/src/dns.js +0 -22
  104. package/src/server/prompt-optimizer.js +0 -28
  105. package/startup.js +0 -11
@@ -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';
@@ -403,6 +402,11 @@ const Modal = {
403
402
  })}
404
403
  </div>
405
404
  </div>
405
+ ${options?.slideMenuTopBarFix
406
+ ? html`<div class="abs modal slide-menu-top-bar-fix" style="height: ${options.heightTopBar}px">
407
+ ${await options.slideMenuTopBarFix()}
408
+ </div>`
409
+ : ''}
406
410
  </div>`,
407
411
  );
408
412
  EventsUI.onClick(`.action-btn-profile-log-in`, () => {
@@ -537,12 +541,12 @@ const Modal = {
537
541
  if (routerId) {
538
542
  if (
539
543
  s(`.main-btn-${routerId}`) &&
540
- (routerId.toLocaleLowerCase().match(s(`.${id}`).value.toLocaleLowerCase()) ||
544
+ (routerId.toLowerCase().match(s(`.${id}`).value.toLowerCase()) ||
541
545
  (Translate.Data[routerId] &&
542
546
  Object.keys(Translate.Data[routerId]).filter((keyLang) =>
543
547
  Translate.Data[routerId][keyLang]
544
- .toLocaleLowerCase()
545
- .match(s(`.${id}`).value.toLocaleLowerCase()),
548
+ .toLowerCase()
549
+ .match(s(`.${id}`).value.toLowerCase()),
546
550
  ).length > 0))
547
551
  ) {
548
552
  const fontAwesomeIcon = getAllChildNodes(s(`.main-btn-${routerId}`)).find((e) => {
@@ -1691,7 +1695,7 @@ const Modal = {
1691
1695
  const htmlRender = html`
1692
1696
  <br />
1693
1697
  <div class="in section-mp" style="font-size: 40px; text-align: center">
1694
- <i class="fas fa-question-circle"></i>
1698
+ ${options.icon ? options.icon : html` <i class="fas fa-question-circle"></i>`}
1695
1699
  </div>
1696
1700
  ${await options.html()}
1697
1701
  <div class="in section-mp">
@@ -1702,7 +1706,7 @@ const Modal = {
1702
1706
  style: `margin: auto`,
1703
1707
  })}
1704
1708
  </div>
1705
- <div class="in section-mp">
1709
+ <div class="in section-mp ${options.disableBtnCancel ? 'hide' : ''}">
1706
1710
  ${await BtnIcon.Render({
1707
1711
  class: `in section-mp form-button btn-cancel-${id}`,
1708
1712
  label: Translate.Render('cancel'),
@@ -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';
@@ -51,8 +51,6 @@ const Panel = {
51
51
  <i style="font-size: 25px" class="fa-solid fa-cloud"></i>
52
52
  </div>`;
53
53
 
54
- let editId;
55
-
56
54
  const openPanelForm = () => {
57
55
  s(`.${idPanel}-form-body`).classList.remove('hide');
58
56
  s(`.btn-${idPanel}-add`).classList.add('hide');
@@ -72,7 +70,7 @@ const Panel = {
72
70
  };
73
71
 
74
72
  const renderPanel = async (payload) => {
75
- const obj = payload;
73
+ const obj = newInstance(payload);
76
74
  if ('_id' in obj) obj.id = obj._id;
77
75
  const { id } = obj;
78
76
 
@@ -98,8 +96,8 @@ const Panel = {
98
96
  });
99
97
  EventsUI.onClick(`.${idPanel}-btn-edit-${id}`, async () => {
100
98
  logger.warn('edit', obj);
101
- if (obj._id) editId = obj._id;
102
- else if (obj.id) editId = obj.id;
99
+ if (obj._id) Panel.Tokens[idPanel].editId = obj._id;
100
+ else if (obj.id) Panel.Tokens[idPanel].editId = obj.id;
103
101
 
104
102
  s(`.btn-${idPanel}-label-edit`).classList.remove('hide');
105
103
  s(`.btn-${idPanel}-label-add`).classList.add('hide');
@@ -171,6 +169,10 @@ const Panel = {
171
169
  const valueIcon = formObjData?.panel?.icon?.value ? formObjData.panel.icon.value : '';
172
170
  const keyIcon = formObjData?.panel?.icon?.key ? formObjData.panel.icon.key : '';
173
171
 
172
+ if (formObjData && ['datetime-local'].includes(formObjData.inputType) && isValidDate(obj[infoKey])) {
173
+ obj[infoKey] = `${obj[infoKey]}`.replace('T', ' ').replace('.000Z', '');
174
+ }
175
+
174
176
  if (formData.find((f) => f.model === infoKey && f.panel && f.panel.type === 'tags')) {
175
177
  setTimeout(async () => {
176
178
  let tagRender = html``;
@@ -186,22 +188,50 @@ const Panel = {
186
188
  });
187
189
  return html``;
188
190
  }
191
+ {
192
+ const formDataObj = formData.find((f) => f.model === infoKey && f.panel && f.panel.type === 'list');
193
+ if (obj[infoKey] && obj[infoKey].length > 0 && formDataObj)
194
+ return html`<div class="in ${idPanel}-row">
195
+ <span class="${idPanel}-row-key capitalize ${formObjData.label?.disabled ? 'hide' : ''}">
196
+ ${keyIcon} ${Translate.Render(infoKey)}:</span
197
+ >
198
+ <span class="${idPanel}-row-value"
199
+ >${valueIcon} ${obj[infoKey].map((k) => Translate.Render(k)).join(', ')}</span
200
+ >
201
+ </div> `;
202
+ }
189
203
 
190
- if (formData.find((f) => f.model === infoKey && f.panel && f.panel.type === 'info-row-pin'))
191
- return html`<div class="in ${idPanel}-row">
192
- <span class="${idPanel}-row-pin-key capitalize ${formObjData.label?.disabled ? 'hide' : ''}">
193
- ${keyIcon} ${infoKey}:</span
194
- >
195
- <span class="${idPanel}-row-pin-value">${valueIcon} ${obj[infoKey]}</span>
196
- </div> `;
204
+ {
205
+ const formDataObj = formData.find(
206
+ (f) => f.model === infoKey && f.panel && f.panel.type === 'info-row-pin',
207
+ );
208
+ if (obj[infoKey] && formDataObj)
209
+ return html`<div class="in ${idPanel}-row">
210
+ <span class="${idPanel}-row-pin-key capitalize ${formObjData.label?.disabled ? 'hide' : ''}">
211
+ ${keyIcon}
212
+ ${formDataObj.translateCode
213
+ ? Translate.Render(formDataObj.translateCode)
214
+ : Translate.Render(infoKey)}:</span
215
+ >
216
+ <span class="${idPanel}-row-pin-value">${valueIcon} ${obj[infoKey]}</span>
217
+ </div> `;
218
+ }
197
219
 
198
- if (formData.find((f) => f.model === infoKey && f.panel && f.panel.type === 'info-row'))
199
- return html`<div class="in ${idPanel}-row">
200
- <span class="${idPanel}-row-key capitalize ${formObjData.label?.disabled ? 'hide' : ''}">
201
- ${keyIcon} ${infoKey}:</span
202
- >
203
- <span class="${idPanel}-row-value"> ${valueIcon} ${obj[infoKey]}</span>
204
- </div> `;
220
+ {
221
+ const formDataObj = formData.find(
222
+ (f) => f.model === infoKey && f.panel && f.panel.type === 'info-row',
223
+ );
224
+ if (obj[infoKey] && formDataObj)
225
+ return html`<div class="in ${idPanel}-row">
226
+ <span class="${idPanel}-row-key capitalize ${formObjData.label?.disabled ? 'hide' : ''}">
227
+ ${keyIcon}
228
+ ${formDataObj.translateCode
229
+ ? Translate.Render(formDataObj.translateCode)
230
+ : Translate.Render(infoKey)}:</span
231
+ >
232
+ <span class="${idPanel}-row-value"> ${valueIcon} ${obj[infoKey]}</span>
233
+ </div> `;
234
+ }
205
235
 
206
236
  return html``;
207
237
  })
@@ -224,6 +254,30 @@ const Panel = {
224
254
  for (const modelData of formData) {
225
255
  if (modelData.disableRender) continue;
226
256
  switch (modelData.inputType) {
257
+ case 'dropdown-checkbox': {
258
+ renderForm += html`<div class="in section-mp">
259
+ ${await DropDown.Render({
260
+ id: `${modelData.id}`,
261
+ label: html`${Translate.Render(modelData.model)}`,
262
+ type: 'checkbox',
263
+ value: modelData.dropdown.options[0],
264
+ resetOption: true,
265
+ containerClass: `${idPanel}-dropdown-checkbox`,
266
+ data: modelData.dropdown.options.map((dKey) => {
267
+ return {
268
+ value: dKey,
269
+ data: dKey,
270
+ checked: false,
271
+ display: html`${Translate.Render(dKey)}`,
272
+ onClick: function () {
273
+ logger.info('DropDown onClick', this.checked);
274
+ },
275
+ };
276
+ }),
277
+ })}
278
+ </div>`;
279
+ break;
280
+ }
227
281
  case 'dropdown':
228
282
  renderForm += html` <div class="in section-mp">
229
283
  ${await DropDown.Render({
@@ -418,21 +472,23 @@ const Panel = {
418
472
  obj.id = `${data.length}`;
419
473
  let documents;
420
474
  if (options && options.on && options.on.add) {
421
- const { status, data } = await options.on.add({ data: obj, editId });
475
+ const { status, data } = await options.on.add({ data: obj, editId: Panel.Tokens[idPanel].editId });
422
476
  if (status === 'error') return;
423
477
  documents = data;
424
478
  }
425
479
  s(`.btn-${idPanel}-clean`).click();
426
- if (editId && s(`.${idPanel}-${editId}`)) s(`.${idPanel}-${editId}`).remove();
480
+ if (Panel.Tokens[idPanel].editId && s(`.${idPanel}-${Panel.Tokens[idPanel].editId}`))
481
+ s(`.${idPanel}-${Panel.Tokens[idPanel].editId}`).remove();
427
482
  if (Array.isArray(documents)) {
428
483
  htmls(`.${idPanel}-render`, '');
429
484
  for (const doc of documents) {
430
485
  append(`.${idPanel}-render`, await renderPanel(doc));
431
486
  }
432
- } else htmls(`.${idPanel}-render`, await renderPanel(obj));
487
+ } else htmls(`.${idPanel}-render`, await renderPanel({ ...obj, ...documents }));
433
488
  Input.cleanValues(formData);
434
489
  s(`.btn-${idPanel}-close`).click();
435
490
  s(`.${scrollClassContainer}`).scrollTop = 0;
491
+ if (s(`.${scrollClassContainer}`)) s(`.${scrollClassContainer}`).style.overflow = 'auto';
436
492
  });
437
493
  s(`.btn-${idPanel}-clean`).onclick = () => {
438
494
  Input.cleanValues(formData);
@@ -458,13 +514,14 @@ const Panel = {
458
514
  s(`.btn-${idPanel}-add`).onclick = (e) => {
459
515
  e.preventDefault();
460
516
  // s(`.btn-${idPanel}-clean`).click();
461
- editId = undefined;
517
+ Panel.Tokens[idPanel].editId = undefined;
462
518
  s(`.btn-${idPanel}-label-add`).classList.remove('hide');
463
519
  s(`.btn-${idPanel}-label-edit`).classList.add('hide');
464
520
  s(`.${scrollClassContainer}`).scrollTop = 0;
465
521
 
466
522
  openPanelForm();
467
523
  };
524
+ if (s(`.${scrollClassContainer}`)) s(`.${scrollClassContainer}`).style.overflow = 'auto';
468
525
  });
469
526
 
470
527
  if (data.length > 0) for (const obj of data) render += await renderPanel(obj);
@@ -597,7 +654,9 @@ const Panel = {
597
654
  >
598
655
  <div class="in ${idPanel}-form-header">
599
656
  ${await BtnIcon.Render({
600
- class: `section-mp btn-custom btn-${idPanel}-add`,
657
+ class: `section-mp btn-custom btn-${idPanel}-add ${
658
+ options?.role?.add ? (!options.role.add() ? 'hide' : '') : ''
659
+ }`,
601
660
  label: html`<i class="fas fa-plus"></i> ${Translate.Render('add')}`,
602
661
  type: 'button',
603
662
  })}
@@ -90,16 +90,7 @@ const PanelForm = {
90
90
  },
91
91
  },
92
92
  ];
93
- const dateFormat = (date) =>
94
- html`<span
95
- style="${renderCssAttr({
96
- style: {
97
- 'font-size': '14px',
98
- color: '#888',
99
- },
100
- })}"
101
- >${new Date(date).toLocaleString().replaceAll(',', '')}</span
102
- >`;
93
+
103
94
  const titleIcon = html`<i class="fa-solid fa-quote-left"></i>`;
104
95
  const panelRender = async ({ data }) =>
105
96
  await Panel.Render({
@@ -271,7 +262,7 @@ const PanelForm = {
271
262
  fileId: file ? URL.createObjectURL(file) : undefined,
272
263
  _id: documentData._id,
273
264
  id: documentData._id,
274
- createdAt: dateFormat(documentData.createdAt),
265
+ createdAt: documentData.createdAt,
275
266
  };
276
267
 
277
268
  if (documentStatus === 'error') status = 'error';
@@ -376,7 +367,7 @@ const PanelForm = {
376
367
  PanelForm.Data[idPanel].data.push({
377
368
  id: documentObject._id,
378
369
  title: documentObject.title,
379
- createdAt: dateFormat(documentObject.createdAt),
370
+ createdAt: documentObject.createdAt,
380
371
  tags: documentObject.tags.filter((t) => !prefixTags.includes(t)),
381
372
  mdFileId: marked.parse(mdFileId),
382
373
  userId: documentObject.userId._id,
@@ -431,14 +422,9 @@ const PanelForm = {
431
422
  })),
432
423
  });
433
424
 
434
- let lastCid;
435
- let lasUserId;
436
425
  this.Data[idPanel].updatePanel = async () => {
437
426
  const cid = getQueryParams().cid ? getQueryParams().cid : '';
438
- if (lastCid === cid && lasUserId === Elements.Data.user.main.model.user._id) return;
439
427
  if (options.route === 'home') Modal.homeCid = newInstance(cid);
440
- lastCid = cid;
441
- lasUserId = newInstance(Elements.Data.user.main.model.user._id);
442
428
  htmls(`.${options.parentIdModal ? 'html-' + options.parentIdModal : 'main-body'}`, await renderSrrPanelData());
443
429
  await getPanelData();
444
430
  htmls(
@@ -451,7 +437,7 @@ const PanelForm = {
451
437
  id: options.parentIdModal ? 'html-' + options.parentIdModal : 'main-body',
452
438
  routeId: options.route,
453
439
  event: async (path) => {
454
- await this.Data[idPanel].updatePanel();
440
+ if (!PanelForm.Data[idPanel].sessionIn) await this.Data[idPanel].updatePanel();
455
441
  },
456
442
  });
457
443
 
@@ -39,6 +39,7 @@ const Scroll = {
39
39
  delete this.topRefreshEvents[id];
40
40
  },
41
41
  pullTopRefresh: function () {
42
+ return;
42
43
  append(
43
44
  'body',
44
45
  html` <style>
@@ -11,35 +11,49 @@ const Translate = {
11
11
  Data: {},
12
12
  Token: {},
13
13
  Event: {},
14
+ Options: {},
14
15
  Parse: function (lang) {
15
16
  s('html').lang = lang;
16
17
  Object.keys(this.Token).map((translateHash) => {
17
18
  if (translateHash in this.Token && lang in this.Token[translateHash]) {
18
- if (!('placeholder' in this.Token[translateHash]) && s(`.${translateHash}`))
19
- htmls(`.${translateHash}`, textFormatted(this.Token[translateHash][lang]));
19
+ if (!('placeholder' in this.Options[translateHash]) && s(`.${translateHash}`))
20
+ htmls(
21
+ `.${translateHash}`,
22
+ this.Options[translateHash]?.disableTextFormat
23
+ ? this.Token[translateHash][lang]
24
+ : textFormatted(this.Token[translateHash][lang]),
25
+ );
20
26
  else if ('placeholder' in this.Token[translateHash] && s(this.Token[translateHash].placeholder))
21
- s(this.Token[translateHash].placeholder).placeholder = textFormatted(this.Token[translateHash][lang]);
27
+ s(this.Token[translateHash].placeholder).placeholder = this.Options[translateHash]?.disableTextFormat
28
+ ? this.Token[translateHash][lang]
29
+ : textFormatted(this.Token[translateHash][lang]);
22
30
  }
23
31
  });
24
32
  for (const keyEvent of Object.keys(this.Event)) this.Event[keyEvent]();
25
33
  },
26
- Render: function (keyLang, placeholder) {
34
+ Render: function (keyLang, placeholder, options = { disableTextFormat: false }) {
27
35
  if (!(keyLang in this.Data)) {
28
36
  // TODO: add translate package or library for this case
29
37
  logger.warn('translate key lang does not exist: ', keyLang);
30
- return textFormatted(keyLang);
38
+ return options.disableTextFormat ? keyLang : textFormatted(keyLang);
31
39
  }
32
40
  if (placeholder) this.Data[keyLang].placeholder = placeholder;
33
41
  keyLang = this.Data[keyLang];
34
42
  const translateHash = getId(this.Token, 'trans');
43
+ this.Options[translateHash] = options;
35
44
  this.Token[translateHash] = newInstance(keyLang);
36
45
  if ('placeholder' in keyLang) {
37
- if (s('html').lang in keyLang) return textFormatted(keyLang[s('html').lang]);
38
- return textFormatted(keyLang['en']);
46
+ if (s('html').lang in keyLang)
47
+ return options.disableTextFormat ? keyLang[s('html').lang] : textFormatted(keyLang[s('html').lang]);
48
+ return options.disableTextFormat ? keyLang['en'] : textFormatted(keyLang['en']);
39
49
  }
40
50
  if (s('html').lang in keyLang)
41
- return html`<span class="${translateHash}">${textFormatted(keyLang[s('html').lang])}</span>`;
42
- return html`<span class="${translateHash}">${textFormatted(keyLang['en'])}</span>`;
51
+ return html`<span class="${translateHash}"
52
+ >${options.disableTextFormat ? keyLang[s('html').lang] : textFormatted(keyLang[s('html').lang])}</span
53
+ >`;
54
+ return html`<span class="${translateHash}"
55
+ >${options.disableTextFormat ? keyLang['en'] : textFormatted(keyLang['en'])}</span
56
+ >`;
43
57
  },
44
58
  renderLang: function (language) {
45
59
  localStorage.setItem('lang', language);
@@ -474,6 +488,30 @@ const TranslateCore = {
474
488
  Translate.Data['friday'] = { es: 'Viernes', en: 'Friday' };
475
489
  Translate.Data['saturday'] = { es: 'Sábado', en: 'Saturday' };
476
490
  Translate.Data['sunday'] = { es: 'Domingo', en: 'Sunday' };
491
+
492
+ Translate.Data['description'] = { es: 'Descripción', en: 'Description' };
493
+ Translate.Data['daysOfWeek'] = { es: 'Días de la semana', en: 'Days of the week' };
494
+ Translate.Data['startTime'] = { es: 'Hora de inicio', en: 'Start time' };
495
+ Translate.Data['endTime'] = { es: 'Hora de finalizacion', en: 'End time' };
496
+ Translate.Data['appointment-scheduled'] = {
497
+ en: 'Your appointment has been scheduled',
498
+ es: 'Tu cita ha sido programada',
499
+ };
500
+ Translate.Data['info'] = { es: 'Información', en: 'Info' };
501
+ Translate.Data['complete-name'] = { es: 'Nombre completo', en: 'Complete name' };
502
+ Translate.Data['identityDocument'] = { es: 'Rut', en: 'Identity document' };
503
+ Translate.Data['day'] = { es: 'Día', en: 'Day' };
504
+ Translate.Data['month'] = { es: 'Mes', en: 'Month' };
505
+ Translate.Data['year'] = { es: 'Año', en: 'Year' };
506
+ Translate.Data['phone'] = { es: 'Teléfono', en: 'Phone' };
507
+ Translate.Data['invalid-identity-document'] = {
508
+ en: 'Invalid identity document',
509
+ es: 'Documento de identidad inválido',
510
+ };
511
+ Translate.Data['expired-session'] = {
512
+ en: 'Your session has expired. Please log in again.',
513
+ es: 'Su sesión ha expirado. Por favor, inicie sesión de nuevo.',
514
+ };
477
515
  },
478
516
  };
479
517
 
@@ -1,4 +1,4 @@
1
- import { validatePassword } from './CommonJs.js';
1
+ import { isChileanIdentityDocument, validatePassword } from './CommonJs.js';
2
2
  import { renderStatus } from './Css.js';
3
3
  import { loggerFactory } from './Logger.js';
4
4
  import { textFormatted, Translate } from './Translate.js';
@@ -58,6 +58,14 @@ const Validator = {
58
58
  if (!validator.isLength(s(`.${validatorData.id}`).value, rule.options))
59
59
  errorMessage += this.renderErrorMessage(rule);
60
60
  break;
61
+
62
+ case 'isChileanIdentityDocument': {
63
+ if (!isChileanIdentityDocument(s(`.${validatorData.id}`).value)) {
64
+ errorMessage += this.renderErrorMessage(undefined, Translate.Render('invalid-identity-document'));
65
+ }
66
+
67
+ break;
68
+ }
61
69
  default:
62
70
  if (
63
71
  validator[rule.type] &&
@@ -419,14 +419,6 @@ const isActiveTab = () => document.hasFocus();
419
419
  const isActiveElement = (classSearch = '') =>
420
420
  document.activeElement?.classList?.value?.match(classSearch) ? true : false;
421
421
 
422
- const getCurrentTrace = () => {
423
- try {
424
- _stack;
425
- } catch (error) {
426
- return error.stack.split('is not defined')[1];
427
- }
428
- };
429
-
430
422
  const isDevInstance = () => location.origin.match('localhost') && location.port;
431
423
 
432
424
  const getDataFromInputFile = async (file) => Array.from(new Uint8Array(await file.arrayBuffer()));
@@ -460,7 +452,6 @@ export {
460
452
  isNavigator,
461
453
  getTimeZone,
462
454
  getAllChildNodes,
463
- getCurrentTrace,
464
455
  isActiveTab,
465
456
  isActiveElement,
466
457
  isDevInstance,
@@ -22,41 +22,44 @@ const Worker = {
22
22
  setTimeout(() => {
23
23
  if ('onLine' in navigator && navigator.onLine) window.ononline();
24
24
  });
25
- navigator.serviceWorker.addEventListener('controllerchange', () => {
26
- logger.info('The controller of current browsing context has changed.');
27
- });
28
- navigator.serviceWorker.ready.then((worker) => {
29
- logger.info('Ready', worker);
30
- // event message
31
- navigator.serviceWorker.addEventListener('message', (event) => {
32
- logger.info('Received event message', event.data);
33
- const { status } = event.data;
25
+ if ('serviceWorker' in navigator) {
26
+ navigator.serviceWorker.addEventListener('controllerchange', () => {
27
+ logger.info('The controller of current browsing context has changed.');
28
+ });
29
+ navigator.serviceWorker.ready.then((worker) => {
30
+ logger.info('Ready', worker);
31
+ // event message
32
+ navigator.serviceWorker.addEventListener('message', (event) => {
33
+ logger.info('Received event message', event.data);
34
+ const { status } = event.data;
34
35
 
35
- switch (status) {
36
- case 'loader':
37
- {
38
- LoadingAnimation.RenderCurrentSrcLoad(event);
39
- }
40
- break;
36
+ switch (status) {
37
+ case 'loader':
38
+ {
39
+ LoadingAnimation.RenderCurrentSrcLoad(event);
40
+ }
41
+ break;
41
42
 
42
- default:
43
- break;
44
- }
45
- });
43
+ default:
44
+ break;
45
+ }
46
+ });
46
47
 
47
- // if (navigator.serviceWorker.controller)
48
- // navigator.serviceWorker.controller.postMessage({
49
- // title: 'Hello from Client event message',
50
- // });
48
+ // if (navigator.serviceWorker.controller)
49
+ // navigator.serviceWorker.controller.postMessage({
50
+ // title: 'Hello from Client event message',
51
+ // });
52
+
53
+ // broadcast message
54
+ // const channel = new BroadcastChannel('sw-messages');
55
+ // channel.addEventListener('message', (event) => {
56
+ // logger.info('Received broadcast message', event.data);
57
+ // });
58
+ // channel.postMessage({ title: 'Hello from Client broadcast message' });
59
+ // channel.close();
60
+ });
61
+ }
51
62
 
52
- // broadcast message
53
- // const channel = new BroadcastChannel('sw-messages');
54
- // channel.addEventListener('message', (event) => {
55
- // logger.info('Received broadcast message', event.data);
56
- // });
57
- // channel.postMessage({ title: 'Hello from Client broadcast message' });
58
- // channel.close();
59
- });
60
63
  this.RouterInstance = router();
61
64
  const isInstall = await this.status();
62
65
  if (!isInstall) await this.install();
@@ -1,6 +1,6 @@
1
1
  import { AgGrid } from '../../components/core/AgGrid.js';
2
2
  import { BtnIcon } from '../../components/core/BtnIcon.js';
3
- import { getId, timer } from '../../components/core/CommonJs.js';
3
+ import { getId, getValueFromJoinString, timer } from '../../components/core/CommonJs.js';
4
4
  import { darkTheme } from '../../components/core/Css.js';
5
5
  import { EventsUI } from '../../components/core/EventsUI.js';
6
6
  import { loggerFactory } from '../../components/core/Logger.js';
@@ -88,7 +88,9 @@ const DefaultManagement = {
88
88
  ${Translate.Render('confirm-delete-item')}
89
89
  ${Object.keys(params.data).length > 0
90
90
  ? html`<br />
91
- "${params.data[Object.keys(params.data)[0]]}"`
91
+ "${options.defaultColKeyFocus
92
+ ? getValueFromJoinString(params.data, options.defaultColKeyFocus)
93
+ : params.data[Object.keys(params.data)[0]]}"`
92
94
  : ''}
93
95
  </div>
94
96
  `;
@@ -106,10 +106,10 @@ SrrComponent = ({ ttiLoadTimeLimit }) => {
106
106
  </style>
107
107
  ${borderChar(1, 'black', ['.clean-cache-container'])}
108
108
  <script>
109
- window._VERSION = '${process.env.npm_package_version}';
109
+ window._VERSION = '${npm_package_version}';
110
110
  const CacheControl = ${CacheControl};
111
111
  CacheControl({ ttiLoadTimeLimit: ${ttiLoadTimeLimit ? ttiLoadTimeLimit : 1000 * 70 * 1} });
112
112
  </script>
113
- <div class="clean-cache-container">${process.env.npm_package_version}</div>
113
+ <div class="clean-cache-container">${npm_package_version}</div>
114
114
  `;
115
115
  };
@@ -9,7 +9,12 @@ const MongooseDB = {
9
9
  connect: async (host, name) => {
10
10
  const uri = `${host}/${name}`;
11
11
  // logger.info('MongooseDB connect', { host, name, uri });
12
- return await mongoose.createConnection(uri).asPromise();
12
+ return await mongoose
13
+ .createConnection(uri, {
14
+ // useNewUrlParser: true,
15
+ // useUnifiedTopology: true,
16
+ })
17
+ .asPromise();
13
18
  return new Promise((resolve, reject) =>
14
19
  mongoose
15
20
  .connect(
@@ -67,8 +72,15 @@ const MongooseDB = {
67
72
  shellExec(`sudo rm -r /var/lib/mongodb`);
68
73
  // restore lib
69
74
  // shellExec(`sudo chown -R mongodb:mongodb /var/lib/mongodb/*`);
75
+ // mongod --repair
70
76
 
71
77
  if (process.argv.includes('legacy')) {
78
+ // TODO:
79
+ if (process.argv.includes('rocky')) {
80
+ // https://github.com/mongodb/mongodb-selinux
81
+ // https://www.mongodb.com/docs/v7.0/tutorial/install-mongodb-enterprise-on-red-hat/
82
+ shellExec(`sudo chown -R mongod:mongod /var/lib/mongo`);
83
+ }
72
84
  logger.info('install legacy 4.4');
73
85
  shellExec(`wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -`);
74
86