@ozdao/prometheus-framework 0.1.32 → 0.1.33

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. package/dist/Chips-41cd6570.mjs +203 -0
  2. package/dist/Chips-c3d7341e.js +1 -0
  3. package/dist/EULA-e05236af.mjs +4210 -0
  4. package/dist/EULA-f5fba925.js +1 -0
  5. package/dist/Feed-046852fc.js +1 -0
  6. package/dist/Feed-4efa2a93.mjs +394 -0
  7. package/dist/Feed-acfbb839.mjs +371 -0
  8. package/dist/Feed-e6e84388.js +1 -0
  9. package/dist/Image-93c3a270.mjs +480 -0
  10. package/dist/Image-de94b883.js +9 -0
  11. package/dist/Product-1892b14a.js +7 -0
  12. package/dist/Product-d3f1d10a.mjs +844 -0
  13. package/dist/ProductEdit-8e779ed8.js +1 -0
  14. package/dist/ProductEdit-ebcc3f98.mjs +306 -0
  15. package/dist/ProfileBlogposts-8c10a505.js +1 -0
  16. package/dist/ProfileBlogposts-a2f7cd4c.mjs +70 -0
  17. package/dist/ProfileEvents-47409c9e.mjs +62 -0
  18. package/dist/ProfileEvents-db12cf78.js +1 -0
  19. package/dist/auth.server.js +4 -4
  20. package/dist/auth.server.mjs +4 -4
  21. package/dist/community.client.cjs +1 -1
  22. package/dist/community.client.js +217 -241
  23. package/dist/community.server.js +2 -2
  24. package/dist/community.server.mjs +2 -2
  25. package/dist/events.client.cjs +1 -1
  26. package/dist/events.client.js +4 -4
  27. package/dist/events.server.js +447 -270
  28. package/dist/events.server.mjs +447 -270
  29. package/dist/files.server.js +1 -1
  30. package/dist/files.server.mjs +1 -1
  31. package/dist/legal.client.cjs +1 -1
  32. package/dist/legal.client.js +1 -1
  33. package/dist/modules/community/components/sections/Feed.vue.d.ts +2 -0
  34. package/dist/organizations.client-76c3660a.mjs +3072 -0
  35. package/dist/organizations.client-ddbf8809.js +3 -0
  36. package/dist/organizations.client.cjs +1 -1
  37. package/dist/organizations.client.js +4 -4
  38. package/dist/organizations.server.js +4 -4
  39. package/dist/organizations.server.mjs +4 -4
  40. package/dist/style.css +1 -1
  41. package/dist/users.client.cjs +1 -1
  42. package/dist/users.client.js +2 -2
  43. package/dist/users.server.js +2 -2
  44. package/dist/users.server.mjs +2 -2
  45. package/package.json +1 -1
  46. package/src/components/CardHeader/CardHeader.vue +3 -3
  47. package/src/modules/community/components/blocks/CardBlogpost.vue +2 -4
  48. package/src/modules/community/components/sections/Feed.vue +44 -39
  49. package/src/modules/community/components/sections/HotPosts.vue +9 -56
  50. package/src/modules/events/components/blocks/CardEvent.vue +0 -2
  51. package/src/modules/events/controllers/events.controller.js +55 -265
  52. package/src/modules/events/controllers/utils/queryProcessor.js +118 -0
  53. package/src/modules/events/models/event.model.js +43 -49
  54. package/src/modules/events/models/event.new.model.js +82 -0
  55. package/src/modules/files/middlewares/server/middlewareMulter.js +1 -0
  56. package/src/modules/globals/controllers/utils/queryProcessor.js +228 -0
  57. package/src/modules/globals/models/common.schema.js +14 -0
  58. package/src/modules/globals/models/engagement.schema.js +10 -0
  59. package/src/modules/globals/models/metadata.schema.js +15 -0
  60. package/src/modules/globals/models/ownership.schema.js +34 -0
  61. package/src/modules/globals/utils/seo-friendly-url.js +28 -0
  62. package/src/modules/legal/components/pages/legal/EULA.vue +0 -3
  63. package/src/modules/products/controllers/categories.controller.js +3 -0
  64. package/src/modules/products/models/category.model.js +63 -13
  65. package/src/modules/products/models/leftover.model.js +38 -17
  66. package/src/modules/products/models/modification.model.js +31 -14
  67. package/src/modules/products/models/product.model.js +37 -38
  68. package/src/modules/products/products.server.js +11 -1
