@ozdao/martyrs 0.2.584 → 0.2.585

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 (85) hide show
  1. package/dist/builder.js +2 -0
  2. package/dist/{main-fmp55tJF.js → main-xL-jtBkT.js} +2 -1
  3. package/dist/martyrs/dist/{main-fmp55tJF.js → main-xL-jtBkT.js} +3 -2
  4. package/dist/martyrs/dist/{main-fmp55tJF.js.map → main-xL-jtBkT.js.map} +1 -1
  5. package/dist/martyrs/dist/{web-BDuQSQKS.js → web-BA6h6Z8P.js} +2 -2
  6. package/dist/martyrs/dist/{web-BDuQSQKS.js.map → web-BA6h6Z8P.js.map} +1 -1
  7. package/dist/martyrs/src/components/EditImages/{EditImages.vue2.js → EditImages.vue.js} +2 -2
  8. package/dist/martyrs/src/components/EditImages/EditImages.vue.js.map +1 -0
  9. package/dist/martyrs/src/components/Tab/{Tab.vue.js → Tab.vue2.js} +2 -2
  10. package/dist/martyrs/src/components/Tab/Tab.vue2.js.map +1 -0
  11. package/dist/martyrs/src/modules/auth/views/components/pages/EnterPassword.vue.js +1 -1
  12. package/dist/martyrs/src/modules/auth/views/components/pages/Invite.vue.js +1 -1
  13. package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.js +59 -40
  14. package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.js.map +1 -1
  15. package/dist/martyrs/src/modules/auth/views/components/pages/ProfileBlogposts.vue.js +1 -1
  16. package/dist/martyrs/src/modules/auth/views/components/pages/ResetPassword.vue.js +1 -1
  17. package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.js +1 -1
  18. package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.js +1 -1
  19. package/dist/martyrs/src/modules/backoffice/backoffice.client.js +3 -15
  20. package/dist/martyrs/src/modules/backoffice/backoffice.client.js.map +1 -1
  21. package/dist/martyrs/src/modules/backoffice/configs/navigation.backoffice.config.js +99 -0
  22. package/dist/martyrs/src/modules/backoffice/configs/navigation.backoffice.config.js.map +1 -0
  23. package/dist/martyrs/src/modules/backoffice/{backoffice.router.js → router/backoffice.router.js} +9 -7
  24. package/dist/martyrs/src/modules/backoffice/router/backoffice.router.js.map +1 -0
  25. package/dist/martyrs/src/modules/community/components/pages/BlogPost.vue.js +6 -0
  26. package/dist/martyrs/src/modules/community/components/pages/BlogPost.vue.js.map +1 -1
  27. package/dist/martyrs/src/modules/core/core.client.js.map +1 -1
  28. package/dist/martyrs/src/modules/core/views/classes/core.app.js +5 -1
  29. package/dist/martyrs/src/modules/core/views/classes/core.app.js.map +1 -1
  30. package/dist/martyrs/src/modules/core/views/components/layouts/Client.vue.js +20 -26
  31. package/dist/martyrs/src/modules/core/views/components/layouts/Client.vue.js.map +1 -1
  32. package/dist/martyrs/src/modules/core/views/components/pages/404.vue.js +76 -7
  33. package/dist/martyrs/src/modules/core/views/components/pages/404.vue.js.map +1 -1
  34. package/dist/martyrs/src/modules/core/views/components/sections/SectionPageTitle.vue.js +1 -1
  35. package/dist/martyrs/src/modules/core/views/store/core.store.js +1 -0
  36. package/dist/martyrs/src/modules/core/views/store/core.store.js.map +1 -1
  37. package/dist/martyrs/src/modules/core/views/utils/vue-app-renderer.js +2 -1
  38. package/dist/martyrs/src/modules/core/views/utils/vue-app-renderer.js.map +1 -1
  39. package/dist/martyrs/src/modules/events/components/pages/EditEvent.vue.js +1 -1
  40. package/dist/martyrs/src/modules/events/components/pages/Event.vue.js +1 -0
  41. package/dist/martyrs/src/modules/events/components/pages/Event.vue.js.map +1 -1
  42. package/dist/martyrs/src/modules/events/components/pages/EventsBackoffice.vue.js +1 -1
  43. package/dist/martyrs/src/modules/gallery/components/sections/BackofficeGallery.vue.js +1 -1
  44. package/dist/martyrs/src/modules/music/components/player/FullscreenPlayer.vue.js +1 -1
  45. package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.js +1 -1
  46. package/dist/martyrs/src/modules/orders/components/pages/Orders.vue.js +1 -1
  47. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.js +2 -1
  48. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.js.map +1 -1
  49. package/dist/martyrs/src/modules/organizations/components/pages/Organizations.vue.js +1 -1
  50. package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.js +1 -1
  51. package/dist/martyrs/src/modules/pages/pages.router.js +7 -5
  52. package/dist/martyrs/src/modules/pages/pages.router.js.map +1 -1
  53. package/dist/martyrs/src/modules/products/components/pages/Product.vue.js +1 -1
  54. package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.js +2 -2
  55. package/dist/martyrs/src/modules/products/components/pages/Products.vue.js +1 -1
  56. package/dist/martyrs/src/modules/products/components/sections/EditVariants.vue.js +1 -1
  57. package/dist/martyrs/src/modules/products/components/sections/SectionProduct.vue.js +1 -1
  58. package/dist/martyrs/src/modules/rents/views/components/pages/Gant/GanttToolbar.vue.js +1 -1
  59. package/dist/martyrs/src/modules/rents/views/components/pages/Rents.vue.js +1 -1
  60. package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.js +1 -1
  61. package/dist/martyrs.es.js +1 -1
  62. package/dist/style.css +5 -0
  63. package/dist/{web-BDuQSQKS.js → web-BA6h6Z8P.js} +1 -1
  64. package/package.json +1 -1
  65. package/src/builder/modes/ssr.rspack.dev.js +2 -0
  66. package/src/modules/auth/views/components/pages/Profile.vue +33 -5
  67. package/src/modules/backoffice/backoffice.client.js +1 -25
  68. package/src/modules/backoffice/configs/navigation.backoffice.config.js +99 -0
  69. package/src/modules/backoffice/router/backoffice.router.js +8 -7
  70. package/src/modules/community/components/pages/BlogPost.vue +9 -1
  71. package/src/modules/core/core.client.js +1 -0
  72. package/src/modules/core/views/classes/core.app.js +8 -3
  73. package/src/modules/core/views/components/layouts/Client.vue +41 -42
  74. package/src/modules/core/views/components/pages/404.vue +55 -3
  75. package/src/modules/core/views/store/core.store.js +1 -0
  76. package/src/modules/core/views/utils/vue-app-renderer.js +9 -1
  77. package/src/modules/pages/pages.router.js +4 -2
  78. package/src/modules/pages/views/router/pages.backoffice.router.js +4 -3
  79. package/dist/martyrs/src/components/EditImages/EditImages.vue2.js.map +0 -1
  80. package/dist/martyrs/src/components/Tab/Tab.vue.js.map +0 -1
  81. package/dist/martyrs/src/modules/backoffice/backoffice.router.js.map +0 -1
  82. package/dist/martyrs/src/modules/backoffice/components/partials/Sidebar.vue.js +0 -150
  83. package/dist/martyrs/src/modules/backoffice/components/partials/Sidebar.vue.js.map +0 -1
  84. package/src/modules/backoffice/backoffice.router.js +0 -69
  85. package/src/modules/backoffice/components/partials/Sidebar.vue +0 -165
