underpost 2.8.847 → 2.8.848

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.
package/README.md CHANGED
@@ -38,6 +38,10 @@ template
38
38
 
39
39
 
40
40
 
41
+
42
+
43
+
44
+
41
45
 
42
46
 
43
47
 
@@ -46,7 +50,7 @@ template
46
50
  <!-- badges -->
47
51
 
48
52
 
49
- [![Node.js CI](https://github.com/underpostnet/engine/actions/workflows/docker-image.ci.yml/badge.svg?branch=master)](https://github.com/underpostnet/engine/actions/workflows/docker-image.yml) [![Test](https://github.com/underpostnet/engine/actions/workflows/coverall.ci.yml/badge.svg?branch=master)](https://github.com/underpostnet/engine/actions/workflows/coverall.yml) [![Downloads](https://img.shields.io/npm/dm/underpost.svg)](https://www.npmjs.com/package/underpost) [![Socket Badge](https://socket.dev/api/badge/npm/package/underpost/2.8.847)](https://socket.dev/npm/package/underpost/overview/2.8.847) [![Coverage Status](https://coveralls.io/repos/github/underpostnet/engine/badge.svg?branch=master)](https://coveralls.io/github/underpostnet/engine?branch=master) [![Version](https://img.shields.io/npm/v/underpost.svg)](https://www.npmjs.org/package/underpost) [![License](https://img.shields.io/npm/l/underpost.svg)](https://www.npmjs.com/package/underpost)
53
+ [![Node.js CI](https://github.com/underpostnet/engine/actions/workflows/docker-image.ci.yml/badge.svg?branch=master)](https://github.com/underpostnet/engine/actions/workflows/docker-image.yml) [![Test](https://github.com/underpostnet/engine/actions/workflows/coverall.ci.yml/badge.svg?branch=master)](https://github.com/underpostnet/engine/actions/workflows/coverall.yml) [![Downloads](https://img.shields.io/npm/dm/underpost.svg)](https://www.npmjs.com/package/underpost) [![Socket Badge](https://socket.dev/api/badge/npm/package/underpost/2.8.848)](https://socket.dev/npm/package/underpost/overview/2.8.848) [![Coverage Status](https://coveralls.io/repos/github/underpostnet/engine/badge.svg?branch=master)](https://coveralls.io/github/underpostnet/engine?branch=master) [![Version](https://img.shields.io/npm/v/underpost.svg)](https://www.npmjs.org/package/underpost) [![License](https://img.shields.io/npm/l/underpost.svg)](https://www.npmjs.com/package/underpost)
50
54
 
51
55
 
52
56
  <!-- end-badges -->
@@ -67,6 +71,10 @@ template
67
71
 
68
72
 
69
73
 
74
+
75
+
76
+
77
+
70
78
 
71
79
 
72
80
 
@@ -116,7 +124,7 @@ Run dev client server
116
124
  npm run dev
117
125
  ```
118
126
  <!-- -->
119
- ## underpost ci/cd cli v2.8.847
127
+ ## underpost ci/cd cli v2.8.848
120
128
 
121
129
  ### Usage: `underpost [options] [command]`
122
130
  ```
package/cli.md CHANGED
@@ -1,4 +1,4 @@
1
- ## underpost ci/cd cli v2.8.847
1
+ ## underpost ci/cd cli v2.8.848
2
2
 
3
3
  ### Usage: `underpost [options] [command]`
4
4
  ```
@@ -574,7 +574,7 @@ Options:
574
574
  Runs a script from the specified path.
575
575
 
576
576
  Arguments:
577
- runner-id The runner ID to run. Options: spark-template, rmi, kill, secret, gpu-env, tf-gpu-test, dev-cluster, cyberia-ide, engine-ide, ssh-deploy, ide, monitor, db-client, cluster, deploy, tf-vae-test, deploy-job.
577
+ runner-id The runner ID to run. Options: spark-template, rmi, kill, secret, gpu-env, tf-gpu-test, dev-cluster, cyberia-ide, engine-ide, template-deploy, ssh-deploy, ide, monitor, db-client, cluster, deploy, tf-vae-test, deploy-job.
578
578
  path The absolute or relative directory path where the script is located.
579
579
 
580
580
  Options:
package/conf.js CHANGED
@@ -6,7 +6,7 @@ const DefaultConf = /**/ {
6
6
  client: {
7
7
  default: {
8
8
  metadata: {
9
- title: 'Demo App',
9
+ title: 'PWA Demo App',
10
10
  backgroundImage: 'assets/background/white0-min.jpg',
11
11
  description: 'Web application',
12
12
  keywords: ['web', 'app', 'spa', 'demo', 'github-pages'],
@@ -58,7 +58,7 @@ services:
58
58
  cpus: '0.25'
59
59
  memory: 20M
60
60
  labels: # labels in Compose file instead of Dockerfile
61
- engine.version: '2.8.847'
61
+ engine.version: '2.8.848'
62
62
  networks:
63
63
  - load-balancer
64
64
 
@@ -17,7 +17,7 @@ spec:
17
17
  spec:
18
18
  containers:
19
19
  - name: dd-template-development-blue
20
- image: localhost/rockylinux9-underpost:v2.8.847
20
+ image: localhost/rockylinux9-underpost:v2.8.848
21
21
  # resources:
22
22
  # requests:
23
23
  # memory: "124Ki"
@@ -100,7 +100,7 @@ spec:
100
100
  spec:
101
101
  containers:
102
102
  - name: dd-template-development-green
103
- image: localhost/rockylinux9-underpost:v2.8.847
103
+ image: localhost/rockylinux9-underpost:v2.8.848
104
104
  # resources:
105
105
  # requests:
106
106
  # memory: "124Ki"
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "type": "module",
3
3
  "main": "src/index.js",
4
4
  "name": "underpost",
5
- "version": "2.8.847",
5
+ "version": "2.8.848",
6
6
  "description": "pwa api rest template",
7
7
  "scripts": {
8
8
  "start": "env-cmd -f .env.production node --max-old-space-size=8192 src/server",
@@ -444,7 +444,7 @@ const UserService = {
444
444
  _id: user._id,
445
445
  }).select(UserDto.select.get());
446
446
  } else throw new Error('invalid token');
447
- }
447
+ } else delete req.body.password;
448
448
 
449
449
  switch (req.params.id) {
450
450
  default: {
@@ -453,9 +453,6 @@ const UserService = {
453
453
  });
454
454
  switch (user.role) {
455
455
  case 'admin': {
456
- if (req.body.password !== undefined && req.body.password !== user.password)
457
- req.body.password = await hashPassword(req.body.password);
458
- else delete req.body.password;
459
456
  return await User.findByIdAndUpdate(req.params.id, req.body, {
460
457
  runValidators: true,
461
458
  });
package/src/cli/run.js CHANGED
@@ -86,6 +86,13 @@ class UnderpostRun {
86
86
  shellExec(`${baseCommand} run ide /home/dd/engine`);
87
87
  shellExec(`${baseCommand} run ide /home/dd/engine/engine-private`);
88
88
  },
89
+ 'template-deploy': (path, options = UnderpostRun.DEFAULT_OPTION) => {
90
+ const baseCommand = options.dev || true ? 'node bin' : 'underpost';
91
+ shellCd('/home/dd/engine');
92
+ shellExec(`git reset`);
93
+ shellExec(`${baseCommand} cmt . --empty ci package-pwa-microservices-template`);
94
+ shellExec(`${baseCommand} push . underpostnet/engine`);
95
+ },
89
96
  'ssh-deploy': (path, options = UnderpostRun.DEFAULT_OPTION) => {
90
97
  const baseCommand = options.dev || true ? 'node bin' : 'underpost';
91
98
  shellCd('/home/dd/engine');
@@ -16,6 +16,7 @@ import { SocketIo } from './components/core/SocketIo.js';
16
16
  import { SocketIoDefault } from './components/default/SocketIoDefault.js';
17
17
  import { ElementsDefault } from './components/default/ElementsDefault.js';
18
18
  import { Scroll } from './components/core/Scroll.js';
19
+ import { CssDefaultDark, CssDefaultLight } from './components/default/CssDefault.js';
19
20
 
20
21
  const htmlMainBody = async () => {
21
22
  return html`<span>Hello World!!</span>`;
@@ -25,12 +26,15 @@ window.onload = () =>
25
26
  Worker.instance({
26
27
  router: RouterDefault,
27
28
  render: async () => {
28
- await Css.loadThemes();
29
+ await Css.loadThemes([CssDefaultLight, CssDefaultDark]);
29
30
  await TranslateCore.Init();
30
31
  await TranslateDefault.Init();
31
32
  await Responsive.Init();
32
33
  await MenuDefault.Render({ htmlMainBody });
33
- await SocketIo.Init({ channels: ElementsDefault.Data });
34
+ await SocketIo.Init({
35
+ channels: ElementsDefault.Data,
36
+ path: `/`,
37
+ });
34
38
  await SocketIoDefault.Init();
35
39
  await LogInDefault();
36
40
  await LogOutDefault();
@@ -44,7 +44,7 @@ const Account = {
44
44
  { model: 'email', id: `account-email`, rules: [{ type: 'isEmpty' }, { type: 'isEmail' }] },
45
45
  {
46
46
  model: 'password',
47
- defaultValue: '*******',
47
+ defaultValue: '#Changethis123',
48
48
  id: `account-password`,
49
49
  rules: [{ type: 'isStrongPassword' }],
50
50
  },
@@ -51,8 +51,8 @@ const Css = {
51
51
  // if (!ThemesScope.find((t) => t.dark)) addTheme(CssCoreDark);
52
52
  // if (!ThemesScope.find((t) => !t.dark)) addTheme(CssCoreLight);
53
53
  if (ThemesScope.length === 0) {
54
- addTheme(CssCoreDark);
55
54
  addTheme(CssCoreLight);
55
+ addTheme(CssCoreDark);
56
56
  }
57
57
  const localStorageTheme = localStorage.getItem('_theme');
58
58
  if (localStorageTheme && Themes[localStorageTheme]) {
@@ -199,6 +199,7 @@ const addTheme = (options) => {
199
199
  if (!['core', 'css-core'].includes(options.theme))
200
200
  render += darkTheme ? await CssCoreDark.render() : await CssCoreLight.render();
201
201
  render += await options.render();
202
+ render += await subThemeManager.render();
202
203
  htmls('.theme', render);
203
204
  TriggerThemeEvents();
204
205
  }
@@ -232,18 +233,29 @@ const borderChar = (px, color, selectors, hover = false) => {
232
233
  ${color}, ${px}px ${px}px ${px}px ${color};
233
234
  `;
234
235
  };
235
-
236
236
  const boxShadow = ({ selector }) => html`
237
- <style>
238
- ${selector} {
239
- box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
240
- }
241
- ${selector}:hover {
242
- box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2), 0 10px 30px 0 rgba(0, 0, 0, 0.3);
243
- }
244
- </style>
237
+ ${darkTheme
238
+ ? html`
239
+ <style>
240
+ ${selector} {
241
+ box-shadow: 0 4px 8px 0 rgba(255, 255, 255, 0.1), 0 6px 20px 0 rgba(255, 255, 255, 0.08);
242
+ }
243
+ ${selector}:hover {
244
+ box-shadow: 0 8px 16px 0 rgba(255, 255, 255, 0.15), 0 10px 30px 0 rgba(255, 255, 255, 0.1);
245
+ }
246
+ </style>
247
+ `
248
+ : html`
249
+ <style>
250
+ ${selector} {
251
+ box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
252
+ }
253
+ ${selector}:hover {
254
+ box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2), 0 10px 30px 0 rgba(0, 0, 0, 0.3);
255
+ }
256
+ </style>
257
+ `}
245
258
  `;
246
-
247
259
  const renderMediaQuery = (mediaData) => {
248
260
  // first limit should be '0'
249
261
  return html`
@@ -677,6 +689,166 @@ const scrollBarLightRender = () => {
677
689
  .join('');
678
690
  };
679
691
 
692
+ /**
693
+ * Adjust hex color brightness toward white/black ("mix") or by modifying HSL lightness ("hsl").
694
+ *
695
+ * @param {string} hex - Color as '#rrggbb', 'rrggbb', '#rgb', or 'rgb'.
696
+ * @param {number} factor - -1..1 or -100..100 (percent). Positive = lighten, negative = darken.
697
+ * @param {{mode?: 'mix'|'hsl'}} [options]
698
+ * @returns {string} - Adjusted color as '#rrggbb' (lowercase).
699
+ */
700
+ function adjustHex(hex, factor = 0.1, options = {}) {
701
+ if (typeof hex !== 'string') throw new TypeError('hex must be a string');
702
+ if (typeof factor !== 'number') throw new TypeError('factor must be a number');
703
+
704
+ // normalize factor: allow -100..100 or -1..1
705
+ if (factor > 1 && factor <= 100) factor = factor / 100;
706
+ if (factor < -1 && factor >= -100) factor = factor / 100;
707
+ factor = Math.max(-1, Math.min(1, factor));
708
+
709
+ const mode = options.mode === 'hsl' ? 'hsl' : 'mix';
710
+
711
+ // normalize hex
712
+ let h = hex.replace(/^#/, '').trim();
713
+ if (!(h.length === 3 || h.length === 6)) throw new Error('Invalid hex format');
714
+ if (h.length === 3)
715
+ h = h
716
+ .split('')
717
+ .map((c) => c + c)
718
+ .join('');
719
+
720
+ const r = parseInt(h.slice(0, 2), 16);
721
+ const g = parseInt(h.slice(2, 4), 16);
722
+ const b = parseInt(h.slice(4, 6), 16);
723
+
724
+ const clamp = (v, a = 0, z = 255) => Math.max(a, Math.min(z, v));
725
+
726
+ const rgbToHex = (rr, gg, bb) =>
727
+ '#' +
728
+ [rr, gg, bb]
729
+ .map((v) => Math.round(v).toString(16).padStart(2, '0'))
730
+ .join('')
731
+ .toLowerCase();
732
+
733
+ if (mode === 'mix') {
734
+ // positive: mix toward white (255); negative: mix toward black (0)
735
+ const mixChannel = (c) => {
736
+ if (factor >= 0) {
737
+ return clamp(Math.round(c + (255 - c) * factor));
738
+ } else {
739
+ const a = Math.abs(factor);
740
+ return clamp(Math.round(c * (1 - a)));
741
+ }
742
+ };
743
+ return rgbToHex(mixChannel(r), mixChannel(g), mixChannel(b));
744
+ } else {
745
+ // HSL mode: convert rgb to hsl, adjust L by factor, convert back
746
+ const rgbToHsl = (r, g, b) => {
747
+ r /= 255;
748
+ g /= 255;
749
+ b /= 255;
750
+ const max = Math.max(r, g, b),
751
+ min = Math.min(r, g, b);
752
+ let h = 0,
753
+ s = 0,
754
+ l = (max + min) / 2;
755
+ if (max !== min) {
756
+ const d = max - min;
757
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
758
+ switch (max) {
759
+ case r:
760
+ h = (g - b) / d + (g < b ? 6 : 0);
761
+ break;
762
+ case g:
763
+ h = (b - r) / d + 2;
764
+ break;
765
+ case b:
766
+ h = (r - g) / d + 4;
767
+ break;
768
+ }
769
+ h /= 6;
770
+ }
771
+ return { h, s, l };
772
+ };
773
+
774
+ const hslToRgb = (h, s, l) => {
775
+ let r, g, b;
776
+ if (s === 0) {
777
+ r = g = b = l;
778
+ } else {
779
+ const hue2rgb = (p, q, t) => {
780
+ if (t < 0) t += 1;
781
+ if (t > 1) t -= 1;
782
+ if (t < 1 / 6) return p + (q - p) * 6 * t;
783
+ if (t < 1 / 2) return q;
784
+ if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
785
+ return p;
786
+ };
787
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
788
+ const p = 2 * l - q;
789
+ r = hue2rgb(p, q, h + 1 / 3);
790
+ g = hue2rgb(p, q, h);
791
+ b = hue2rgb(p, q, h - 1 / 3);
792
+ }
793
+ return { r: r * 255, g: g * 255, b: b * 255 };
794
+ };
795
+
796
+ const { h: hh, s: ss, l: ll } = rgbToHsl(r, g, b);
797
+ // add factor to lightness (factor already normalized -1..1)
798
+ let newL = ll + factor;
799
+ newL = Math.max(0, Math.min(1, newL));
800
+ const { r: r2, g: g2, b: b2 } = hslToRgb(hh, ss, newL);
801
+ return rgbToHex(r2, g2, b2);
802
+ }
803
+ }
804
+
805
+ // Convenience helpers:
806
+ function lightenHex(hex, percentOr01 = 0.1, options = {}) {
807
+ return adjustHex(hex, Math.abs(percentOr01), options);
808
+ }
809
+ function darkenHex(hex, percentOr01 = 0.1, options = {}) {
810
+ return adjustHex(hex, -Math.abs(percentOr01), options);
811
+ }
812
+
813
+ const subThemeManager = {
814
+ render: async function () {
815
+ if (darkTheme && this.renderDark) {
816
+ return await this.renderDark();
817
+ } else if (!darkTheme && this.renderLight) {
818
+ return await this.renderLight();
819
+ }
820
+ return html``;
821
+ },
822
+ lightColor: null,
823
+ setLightTheme: function (color) {
824
+ this.lightColor = color;
825
+ this.renderLight = async function () {
826
+ return html`<style>
827
+ button:hover,
828
+ .a-btn:hover,
829
+ .main-btn-menu-active {
830
+ color: ${this.lightColor};
831
+ background-color: ${lightenHex(this.lightColor, 0.8)};
832
+ }
833
+ </style>`;
834
+ };
835
+ },
836
+ darkColor: null,
837
+ setDarkTheme: function (color) {
838
+ this.darkColor = color;
839
+ this.renderDark = async function () {
840
+ return html`<style>
841
+ button:hover,
842
+ .a-btn:hover,
843
+ .main-btn-menu-active {
844
+ color: ${lightenHex(this.darkColor, 0.8)};
845
+ background-color: ${darkenHex(this.darkColor, 0.75)};
846
+ }
847
+ </style>`;
848
+ };
849
+ },
850
+ };
851
+
680
852
  const scrollBarDarkRender = () => {
681
853
  return cssBrowserCodes
682
854
  .map(
@@ -685,8 +857,8 @@ const scrollBarDarkRender = () => {
685
857
  ::-` +
686
858
  b +
687
859
  `-scrollbar {
688
- width: 5px;
689
- height: 5px;
860
+ width: 8px;
861
+ height: 8px;
690
862
  /* line-height: 1em; */
691
863
  }
692
864
 
@@ -702,7 +874,7 @@ const scrollBarDarkRender = () => {
702
874
  b +
703
875
  `-scrollbar-thumb {
704
876
  background: #74747457;
705
- border-radius: 3px;
877
+ border-radius: 4px;
706
878
  }
707
879
 
708
880
  /* Handle on hover */
@@ -907,4 +1079,8 @@ export {
907
1079
  simpleIconsRender,
908
1080
  extractBackgroundImageUrl,
909
1081
  renderChessPattern,
1082
+ subThemeManager,
1083
+ lightenHex,
1084
+ darkenHex,
1085
+ adjustHex,
910
1086
  };
@@ -33,7 +33,7 @@ const CssCommonCore = async () => {
33
33
  top: 0;
34
34
  left: 0;
35
35
  transition: 0.3s;
36
- height: 5px;
36
+ height: 10px;
37
37
  width: 100%;
38
38
  z-index: 11;
39
39
  }
@@ -16,10 +16,7 @@ const Docs = {
16
16
  const docData = this.Data.find((d) => d.type === type);
17
17
  const ModalId = `modal-docs-${docData.type}`;
18
18
  const { barConfig } = await Themes[Css.currentTheme]();
19
- barConfig.buttons.close.onClick = () => {
20
- setQueryPath({ path: 'docs' });
21
- Modal.removeModal(ModalId);
22
- };
19
+
23
20
  await Modal.Render({
24
21
  barConfig,
25
22
  title: renderViewTitle(docData),
@@ -53,6 +50,9 @@ const Docs = {
53
50
  }
54
51
  };
55
52
  Modal.Data[ModalId].onObserverListener[ModalId]();
53
+ Modal.Data[ModalId].onCloseListener[ModalId] = () => {
54
+ setQueryPath({ path: 'docs', queryPath: '' });
55
+ };
56
56
  },
57
57
  Data: [
58
58
  {
@@ -1,7 +1,7 @@
1
1
  import { CoreService } from '../../services/core/core.service.js';
2
2
  import { BtnIcon } from './BtnIcon.js';
3
3
  import { s4 } from './CommonJs.js';
4
- import { darkTheme, renderCssAttr } from './Css.js';
4
+ import { darkTheme, renderCssAttr, subThemeManager } from './Css.js';
5
5
  import { loggerFactory } from './Logger.js';
6
6
  import { append, getAllChildNodes, getProxyPath, htmls, s, sa } from './VanillaJs.js';
7
7
 
@@ -23,12 +23,12 @@ const LoadingAnimation = {
23
23
  <div
24
24
  class="fix progress-bar box-shadow ${id}"
25
25
  style="left: -100%; background: ${darkTheme
26
- ? LoadingAnimation.darkColor
27
- ? LoadingAnimation.darkColor
28
- : `#c9c9c9`
29
- : LoadingAnimation.lightColor
30
- ? LoadingAnimation.lightColor
31
- : `#515151`};"
26
+ ? subThemeManager.darkColor
27
+ ? subThemeManager.darkColor
28
+ : `#66e400`
29
+ : subThemeManager.lightColor
30
+ ? subThemeManager.lightColor
31
+ : `#157e00`};"
32
32
  ></div>
33
33
  `,
34
34
  );
@@ -140,14 +140,7 @@ const LoadingAnimation = {
140
140
  }, 300);
141
141
  });
142
142
  },
143
- lightColor: null,
144
- setLightColor: function (color) {
145
- this.lightColor = color;
146
- },
147
- darkColor: null,
148
- setDarkColor: function (color) {
149
- this.darkColor = color;
150
- },
143
+
151
144
  RenderCurrentSrcLoad: function (event) {
152
145
  if (s(`.ssr-loading-info`)) {
153
146
  let nameSrcLoad = event.data.path;
@@ -166,9 +166,9 @@ const Modal = {
166
166
  height: 100px;
167
167
  }
168
168
  .default-slide-menu-top-bar-fix-logo {
169
- width: 80px;
170
- height: 80px;
171
- padding: 10px;
169
+ width: 50px;
170
+ height: 50px;
171
+ padding: 24px;
172
172
  }
173
173
  .default-slide-menu-top-bar-fix-title-container-text {
174
174
  font-size: 30px;
@@ -502,7 +502,9 @@ const Modal = {
502
502
  class="abs modal slide-menu-top-bar-fix"
503
503
  style="height: ${options.heightTopBar}px; top: 0px"
504
504
  >
505
- <a class="a-link-top-banner"> ${await options.slideMenuTopBarBannerFix()}</a>
505
+ <a class="a-link-top-banner">
506
+ <div class="inl">${await options.slideMenuTopBarBannerFix()}</div></a
507
+ >
506
508
  </div>`
507
509
  : ''}
508
510
  </div>`,
@@ -711,6 +713,9 @@ const Modal = {
711
713
 
712
714
  const updateSearchBoxValue = (selector) => {
713
715
  if (!selector) selector = getDefaultSearchBoxSelector();
716
+ // check exist childNodes
717
+ if (!s(selector) || !s(selector).hasChildNodes()) return;
718
+
714
719
  if (s(selector).childNodes) {
715
720
  if (
716
721
  s(selector).childNodes[s(selector).childNodes.length - 1] &&
@@ -734,6 +739,10 @@ const Modal = {
734
739
 
735
740
  const setSearchValue = (selector) => {
736
741
  if (!selector) selector = getDefaultSearchBoxSelector();
742
+
743
+ // check exist childNodes
744
+ if (!s(selector) || !s(selector).hasChildNodes()) return;
745
+
737
746
  historySearchBox = historySearchBox.filter(
738
747
  (h) => h.routerId !== results[currentKeyBoardSearchBoxIndex].routerId,
739
748
  );
@@ -1538,12 +1547,12 @@ const Modal = {
1538
1547
  if (
1539
1548
  ![idModal, 'main-body-top', 'main-body'].concat(this.Data[idModal]?.homeModals || []).includes(keyModal)
1540
1549
  )
1541
- s(`.btn-close-${keyModal}`).click();
1550
+ if (s(`.btn-close-${keyModal}`)) s(`.btn-close-${keyModal}`).click();
1542
1551
  backMenuButtonEvent();
1543
1552
  }
1544
- s(`.btn-close-modal-menu`).click();
1553
+ if (s(`.btn-close-modal-menu`)) s(`.btn-close-modal-menu`).click();
1545
1554
  setPath(getProxyPath());
1546
- setDocTitle({ ...options.RouterInstance, route: '' });
1555
+ setDocTitle();
1547
1556
  };
1548
1557
  s(`.main-btn-home`).onclick = async () => {
1549
1558
  // await this.onHomeRouterEvent();
@@ -2217,7 +2226,6 @@ const Modal = {
2217
2226
  if (s(`.a-link-top-banner`)) {
2218
2227
  s(`.a-link-top-banner`).setAttribute('href', `${location.origin}${getProxyPath()}`);
2219
2228
  EventsUI.onClick(`.a-link-top-banner`, (e) => {
2220
- if (location.pathname === '/') return location.reload();
2221
2229
  e.preventDefault();
2222
2230
  s(`.action-btn-home`).click();
2223
2231
  });
@@ -15,7 +15,7 @@ import { getSrcFromFileData } from './Input.js';
15
15
  import { imageShimmer, renderCssAttr } from './Css.js';
16
16
  import { Translate } from './Translate.js';
17
17
  import { Modal } from './Modal.js';
18
- import { closeModalRouteChangeEvents, listenQueryPathInstance, renderTitle, setQueryPath } from './Router.js';
18
+ import { closeModalRouteChangeEvents, listenQueryPathInstance, setQueryPath } from './Router.js';
19
19
 
20
20
  const PanelForm = {
21
21
  Data: {},
@@ -92,7 +92,7 @@ const PanelForm = {
92
92
  },
93
93
  ];
94
94
 
95
- const titleIcon = html`<i class="fa-solid fa-quote-left"></i>`;
95
+ const titleIcon = html`<i class="fa-solid fa-quote-left title-icon-${idPanel}"></i>`;
96
96
  const panelRender = async ({ data }) =>
97
97
  await Panel.Render({
98
98
  idPanel,
@@ -440,7 +440,6 @@ const PanelForm = {
440
440
  if (options.route === 'home') Modal.homeCid = newInstance(cid);
441
441
  htmls(`.${options.parentIdModal ? 'html-' + options.parentIdModal : 'main-body'}`, await renderSrrPanelData());
442
442
  await getPanelData();
443
- if (this.Data[idPanel].data.length === 1) renderTitle(this.Data[idPanel].data[0].title);
444
443
  htmls(
445
444
  `.${options.parentIdModal ? 'html-' + options.parentIdModal : 'main-body'}`,
446
445
  await panelRender({ data: this.Data[idPanel].data }),