@@ -1,44 +1,41 @@
1
1
  <template>
2
- <section class="feed">
3
- <transition name="scaleTransition">
4
- <Loader
5
- v-if="isLoading"
6
- class="z-index-5 pos-t-50 left-t-50 pos-absolute"
7
- />
8
- </transition>
2
+ <transition name="scaleTransition">
3
+ <Loader
4
+ v-if="isLoading"
5
+ class="z-index-5 pos-t-50 left-t-50 pos-absolute"
6
+ />
7
+ </transition>
9
8
 
10
- <transition name="scaleTransition">
11
- <EmptyState
12
- v-if="!isLoading && posts.length < 1"
13
- title="No Blog Posts Found"
14
- description="Currently, there are no posts available in this blog. Please check back later."
15
- class="pd-medium mn-thin bg-grey radius-big"
16
- />
17
- <div v-else>
9
+ <transition name="scaleTransition">
10
+ <EmptyState
11
+ v-if="!isLoading && posts.length < 1"
12
+ title="No Blog Posts Found"
13
+ description="Currently, there are no posts available in this blog. Please check back later."
14
+ class="pd-medium mn-thin bg-grey radius-big"
15
+ />
16
+ <div :class="$attrs.class" v-else>
18
17
 
19
- <CardBlogpost
20
- v-for="blogpost in posts"
21
- :key="blogpost._id"
22
- :blogpost="blogpost"
23
- :user="user"
24
- class="mn-medium"
25
- />
26
-
27
- <transition
28
- name="scaleTransition"
18
+ <CardBlogpost
19
+ v-for="blogpost in posts"
20
+ :key="blogpost._id"
21
+ :blogpost="blogpost"
22
+ :user="user"
23
+ class="mn-medium"
24
+ />
25
+
26
+ <transition
27
+ name="scaleTransition"
28
+ >
29
+ <button
30
+ v-if="hasMorePosts && posts.length > 0"
31
+ @click="loadMorePosts"
32
+ class="w-100 bg-main button"
29
33
  >
30
- <button
31
- v-if="hasMorePosts && posts.length > 0"
32
- @click="loadMorePosts"
33
- class="w-100 bg-main button"
34
- >
35
- Load more
36
- </button>
37
- </transition>
38
- </div>
39
- </transition>
40
-
41
- </section>
34
+ Load more
35
+ </button>
36
+ </transition>
37
+ </div>
38
+ </transition>
42
39
  </template>
43
40
 
44
41
  <script setup>
@@ -56,6 +53,14 @@
56
53
  type: String,
57
54
  default: null
58
55
  },