@@ -160,6 +160,7 @@ export default function createSsrDevServer(projectRoot, configs, createServer) {
160
160
  const measure5 = performance.getEntriesByName('loading-5')[0];
161
161
  console.log(`[LOADING 5] HTML rendering and Beasties completed in ${measure5?.duration?.toFixed(2)}ms`);
162
162
 
163
+ console.log('[SSR-404] dev renderer returning statusCode:', statusCode);
163
164
  return { html: completeHtml, statusCode };
164
165
  };
165
166
  };
@@ -273,6 +274,7 @@ export default function createSsrDevServer(projectRoot, configs, createServer) {
273
274
  res.locals.webpack.devMiddleware // Update to rspack middleware context
274
275
  );
275
276
 
277
+ console.log('[SSR-404] sending response with statusCode:', result.statusCode);
276
278
  res.status(result.statusCode)
277
279
  .header("Content-Type", "text/html; charset=utf-8")
278
280
  .send(result.html);
@@ -1,6 +1,5 @@
1
1
  <template>
2
2
  <div
3
- v-if="show"
4
3
  class="for-transition bg-white w-100"
5
4
  >
6
5
  <div
@@ -259,7 +258,7 @@ import IconEdit from '@martyrs/src/modules/icons/navigation/IconEdit.vue'
259
258
 
260
259
  import PlaceholderUserpic from '@martyrs/src/modules/icons/placeholders/PlaceholderUserpic.vue'
261
260
  // Import libs
262
- import { computed, watch, onMounted, ref, onBeforeMount, inject } from 'vue'
261
+ import { computed, watch, onMounted, onServerPrefetch, ref, onBeforeMount, inject } from 'vue'
263
262
  import { useRoute, useRouter } from 'vue-router'
264
263
 
265
264
  // Import state
@@ -267,13 +266,14 @@ import * as auth from '@martyrs/src/modules/auth/views/store/auth.js'
267
266
  import * as users from '@martyrs/src/modules/auth/views/store/users.js'
268
267
  import membershipsStore from '@martyrs/src/modules/organizations/store/memberships.store.js'
269
268
  import { useGlobalMixins } from '@martyrs/src/modules/core/views/mixins/mixins.js'
269
+ import { useStore } from '@martyrs/src/modules/core/views/store/core.store.js'
270
270
  // Accessing router
271
271
  const route = useRoute()
272
272
  const router = useRouter()
273
273
  // Get organization _id from cookie
274
274
  const show = ref(false)
275
275
 
276
- const store = inject('store')
276
+ const store = useStore()
277
277
  const { isModuleInstalled } = useGlobalMixins()
278
278
 
