@ozdao/martyrs 0.2.586 → 0.2.587
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/auth.server.js +14 -1
- package/dist/chats.server.js +1 -1
- package/dist/community.server.js +1 -1
- package/dist/core.server.js +24 -25
- package/dist/events.server.js +1 -1
- package/dist/files.server.js +1 -1
- package/dist/gallery.server.js +1 -1
- package/dist/inventory.server.js +1 -1
- package/dist/marketplace.server.js +1 -1
- package/dist/martyrs/src/components/Feed/Carousel.vue.js +1 -1
- package/dist/martyrs/src/components/Feed/Feed.vue.js +2 -2
- package/dist/martyrs/src/components/Loader/{Loader.vue.js → Loader.vue2.js} +2 -2
- package/dist/martyrs/src/components/Loader/Loader.vue2.js.map +1 -0
- package/dist/martyrs/src/components/LocationMarker/LocationMarker.vue.js +1 -1
- package/dist/martyrs/src/components/Media/Media.vue.js +1 -1
- 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/Select/{Select.vue.js → Select.vue2.js} +2 -2
- package/dist/martyrs/src/components/Select/Select.vue2.js.map +1 -0
- package/dist/martyrs/src/components/Spoiler/{Spoiler.vue.js → Spoiler.vue2.js} +2 -2
- package/dist/martyrs/src/components/Spoiler/Spoiler.vue2.js.map +1 -0
- package/dist/martyrs/src/components/UploadImage/UploadImage.vue.js +1 -1
- package/dist/martyrs/src/components/UploadImageMultiple/UploadImageMultiple.vue.js +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/ProfileEdit.vue.js +1 -1
- package/dist/martyrs/src/modules/community/components/layouts/Community.vue.js +1 -1
- package/dist/martyrs/src/modules/community/components/pages/BlogPost.vue.js +1 -1
- package/dist/martyrs/src/modules/core/views/components/blocks/PopupDateSelector.vue.js +1 -1
- package/dist/martyrs/src/modules/core/views/components/layouts/Client.vue.js +1 -1
- package/dist/martyrs/src/modules/core/views/components/pages/404.vue.js +10 -33
- package/dist/martyrs/src/modules/core/views/components/pages/404.vue.js.map +1 -1
- package/dist/martyrs/src/modules/core/views/components/partials/Header.vue.js +1 -1
- package/dist/martyrs/src/modules/core/views/components/partials/Navigation.vue.js +1 -1
- package/dist/martyrs/src/modules/core/views/components/sections/{Filters.vue.js → Filters.vue2.js} +2 -2
- package/dist/martyrs/src/modules/core/views/components/sections/Filters.vue2.js.map +1 -0
- package/dist/martyrs/src/modules/events/components/pages/EditEvent.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/pages/Event.vue.js +2 -2
- package/dist/martyrs/src/modules/events/components/sections/Feed.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/sections/List.vue.js +1 -1
- package/dist/martyrs/src/modules/gallery/components/sections/BackofficeGallery.vue.js +1 -1
- package/dist/martyrs/src/modules/inventory/components/forms/AdjustmentForm.vue.js +1 -1
- package/dist/martyrs/src/modules/inventory/components/forms/StockAlertsForm.vue.js +1 -1
- package/dist/martyrs/src/modules/inventory/components/pages/InventoryEdit.vue.js +1 -1
- package/dist/martyrs/src/modules/landing/components/sections/SectionGuide.vue.js +1 -1
- package/dist/martyrs/src/modules/marketplace/views/components/pages/Marketplace.vue.js +1 -1
- package/dist/martyrs/src/modules/marketplace/views/components/sections/SectionMenu.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/forms/AlbumForm.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/forms/ArtistForm.vue.js +2 -2
- package/dist/martyrs/src/modules/music/components/forms/TrackForm.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/pages/Album.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/pages/Artist.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/pages/Playlist.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/pages/SearchResults.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/pages/Track.vue.js +1 -1
- package/dist/martyrs/src/modules/notifications/components/sections/NotificationPreferences.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/forms/FormApplicationDetails.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/forms/FormCustomerDetails.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderBackoffice.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/sections/FormDelivery.vue.js +2 -2
- package/dist/martyrs/src/modules/orders/components/sections/FormPayment.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/blocks/CardDepartment.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/forms/DepartmentForm.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/Department.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/Organization.vue.js +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.js +3 -3
- package/dist/martyrs/src/modules/organizations/components/sections/MembersAdd.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/elements/Image360.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js +3 -3
- package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Products.vue.js +2 -2
- package/dist/martyrs/src/modules/products/components/sections/EditDiscounts.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/sections/EditVariants.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/sections/FilterProducts.vue.js +1 -1
- package/dist/martyrs/src/modules/reports/components/sections/FormReport.vue.js +1 -1
- package/dist/martyrs/src/modules/spots/components/blocks/SpotMemberModify.vue.js +1 -1
- package/dist/martyrs/src/modules/spots/components/layouts/Spots.vue.js +1 -1
- package/dist/martyrs/src/modules/spots/components/pages/Spot.vue.js +1 -1
- package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.js +1 -1
- package/dist/martyrs/src/modules/spots/components/sections/WorktimeEdit.vue.js +1 -1
- package/dist/notifications.server.js +1 -1
- package/dist/orders.server.js +1 -1
- package/dist/organizations.server.js +1 -1
- package/dist/pages.server.js +1 -1
- package/dist/products.server.js +1 -1
- package/dist/rents.server.js +1 -1
- package/dist/reports.server.js +1 -1
- package/dist/spots.server.js +1 -1
- package/dist/style.css +2 -2
- package/dist/wallet.server.js +1 -1
- package/package.json +2 -4
- package/src/modules/auth/auth.server.js +15 -1
- package/src/modules/chats/chats.server.js +1 -1
- package/src/modules/community/community.server.js +1 -1
- package/src/modules/core/core.server.js +4 -31
- package/src/modules/core/models/log.model.js +24 -0
- package/src/modules/core/views/components/pages/404.vue +2 -3
- package/src/modules/events/events.server.js +1 -1
- package/src/modules/files/files.server.js +1 -1
- package/src/modules/gallery/gallery.server.js +1 -1
- package/src/modules/governance/governance.server.js +1 -1
- package/src/modules/icons/icons.server.js +1 -1
- package/src/modules/inventory/inventory.server.js +1 -1
- package/src/modules/marketplace/marketplace.server.js +1 -1
- package/src/modules/notifications/notifications.server.js +1 -1
- package/src/modules/orders/orders.server.js +1 -1
- package/src/modules/organizations/organizations.server.js +1 -1
- package/src/modules/pages/pages.server.js +1 -1
- package/src/modules/products/products.server.js +1 -1
- package/src/modules/rents/rents.server.js +1 -1
- package/src/modules/reports/reports.server.js +1 -1
- package/src/modules/spots/spots.server.js +1 -1
- package/src/modules/wallet/wallet.server.js +1 -1
- package/dist/martyrs/src/components/Loader/Loader.vue.js.map +0 -1
- package/dist/martyrs/src/components/Menu/Menu.vue.js.map +0 -1
- package/dist/martyrs/src/components/Select/Select.vue.js.map +0 -1
- package/dist/martyrs/src/components/Spoiler/Spoiler.vue.js.map +0 -1
- package/dist/martyrs/src/modules/core/views/components/sections/Filters.vue.js.map +0 -1
- package/src/cli/commands/create.js +0 -106
- package/src/cli/index.js +0 -25
- package/src/cli/templates/app/.env.development.mustache +0 -14
- package/src/cli/templates/app/.env.production.mustache +0 -14
- package/src/cli/templates/app/Dockerfile +0 -36
- package/src/cli/templates/app/babel.config.js +0 -14
- package/src/cli/templates/app/env.js +0 -3
- package/src/cli/templates/app/index.js +0 -46
- package/src/cli/templates/app/mongodb.config.js +0 -18
- package/src/cli/templates/app/package.json.mustache +0 -65
- package/src/cli/templates/app/src/client.js +0 -22
- package/src/cli/templates/app/src/components/pages/Index.vue +0 -11
- package/src/cli/templates/app/src/configs/global.config.js.mustache +0 -40
- package/src/cli/templates/app/src/localization/extensions.js +0 -2
- package/src/cli/templates/app/src/localization/index.js +0 -44
- package/src/cli/templates/app/src/localization/overrides.js +0 -2
- package/src/cli/templates/app/src/localization/translations.js +0 -10
- package/src/cli/templates/app/src/models/index.js +0 -9
- package/src/cli/templates/app/src/router/index.js +0 -48
- package/src/cli/templates/app/src/scss/theme.scss +0 -18
- package/src/cli/templates/app/src/server.js +0 -68
- package/src/cli/templates/app/src/store/index.js +0 -9
- package/src/cli/templates/docker-compose.yaml.mustache +0 -47
- package/src/cli/templates/nginx/Dockerfile +0 -5
- package/src/cli/templates/nginx/default.conf.mustache +0 -55
- package/src/cli/templates/public/favicon/.gitkeep +0 -0
- package/src/cli/templates/start-dev.sh.mustache +0 -131
- package/src/cli/templates/start-prod.sh.mustache +0 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ozdao/martyrs",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.587",
|
|
4
4
|
"description": "Fullstack framework focused on user experience and ease of development.",
|
|
5
5
|
"author": "OZ DAO <hello@ozdao.dev>",
|
|
6
6
|
"license": "GPL-3.0-or-later",
|
|
@@ -15,9 +15,6 @@
|
|
|
15
15
|
"vue3",
|
|
16
16
|
"express"
|
|
17
17
|
],
|
|
18
|
-
"bin": {
|
|
19
|
-
"martyrs": "./src/cli/index.js"
|
|
20
|
-
},
|
|
21
18
|
"type": "module",
|
|
22
19
|
"sideEffects": [
|
|
23
20
|
"*.css",
|
|
@@ -75,6 +72,7 @@
|
|
|
75
72
|
"build:builder:rspack": "rspack --config rspack.builder.config.js"
|
|
76
73
|
},
|
|
77
74
|
"dependencies": {
|
|
75
|
+
"beasties": "0.3.5",
|
|
78
76
|
"@capacitor/core": "7.4.4",
|
|
79
77
|
"commander": "12.1.0",
|
|
80
78
|
"@capacitor/preferences": "7.0.2",
|
|
@@ -7,7 +7,7 @@ import RoleModel from './models/role.model.js';
|
|
|
7
7
|
import UserModel from './models/user.model.js';
|
|
8
8
|
import OtpModel from './models/otp.model.js';
|
|
9
9
|
|
|
10
|
-
function initializeAuth(app, db, origins, publicPath) {
|
|
10
|
+
function initializeAuth({ app, db, origins, publicPath, wss }) {
|
|
11
11
|
db.role = RoleModel(db);
|
|
12
12
|
db.user = UserModel(db);
|
|
13
13
|
db.otp = OtpModel(db);
|
|
@@ -16,6 +16,20 @@ function initializeAuth(app, db, origins, publicPath) {
|
|
|
16
16
|
authRoutes(app, db, origins, publicPath);
|
|
17
17
|
usersRoutes(app, db, origins, publicPath);
|
|
18
18
|
}
|
|
19
|
+
|
|
20
|
+
if (wss) {
|
|
21
|
+
wss.registerRpcMethod('auth', 'getOnlineStatus', async ({ userId }) => {
|
|
22
|
+
if (!userId) return { isOnline: false, lastSeenAt: null };
|
|
23
|
+
const isOnline = wss.userConnections.has(userId.toString());
|
|
24
|
+
if (isOnline) return { isOnline: true, lastSeenAt: new Date() };
|
|
25
|
+
const session = await db.session.findOne(
|
|
26
|
+
{ target: new db.mongoose.Types.ObjectId(userId), isActive: true },
|
|
27
|
+
{ lastSeenAt: 1 },
|
|
28
|
+
{ sort: { lastSeenAt: -1 } }
|
|
29
|
+
).lean();
|
|
30
|
+
return { isOnline: false, lastSeenAt: session?.lastSeenAt || null };
|
|
31
|
+
}, { requireAuth: false });
|
|
32
|
+
}
|
|
19
33
|
}
|
|
20
34
|
export const models = {
|
|
21
35
|
RoleModel,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import ChatsController from './controllers/chats.controller.js';
|
|
2
2
|
import ChatModel from './models/chat.model.js';
|
|
3
3
|
import chatsRoutes from './routes/chats.routes.js';
|
|
4
|
-
function initializeChats(app, db, wss, origins, publicPath) {
|
|
4
|
+
function initializeChats({ app, db, wss, origins, publicPath }) {
|
|
5
5
|
// Настраиваем модели в объекте базы данных
|
|
6
6
|
db.chat = ChatModel(db);
|
|
7
7
|
// Настраиваем маршруты, если объект приложения передан
|
|
@@ -9,7 +9,7 @@ import commentsRoutes from './routes/comments.routes.js';
|
|
|
9
9
|
import reactionsRoutes from './routes/reactions.routes.js';
|
|
10
10
|
import coreabac from '@martyrs/src/modules/core/controllers/classes/abac/abac.js';
|
|
11
11
|
import initBlogPolicies from './policies/blog.policies.js';
|
|
12
|
-
function initializeCommunity(app, db, origins, publicPath) {
|
|
12
|
+
function initializeCommunity({ app, db, origins, publicPath }) {
|
|
13
13
|
// Настраиваем модели в объекте базы данных
|
|
14
14
|
db.blogpost = BlogpostModel(db);
|
|
15
15
|
db.comment = CommentModel(db);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import coreabac from './controllers/classes/abac/abac.js';
|
|
2
2
|
import initCorePolicies from './controllers/policies/core.policies.js';
|
|
3
3
|
|
|
4
|
+
import LogModel from './models/log.model.js';
|
|
4
5
|
import SessionModel from './models/session.model.js';
|
|
5
6
|
import VisitorModel from './models/visitor.model.js';
|
|
6
7
|
import RequestModel from './models/request.model.js';
|
|
@@ -28,23 +29,9 @@ async function createWebSocketManager(...args) {
|
|
|
28
29
|
// Для обратной совместимости экспортируем как WebSocketManager
|
|
29
30
|
const WebSocketManager = createWebSocketManager;
|
|
30
31
|
|
|
31
|
-
function initializeCore(app, db, origins, publicPath, wss
|
|
32
|
-
//
|
|
33
|
-
db.log =
|
|
34
|
-
db.mongoose.models.Log ||
|
|
35
|
-
db.mongoose.model(
|
|
36
|
-
'Log',
|
|
37
|
-
new db.mongoose.Schema(
|
|
38
|
-
{
|
|
39
|
-
timestamp: { type: Date, default: Date.now },
|
|
40
|
-
level: String,
|
|
41
|
-
message: String,
|
|
42
|
-
},
|
|
43
|
-
{ versionKey: false }
|
|
44
|
-
)
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
// Session, Visitor, Request models
|
|
32
|
+
function initializeCore({ app, db, origins, publicPath, wss }) {
|
|
33
|
+
// Models
|
|
34
|
+
db.log = LogModel(db);
|
|
48
35
|
db.session = SessionModel(db);
|
|
49
36
|
db.visitor = VisitorModel(db);
|
|
50
37
|
db.request = RequestModel(db);
|
|
@@ -64,20 +51,6 @@ function initializeCore(app, db, origins, publicPath, wss = null) {
|
|
|
64
51
|
app.use(visitorLogger);
|
|
65
52
|
}
|
|
66
53
|
|
|
67
|
-
// WebSocket RPC methods
|
|
68
|
-
if (wss) {
|
|
69
|
-
wss.registerRpcMethod('core', 'getOnlineStatus', async ({ userId }) => {
|
|
70
|
-
if (!userId) return { isOnline: false, lastSeenAt: null };
|
|
71
|
-
const isOnline = wss.userConnections.has(userId.toString());
|
|
72
|
-
if (isOnline) return { isOnline: true, lastSeenAt: new Date() };
|
|
73
|
-
const session = await db.session.findOne(
|
|
74
|
-
{ target: new db.mongoose.Types.ObjectId(userId), isActive: true },
|
|
75
|
-
{ lastSeenAt: 1 },
|
|
76
|
-
{ sort: { lastSeenAt: -1 } }
|
|
77
|
-
).lean();
|
|
78
|
-
return { isOnline: false, lastSeenAt: session?.lastSeenAt || null };
|
|
79
|
-
}, { requireAuth: false });
|
|
80
|
-
}
|
|
81
54
|
}
|
|
82
55
|
export { WebSocketManager, initializeCore as initialize };
|
|
83
56
|
export default {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export default db => {
|
|
2
|
+
const LogSchema = new db.mongoose.Schema(
|
|
3
|
+
{
|
|
4
|
+
level: {
|
|
5
|
+
type: String,
|
|
6
|
+
required: true,
|
|
7
|
+
},
|
|
8
|
+
message: {
|
|
9
|
+
type: String,
|
|
10
|
+
required: true,
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
timestamps: true,
|
|
15
|
+
versionKey: false,
|
|
16
|
+
}
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
LogSchema.index({ level: 1 });
|
|
20
|
+
LogSchema.index({ createdAt: -1 });
|
|
21
|
+
|
|
22
|
+
const Log = db.mongoose.models.Log || db.mongoose.model('Log', LogSchema);
|
|
23
|
+
return Log;
|
|
24
|
+
};
|
|
@@ -14,7 +14,6 @@ const goBack = () => window.history.length > 1 ? router.back() : router.push('/'
|
|
|
14
14
|
<div class="bg-light w-100 h-100 flex flex-h-center flex-column radius-big pd-medium">
|
|
15
15
|
|
|
16
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
17
|
<span class="p-small">Error 404</span>
|
|
19
18
|
</div>
|
|
20
19
|
|
|
@@ -35,7 +34,7 @@ const goBack = () => window.history.length > 1 ? router.back() : router.push('/'
|
|
|
35
34
|
</button>
|
|
36
35
|
</div>
|
|
37
36
|
|
|
38
|
-
<div class="pd-t-medium w-max-25r">
|
|
37
|
+
<!-- <div class="pd-t-medium w-max-25r">
|
|
39
38
|
<span class="p-micro t-transp t-upper t-500 ls-wide d-block mn-b-small">Search Documentation</span>
|
|
40
39
|
<div class="field-wrapper bg-white flex flex-v-center radius-small pd-small gap-small">
|
|
41
40
|
<IconSearch class="i-small t-transp" />
|
|
@@ -45,7 +44,7 @@ const goBack = () => window.history.length > 1 ? router.back() : router.push('/'
|
|
|
45
44
|
<a href="#" class="flex flex-v-center gap-micro p-small t-transp"><IconInfo class="i-small" /> Help Center</a>
|
|
46
45
|
<a href="#" class="p-small t-transp">API Status</a>
|
|
47
46
|
</div>
|
|
48
|
-
</div>
|
|
47
|
+
</div> -->
|
|
49
48
|
|
|
50
49
|
</div>
|
|
51
50
|
</div>
|
|
@@ -4,7 +4,7 @@ import createEventModel from './models/event.model.js';
|
|
|
4
4
|
import createTicketModel from './models/ticket.model.js';
|
|
5
5
|
import eventsRoutes from './routes/events.routes.js';
|
|
6
6
|
import ticketsRoutes from './routes/tickets.routes.js';
|
|
7
|
-
function initializeEvent(app, db, origins, publicPath, options = {}) {
|
|
7
|
+
function initializeEvent({ app, db, origins, publicPath, options = {} }) {
|
|
8
8
|
console.log('initializeEvent publicPath:', publicPath);
|
|
9
9
|
// Получаем дополнительные поля для моделей из options
|
|
10
10
|
const { eventFields = {}, ticketFields = {} } = options;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import filesController from './controllers/files.controller.js';
|
|
2
2
|
import filesRoutes from './routes/files.routes.js';
|
|
3
|
-
function initializeFiles(app, db, origins, publicPath) {
|
|
3
|
+
function initializeFiles({ app, db, origins, publicPath }) {
|
|
4
4
|
// Настраиваем маршруты, если объект приложения передан
|
|
5
5
|
if (app) {
|
|
6
6
|
filesRoutes(app, db, origins, publicPath);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import GalleryController from './controllers/gallery.controller.js';
|
|
2
2
|
import PhotoModel from './models/photo.model.js';
|
|
3
3
|
import galleryRoutes from './routes/gallery.routes.js';
|
|
4
|
-
function initializeGallery(app, db, origins, publicPath) {
|
|
4
|
+
function initializeGallery({ app, db, origins, publicPath }) {
|
|
5
5
|
// Настраиваем модели в объекте базы данных
|
|
6
6
|
db.photo = PhotoModel(db);
|
|
7
7
|
// Настраиваем маршруты, если объект приложения передан
|
|
@@ -8,7 +8,7 @@ import ModelMilestone from './models/milestone.model.js';
|
|
|
8
8
|
import ModelTask from './models/task.model.js';
|
|
9
9
|
import ModelVote from './models/vote.model.js';
|
|
10
10
|
import ModelVoting from './models/voting.model.js';
|
|
11
|
-
function initializeGovernance(app, db, origins, publicPath) {
|
|
11
|
+
function initializeGovernance({ app, db, origins, publicPath }) {
|
|
12
12
|
// Setup models in the database object
|
|
13
13
|
db.initiative = ModelInitiative(db);
|
|
14
14
|
db.milestone = ModelMilestone(db);
|
|
@@ -271,7 +271,7 @@ export async function saveIconToDisk(iconId, category, iconName, mode = 'add', c
|
|
|
271
271
|
}
|
|
272
272
|
|
|
273
273
|
// Module initialization
|
|
274
|
-
function initializeIcons(app, db, origins, publicPath, options = {}) {
|
|
274
|
+
function initializeIcons({ app, db, origins, publicPath, options = {} }) {
|
|
275
275
|
console.log('initializeIcons publicPath:', publicPath);
|
|
276
276
|
|
|
277
277
|
// Setup routes if app object is provided
|
|
@@ -7,7 +7,7 @@ import inventoryRoutes from './routes/inventory.routes.js';
|
|
|
7
7
|
import inventoryPolicies from './policies/inventory.policies.js';
|
|
8
8
|
import availabilityServiceFactory from './services/availability.service.js';
|
|
9
9
|
|
|
10
|
-
function initializeInventory(app, db, origins, publicPath) {
|
|
10
|
+
function initializeInventory({ app, db, origins, publicPath }) {
|
|
11
11
|
// Регистрация моделей
|
|
12
12
|
db.stockAdjustment = StockAdjustmentModel(db);
|
|
13
13
|
db.stockAvailability = StockAvailabilityModel(db);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import marketplaceRoutes from './routes/marketplace.routes.js';
|
|
2
2
|
|
|
3
|
-
function initializeMarketplace(app, db, origins, publicPath) {
|
|
3
|
+
function initializeMarketplace({ app, db, origins, publicPath }) {
|
|
4
4
|
// Marketplace использует существующие модели (Spot, StockAvailability, Variant, Product, Organization)
|
|
5
5
|
// Модели уже зарегистрированы в spots, inventory, products, organizations модулях
|
|
6
6
|
|
|
@@ -6,7 +6,7 @@ import UserDeviceModel from './models/user-device.model.js';
|
|
|
6
6
|
import notificationsRoutes from './routes/notifications.routes.js';
|
|
7
7
|
import NotificationService from './services/notification.service.js';
|
|
8
8
|
|
|
9
|
-
function initializeNotifications(app, db, wss, origins, publicPath) {
|
|
9
|
+
function initializeNotifications({ app, db, wss, origins, publicPath }) {
|
|
10
10
|
// Set up models in the database object
|
|
11
11
|
db.notification = NotificationModel(db);
|
|
12
12
|
db.userDevice = UserDeviceModel(db);
|
|
@@ -6,7 +6,7 @@ import ModelTestimonial from './models/testimonial.model.js';
|
|
|
6
6
|
import RoutesApplications from './routes/applications.routes.js';
|
|
7
7
|
import RoutesOrder from './routes/orders.routes.js';
|
|
8
8
|
import RoutesCustomers from './routes/customers.routes.js';
|
|
9
|
-
function initializeOrders(app, db, origins, publicPath) {
|
|
9
|
+
function initializeOrders({ app, db, origins, publicPath }) {
|
|
10
10
|
// Setup models in the database object
|
|
11
11
|
db.order = ModelOrder(db);
|
|
12
12
|
db.customer = ModelCustomer(db);
|
|
@@ -20,7 +20,7 @@ import initOrganizationPolicies from './policies/organizations.policies.js';
|
|
|
20
20
|
|
|
21
21
|
const { getInstance } = coreabac;
|
|
22
22
|
|
|
23
|
-
function initializeOrganization(app, db, origins, publicPath) {
|
|
23
|
+
function initializeOrganization({ app, db, origins, publicPath }) {
|
|
24
24
|
// Настраиваем модели в объекте базы данных
|
|
25
25
|
db.department = DepartmentModel(db);
|
|
26
26
|
db.organization = OrganizationModel(db);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import FactoryPage from './controllers/factories/pages.factory.js';
|
|
2
2
|
import RoutesPage from './controllers/routes/pages.routes.js';
|
|
3
3
|
import ModelPage from './models/page.model.js';
|
|
4
|
-
function initializePages(app, db, origins, publicPath) {
|
|
4
|
+
function initializePages({ app, db, origins, publicPath }) {
|
|
5
5
|
// Setup models in the database object
|
|
6
6
|
db.page = ModelPage(db);
|
|
7
7
|
// Setup routes if the app object is provided
|
|
@@ -6,7 +6,7 @@ import VariantModel from './models/variant.model.js';
|
|
|
6
6
|
import categoriesRoutes from './routes/categories.routes.js';
|
|
7
7
|
import productsRoutes from './routes/products.routes.js';
|
|
8
8
|
import variantsRoutes from './routes/variants.routes.js';
|
|
9
|
-
function initializeProduct(app, db, origins, publicPath) {
|
|
9
|
+
function initializeProduct({ app, db, origins, publicPath }) {
|
|
10
10
|
// Настраиваем модели в объекте базы данных
|
|
11
11
|
db.product = ProductModel(db);
|
|
12
12
|
db.variant = VariantModel(db);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import RentRoutes from './controllers/routes/rents.routes.js';
|
|
2
2
|
import RentServices from './controllers/services/rents.services.js';
|
|
3
3
|
import RentModel from './models/rent.model.js';
|
|
4
|
-
function initializeRenting(app, db, origins, publicPath, options = {}) {
|
|
4
|
+
function initializeRenting({ app, db, origins, publicPath, options = {} }) {
|
|
5
5
|
// Получаем дополнительные поля для модели из options
|
|
6
6
|
const { rentFields = {} } = options;
|
|
7
7
|
// Инициализируем модель с дополнительными полями
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import ReportsController from './controllers/reports.controller.js';
|
|
2
2
|
import ReportModel from './models/report.model.js';
|
|
3
3
|
import reportsRoutes from './routes/reports.routes.js';
|
|
4
|
-
function initializeReports(app, db, origins, publicPath) {
|
|
4
|
+
function initializeReports({ app, db, origins, publicPath }) {
|
|
5
5
|
// Настраиваем модели в объекте базы данных
|
|
6
6
|
db.report = ReportModel(db);
|
|
7
7
|
// Настраиваем маршруты, если объект приложения передан
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import FactorySpot from './controllers/spots.controller.js';
|
|
2
2
|
import ModelSpot from './models/spot.model.js';
|
|
3
3
|
import RoutesSpot from './routes/spots.routes.js';
|
|
4
|
-
function initializeSpots(app, db, origins, publicPath) {
|
|
4
|
+
function initializeSpots({ app, db, origins, publicPath }) {
|
|
5
5
|
// Setup models in the database object
|
|
6
6
|
db.spot = ModelSpot(db);
|
|
7
7
|
// Setup routes if the app object is provided
|
|
@@ -5,7 +5,7 @@ import ModelPayment from './models/payment.model.js';
|
|
|
5
5
|
// import ModelReward from './models/reward.model.js';
|
|
6
6
|
// import ModelWallet from './models/wallet.model.js';
|
|
7
7
|
// Initialization function for setting up the module within the application
|
|
8
|
-
function initializePayments(app, db, wss, origins, publicPath) {
|
|
8
|
+
function initializePayments({ app, db, wss, origins, publicPath }) {
|
|
9
9
|
// Setup models in the database object
|
|
10
10
|
// db.wallet = ModelWallet(db);
|
|
11
11
|
db.payment = ModelPayment(db);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Loader.vue.js","sources":["../../../../../src/components/Loader/Loader.vue"],"sourcesContent":["<template>\n <div class=\"circular-loader z-index-1 w-100 h-100 w-max-2r h-max-2r\" :class=\"{ 'circular-loader-centered': centered }\">\n <svg viewBox=\"25 25 50 50\">\n <circle class=\"circular-loader-fill\" cx=\"50\" cy=\"50\" r=\"20\" fill=\"none\" stroke-width=\"4\" stroke-miterlimit=\"10\" />\n <circle class=\"circular-loader-circle\" cx=\"50\" cy=\"50\" r=\"20\" fill=\"none\" stroke-width=\"4\" stroke-miterlimit=\"10\" />\n </svg>\n <div v-if=\"progress\" class=\"progress-text\">{{ progress }}</div>\n <div v-if=\"status\" class=\"uppercase fw-semi w-m-10r status-text\">{{ status }}</div>\n </div>\n</template>\n\n<script>\nexport default {\n props: {\n progress: {\n type: Number,\n default: null,\n },\n status: {\n type: String,\n default: null,\n },\n centered: {\n type: Boolean,\n default: false\n },\n },\n};\n</script>\n\n<style>\n.circular-loader-centered {\n top: calc(50% - 1rem);\n left: calc(50% - 1rem);\n}\n\n.circular-loader svg {\n animation: rotate 2s linear infinite;\n}\n\n.circular-loader-circle {\n stroke-dasharray: 1, 200;\n stroke-dashoffset: 0;\n stroke-linecap: round;\n stroke: rgb(var(--main));\n animation: dash 1.5s ease-in-out infinite;\n}\n\n.circular-loader-fill {\n stroke-linecap: round;\n stroke: rgba(var(--black),0.2);\n}\n\n.progress-text {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n font-size: 0.8rem;\n color: rgb(var(--main));;\n}\n\n.status-text {\n position: absolute;\n top: 120%;\n left: calc(50% - 5rem);\n font-size: 0.8rem;\n width: 10rem !important;\n text-align: center;\n}\n\n@keyframes rotate {\n 100% {\n transform: rotate(360deg);\n }\n}\n\n@keyframes dash {\n 0% {\n stroke-dasharray: 1, 200;\n stroke-dashoffset: 0;\n }\n 50% {\n stroke-dasharray: 89, 200;\n stroke-dashoffset: -35;\n }\n 100% {\n stroke-dasharray: 1, 200;\n stroke-dashoffset: -124;\n }\n}\n</style>"],"names":["_createElementBlock","_normalizeClass","_createElementVNode","_toDisplayString","_createCommentVNode"],"mappings":";;;AAYA,MAAK,YAAU;AAAA,EACb,OAAO;AAAA,IACL,UAAU;AAAA,MACR,MAAM;AAAA,MACN,SAAS;AAAA;IAEX,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA;IAEX,UAAU;AAAA,MACR,MAAM;AAAA,MACN,SAAS;AAAA;;AAGf;;EA3BA,KAAA;AAAA,EAMyB,OAAM;;;EAN/B,KAAA;AAAA,EAOuB,OAAM;;;sBAN3BA,mBAOM,OAAA;AAAA,IAPD,OADPC,eAAA,CACa,2DAAyD,EAAA,4BAAuC,OAAA,UAAQ,CAAA;AAAA;8BACjHC,mBAGM,OAAA,EAHD,SAAQ,iBAAa;AAAA,MACxBA,mBAAkH,UAAA;AAAA,QAA1G,OAAM;AAAA,QAAuB,IAAG;AAAA,QAAK,IAAG;AAAA,QAAK,GAAE;AAAA,QAAK,MAAK;AAAA,QAAO,gBAAa;AAAA,QAAI,qBAAkB;AAAA;MAC3GA,mBAAoH,UAAA;AAAA,QAA5G,OAAM;AAAA,QAAyB,IAAG;AAAA,QAAK,IAAG;AAAA,QAAK,GAAE;AAAA,QAAK,MAAK;AAAA,QAAO,gBAAa;AAAA,QAAI,qBAAkB;AAAA;;IAEpG,OAAA,yBAAXF,mBAA+D,OAA/D,YAA+DG,gBAAjB,OAAA,QAAQ,GAAA,CAAA,KAN1DC,mBAAA,IAAA,IAAA;AAAA,IAOe,OAAA,uBAAXJ,mBAAmF,OAAnF,YAAmFG,gBAAf,OAAA,MAAM,GAAA,CAAA,KAP9EC,mBAAA,IAAA,IAAA;AAAA;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Menu.vue.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Select.vue.js","sources":["../../../../../src/components/Select/Select.vue"],"sourcesContent":["<template>\n <!-- Input Wrapper -->\n <div \n ref=\"fieldWrapper\"\n tabindex=\"0\"\n @click.stop=\"toggleMenu\" \n v-click-outside=\"clickedOutside\" \n :class=\"$attrs.class\" \n class=\"cursor-pointer field-wrapper flex-v-center flex-nowrap flex pos-relative\"\n >\n <!-- Label -->\n <span v-if=\"label\" class=\"t-transp mn-r-small\">{{label}}</span>\n \n <!-- Input -->\n <span>\n {{ optionsSelected ? (optionsSelected.name || optionsSelected[props.value] || optionsSelected) : placeholder }}\n </span>\n <!-- Dropdown menu -->\n <transition mode=\"out-in\" name=\"TransitionTranslateY\">\n <ul \n v-show=\"showMenu\" \n class=\"bs-black pos-absolute pos-t-100 pos-l-0 z-index-5 pd-small radius-small bg-white mn-t-thin w-100\"\n style=\"min-width: max-content;\"\n >\n <li @click.stop=\"selectOption(option)\" v-for=\"option in optionsListed\" class=\"radius-thin hover:bg-light pd-thin text-box-trim\">\n <span v-if=\"option\" class=\"w-100\">\n {{ option.name || option[props.value] || option }}\n </span>\n </li>\n </ul>\n </transition>\n </div>\n <!-- Validation -->\n <transition mode=\"out-in\" name=\"fade\">\n <div v-if=\"validation\" class=\"mn-t-thin invalid-feedback\">\n * {{validation.message}}\n </div>\n </transition>\n</template>\n<script setup>\nimport { ref, computed, watch, nextTick } from 'vue'\nimport clickOutside from '../FieldPhone/click-outside.js';\nlet vClickOutside = clickOutside\nconst emit = defineEmits([\n 'update:select', \n 'focus', \n 'blur'\n])\nconst props = defineProps({\n label: String,\n placeholder: { type: String, default: 'Please select an item' },\n select: [String, Object],\n property: String,\n value: String,\n options: { type: Array, default: () => [] },\n validation: Boolean,\n})\nconst showMenu = ref(false)\nconst fieldWrapper = ref(null)\nconst optionsSelected = ref(\n props.property \n ? findObjectByValue(props.select, props.property, props.options) \n : props.select\n)\nconst optionsListed = computed(() => {\n return props.select \n ? props.options.filter(option => option !== props.select) \n : props.options\n})\nwatch(() => props.select, (newSelect) => {\n optionsSelected.value = \n props.property \n ? findObjectByValue(props.select, props.property, props.options) \n : props.select;\n});\nconst toggleMenu = async () => {\n showMenu.value = !showMenu.value\n \n if (showMenu.value) {\n await nextTick()\n fieldWrapper.value?.focus()\n emit('focus')\n } else {\n emit('blur')\n }\n}\nfunction clickedOutside () {\n showMenu.value = false\n}\nconst selectOption = option => {\n optionsSelected.value = option\n \n toggleMenu()\n if (props.property) { \n emit('update:select', optionsSelected.value[props.property])\n } else {\n emit('update:select', optionsSelected.value)\n }\n}\nfunction findObjectByValue (value, property, objects) {\n for (const object of objects) {\n if (object[property] === value || object === value) {\n return object;\n }\n }\n return null;\n}\n</script>\n<style lang=\"scss\" scoped>\n li {\n list-style-type: none;\n }\n ul li {\n line-height: 2;\n }\n .field-wrapper:focus {\n outline: none;\n }\n</style>"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,QAAI,gBAAgB;AACpB,UAAM,OAAO;AAKb,UAAM,QAAQ;AASd,UAAM,WAAW,IAAI,KAAK;AAC1B,UAAM,eAAe,IAAI,IAAI;AAC7B,UAAM,kBAAkB;AAAA,MACtB,MAAM,WACJ,kBAAkB,MAAM,QAAQ,MAAM,UAAU,MAAM,OAAO,IAC7D,MAAM;AAAA,IACV;AACA,UAAM,gBAAgB,SAAS,MAAM;AACnC,aAAO,MAAM,SACX,MAAM,QAAQ,OAAO,YAAU,WAAW,MAAM,MAAM,IACtD,MAAM;AAAA,IACV,CAAC;AACD,UAAM,MAAM,MAAM,QAAQ,CAAC,cAAc;AACvC,sBAAgB,QAChB,MAAM,WACJ,kBAAkB,MAAM,QAAQ,MAAM,UAAU,MAAM,OAAO,IAC7D,MAAM;AAAA,IACV,CAAC;AACD,UAAM,aAAa,YAAY;AAC7B,eAAS,QAAQ,CAAC,SAAS;AAE3B,UAAI,SAAS,OAAO;AAClB,cAAM,SAAQ;AACd,qBAAa,OAAO,MAAK;AACzB,aAAK,OAAO;AAAA,MACd,OAAO;AACL,aAAK,MAAM;AAAA,MACb;AAAA,IACF;AACA,aAAS,iBAAkB;AACzB,eAAS,QAAQ;AAAA,IACnB;AACA,UAAM,eAAe,YAAU;AAC7B,sBAAgB,QAAQ;AAExB,iBAAU;AACV,UAAI,MAAM,UAAU;AAClB,aAAK,iBAAiB,gBAAgB,MAAM,MAAM,QAAQ,CAAC;AAAA,MAC7D,OAAO;AACL,aAAK,iBAAiB,gBAAgB,KAAK;AAAA,MAC7C;AAAA,IACF;AACA,aAAS,kBAAmB,OAAO,UAAU,SAAS;AACpD,iBAAW,UAAU,SAAS;AAC5B,YAAI,OAAO,QAAQ,MAAM,SAAS,WAAW,OAAO;AAClD,iBAAO;AAAA,QACT;AAAA,MACF;AACA,aAAO;AAAA,IACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Spoiler.vue.js","sources":["../../../../../src/components/Spoiler/Spoiler.vue"],"sourcesContent":["<template>\n <div>\n <div @click=\"toggleSpoiler\" class=\"flex-v-center flex-nowrap flex\">\n <slot name=\"header\" :isOpen=\"showSpoiler\"></slot>\n </div>\n <transition\n name=\"collapse\"\n @enter=\"onEnter\"\n @after-enter=\"onAfterEnter\"\n @leave=\"onLeave\"\n >\n <div v-show=\"showSpoiler\" class=\"spoiler\" ref=\"spoilerContent\">\n <slot name=\"content\"></slot>\n </div>\n </transition>\n </div>\n</template>\n<script setup>\nimport { ref, onMounted } from 'vue';\n\nconst props = defineProps({\n status: {\n type: Boolean,\n default: false\n }\n});\n\nconst showSpoiler = ref(false);\nconst spoilerContent = ref(null);\n\nonMounted(() => {\n if (props.status) {\n showSpoiler.value = props.status;\n }\n});\n\nconst toggleSpoiler = () => {\n showSpoiler.value = !showSpoiler.value;\n};\n\n// Анимация открытия\nconst onEnter = (el) => {\n el.style.height = '0';\n void el.offsetHeight; // force reflow\n el.style.height = el.scrollHeight + 'px';\n};\n\nconst onAfterEnter = (el) => {\n el.style.height = 'auto';\n};\n\n// Анимация закрытия\nconst onLeave = (el) => {\n el.style.height = el.scrollHeight + 'px';\n void el.offsetHeight; // force reflow\n el.style.height = '0';\n};\n\ndefineExpose({\n showSpoiler\n});\n</script>\n<style lang=\"scss\">\n.spoiler {\n overflow: hidden;\n transition: height 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n}\n</style>"],"names":[],"mappings":";;;;;;;;;;;AAoBA,UAAM,QAAQ;AAOd,UAAM,cAAc,IAAI,KAAK;AAC7B,UAAM,iBAAiB,IAAI,IAAI;AAE/B,cAAU,MAAM;AACd,UAAI,MAAM,QAAQ;AAChB,oBAAY,QAAQ,MAAM;AAAA,MAC5B;AAAA,IACF,CAAC;AAED,UAAM,gBAAgB,MAAM;AAC1B,kBAAY,QAAQ,CAAC,YAAY;AAAA,IACnC;AAGA,UAAM,UAAU,CAAC,OAAO;AACtB,SAAG,MAAM,SAAS;AAClB,WAAK,GAAG;AACR,SAAG,MAAM,SAAS,GAAG,eAAe;AAAA,IACtC;AAEA,UAAM,eAAe,CAAC,OAAO;AAC3B,SAAG,MAAM,SAAS;AAAA,IACpB;AAGA,UAAM,UAAU,CAAC,OAAO;AACtB,SAAG,MAAM,SAAS,GAAG,eAAe;AACpC,WAAK,GAAG;AACR,SAAG,MAAM,SAAS;AAAA,IACpB;AAEA,aAAa;AAAA,MACX;AAAA,IACF,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Filters.vue.js","sources":["../../../../../../../../src/modules/core/views/components/sections/Filters.vue"],"sourcesContent":["<template>\n <div class=\"flex o-x-scroll scroll-hide ws-nowrap gap-thin\">\n <!-- All Filters Button -->\n <button\n @click=\"showAllFilters = true\"\n class=\"pd-small radius-medium bg-light flex-v-center flex gap-micro cursor-pointer\"\n :class=\"{ 'bg-main': activeFiltersCount > 0 }\"\n >\n <IconFilter class=\"i-regular\" />\n <span class=\"h-1r\"></span>\n <span v-if=\"activeFiltersCount\">{{ activeFiltersCount }}</span>\n </button>\n\n <!-- Individual Filter Buttons -->\n <button\n v-for=\"filter in filters\"\n :key=\"filter.value\"\n @click=\"openFilter(filter.value)\"\n class=\"pd-small radius-medium bg-light cursor-pointer flex-v-center flex gap-micro\"\n :class=\"{ 'selected bg-main': isFilterActive(filter) }\"\n >\n <IconCalendar v-if=\"filter.type === 'date'\" class=\"mn-r-micro i-regular\" />\n <span class=\"ws-nowrap\">{{ filter.type === 'date' && getFilterValue(filter) ? formatFilterValue(filter) : filter.title }}</span>\n <span v-if=\"getFilterValue(filter) && filter.type !== 'date'\" class=\"mn-l-micro\">\n {{ formatFilterValue(filter) }}\n </span>\n </button>\n\n <!-- All Filters Popup -->\n <Popup\n :isPopupOpen=\"showAllFilters\"\n @close-popup=\"closeAllFilters\"\n :align=\"isPhone() ? 'bottom center' : 'center center'\"\n class=\"w-min-20r bg-white radius-medium mobile:radius-zero mobile:radius-tr-medium mobile:radius-tl-medium mobile:w-100 pd-medium\"\n >\n <FiltersGroup\n :filters=\"filters\"\n v-model:selected=\"tempSelected\"\n :immediate=\"false\"\n :showHeader=\"true\"\n :showApplyButton=\"true\"\n :showResetButton=\"true\"\n @update:selected=\"applyAllFilters\"\n />\n </Popup>\n\n <!-- Individual Filter Popups -->\n <Popup\n v-for=\"filter in filters\"\n :key=\"`popup-${filter.value}`\"\n :isPopupOpen=\"individualPopups[filter.value]\"\n @close-popup=\"cancelFilter(filter.value)\"\n :align=\"isPhone() ? 'bottom center' : 'center center'\"\n class=\"bg-white radius-medium mobile:radius-zero mobile:radius-tr-medium mobile:radius-tl-medium mobile:w-100 pd-medium\"\n >\n <h4 class=\"mn-b-medium\">{{ filter.title }}</h4>\n\n <!-- Checkbox Filter -->\n <FilterCheckbox\n v-if=\"filter.type === 'checkbox'\"\n v-model=\"tempSelected[filter.value]\"\n :options=\"filter.options\"\n />\n\n <!-- Range Filter -->\n <FilterRange\n v-else-if=\"filter.type === 'range'\"\n v-model=\"tempSelected[filter.value]\"\n :minPlaceholder=\"filter.minPlaceholder || 'Min'\"\n :maxPlaceholder=\"filter.maxPlaceholder || 'Max'\"\n :label=\"filter.label\"\n />\n\n <!-- Date Filter -->\n <div v-else-if=\"filter.type === 'date'\">\n <div class=\"mn-t-small\">\n <Calendar\n v-model:date=\"tempSelected[filter.value]\"\n :allowRange=\"true\"\n :disablePastDates=\"true\"\n class=\"bg-light radius-small\"\n />\n </div>\n </div>\n\n <!-- Radio/Options Filter -->\n <FilterOptions\n v-else-if=\"filter.type === 'radio'\"\n v-model=\"tempSelected[filter.value]\"\n :options=\"filter.options\"\n />\n\n <div class=\"flex gap-thin mn-t-medium\">\n <button\n @click=\"cancelFilter(filter.value)\"\n class=\"bg-light button flex-child-full\"\n >\n Cancel\n </button>\n <button\n @click=\"applyFilter(filter.value)\"\n class=\"bg-main w-100 button flex-child-full\"\n >\n Apply\n </button>\n </div>\n </Popup>\n </div>\n</template>\n\n<script setup>\nimport { ref, computed, reactive, watch } from 'vue'\nimport { useGlobalMixins } from '@martyrs/src/modules/core/views/mixins/mixins.js'\nimport Popup from '@martyrs/src/components/Popup/Popup.vue'\nimport Calendar from '@martyrs/src/components/Calendar/Calendar.vue'\nimport FiltersGroup from './filters/FiltersGroup.vue'\nimport FilterCheckbox from './filters/FilterCheckbox.vue'\nimport FilterRange from './filters/FilterRange.vue'\nimport FilterDateRange from './filters/FilterDateRange.vue'\nimport FilterOptions from './filters/FilterOptions.vue'\nimport IconFilter from '@martyrs/src/modules/icons/navigation/IconFilter.vue'\nimport IconCross from '@martyrs/src/modules/icons/navigation/IconCross.vue'\nimport IconCalendar from '@martyrs/src/modules/icons/entities/IconCalendar.vue'\n\nconst filters = defineModel('filters', {\n type: Array,\n required: true\n})\n\nconst selected = defineModel('selected', {\n type: Object,\n default: () => ({})\n})\n\nconst emit = defineEmits(['select'])\n\nconst { formatDate, returnCurrency } = useGlobalMixins()\n\n// State\nconst showAllFilters = ref(false)\nconst individualPopups = reactive({})\nconst tempSelected = reactive({})\nconst tempDateRange = ref(null)\n\n// Initialize popups and temp values\nwatch(filters, (newFilters) => {\n newFilters.forEach(filter => {\n individualPopups[filter.value] = false\n \n if (!tempSelected[filter.value]) {\n if (filter.type === 'checkbox') {\n tempSelected[filter.value] = [...(selected.value[filter.value] || [])]\n } else if (filter.type === 'range') {\n tempSelected[filter.value] = { ...(selected.value[filter.value] || { min: '', max: '' }) }\n } else if (filter.type === 'date') {\n tempSelected[filter.value] = selected.value[filter.value] || null\n } else {\n tempSelected[filter.value] = selected.value[filter.value] || null\n }\n }\n })\n}, { immediate: true, deep: true })\n\n// Sync selected to tempSelected\nwatch(selected, (newSelected) => {\n Object.keys(newSelected).forEach(key => {\n const filter = filters.value.find(f => f.value === key)\n if (filter) {\n if (filter.type === 'checkbox') {\n tempSelected[key] = [...(newSelected[key] || [])]\n } else if (filter.type === 'range') {\n tempSelected[key] = { ...(newSelected[key] || { min: '', max: '' }) }\n } else {\n tempSelected[key] = newSelected[key]\n }\n }\n })\n}, { deep: true })\n\n// Computed\nconst activeFiltersCount = computed(() => {\n return Object.entries(selected.value).filter(([key, value]) => {\n if (Array.isArray(value)) return value.length > 0\n if (typeof value === 'object' && value !== null) {\n return value.min || value.max\n }\n return value !== null && value !== undefined\n }).length\n})\n\n// Methods\nconst openFilter = (filterValue) => {\n individualPopups[filterValue] = true\n}\n\nconst isFilterActive = (filter) => {\n const value = selected.value[filter.value]\n if (!value) return false\n if (Array.isArray(value)) return value.length > 0\n if (filter.type === 'range') return value.min || value.max\n return true\n}\n\nconst getFilterValue = (filter) => {\n const value = selected.value[filter.value]\n if (!value) return false\n \n if (filter.type === 'range') {\n return value.min || value.max\n }\n \n if (filter.type === 'date') {\n return value && value.start && value.end\n }\n \n if (Array.isArray(value)) {\n return value.length > 0\n }\n \n return value\n}\n\nconst formatFilterValue = (filter) => {\n const value = selected.value[filter.value]\n if (!value) return ''\n \n if (Array.isArray(value)) {\n return `(${value.length})`\n }\n \n if (filter.type === 'range') {\n if (!value.min && !value.max) return ''\n return `${value.min || '0'}-${value.max || '∞'}`\n }\n \n if (filter.type === 'date') {\n if (!value || !value.start || !value.end) return ''\n return `${formatDate(value.start, { dayMonth: true, language: 'en' })} - ${formatDate(value.end, { dayMonth: true, language: 'en' })}`\n }\n \n if (filter.type === 'radio') {\n const option = filter.options.find(o => o.value === value)\n return option ? `(${option.label})` : ''\n }\n \n return ''\n}\n\nconst applyFilter = (filterValue) => {\n selected.value[filterValue] = tempSelected[filterValue]\n individualPopups[filterValue] = false\n emit('select', { filter: filterValue, value: tempSelected[filterValue] })\n}\n\nconst cancelFilter = (filterValue) => {\n const filter = filters.value.find(f => f.value === filterValue)\n if (filter) {\n if (filter.type === 'checkbox') {\n tempSelected[filterValue] = [...(selected.value[filterValue] || [])]\n } else if (filter.type === 'range') {\n tempSelected[filterValue] = { ...(selected.value[filterValue] || { min: '', max: '' }) }\n } else if (filter.type === 'date') {\n tempSelected[filterValue] = selected.value[filterValue] || null\n } else {\n tempSelected[filterValue] = selected.value[filterValue] || null\n }\n }\n individualPopups[filterValue] = false\n}\n\nconst applyAllFilters = (newValues) => {\n Object.entries(newValues).forEach(([key, value]) => {\n if (selected.value[key] !== value) {\n selected.value[key] = value\n emit('select', { filter: key, value })\n }\n })\n showAllFilters.value = false\n}\n\nconst closeAllFilters = () => {\n showAllFilters.value = false\n}\n</script>\n\n<style scoped>\n.filters-content {\n max-height: 60vh;\n overflow-y: auto;\n}\n</style>"],"names":["_useModel"],"mappings":"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"}
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { mkdir, readFile, writeFile, readdir, stat, chmod, copyFile } from 'fs/promises';
|
|
2
|
-
import { join, dirname, relative } from 'path';
|
|
3
|
-
import { fileURLToPath } from 'url';
|
|
4
|
-
import Mustache from 'mustache';
|
|
5
|
-
import { execSync } from 'child_process';
|
|
6
|
-
|
|
7
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
-
const __dirname = dirname(__filename);
|
|
9
|
-
|
|
10
|
-
const TEMPLATES_DIR = join(__dirname, '../templates');
|
|
11
|
-
|
|
12
|
-
export async function createProject(projectName, options) {
|
|
13
|
-
const targetDir = join(process.cwd(), projectName);
|
|
14
|
-
|
|
15
|
-
console.log(`\nCreating project: ${projectName}\n`);
|
|
16
|
-
|
|
17
|
-
// Контекст для шаблонов
|
|
18
|
-
const context = {
|
|
19
|
-
projectName,
|
|
20
|
-
projectNameLower: projectName.toLowerCase().replace(/[^a-z0-9]/g, ''),
|
|
21
|
-
martyrsVersion: '^0.2.585',
|
|
22
|
-
year: new Date().getFullYear(),
|
|
23
|
-
port: '8040',
|
|
24
|
-
portNginx: '8041',
|
|
25
|
-
portWss: '8020',
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
// Копируем шаблоны
|
|
29
|
-
await copyTemplates(TEMPLATES_DIR, targetDir, context);
|
|
30
|
-
|
|
31
|
-
// Делаем скрипты исполняемыми
|
|
32
|
-
try {
|
|
33
|
-
await chmod(join(targetDir, 'start-dev.sh'), 0o755);
|
|
34
|
-
await chmod(join(targetDir, 'start-prod.sh'), 0o755);
|
|
35
|
-
} catch (e) {
|
|
36
|
-
// Игнорируем если файлов нет
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Git init
|
|
40
|
-
try {
|
|
41
|
-
execSync('git init', { cwd: targetDir, stdio: 'pipe' });
|
|
42
|
-
console.log('✓ Git repository initialized');
|
|
43
|
-
} catch (e) {
|
|
44
|
-
console.log('⚠ Git init skipped');
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// pnpm install
|
|
48
|
-
if (!options.skipInstall) {
|
|
49
|
-
console.log('\nInstalling dependencies...\n');
|
|
50
|
-
try {
|
|
51
|
-
execSync('pnpm install', { cwd: join(targetDir, 'app'), stdio: 'inherit' });
|
|
52
|
-
console.log('\n✓ Dependencies installed');
|
|
53
|
-
} catch (e) {
|
|
54
|
-
console.log('\n⚠ Install failed. Run manually: cd app && pnpm install');
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Инструкции
|
|
59
|
-
console.log(`
|
|
60
|
-
═══════════════════════════════════════════
|
|
61
|
-
Project "${projectName}" created!
|
|
62
|
-
═══════════════════════════════════════════
|
|
63
|
-
|
|
64
|
-
Next steps:
|
|
65
|
-
|
|
66
|
-
cd ${projectName}/app
|
|
67
|
-
${options.skipInstall ? 'pnpm install\n ' : ''}pnpm dev:nginx
|
|
68
|
-
|
|
69
|
-
Then open: http://localhost:${context.portNginx}
|
|
70
|
-
|
|
71
|
-
═══════════════════════════════════════════
|
|
72
|
-
`);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
async function copyTemplates(srcDir, destDir, context) {
|
|
76
|
-
await mkdir(destDir, { recursive: true });
|
|
77
|
-
|
|
78
|
-
const entries = await readdir(srcDir, { withFileTypes: true });
|
|
79
|
-
|
|
80
|
-
for (const entry of entries) {
|
|
81
|
-
const srcPath = join(srcDir, entry.name);
|
|
82
|
-
let destName = entry.name;
|
|
83
|
-
|
|
84
|
-
// Убираем .mustache из имени
|
|
85
|
-
if (destName.endsWith('.mustache')) {
|
|
86
|
-
destName = destName.replace('.mustache', '');
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const destPath = join(destDir, destName);
|
|
90
|
-
|
|
91
|
-
if (entry.isDirectory()) {
|
|
92
|
-
await copyTemplates(srcPath, destPath, context);
|
|
93
|
-
} else {
|
|
94
|
-
const content = await readFile(srcPath, 'utf8');
|
|
95
|
-
|
|
96
|
-
// Обрабатываем .mustache файлы
|
|
97
|
-
let output = content;
|
|
98
|
-
if (entry.name.endsWith('.mustache')) {
|
|
99
|
-
output = Mustache.render(content, context);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
await mkdir(dirname(destPath), { recursive: true });
|
|
103
|
-
await writeFile(destPath, output);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
package/src/cli/index.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { program } from 'commander';
|
|
4
|
-
import { createProject } from './commands/create.js';
|
|
5
|
-
import { fileURLToPath } from 'url';
|
|
6
|
-
import { dirname, join } from 'path';
|
|
7
|
-
import { readFileSync } from 'fs';
|
|
8
|
-
|
|
9
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
-
const __dirname = dirname(__filename);
|
|
11
|
-
|
|
12
|
-
const pkg = JSON.parse(readFileSync(join(__dirname, '../../package.json'), 'utf8'));
|
|
13
|
-
|
|
14
|
-
program
|
|
15
|
-
.name('martyrs')
|
|
16
|
-
.description('CLI for @ozdao/martyrs framework')
|
|
17
|
-
.version(pkg.version);
|
|
18
|
-
|
|
19
|
-
program
|
|
20
|
-
.command('create <project-name>')
|
|
21
|
-
.description('Create a new martyrs project')
|
|
22
|
-
.option('--skip-install', 'Skip pnpm install after creation')
|
|
23
|
-
.action(createProject);
|
|
24
|
-
|
|
25
|
-
program.parse();
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
NODE_ENV=development
|
|
2
|
-
PORT={{port}}
|
|
3
|
-
PORT_WSS={{portWss}}
|
|
4
|
-
SSL=false
|
|
5
|
-
APP_NAME={{projectName}}
|
|
6
|
-
|
|
7
|
-
DOMAIN_URL=localhost
|
|
8
|
-
API_URL=http://localhost:{{port}}
|
|
9
|
-
WSS_URL=ws://localhost:{{portNginx}}/api/ws
|
|
10
|
-
|
|
11
|
-
DB_ADDRESS='mongodb://localhost:27017/{{projectNameLower}}?authSource=admin'
|
|
12
|
-
SECRET_KEY=change-me-in-production
|
|
13
|
-
|
|
14
|
-
GOOGLE_TAG_ID=
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
NODE_ENV=production
|
|
2
|
-
PORT=8080
|
|
3
|
-
PORT_WSS=8020
|
|
4
|
-
SSL=false
|
|
5
|
-
APP_NAME={{projectName}}
|
|
6
|
-
|
|
7
|
-
DOMAIN_URL=example.com
|
|
8
|
-
API_URL=https://example.com
|
|
9
|
-
WSS_URL=wss://example.com/api/ws
|
|
10
|
-
|
|
11
|
-
DB_ADDRESS='mongodb://user:password@localhost:27017/{{projectNameLower}}?authSource=admin'
|
|
12
|
-
SECRET_KEY=change-me-in-production
|
|
13
|
-
|
|
14
|
-
GOOGLE_TAG_ID=
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
FROM node:22.14.0-alpine
|
|
2
|
-
|
|
3
|
-
WORKDIR /app
|
|
4
|
-
|
|
5
|
-
RUN apk update && apk upgrade && apk add --no-cache \
|
|
6
|
-
build-base \
|
|
7
|
-
git \
|
|
8
|
-
make \
|
|
9
|
-
gcc \
|
|
10
|
-
g++ \
|
|
11
|
-
libc6-compat \
|
|
12
|
-
vips-dev \
|
|
13
|
-
python3 \
|
|
14
|
-
py3-setuptools \
|
|
15
|
-
linux-headers \
|
|
16
|
-
libuv-dev \
|
|
17
|
-
openssl-dev \
|
|
18
|
-
zlib-dev
|
|
19
|
-
|
|
20
|
-
COPY app/package*.json ./
|
|
21
|
-
COPY public/sw.js public/sw.js
|
|
22
|
-
|
|
23
|
-
RUN corepack enable
|
|
24
|
-
RUN corepack prepare pnpm@latest --activate
|
|
25
|
-
|
|
26
|
-
RUN pnpm install
|
|
27
|
-
|
|
28
|
-
COPY app/ .
|
|
29
|
-
|
|
30
|
-
ENV TZ=Europe/Moscow
|
|
31
|
-
|
|
32
|
-
EXPOSE 8080
|
|
33
|
-
|
|
34
|
-
RUN pnpm run build
|
|
35
|
-
|
|
36
|
-
CMD ["pnpm", "run", "start"]
|