cyberia 3.0.2 → 3.0.3

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 (47) hide show
  1. package/CHANGELOG.md +323 -290
  2. package/CLI-HELP.md +2 -1
  3. package/bin/build.js +0 -1
  4. package/bin/cyberia.js +98 -4
  5. package/bin/index.js +98 -4
  6. package/conf.js +192 -0
  7. package/deployment.yaml +72 -2
  8. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +1 -1
  9. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +1 -1
  10. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  11. package/manifests/deployment/dd-test-development/deployment.yaml +2 -2
  12. package/package.json +13 -9
  13. package/proxy.yaml +56 -9
  14. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +40 -7
  15. package/src/api/object-layer/object-layer.model.js +61 -19
  16. package/src/api/object-layer/object-layer.service.js +4 -9
  17. package/src/cli/index.js +6 -0
  18. package/src/cli/run.js +30 -2
  19. package/src/client/Underpost.index.js +36 -0
  20. package/src/client/components/core/Modal.js +2 -0
  21. package/src/client/components/core/PublicProfile.js +3 -3
  22. package/src/client/components/core/Router.js +34 -1
  23. package/src/client/components/core/Worker.js +1 -1
  24. package/src/client/components/cryptokoyn/CssCryptokoyn.js +63 -1
  25. package/src/client/components/cyberia/ObjectLayerEngineModal.js +145 -119
  26. package/src/client/components/cyberia/ObjectLayerEngineViewer.js +64 -6
  27. package/src/client/components/itemledger/CssItemledger.js +62 -0
  28. package/src/client/components/underpost/CommonUnderpost.js +29 -0
  29. package/src/client/components/underpost/CssUnderpost.js +222 -0
  30. package/src/client/components/underpost/CyberpunkBloggerUnderpost.js +879 -0
  31. package/src/client/components/underpost/DocumentSearchProvider.js +448 -0
  32. package/src/client/components/underpost/ElementsUnderpost.js +38 -0
  33. package/src/client/components/underpost/LabGalleryUnderpost.js +82 -0
  34. package/src/client/components/underpost/LogInUnderpost.js +20 -0
  35. package/src/client/components/underpost/LogOutUnderpost.js +13 -0
  36. package/src/client/components/underpost/MenuUnderpost.js +605 -0
  37. package/src/client/components/underpost/RoutesUnderpost.js +45 -0
  38. package/src/client/components/underpost/SettingsUnderpost.js +16 -0
  39. package/src/client/components/underpost/SignUpUnderpost.js +9 -0
  40. package/src/client/components/underpost/SocketIoUnderpost.js +54 -0
  41. package/src/client/components/underpost/TranslateUnderpost.js +10 -0
  42. package/src/client/services/object-layer/object-layer.management.js +23 -4
  43. package/src/client/ssr/body/UnderpostDefaultSplashScreen.js +83 -0
  44. package/src/client/ssr/head/UnderpostScripts.js +6 -0
  45. package/src/index.js +1 -1
  46. package/src/server/object-layer.js +13 -10
  47. package/src/server/semantic-layer-generator.js +1 -0