279
279
  const modules = {
@@ -310,9 +310,37 @@ const modules = {
310
310
  }
311
311
 
312
312
 
313
+ // Функция загрузки данных пользователя
314
+ async function fetchUser() {
315
+ try {
316
+ const result = await users.actions.read({ _id: route.params._id, user: auth.state.user?._id });
317
+ // Если пользователь не найден - устанавливаем 404
318
+ if (!result || result.length === 0 || !users.state.current?._id) {
319
+ store.core.state.notFound = true;
320
+ return false;
321
+ }
322
+ return true;
323
+ } catch (error) {
324
+ console.error('Error fetching user:', error);
325
+ store.core.state.notFound = true;
326
+ return false;
327
+ }
328
+ }
329
+
330
+ // SSR: загружаем данные на сервере для SEO
331
+ onServerPrefetch(async () => {
332
+ console.log('[SSR-404] Profile onServerPrefetch, route._id:', route.params._id);
333
+ await fetchUser();
334
+ console.log('[SSR-404] Profile fetchUser completed');
335
+ });
336
+
337
+ // Client: загружаем данные если еще не загружены (после гидратации)
313
338
  onMounted(async () => {
314
- await users.actions.read({ _id: route.params._id, user: auth.state.user._id });
315
- show.value = true
339
+ // Если данные уже загружены на сервере (SSR) - не загружаем повторно
340
+ if (!users.state.current?._id || users.state.current._id !== route.params._id) {
341
+ await fetchUser();
342
+ }
343
+ show.value = true;
316
344
  })
317
345
 
318
346
  const handleMembershipUpdate = ({ membership, status, target }, statusName, statusNumber) => {
@@ -1,24 +1,11 @@
1
1
  // Router
2
2
  import addRoutes from '@martyrs/src/modules/core/views/router/addRoutes.js';
3
- import { getRoutes } from './backoffice.router.js';
3
+ import { getRoutes } from './router/backoffice.router.js';
4
4
 
5
5
  // Views
6
- // Layouts
7
-
8
6
  // Pages
9
7
  import Dashboard from './components/pages/Dashboard.vue';
10
8
 
11
- // Admin components
12
- // import AdminDashboard from './components/admin/Dashboard.vue';
13
- // import FastOrders from './components/admin/FastOrders.vue';
14
- // import UserEdit from './components/admin/UserEdit.vue';
15
- // import Users from './components/admin/Users.vue';
16
- // import ProductEdit from './components/admin/ProductEdit.vue';
17
- // import Backcalls from './components/admin/Backcalls.vue';
18
-
19
- // Partials
20
- import Sidebar from './components/partials/Sidebar.vue';
21
-
22
9
  // Пример функции инициализации для модуля бэкофиса
23
10
  function initializeBackoffice(app, store, router, options = {}) {
24
11
  const routes = getRoutes(options);
@@ -34,18 +21,7 @@ const ModuleBackoffice = {
34
21
  getRoutes,
35
22
  },
36
23
  components: {
37
- // Layouts
38
- // Pages
39
24
  Dashboard,
40
- // Admin components
41
- // AdminDashboard,
42
- // FastOrders,
43
- // UserEdit,
44
- // Users,
45
- // ProductEdit,
46
- // Backcalls,
47
- // Partials
48
- Sidebar,
49
25
  },
50
26
  },
51
27
  };
@@ -0,0 +1,99 @@
1
+ // Import icons
2
+ import IconProducts from '@martyrs/src/modules/icons/entities/IconProducts.vue'
3
+ import IconPayments from '@martyrs/src/modules/icons/entities/IconPayments.vue'
4
+ import IconEvents from '@martyrs/src/modules/icons/entities/IconEvents.vue'
5
+ import IconGroups from '@martyrs/src/modules/icons/entities/IconGroups.vue'
6
+ import IconCommunity from '@martyrs/src/modules/icons/entities/IconCommunity.vue'
7
+ import IconGallery from '@martyrs/src/modules/icons/entities/IconGallery.vue'
8
+ import IconOrders from '@martyrs/src/modules/icons/entities/IconOrders.vue'
9
+ import IconLeftovers from '@martyrs/src/modules/icons/entities/IconLeftovers.vue'
10
+
11
+ // Backoffice navigation configuration
12
+ export const navigationItems = [
13
+ {
14
+ category: 'Menu',
15
+ visible: () => true,
16
+ items: [
17
+ {
18
+ title: 'Organizations',
19
+ iconComponent: IconGroups,
20
+ route: () => '/backoffice/organizations',
21
+ visible: () => true
22
+ },
23
+ {
24
+ title: 'Community',
25
+ iconComponent: IconCommunity,
26
+ route: () => '/backoffice/community',
27
+ visible: () => true
28
+ },
29
+ {
30
+ title: 'Products',
31
+ iconComponent: IconProducts,
32
+ route: () => '/backoffice/products',
33
+ visible: () => true
34
+ },
35
+ {
36
+ title: 'Inventory',
37
+ iconComponent: IconLeftovers,
38
+ route: () => '/backoffice/inventory',
39
+ visible: () => true
40
+ },
41
+ {
42
+ title: 'Orders',
43
+ iconComponent: IconOrders,
44
+ route: () => '/backoffice/orders',
45
+ visible: () => true
46
+ },
47
+ {
48
+ title: 'Gallery',
49
+ iconComponent: IconGallery,
50
+ route: () => '/backoffice/gallery',
51
+ visible: () => true
52
+ },
53
+ {
54
+ title: 'Applications',
55
+ iconComponent: IconEvents,
56
+ route: () => '/backoffice/applications',
57
+ visible: () => true
58
+ },
59
+ {
60
+ title: 'Events',
61
+ iconComponent: IconEvents,
62
+ route: () => '/backoffice/events',
63
+ visible: () => true
64
+ }
65
+ ]
66
+ },
67
+ {
68
+ category: 'General',
69
+ visible: () => true,
70
+ items: [
71
+ {
72
+ title: 'Payments',
73
+ iconComponent: IconPayments,
74
+ route: () => '/backoffice/payments',
75
+ visible: () => true
76
+ },
77
+ {
78
+ title: 'Users',
79
+ iconComponent: null,
80
+ route: () => '/backoffice/users',
81
+ visible: () => true
82
+ },
83
+ {
84
+ title: 'Pages',
85
+ iconComponent: null,
86
+ route: () => '/backoffice/pages',
87
+ visible: () => true
88
+ },
89
+ {
90
+ title: 'Reports',
91
+ iconComponent: null,
92
+ route: () => '/backoffice/reports',
93
+ visible: () => true
94
+ }
95
+ ]
96
+ }
97
+ ]
98
+
99
+ export default navigationItems
@@ -1,10 +1,10 @@
1
- // backoffice.meta.js
2
- import Sidebar from '../components/partials/Sidebar.vue';
1
+ import Navigation from '@martyrs/src/modules/core/views/components/partials/Navigation.vue'
2
+ import { navigationItems } from '../configs/navigation.backoffice.config.js'
3
3
 
4
4
  export function getRoutes(options = {}) {
5
5
  const route = options.route || 'Home';
6
6
  const routes = [];
7
-
7
+
8
8
  routes.push({
9
9
  parentName: route,
10
10
  config: {
@@ -14,8 +14,9 @@ export function getRoutes(options = {}) {
14
14
  path: '',
15
15
  name: 'Backoffice Root',
16
16
  meta: {
17
- sidebar_navigation: Sidebar,
18
- sidebar_width_hidden: 'w-0',
17
+ sidebar_navigation: Navigation,
18
+ sidebar_navigation_items: navigationItems,
19
+ sidebar_width_hidden: 'w-2r',
19
20
  },
20
21
  props: {
21
22
  newsletterPopup: 12344,
@@ -64,6 +65,6 @@ export function getRoutes(options = {}) {
64
65
  ],
65
66
  }
66
67
  });
67
-
68
+
68
69
  return routes;
69
- }
70
+ }
@@ -74,10 +74,12 @@ import Comments from '@martyrs/src/modules/community/components/sections/Comment
74
74
  import Viewer from '@martyrs/src/modules/constructor/components/sections/Viewer.vue';
75
75
  import * as blog from '@martyrs/src/modules/community/store/blogposts.js';
76
76
  import * as auth from '@martyrs/src/modules/auth/views/store/auth.js';
77
-
77
+ import { useStore } from '@martyrs/src/modules/core/views/store/core.store.js';
78
+
78
79
  import { useRoute } from 'vue-router';
79
80
 
80
81
  const route = useRoute();
82
+ const store = useStore();
81
83
  const blogpost = computed(() => blog.state.current);
82
84
  const isLoading = ref(false);
83
85
  const canShare = ref(false);
@@ -90,9 +92,15 @@ async function fetchBlogpost() {
90
92
  blogpost.value = data[0];
91
93
  // Обновляем состояние хранилища
92
94
  blog.state.current = data[0];
95
+
96
+ // Если пост не найден - устанавливаем 404
97
+ if (!data || data.length === 0 || !blog.state.current) {
98
+ store.core.state.notFound = true;
99
+ }
93
100
  } catch (err) {
94
101
  error.value = err;
95
102
  console.error('Error fetching blogpost:', err);
103
+ store.core.state.notFound = true;
96
104
  } finally {
97
105
  isLoading.value = false;
98
106
  }
@@ -123,6 +123,7 @@ export { default as Sidebar } from '@martyrs/src/modules/core/views/components/p
123
123
  export { default as Footer } from '@martyrs/src/modules/core/views/components/partials/Footer.vue';
124
124
  export { default as Walkthrough } from '@martyrs/src/modules/core/views/components/sections/Walkthrough.vue';
125
125
 
126
+
126
127
  // Functional exports
127
128
  export {
128
129
  appRenderer,
@@ -261,13 +261,14 @@ export function createUniversalApp({
261
261
  // FOR SSR / SERVER ENTRY
262
262
  async function renderApp({ url, cookies, headers, languages, ssrContext }) {
263
263
  const { app, router, store, i18n, meta, moduleManager } = await createApp();
264
-
264
+
265
265
  // Set SSR store for useStore calls
266
266
  if (typeof window === 'undefined') {
267
267
  const { setSSRStore } = await import('../store/core.store.js');
268
268
  await setSSRStore(store);
269
269
  }
270
-
270
+
271
+
271
272
  const context = {
272
273
  app,
273
274
  store,
@@ -278,10 +279,11 @@ export function createUniversalApp({
278
279
 
279
280
  // [LOADING 20] SSR renderApp starting and loading modules
280
281
  performance.mark('loading-20-start');
281
- console.log('[LOADING 20] SSR renderApp starting and loading modules...');
282
+ console.log('[SSR-404] renderApp starting, url:', url);
282
283
 
283
284
  // Для SSR загружаем модули для текущего маршрута
284
285
  const requiredModules = moduleManager.getModulesForRoute(url);
286
+ console.log('[SSR-404] required modules:', requiredModules.map(m => m.name));
285
287
 
286
288
  // Собираем имена модулей которые нужны для текущего роута
287
289
  const currentRouteModules = [];
@@ -299,8 +301,11 @@ export function createUniversalApp({
299
301
  console.log(`[LOADING 20] SSR modules loaded in ${measure20?.duration?.toFixed(2)}ms`);
300
302
 
301
303
  // После загрузки модулей и регистрации роутов, выполняем навигацию
304
+ console.log('[SSR-404] modules loaded, pushing url:', url);
305
+ console.log('[SSR-404] available routes:', router.getRoutes().map(r => r.path));
302
306
  await router.push(url);
303
307
  await router.isReady();
308
+ console.log('[SSR-404] router ready, currentRoute:', router.currentRoute.value.name, router.currentRoute.value.path);
304
309
 
305
310
  const result = await appRenderer.render({
306
311
  url,
@@ -13,7 +13,7 @@
13
13
  }"
14
14
  >
15
15
  <transition name="moveFromTop" appear>
16
- <Loader v-if="!page || store.core.state.loading" :centered="true" class="pos-fixed"/>
16
+ <Loader v-if="!page || store.core.state.loading" :centered="true" class="pos-fixed z-index-10"/>
17
17
  </transition>
18
18
 
19
19
  <transition
@@ -129,21 +129,22 @@
129
129
  </component>
130
130
  <!-- rows-[minmax(0,1fr)] z-index-1 pos-relative w-100 h-100 -->
131
131
  <div class="rows-[minmax(0,1fr)] z-index-1 pos-relative w-100 h-100">
132
- <div id="scrollview" ref="scrollview" @scroll="handleScroll" class="o-y-scroll o-x-hidden h-100">
132
+
133
+ <div id="scrollview" ref="scrollview" @scroll="handleScroll" class="o-y-scroll o-x-hidden h-100">
133
134
  <Status
134
135
  v-if="store.core.state.error.show"
135
- :data="store.core.state.error"
136
- @close="store.core.state.error.show = false"
137
- class="z-index-7"
138
- />
139
- <Snack
140
- v-if="store.core.state.snack.show"
141
- :type="store.core.state.snack.type"
142
- :message="store.core.state.snack.message"
143
- :show="store.core.state.snack.show"
144
- @close="store.core.state.snack.show = false"
145
- class="z-index-7"
146
- />
136
+ :data="store.core.state.error"
137
+ @close="store.core.state.error.show = false"
138
+ class="z-index-7"
139
+ />
140
+ <Snack
141
+ v-if="store.core.state.snack.show"
142
+ :type="store.core.state.snack.type"
143
+ :message="store.core.state.snack.message"
144
+ :show="store.core.state.snack.show"
145
+ @close="store.core.state.snack.show = false"
146
+ class="z-index-7"
147
+ />
147
148
  <div class="h-min-100 pos-relative w-100">
148
149
  <!-- <section v-if="!route.meta?.breadcrumbs?.hide" class="pd-thin pd-b-zero">
149
150
  <Breadcrumbs
@@ -152,41 +153,38 @@
152
153
  />
153
154
  </section> -->
154
155
 
155
- <Suspense @resolve="onSuspenseResolved">
156
- <router-view
156
+ <Suspense @resolve="onSuspenseResolved">
157
+ <router-view
157
158
  id="view"
158
- v-slot="{ Component, route }"
159
+ v-slot="{ Component, route }"
159
160
  :class="{
160
161
  'scroll-hide': MOBILE_APP,
161
162
  }"
162
163
  class="h-min-100 pos-relative w-100"
163
164
  >
164
165
  <transition @before-enter="scrollTop" name="scaleTransition" mode="out-in" appear>
165
- <component
166
- ref="page"
167
- :is="Component"
168
- class="w-100 h-min-100"
169
- @page-loading="handlePageLoading"
170
- @page-loaded="handlePageLoaded"
171
- :key="componentKey"
172
- />
173
- <!-- Key пока выключил непонятно какие проблемы это вызовет -->
174
- <!-- :key="route.path" -->
175
- </transition>
176
- </router-view>
166
+
167
+ <div :key="componentKey" class="w-100 h-min-100">
168
+ <component
169
+ ref="page"
170
+ :is="Component"
171
+ class="w-100 h-min-100"
172
+ @page-loading="handlePageLoading"
173
+ @page-loaded="handlePageLoaded"
174
+ />
175
+ <component
176
+ v-if="!MOBILE_APP && route.meta.footer && !route.meta.hideFooter"
177
+ ref="footer"
178
+ :is="route.meta.footer"
179
+ :theme="route.meta.footer_theme || 'light'"
180
+ :logotype="route.meta.logotype"
181
+ :location="route.meta.location"
182
+ />
183
+ </div>
184
+ </transition>
185
+ </router-view>
177
186
  </Suspense>
178
187
  </div>
179
-
180
- <transition @before-enter="scrollTop" name="scaleTransition" mode="out-in" appear>
181
- <component
182
- v-if="!MOBILE_APP && route.meta.footer && !route.meta.hideFooter && page && !store.core.state.loading"
183
- ref="footer"
184
- :is="route.meta.footer"
185
- :theme="route.meta.footer_theme || 'light'"
186
- :logotype="route.meta.logotype"
187
- :location="route.meta.location"
188
- />
189
- </transition>
190
188
 
191
189
  <component
192
190
  v-if="route.meta.player"
@@ -221,7 +219,7 @@
221
219
 
222
220
 
223
221
  <script setup>
224
- import { computed, ref, onMounted } from 'vue';
222
+ import { computed, ref, onMounted } from 'vue';
225
223
  // Router
226
224
  import { useRoute } from 'vue-router';
227
225
  // Store
@@ -233,7 +231,7 @@
233
231
  import Popup from '@martyrs/src/components/Popup/Popup.vue';
234
232
  import Breadcrumbs from '@martyrs/src/components/Breadcrumbs/Breadcrumbs.vue'
235
233
  import Loader from '@martyrs/src/components/Loader/Loader.vue';
236
-
234
+
237
235
  import NavigationBar from '@martyrs/src/modules/core/views/components/partials/NavigationBar.vue';
238
236
  import LocationSelection from '@martyrs/src/modules/core/views/components/partials/LocationSelection.vue';
239
237
 
@@ -256,6 +254,7 @@
256
254
 
257
255
  const store = useStore()
258
256
 
257
+
259
258
  /////////////////////////////
260
259
  // LOADING
261
260
  /////////////////////////////
@@ -1,5 +1,57 @@
1
+ <script setup>
2
+ import { useRouter } from 'vue-router'
3
+ import IconHome from '@martyrs/src/modules/icons/entities/IconHome.vue'
4
+ import IconArrow from '@martyrs/src/modules/icons/navigation/IconArrow.vue'
5
+ import IconSearch from '@martyrs/src/modules/icons/navigation/IconSearch.vue'
6
+ import IconInfo from '@martyrs/src/modules/icons/entities/IconInfo.vue'
7
+
8
+ const router = useRouter()
9
+ const goBack = () => window.history.length > 1 ? router.back() : router.push('/')
10
+ </script>
11
+
1
12
  <template>
2
- <div class="">
3
- 404 Not Found
13
+ <div class="pd-thin flex flex-v-center w-100 h-100 ">
14
+ <div class="bg-light w-100 h-100 flex flex-h-center flex-column radius-big pd-medium">
15
+
16
+ <div class="flex flex-v-center gap-thin pd-thin radius-big bg-main w-fit mn-b-medium">
17
+ <span class="i-medium radius-big bg-grey"></span>
18
+ <span class="p-small">Error 404</span>
19
+ </div>
20
+
21
+ <h1 class="mn-b-semi">Page not found</h1>
22
+
23
+ <p class="p-medium t-transp w-max-35r mn-b-big" style="line-height: 1.6;">
24
+ The page you are looking for doesn't exist or has been moved. Please check the URL or navigate back to the home page.
25
+ </p>
26
+
27
+ <div class="flex gap-small mn-b-extra">
28
+ <router-link to="/" class="button bg-black t-white pd-regular radius-small flex flex-v-center gap-thin">
29
+ <IconHome class="i-regular" :fill="'rgb(var(--white))'" />
30
+ <span>Go home</span>
31
+ </router-link>
32
+ <button @click="goBack" class="button bg-white t-black pd-regular radius-small flex flex-v-center gap-thin">
33
+ <IconArrow class="i-regular rotate-180" />
34
+ <span>Go back</span>
35
+ </button>
36
+ </div>
37
+
38
+ <div class="pd-t-medium w-max-25r">
39
+ <span class="p-micro t-transp t-upper t-500 ls-wide d-block mn-b-small">Search Documentation</span>
40
+ <div class="field-wrapper bg-white flex flex-v-center radius-small pd-small gap-small">
41
+ <IconSearch class="i-small t-transp" />
42
+ <input type="text" placeholder="e.g. Installation guide..." class="w-100 bd-none" />
43
+ </div>
44
+ <div class="flex gap-medium mn-t-small">
45
+ <a href="#" class="flex flex-v-center gap-micro p-small t-transp"><IconInfo class="i-small" /> Help Center</a>
46
+ <a href="#" class="p-small t-transp">API Status</a>
47
+ </div>
48
+ </div>
49
+
50
+ </div>
4
51
  </div>
5
- </template>
52
+ </template>
53
+
54
+ <style scoped>
55
+ input { border: none; outline: none; }
56
+ input::placeholder { color: rgba(var(--dark), 0.4); }
57
+ </style>
@@ -115,6 +115,7 @@ export function createStore() {
115
115
  // State создается для каждого store instance (изоляция SSR)
116
116
  const state = reactive({
117
117
  loading: false,
118
+ notFound: false,
118
119
 
119
120
  isOpenLocationPopup: false,
120
121
  isOpenSidebar: false,
@@ -269,11 +269,19 @@ export async function render({ url, cookies, headers, ssrContext, createApp }) {
269
269
  const measure26Total = performance.getEntriesByName('loading-26-total')[0];
270
270
  console.log(`[LOADING 26] Total SSR render completed in ${measure26Total?.duration?.toFixed(2)}ms`);
271
271
 
272
+ // Определяем HTTP статус код:
273
+ // 1. Если store.core.state.notFound === true - 404
274
+ // 2. Если роут называется 'notfound' - 404
275
+ // 3. Иначе - 200
276
+ const statusCode = store.core.state.notFound
277
+ ? 404
278
+ : (router.currentRoute?.value?.name?.toLowerCase() === 'notfound' ? 404 : 200);
279
+
272
280
  return {
273
281
  html,
274
282
  meta: payload,
275
283
  state: initialState,
276
- statusCode: router.currentRoute?.value?.name?.toLowerCase() === 'notfound' ? 404 : 200,
284
+ statusCode,
277
285
  usedModules: Array.from(ctx.modules || new Set()), // Return used modules
278
286
  };
279
287
  }
@@ -1,5 +1,6 @@
1
1
  import layoutEmpty from '@martyrs/src/modules/core/views/components/layouts/Empty.vue';
2
- import Sidebar from '@martyrs/src/modules/backoffice/components/partials/Sidebar.vue';
2
+ import Navigation from '@martyrs/src/modules/core/views/components/partials/Navigation.vue';
3
+ import { navigationItems } from '@martyrs/src/modules/backoffice/configs/navigation.backoffice.config.js';
3
4
  import SidebarPages from './views/components/partials/SidebarPages.vue';
4
5
 
5
6
  function createPublicRoutes(options = {}) {
@@ -92,7 +93,8 @@ export function getRoutes(options = {}) {
92
93
  title: {
93
94
  en: 'Pages',
94
95
  },
95
- sidebar: Sidebar,
96
+ sidebar_navigation: Navigation,
97
+ sidebar_navigation_items: navigationItems,
96
98
  },
97
99
  routes: createBackofficeRoutes(options),
98
100
  },
@@ -1,5 +1,5 @@
1
- import Sidebar from '@martyrs/src/modules/backoffice/components/partials/Sidebar.vue';
2
-
1
+ import Navigation from '@martyrs/src/modules/core/views/components/partials/Navigation.vue';
2
+ import { navigationItems } from '@martyrs/src/modules/backoffice/configs/navigation.backoffice.config.js';
3
3
  import SidebarPages from '../components/partials/SidebarPages.vue';
4
4
 
5
5
  const pages = {
@@ -8,7 +8,8 @@ const pages = {
8
8
  title: {
9
9
  en: 'Pages',
10
10
  },
11
- sidebar: Sidebar,
11
+ sidebar_navigation: Navigation,
12
+ sidebar_navigation_items: navigationItems,
12
13
  },
13
14
  children: [
14
15
  {
@@ -1 +0,0 @@
1
- {"version":3,"file":"EditImages.vue2.js","sources":["../../../../../src/components/EditImages/EditImages.vue"],"sourcesContent":["<template>\n\t<div class=\"flex-nowrap flex gap-small\">\n <VueDraggableNext v-if=\"localImages.length > 0\" class=\"gap-small flex dragArea list-group w-full\" v-model=\"localImages\" @change=\"emitChanges\">\n\t\t\t<div v-for=\"(image, index) in localImages\" class=\"pos-relative\">\n\t\t\t\t<img loading=\"lazy\" class=\"i-extra object-fit-contain bg-black-transp-5 pd-nano radius-small o-hidden\" :src=\"(FILE_SERVER_URL || '') + image\" />\n\t\t\t\t\n <IconCross \n @click=\"deleteImage(index)\" \n class=\"cursor-pointer pos-absolute t-center flex-center flex radius-extra i-medium bg-red pos-t-10-negative pos-r-10-negative pd-micro\"\n />\n\t\t\t</div>\n\t\t</VueDraggableNext>\n <div\n v-if=\"localImages.length > 0\" \n class=\"i-extra uppercase flex-center flex radius-small o-hidden br-main br-2px pd-small\"\n >\n <UploadImageMultiple \n @update:images=\"onImagesUpdate\"\n text=\"Add\"\n :options=\"{\n showText: false\n }\"\n :uploadPath=\"'photos'\"\n class=\"radius-big\"\n />\n </div>\n\n\n\t\t<UploadImageMultiple \t\n v-if=\"localImages.length < 1\" \n @update:images=\"onImagesUpdate\"\n :uploadPath=\"props.uploadPath\"\n :text=\"props.text\"\n :options=\"props.options\"\n class=\"w-100 pd-medium\"\n />\n\t</div>\t\n</template>\n\n<script setup>\nimport { ref, defineProps, watchEffect } from 'vue';\nimport { VueDraggableNext } from 'vue-draggable-next'\nimport UploadImageMultiple from \"@martyrs/src/components/UploadImageMultiple/UploadImageMultiple.vue\";\nimport IconCross from '@martyrs/src/modules/icons/navigation/IconCross.vue';\n\nconst props = defineProps({\n images: Array,\n text: Object,\n options: Object,\n uploadPath: {\n type: Object,\n default: 'unsorted'\n }\n});\n\nconst emit = defineEmits(['update:images'])\n\nconst localImages = ref([...props.images])\n\nwatchEffect(() => {\n localImages.value = [...props.images]; // Обновление localImages при изменении props.images\n});\n\nconst emitChanges = () => {\n emit('update:images', localImages.value)\n}\n\nconst onImagesUpdate = (newImages) => {\n localImages.value = [...localImages.value, ...newImages]\n emitChanges()\n}\n\nconst deleteImage = (index) => {\n localImages.value.splice(index, 1)\n emitChanges()\n}\n</script>\n\n<style lang=\"scss\">\n// Your styles here\n</style>\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA6CA,UAAM,QAAQ;AAUd,UAAM,OAAO;AAEb,UAAM,cAAc,IAAI,CAAC,GAAG,MAAM,MAAM,CAAC;AAEzC,gBAAY,MAAM;AAChB,kBAAY,QAAQ,CAAC,GAAG,MAAM,MAAM;AAAA,IACtC,CAAC;AAED,UAAM,cAAc,MAAM;AACxB,WAAK,iBAAiB,YAAY,KAAK;AAAA,IACzC;AAEA,UAAM,iBAAiB,CAAC,cAAc;AACpC,kBAAY,QAAQ,CAAC,GAAG,YAAY,OAAO,GAAG,SAAS;AACvD,kBAAW;AAAA,IACb;AAEA,UAAM,cAAc,CAAC,UAAU;AAC7B,kBAAY,MAAM,OAAO,OAAO,CAAC;AACjC,kBAAW;AAAA,IACb;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"Tab.vue.js","sources":["../../../../../src/components/Tab/Tab.vue"],"sourcesContent":["<template>\n <div class=\"flex-nowrap flex-v-center flex pos-relative\">\n <button \n v-for=\"(tab, index) in tabs\" \n :key=\"index\" \n @click=\"handleTabClick(index, tab)\" \n class=\"z-index-1 t-center cursor-pointer\"\n :style=\"isSelected(index, tab) ? 'background: rgb(var(--main)) !important' : ''\"\n :class=\"[\n isSelected(index, tab) ? 'bg-main' : '',\n replaceClasses('pd-small pd-r-medium pd-l-medium w-max pd-small radius-small', classTab)\n ]\"\n >\n {{tab.name || tab.label}}\n </button>\n </div>\n</template>\n\n<script setup>\nimport { ref, computed, watch } from 'vue'\nimport { useGlobalMixins } from '@martyrs/src/modules/core/views/mixins/mixins.js';\n\nconst { replaceClasses } = useGlobalMixins();\nconst emit = defineEmits(['update:selected', 'tab-click']);\n\nconst props = defineProps({\n tabs: Array,\n classTab: String,\n selected: [String, Number],\n modelValue: [String, Number],\n callback: Function\n})\n\nconst selectedTab = ref(0)\n\n// Handle both v-model and selected prop for backward compatibility\nconst updateSelectedIndex = () => {\n if (props.modelValue !== undefined) {\n const selectedIndex = props.tabs.findIndex(tab => tab.value === props.modelValue)\n if (selectedIndex !== -1) {\n selectedTab.value = selectedIndex\n }\n } else if (props.selected !== undefined) {\n const selectedIndex = props.tabs.findIndex(tab => tab.value === props.selected)\n if (selectedIndex !== -1) {\n selectedTab.value = selectedIndex\n }\n }\n}\n\n// Initial setup\nupdateSelectedIndex()\n\n// Watch for changes in selected or modelValue props\nwatch(() => props.selected, updateSelectedIndex)\nwatch(() => props.modelValue, updateSelectedIndex)\n\n// Check if tab is selected\nconst isSelected = (index, tab) => {\n if (props.modelValue !== undefined) {\n return tab.value === props.modelValue\n } else if (props.selected !== undefined) {\n return tab.value === props.selected\n }\n return index === selectedTab.value\n}\n\n// Handle tab click\nfunction handleTabClick(index, tab) {\n selectedTab.value = index\n \n // Emit both events for flexibility\n emit('update:selected', tab.value)\n emit('tab-click', { index, tab })\n \n // For v-model support\n if (props.modelValue !== undefined) {\n emit('update:modelValue', tab.value)\n }\n \n // Call callback if provided\n if (props.callback) props.callback(tab)\n}\n</script>\n\n<style lang=\"scss\">\n.tab-selector {\n position: absolute;\n width: 50%;\n height: 100%;\n left: 0;\n top: 0;\n z-index: 0;\n transition: left 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n</style>"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAsBA,UAAM,EAAE,eAAc,IAAK,gBAAe;AAC1C,UAAM,OAAO;AAEb,UAAM,QAAQ;AAQd,UAAM,cAAc,IAAI,CAAC;AAGzB,UAAM,sBAAsB,MAAM;AAChC,UAAI,MAAM,eAAe,QAAW;AAClC,cAAM,gBAAgB,MAAM,KAAK,UAAU,SAAO,IAAI,UAAU,MAAM,UAAU;AAChF,YAAI,kBAAkB,IAAI;AACxB,sBAAY,QAAQ;AAAA,QACtB;AAAA,MACF,WAAW,MAAM,aAAa,QAAW;AACvC,cAAM,gBAAgB,MAAM,KAAK,UAAU,SAAO,IAAI,UAAU,MAAM,QAAQ;AAC9E,YAAI,kBAAkB,IAAI;AACxB,sBAAY,QAAQ;AAAA,QACtB;AAAA,MACF;AAAA,IACF;AAGA,wBAAmB;AAGnB,UAAM,MAAM,MAAM,UAAU,mBAAmB;AAC/C,UAAM,MAAM,MAAM,YAAY,mBAAmB;AAGjD,UAAM,aAAa,CAAC,OAAO,QAAQ;AACjC,UAAI,MAAM,eAAe,QAAW;AAClC,eAAO,IAAI,UAAU,MAAM;AAAA,MAC7B,WAAW,MAAM,aAAa,QAAW;AACvC,eAAO,IAAI,UAAU,MAAM;AAAA,MAC7B;AACA,aAAO,UAAU,YAAY;AAAA,IAC/B;AAGA,aAAS,eAAe,OAAO,KAAK;AAClC,kBAAY,QAAQ;AAGpB,WAAK,mBAAmB,IAAI,KAAK;AACjC,WAAK,aAAa,EAAE,OAAO,IAAG,CAAE;AAGhC,UAAI,MAAM,eAAe,QAAW;AAClC,aAAK,qBAAqB,IAAI,KAAK;AAAA,MACrC;AAGA,UAAI,MAAM,SAAU,OAAM,SAAS,GAAG;AAAA,IACxC;;;;;;;;;;;;;;;;;;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"backoffice.router.js","sources":["../../../../../src/modules/backoffice/backoffice.router.js"],"sourcesContent":["// backoffice.meta.js\nimport Sidebar from './components/partials/Sidebar.vue';\n\nexport function getRoutes(options = {}) {\n const route = options.route || 'Home';\n const routes = [];\n \n routes.push({\n parentName: route,\n config: {\n basePath: 'backoffice',\n routes: [\n {\n path: '',\n name: 'Backoffice Root',\n meta: {\n sidebar_navigation: Sidebar,\n sidebar_width_hidden: 'w-0',\n },\n props: {\n newsletterPopup: 12344,\n },\n beforeEnter: [\n () => import(/* webpackChunkName: \"auth-validation\" */ '@martyrs/src/modules/auth/views/middlewares/auth.validation.js').then(m => m.requiresAdmin),\n ],\n children: [\n {\n path: '',\n name: 'Backoffice Admin',\n meta: {\n title: {\n en: 'Backoffice',\n ru: 'Управление',\n },\n },\n component: () => import(/* webpackChunkName: 'BackofficeGallery' */ './components/pages/Dashboard.vue'),\n },\n {\n path: 'organizations',\n name: 'Backoffice Organizations',\n meta: {\n title: {\n en: 'Backoffice Organizations',\n ru: 'Управление Организациями',\n },\n authorize: [],\n },\n component: () => import(/* webpackChunkName: 'BackofficeOrganizations' */ '@martyrs/src/modules/organizations/components/pages/Organizations.vue'),\n },\n {\n path: 'community',\n name: 'Backoffice Community',\n meta: {\n title: {\n en: 'Backoffice Community',\n ru: 'Управление Сообществом',\n },\n authorize: [],\n },\n component: () => import(/* webpackChunkName: 'BackofficeCommunity' */ '@martyrs/src/modules/community/components/pages/Blog.vue'),\n },\n ],\n }\n ],\n }\n });\n \n return routes;\n}"],"names":["Sidebar"],"mappings":";AAGO,SAAS,UAAU,UAAU,IAAI;AACtC,QAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAM,SAAS,CAAA;AAEf,SAAO,KAAK;AAAA,IACV,YAAY;AAAA,IACZ,QAAQ;AAAA,MACN,UAAU;AAAA,MACV,QAAQ;AAAA,QACN;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,YACJ,oBAAoBA;AAAAA,YACpB,sBAAsB;AAAA,UAClC;AAAA,UACU,OAAO;AAAA,YACL,iBAAiB;AAAA,UAC7B;AAAA,UACU,aAAa;AAAA,YACX,MAAM;AAAA;AAAA,cAAiD;AAAA,YAAgE,EAAE,KAAK,OAAK,EAAE,aAAa;AAAA,UAC9J;AAAA,UACU,UAAU;AAAA,YACR;AAAA,cACE,MAAM;AAAA,cACN,MAAM;AAAA,cACN,MAAM;AAAA,gBACJ,OAAO;AAAA,kBACL,IAAI;AAAA,kBACJ,IAAI;AAAA,gBACtB;AAAA,cACA;AAAA,cACc,WAAW,MAAM;AAAA;AAAA,gBAAmD;AAAA,cAAkC;AAAA,YACpH;AAAA,YACY;AAAA,cACE,MAAM;AAAA,cACN,MAAM;AAAA,cACN,MAAM;AAAA,gBACJ,OAAO;AAAA,kBACL,IAAI;AAAA,kBACJ,IAAI;AAAA,gBACtB;AAAA,gBACgB,WAAW,CAAA;AAAA,cAC3B;AAAA,cACc,WAAW,MAAM;AAAA;AAAA,gBAAyD;AAAA,cAAuE;AAAA,YAC/J;AAAA,YACY;AAAA,cACE,MAAM;AAAA,cACN,MAAM;AAAA,cACN,MAAM;AAAA,gBACJ,OAAO;AAAA,kBACL,IAAI;AAAA,kBACJ,IAAI;AAAA,gBACtB;AAAA,gBACgB,WAAW,CAAA;AAAA,cAC3B;AAAA,cACc,WAAW,MAAM;AAAA;AAAA,gBAAqD;AAAA,cAA0D;AAAA,YAC9I;AAAA,UACA;AAAA,QACA;AAAA,MACA;AAAA,IACA;AAAA,EACA,CAAG;AAED,SAAO;AACT;"}