56
+ limit: {
57
+ type: Number,
58
+ default: 7
59
+ },
60
+ skip: {
61
+ type: Number,
62
+ default: 0
63
+ },
59
64
  owner: {
60
65
  type: String,
61
66
  default: null
@@ -82,8 +87,8 @@
82
87
  const hasMorePosts = ref(true);
83
88
  let isLoading = ref(true);
84
89
 
85
- let skip = ref(0);
86
- let limit = ref(7);
90
+ let skip = ref(props.skip);
91
+ let limit = ref(props.limit);
87
92
 
88
93
  const loadMorePosts = async () => {
89
94
  if (hasMorePosts.value) {
@@ -1,55 +1,23 @@
1
1
  <template>
2
2
  <section class="community-feed">
3
3
  <h2 class="w-m-75r mn-auto pd-t-big pd-b-big t-center">Discover the Vibrant Community</h2>
4
- <div class="grid-container">
5
- <CardBlogpost v-for="(blogpost, index) in posts"
6
- :blogpost="blogpost"
7
- :owner="auth.state.user._id"
8
- :key="index"
9
- :class="gridClass(index)"
10
- />
11
- </div>
4
+
5
+ <Feed
6
+ :skip="0"
7
+ :limit="3"
8
+ :user="auth.state.user._id"
9
+ :period="'year'"
10
+ class="cols-2 gap-thin"
11
+ />
12
12
  </section>
13
13
  </template>
14
14
 
15
15
  <script setup="props">
16
16
  import { ref, onMounted } from 'vue'
17
- import CardBlogpost from '@pf/src/modules/community/components/blocks/CardBlogpost.vue'
18
-
17
+ import Feed from '@pf/src/modules/community/components/sections/Feed.vue';
19
18
  // Import state
20
19
  import * as blog from '@pf/src/modules/community/store/blogposts.js';
21
20
  import * as auth from '@pf/src/modules/auth/store/auth'
22
-
23
- const posts = ref([]);
24
-
25
- const loadPosts = async () => {
26
- const data = await blog.read({skip: 0, limit: 7, period: 'year'});
27
- console.log(data)
28
- posts.value = data;
29
- };
30
-
31
- await loadPosts()
32
-
33
-
34
- const gridClass = (index) => {
35
- switch(index) {
36
- case 0:
37
- return 'grid-item-2x2';
38
- case 1:
39
- return 'grid-item-2x1';
40
- case 2:
41
- return 'grid-item-1x1';
42
- case 3:
43
- case 4:
44
- return 'grid-item-1x1';
45
- case 6:
46
- return 'grid-item-2x1';
47
- default:
48
- return '';
49
- }
50
- };
51
-
52
-
53
21
  </script>
54
22
 
55
23
  <style scoped>
@@ -63,21 +31,6 @@
63
31
  grid-gap: 20px;
64
32
  }
65
33
 
66
- .grid-item-2x2 {
67
- grid-row: span 2;
68
- grid-column: span 2;
69
- }
70
-
71
- .grid-item-2x1 {
72
- grid-row: span 1;
73
- grid-column: span 2;
74
- }
75
-
76
- .grid-item-1x1 {
77
- grid-row: span 1;
78
- grid-column: span 1;
79
- }
80
-
81
34
 
82
35
  </style>
83
36
 
@@ -20,10 +20,8 @@
20
20
  :membersPhotos="event.participantsPhotos"
21
21
  :type="type"
22
22
  :dateFormatted="daysUntilEvent"
23
-
24
23
  />
25
24
 
26
-
27
25
  <div
28
26
  v-if="event.cover && type !== 'short'"
29
27
  class="o-hidden pos-relative bg-grey mn-small w-100"
@@ -1,275 +1,65 @@
1
1
  const ObjectId = require('mongoose').Types.ObjectId;
2
+ // Query Processor
3
+ const queryProcessor = require('./utils/queryProcessor');
4
+ const queryProcessorGlobals = require('@pf/src/modules/globals/controllers/utils/queryProcessor');
5
+ // Utils
6
+ const createFriendlyURL = require('@pf/src/modules/globals/utils/seo-friendly-url');
2
7
 
3
8
  const middlewareFactory = (db) => {
4
- const Ticket = db.ticket; // замена Membership на Ticket
9
+ const Ticket = db.ticket;
5
10
  const Event = db.event;
6
11
  const Membership = db.membership;
7
12
 
8
13
  const read = async (req, res) => {
9
14
 
10
- console.log(req.query)
11
-
12
- const sortParam = req.query.sortParam || 'date.start';
13
- const sortOrder = req.query.sortOrder || 'desc';
14
-
15
- const sort = {
16
- [sortParam]: sortOrder === 'desc' ? -1 : 1,
17
- '_id': 1,
18
- };
19
-
20
- const options = {
21
- skip: parseInt(req.query.skip) || 0,
22
- limit: parseInt(req.query.limit) || 20
23
- };
24
-
25
- const status = req.query.status;
26
-
27
- // Initialize the current date once
28
- const now = new Date();
29
-
30
- // For handling 'status'
31
- const todayStart = new Date(now.getTime()); // getTime returns the number of milliseconds since Unix epoch
32
- todayStart.setHours(0, 0, 0, 0);
33
- const todayEnd = new Date(now.getTime());
34
- todayEnd.setHours(23, 59, 59, 999);
35
- let dateConditions = [];
36
-
37
- if (req.query.date) {
38
- const dateString = req.query.date.toString(); // Just to ensure it's a string
39
- const day = parseInt(dateString.substring(0, 2), 10);
40
- const month = parseInt(dateString.substring(2, 4), 10) - 1; // months are 0-based in JavaScript
41
- const year = parseInt(dateString.substring(4, 8), 10);
42
-
43
- const customDate = new Date(year, month, day);
44
- customDate.setHours(0, 0, 0, 0); // Set the start of the day
45
-
46
- const customDateEnd = new Date(year, month, day);
47
- customDateEnd.setHours(23, 59, 59, 999); // Set the end of the day
48
-
49
- dateConditions.push({ "date.start": { $gte: customDate, $lte: customDateEnd } });
50
- }
51
-
52
- // Handling period query parameter
53
- if (req.query.period) {
54
- let startDate = new Date(now.getTime()); // Make a copy
55
- let endDate = new Date(now.getTime()); // New end date variable
56
-
57
- switch (req.query.period) {
58
- case 'today':
59
- startDate.setHours(0, 0, 0, 0);
60
- endDate.setHours(23, 59, 59, 999);
61
- break;
62
- case 'week':
63
- endDate.setDate(now.getDate() + 7);
64
- break;
65
- case 'month':
66
- endDate.setDate(now.getDate() + 30); // Or endDate.setMonth(now.getMonth() + 1); based on your requirement
67
- break;
68
- case 'year':
69
- endDate.setFullYear(now.getFullYear() + 1);
70
- break;
71
- default:
72
- break;
73
- }
74
- dateConditions.push({ "date.start": { $gte: startDate, $lte: endDate } });
75
- }
76
-
77
- console.log(dateConditions)
78
-
79
- // Handling custom period range from frontend
80
- if (req.query.periodStart && req.query.periodEnd) {
81
- const periodStart = new Date(req.query.periodStart);
82
- const periodEnd = new Date(req.query.periodEnd);
83
- dateConditions.push({ "date.start": { $gte: periodStart, $lte: periodEnd } });
84
- }
85
-
86
- // Handling 'status'
87
- if (req.query.status) {
88
- const status = req.query.status;
89
- switch (status) {
90
- case 'finished':
91
- dateConditions.push({ "date.start": { $lt: now } });
92
- break;
93
- case 'today':
94
- dateConditions.push({ "date.start": { $gte: todayStart, $lte: todayEnd } });
95
- break;
96
- case 'live':
97
- dateConditions.push({ "date.start": { $lte: now } });
98
- dateConditions.push({ "date.end": { $gte: now } });
99
- break;
100
- case 'planned':
101
- dateConditions.push({ "date.start": { $gt: now } });
102
- break;
103
- default:
104
- break;
105
- }
106
- }
107
-
108
- const matchConditions = [
109
- ...(dateConditions.length > 0 ? [{ $and: dateConditions }] : []),
110
- ...(req.query.url ? [{ url: req.query.url }] : []),
111
- ...(req.query.owner ? [{ "owner.target": new ObjectId(req.query.owner) }] : []),
112
- ...(req.query.creator ? [{ "creator.target": new ObjectId(req.query.creator) }] : []),
113
- ];
114
-
115
- const matchStage = matchConditions.length > 0 ? { $match: { $and: matchConditions } } : null;
116
-
117
- console.log(dateConditions)
118
-
119
-
120
- const stages = [
121
- ...(matchStage != null ? [matchStage] : []),
122
- {
123
- $lookup: {
124
- from: "tickets", // замена memberships на tickets
125
- localField: "_id",
126
- foreignField: "target",
127
- as: "tickets",
128
- pipeline: [{
129
- $lookup: {
130
- from: "users",
131
- localField: "user",
132
- foreignField: "_id",
133
- as: "user"
134
- }
135
- },{
136
- $unwind: { path: "$user", preserveNullAndEmptyArrays: true }
137
- }]
138
- }
139
- },
140
- {
141
- $addFields: {
142
- participantsPhotos: {
143
- $map: {
144
- input: "$tickets",
145
- as: "ticket",
146
- in: "$$ticket.user.profile.photo"
147
- }
148
- }
149
- }
150
- },
151
- {
152
- $addFields: {
153
- numberOfTickets: { $size: '$tickets' }
154
- }
155
- },
156
- {
157
- $addFields: {
158
- hasTicket: {
159
- $cond: {
160
- if: req.query.user,
161
- then: {
162
- $in: [ new db.mongoose.Types.ObjectId(req.query.user), "$tickets.user._id" ]
163
- },
164
- else: "$$REMOVE"
165
- }
166
- }
167
- }
168
- },
169
- {
170
- $lookup: {
171
- from: "users",
172
- localField: "creator.target",
173
- foreignField: "_id",
174
- as: "creatorUser"
175
- }
176
- },
177
- {
178
- $lookup: {
179
- from: "organizations",
180
- localField: "creator.target",
181
- foreignField: "_id",
182
- as: "creatorOrganization"
183
- }
184
- },
185
- // Для owner
186
- {
187
- $lookup: {
188
- from: "users",
189
- localField: "owner.target",
190
- foreignField: "_id",
191
- as: "ownerUser"
192
- }
193
- },
194
- {
195
- $lookup: {
196
- from: "organizations",
197
- localField: "owner.target",
198
- foreignField: "_id",
199
- as: "ownerOrganization"
200
- }
201
- },
202
- {
203
- $addFields: {
204
- "creator.target": {
205
- $cond: [
206
- { $eq: ["$creator.type", "user"] },
207
- { $arrayElemAt: ["$creatorUser", 0] },
208
- { $arrayElemAt: ["$creatorOrganization", 0] }
209
- ]
210
- },
211
- "owner.target": {
212
- $cond: [
213
- { $eq: ["$owner.type", "user"] },
214
- { $arrayElemAt: ["$ownerUser", 0] },
215
- { $arrayElemAt: ["$ownerOrganization", 0] }
216
- ]
217
- }
218
- }
219
- },
220
- {
221
- $project: {
222
- _id: 1,
223
- url: 1,
224
- cover: 1,
225
- name: 1,
226
- status: 1,
227
- description: 1,
228
- content: 1,
229
- owner: 1,
230
- creator: 1,
231
- tags: 1,
232
- date: 1,
233
- numberOfTickets: 1,
234
- participantsPhotos: 1,
235
- hasTicket: 1,
236
- tickets: 1,
237
- createdAt: 1
238
- }
239
- },
15
+ let stages = [];
16
+
17
+ stages = [
18
+ ...queryProcessorGlobals.getBasicOptions(
19
+ req.query
20
+ ),
21
+ ...queryProcessorGlobals.getDateConditions(
22
+ req.query.date
23
+ ),
24
+ ...queryProcessorGlobals.getPeriodConditions(
25
+ req.query.period,
26
+ req.query.periodStart,
27
+ req.query.periodEnd
28
+ ),
29
+ ...queryProcessorGlobals.getStatusConditions(
30
+ req.query.status
31
+ ),
32
+ // Tickets and Participants
33
+ queryProcessor.getTicketsLookupStage(),
34
+ queryProcessor.getParticipantsPhotosStage(),
35
+ queryProcessor.getNumberOfTicketsStage(),
36
+
37
+ ...queryProcessor.getHasTicketStage(
38
+ req.query.user
39
+ ),
40
+ ...queryProcessor.getParticipantStages(
41
+ req.query.participant
42
+ ),
43
+ // For creator
44
+ queryProcessorGlobals.getCreatorUserLookupStage(),
45
+ queryProcessorGlobals.getCreatorOrganizationLookupStage(),
46
+ // For owner
47
+ queryProcessorGlobals.getOwnerUserLookupStage(),
48
+ queryProcessorGlobals.getOwnerOrganizationLookupStage(),
49
+ queryProcessorGlobals.getAddFieldsCreatorOwnerStage(),
50
+ // Get object
51
+ queryProcessor.getProjectStage(),
52
+ // Pagination
53
+ ...queryProcessorGlobals.getSortingOptions(
54
+ req.query
55
+ ),
56
+ ...queryProcessorGlobals.getPaginationOptions(
57
+ req.query
58
+ )
240
59
  ];
241
60
 
242
- const participantId = req.query.participant ? new db.mongoose.Types.ObjectId(req.query.participant) : null;
243
-
244
- if (participantId) {
245
- stages.push({
246
- $addFields: {
247
- "participantTickets": {
248
- $filter: {
249
- input: "$tickets",
250
- as: "ticket",
251
- cond: { $eq: ["$$ticket.user._id", participantId] }
252
- }
253
- }
254
- }
255
- });
256
-
257
- stages.push({
258
- $match: {
259
- "participantTickets.0": { $exists: true }
260
- }
261
- });
262
- }
263
-
264
- stages.push({ $sort: sort });
265
- stages.push({ $skip: options.skip });
266
- stages.push({ $limit: options.limit });
267
-
268
-
269
61
  try {
270
-
271
- const events = await Event.aggregate(stages);
272
- console.log(events)
62
+ const events = await Event.aggregate(stages).exec();
273
63
  res.status(200).send(events);
274
64
  } catch (err) {
275
65
  console.log(err);
@@ -279,19 +69,19 @@ const middlewareFactory = (db) => {
279
69
 
280
70
 
281
71
  const create = async (req, res) => {
282
- try {
72
+ if (req.body._id) delete req.body._id;
283
73
 
284
- delete req.body._id;
285
- req.body.url = req.body.name.toLowerCase().replace(/ /g, '-').replace(/[^\w-]+/g, '');
74
+ try {
75
+ req.body.url = createFriendlyURL(req.body.name);
286
76
 
287
77
  const event = await Event.create(req.body);
288
78
 
289
79
  if (!event) {
290
80
  return res.status(404).send({ message: "Event is not created." });
291
81
  }
82
+
292
83
  res.status(200).send(event);
293
84
  } catch (err) {
294
- console.log(err)
295
85
  return res.status(500).send({ message: err.message });
296
86
  }
297
87
  };
@@ -0,0 +1,118 @@
1
+ const ObjectId = require('mongoose').Types.ObjectId;
2
+
3
+ function getTicketsLookupStage() {
4
+ return {
5
+ $lookup: {
6
+ from: "tickets",
7
+ localField: "_id",
8
+ foreignField: "target",
9
+ as: "tickets",
10
+ pipeline: [{
11
+ $lookup: {
12
+ from: "users",
13
+ localField: "user",
14
+ foreignField: "_id",
15
+ as: "user"
16
+ }
17
+ },{
18
+ $unwind: { path: "$user", preserveNullAndEmptyArrays: true }
19
+ }]
20
+ }
21
+ };
22
+ }
23
+
24
+ function getParticipantsPhotosStage() {
25
+ return {
26
+ $addFields: {
27
+ participantsPhotos: {
28
+ $map: {
29
+ input: "$tickets",
30
+ as: "ticket",
31
+ in: "$$ticket.user.profile.photo"
32
+ }
33
+ }
34
+ }
35
+ };
36
+ }
37
+
38
+ function getNumberOfTicketsStage() {
39
+ return {
40
+ $addFields: {
41
+ numberOfTickets: { $size: '$tickets' }
42
+ }
43
+ };
44
+ }
45
+
46
+
47
+ function getHasTicketStage(user) {
48
+ if (user) {
49
+ return [{
50
+ $addFields: {
51
+ hasTicket: {
52
+ $in: [ new ObjectId(user), "$tickets.user._id" ]
53
+ }
54
+ }
55
+ }];
56
+ } else {
57
+ return [];
58
+ }
59
+ }
60
+
61
+ function getProjectStage() {
62
+ return {
63
+ $project: {
64
+ _id: 1,
65
+ url: 1,
66
+ cover: 1,
67
+ name: 1,
68
+ status: 1,
69
+ description: 1,
70
+ content: 1,
71
+ owner: 1,
72
+ creator: 1,
73
+ tags: 1,
74
+ date: 1,
75
+ numberOfTickets: 1,
76
+ participantsPhotos: 1,
77
+ hasTicket: 1,
78
+ tickets: 1,
79
+ createdAt: 1
80
+ }
81
+ };
82
+ }
83
+
84
+ function getParticipantStages(participantQuery) {
85
+ const participantId = participantQuery ? new ObjectId(participantQuery) : null;
86
+ let stages = [];
87
+
88
+ if (participantId) {
89
+ stages.push({
90
+ $addFields: {
91
+ "participantTickets": {
92
+ $filter: {
93
+ input: "$tickets",
94
+ as: "ticket",
95
+ cond: { $eq: ["$$ticket.user._id", participantId] }
96
+ }
97
+ }
98
+ }
99
+ });
100
+
101
+ stages.push({
102
+ $match: {
103
+ "participantTickets.0": { $exists: true }
104
+ }
105
+ });
106
+ }
107
+
108
+ return stages;
109
+ }
110
+
111
+ module.exports = {
112
+ getTicketsLookupStage,
113
+ getParticipantsPhotosStage,
114
+ getNumberOfTicketsStage,
115
+ getHasTicketStage,
116
+ getProjectStage,
117
+ getParticipantStages
118
+ };