@@ -0,0 +1,605 @@
1
+ import { Account } from '../core/Account.js';
2
+ import { BtnIcon } from '../core/BtnIcon.js';
3
+ import { getId, newInstance } from '../core/CommonJs.js';
4
+ import { Css, ThemeEvents, Themes, darkTheme } from '../core/Css.js';
5
+ import { EventsUI } from '../core/EventsUI.js';
6
+ import { LogIn } from '../core/LogIn.js';
7
+ import { LogOut } from '../core/LogOut.js';
8
+ import { buildBadgeToolTipMenuOption, Modal, renderMenuLabel, renderViewTitle } from '../core/Modal.js';
9
+ import { SignUp } from '../core/SignUp.js';
10
+ import { Translate } from '../core/Translate.js';
11
+ import { htmls, s } from '../core/VanillaJs.js';
12
+ import { extractUsernameFromPath, getProxyPath, getQueryParams } from '../core/Router.js';
13
+ import { ElementsUnderpost } from './ElementsUnderpost.js';
14
+ import Sortable from 'sortablejs';
15
+ import { RouterUnderpost, BannerAppTemplate } from './RoutesUnderpost.js';
16
+ import { LabGalleryUnderpost } from './LabGalleryUnderpost.js';
17
+ import { CyberpunkBloggerUnderpost } from './CyberpunkBloggerUnderpost.js';
18
+ import { Badge } from '../core/Badge.js';
19
+ import { SettingsUnderpost } from './SettingsUnderpost.js';
20
+ import { Recover } from '../core/Recover.js';
21
+ import { PanelForm } from '../core/PanelForm.js';
22
+ import { SearchBox } from '../core/SearchBox.js';
23
+ import { DocumentSearchProvider } from './DocumentSearchProvider.js';
24
+ import { PublicProfile } from '../core/PublicProfile.js';
25
+ import { Polyhedron } from '../core/Polyhedron.js';
26
+
27
+ const MenuUnderpost = {
28
+ Data: {},
29
+ Render: async function () {
30
+ const id = getId(this.Data, 'menu-');
31
+ this.Data[id] = {};
32
+ const RouterInstance = RouterUnderpost();
33
+
34
+ const { barConfig } = await Themes[Css.currentTheme]();
35
+
36
+ await Modal.Render({
37
+ id: 'modal-menu',
38
+ html: html`
39
+ <div class="fl menu-btn-container">
40
+ ${await BtnIcon.Render({
41
+ class: 'in wfa main-btn-menu main-btn-contracultura-cyberpunk',
42
+ useMenuBtn: true,
43
+ label: renderMenuLabel({
44
+ icon: html`<img class="inl underpost-menu-icon" src="${getProxyPath()}assets/ui-icons/blogger.png" />`,
45
+ text: html`<span class="menu-label-text">${Translate.Render('contracultura-cyberpunk')}</span>`,
46
+ }),
47
+ // style: 'display: none',
48
+ attrs: `data-id="contracultura-cyberpunk"`,
49
+ tabHref: `${getProxyPath()}contracultura-cyberpunk`,
50
+ handleContainerClass: 'handle-btn-container',
51
+ tooltipHtml: await Badge.Render(buildBadgeToolTipMenuOption('blog')),
52
+ })}
53
+ ${await BtnIcon.Render({
54
+ class: 'in wfa main-btn-menu main-btn-lab-gallery hide',
55
+ useMenuBtn: true,
56
+ label: renderMenuLabel({
57
+ icon: html`<img class="inl underpost-menu-icon" src="${getProxyPath()}assets/ui-icons/gallery.png" />`,
58
+ text: html`<span class="menu-label-text">${Translate.Render('lab-gallery')}</span>`,
59
+ }),
60
+ // style: 'display: none',
61
+ attrs: `data-id="lab-gallery"`,
62
+ tabHref: `${getProxyPath()}lab-gallery`,
63
+ handleContainerClass: 'handle-btn-container',
64
+ tooltipHtml: await Badge.Render(buildBadgeToolTipMenuOption('blog')),
65
+ })}
66
+ ${await BtnIcon.Render({
67
+ class: 'in wfa main-btn-menu main-btn-home main-btn-menu-active',
68
+ useMenuBtn: true,
69
+ label: renderMenuLabel({
70
+ icon: html`<img class="inl underpost-menu-icon" src="${getProxyPath()}assets/ui-icons/home.png" />`,
71
+ text: html`<span class="menu-label-text">${Translate.Render('home')}</span>`,
72
+ }),
73
+ // style: 'display: none',
74
+ attrs: `data-id="home"`,
75
+ tabHref: `${getProxyPath()}`,
76
+ handleContainerClass: 'handle-btn-container',
77
+ tooltipHtml: await Badge.Render(buildBadgeToolTipMenuOption('home')),
78
+ })}
79
+ ${await BtnIcon.Render({
80
+ class: 'in wfa main-btn-menu main-btn-log-in',
81
+ useMenuBtn: true,
82
+ label: renderMenuLabel({
83
+ icon: html`<img class="inl underpost-menu-icon" src="${getProxyPath()}assets/ui-icons/log-in.png" />`,
84
+ text: html`<span class="menu-label-text">${Translate.Render('log-in')}</span>`,
85
+ }),
86
+ attrs: `data-id="log-in"`,
87
+ tabHref: `${getProxyPath()}log-in`,
88
+ handleContainerClass: 'handle-btn-container',
89
+ tooltipHtml: await Badge.Render(buildBadgeToolTipMenuOption('log-in')),
90
+ })}
91
+ ${await BtnIcon.Render({
92
+ class: 'in wfa main-btn-menu main-btn-sign-up',
93
+ useMenuBtn: true,
94
+ label: renderMenuLabel({
95
+ icon: html`<img class="inl underpost-menu-icon" src="${getProxyPath()}assets/ui-icons/sign-up.png" />`,
96
+ text: html`<span class="menu-label-text">${Translate.Render('sign-up')}</span>`,
97
+ }),
98
+ attrs: `data-id="sign-up"`,
99
+ tabHref: `${getProxyPath()}sign-up`,
100
+ handleContainerClass: 'handle-btn-container',
101
+ tooltipHtml: await Badge.Render(buildBadgeToolTipMenuOption('sign-up')),
102
+ })}
103
+ ${await BtnIcon.Render({
104
+ class: 'in wfa main-btn-menu main-btn-log-out',
105
+ useMenuBtn: true,
106
+ label: renderMenuLabel({
107
+ icon: html`<img class="inl underpost-menu-icon" src="${getProxyPath()}assets/ui-icons/log-out.png" />`,
108
+ text: html`<span class="menu-label-text">${Translate.Render('log-out')}</span>`,
109
+ }),
110
+ attrs: `data-id="log-out"`,
111
+ style: 'display: none',
112
+ tabHref: `${getProxyPath()}log-out`,
113
+ handleContainerClass: 'handle-btn-container',
114
+ tooltipHtml: await Badge.Render(buildBadgeToolTipMenuOption('log-out')),
115
+ })}
116
+ ${await BtnIcon.Render({
117
+ class: 'in wfa main-btn-menu main-btn-account',
118
+ useMenuBtn: true,
119
+ label: renderMenuLabel({
120
+ icon: html`<img class="inl underpost-menu-icon" src="${getProxyPath()}assets/ui-icons/account.png" />`,
121
+ text: html`<span class="menu-label-text">${Translate.Render('account')}</span>`,
122
+ }),
123
+ style: 'display: none',
124
+ attrs: `data-id="account"`,
125
+ tabHref: `${getProxyPath()}account`,
126
+ handleContainerClass: 'handle-btn-container',
127
+ tooltipHtml: await Badge.Render(buildBadgeToolTipMenuOption('account')),
128
+ })}
129
+ ${await BtnIcon.Render({
130
+ class: 'in wfa main-btn-menu main-btn-public-profile',
131
+ useMenuBtn: true,
132
+ label: renderMenuLabel({
133
+ icon: html`<img class="inl underpost-menu-icon" src="${getProxyPath()}assets/ui-icons/character.png" />`,
134
+ text: html`<span class="menu-label-text">${Translate.Render('public-profile')}</span>`,
135
+ }),
136
+ style: 'display: none',
137
+ attrs: `data-id="public-profile"`,
138
+ tabHref: `${getProxyPath()}u`,
139
+ handleContainerClass: 'handle-btn-container',
140
+ tooltipHtml: await Badge.Render(buildBadgeToolTipMenuOption('public-profile')),
141
+ })}
142
+ ${await BtnIcon.Render({
143
+ class: 'in wfa main-btn-menu main-btn-settings',
144
+ useMenuBtn: true,
145
+ label: renderMenuLabel({
146
+ icon: html`<img class="inl underpost-menu-icon" src="${getProxyPath()}assets/ui-icons/settings.png" />`,
147
+ text: html`<span class="menu-label-text">${Translate.Render('settings')}</span>`,
148
+ }),
149
+ attrs: `data-id="settings"`,
150
+ tabHref: `${getProxyPath()}settings`,
151
+ handleContainerClass: 'handle-btn-container',
152
+ tooltipHtml: await Badge.Render(buildBadgeToolTipMenuOption('settings')),
153
+ })}
154
+ ${await BtnIcon.Render({
155
+ class: 'in wfa main-btn-menu main-btn-recover hide',
156
+ useMenuBtn: true,
157
+ label: renderMenuLabel({
158
+ icon: html`<img class="inl underpost-menu-icon" src="${getProxyPath()}assets/ui-icons/update.png" />`,
159
+ text: html`<span class="menu-label-text">${Translate.Render('recover')}</span>`,
160
+ }),
161
+ attrs: `data-id="recover"`,
162
+ tabHref: `${getProxyPath()}recover`,
163
+ handleContainerClass: 'handle-btn-container',
164
+ tooltipHtml: await Badge.Render(buildBadgeToolTipMenuOption('recover')),
165
+ })}
166
+ ${await BtnIcon.Render({
167
+ class: 'in wfa main-btn-menu main-btn-polyhedron',
168
+ useMenuBtn: true,
169
+ label: renderMenuLabel({
170
+ icon: html`<img class="inl underpost-menu-icon" src="${getProxyPath()}assets/ui-icons/polyhedron.png" />`,
171
+ text: html`<span class="menu-label-text">Polyhedron</span>`,
172
+ }),
173
+ attrs: `data-id="polyhedron"`,
174
+ tabHref: `${getProxyPath()}polyhedron`,
175
+ handleContainerClass: 'handle-btn-container',
176
+ tooltipHtml: await Badge.Render(buildBadgeToolTipMenuOption('polyhedron')),
177
+ })}
178
+ ${await BtnIcon.Render({
179
+ class: 'in wfa main-btn-menu main-btn-github',
180
+ useMenuBtn: true,
181
+ label: renderMenuLabel({
182
+ icon: html`<img class="inl underpost-menu-icon" src="${getProxyPath()}assets/ui-icons/github.png" />`,
183
+ text: html`<span class="menu-label-text">${Translate.Render('github')}</span>`,
184
+ }),
185
+ attrs: `data-id="github"`,
186
+ tabHref: `https://github.com/underpostnet/`,
187
+ handleContainerClass: 'handle-btn-container',
188
+ tooltipHtml: await Badge.Render(buildBadgeToolTipMenuOption('github')),
189
+ })}
190
+ </div>
191
+ `,
192
+ barConfig: newInstance(barConfig),
193
+ title: BannerAppTemplate,
194
+ // titleClass: 'hide',
195
+ titleRender: () => {
196
+ return '';
197
+ },
198
+ mode: 'slide-menu',
199
+ RouterInstance,
200
+ searchCustomImgClass: 'underpost-menu-icon',
201
+ htmlMainBody: async () => {
202
+ // Create PanelForm instance first to get update function
203
+ const panelFormInstance = await PanelForm.instance({
204
+ idPanel: 'underpost-panel',
205
+ defaultUrlImage: `${getProxyPath()}assets/splash/apple-touch-icon-precomposed.png`,
206
+ Elements: ElementsUnderpost,
207
+ route: 'home',
208
+ share: {
209
+ copyLink: true,
210
+ copySourceMd: true,
211
+ },
212
+ showCreatorProfile: true,
213
+ });
214
+
215
+ // Register document search provider with SPA navigation and panel context
216
+ SearchBox.registerProvider({
217
+ ...DocumentSearchProvider,
218
+ search: async (query, context) => {
219
+ // Add idPanel to context to filter documents by panel tag
220
+ return DocumentSearchProvider.search(query, {
221
+ ...context,
222
+ idPanel: 'underpost-panel', // Filter documents by panel tag
223
+ });
224
+ },
225
+ onClick: (result, context) => {
226
+ DocumentSearchProvider.onClick(result, {
227
+ ...context,
228
+ RouterInstance,
229
+ currentRoute: 'home',
230
+ updatePanel: PanelForm.Data['underpost-panel'].updatePanel,
231
+ });
232
+ },
233
+ });
234
+
235
+ // Inject and update document search styles with theme support
236
+ const updateDocumentSearchStyles = () => {
237
+ const styleId = 'document-search-provider-styles';
238
+ let styleTag = s(`#${styleId}`);
239
+
240
+ if (!styleTag) {
241
+ styleTag = document.createElement('style');
242
+ styleTag.id = styleId;
243
+ document.head.appendChild(styleTag);
244
+ }
245
+
246
+ styleTag.textContent = DocumentSearchProvider.getStyles();
247
+ };
248
+
249
+ // Update SearchBox base styles
250
+ const updateSearchBoxBaseStyles = () => {
251
+ const baseStyleId = 'search-box-base-styles';
252
+ let baseStyleTag = s(`#${baseStyleId}`);
253
+
254
+ if (!baseStyleTag) {
255
+ baseStyleTag = document.createElement('style');
256
+ baseStyleTag.id = baseStyleId;
257
+ document.head.appendChild(baseStyleTag);
258
+ }
259
+
260
+ baseStyleTag.textContent = SearchBox.getBaseStyles();
261
+ };
262
+
263
+ // Initial style injection
264
+ updateDocumentSearchStyles();
265
+ updateSearchBoxBaseStyles();
266
+
267
+ // Register theme change handlers for dynamic styling
268
+ ThemeEvents['documentSearchStyles'] = () => {
269
+ updateDocumentSearchStyles();
270
+ updateSearchBoxBaseStyles();
271
+ };
272
+
273
+ return panelFormInstance;
274
+ },
275
+ });
276
+
277
+ ThemeEvents['underpost-main-theme-event'] = () => {
278
+ const srcLogo = darkTheme
279
+ ? `${getProxyPath()}assets/ui-icons/underpost.png`
280
+ : `${getProxyPath()}assets/ui-icons/underpost.png`;
281
+
282
+ if (s('.action-btn-app-icon-render'))
283
+ htmls('.action-btn-app-icon-render', html`<img class="inl top-bar-app-icon" src="${srcLogo}" />`);
284
+
285
+ if (s(`.style-ssr-background-image`)) {
286
+ if (darkTheme) {
287
+ htmls(
288
+ `.style-ssr-background-image`,
289
+ css`
290
+ .ssr-background-image {
291
+ background: #191919;
292
+ }
293
+ `,
294
+ );
295
+ } else {
296
+ htmls(
297
+ `.style-ssr-background-image`,
298
+ css`
299
+ .ssr-background-image {
300
+ background: #e8e8e8;
301
+ }
302
+ `,
303
+ );
304
+ }
305
+ }
306
+ };
307
+ setTimeout(ThemeEvents['underpost-main-theme-event']);
308
+
309
+ this.Data[id].sortable = new Sortable(s(`.menu-btn-container`), {
310
+ animation: 150,
311
+ group: `menu-sortable`,
312
+ forceFallback: true,
313
+ fallbackOnBody: true,
314
+ handle: '.handle-btn-container',
315
+ store: {
316
+ /**
317
+ * Get the order of elements. Called once during initialization.
318
+ * @param {Sortable} sortable
319
+ * @returns {Array}
320
+ */
321
+ get: function (sortable) {
322
+ const order = localStorage.getItem(sortable.options.group.name);
323
+ return order ? order.split('|') : [];
324
+ },
325
+
326
+ /**
327
+ * Save the order of elements. Called onEnd (when the item is dropped).
328
+ * @param {Sortable} sortable
329
+ */
330
+ set: function (sortable) {
331
+ const order = sortable.toArray();
332
+ localStorage.setItem(sortable.options.group.name, order.join('|'));
333
+ },
334
+ },
335
+ // chosenClass: 'css-class',
336
+ // ghostClass: 'css-class',
337
+ // Element dragging ended
338
+ onEnd: function (/**Event*/ evt) {
339
+ // console.log('Sortable onEnd', evt);
340
+ // console.log('evt.oldIndex', evt.oldIndex);
341
+ // console.log('evt.newIndex', evt.newIndex);
342
+ const slotId = Array.from(evt.item.classList).pop();
343
+ // console.log('slotId', slotId);
344
+ if (evt.oldIndex === evt.newIndex) s(`.${slotId}`).click();
345
+
346
+ // var itemEl = evt.item; // dragged HTMLElement
347
+ // evt.to; // target list
348
+ // evt.from; // previous list
349
+ // evt.oldIndex; // element's old index within old parent
350
+ // evt.newIndex; // element's new index within new parent
351
+ // evt.oldDraggableIndex; // element's old index within old parent, only counting draggable elements
352
+ // evt.newDraggableIndex; // element's new index within new parent, only counting draggable elements
353
+ // evt.clone; // the clone element
354
+ // evt.pullMode; // when item is in another sortable: `"clone"` if cloning, `true` if moving
355
+ },
356
+ });
357
+
358
+ EventsUI.onClick(`.main-btn-sign-up`, async () => {
359
+ const { barConfig } = await Themes[Css.currentTheme]();
360
+ await Modal.Render({
361
+ id: 'modal-sign-up',
362
+ route: 'sign-up',
363
+ barConfig,
364
+ title: renderViewTitle({
365
+ icon: html`<img class="inl underpost-menu-icon-modal" src="${getProxyPath()}assets/ui-icons/sign-up.png" />`,
366
+ text: `<span class='inl underpost-text-title-modal'>${Translate.Render('sign-up')}</span>`,
367
+ }),
368
+ html: async () => await SignUp.Render({ idModal: 'modal-sign-up' }),
369
+ handleType: 'bar',
370
+ maximize: true,
371
+ mode: 'view',
372
+ slideMenu: 'modal-menu',
373
+ RouterInstance,
374
+ });
375
+ });
376
+
377
+ EventsUI.onClick(`.main-btn-log-out`, async () => {
378
+ const { barConfig } = await Themes[Css.currentTheme]();
379
+ await Modal.Render({
380
+ id: 'modal-log-out',
381
+ route: 'log-out',
382
+ barConfig,
383
+ title: renderViewTitle({
384
+ icon: html`<img class="inl underpost-menu-icon-modal" src="${getProxyPath()}assets/ui-icons/log-out.png" />`,
385
+ text: `<span class='inl underpost-text-title-modal'>${Translate.Render('log-out')}</span>`,
386
+ }),
387
+ html: async () => await LogOut.Render(),
388
+ handleType: 'bar',
389
+ maximize: true,
390
+ mode: 'view',
391
+ slideMenu: 'modal-menu',
392
+ RouterInstance,
393
+ });
394
+ });
395
+
396
+ EventsUI.onClick(`.main-btn-log-in`, async () => {
397
+ const { barConfig } = await Themes[Css.currentTheme]();
398
+ await Modal.Render({
399
+ id: 'modal-log-in',
400
+ route: 'log-in',
401
+ barConfig,
402
+ title: renderViewTitle({
403
+ icon: html`<img class="inl underpost-menu-icon-modal" src="${getProxyPath()}assets/ui-icons/log-in.png" />`,
404
+ text: `<span class='inl underpost-text-title-modal'>${Translate.Render('log-in')}</span>`,
405
+ }),
406
+ html: async () => await LogIn.Render(),
407
+ handleType: 'bar',
408
+ maximize: true,
409
+ mode: 'view',
410
+ slideMenu: 'modal-menu',
411
+ RouterInstance,
412
+ });
413
+ });
414
+
415
+ EventsUI.onClick(`.main-btn-lab-gallery`, async () => {
416
+ const { barConfig } = await Themes[Css.currentTheme]();
417
+ await Modal.Render({
418
+ id: 'modal-lab-gallery',
419
+ route: 'lab-gallery',
420
+ barConfig,
421
+ title: renderViewTitle({
422
+ icon: html`<img class="inl underpost-menu-icon-modal" src="${getProxyPath()}assets/ui-icons/gallery.png" />`,
423
+ text: `<span class='inl underpost-text-title-modal'>${Translate.Render('lab-gallery')}</span>`,
424
+ }),
425
+ html: async () => await LabGalleryUnderpost.Render(),
426
+ handleType: 'bar',
427
+ maximize: true,
428
+ mode: 'view',
429
+ slideMenu: 'modal-menu',
430
+ RouterInstance,
431
+ });
432
+ });
433
+
434
+ EventsUI.onClick(`.main-btn-contracultura-cyberpunk`, async () => {
435
+ const { barConfig } = await Themes[Css.currentTheme]();
436
+ await Modal.Render({
437
+ id: 'modal-contracultura-cyberpunk',
438
+ route: 'contracultura-cyberpunk',
439
+ barConfig,
440
+ title: renderViewTitle({
441
+ icon: html`<img class="inl underpost-menu-icon-modal" src="${getProxyPath()}assets/ui-icons/blogger.png" />`,
442
+ text: `<span class='inl underpost-text-title-modal'>${Translate.Render('contracultura-cyberpunk')}</span>`,
443
+ }),
444
+ html: async () => await CyberpunkBloggerUnderpost.Render(),
445
+ handleType: 'bar',
446
+ maximize: true,
447
+ mode: 'view',
448
+ slideMenu: 'modal-menu',
449
+ RouterInstance,
450
+ });
451
+ });
452
+
453
+ EventsUI.onClick(`.main-btn-account`, async () => {
454
+ const { barConfig } = await Themes[Css.currentTheme]();
455
+ await Modal.Render({
456
+ id: 'modal-account',
457
+ route: 'account',
458
+ barConfig,
459
+ title: renderViewTitle({
460
+ icon: html`<img class="inl underpost-menu-icon-modal" src="${getProxyPath()}assets/ui-icons/account.png" />`,
461
+ text: `<span class='inl underpost-text-title-modal'>${Translate.Render('account')}</span>`,
462
+ }),
463
+ html: async () =>
464
+ await Account.Render({
465
+ idModal: 'modal-account',
466
+ user: ElementsUnderpost.Data.user.main.model.user,
467
+ disabled: [],
468
+ }),
469
+ handleType: 'bar',
470
+ maximize: true,
471
+ mode: 'view',
472
+ slideMenu: 'modal-menu',
473
+ RouterInstance,
474
+ });
475
+ });
476
+
477
+ PublicProfile.Router();
478
+
479
+ EventsUI.onClick(`.main-btn-public-profile`, async () => {
480
+ const { barConfig } = await Themes[Css.currentTheme]();
481
+ const idModal = 'modal-public-profile';
482
+ const loggedInUser = ElementsUnderpost.Data.user.main.model.user;
483
+
484
+ // Determine the target username: prefer URL path/query over logged-in user
485
+ const usernameFromPath = extractUsernameFromPath();
486
+ const queryParams = getQueryParams();
487
+ const targetUsername = usernameFromPath || queryParams.cid || loggedInUser.username || null;
488
+
489
+ // Create user object with the target username for rendering
490
+ const targetUser = targetUsername ? { username: targetUsername } : loggedInUser;
491
+
492
+ // Check if modal already exists
493
+ const existingModal = s(`.${idModal}`);
494
+ if (existingModal) {
495
+ if (targetUsername) {
496
+ await PublicProfile.Update({
497
+ idModal: 'modal-public-profile',
498
+ user: { username: targetUsername },
499
+ });
500
+ return;
501
+ }
502
+ }
503
+
504
+ await Modal.Render({
505
+ id: idModal,
506
+ route: 'u',
507
+ barConfig,
508
+ title: '',
509
+ // renderViewTitle({
510
+ // icon: html`<i class="fas fa-user-circle"></i>`,
511
+ // text: Translate.Render('public-profile'),
512
+ // }),
513
+ html: async () =>
514
+ await PublicProfile.Render({
515
+ idModal,
516
+ user: targetUser,
517
+ }),
518
+ handleType: 'bar',
519
+ maximize: true,
520
+ mode: 'view',
521
+ slideMenu: 'modal-menu',
522
+ RouterInstance,
523
+ observer: true,
524
+ });
525
+ });
526
+
527
+ EventsUI.onClick(`.main-btn-settings`, async () => {
528
+ const { barConfig } = await Themes[Css.currentTheme]();
529
+ await Modal.Render({
530
+ id: 'modal-settings',
531
+ route: 'settings',
532
+ barConfig,
533
+ title: renderViewTitle({
534
+ icon: html`<img class="inl underpost-menu-icon-modal" src="${getProxyPath()}assets/ui-icons/settings.png" />`,
535
+ text: `<span class='inl underpost-text-title-modal'>${Translate.Render('settings')}</span>`,
536
+ }),
537
+ html: async () => await SettingsUnderpost.Render({ idModal: 'modal-settings' }),
538
+ handleType: 'bar',
539
+ maximize: true,
540
+ mode: 'view',
541
+ slideMenu: 'modal-menu',
542
+ RouterInstance,
543
+ });
544
+ });
545
+
546
+ EventsUI.onClick(`.main-btn-recover`, async () => {
547
+ const { barConfig } = await Themes[Css.currentTheme]();
548
+ await Modal.Render({
549
+ id: 'modal-recover',
550
+ route: 'recover',
551
+ barConfig,
552
+ title: renderViewTitle({
553
+ icon: html`<img class="inl underpost-menu-icon-modal" src="${getProxyPath()}assets/ui-icons/update.png" />`,
554
+ text: `<span class='inl underpost-text-title-modal'>${Translate.Render('recover')}</span>`,
555
+ }),
556
+ html: async () =>
557
+ await Recover.Render({ idModal: 'modal-recover', user: ElementsUnderpost.Data.user.main.model.user }),
558
+ handleType: 'bar',
559
+ maximize: true,
560
+ mode: 'view',
561
+ slideMenu: 'modal-menu',
562
+ RouterInstance,
563
+ });
564
+ });
565
+
566
+ EventsUI.onClick(`.main-btn-polyhedron`, async () => {
567
+ const { barConfig } = await Themes[Css.currentTheme]();
568
+ await Modal.Render({
569
+ id: 'modal-polyhedron',
570
+ route: 'polyhedron',
571
+ barConfig,
572
+ title: renderViewTitle({
573
+ icon: html`<img
574
+ class="inl underpost-menu-icon-modal"
575
+ src="${getProxyPath()}assets/ui-icons/polyhedron.png"
576
+ />`,
577
+ text: `<span class='inl underpost-text-title-modal'>Polyhedron</span>`,
578
+ }),
579
+ html: async () =>
580
+ await Polyhedron.Render({
581
+ idModal: 'modal-polyhedron',
582
+ style: {
583
+ scene: { background: '#111' },
584
+ face: {
585
+ background: 'rgba(255,255,255,.08)',
586
+ border: '1px solid rgba(255,255,255,.18)',
587
+ color: '#fff',
588
+ },
589
+ },
590
+ }),
591
+ handleType: 'bar',
592
+ maximize: true,
593
+ mode: 'view',
594
+ slideMenu: 'modal-menu',
595
+ RouterInstance,
596
+ });
597
+ });
598
+
599
+ EventsUI.onClick(`.main-btn-github`, async () => {
600
+ location.href = `https://github.com/underpostnet/pwa-microservices-template/`;
601
+ });
602
+ },
603
+ };
604
+
605
+ export { MenuUnderpost };
@@ -0,0 +1,45 @@
1
+ import { loggerFactory } from '../core/Logger.js';
2
+ import { Modal } from '../core/Modal.js';
3
+ import { s } from '../core/VanillaJs.js';
4
+ import { getProxyPath } from '../core/Router.js';
5
+
6
+ const logger = loggerFactory(import.meta);
7
+
8
+ const BannerAppTemplate = html`underpost.net`;
9
+
10
+ // Router
11
+ const RoutesUnderpost = () => {
12
+ return {
13
+ '/': {
14
+ title: 'Home',
15
+ render: () => Modal.onHomeRouterEvent(),
16
+ },
17
+ '/contracultura-cyberpunk': {
18
+ title: 'contracultura-cyberpunk',
19
+ render: () => s(`.main-btn-contracultura-cyberpunk`).click(),
20
+ },
21
+ '/lab-gallery': { title: 'lab-gallery', render: () => s(`.main-btn-lab-gallery`).click() },
22
+ '/log-in': { title: 'log-in', render: () => s(`.main-btn-log-in`).click() },
23
+ '/sign-up': { title: 'sign-up', render: () => s(`.main-btn-sign-up`).click() },
24
+ '/log-out': {
25
+ title: 'log-out',
26
+ render: () => s(`.main-btn-log-out`).click(),
27
+ },
28
+ '/account': {
29
+ title: 'account',
30
+ render: () => s(`.main-btn-account`).click(),
31
+ },
32
+ '/u': { title: 'public-profile', render: () => s(`.main-btn-public-profile`).click() },
33
+ '/settings': { title: 'settings', render: () => s(`.main-btn-settings`).click() },
34
+ '/recover': { title: 'recover', render: () => s(`.main-btn-recover`).click() },
35
+ '/polyhedron': { title: 'polyhedron', render: () => s(`.main-btn-polyhedron`).click() },
36
+ };
37
+ };
38
+
39
+ window.Routes = RoutesUnderpost;
40
+
41
+ const RouterUnderpost = () => {
42
+ return { Routes: RoutesUnderpost };
43
+ };
44
+
45
+ export { RoutesUnderpost, RouterUnderpost, BannerAppTemplate };
@@ -0,0 +1,16 @@
1
+ import { Css } from '../core/Css.js';
2
+ import { FullScreen } from '../core/FullScreen.js';
3
+ import { Translate } from '../core/Translate.js';
4
+ import { Worker } from '../core/Worker.js';
5
+
6
+ const SettingsUnderpost = {
7
+ Render: async function () {
8
+ let render = await FullScreen.RenderSetting();
9
+ render += await Css.RenderSetting();
10
+ render += await Translate.RenderSetting();
11
+ render += await Worker.RenderSetting();
12
+ return render;
13
+ },
14
+ };
15
+
16
+ export { SettingsUnderpost };
@@ -0,0 +1,9 @@
1
+ import { SignUp } from '../core/SignUp.js';
2
+
3
+ const SignUpUnderpost = function () {
4
+ SignUp.Event['SignUpUnderpost'] = async (options) => {
5
+ const { user } = options;
6
+ };
7
+ };
8
+
9
+ export { SignUpUnderpost };