UNPKG

6.48 kBJavaScriptView Raw
1var _ = require('@sailshq/lodash');
2var async = require('async');
3var moment = require('moment');
4
5module.exports = {
6 name: 'apostrophe-event',
7 alias: 'events',
8 label: 'Event',
9 extend: 'apostrophe-pieces',
10
11 moogBundle: {
12 modules: ['apostrophe-events-pages', 'apostrophe-events-widgets'],
13 directory: 'lib/modules'
14 },
15
16 beforeConstruct: function(self, options) {
17 options.sort = {
18 startDate: 1,
19 startTime: 1
20 };
21
22 options.addFields = [
23 {
24 name: 'startDate',
25 label: 'Date',
26 help: 'The date, or starting date, of the event',
27 type: 'date',
28 required: true
29 },
30 {
31 name: 'allDay',
32 label: 'Is this an all day event?',
33 type: 'boolean',
34 choices: [
35 {
36 label: 'Yes',
37 value: true
38 },
39 {
40 label: 'No',
41 value: false,
42 showFields: ['startTime', 'endTime']
43 }
44 ],
45 def: false
46 },
47 {
48 name: 'startTime',
49 label: 'Start Time',
50 type: 'time',
51 def: '09:00:00',
52 required: true
53 },
54 {
55 name: 'endTime',
56 label: 'End Time',
57 type: 'time',
58 def: '17:30:00',
59 required: true
60 },
61 {
62 name: 'dateType',
63 label: 'What type of event is this?',
64 help: 'Select if the event is on a single day, consecutive days, or repeats.',
65 type: 'select',
66 choices: [
67 {
68 label: 'Single Day',
69 value: 'single'
70 },
71 {
72 label: 'Consecutive Days',
73 value: 'consecutive',
74 showFields: ['endDate']
75 },
76 {
77 label: 'Recurring',
78 value: 'repeat',
79 showFields: ['repeatInterval', 'repeatCount']
80 }
81 ],
82 def: 'single'
83 },
84 {
85 name: 'endDate',
86 label: 'End Date',
87 type: 'date'
88 },
89 {
90 name: 'repeatInterval',
91 label: 'How often does the event repeat?',
92 type: 'select',
93 choices: [
94 {
95 label: 'Every week',
96 value: 'weeks'
97 },
98 {
99 label: 'Every month',
100 value: 'months'
101 }
102 ]
103 },
104 {
105 name: 'repeatCount',
106 label: 'How many times does it repeat?',
107 type: 'integer',
108 def: 1
109 }
110 ].concat(options.addFields || []);
111
112 options.arrangeFields = options.arrangeFields || [
113 {
114 name: 'basic',
115 label: 'Basics',
116 fields: ['title', 'slug', 'startDate', 'allDay', 'startTime', 'endTime']
117 },
118 {
119 name: 'advanced',
120 label: 'Advanced',
121 fields: ['dateType', 'endDate', 'repeatInterval', 'repeatCount']
122 },
123 {
124 name: 'meta',
125 label: 'Meta',
126 fields: ['tags', 'published']
127 }
128 ];
129
130 options.addColumns = [
131 {
132 name: 'startDate',
133 label: 'Start Date'
134 }
135 ].concat(options.addColumns || []);
136
137 options.addSorts = [
138 {
139 name: 'startDate',
140 label: 'By Start Date',
141 sort: { startDate: -1 }
142 }
143 ].concat(options.addSorts || []);
144
145 options.addFilters = [
146 {
147 name: 'upcoming',
148 choices: [
149 {
150 value: true,
151 label: 'Upcoming'
152 },
153 {
154 value: false,
155 label: 'Past'
156 },
157 {
158 value: null,
159 label: 'Both'
160 }
161 ],
162 def: true
163 }
164 ].concat(options.addFilters || []);
165 },
166
167 construct: function(self, options) {
168
169 // limit the results of autocomplete for joins
170 // so they only include upcoming events
171 self.extendAutocompleteCursor = function(cursor) {
172 return cursor.upcoming(true);
173 };
174
175 self.beforeSave = function(req, piece, options, callback) {
176 self.denormalizeDatesAndTimes(piece);
177 return callback(null);
178 };
179
180 self.afterSave = function(req, piece, options, callback) {
181 if (piece._workflowPropagating) {
182 // Workflow is replicating this but also its existing
183 // scheduled repetitions, don't re-replicate them and cause problems
184 return callback(null);
185 }
186
187 if (piece.dateType !== 'repeat') {
188 return callback(null);
189 }
190
191 self
192 .find(req, { parentId: piece._id, trash: false }, { _id: 1 })
193 .toArray(function(err, docs) {
194 if (err) {
195 return callback(err);
196 }
197 if (!docs.length) {
198 // Replicate event only if it has no replicated events already
199 return self.repeatEvent(req, piece, callback);
200 }
201 callback(null);
202 });
203 };
204
205 self.denormalizeDatesAndTimes = function(piece) {
206 // Parse our dates and times
207 var startTime = piece.startTime;
208 var startDate = piece.startDate;
209 var endTime = piece.endTime;
210 var endDate;
211
212 if (piece.dateType === 'consecutive') {
213 endDate = piece.endDate;
214 } else {
215 piece.endDate = piece.startDate;
216 endDate = piece.startDate;
217 }
218
219 if (piece.allDay) {
220 startTime = '00:00:00';
221 endTime = '23:59:59';
222 }
223
224 if (piece.dateType === 'repeat') {
225 piece.hasClones = true;
226 }
227
228 piece.start = new Date(startDate + ' ' + startTime);
229 piece.end = new Date(endDate + ' ' + endTime);
230 };
231
232 self.repeatEvent = function(req, piece, finalCallback) {
233 var i;
234 var repeat = parseInt(piece.repeatCount) + 1;
235 var multiplier = piece.repeatInterval;
236 var addDates = [];
237
238 for (i = 1; i < repeat; i++) {
239 addDates.push(moment(piece.startDate).add(i, multiplier).format('YYYY-MM-DD'));
240 }
241
242 return async.eachLimit(addDates, 5, function(date, callback) {
243 var eventCopy = _.cloneDeep(piece);
244 eventCopy._id = self.apos.utils.generateId();
245 if (piece.workflowGuid) {
246 eventCopy.workflowGuid = self.apos.utils.generateId();
247 }
248 eventCopy.parentId = piece._id;
249 eventCopy.isClone = true;
250 eventCopy.startDate = date;
251 eventCopy.endDate = date;
252 eventCopy.slug = eventCopy.slug + '-' + date;
253 eventCopy.dateType = 'single';
254 self.denormalizeDatesAndTimes(eventCopy);
255 return self.insert(req, eventCopy, callback);
256 }, finalCallback);
257 };
258 }
259};