@things-factory/calendar 10.1.202 → 10.1.205
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-client/pages/calendar/calendar-list-page.d.ts +1 -9
- package/dist-client/pages/calendar/calendar-list-page.js +2 -27
- package/dist-client/pages/calendar/calendar-list-page.js.map +1 -1
- package/dist-client/pages/event/event-list-page.d.ts +5 -28
- package/dist-client/pages/event/event-list-page.js +65 -177
- package/dist-client/pages/event/event-list-page.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/route.js +0 -3
- package/dist-client/route.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/index.d.ts +1 -0
- package/dist-server/index.js +5 -0
- package/dist-server/index.js.map +1 -1
- package/dist-server/role-tasks.d.ts +2 -0
- package/dist-server/role-tasks.js +16 -0
- package/dist-server/role-tasks.js.map +1 -0
- package/dist-server/service/attendee/attendee-query.d.ts +7 -4
- package/dist-server/service/attendee/attendee-query.js +34 -25
- package/dist-server/service/attendee/attendee-query.js.map +1 -1
- package/dist-server/service/attendee/attendee-service.d.ts +41 -0
- package/dist-server/service/attendee/attendee-service.js +90 -0
- package/dist-server/service/attendee/attendee-service.js.map +1 -0
- package/dist-server/service/attendee/attendee-type.d.ts +3 -15
- package/dist-server/service/attendee/attendee-type.js +12 -53
- package/dist-server/service/attendee/attendee-type.js.map +1 -1
- package/dist-server/service/attendee/attendee.d.ts +24 -7
- package/dist-server/service/attendee/attendee.js +99 -23
- package/dist-server/service/attendee/attendee.js.map +1 -1
- package/dist-server/service/attendee/index.d.ts +1 -2
- package/dist-server/service/attendee/index.js +1 -2
- package/dist-server/service/attendee/index.js.map +1 -1
- package/dist-server/service/calendar/calendar-mutation.d.ts +1 -3
- package/dist-server/service/calendar/calendar-mutation.js +21 -94
- package/dist-server/service/calendar/calendar-mutation.js.map +1 -1
- package/dist-server/service/calendar/calendar-query.d.ts +1 -1
- package/dist-server/service/calendar/calendar-query.js +15 -17
- package/dist-server/service/calendar/calendar-query.js.map +1 -1
- package/dist-server/service/calendar/calendar-service.d.ts +10 -0
- package/dist-server/service/calendar/calendar-service.js +58 -0
- package/dist-server/service/calendar/calendar-service.js.map +1 -0
- package/dist-server/service/calendar/calendar-type.d.ts +1 -4
- package/dist-server/service/calendar/calendar-type.js +13 -25
- package/dist-server/service/calendar/calendar-type.js.map +1 -1
- package/dist-server/service/calendar/calendar.d.ts +7 -8
- package/dist-server/service/calendar/calendar.js +23 -33
- package/dist-server/service/calendar/calendar.js.map +1 -1
- package/dist-server/service/event/event-mutation.d.ts +6 -4
- package/dist-server/service/event/event-mutation.js +60 -83
- package/dist-server/service/event/event-mutation.js.map +1 -1
- package/dist-server/service/event/event-query.d.ts +11 -1
- package/dist-server/service/event/event-query.js +106 -13
- package/dist-server/service/event/event-query.js.map +1 -1
- package/dist-server/service/event/event-rules.d.ts +10 -0
- package/dist-server/service/event/event-rules.js +38 -0
- package/dist-server/service/event/event-rules.js.map +1 -0
- package/dist-server/service/event/event-service.d.ts +42 -0
- package/dist-server/service/event/event-service.js +159 -0
- package/dist-server/service/event/event-service.js.map +1 -0
- package/dist-server/service/event/event-type.d.ts +10 -11
- package/dist-server/service/event/event-type.js +32 -36
- package/dist-server/service/event/event-type.js.map +1 -1
- package/dist-server/service/event/event.d.ts +25 -11
- package/dist-server/service/event/event.js +89 -36
- package/dist-server/service/event/event.js.map +1 -1
- package/dist-server/service/event-series/event-series-mutation.d.ts +11 -0
- package/dist-server/service/event-series/event-series-mutation.js +100 -0
- package/dist-server/service/event-series/event-series-mutation.js.map +1 -0
- package/dist-server/service/event-series/event-series-query.d.ts +16 -0
- package/dist-server/service/event-series/event-series-query.js +109 -0
- package/dist-server/service/event-series/event-series-query.js.map +1 -0
- package/dist-server/service/event-series/event-series-service.d.ts +40 -0
- package/dist-server/service/event-series/event-series-service.js +253 -0
- package/dist-server/service/event-series/event-series-service.js.map +1 -0
- package/dist-server/service/event-series/event-series-type.d.ts +41 -0
- package/dist-server/service/event-series/event-series-type.js +155 -0
- package/dist-server/service/event-series/event-series-type.js.map +1 -0
- package/dist-server/service/event-series/event-series.d.ts +32 -0
- package/dist-server/service/event-series/event-series.js +134 -0
- package/dist-server/service/event-series/event-series.js.map +1 -0
- package/dist-server/service/event-series/index.d.ts +6 -0
- package/dist-server/service/event-series/index.js +10 -0
- package/dist-server/service/event-series/index.js.map +1 -0
- package/dist-server/service/event-series/recurrence.d.ts +19 -0
- package/dist-server/service/event-series/recurrence.js +95 -0
- package/dist-server/service/event-series/recurrence.js.map +1 -0
- package/dist-server/service/index.d.ts +15 -4
- package/dist-server/service/index.js +29 -11
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -5
- package/tests/open-doors.test.ts +18 -21
- package/things-factory.config.js +0 -4
- package/translations/en.json +44 -1
- package/translations/es.json +44 -1
- package/translations/ja.json +44 -1
- package/translations/ko.json +44 -1
- package/translations/ms.json +44 -1
- package/translations/zh.json +44 -1
- package/concept.md +0 -31
- package/dist-client/pages/attendee/attendee-importer.d.ts +0 -23
- package/dist-client/pages/attendee/attendee-importer.js +0 -93
- package/dist-client/pages/attendee/attendee-importer.js.map +0 -1
- package/dist-client/pages/attendee/attendee-list-page.d.ts +0 -56
- package/dist-client/pages/attendee/attendee-list-page.js +0 -263
- package/dist-client/pages/attendee/attendee-list-page.js.map +0 -1
- package/dist-client/pages/calendar/calendar-importer.d.ts +0 -23
- package/dist-client/pages/calendar/calendar-importer.js +0 -93
- package/dist-client/pages/calendar/calendar-importer.js.map +0 -1
- package/dist-client/pages/event/event-importer.d.ts +0 -23
- package/dist-client/pages/event/event-importer.js +0 -93
- package/dist-client/pages/event/event-importer.js.map +0 -1
- package/dist-server/service/attendee/attendee-mutation.d.ts +0 -10
- package/dist-server/service/attendee/attendee-mutation.js +0 -140
- package/dist-server/service/attendee/attendee-mutation.js.map +0 -1
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EventSeriesQuery = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const type_graphql_1 = require("type-graphql");
|
|
6
|
+
const auth_base_1 = require("@things-factory/auth-base");
|
|
7
|
+
const shell_1 = require("@things-factory/shell");
|
|
8
|
+
const attendee_1 = require("../attendee/attendee");
|
|
9
|
+
const calendar_1 = require("../calendar/calendar");
|
|
10
|
+
const event_series_1 = require("./event-series");
|
|
11
|
+
const event_series_type_1 = require("./event-series-type");
|
|
12
|
+
let EventSeriesQuery = class EventSeriesQuery {
|
|
13
|
+
eventSeries(id, context) {
|
|
14
|
+
return (0, shell_1.getRepository)(event_series_1.EventSeries).findOne({ where: { domain: { id: context.state.domain.id }, id } });
|
|
15
|
+
}
|
|
16
|
+
async eventSeriesList(params, context) {
|
|
17
|
+
const queryBuilder = (0, shell_1.getQueryBuilderFromListParams)({
|
|
18
|
+
domain: context.state.domain,
|
|
19
|
+
params,
|
|
20
|
+
repository: (0, shell_1.getRepository)(event_series_1.EventSeries),
|
|
21
|
+
searchables: ['name', 'description', 'location']
|
|
22
|
+
});
|
|
23
|
+
const [items, total] = await queryBuilder.getManyAndCount();
|
|
24
|
+
return { items, total };
|
|
25
|
+
}
|
|
26
|
+
attendees(series) {
|
|
27
|
+
return (0, shell_1.getRepository)(attendee_1.Attendee).find({ where: { series: { id: series.id } }, order: { createdAt: 'ASC' } });
|
|
28
|
+
}
|
|
29
|
+
calendar(series) {
|
|
30
|
+
return series.calendarId ? (0, shell_1.getRepository)(calendar_1.Calendar).findOneBy({ id: series.calendarId }) : null;
|
|
31
|
+
}
|
|
32
|
+
organizer(series) {
|
|
33
|
+
return series.organizerId ? (0, shell_1.getRepository)(auth_base_1.User).findOneBy({ id: series.organizerId }) : null;
|
|
34
|
+
}
|
|
35
|
+
domain(series) {
|
|
36
|
+
return (0, shell_1.getRepository)(shell_1.Domain).findOneBy({ id: series.domainId });
|
|
37
|
+
}
|
|
38
|
+
updater(series) {
|
|
39
|
+
return series.updaterId ? (0, shell_1.getRepository)(auth_base_1.User).findOneBy({ id: series.updaterId }) : null;
|
|
40
|
+
}
|
|
41
|
+
creator(series) {
|
|
42
|
+
return series.creatorId ? (0, shell_1.getRepository)(auth_base_1.User).findOneBy({ id: series.creatorId }) : null;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
exports.EventSeriesQuery = EventSeriesQuery;
|
|
46
|
+
tslib_1.__decorate([
|
|
47
|
+
(0, type_graphql_1.Directive)('@privilege(category: "calendar", privilege: "query", domainOwnerGranted: true)'),
|
|
48
|
+
(0, type_graphql_1.Query)(returns => event_series_1.EventSeries, { nullable: true, description: 'To fetch a series' }),
|
|
49
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('id')),
|
|
50
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
51
|
+
tslib_1.__metadata("design:type", Function),
|
|
52
|
+
tslib_1.__metadata("design:paramtypes", [String, Object]),
|
|
53
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
54
|
+
], EventSeriesQuery.prototype, "eventSeries", null);
|
|
55
|
+
tslib_1.__decorate([
|
|
56
|
+
(0, type_graphql_1.Directive)('@privilege(category: "calendar", privilege: "query", domainOwnerGranted: true)'),
|
|
57
|
+
(0, type_graphql_1.Query)(returns => event_series_type_1.EventSeriesList, { description: 'To fetch a page of series' }),
|
|
58
|
+
tslib_1.__param(0, (0, type_graphql_1.Args)(type => shell_1.ListParam)),
|
|
59
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
60
|
+
tslib_1.__metadata("design:type", Function),
|
|
61
|
+
tslib_1.__metadata("design:paramtypes", [shell_1.ListParam, Object]),
|
|
62
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
63
|
+
], EventSeriesQuery.prototype, "eventSeriesList", null);
|
|
64
|
+
tslib_1.__decorate([
|
|
65
|
+
(0, type_graphql_1.FieldResolver)(type => [attendee_1.Attendee], { description: 'The people named on every occurrence' }),
|
|
66
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
67
|
+
tslib_1.__metadata("design:type", Function),
|
|
68
|
+
tslib_1.__metadata("design:paramtypes", [event_series_1.EventSeries]),
|
|
69
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
70
|
+
], EventSeriesQuery.prototype, "attendees", null);
|
|
71
|
+
tslib_1.__decorate([
|
|
72
|
+
(0, type_graphql_1.FieldResolver)(type => calendar_1.Calendar, { nullable: true }),
|
|
73
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
74
|
+
tslib_1.__metadata("design:type", Function),
|
|
75
|
+
tslib_1.__metadata("design:paramtypes", [event_series_1.EventSeries]),
|
|
76
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
77
|
+
], EventSeriesQuery.prototype, "calendar", null);
|
|
78
|
+
tslib_1.__decorate([
|
|
79
|
+
(0, type_graphql_1.FieldResolver)(type => auth_base_1.User, { nullable: true }),
|
|
80
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
81
|
+
tslib_1.__metadata("design:type", Function),
|
|
82
|
+
tslib_1.__metadata("design:paramtypes", [event_series_1.EventSeries]),
|
|
83
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
84
|
+
], EventSeriesQuery.prototype, "organizer", null);
|
|
85
|
+
tslib_1.__decorate([
|
|
86
|
+
(0, type_graphql_1.FieldResolver)(type => shell_1.Domain),
|
|
87
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
88
|
+
tslib_1.__metadata("design:type", Function),
|
|
89
|
+
tslib_1.__metadata("design:paramtypes", [event_series_1.EventSeries]),
|
|
90
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
91
|
+
], EventSeriesQuery.prototype, "domain", null);
|
|
92
|
+
tslib_1.__decorate([
|
|
93
|
+
(0, type_graphql_1.FieldResolver)(type => auth_base_1.User),
|
|
94
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
95
|
+
tslib_1.__metadata("design:type", Function),
|
|
96
|
+
tslib_1.__metadata("design:paramtypes", [event_series_1.EventSeries]),
|
|
97
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
98
|
+
], EventSeriesQuery.prototype, "updater", null);
|
|
99
|
+
tslib_1.__decorate([
|
|
100
|
+
(0, type_graphql_1.FieldResolver)(type => auth_base_1.User),
|
|
101
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
102
|
+
tslib_1.__metadata("design:type", Function),
|
|
103
|
+
tslib_1.__metadata("design:paramtypes", [event_series_1.EventSeries]),
|
|
104
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
105
|
+
], EventSeriesQuery.prototype, "creator", null);
|
|
106
|
+
exports.EventSeriesQuery = EventSeriesQuery = tslib_1.__decorate([
|
|
107
|
+
(0, type_graphql_1.Resolver)(event_series_1.EventSeries)
|
|
108
|
+
], EventSeriesQuery);
|
|
109
|
+
//# sourceMappingURL=event-series-query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-series-query.js","sourceRoot":"","sources":["../../../server/service/event-series/event-series-query.ts"],"names":[],"mappings":";;;;AAAA,+CAA8F;AAE9F,yDAAgD;AAChD,iDAAuG;AAEvG,mDAA+C;AAC/C,mDAA+C;AAC/C,iDAA4C;AAC5C,2DAAqD;AAG9C,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;IAG3B,WAAW,CAAY,EAAU,EAAS,OAAwB;QAChE,OAAO,IAAA,qBAAa,EAAC,0BAAW,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;IACvG,CAAC;IAIK,AAAN,KAAK,CAAC,eAAe,CAA0B,MAAiB,EAAS,OAAwB;QAC/F,MAAM,YAAY,GAAG,IAAA,qCAA6B,EAAC;YACjD,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM;YAC5B,MAAM;YACN,UAAU,EAAE,IAAA,qBAAa,EAAC,0BAAW,CAAC;YACtC,WAAW,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,UAAU,CAAC;SACjD,CAAC,CAAA;QACF,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,YAAY,CAAC,eAAe,EAAE,CAAA;QAC3D,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;IACzB,CAAC;IAGD,SAAS,CAAS,MAAmB;QACnC,OAAO,IAAA,qBAAa,EAAC,mBAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,CAAC,CAAA;IAC5G,CAAC;IAGD,QAAQ,CAAS,MAAmB;QAClC,OAAO,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,IAAA,qBAAa,EAAC,mBAAQ,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAChG,CAAC;IAGD,SAAS,CAAS,MAAmB;QACnC,OAAO,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,IAAA,qBAAa,EAAC,gBAAI,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAC9F,CAAC;IAGD,MAAM,CAAS,MAAmB;QAChC,OAAO,IAAA,qBAAa,EAAC,cAAM,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAA;IACjE,CAAC;IAGD,OAAO,CAAS,MAAmB;QACjC,OAAO,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAA,qBAAa,EAAC,gBAAI,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAC1F,CAAC;IAGD,OAAO,CAAS,MAAmB;QACjC,OAAO,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAA,qBAAa,EAAC,gBAAI,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAC1F,CAAC;CACF,CAAA;AAjDY,4CAAgB;AAG3B;IAFC,IAAA,wBAAS,EAAC,gFAAgF,CAAC;IAC3F,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,0BAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,mBAAmB,EAAE,CAAC;IACvE,mBAAA,IAAA,kBAAG,EAAC,IAAI,CAAC,CAAA;IAAc,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;mDAExC;AAIK;IAFL,IAAA,wBAAS,EAAC,gFAAgF,CAAC;IAC3F,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,mCAAe,EAAE,EAAE,WAAW,EAAE,2BAA2B,EAAE,CAAC;IACzD,mBAAA,IAAA,mBAAI,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAS,CAAC,CAAA;IAAqB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CAAjB,iBAAS;;uDAS/D;AAGD;IADC,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,mBAAQ,CAAC,EAAE,EAAE,WAAW,EAAE,sCAAsC,EAAE,CAAC;IAChF,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAS,0BAAW;;iDAEpC;AAGD;IADC,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,mBAAQ,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1C,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAS,0BAAW;;gDAEnC;AAGD;IADC,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACrC,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAS,0BAAW;;iDAEpC;AAGD;IADC,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,CAAC;IACtB,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAS,0BAAW;;8CAEjC;AAGD;IADC,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,CAAC;IACnB,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAS,0BAAW;;+CAElC;AAGD;IADC,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,CAAC;IACnB,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAS,0BAAW;;+CAElC;2BAhDU,gBAAgB;IAD5B,IAAA,uBAAQ,EAAC,0BAAW,CAAC;GACT,gBAAgB,CAiD5B","sourcesContent":["import { Arg, Args, Ctx, Directive, FieldResolver, Query, Resolver, Root } from 'type-graphql'\n\nimport { User } from '@things-factory/auth-base'\nimport { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'\n\nimport { Attendee } from '../attendee/attendee'\nimport { Calendar } from '../calendar/calendar'\nimport { EventSeries } from './event-series'\nimport { EventSeriesList } from './event-series-type'\n\n@Resolver(EventSeries)\nexport class EventSeriesQuery {\n @Directive('@privilege(category: \"calendar\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => EventSeries, { nullable: true, description: 'To fetch a series' })\n eventSeries(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<EventSeries> {\n return getRepository(EventSeries).findOne({ where: { domain: { id: context.state.domain.id }, id } })\n }\n\n @Directive('@privilege(category: \"calendar\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => EventSeriesList, { description: 'To fetch a page of series' })\n async eventSeriesList(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<EventSeriesList> {\n const queryBuilder = getQueryBuilderFromListParams({\n domain: context.state.domain,\n params,\n repository: getRepository(EventSeries),\n searchables: ['name', 'description', 'location']\n })\n const [items, total] = await queryBuilder.getManyAndCount()\n return { items, total }\n }\n\n @FieldResolver(type => [Attendee], { description: 'The people named on every occurrence' })\n attendees(@Root() series: EventSeries): Promise<Attendee[]> {\n return getRepository(Attendee).find({ where: { series: { id: series.id } }, order: { createdAt: 'ASC' } })\n }\n\n @FieldResolver(type => Calendar, { nullable: true })\n calendar(@Root() series: EventSeries): Promise<Calendar> {\n return series.calendarId ? getRepository(Calendar).findOneBy({ id: series.calendarId }) : null\n }\n\n @FieldResolver(type => User, { nullable: true })\n organizer(@Root() series: EventSeries): Promise<User> {\n return series.organizerId ? getRepository(User).findOneBy({ id: series.organizerId }) : null\n }\n\n @FieldResolver(type => Domain)\n domain(@Root() series: EventSeries): Promise<Domain> {\n return getRepository(Domain).findOneBy({ id: series.domainId })\n }\n\n @FieldResolver(type => User)\n updater(@Root() series: EventSeries): Promise<User> {\n return series.updaterId ? getRepository(User).findOneBy({ id: series.updaterId }) : null\n }\n\n @FieldResolver(type => User)\n creator(@Root() series: EventSeries): Promise<User> {\n return series.creatorId ? getRepository(User).findOneBy({ id: series.creatorId }) : null\n }\n}\n"]}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { EntityManager } from 'typeorm';
|
|
2
|
+
import { User } from '@things-factory/auth-base';
|
|
3
|
+
import { Domain } from '@things-factory/shell';
|
|
4
|
+
import { AttendeeInput } from '../attendee/attendee-type';
|
|
5
|
+
import { Event } from '../event/event';
|
|
6
|
+
import { EventSeries } from './event-series';
|
|
7
|
+
import { EventSeriesChange, EventSeriesPatch, NewEventSeries } from './event-series-type';
|
|
8
|
+
export declare function eventSeriesInDomain(tx: EntityManager, domain: Domain, id: string): Promise<EventSeries>;
|
|
9
|
+
export declare function createEventSeries(tx: EntityManager, domain: Domain, user: User, input: NewEventSeries): Promise<EventSeries>;
|
|
10
|
+
/**
|
|
11
|
+
* Create the series' occurrences from now (or its start) up to `until`. Times that already have an occurrence —
|
|
12
|
+
* postponed or not — get none; asking twice makes one. Returns every occurrence in the range.
|
|
13
|
+
*/
|
|
14
|
+
export declare function generateEventOccurrences(tx: EntityManager, domain: Domain, user: User, id: string, until: Date, { now }?: {
|
|
15
|
+
now?: Date;
|
|
16
|
+
}): Promise<Event[]>;
|
|
17
|
+
/**
|
|
18
|
+
* Change a series. From now (or its start) on, undecided occurrences follow it — kept, removed or added as
|
|
19
|
+
* `planChange` says; nothing earlier and nothing already postponed, cancelled or held moves. With `preview` nothing
|
|
20
|
+
* is written and the answer says what would happen, so the caller can stop or ask a person first.
|
|
21
|
+
*/
|
|
22
|
+
export declare function updateEventSeries(tx: EntityManager, domain: Domain, user: User, id: string, patch: EventSeriesPatch, { preview, now }?: {
|
|
23
|
+
preview?: boolean;
|
|
24
|
+
now?: Date;
|
|
25
|
+
}): Promise<EventSeriesChange>;
|
|
26
|
+
/**
|
|
27
|
+
* Delete a series: its undecided occurrences from now on go with it; earlier, postponed, cancelled and held ones stay.
|
|
28
|
+
* With `preview` nothing is written.
|
|
29
|
+
*/
|
|
30
|
+
export declare function deleteEventSeries(tx: EntityManager, domain: Domain, user: User, id: string, { preview, now }?: {
|
|
31
|
+
preview?: boolean;
|
|
32
|
+
now?: Date;
|
|
33
|
+
}): Promise<EventSeriesChange>;
|
|
34
|
+
/**
|
|
35
|
+
* Make the people named on a series exactly these. Its undecided occurrences from now on gain the people added and
|
|
36
|
+
* lose the people removed; anyone named on one occurrence alone stays there.
|
|
37
|
+
*/
|
|
38
|
+
export declare function setEventSeriesAttendees(tx: EntityManager, domain: Domain, user: User, id: string, inputs: AttendeeInput[], { now }?: {
|
|
39
|
+
now?: Date;
|
|
40
|
+
}): Promise<EventSeries>;
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.eventSeriesInDomain = eventSeriesInDomain;
|
|
4
|
+
exports.createEventSeries = createEventSeries;
|
|
5
|
+
exports.generateEventOccurrences = generateEventOccurrences;
|
|
6
|
+
exports.updateEventSeries = updateEventSeries;
|
|
7
|
+
exports.deleteEventSeries = deleteEventSeries;
|
|
8
|
+
exports.setEventSeriesAttendees = setEventSeriesAttendees;
|
|
9
|
+
const typeorm_1 = require("typeorm");
|
|
10
|
+
const shell_1 = require("@things-factory/shell");
|
|
11
|
+
const attendee_1 = require("../attendee/attendee");
|
|
12
|
+
const attendee_service_1 = require("../attendee/attendee-service");
|
|
13
|
+
const event_1 = require("../event/event");
|
|
14
|
+
const event_rules_1 = require("../event/event-rules");
|
|
15
|
+
const event_service_1 = require("../event/event-service");
|
|
16
|
+
const event_series_1 = require("./event-series");
|
|
17
|
+
const recurrence_1 = require("./recurrence");
|
|
18
|
+
const MINUTE = 60_000;
|
|
19
|
+
async function eventSeriesInDomain(tx, domain, id) {
|
|
20
|
+
const series = await tx.getRepository(event_series_1.EventSeries).findOne({ where: { id, domain: { id: domain.id } } });
|
|
21
|
+
if (!series)
|
|
22
|
+
throw new shell_1.Refusal('event-series-not-found', {}, 'Series not found');
|
|
23
|
+
return series;
|
|
24
|
+
}
|
|
25
|
+
function checkShape(shape) {
|
|
26
|
+
(0, event_service_1.checkEventName)(shape.name);
|
|
27
|
+
(0, recurrence_1.checkRule)(shape.rule, shape.timezone);
|
|
28
|
+
if (!Number.isInteger(shape.durationMinutes) || shape.durationMinutes <= 0)
|
|
29
|
+
throw new shell_1.Refusal('event-series-duration-invalid', {}, 'Give the length in whole minutes, more than zero');
|
|
30
|
+
if (!(shape.startsAt instanceof Date) || isNaN(shape.startsAt.getTime()))
|
|
31
|
+
throw new shell_1.Refusal('event-series-starts-at-required', {}, 'Give when the series starts');
|
|
32
|
+
if (shape.endsAt && !(shape.endsAt > shape.startsAt))
|
|
33
|
+
throw new shell_1.Refusal('event-series-ends-before-start', {}, 'The series ends after it starts');
|
|
34
|
+
}
|
|
35
|
+
function shapeOf(series) {
|
|
36
|
+
const { name, description, location, rule, timezone, durationMinutes, startsAt, endsAt, active } = series;
|
|
37
|
+
return { name, description, location, rule, timezone, durationMinutes, startsAt, endsAt, active, calendarId: series.calendarId ?? null, organizerId: series.organizerId ?? null };
|
|
38
|
+
}
|
|
39
|
+
/** The rule's times for `shape` from `from` to `until`, kept inside the series' own bounds. */
|
|
40
|
+
function timesOf(shape, from, until) {
|
|
41
|
+
if (!shape.active)
|
|
42
|
+
return [];
|
|
43
|
+
const start = from > shape.startsAt ? from : shape.startsAt;
|
|
44
|
+
const end = shape.endsAt && shape.endsAt < until ? shape.endsAt : until;
|
|
45
|
+
return (0, recurrence_1.occurrenceTimes)(shape.rule, shape.timezone, start, end);
|
|
46
|
+
}
|
|
47
|
+
async function occurrencesOf(tx, domain, series, from) {
|
|
48
|
+
return tx.getRepository(event_1.Event).find({
|
|
49
|
+
where: { domain: { id: domain.id }, series: { id: series.id }, scheduledAt: (0, typeorm_1.MoreThanOrEqual)(from) },
|
|
50
|
+
order: { scheduledAt: 'ASC' }
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
async function createOccurrences(tx, domain, user, series, times, attendees) {
|
|
54
|
+
const repository = tx.getRepository(event_1.Event);
|
|
55
|
+
const created = [];
|
|
56
|
+
for (const time of times) {
|
|
57
|
+
const event = await repository.save(repository.create({
|
|
58
|
+
domain,
|
|
59
|
+
calendar: series.calendarId ? { id: series.calendarId } : null,
|
|
60
|
+
series,
|
|
61
|
+
scheduledAt: time,
|
|
62
|
+
startAt: time,
|
|
63
|
+
endAt: new Date(time.getTime() + series.durationMinutes * MINUTE),
|
|
64
|
+
status: event_rules_1.EventStatus.SCHEDULED,
|
|
65
|
+
name: series.name,
|
|
66
|
+
description: series.description ?? null,
|
|
67
|
+
location: series.location ?? null,
|
|
68
|
+
organizer: series.organizerId ? { id: series.organizerId } : null,
|
|
69
|
+
creator: user,
|
|
70
|
+
updater: user
|
|
71
|
+
}));
|
|
72
|
+
await (0, attendee_service_1.replaceAttendees)(tx, domain, user, { event }, attendees);
|
|
73
|
+
created.push(event);
|
|
74
|
+
}
|
|
75
|
+
return created;
|
|
76
|
+
}
|
|
77
|
+
async function createEventSeries(tx, domain, user, input) {
|
|
78
|
+
const shape = {
|
|
79
|
+
name: input.name?.trim(),
|
|
80
|
+
description: input.description?.trim() || null,
|
|
81
|
+
location: input.location?.trim() || null,
|
|
82
|
+
rule: input.rule?.trim(),
|
|
83
|
+
timezone: input.timezone?.trim() || domain.timezone || 'UTC',
|
|
84
|
+
durationMinutes: input.durationMinutes,
|
|
85
|
+
startsAt: input.startsAt,
|
|
86
|
+
endsAt: input.endsAt ?? null,
|
|
87
|
+
active: true,
|
|
88
|
+
calendarId: (await (0, event_service_1.calendarOfDomain)(tx, domain, input.calendarId))?.id ?? null,
|
|
89
|
+
organizerId: input.organizerId && input.organizerId !== user.id ? (await (0, event_service_1.checkOrganizer)(tx, domain, input.organizerId)).id : user.id
|
|
90
|
+
};
|
|
91
|
+
checkShape(shape);
|
|
92
|
+
const attendees = await (0, attendee_service_1.checkAttendees)(tx, domain, input.attendees);
|
|
93
|
+
const repository = tx.getRepository(event_series_1.EventSeries);
|
|
94
|
+
const { calendarId, organizerId, ...facts } = shape;
|
|
95
|
+
const saved = await repository.save(repository.create({
|
|
96
|
+
...facts,
|
|
97
|
+
domain,
|
|
98
|
+
calendar: calendarId ? { id: calendarId } : null,
|
|
99
|
+
organizer: { id: organizerId },
|
|
100
|
+
creator: user,
|
|
101
|
+
updater: user
|
|
102
|
+
}));
|
|
103
|
+
await (0, attendee_service_1.replaceAttendees)(tx, domain, user, { series: saved }, attendees);
|
|
104
|
+
return eventSeriesInDomain(tx, domain, saved.id);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Create the series' occurrences from now (or its start) up to `until`. Times that already have an occurrence —
|
|
108
|
+
* postponed or not — get none; asking twice makes one. Returns every occurrence in the range.
|
|
109
|
+
*/
|
|
110
|
+
async function generateEventOccurrences(tx, domain, user, id, until, { now = new Date() } = {}) {
|
|
111
|
+
const series = await eventSeriesInDomain(tx, domain, id);
|
|
112
|
+
if (!series.active)
|
|
113
|
+
throw new shell_1.Refusal('event-series-inactive', {}, 'The series is not active');
|
|
114
|
+
if (!(until instanceof Date) || isNaN(until.getTime()))
|
|
115
|
+
throw new shell_1.Refusal('event-series-until-required', {}, 'Give the time to create occurrences up to');
|
|
116
|
+
const times = timesOf(shapeOf(series), now, until);
|
|
117
|
+
const existing = new Set((await occurrencesOf(tx, domain, series, times[0] ?? now)).map(event => event.scheduledAt.getTime()));
|
|
118
|
+
const missing = times.filter(time => !existing.has(time.getTime()));
|
|
119
|
+
await createOccurrences(tx, domain, user, series, missing, (0, attendee_service_1.entriesOf)(await (0, attendee_service_1.attendeesOf)(tx, domain, { series })));
|
|
120
|
+
if (!times.length)
|
|
121
|
+
return [];
|
|
122
|
+
return tx.getRepository(event_1.Event).find({
|
|
123
|
+
where: { domain: { id: domain.id }, series: { id: series.id }, scheduledAt: (0, typeorm_1.In)(times) },
|
|
124
|
+
order: { scheduledAt: 'ASC' }
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
/** What follows the series onto an undecided occurrence when it changes: only the fields that changed. */
|
|
128
|
+
function followingChange(before, after, event) {
|
|
129
|
+
const change = {};
|
|
130
|
+
if (before.name !== after.name)
|
|
131
|
+
change.name = after.name;
|
|
132
|
+
if (before.description !== after.description)
|
|
133
|
+
change.description = after.description;
|
|
134
|
+
if (before.location !== after.location)
|
|
135
|
+
change.location = after.location;
|
|
136
|
+
if (before.calendarId !== after.calendarId)
|
|
137
|
+
change.calendar = after.calendarId ? { id: after.calendarId } : null;
|
|
138
|
+
if (before.organizerId !== after.organizerId)
|
|
139
|
+
change.organizer = after.organizerId ? { id: after.organizerId } : null;
|
|
140
|
+
if (before.durationMinutes !== after.durationMinutes)
|
|
141
|
+
change.endAt = new Date(event.startAt.getTime() + after.durationMinutes * MINUTE);
|
|
142
|
+
return change;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* What a series becoming `after` does from `from` on: an undecided occurrence still on the rule stays, one off it is
|
|
146
|
+
* removed, and the rule's new times up to the furthest occurrence already there are added. Postponed, cancelled,
|
|
147
|
+
* held and earlier occurrences are not looked at.
|
|
148
|
+
*/
|
|
149
|
+
async function planChange(tx, domain, series, after, from) {
|
|
150
|
+
const future = await occurrencesOf(tx, domain, series, from);
|
|
151
|
+
const horizon = future.length ? future[future.length - 1].scheduledAt : null;
|
|
152
|
+
const times = horizon ? timesOf(after, from, horizon) : [];
|
|
153
|
+
const onRule = new Set(times.map(time => time.getTime()));
|
|
154
|
+
const undecided = future.filter(event => event.status === event_rules_1.EventStatus.SCHEDULED);
|
|
155
|
+
const taken = new Set(future.map(event => event.scheduledAt.getTime()));
|
|
156
|
+
return {
|
|
157
|
+
kept: undecided.filter(event => onRule.has(event.scheduledAt.getTime())),
|
|
158
|
+
removed: undecided.filter(event => !onRule.has(event.scheduledAt.getTime())),
|
|
159
|
+
added: times.filter(time => !taken.has(time.getTime()))
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
async function removeOccurrences(tx, user, events) {
|
|
163
|
+
if (!events.length)
|
|
164
|
+
return;
|
|
165
|
+
const ids = events.map(event => event.id);
|
|
166
|
+
await tx.getRepository(event_1.Event).update({ id: (0, typeorm_1.In)(ids) }, { updater: user });
|
|
167
|
+
await tx.getRepository(event_1.Event).softDelete({ id: (0, typeorm_1.In)(ids) });
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Change a series. From now (or its start) on, undecided occurrences follow it — kept, removed or added as
|
|
171
|
+
* `planChange` says; nothing earlier and nothing already postponed, cancelled or held moves. With `preview` nothing
|
|
172
|
+
* is written and the answer says what would happen, so the caller can stop or ask a person first.
|
|
173
|
+
*/
|
|
174
|
+
async function updateEventSeries(tx, domain, user, id, patch, { preview = false, now = new Date() } = {}) {
|
|
175
|
+
const series = await eventSeriesInDomain(tx, domain, id);
|
|
176
|
+
const before = shapeOf(series);
|
|
177
|
+
const after = { ...before };
|
|
178
|
+
if (patch.name !== undefined)
|
|
179
|
+
after.name = patch.name?.trim();
|
|
180
|
+
if (patch.description !== undefined)
|
|
181
|
+
after.description = patch.description?.trim() || null;
|
|
182
|
+
if (patch.location !== undefined)
|
|
183
|
+
after.location = patch.location?.trim() || null;
|
|
184
|
+
if (patch.rule !== undefined)
|
|
185
|
+
after.rule = patch.rule?.trim();
|
|
186
|
+
if (patch.timezone !== undefined)
|
|
187
|
+
after.timezone = patch.timezone?.trim();
|
|
188
|
+
if (patch.durationMinutes !== undefined)
|
|
189
|
+
after.durationMinutes = patch.durationMinutes;
|
|
190
|
+
if (patch.startsAt !== undefined)
|
|
191
|
+
after.startsAt = patch.startsAt;
|
|
192
|
+
if (patch.endsAt !== undefined)
|
|
193
|
+
after.endsAt = patch.endsAt ?? null;
|
|
194
|
+
if (patch.active !== undefined && patch.active !== null)
|
|
195
|
+
after.active = patch.active;
|
|
196
|
+
if (patch.calendarId !== undefined)
|
|
197
|
+
after.calendarId = (await (0, event_service_1.calendarOfDomain)(tx, domain, patch.calendarId))?.id ?? null;
|
|
198
|
+
if (patch.organizerId !== undefined && patch.organizerId !== before.organizerId)
|
|
199
|
+
after.organizerId = patch.organizerId ? (await (0, event_service_1.checkOrganizer)(tx, domain, patch.organizerId)).id : null;
|
|
200
|
+
checkShape(after);
|
|
201
|
+
const plan = await planChange(tx, domain, series, after, now);
|
|
202
|
+
const { calendarId, organizerId, ...facts } = after;
|
|
203
|
+
if (preview) {
|
|
204
|
+
return { series: Object.assign(new event_series_1.EventSeries(), series, after), applied: false, kept: plan.kept, removed: plan.removed, added: plan.added, created: [] };
|
|
205
|
+
}
|
|
206
|
+
await tx.getRepository(event_series_1.EventSeries).update({ id: series.id }, { ...facts, calendar: calendarId ? { id: calendarId } : null, organizer: organizerId ? { id: organizerId } : null, updater: user });
|
|
207
|
+
const saved = await eventSeriesInDomain(tx, domain, series.id);
|
|
208
|
+
for (const event of plan.kept) {
|
|
209
|
+
const change = followingChange(before, after, event);
|
|
210
|
+
if (Object.keys(change).length)
|
|
211
|
+
await tx.getRepository(event_1.Event).update({ id: event.id }, { ...change, updater: user });
|
|
212
|
+
}
|
|
213
|
+
await removeOccurrences(tx, user, plan.removed);
|
|
214
|
+
const created = await createOccurrences(tx, domain, user, saved, plan.added, (0, attendee_service_1.entriesOf)(await (0, attendee_service_1.attendeesOf)(tx, domain, { series: saved })));
|
|
215
|
+
const kept = plan.kept.length ? await tx.getRepository(event_1.Event).find({ where: { id: (0, typeorm_1.In)(plan.kept.map(event => event.id)) }, order: { scheduledAt: 'ASC' } }) : [];
|
|
216
|
+
return { series: saved, applied: true, kept, removed: plan.removed, added: plan.added, created };
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Delete a series: its undecided occurrences from now on go with it; earlier, postponed, cancelled and held ones stay.
|
|
220
|
+
* With `preview` nothing is written.
|
|
221
|
+
*/
|
|
222
|
+
async function deleteEventSeries(tx, domain, user, id, { preview = false, now = new Date() } = {}) {
|
|
223
|
+
const series = await eventSeriesInDomain(tx, domain, id);
|
|
224
|
+
const removed = (await occurrencesOf(tx, domain, series, now)).filter(event => event.status === event_rules_1.EventStatus.SCHEDULED);
|
|
225
|
+
if (!preview) {
|
|
226
|
+
await removeOccurrences(tx, user, removed);
|
|
227
|
+
const attendees = await (0, attendee_service_1.attendeesOf)(tx, domain, { series });
|
|
228
|
+
if (attendees.length)
|
|
229
|
+
await tx.getRepository(attendee_1.Attendee).softDelete({ id: (0, typeorm_1.In)(attendees.map(row => row.id)) });
|
|
230
|
+
await tx.getRepository(event_series_1.EventSeries).update({ id: series.id }, { updater: user });
|
|
231
|
+
await tx.getRepository(event_series_1.EventSeries).softDelete({ id: series.id });
|
|
232
|
+
}
|
|
233
|
+
return { series, applied: !preview, kept: [], removed, added: [], created: [] };
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Make the people named on a series exactly these. Its undecided occurrences from now on gain the people added and
|
|
237
|
+
* lose the people removed; anyone named on one occurrence alone stays there.
|
|
238
|
+
*/
|
|
239
|
+
async function setEventSeriesAttendees(tx, domain, user, id, inputs, { now = new Date() } = {}) {
|
|
240
|
+
const series = await eventSeriesInDomain(tx, domain, id);
|
|
241
|
+
const entries = await (0, attendee_service_1.checkAttendees)(tx, domain, inputs);
|
|
242
|
+
const before = (0, attendee_service_1.entriesOf)(await (0, attendee_service_1.attendeesOf)(tx, domain, { series }));
|
|
243
|
+
const keys = entries.map(entry => entry.key);
|
|
244
|
+
const removed = before.map(entry => entry.key).filter(key => !keys.includes(key));
|
|
245
|
+
const changed = entries.filter(entry => !before.some(one => one.key === entry.key && one.name === entry.name));
|
|
246
|
+
await (0, attendee_service_1.replaceAttendees)(tx, domain, user, { series }, entries);
|
|
247
|
+
const undecided = (await occurrencesOf(tx, domain, series, now)).filter(event => event.status === event_rules_1.EventStatus.SCHEDULED);
|
|
248
|
+
for (const event of undecided)
|
|
249
|
+
await (0, attendee_service_1.changeAttendees)(tx, domain, user, { event }, changed, removed);
|
|
250
|
+
await tx.getRepository(event_series_1.EventSeries).update({ id: series.id }, { updater: user });
|
|
251
|
+
return eventSeriesInDomain(tx, domain, series.id);
|
|
252
|
+
}
|
|
253
|
+
//# sourceMappingURL=event-series-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-series-service.js","sourceRoot":"","sources":["../../../server/service/event-series/event-series-service.ts"],"names":[],"mappings":"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","sourcesContent":["import { EntityManager, In, MoreThanOrEqual } from 'typeorm'\n\nimport { User } from '@things-factory/auth-base'\nimport { Domain, Refusal } from '@things-factory/shell'\n\nimport { Attendee } from '../attendee/attendee'\nimport { AttendeeInput } from '../attendee/attendee-type'\nimport { AttendeeEntry, attendeesOf, changeAttendees, checkAttendees, entriesOf, replaceAttendees } from '../attendee/attendee-service'\nimport { Event } from '../event/event'\nimport { EventStatus } from '../event/event-rules'\nimport { calendarOfDomain, checkEventName, checkOrganizer } from '../event/event-service'\nimport { EventSeries } from './event-series'\nimport { EventSeriesChange, EventSeriesPatch, NewEventSeries } from './event-series-type'\nimport { checkRule, occurrenceTimes } from './recurrence'\n\nconst MINUTE = 60_000\n\nexport async function eventSeriesInDomain(tx: EntityManager, domain: Domain, id: string): Promise<EventSeries> {\n const series = await tx.getRepository(EventSeries).findOne({ where: { id, domain: { id: domain.id } } })\n if (!series) throw new Refusal('event-series-not-found', {}, 'Series not found')\n return series\n}\n\n/** The facts a series' occurrences are made from, checked. */\ntype Shape = Pick<EventSeries, 'name' | 'description' | 'location' | 'rule' | 'timezone' | 'durationMinutes' | 'startsAt' | 'endsAt' | 'active'> & {\n calendarId: string | null\n organizerId: string | null\n}\n\nfunction checkShape(shape: Shape) {\n checkEventName(shape.name)\n checkRule(shape.rule, shape.timezone)\n if (!Number.isInteger(shape.durationMinutes) || shape.durationMinutes <= 0)\n throw new Refusal('event-series-duration-invalid', {}, 'Give the length in whole minutes, more than zero')\n if (!(shape.startsAt instanceof Date) || isNaN(shape.startsAt.getTime())) throw new Refusal('event-series-starts-at-required', {}, 'Give when the series starts')\n if (shape.endsAt && !(shape.endsAt > shape.startsAt)) throw new Refusal('event-series-ends-before-start', {}, 'The series ends after it starts')\n}\n\nfunction shapeOf(series: EventSeries): Shape {\n const { name, description, location, rule, timezone, durationMinutes, startsAt, endsAt, active } = series\n return { name, description, location, rule, timezone, durationMinutes, startsAt, endsAt, active, calendarId: series.calendarId ?? null, organizerId: series.organizerId ?? null }\n}\n\n/** The rule's times for `shape` from `from` to `until`, kept inside the series' own bounds. */\nfunction timesOf(shape: Shape, from: Date, until: Date): Date[] {\n if (!shape.active) return []\n const start = from > shape.startsAt ? from : shape.startsAt\n const end = shape.endsAt && shape.endsAt < until ? shape.endsAt : until\n return occurrenceTimes(shape.rule, shape.timezone, start, end)\n}\n\nasync function occurrencesOf(tx: EntityManager, domain: Domain, series: EventSeries, from: Date): Promise<Event[]> {\n return tx.getRepository(Event).find({\n where: { domain: { id: domain.id }, series: { id: series.id }, scheduledAt: MoreThanOrEqual(from) },\n order: { scheduledAt: 'ASC' }\n })\n}\n\nasync function createOccurrences(tx: EntityManager, domain: Domain, user: User, series: EventSeries, times: Date[], attendees: AttendeeEntry[]): Promise<Event[]> {\n const repository = tx.getRepository(Event)\n const created: Event[] = []\n for (const time of times) {\n const event = await repository.save(\n repository.create({\n domain,\n calendar: series.calendarId ? ({ id: series.calendarId } as any) : null,\n series,\n scheduledAt: time,\n startAt: time,\n endAt: new Date(time.getTime() + series.durationMinutes * MINUTE),\n status: EventStatus.SCHEDULED,\n name: series.name,\n description: series.description ?? null,\n location: series.location ?? null,\n organizer: series.organizerId ? ({ id: series.organizerId } as User) : null,\n creator: user,\n updater: user\n })\n )\n await replaceAttendees(tx, domain, user, { event }, attendees)\n created.push(event)\n }\n return created\n}\n\nexport async function createEventSeries(tx: EntityManager, domain: Domain, user: User, input: NewEventSeries): Promise<EventSeries> {\n const shape: Shape = {\n name: input.name?.trim(),\n description: input.description?.trim() || null,\n location: input.location?.trim() || null,\n rule: input.rule?.trim(),\n timezone: input.timezone?.trim() || domain.timezone || 'UTC',\n durationMinutes: input.durationMinutes,\n startsAt: input.startsAt,\n endsAt: input.endsAt ?? null,\n active: true,\n calendarId: (await calendarOfDomain(tx, domain, input.calendarId))?.id ?? null,\n organizerId: input.organizerId && input.organizerId !== user.id ? (await checkOrganizer(tx, domain, input.organizerId)).id : user.id\n }\n checkShape(shape)\n const attendees = await checkAttendees(tx, domain, input.attendees)\n\n const repository = tx.getRepository(EventSeries)\n const { calendarId, organizerId, ...facts } = shape\n const saved = await repository.save(\n repository.create({\n ...facts,\n domain,\n calendar: calendarId ? ({ id: calendarId } as any) : null,\n organizer: { id: organizerId } as User,\n creator: user,\n updater: user\n })\n )\n await replaceAttendees(tx, domain, user, { series: saved }, attendees)\n return eventSeriesInDomain(tx, domain, saved.id)\n}\n\n/**\n * Create the series' occurrences from now (or its start) up to `until`. Times that already have an occurrence —\n * postponed or not — get none; asking twice makes one. Returns every occurrence in the range.\n */\nexport async function generateEventOccurrences(\n tx: EntityManager,\n domain: Domain,\n user: User,\n id: string,\n until: Date,\n { now = new Date() }: { now?: Date } = {}\n): Promise<Event[]> {\n const series = await eventSeriesInDomain(tx, domain, id)\n if (!series.active) throw new Refusal('event-series-inactive', {}, 'The series is not active')\n if (!(until instanceof Date) || isNaN(until.getTime())) throw new Refusal('event-series-until-required', {}, 'Give the time to create occurrences up to')\n\n const times = timesOf(shapeOf(series), now, until)\n const existing = new Set((await occurrencesOf(tx, domain, series, times[0] ?? now)).map(event => event.scheduledAt.getTime()))\n const missing = times.filter(time => !existing.has(time.getTime()))\n await createOccurrences(tx, domain, user, series, missing, entriesOf(await attendeesOf(tx, domain, { series })))\n\n if (!times.length) return []\n return tx.getRepository(Event).find({\n where: { domain: { id: domain.id }, series: { id: series.id }, scheduledAt: In(times) },\n order: { scheduledAt: 'ASC' }\n })\n}\n\n/** What follows the series onto an undecided occurrence when it changes: only the fields that changed. */\nfunction followingChange(before: Shape, after: Shape, event: Event): Partial<Event> {\n const change: Partial<Event> = {}\n if (before.name !== after.name) change.name = after.name\n if (before.description !== after.description) change.description = after.description\n if (before.location !== after.location) change.location = after.location\n if (before.calendarId !== after.calendarId) change.calendar = after.calendarId ? ({ id: after.calendarId } as any) : null\n if (before.organizerId !== after.organizerId) change.organizer = after.organizerId ? ({ id: after.organizerId } as User) : null\n if (before.durationMinutes !== after.durationMinutes) change.endAt = new Date(event.startAt.getTime() + after.durationMinutes * MINUTE)\n return change\n}\n\n/**\n * What a series becoming `after` does from `from` on: an undecided occurrence still on the rule stays, one off it is\n * removed, and the rule's new times up to the furthest occurrence already there are added. Postponed, cancelled,\n * held and earlier occurrences are not looked at.\n */\nasync function planChange(tx: EntityManager, domain: Domain, series: EventSeries, after: Shape, from: Date) {\n const future = await occurrencesOf(tx, domain, series, from)\n const horizon = future.length ? future[future.length - 1].scheduledAt : null\n const times = horizon ? timesOf(after, from, horizon) : []\n const onRule = new Set(times.map(time => time.getTime()))\n const undecided = future.filter(event => event.status === EventStatus.SCHEDULED)\n const taken = new Set(future.map(event => event.scheduledAt.getTime()))\n return {\n kept: undecided.filter(event => onRule.has(event.scheduledAt.getTime())),\n removed: undecided.filter(event => !onRule.has(event.scheduledAt.getTime())),\n added: times.filter(time => !taken.has(time.getTime()))\n }\n}\n\nasync function removeOccurrences(tx: EntityManager, user: User, events: Event[]) {\n if (!events.length) return\n const ids = events.map(event => event.id)\n await tx.getRepository(Event).update({ id: In(ids) }, { updater: user })\n await tx.getRepository(Event).softDelete({ id: In(ids) })\n}\n\n/**\n * Change a series. From now (or its start) on, undecided occurrences follow it — kept, removed or added as\n * `planChange` says; nothing earlier and nothing already postponed, cancelled or held moves. With `preview` nothing\n * is written and the answer says what would happen, so the caller can stop or ask a person first.\n */\nexport async function updateEventSeries(\n tx: EntityManager,\n domain: Domain,\n user: User,\n id: string,\n patch: EventSeriesPatch,\n { preview = false, now = new Date() }: { preview?: boolean; now?: Date } = {}\n): Promise<EventSeriesChange> {\n const series = await eventSeriesInDomain(tx, domain, id)\n const before = shapeOf(series)\n const after: Shape = { ...before }\n if (patch.name !== undefined) after.name = patch.name?.trim()\n if (patch.description !== undefined) after.description = patch.description?.trim() || null\n if (patch.location !== undefined) after.location = patch.location?.trim() || null\n if (patch.rule !== undefined) after.rule = patch.rule?.trim()\n if (patch.timezone !== undefined) after.timezone = patch.timezone?.trim()\n if (patch.durationMinutes !== undefined) after.durationMinutes = patch.durationMinutes\n if (patch.startsAt !== undefined) after.startsAt = patch.startsAt\n if (patch.endsAt !== undefined) after.endsAt = patch.endsAt ?? null\n if (patch.active !== undefined && patch.active !== null) after.active = patch.active\n if (patch.calendarId !== undefined) after.calendarId = (await calendarOfDomain(tx, domain, patch.calendarId))?.id ?? null\n if (patch.organizerId !== undefined && patch.organizerId !== before.organizerId)\n after.organizerId = patch.organizerId ? (await checkOrganizer(tx, domain, patch.organizerId)).id : null\n checkShape(after)\n\n const plan = await planChange(tx, domain, series, after, now)\n const { calendarId, organizerId, ...facts } = after\n if (preview) {\n return { series: Object.assign(new EventSeries(), series, after), applied: false, kept: plan.kept, removed: plan.removed, added: plan.added, created: [] }\n }\n\n await tx.getRepository(EventSeries).update(\n { id: series.id },\n { ...facts, calendar: calendarId ? ({ id: calendarId } as any) : null, organizer: organizerId ? ({ id: organizerId } as User) : null, updater: user }\n )\n const saved = await eventSeriesInDomain(tx, domain, series.id)\n\n for (const event of plan.kept) {\n const change = followingChange(before, after, event)\n if (Object.keys(change).length) await tx.getRepository(Event).update({ id: event.id }, { ...change, updater: user })\n }\n await removeOccurrences(tx, user, plan.removed)\n const created = await createOccurrences(tx, domain, user, saved, plan.added, entriesOf(await attendeesOf(tx, domain, { series: saved })))\n const kept = plan.kept.length ? await tx.getRepository(Event).find({ where: { id: In(plan.kept.map(event => event.id)) }, order: { scheduledAt: 'ASC' } }) : []\n return { series: saved, applied: true, kept, removed: plan.removed, added: plan.added, created }\n}\n\n/**\n * Delete a series: its undecided occurrences from now on go with it; earlier, postponed, cancelled and held ones stay.\n * With `preview` nothing is written.\n */\nexport async function deleteEventSeries(\n tx: EntityManager,\n domain: Domain,\n user: User,\n id: string,\n { preview = false, now = new Date() }: { preview?: boolean; now?: Date } = {}\n): Promise<EventSeriesChange> {\n const series = await eventSeriesInDomain(tx, domain, id)\n const removed = (await occurrencesOf(tx, domain, series, now)).filter(event => event.status === EventStatus.SCHEDULED)\n if (!preview) {\n await removeOccurrences(tx, user, removed)\n const attendees = await attendeesOf(tx, domain, { series })\n if (attendees.length) await tx.getRepository(Attendee).softDelete({ id: In(attendees.map(row => row.id)) })\n await tx.getRepository(EventSeries).update({ id: series.id }, { updater: user })\n await tx.getRepository(EventSeries).softDelete({ id: series.id })\n }\n return { series, applied: !preview, kept: [], removed, added: [], created: [] }\n}\n\n/**\n * Make the people named on a series exactly these. Its undecided occurrences from now on gain the people added and\n * lose the people removed; anyone named on one occurrence alone stays there.\n */\nexport async function setEventSeriesAttendees(\n tx: EntityManager,\n domain: Domain,\n user: User,\n id: string,\n inputs: AttendeeInput[],\n { now = new Date() }: { now?: Date } = {}\n): Promise<EventSeries> {\n const series = await eventSeriesInDomain(tx, domain, id)\n const entries = await checkAttendees(tx, domain, inputs)\n const before = entriesOf(await attendeesOf(tx, domain, { series }))\n const keys = entries.map(entry => entry.key)\n const removed = before.map(entry => entry.key).filter(key => !keys.includes(key))\n const changed = entries.filter(entry => !before.some(one => one.key === entry.key && one.name === entry.name))\n\n await replaceAttendees(tx, domain, user, { series }, entries)\n const undecided = (await occurrencesOf(tx, domain, series, now)).filter(event => event.status === EventStatus.SCHEDULED)\n for (const event of undecided) await changeAttendees(tx, domain, user, { event }, changed, removed)\n await tx.getRepository(EventSeries).update({ id: series.id }, { updater: user })\n return eventSeriesInDomain(tx, domain, series.id)\n}\n\n"]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { AttendeeInput } from '../attendee/attendee-type';
|
|
2
|
+
import { Event } from '../event/event';
|
|
3
|
+
import { EventSeries } from './event-series';
|
|
4
|
+
export declare class NewEventSeries {
|
|
5
|
+
name: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
location?: string;
|
|
8
|
+
calendarId?: string;
|
|
9
|
+
organizerId?: string;
|
|
10
|
+
rule: string;
|
|
11
|
+
timezone?: string;
|
|
12
|
+
durationMinutes: number;
|
|
13
|
+
startsAt: Date;
|
|
14
|
+
endsAt?: Date;
|
|
15
|
+
attendees?: AttendeeInput[];
|
|
16
|
+
}
|
|
17
|
+
export declare class EventSeriesPatch {
|
|
18
|
+
name?: string;
|
|
19
|
+
description?: string;
|
|
20
|
+
location?: string;
|
|
21
|
+
calendarId?: string;
|
|
22
|
+
organizerId?: string;
|
|
23
|
+
rule?: string;
|
|
24
|
+
timezone?: string;
|
|
25
|
+
durationMinutes?: number;
|
|
26
|
+
startsAt?: Date;
|
|
27
|
+
endsAt?: Date;
|
|
28
|
+
active?: boolean;
|
|
29
|
+
}
|
|
30
|
+
export declare class EventSeriesChange {
|
|
31
|
+
series: EventSeries;
|
|
32
|
+
applied: boolean;
|
|
33
|
+
kept: Event[];
|
|
34
|
+
removed: Event[];
|
|
35
|
+
added: Date[];
|
|
36
|
+
created: Event[];
|
|
37
|
+
}
|
|
38
|
+
export declare class EventSeriesList {
|
|
39
|
+
items: EventSeries[];
|
|
40
|
+
total: number;
|
|
41
|
+
}
|