@ozdao/martyrs 0.2.470 → 0.2.472
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/dist/{Media-CR0V1zvB.js → Media-DW8RLbfM.js} +1 -1
- package/dist/{Media-C4Ges_Sd.mjs → Media-y_TX6us_.mjs} +1 -1
- package/dist/_virtual/index.cjs +1 -1
- package/dist/_virtual/index.js +1 -1
- package/dist/auth.server.js +1 -1
- package/dist/auth.server.mjs +1 -1
- package/dist/chats.server.js +1 -1
- package/dist/chats.server.mjs +1 -1
- package/dist/community.server.js +1 -1
- package/dist/community.server.mjs +1 -1
- package/dist/events.server.js +1 -1
- package/dist/events.server.mjs +1 -1
- package/dist/files.server.js +1 -1
- package/dist/files.server.mjs +1 -1
- package/dist/gallery.server.js +1 -1
- package/dist/gallery.server.mjs +1 -1
- package/dist/{index-DQqZReAr.js → index-CVXl1rB5.js} +0 -1
- package/dist/{index-DICZTQ-1.mjs → index-Df8vtZx7.mjs} +0 -1
- package/dist/{main-CsZAG5Wz.js → main-CCfQH-Dd.js} +2 -2
- package/dist/{main-CTcal9qN.mjs → main-CgmHzhq5.mjs} +74 -74
- package/dist/{node_modules/.pnpm/@vue_server-renderer@3.5.13_vue@3.5.13_typescript@5.8.3_ → martyrs}/node_modules/@vue/server-renderer/dist/server-renderer.esm-bundler.cjs +1 -1
- package/dist/martyrs/node_modules/@vue/server-renderer/dist/server-renderer.esm-bundler.cjs.map +1 -0
- package/dist/{node_modules/.pnpm/@vue_server-renderer@3.5.13_vue@3.5.13_typescript@5.8.3_ → martyrs}/node_modules/@vue/server-renderer/dist/server-renderer.esm-bundler.js +1 -1
- package/dist/martyrs/node_modules/@vue/server-renderer/dist/server-renderer.esm-bundler.js.map +1 -0
- package/dist/martyrs/node_modules/@vue/shared/dist/shared.esm-bundler.cjs.map +1 -0
- package/dist/martyrs/node_modules/@vue/shared/dist/shared.esm-bundler.js.map +1 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/regex.cjs +5 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/regex.cjs.map +1 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/regex.js +5 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/regex.js.map +1 -0
- package/dist/{node_modules/.pnpm/uuid@11.1.0 → martyrs}/node_modules/uuid/dist/esm-browser/rng.cjs +4 -4
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/rng.cjs.map +1 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/rng.js +15 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/rng.js.map +1 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/stringify.cjs +17 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/stringify.cjs.map +1 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/stringify.js +17 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/stringify.js.map +1 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/v4.cjs +13 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/v4.cjs.map +1 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/v4.js +13 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/v4.js.map +1 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/validate.cjs +8 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/validate.cjs.map +1 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/validate.js +8 -0
- package/dist/martyrs/node_modules/uuid/dist/esm-browser/validate.js.map +1 -0
- package/dist/martyrs/src/components/Feed/Feed.vue.cjs +2 -2
- package/dist/martyrs/src/components/Feed/Feed.vue.cjs.map +1 -1
- package/dist/martyrs/src/components/Feed/Feed.vue.js +2 -2
- package/dist/martyrs/src/components/Feed/Feed.vue.js.map +1 -1
- package/dist/martyrs/src/components/Menu/{Menu.vue.cjs → Menu.vue2.cjs} +2 -2
- package/dist/martyrs/src/components/Menu/Menu.vue2.cjs.map +1 -0
- package/dist/martyrs/src/components/Menu/{Menu.vue.js → Menu.vue2.js} +2 -2
- package/dist/martyrs/src/components/Menu/Menu.vue2.js.map +1 -0
- package/dist/martyrs/src/components/Skeleton/Skeleton.vue.cjs +5 -5
- package/dist/martyrs/src/components/Skeleton/Skeleton.vue.cjs.map +1 -1
- package/dist/martyrs/src/components/Skeleton/Skeleton.vue.js +5 -5
- package/dist/martyrs/src/components/Skeleton/Skeleton.vue.js.map +1 -1
- package/dist/martyrs/src/components/Tab/{Tab.vue2.cjs → Tab.vue.cjs} +2 -2
- package/dist/martyrs/src/components/Tab/{Tab.vue2.js.map → Tab.vue.cjs.map} +1 -1
- package/dist/martyrs/src/components/Tab/{Tab.vue2.js → Tab.vue.js} +2 -2
- package/dist/martyrs/src/components/Tab/Tab.vue.js.map +1 -0
- package/dist/martyrs/src/components/Tree/Tree.vue.cjs +3 -1
- package/dist/martyrs/src/components/Tree/Tree.vue.cjs.map +1 -1
- package/dist/martyrs/src/components/Tree/Tree.vue.js +3 -1
- package/dist/martyrs/src/components/Tree/Tree.vue.js.map +1 -1
- package/dist/martyrs/src/modules/auth/views/components/layouts/Auth.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/layouts/Auth.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/EnterPassword.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/EnterPassword.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/Invite.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/Invite.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ProfileBlogposts.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ProfileBlogposts.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEdit.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEdit.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ResetPassword.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ResetPassword.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.cjs +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/store/auth.cjs +1 -0
- package/dist/martyrs/src/modules/auth/views/store/auth.cjs.map +1 -1
- package/dist/martyrs/src/modules/auth/views/store/auth.js +1 -0
- package/dist/martyrs/src/modules/auth/views/store/auth.js.map +1 -1
- package/dist/martyrs/src/modules/constructor/components/sections/Constructor.vue.cjs +1 -1
- package/dist/martyrs/src/modules/constructor/components/sections/Constructor.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/pages/EventsBackoffice.vue.cjs +1 -1
- package/dist/martyrs/src/modules/events/components/pages/EventsBackoffice.vue.js +1 -1
- package/dist/martyrs/src/modules/globals/views/classes/globals.store.cjs +107 -21
- package/dist/martyrs/src/modules/globals/views/classes/globals.store.cjs.map +1 -1
- package/dist/martyrs/src/modules/globals/views/classes/globals.store.js +107 -21
- package/dist/martyrs/src/modules/globals/views/classes/globals.store.js.map +1 -1
- package/dist/martyrs/src/modules/globals/views/components/partials/Navigation.vue.cjs +10 -14
- package/dist/martyrs/src/modules/globals/views/components/partials/Navigation.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/globals/views/components/partials/Navigation.vue.js +12 -16
- package/dist/martyrs/src/modules/globals/views/components/partials/Navigation.vue.js.map +1 -1
- package/dist/martyrs/src/modules/globals/views/components/sections/SectionPageTitle.vue.cjs +1 -1
- package/dist/martyrs/src/modules/globals/views/components/sections/SectionPageTitle.vue.js +1 -1
- package/dist/martyrs/src/modules/globals/views/utils/vue-app-renderer.cjs +7 -13
- package/dist/martyrs/src/modules/globals/views/utils/vue-app-renderer.cjs.map +1 -1
- package/dist/martyrs/src/modules/globals/views/utils/vue-app-renderer.js +7 -13
- package/dist/martyrs/src/modules/globals/views/utils/vue-app-renderer.js.map +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreate.vue.cjs +6 -7
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreate.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreate.vue.js +7 -8
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreate.vue.js.map +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.cjs +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/Orders.vue.cjs +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/Orders.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/DepartmentEdit.vue.cjs +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/DepartmentEdit.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/Members.vue.cjs +2 -2
- package/dist/martyrs/src/modules/organizations/components/pages/Members.vue.js +2 -2
- package/dist/martyrs/src/modules/organizations/components/pages/Organization.vue.cjs +2 -2
- package/dist/martyrs/src/modules/organizations/components/pages/Organization.vue.js +2 -2
- package/dist/martyrs/src/modules/organizations/components/pages/OrganizationBackoffice.vue.cjs +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/OrganizationBackoffice.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.cjs +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/Organizations.vue.cjs +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/Organizations.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.cjs +1 -1
- package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/blocks/CardCategory.vue.cjs +11 -5
- package/dist/martyrs/src/modules/products/components/blocks/CardCategory.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/products/components/blocks/CardCategory.vue.js +12 -6
- package/dist/martyrs/src/modules/products/components/blocks/CardCategory.vue.js.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Categories.vue.cjs +34 -13
- package/dist/martyrs/src/modules/products/components/pages/Categories.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Categories.vue.js +35 -14
- package/dist/martyrs/src/modules/products/components/pages/Categories.vue.js.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.cjs +20 -9
- package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js +21 -10
- package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Leftovers.vue.cjs +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Leftovers.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Product.vue.cjs +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Product.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.cjs +2 -1
- package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.js +2 -1
- package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.js.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Products.vue.cjs +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Products.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/sections/SectionProduct.vue.cjs +1 -1
- package/dist/martyrs/src/modules/products/components/sections/SectionProduct.vue.js +1 -1
- package/dist/martyrs/src/modules/rents/views/components/pages/GanttChart.vue.cjs +1 -1
- package/dist/martyrs/src/modules/rents/views/components/pages/GanttChart.vue.js +1 -1
- package/dist/martyrs/src/modules/rents/views/components/pages/Rents.vue.cjs +1 -1
- package/dist/martyrs/src/modules/rents/views/components/pages/Rents.vue.js +1 -1
- package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.cjs +1 -1
- package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.js +1 -1
- package/dist/martyrs.cjs.js +1 -1
- package/dist/martyrs.css +1 -1
- package/dist/martyrs.es.js +1 -1
- package/dist/notifications.server.js +35 -2
- package/dist/notifications.server.mjs +35 -2
- package/dist/orders.server.js +3 -3
- package/dist/orders.server.mjs +3 -3
- package/dist/organizations.server.js +1 -1
- package/dist/organizations.server.mjs +1 -1
- package/dist/products.server.js +78 -53
- package/dist/products.server.mjs +78 -53
- package/dist/rents.server.js +1 -1
- package/dist/rents.server.mjs +1 -1
- package/dist/style.css +37 -38
- package/dist/wallet.server.js +1 -1
- package/dist/wallet.server.mjs +1 -1
- package/package.json +2 -1
- package/src/components/Feed/Feed.vue +2 -7
- package/src/components/Skeleton/Skeleton.vue +4 -5
- package/src/components/Tree/Tree.vue +5 -2
- package/src/modules/auth/controllers/middlewares/authJwt.js +1 -1
- package/src/modules/auth/views/store/auth.js +2 -1
- package/src/modules/globals/controllers/classes/globals.crud.js +2 -2
- package/src/modules/globals/views/classes/globals.store.js +119 -31
- package/src/modules/globals/views/components/partials/Navigation.vue +11 -10
- package/src/modules/globals/views/utils/vue-app-renderer.js +7 -16
- package/src/modules/icons/entities/IconMusic.vue +14 -0
- package/src/modules/icons/navigation/IconCheck.vue +31 -0
- package/src/modules/icons/navigation/IconHeart.vue +26 -0
- package/src/modules/icons/navigation/IconPause.vue +31 -0
- package/src/modules/icons/navigation/IconPlay.vue +17 -0
- package/src/modules/icons/navigation/IconRefresh.vue +31 -0
- package/src/modules/icons/navigation/IconShuffle.vue +31 -0
- package/src/modules/icons/navigation/IconVolume.vue +31 -0
- package/src/modules/music/components/SidebarMusic.vue +156 -0
- package/src/modules/music/components/cards/AlbumCard.vue +107 -0
- package/src/modules/music/components/cards/ArtistCard.vue +37 -0
- package/src/modules/music/components/cards/PlaylistCard.vue +100 -0
- package/src/modules/music/components/cards/TrackCard.vue +86 -0
- package/src/modules/music/components/forms/PlaylistForm.vue +156 -0
- package/src/modules/music/components/forms/SearchForm.vue +82 -0
- package/src/modules/music/components/forms/UploadForm.vue +313 -0
- package/src/modules/music/components/layouts/MusicLayout.vue +137 -0
- package/src/modules/music/components/lists/AlbumList.vue +25 -0
- package/src/modules/music/components/lists/ArtistList.vue +25 -0
- package/src/modules/music/components/lists/PlaylistList.vue +25 -0
- package/src/modules/music/components/lists/TrackList.vue +175 -0
- package/src/modules/music/components/pages/AlbumDetail.vue +265 -0
- package/src/modules/music/components/pages/ArtistDetail.vue +247 -0
- package/src/modules/music/components/pages/MusicHome.vue +177 -0
- package/src/modules/music/components/pages/MusicLibrary.vue +192 -0
- package/src/modules/music/components/pages/MusicUpload.vue +44 -0
- package/src/modules/music/components/pages/PlaylistDetail.vue +504 -0
- package/src/modules/music/components/pages/SearchResults.vue +397 -0
- package/src/modules/music/components/pages/TrackDetail.vue +143 -0
- package/src/modules/music/components/player/MusicPlayer.vue +202 -0
- package/src/modules/music/components/player/TrackProgress.vue +110 -0
- package/src/modules/music/components/player/VolumeControl.vue +98 -0
- package/src/modules/music/controllers/album.controller.js +98 -0
- package/src/modules/music/controllers/artist.controller.js +111 -0
- package/src/modules/music/controllers/genre.controller.js +71 -0
- package/src/modules/music/controllers/music.controller.js +174 -0
- package/src/modules/music/controllers/playlist.controller.js +182 -0
- package/src/modules/music/controllers/search.controller.js +103 -0
- package/src/modules/music/controllers/stream.controller.js +106 -0
- package/src/modules/music/models/album.model.js +61 -0
- package/src/modules/music/models/artist.model.js +67 -0
- package/src/modules/music/models/genre.model.js +42 -0
- package/src/modules/music/models/play-history.model.js +51 -0
- package/src/modules/music/models/playlist.model.js +69 -0
- package/src/modules/music/models/track.model.js +94 -0
- package/src/modules/music/music.client.js +186 -0
- package/src/modules/music/music.server.js +114 -0
- package/src/modules/music/policies/music.policies.js +84 -0
- package/src/modules/music/router/music.js +77 -0
- package/src/modules/music/routes/album.routes.js +62 -0
- package/src/modules/music/routes/artist.routes.js +67 -0
- package/src/modules/music/routes/genre.routes.js +60 -0
- package/src/modules/music/routes/music.routes.js +145 -0
- package/src/modules/music/routes/playlist.routes.js +99 -0
- package/src/modules/music/routes/search.routes.js +10 -0
- package/src/modules/music/routes/stream.routes.js +38 -0
- package/src/modules/music/store/albums.js +200 -0
- package/src/modules/music/store/artists.js +180 -0
- package/src/modules/music/store/player.js +397 -0
- package/src/modules/music/store/playlists.js +211 -0
- package/src/modules/music/store/search.js +126 -0
- package/src/modules/music/store/tracks.js +230 -0
- package/src/modules/music/websocket/streaming.handler.js +151 -0
- package/src/modules/notifications/controllers/notifications.controller.js +44 -1
- package/src/modules/notifications/notifications.server.js +0 -1
- package/src/modules/notifications/routes/notifications.routes.js +3 -0
- package/src/modules/orders/components/pages/OrderCreate.vue +0 -2
- package/src/modules/products/components/blocks/CardCategory.vue +5 -4
- package/src/modules/products/components/pages/Categories.vue +38 -20
- package/src/modules/products/components/pages/CategoryEdit.vue +16 -7
- package/src/modules/products/components/pages/ProductEdit.vue +1 -0
- package/src/modules/products/controllers/categories.controller.js +155 -103
- package/dist/martyrs/src/components/Menu/Menu.vue.cjs.map +0 -1
- package/dist/martyrs/src/components/Menu/Menu.vue.js.map +0 -1
- package/dist/martyrs/src/components/Tab/Tab.vue2.cjs.map +0 -1
- package/dist/node_modules/.pnpm/@vue_server-renderer@3.5.13_vue@3.5.13_typescript@5.8.3_/node_modules/@vue/server-renderer/dist/server-renderer.esm-bundler.cjs.map +0 -1
- package/dist/node_modules/.pnpm/@vue_server-renderer@3.5.13_vue@3.5.13_typescript@5.8.3_/node_modules/@vue/server-renderer/dist/server-renderer.esm-bundler.js.map +0 -1
- package/dist/node_modules/.pnpm/@vue_shared@3.5.13/node_modules/@vue/shared/dist/shared.esm-bundler.cjs.map +0 -1
- package/dist/node_modules/.pnpm/@vue_shared@3.5.13/node_modules/@vue/shared/dist/shared.esm-bundler.js.map +0 -1
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/native.cjs +0 -6
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/native.cjs.map +0 -1
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/native.js +0 -6
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/native.js.map +0 -1
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/rng.cjs.map +0 -1
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/rng.js +0 -15
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/rng.js.map +0 -1
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/stringify.cjs +0 -11
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/stringify.cjs.map +0 -1
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/stringify.js +0 -11
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/stringify.js.map +0 -1
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/v4.cjs +0 -21
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/v4.cjs.map +0 -1
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/v4.js +0 -21
- package/dist/node_modules/.pnpm/uuid@11.1.0/node_modules/uuid/dist/esm-browser/v4.js.map +0 -1
- /package/dist/{node_modules/.pnpm/@vue_shared@3.5.13 → martyrs}/node_modules/@vue/shared/dist/shared.esm-bundler.cjs +0 -0
- /package/dist/{node_modules/.pnpm/@vue_shared@3.5.13 → martyrs}/node_modules/@vue/shared/dist/shared.esm-bundler.js +0 -0
- /package/dist/{node_modules → martyrs/node_modules}/fast-deep-equal/index.cjs +0 -0
- /package/dist/{node_modules → martyrs/node_modules}/fast-deep-equal/index.cjs.map +0 -0
- /package/dist/{node_modules → martyrs/node_modules}/fast-deep-equal/index.js +0 -0
- /package/dist/{node_modules → martyrs/node_modules}/fast-deep-equal/index.js.map +0 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// store/search.js
|
|
2
|
+
import { reactive } from 'vue';
|
|
3
|
+
|
|
4
|
+
// State
|
|
5
|
+
export const state = reactive({
|
|
6
|
+
query: '',
|
|
7
|
+
results: {
|
|
8
|
+
tracks: [],
|
|
9
|
+
albums: [],
|
|
10
|
+
artists: [],
|
|
11
|
+
playlists: [],
|
|
12
|
+
genres: []
|
|
13
|
+
},
|
|
14
|
+
isLoading: false,
|
|
15
|
+
error: null,
|
|
16
|
+
activeFilter: 'all' // 'all', 'tracks', 'albums', 'artists', 'playlists', 'genres'
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// Actions
|
|
20
|
+
export const actions = {
|
|
21
|
+
async search(query, type = null, limit = 10) {
|
|
22
|
+
if (!query || query.length < 2) {
|
|
23
|
+
// Reset results if query is too short
|
|
24
|
+
state.results = {
|
|
25
|
+
tracks: [],
|
|
26
|
+
albums: [],
|
|
27
|
+
artists: [],
|
|
28
|
+
playlists: [],
|
|
29
|
+
genres: []
|
|
30
|
+
};
|
|
31
|
+
state.error = "Search query must be at least 2 characters";
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
state.query = query;
|
|
36
|
+
state.isLoading = true;
|
|
37
|
+
state.error = null;
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
const queryParams = new URLSearchParams({
|
|
41
|
+
query,
|
|
42
|
+
limit
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
if (type) {
|
|
46
|
+
queryParams.append('type', type);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const response = await fetch(`${process.env.API_URL}/api/music/search?${queryParams.toString()}`);
|
|
50
|
+
|
|
51
|
+
if (!response.ok) {
|
|
52
|
+
throw new Error('Search request failed');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const data = await response.json();
|
|
56
|
+
|
|
57
|
+
// Update state with results
|
|
58
|
+
state.results = {
|
|
59
|
+
tracks: data.tracks || [],
|
|
60
|
+
albums: data.albums || [],
|
|
61
|
+
artists: data.artists || [],
|
|
62
|
+
playlists: data.playlists || [],
|
|
63
|
+
genres: data.genres || []
|
|
64
|
+
};
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.error('Search error:', error);
|
|
67
|
+
state.error = error.message;
|
|
68
|
+
// Clear results on error
|
|
69
|
+
state.results = {
|
|
70
|
+
tracks: [],
|
|
71
|
+
albums: [],
|
|
72
|
+
artists: [],
|
|
73
|
+
playlists: [],
|
|
74
|
+
genres: []
|
|
75
|
+
};
|
|
76
|
+
} finally {
|
|
77
|
+
state.isLoading = false;
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
setFilter(filter) {
|
|
82
|
+
state.activeFilter = filter;
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
clearSearch() {
|
|
86
|
+
state.query = '';
|
|
87
|
+
state.results = {
|
|
88
|
+
tracks: [],
|
|
89
|
+
albums: [],
|
|
90
|
+
artists: [],
|
|
91
|
+
playlists: [],
|
|
92
|
+
genres: []
|
|
93
|
+
};
|
|
94
|
+
state.error = null;
|
|
95
|
+
state.isLoading = false;
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// Computed values
|
|
100
|
+
export const computed = {
|
|
101
|
+
hasResults: () => {
|
|
102
|
+
return Object.values(state.results).some(arr => arr.length > 0);
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
filteredResults: () => {
|
|
106
|
+
if (state.activeFilter === 'all') {
|
|
107
|
+
return state.results;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Return only the filtered category
|
|
111
|
+
const filtered = {
|
|
112
|
+
tracks: [],
|
|
113
|
+
albums: [],
|
|
114
|
+
artists: [],
|
|
115
|
+
playlists: [],
|
|
116
|
+
genres: []
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
filtered[state.activeFilter] = state.results[state.activeFilter];
|
|
120
|
+
return filtered;
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
totalResultsCount: () => {
|
|
124
|
+
return Object.values(state.results).reduce((sum, arr) => sum + arr.length, 0);
|
|
125
|
+
}
|
|
126
|
+
};
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
// store/tracks.js
|
|
2
|
+
import { reactive } from 'vue';
|
|
3
|
+
import Store from '@martyrs/src/modules/globals/views/classes/globals.store';
|
|
4
|
+
|
|
5
|
+
// Create store instance
|
|
6
|
+
const trackStore = new Store(`${process.env.API_URL}/api/tracks`);
|
|
7
|
+
|
|
8
|
+
// State
|
|
9
|
+
export const state = reactive({
|
|
10
|
+
tracks: [],
|
|
11
|
+
popular: [],
|
|
12
|
+
recent: [],
|
|
13
|
+
featured: [],
|
|
14
|
+
userTracks: [],
|
|
15
|
+
currentTrack: null,
|
|
16
|
+
isLoading: false,
|
|
17
|
+
loadingPopular: false,
|
|
18
|
+
loadingRecent: false,
|
|
19
|
+
loadingFeatured: false
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// Actions
|
|
23
|
+
export const actions = {
|
|
24
|
+
async fetchTracks(options = {}) {
|
|
25
|
+
state.isLoading = true;
|
|
26
|
+
try {
|
|
27
|
+
const tracks = await trackStore.read(options);
|
|
28
|
+
state.tracks = tracks;
|
|
29
|
+
return tracks;
|
|
30
|
+
} catch (error) {
|
|
31
|
+
console.error('Error fetching tracks:', error);
|
|
32
|
+
return [];
|
|
33
|
+
} finally {
|
|
34
|
+
state.isLoading = false;
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
async fetchPopularTracks(limit = 10) {
|
|
39
|
+
state.loadingPopular = true;
|
|
40
|
+
try {
|
|
41
|
+
const response = await fetch(`${process.env.API_URL}/api/tracks/popular?limit=${limit}`);
|
|
42
|
+
const tracks = await response.json();
|
|
43
|
+
state.popular = tracks;
|
|
44
|
+
return tracks;
|
|
45
|
+
} catch (error) {
|
|
46
|
+
console.error('Error fetching popular tracks:', error);
|
|
47
|
+
return [];
|
|
48
|
+
} finally {
|
|
49
|
+
state.loadingPopular = false;
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
async fetchRecentTracks(limit = 10) {
|
|
54
|
+
state.loadingRecent = true;
|
|
55
|
+
try {
|
|
56
|
+
const response = await fetch(`${process.env.API_URL}/api/tracks/recent?limit=${limit}`);
|
|
57
|
+
const tracks = await response.json();
|
|
58
|
+
state.recent = tracks;
|
|
59
|
+
return tracks;
|
|
60
|
+
} catch (error) {
|
|
61
|
+
console.error('Error fetching recent tracks:', error);
|
|
62
|
+
return [];
|
|
63
|
+
} finally {
|
|
64
|
+
state.loadingRecent = false;
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
async fetchTracksByGenre(genreId, limit = 20) {
|
|
69
|
+
try {
|
|
70
|
+
const response = await fetch(`${process.env.API_URL}/api/tracks/genre/${genreId}?limit=${limit}`);
|
|
71
|
+
return await response.json();
|
|
72
|
+
} catch (error) {
|
|
73
|
+
console.error('Error fetching tracks by genre:', error);
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
async fetchTrackByUrl(url) {
|
|
79
|
+
try {
|
|
80
|
+
const response = await fetch(`${process.env.API_URL}/api/tracks/url/${url}`);
|
|
81
|
+
const track = await response.json();
|
|
82
|
+
state.currentTrack = track;
|
|
83
|
+
return track;
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.error('Error fetching track by URL:', error);
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
// Improved createTrack action with better error handling
|
|
91
|
+
async createTrack(trackData) {
|
|
92
|
+
console.log('Creating track with data:', trackData);
|
|
93
|
+
|
|
94
|
+
// Validate required fields to prevent silent failures
|
|
95
|
+
const requiredFields = ['title', 'artist', 'genre', 'fileUrl'];
|
|
96
|
+
const missingFields = requiredFields.filter(field => !trackData[field]);
|
|
97
|
+
|
|
98
|
+
if (missingFields.length > 0) {
|
|
99
|
+
const error = new Error(`Missing required fields: ${missingFields.join(', ')}`);
|
|
100
|
+
console.error(error);
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Ensure proper structure for owner and creator fields
|
|
105
|
+
if (!trackData.owner || !trackData.owner.target || !trackData.owner.type) {
|
|
106
|
+
console.error('Track data missing owner information');
|
|
107
|
+
throw new Error('Owner information is required');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (!trackData.creator || !trackData.creator.target || !trackData.creator.type) {
|
|
111
|
+
console.error('Track data missing creator information');
|
|
112
|
+
throw new Error('Creator information is required');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
try {
|
|
116
|
+
console.log('Calling API to create track...');
|
|
117
|
+
|
|
118
|
+
// Check what API URL we're using
|
|
119
|
+
console.log('API URL:', trackStore.apiUrl);
|
|
120
|
+
|
|
121
|
+
// Use a timeout to detect hanging requests
|
|
122
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
123
|
+
setTimeout(() => reject(new Error('Request timed out after 15 seconds')), 15000);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Race between the actual request and the timeout
|
|
127
|
+
const createdTrack = await Promise.race([
|
|
128
|
+
trackStore.create(trackData),
|
|
129
|
+
timeoutPromise
|
|
130
|
+
]);
|
|
131
|
+
|
|
132
|
+
console.log('Track created successfully, server response:', createdTrack);
|
|
133
|
+
|
|
134
|
+
// Check if the response is what we expect
|
|
135
|
+
if (!createdTrack || !createdTrack._id) {
|
|
136
|
+
console.error('API returned success but without expected track data:', createdTrack);
|
|
137
|
+
throw new Error('Invalid response from server');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Update local state
|
|
141
|
+
state.tracks.unshift(createdTrack);
|
|
142
|
+
state.userTracks.unshift(createdTrack);
|
|
143
|
+
|
|
144
|
+
console.log('Local state updated with new track');
|
|
145
|
+
return createdTrack;
|
|
146
|
+
} catch (error) {
|
|
147
|
+
console.error('Error creating track:', error);
|
|
148
|
+
|
|
149
|
+
// Enhanced error logging
|
|
150
|
+
if (error.response) {
|
|
151
|
+
console.error('Error response:', error.response);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Format the error for better user feedback
|
|
155
|
+
const formattedError = new Error(
|
|
156
|
+
error.message || 'Failed to create track. Please try again.'
|
|
157
|
+
);
|
|
158
|
+
formattedError.originalError = error;
|
|
159
|
+
|
|
160
|
+
// Set a global error
|
|
161
|
+
setError({
|
|
162
|
+
message: formattedError.message,
|
|
163
|
+
errorCode: error.errorCode || 'TRACK_CREATE_FAILED'
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
throw formattedError;
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
|
|
170
|
+
async updateTrack(trackData) {
|
|
171
|
+
try {
|
|
172
|
+
const updatedTrack = await trackStore.update(trackData);
|
|
173
|
+
|
|
174
|
+
// Update local state
|
|
175
|
+
const index = state.tracks.findIndex(t => t._id === updatedTrack._id);
|
|
176
|
+
if (index !== -1) {
|
|
177
|
+
state.tracks[index] = updatedTrack;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const userIndex = state.userTracks.findIndex(t => t._id === updatedTrack._id);
|
|
181
|
+
if (userIndex !== -1) {
|
|
182
|
+
state.userTracks[userIndex] = updatedTrack;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (state.currentTrack && state.currentTrack._id === updatedTrack._id) {
|
|
186
|
+
state.currentTrack = updatedTrack;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return updatedTrack;
|
|
190
|
+
} catch (error) {
|
|
191
|
+
console.error('Error updating track:', error);
|
|
192
|
+
throw error;
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
|
|
196
|
+
async deleteTrack(trackId) {
|
|
197
|
+
try {
|
|
198
|
+
await trackStore.delete({ _id: trackId });
|
|
199
|
+
|
|
200
|
+
// Update local state
|
|
201
|
+
state.tracks = state.tracks.filter(t => t._id !== trackId);
|
|
202
|
+
state.userTracks = state.userTracks.filter(t => t._id !== trackId);
|
|
203
|
+
|
|
204
|
+
if (state.currentTrack && state.currentTrack._id === trackId) {
|
|
205
|
+
state.currentTrack = null;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return true;
|
|
209
|
+
} catch (error) {
|
|
210
|
+
console.error('Error deleting track:', error);
|
|
211
|
+
throw error;
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
|
|
215
|
+
async fetchUserTracks(userId) {
|
|
216
|
+
try {
|
|
217
|
+
const options = {
|
|
218
|
+
creator: userId,
|
|
219
|
+
limit: 100
|
|
220
|
+
};
|
|
221
|
+
console.log('fetchUserTracks', userId)
|
|
222
|
+
const tracks = await trackStore.read(options);
|
|
223
|
+
state.userTracks = tracks;
|
|
224
|
+
return tracks;
|
|
225
|
+
} catch (error) {
|
|
226
|
+
console.error('Error fetching user tracks:', error);
|
|
227
|
+
return [];
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
};
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
// websocket/streaming.handler.js (continued)
|
|
2
|
+
module.exports = function(db) {
|
|
3
|
+
const Logger = require('@martyrs/src/modules/globals/controllers/classes/globals.logger');
|
|
4
|
+
const logger = new Logger(db);
|
|
5
|
+
|
|
6
|
+
return {
|
|
7
|
+
// Handle WebSocket messages for music streaming
|
|
8
|
+
handleStreamingMessage: async (ws, message) => {
|
|
9
|
+
try {
|
|
10
|
+
const { action, data } = message;
|
|
11
|
+
|
|
12
|
+
switch (action) {
|
|
13
|
+
case 'startPlaying':
|
|
14
|
+
// Log play event
|
|
15
|
+
if (ws.userId && data.trackId) {
|
|
16
|
+
await db.playHistory.create({
|
|
17
|
+
user: ws.userId,
|
|
18
|
+
track: data.trackId,
|
|
19
|
+
playedAt: new Date(),
|
|
20
|
+
deviceInfo: data.deviceInfo || 'Unknown',
|
|
21
|
+
playedFrom: data.from || 'other',
|
|
22
|
+
contextId: data.contextId || null
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Increment play count
|
|
26
|
+
await db.track.findByIdAndUpdate(data.trackId, { $inc: { playCount: 1 } });
|
|
27
|
+
|
|
28
|
+
// Acknowledge
|
|
29
|
+
ws.send(JSON.stringify({
|
|
30
|
+
type: 'playAcknowledged',
|
|
31
|
+
trackId: data.trackId
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
34
|
+
break;
|
|
35
|
+
|
|
36
|
+
case 'syncPosition':
|
|
37
|
+
// Track playback position for potential resume later
|
|
38
|
+
if (ws.userId && data.trackId && data.position) {
|
|
39
|
+
// Find the latest play history entry
|
|
40
|
+
const latestPlay = await db.playHistory.findOne({
|
|
41
|
+
user: ws.userId,
|
|
42
|
+
track: data.trackId
|
|
43
|
+
}).sort({ playedAt: -1 });
|
|
44
|
+
|
|
45
|
+
if (latestPlay) {
|
|
46
|
+
latestPlay.playDuration = data.position;
|
|
47
|
+
await latestPlay.save();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
break;
|
|
51
|
+
|
|
52
|
+
case 'getRecommendations':
|
|
53
|
+
// Generate personalized recommendations
|
|
54
|
+
if (ws.userId) {
|
|
55
|
+
// Get user's recently played tracks
|
|
56
|
+
const recentTracks = await db.playHistory.find({
|
|
57
|
+
user: ws.userId
|
|
58
|
+
})
|
|
59
|
+
.sort({ playedAt: -1 })
|
|
60
|
+
.limit(10)
|
|
61
|
+
.populate('track');
|
|
62
|
+
|
|
63
|
+
// Extract genres and artists from recently played
|
|
64
|
+
const recentGenres = new Set();
|
|
65
|
+
const recentArtists = new Set();
|
|
66
|
+
|
|
67
|
+
recentTracks.forEach(history => {
|
|
68
|
+
if (history.track) {
|
|
69
|
+
if (history.track.genre) {
|
|
70
|
+
history.track.genre.forEach(g => recentGenres.add(g.toString()));
|
|
71
|
+
}
|
|
72
|
+
if (history.track.artist) {
|
|
73
|
+
recentArtists.add(history.track.artist.toString());
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Find recommendations based on genres and artists
|
|
79
|
+
const recommendations = await db.track.find({
|
|
80
|
+
$or: [
|
|
81
|
+
{ genre: { $in: Array.from(recentGenres) } },
|
|
82
|
+
{ artist: { $in: Array.from(recentArtists) } }
|
|
83
|
+
],
|
|
84
|
+
_id: { $nin: recentTracks.map(h => h.track._id) }, // Exclude recently played
|
|
85
|
+
status: 'published',
|
|
86
|
+
isPublic: true
|
|
87
|
+
})
|
|
88
|
+
.limit(10)
|
|
89
|
+
.populate('artist', 'name')
|
|
90
|
+
.populate('album', 'title coverUrl');
|
|
91
|
+
|
|
92
|
+
// Send recommendations to the client
|
|
93
|
+
ws.send(JSON.stringify({
|
|
94
|
+
type: 'recommendations',
|
|
95
|
+
tracks: recommendations
|
|
96
|
+
}));
|
|
97
|
+
}
|
|
98
|
+
break;
|
|
99
|
+
|
|
100
|
+
case 'joinListeningParty':
|
|
101
|
+
// Implement a shared listening experience
|
|
102
|
+
if (ws.userId && data.partyId) {
|
|
103
|
+
// Join a room based on the party ID
|
|
104
|
+
ws.listeningParty = data.partyId;
|
|
105
|
+
|
|
106
|
+
// Broadcast to all users in the party that a new user joined
|
|
107
|
+
global.webSocketManager.broadcastToModuleWithFilter(
|
|
108
|
+
'music-streaming',
|
|
109
|
+
(socket) => socket.listeningParty === data.partyId,
|
|
110
|
+
{
|
|
111
|
+
type: 'partyMemberJoined',
|
|
112
|
+
userId: ws.userId,
|
|
113
|
+
partyId: data.partyId
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
break;
|
|
118
|
+
|
|
119
|
+
case 'syncPartyPlayback':
|
|
120
|
+
// Synchronize playback for listening party members
|
|
121
|
+
if (ws.userId && ws.listeningParty && data.trackId && data.position) {
|
|
122
|
+
// Broadcast current position to all users in the party
|
|
123
|
+
global.webSocketManager.broadcastToModuleWithFilter(
|
|
124
|
+
'music-streaming',
|
|
125
|
+
(socket) => socket.listeningParty === ws.listeningParty && socket !== ws,
|
|
126
|
+
{
|
|
127
|
+
type: 'partyPlaybackSync',
|
|
128
|
+
trackId: data.trackId,
|
|
129
|
+
position: data.position,
|
|
130
|
+
isPlaying: data.isPlaying,
|
|
131
|
+
timestamp: Date.now()
|
|
132
|
+
}
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
break;
|
|
136
|
+
|
|
137
|
+
default:
|
|
138
|
+
logger.info(`Unknown streaming action: ${action}`);
|
|
139
|
+
}
|
|
140
|
+
} catch (error) {
|
|
141
|
+
logger.error(`Error in streaming handler: ${error.message}`);
|
|
142
|
+
|
|
143
|
+
// Send error to client
|
|
144
|
+
ws.send(JSON.stringify({
|
|
145
|
+
type: 'error',
|
|
146
|
+
message: 'An error occurred while processing your request'
|
|
147
|
+
}));
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
};
|
|
@@ -58,6 +58,48 @@ const NotificationsController = (db, wss) => {
|
|
|
58
58
|
}
|
|
59
59
|
};
|
|
60
60
|
|
|
61
|
+
// controllers/notifications.controller.js (добавить к существующему контроллеру)
|
|
62
|
+
|
|
63
|
+
// Mark all notifications as read for a user
|
|
64
|
+
const markAllAsRead = async (req, res) => {
|
|
65
|
+
try {
|
|
66
|
+
const userId = req.params.userId;
|
|
67
|
+
|
|
68
|
+
// Update all unread notifications for this user
|
|
69
|
+
const result = await db.notification.updateMany(
|
|
70
|
+
{ userId: userId, status: 'unread' },
|
|
71
|
+
{ status: 'read', updatedAt: Date.now() }
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
// Get all updated notifications for logging
|
|
75
|
+
const updatedNotifications = await db.notification.find({
|
|
76
|
+
userId: userId,
|
|
77
|
+
status: 'read',
|
|
78
|
+
updatedAt: { $gte: new Date(Date.now() - 10000) } // Get notifications updated in the last 10 seconds
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// Log the read status for each notification
|
|
82
|
+
const logPromises = updatedNotifications.map(notification => {
|
|
83
|
+
return db.notificationLog.create({
|
|
84
|
+
notificationId: notification._id,
|
|
85
|
+
userId: userId,
|
|
86
|
+
channelType: 'web', // Assuming web as default
|
|
87
|
+
status: 'read',
|
|
88
|
+
readAt: Date.now()
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
await Promise.all(logPromises);
|
|
93
|
+
|
|
94
|
+
return res.json({
|
|
95
|
+
message: 'All notifications marked as read',
|
|
96
|
+
count: result.modifiedCount
|
|
97
|
+
});
|
|
98
|
+
} catch (err) {
|
|
99
|
+
return res.status(500).json({ message: err.message });
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
61
103
|
// Register device for push notifications
|
|
62
104
|
const registerDevice = async (req, res) => {
|
|
63
105
|
try {
|
|
@@ -132,7 +174,8 @@ const NotificationsController = (db, wss) => {
|
|
|
132
174
|
markAsRead,
|
|
133
175
|
registerDevice,
|
|
134
176
|
updatePreferences,
|
|
135
|
-
getUserPreferences
|
|
177
|
+
getUserPreferences,
|
|
178
|
+
markAllAsRead
|
|
136
179
|
};
|
|
137
180
|
};
|
|
138
181
|
|
|
@@ -20,7 +20,6 @@ const NotificationService = require('./services/notification.service.js');
|
|
|
20
20
|
const { getInstance } = require('@martyrs/src/modules/globals/controllers/classes/globals.abac.js');
|
|
21
21
|
|
|
22
22
|
function initializeNotifications(app, db, wss, origins, publicPath) {
|
|
23
|
-
console.log('wss init is', wss)
|
|
24
23
|
// Set up models in the database object
|
|
25
24
|
db.notification = NotificationModel(db);
|
|
26
25
|
db.userDevice = UserDeviceModel(db);
|
|
@@ -10,6 +10,9 @@ const notificationsRoutes = (app, db, wss, origins, publicPath) => {
|
|
|
10
10
|
|
|
11
11
|
// Mark notification as read
|
|
12
12
|
app.put('/api/notifications/:id/read', controller.markAsRead);
|
|
13
|
+
|
|
14
|
+
// Mark all notifications as read for a user
|
|
15
|
+
app.put('/api/notifications/user/:userId/read-all', controller.markAllAsRead);
|
|
13
16
|
|
|
14
17
|
// Register a device for push notifications
|
|
15
18
|
app.post('/api/notifications/devices/register', controller.registerDevice);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="flex-v-center bg-light pd-small radius-small flex-column flex">
|
|
3
|
-
<div class="w-100 flex-nowrap gap-thin flex">
|
|
4
|
-
<
|
|
3
|
+
<div class="w-100 flex-v-center flex-nowrap gap-thin flex">
|
|
4
|
+
<img v-if="category.photo" class="i-big radius-small object-fit-contain bg-white" :src="(FILE_SERVER_URL || '') + category.photo"/>
|
|
5
|
+
<h4 class="my-handle word-break t-truncate w-100 w-max-100 mn-r-auto">{{category.name}}</h4>
|
|
5
6
|
|
|
6
7
|
<router-link
|
|
7
8
|
:to="{
|
|
@@ -13,10 +14,10 @@
|
|
|
13
14
|
}"
|
|
14
15
|
class="
|
|
15
16
|
i-semi
|
|
16
|
-
z-index-2
|
|
17
17
|
cursor-pointer
|
|
18
18
|
card-page-actions
|
|
19
19
|
radius-extra pd-micro bg-second
|
|
20
|
+
flex-child-default
|
|
20
21
|
"
|
|
21
22
|
>
|
|
22
23
|
<IconEdit
|
|
@@ -29,10 +30,10 @@
|
|
|
29
30
|
@click="deleteCategory(category)"
|
|
30
31
|
class="
|
|
31
32
|
i-semi
|
|
32
|
-
z-index-2
|
|
33
33
|
cursor-pointer
|
|
34
34
|
card-page-actions
|
|
35
35
|
radius-extra pd-micro bg-second
|
|
36
|
+
flex-child-default
|
|
36
37
|
"
|
|
37
38
|
>
|
|
38
39
|
<IconDelete
|