@aneuhold/be-ts-db-lib 2.0.78 → 2.0.80
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/CHANGELOG.md +16 -0
- package/lib/services/DemoAccountsService/DashboardDemoAccountsService.d.ts +72 -0
- package/lib/services/DemoAccountsService/DashboardDemoAccountsService.d.ts.map +1 -0
- package/lib/services/DemoAccountsService/DashboardDemoAccountsService.js +234 -0
- package/lib/services/DemoAccountsService/DashboardDemoAccountsService.js.map +1 -0
- package/lib/services/DemoAccountsService/DashboardDemoAccountsService.ts +257 -0
- package/lib/services/DemoAccountsService/DemoAccountsService.d.ts +17 -0
- package/lib/services/DemoAccountsService/DemoAccountsService.d.ts.map +1 -0
- package/lib/services/DemoAccountsService/DemoAccountsService.js +19 -0
- package/lib/services/DemoAccountsService/DemoAccountsService.js.map +1 -0
- package/lib/services/DemoAccountsService/DemoAccountsService.ts +23 -0
- package/lib/services/DemoAccountsService/index.d.ts +2 -0
- package/lib/services/DemoAccountsService/index.d.ts.map +1 -0
- package/lib/services/DemoAccountsService/index.js +2 -0
- package/lib/services/DemoAccountsService/index.js.map +1 -0
- package/lib/services/DemoAccountsService/index.ts +1 -0
- package/lib/util/DocumentDb.d.ts +16 -0
- package/lib/util/DocumentDb.d.ts.map +1 -1
- package/lib/util/DocumentDb.js +16 -0
- package/lib/util/DocumentDb.js.map +1 -1
- package/lib/util/DocumentDb.ts +16 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## 🔖 [2.0.80] (2025-10-17)
|
|
9
|
+
|
|
10
|
+
### 🏗️ Changed
|
|
11
|
+
|
|
12
|
+
- Improved and expanded JSDoc comments and documentation for public types and methods throughout the package
|
|
13
|
+
|
|
14
|
+
## 🔖 [2.0.79] (2025-08-18)
|
|
15
|
+
|
|
16
|
+
### ✅ Added
|
|
17
|
+
|
|
18
|
+
- Added `DemoAccountsService` and `DashboardDemoAccountsService` for seeding demo accounts and demo data for dashboard users
|
|
19
|
+
- Utilities to create, reset, and seed demo users with example tasks, collaborators, and user configs
|
|
20
|
+
- Shared and non-shared demo task creation logic for onboarding/testing
|
|
21
|
+
|
|
8
22
|
## 🔖 [2.0.78] (2025-07-04)
|
|
9
23
|
|
|
10
24
|
### 🏗️ Changed
|
|
@@ -38,6 +52,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
|
38
52
|
|
|
39
53
|
<!-- Link References -->
|
|
40
54
|
|
|
55
|
+
[2.0.80]: https://github.com/aneuhold/ts-libs/compare/be-ts-db-lib-v2.0.79...be-ts-db-lib-v2.0.80
|
|
56
|
+
[2.0.79]: https://github.com/aneuhold/ts-libs/compare/be-ts-db-lib-v2.0.78...be-ts-db-lib-v2.0.79
|
|
41
57
|
[2.0.78]: https://github.com/aneuhold/ts-libs/compare/be-ts-db-lib-v2.0.77...be-ts-db-lib-v2.0.78
|
|
42
58
|
[2.0.77]: https://github.com/aneuhold/ts-libs/compare/be-ts-db-lib-v2.0.76...be-ts-db-lib-v2.0.77
|
|
43
59
|
[2.0.76]: https://github.com/aneuhold/ts-libs/compare/be-ts-db-lib-v2.0.75...be-ts-db-lib-v2.0.76
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { ObjectId } from 'bson';
|
|
2
|
+
/**
|
|
3
|
+
* Dashboard-specific demo seeding utilities.
|
|
4
|
+
*/
|
|
5
|
+
export default class DashboardDemoAccountsService {
|
|
6
|
+
/**
|
|
7
|
+
* Default priorities for known demo tags. If a tag is not listed here,
|
|
8
|
+
* a fallback priority will be used.
|
|
9
|
+
*/
|
|
10
|
+
private static readonly TAG_PRIORITY;
|
|
11
|
+
/**
|
|
12
|
+
* Seeds the dashboard demo data for two users. This will:
|
|
13
|
+
* - Ensure both users have configs and are collaborators of each other
|
|
14
|
+
* - Reset select config flags (enableDevMode, useConfettiForTasks, catImageOnHomePage)
|
|
15
|
+
* - Wipe all tasks owned by either user
|
|
16
|
+
* - Create example tasks (shared, nested, completed, with tags)
|
|
17
|
+
*
|
|
18
|
+
* Safe to re-run; will produce the same end state.
|
|
19
|
+
*
|
|
20
|
+
* @param demoUser1Id The first user
|
|
21
|
+
* @param demoUser2Id The second user
|
|
22
|
+
*/
|
|
23
|
+
static seedDemoAccounts(demoUser1Id: ObjectId, demoUser2Id: ObjectId): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Ensures user has a config with the collaborator, and resets specific flags.
|
|
26
|
+
*
|
|
27
|
+
* @param ownerId The config owner
|
|
28
|
+
* @param collaboratorId The collaborator to include
|
|
29
|
+
*/
|
|
30
|
+
private static ensureCollaboratorsAndResetConfig;
|
|
31
|
+
/**
|
|
32
|
+
* Deletes all tasks owned by the provided users. Children are also removed
|
|
33
|
+
* since they share the same owner.
|
|
34
|
+
*
|
|
35
|
+
* @param userIds The users to wipe tasks for
|
|
36
|
+
*/
|
|
37
|
+
private static wipeTasksForUsers;
|
|
38
|
+
/**
|
|
39
|
+
* Creates a task owned by the specified user. Because we wipe all tasks
|
|
40
|
+
* for the demo users prior to creation, we don't need to check for
|
|
41
|
+
* existing tasks and can always insert.
|
|
42
|
+
*
|
|
43
|
+
* @param ownerId The owning user ID
|
|
44
|
+
* @param title The task title
|
|
45
|
+
* @param opts Additional optional task properties
|
|
46
|
+
* @param opts.description Description text
|
|
47
|
+
* @param opts.completed Completion flag
|
|
48
|
+
* @param opts.parentTaskId Parent task reference for subtasks
|
|
49
|
+
* @param opts.sharedWith Users the task is shared with
|
|
50
|
+
* @param opts.assignedTo The assigned user
|
|
51
|
+
* @param opts.tags Tags for the owning user
|
|
52
|
+
* @param opts.startDate Optional start date
|
|
53
|
+
* @param opts.dueDate Optional due date
|
|
54
|
+
* @param opts.category System category
|
|
55
|
+
*/
|
|
56
|
+
private static createTask;
|
|
57
|
+
/**
|
|
58
|
+
* Creates shared demo tasks visible to both users exactly once to avoid duplicates.
|
|
59
|
+
*
|
|
60
|
+
* @param user1Id The primary owner of some shared tasks
|
|
61
|
+
* @param user2Id The collaborator for shared tasks
|
|
62
|
+
*/
|
|
63
|
+
private static createExampleTasks;
|
|
64
|
+
/**
|
|
65
|
+
* Creates non-shared demo tasks for each user.
|
|
66
|
+
*
|
|
67
|
+
* @param user1Id The first user
|
|
68
|
+
* @param user2Id The second user
|
|
69
|
+
*/
|
|
70
|
+
private static createNonSharedTasks;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=DashboardDemoAccountsService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DashboardDemoAccountsService.d.ts","sourceRoot":"","sources":["../../../src/services/DemoAccountsService/DashboardDemoAccountsService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAIhC;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,4BAA4B;IAC/C;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAUlC;IAEF;;;;;;;;;;;OAWG;WACU,gBAAgB,CAAC,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAY1F;;;;;OAKG;mBACkB,iCAAiC;IA4BtD;;;;;OAKG;mBACkB,iBAAiB;IAYtC;;;;;;;;;;;;;;;;;OAiBG;mBACkB,UAAU;IAgC/B;;;;;OAKG;mBACkB,kBAAkB;IAqCvC;;;;;OAKG;mBACkB,oBAAoB;CAwD1C"}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { DashboardTask, DashboardUserConfig } from '@aneuhold/core-ts-db-lib';
|
|
2
|
+
import DashboardTaskRepository from '../../repositories/dashboard/DashboardTaskRepository.js';
|
|
3
|
+
import DashboardUserConfigRepository from '../../repositories/dashboard/DashboardUserConfigRepository.js';
|
|
4
|
+
/**
|
|
5
|
+
* Dashboard-specific demo seeding utilities.
|
|
6
|
+
*/
|
|
7
|
+
export default class DashboardDemoAccountsService {
|
|
8
|
+
/**
|
|
9
|
+
* Default priorities for known demo tags. If a tag is not listed here,
|
|
10
|
+
* a fallback priority will be used.
|
|
11
|
+
*/
|
|
12
|
+
static TAG_PRIORITY = {
|
|
13
|
+
planning: 9,
|
|
14
|
+
fun: 8,
|
|
15
|
+
booking: 7,
|
|
16
|
+
food: 6,
|
|
17
|
+
home: 5,
|
|
18
|
+
bbq: 4,
|
|
19
|
+
admin: 3,
|
|
20
|
+
paint: 2,
|
|
21
|
+
electric: 1
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Seeds the dashboard demo data for two users. This will:
|
|
25
|
+
* - Ensure both users have configs and are collaborators of each other
|
|
26
|
+
* - Reset select config flags (enableDevMode, useConfettiForTasks, catImageOnHomePage)
|
|
27
|
+
* - Wipe all tasks owned by either user
|
|
28
|
+
* - Create example tasks (shared, nested, completed, with tags)
|
|
29
|
+
*
|
|
30
|
+
* Safe to re-run; will produce the same end state.
|
|
31
|
+
*
|
|
32
|
+
* @param demoUser1Id The first user
|
|
33
|
+
* @param demoUser2Id The second user
|
|
34
|
+
*/
|
|
35
|
+
static async seedDemoAccounts(demoUser1Id, demoUser2Id) {
|
|
36
|
+
await this.ensureCollaboratorsAndResetConfig(demoUser1Id, demoUser2Id);
|
|
37
|
+
await this.ensureCollaboratorsAndResetConfig(demoUser2Id, demoUser1Id);
|
|
38
|
+
await this.wipeTasksForUsers([demoUser1Id, demoUser2Id]);
|
|
39
|
+
// Create shared tasks (visible to both users) exactly once
|
|
40
|
+
await this.createExampleTasks(demoUser1Id, demoUser2Id);
|
|
41
|
+
// Create non-shared tasks for each user
|
|
42
|
+
await this.createNonSharedTasks(demoUser1Id, demoUser2Id);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Ensures user has a config with the collaborator, and resets specific flags.
|
|
46
|
+
*
|
|
47
|
+
* @param ownerId The config owner
|
|
48
|
+
* @param collaboratorId The collaborator to include
|
|
49
|
+
*/
|
|
50
|
+
static async ensureCollaboratorsAndResetConfig(ownerId, collaboratorId) {
|
|
51
|
+
const cfgRepo = DashboardUserConfigRepository.getRepo();
|
|
52
|
+
let cfg = await cfgRepo.getForUser(ownerId);
|
|
53
|
+
let isNew = false;
|
|
54
|
+
if (!cfg) {
|
|
55
|
+
cfg = new DashboardUserConfig(ownerId);
|
|
56
|
+
isNew = true;
|
|
57
|
+
}
|
|
58
|
+
// Ensure collaborator and reset flags
|
|
59
|
+
cfg.collaborators = [collaboratorId];
|
|
60
|
+
cfg.enableDevMode = true;
|
|
61
|
+
cfg.enabledFeatures.useConfettiForTasks = true;
|
|
62
|
+
cfg.enabledFeatures.catImageOnHomePage = false;
|
|
63
|
+
// Reset tag settings and seed priorities for demo tags
|
|
64
|
+
cfg.tagSettings = {};
|
|
65
|
+
for (const [tag, priority] of Object.entries(this.TAG_PRIORITY)) {
|
|
66
|
+
cfg.tagSettings[tag] = { priority };
|
|
67
|
+
}
|
|
68
|
+
if (isNew) {
|
|
69
|
+
await cfgRepo.insertNew(cfg);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
await cfgRepo.update(cfg);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Deletes all tasks owned by the provided users. Children are also removed
|
|
77
|
+
* since they share the same owner.
|
|
78
|
+
*
|
|
79
|
+
* @param userIds The users to wipe tasks for
|
|
80
|
+
*/
|
|
81
|
+
static async wipeTasksForUsers(userIds) {
|
|
82
|
+
const taskRepo = DashboardTaskRepository.getRepo();
|
|
83
|
+
// Delete per-user using repo.deleteList to leverage child cleanup logic.
|
|
84
|
+
for (const userId of userIds) {
|
|
85
|
+
const allVisible = await taskRepo.getAllForUser(userId);
|
|
86
|
+
const owned = allVisible.filter((t) => t.userId.equals(userId));
|
|
87
|
+
if (owned.length === 0)
|
|
88
|
+
continue;
|
|
89
|
+
const ids = owned.map((t) => t._id);
|
|
90
|
+
await taskRepo.deleteList(ids);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Creates a task owned by the specified user. Because we wipe all tasks
|
|
95
|
+
* for the demo users prior to creation, we don't need to check for
|
|
96
|
+
* existing tasks and can always insert.
|
|
97
|
+
*
|
|
98
|
+
* @param ownerId The owning user ID
|
|
99
|
+
* @param title The task title
|
|
100
|
+
* @param opts Additional optional task properties
|
|
101
|
+
* @param opts.description Description text
|
|
102
|
+
* @param opts.completed Completion flag
|
|
103
|
+
* @param opts.parentTaskId Parent task reference for subtasks
|
|
104
|
+
* @param opts.sharedWith Users the task is shared with
|
|
105
|
+
* @param opts.assignedTo The assigned user
|
|
106
|
+
* @param opts.tags Tags for the owning user
|
|
107
|
+
* @param opts.startDate Optional start date
|
|
108
|
+
* @param opts.dueDate Optional due date
|
|
109
|
+
* @param opts.category System category
|
|
110
|
+
*/
|
|
111
|
+
static async createTask(ownerId, title, opts) {
|
|
112
|
+
const taskRepo = DashboardTaskRepository.getRepo();
|
|
113
|
+
const task = new DashboardTask(ownerId);
|
|
114
|
+
task.title = title;
|
|
115
|
+
if (opts?.description)
|
|
116
|
+
task.description = opts.description;
|
|
117
|
+
if (opts?.completed !== undefined)
|
|
118
|
+
task.completed = opts.completed;
|
|
119
|
+
if (opts?.parentTaskId)
|
|
120
|
+
task.parentTaskId = opts.parentTaskId;
|
|
121
|
+
if (opts?.sharedWith)
|
|
122
|
+
task.sharedWith = opts.sharedWith;
|
|
123
|
+
if (opts?.assignedTo)
|
|
124
|
+
task.assignedTo = opts.assignedTo;
|
|
125
|
+
if (opts?.category)
|
|
126
|
+
task.category = opts.category;
|
|
127
|
+
if (opts?.startDate)
|
|
128
|
+
task.startDate = opts.startDate;
|
|
129
|
+
if (opts?.dueDate)
|
|
130
|
+
task.dueDate = opts.dueDate;
|
|
131
|
+
task.tags[ownerId.toString()] = opts?.tags ?? [];
|
|
132
|
+
const inserted = await taskRepo.insertNew(task);
|
|
133
|
+
return inserted ?? task;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Creates shared demo tasks visible to both users exactly once to avoid duplicates.
|
|
137
|
+
*
|
|
138
|
+
* @param user1Id The primary owner of some shared tasks
|
|
139
|
+
* @param user2Id The collaborator for shared tasks
|
|
140
|
+
*/
|
|
141
|
+
static async createExampleTasks(user1Id, user2Id) {
|
|
142
|
+
// Shared parent task (owned by user1, shared with user2)
|
|
143
|
+
const parent = await this.createTask(user1Id, 'Plan weekend trip', {
|
|
144
|
+
description: 'Decide destination and plan activities for the weekend.',
|
|
145
|
+
sharedWith: [user2Id],
|
|
146
|
+
tags: ['planning', 'fun']
|
|
147
|
+
});
|
|
148
|
+
const child1 = await this.createTask(user1Id, 'Book hotel', {
|
|
149
|
+
parentTaskId: parent._id,
|
|
150
|
+
tags: ['booking']
|
|
151
|
+
});
|
|
152
|
+
await this.createTask(user1Id, 'Create itinerary', {
|
|
153
|
+
parentTaskId: parent._id,
|
|
154
|
+
tags: ['planning']
|
|
155
|
+
});
|
|
156
|
+
await this.createTask(user1Id, 'Pack bags', { parentTaskId: parent._id });
|
|
157
|
+
await this.createTask(user1Id, 'Buy snacks', {
|
|
158
|
+
parentTaskId: child1._id,
|
|
159
|
+
completed: true,
|
|
160
|
+
tags: ['food']
|
|
161
|
+
});
|
|
162
|
+
// Shared task assigned to user2 (owned by user1)
|
|
163
|
+
await this.createTask(user1Id, 'Buy groceries for BBQ', {
|
|
164
|
+
sharedWith: [user2Id],
|
|
165
|
+
assignedTo: user2Id,
|
|
166
|
+
tags: ['home', 'bbq']
|
|
167
|
+
});
|
|
168
|
+
// A shared planning task owned by user2
|
|
169
|
+
await this.createTask(user2Id, 'Plan potluck dinner', {
|
|
170
|
+
sharedWith: [user1Id],
|
|
171
|
+
assignedTo: user1Id,
|
|
172
|
+
tags: ['food', 'planning']
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Creates non-shared demo tasks for each user.
|
|
177
|
+
*
|
|
178
|
+
* @param user1Id The first user
|
|
179
|
+
* @param user2Id The second user
|
|
180
|
+
*/
|
|
181
|
+
static async createNonSharedTasks(user1Id, user2Id) {
|
|
182
|
+
const now = new Date();
|
|
183
|
+
const futureDue = new Date(now.getTime());
|
|
184
|
+
futureDue.setMonth(futureDue.getMonth() + 4);
|
|
185
|
+
const pastDue = new Date(now.getTime());
|
|
186
|
+
const pastDueStart = new Date(now.getTime());
|
|
187
|
+
pastDue.setDate(pastDue.getDate() - 7);
|
|
188
|
+
pastDueStart.setDate(pastDueStart.getDate() - 14);
|
|
189
|
+
// User 1: A completed solo task
|
|
190
|
+
await this.createTask(user1Id, 'Renew car registration', {
|
|
191
|
+
completed: true,
|
|
192
|
+
tags: ['admin']
|
|
193
|
+
});
|
|
194
|
+
// User 2: Own parent task with subtasks (not shared)
|
|
195
|
+
const u2Parent = await this.createTask(user2Id, 'Home improvement project', {
|
|
196
|
+
description: 'Small updates around the house.',
|
|
197
|
+
tags: ['home']
|
|
198
|
+
});
|
|
199
|
+
await this.createTask(user2Id, 'Paint living room walls', {
|
|
200
|
+
parentTaskId: u2Parent._id,
|
|
201
|
+
completed: true,
|
|
202
|
+
tags: ['paint']
|
|
203
|
+
});
|
|
204
|
+
await this.createTask(user2Id, 'Replace light fixtures', {
|
|
205
|
+
parentTaskId: u2Parent._id,
|
|
206
|
+
tags: ['electric']
|
|
207
|
+
});
|
|
208
|
+
// Root task with a future due date (>= 4 months out)
|
|
209
|
+
await this.createTask(user1Id, 'Schedule annual physical', {
|
|
210
|
+
description: 'Book an appointment and add to calendar.',
|
|
211
|
+
dueDate: futureDue,
|
|
212
|
+
tags: ['admin']
|
|
213
|
+
});
|
|
214
|
+
await this.createTask(user2Id, 'Schedule annual physical', {
|
|
215
|
+
description: 'Book an appointment and add to calendar.',
|
|
216
|
+
dueDate: futureDue,
|
|
217
|
+
tags: ['admin']
|
|
218
|
+
});
|
|
219
|
+
// Past-due task
|
|
220
|
+
await this.createTask(user1Id, 'Submit expense report', {
|
|
221
|
+
description: 'Collect receipts and submit to finance.',
|
|
222
|
+
startDate: pastDueStart,
|
|
223
|
+
dueDate: pastDue,
|
|
224
|
+
tags: ['admin']
|
|
225
|
+
});
|
|
226
|
+
await this.createTask(user2Id, 'Submit expense report', {
|
|
227
|
+
description: 'Collect receipts and submit to finance.',
|
|
228
|
+
startDate: pastDueStart,
|
|
229
|
+
dueDate: pastDue,
|
|
230
|
+
tags: ['admin']
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=DashboardDemoAccountsService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DashboardDemoAccountsService.js","sourceRoot":"","sources":["../../../src/services/DemoAccountsService/DashboardDemoAccountsService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE9E,OAAO,uBAAuB,MAAM,yDAAyD,CAAC;AAC9F,OAAO,6BAA6B,MAAM,+DAA+D,CAAC;AAE1G;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,4BAA4B;IAC/C;;;OAGG;IACK,MAAM,CAAU,YAAY,GAA2B;QAC7D,QAAQ,EAAE,CAAC;QACX,GAAG,EAAE,CAAC;QACN,OAAO,EAAE,CAAC;QACV,IAAI,EAAE,CAAC;QACP,IAAI,EAAE,CAAC;QACP,GAAG,EAAE,CAAC;QACN,KAAK,EAAE,CAAC;QACR,KAAK,EAAE,CAAC;QACR,QAAQ,EAAE,CAAC;KACZ,CAAC;IAEF;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,WAAqB,EAAE,WAAqB;QACxE,MAAM,IAAI,CAAC,iCAAiC,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QACvE,MAAM,IAAI,CAAC,iCAAiC,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QAEvE,MAAM,IAAI,CAAC,iBAAiB,CAAC,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC;QAEzD,2DAA2D;QAC3D,MAAM,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QACxD,wCAAwC;QACxC,MAAM,IAAI,CAAC,oBAAoB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IAC5D,CAAC;IAED;;;;;OAKG;IACK,MAAM,CAAC,KAAK,CAAC,iCAAiC,CACpD,OAAiB,EACjB,cAAwB;QAExB,MAAM,OAAO,GAAG,6BAA6B,CAAC,OAAO,EAAE,CAAC;QACxD,IAAI,GAAG,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAC5C,IAAI,KAAK,GAAG,KAAK,CAAC;QAClB,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,GAAG,GAAG,IAAI,mBAAmB,CAAC,OAAO,CAAC,CAAC;YACvC,KAAK,GAAG,IAAI,CAAC;QACf,CAAC;QACD,sCAAsC;QACtC,GAAG,CAAC,aAAa,GAAG,CAAC,cAAc,CAAC,CAAC;QACrC,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC;QACzB,GAAG,CAAC,eAAe,CAAC,mBAAmB,GAAG,IAAI,CAAC;QAC/C,GAAG,CAAC,eAAe,CAAC,kBAAkB,GAAG,KAAK,CAAC;QAC/C,uDAAuD;QACvD,GAAG,CAAC,WAAW,GAAG,EAAE,CAAC;QACrB,KAAK,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;YAChE,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC;QACtC,CAAC;QACD,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAC/B,CAAC;aAAM,CAAC;YACN,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACK,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,OAAmB;QACxD,MAAM,QAAQ,GAAG,uBAAuB,CAAC,OAAO,EAAE,CAAC;QACnD,yEAAyE;QACzE,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;YACxD,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;YAChE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAS;YACjC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACpC,MAAM,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACK,MAAM,CAAC,KAAK,CAAC,UAAU,CAC7B,OAAiB,EACjB,KAAa,EACb,IAUC;QAED,MAAM,QAAQ,GAAG,uBAAuB,CAAC,OAAO,EAAE,CAAC;QACnD,MAAM,IAAI,GAAG,IAAI,aAAa,CAAC,OAAO,CAAC,CAAC;QACxC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,IAAI,EAAE,WAAW;YAAE,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;QAC3D,IAAI,IAAI,EAAE,SAAS,KAAK,SAAS;YAAE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QACnE,IAAI,IAAI,EAAE,YAAY;YAAE,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;QAC9D,IAAI,IAAI,EAAE,UAAU;YAAE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QACxD,IAAI,IAAI,EAAE,UAAU;YAAE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QACxD,IAAI,IAAI,EAAE,QAAQ;YAAE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAClD,IAAI,IAAI,EAAE,SAAS;YAAE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QACrD,IAAI,IAAI,EAAE,OAAO;YAAE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC/C,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC;QAEjD,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAChD,OAAO,QAAQ,IAAI,IAAI,CAAC;IAC1B,CAAC;IAED;;;;;OAKG;IACK,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,OAAiB,EAAE,OAAiB;QAC1E,yDAAyD;QACzD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,mBAAmB,EAAE;YACjE,WAAW,EAAE,yDAAyD;YACtE,UAAU,EAAE,CAAC,OAAO,CAAC;YACrB,IAAI,EAAE,CAAC,UAAU,EAAE,KAAK,CAAC;SAC1B,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,YAAY,EAAE;YAC1D,YAAY,EAAE,MAAM,CAAC,GAAG;YACxB,IAAI,EAAE,CAAC,SAAS,CAAC;SAClB,CAAC,CAAC;QACH,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,kBAAkB,EAAE;YACjD,YAAY,EAAE,MAAM,CAAC,GAAG;YACxB,IAAI,EAAE,CAAC,UAAU,CAAC;SACnB,CAAC,CAAC;QACH,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,YAAY,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;QAC1E,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,YAAY,EAAE;YAC3C,YAAY,EAAE,MAAM,CAAC,GAAG;YACxB,SAAS,EAAE,IAAI;YACf,IAAI,EAAE,CAAC,MAAM,CAAC;SACf,CAAC,CAAC;QAEH,iDAAiD;QACjD,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,uBAAuB,EAAE;YACtD,UAAU,EAAE,CAAC,OAAO,CAAC;YACrB,UAAU,EAAE,OAAO;YACnB,IAAI,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC;SACtB,CAAC,CAAC;QAEH,wCAAwC;QACxC,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,qBAAqB,EAAE;YACpD,UAAU,EAAE,CAAC,OAAO,CAAC;YACrB,UAAU,EAAE,OAAO;YACnB,IAAI,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC;SAC3B,CAAC,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACK,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,OAAiB,EAAE,OAAiB;QAC5E,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1C,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC;QAC7C,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACxC,MAAM,YAAY,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7C,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QACvC,YAAY,CAAC,OAAO,CAAC,YAAY,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;QAElD,gCAAgC;QAChC,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,wBAAwB,EAAE;YACvD,SAAS,EAAE,IAAI;YACf,IAAI,EAAE,CAAC,OAAO,CAAC;SAChB,CAAC,CAAC;QAEH,qDAAqD;QACrD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,0BAA0B,EAAE;YAC1E,WAAW,EAAE,iCAAiC;YAC9C,IAAI,EAAE,CAAC,MAAM,CAAC;SACf,CAAC,CAAC;QACH,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,yBAAyB,EAAE;YACxD,YAAY,EAAE,QAAQ,CAAC,GAAG;YAC1B,SAAS,EAAE,IAAI;YACf,IAAI,EAAE,CAAC,OAAO,CAAC;SAChB,CAAC,CAAC;QACH,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,wBAAwB,EAAE;YACvD,YAAY,EAAE,QAAQ,CAAC,GAAG;YAC1B,IAAI,EAAE,CAAC,UAAU,CAAC;SACnB,CAAC,CAAC;QAEH,qDAAqD;QACrD,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,0BAA0B,EAAE;YACzD,WAAW,EAAE,0CAA0C;YACvD,OAAO,EAAE,SAAS;YAClB,IAAI,EAAE,CAAC,OAAO,CAAC;SAChB,CAAC,CAAC;QACH,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,0BAA0B,EAAE;YACzD,WAAW,EAAE,0CAA0C;YACvD,OAAO,EAAE,SAAS;YAClB,IAAI,EAAE,CAAC,OAAO,CAAC;SAChB,CAAC,CAAC;QAEH,gBAAgB;QAChB,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,uBAAuB,EAAE;YACtD,WAAW,EAAE,yCAAyC;YACtD,SAAS,EAAE,YAAY;YACvB,OAAO,EAAE,OAAO;YAChB,IAAI,EAAE,CAAC,OAAO,CAAC;SAChB,CAAC,CAAC;QACH,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,uBAAuB,EAAE;YACtD,WAAW,EAAE,yCAAyC;YACtD,SAAS,EAAE,YAAY;YACvB,OAAO,EAAE,OAAO;YAChB,IAAI,EAAE,CAAC,OAAO,CAAC;SAChB,CAAC,CAAC;IACL,CAAC"}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { DashboardTask, DashboardUserConfig } from '@aneuhold/core-ts-db-lib';
|
|
2
|
+
import { ObjectId } from 'bson';
|
|
3
|
+
import DashboardTaskRepository from '../../repositories/dashboard/DashboardTaskRepository.js';
|
|
4
|
+
import DashboardUserConfigRepository from '../../repositories/dashboard/DashboardUserConfigRepository.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Dashboard-specific demo seeding utilities.
|
|
8
|
+
*/
|
|
9
|
+
export default class DashboardDemoAccountsService {
|
|
10
|
+
/**
|
|
11
|
+
* Default priorities for known demo tags. If a tag is not listed here,
|
|
12
|
+
* a fallback priority will be used.
|
|
13
|
+
*/
|
|
14
|
+
private static readonly TAG_PRIORITY: Record<string, number> = {
|
|
15
|
+
planning: 9,
|
|
16
|
+
fun: 8,
|
|
17
|
+
booking: 7,
|
|
18
|
+
food: 6,
|
|
19
|
+
home: 5,
|
|
20
|
+
bbq: 4,
|
|
21
|
+
admin: 3,
|
|
22
|
+
paint: 2,
|
|
23
|
+
electric: 1
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Seeds the dashboard demo data for two users. This will:
|
|
28
|
+
* - Ensure both users have configs and are collaborators of each other
|
|
29
|
+
* - Reset select config flags (enableDevMode, useConfettiForTasks, catImageOnHomePage)
|
|
30
|
+
* - Wipe all tasks owned by either user
|
|
31
|
+
* - Create example tasks (shared, nested, completed, with tags)
|
|
32
|
+
*
|
|
33
|
+
* Safe to re-run; will produce the same end state.
|
|
34
|
+
*
|
|
35
|
+
* @param demoUser1Id The first user
|
|
36
|
+
* @param demoUser2Id The second user
|
|
37
|
+
*/
|
|
38
|
+
static async seedDemoAccounts(demoUser1Id: ObjectId, demoUser2Id: ObjectId): Promise<void> {
|
|
39
|
+
await this.ensureCollaboratorsAndResetConfig(demoUser1Id, demoUser2Id);
|
|
40
|
+
await this.ensureCollaboratorsAndResetConfig(demoUser2Id, demoUser1Id);
|
|
41
|
+
|
|
42
|
+
await this.wipeTasksForUsers([demoUser1Id, demoUser2Id]);
|
|
43
|
+
|
|
44
|
+
// Create shared tasks (visible to both users) exactly once
|
|
45
|
+
await this.createExampleTasks(demoUser1Id, demoUser2Id);
|
|
46
|
+
// Create non-shared tasks for each user
|
|
47
|
+
await this.createNonSharedTasks(demoUser1Id, demoUser2Id);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Ensures user has a config with the collaborator, and resets specific flags.
|
|
52
|
+
*
|
|
53
|
+
* @param ownerId The config owner
|
|
54
|
+
* @param collaboratorId The collaborator to include
|
|
55
|
+
*/
|
|
56
|
+
private static async ensureCollaboratorsAndResetConfig(
|
|
57
|
+
ownerId: ObjectId,
|
|
58
|
+
collaboratorId: ObjectId
|
|
59
|
+
): Promise<void> {
|
|
60
|
+
const cfgRepo = DashboardUserConfigRepository.getRepo();
|
|
61
|
+
let cfg = await cfgRepo.getForUser(ownerId);
|
|
62
|
+
let isNew = false;
|
|
63
|
+
if (!cfg) {
|
|
64
|
+
cfg = new DashboardUserConfig(ownerId);
|
|
65
|
+
isNew = true;
|
|
66
|
+
}
|
|
67
|
+
// Ensure collaborator and reset flags
|
|
68
|
+
cfg.collaborators = [collaboratorId];
|
|
69
|
+
cfg.enableDevMode = true;
|
|
70
|
+
cfg.enabledFeatures.useConfettiForTasks = true;
|
|
71
|
+
cfg.enabledFeatures.catImageOnHomePage = false;
|
|
72
|
+
// Reset tag settings and seed priorities for demo tags
|
|
73
|
+
cfg.tagSettings = {};
|
|
74
|
+
for (const [tag, priority] of Object.entries(this.TAG_PRIORITY)) {
|
|
75
|
+
cfg.tagSettings[tag] = { priority };
|
|
76
|
+
}
|
|
77
|
+
if (isNew) {
|
|
78
|
+
await cfgRepo.insertNew(cfg);
|
|
79
|
+
} else {
|
|
80
|
+
await cfgRepo.update(cfg);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Deletes all tasks owned by the provided users. Children are also removed
|
|
86
|
+
* since they share the same owner.
|
|
87
|
+
*
|
|
88
|
+
* @param userIds The users to wipe tasks for
|
|
89
|
+
*/
|
|
90
|
+
private static async wipeTasksForUsers(userIds: ObjectId[]): Promise<void> {
|
|
91
|
+
const taskRepo = DashboardTaskRepository.getRepo();
|
|
92
|
+
// Delete per-user using repo.deleteList to leverage child cleanup logic.
|
|
93
|
+
for (const userId of userIds) {
|
|
94
|
+
const allVisible = await taskRepo.getAllForUser(userId);
|
|
95
|
+
const owned = allVisible.filter((t) => t.userId.equals(userId));
|
|
96
|
+
if (owned.length === 0) continue;
|
|
97
|
+
const ids = owned.map((t) => t._id);
|
|
98
|
+
await taskRepo.deleteList(ids);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Creates a task owned by the specified user. Because we wipe all tasks
|
|
104
|
+
* for the demo users prior to creation, we don't need to check for
|
|
105
|
+
* existing tasks and can always insert.
|
|
106
|
+
*
|
|
107
|
+
* @param ownerId The owning user ID
|
|
108
|
+
* @param title The task title
|
|
109
|
+
* @param opts Additional optional task properties
|
|
110
|
+
* @param opts.description Description text
|
|
111
|
+
* @param opts.completed Completion flag
|
|
112
|
+
* @param opts.parentTaskId Parent task reference for subtasks
|
|
113
|
+
* @param opts.sharedWith Users the task is shared with
|
|
114
|
+
* @param opts.assignedTo The assigned user
|
|
115
|
+
* @param opts.tags Tags for the owning user
|
|
116
|
+
* @param opts.startDate Optional start date
|
|
117
|
+
* @param opts.dueDate Optional due date
|
|
118
|
+
* @param opts.category System category
|
|
119
|
+
*/
|
|
120
|
+
private static async createTask(
|
|
121
|
+
ownerId: ObjectId,
|
|
122
|
+
title: string,
|
|
123
|
+
opts?: {
|
|
124
|
+
description?: string;
|
|
125
|
+
completed?: boolean;
|
|
126
|
+
parentTaskId?: ObjectId;
|
|
127
|
+
sharedWith?: ObjectId[];
|
|
128
|
+
assignedTo?: ObjectId;
|
|
129
|
+
tags?: string[];
|
|
130
|
+
startDate?: Date;
|
|
131
|
+
dueDate?: Date;
|
|
132
|
+
category?: string;
|
|
133
|
+
}
|
|
134
|
+
): Promise<DashboardTask> {
|
|
135
|
+
const taskRepo = DashboardTaskRepository.getRepo();
|
|
136
|
+
const task = new DashboardTask(ownerId);
|
|
137
|
+
task.title = title;
|
|
138
|
+
if (opts?.description) task.description = opts.description;
|
|
139
|
+
if (opts?.completed !== undefined) task.completed = opts.completed;
|
|
140
|
+
if (opts?.parentTaskId) task.parentTaskId = opts.parentTaskId;
|
|
141
|
+
if (opts?.sharedWith) task.sharedWith = opts.sharedWith;
|
|
142
|
+
if (opts?.assignedTo) task.assignedTo = opts.assignedTo;
|
|
143
|
+
if (opts?.category) task.category = opts.category;
|
|
144
|
+
if (opts?.startDate) task.startDate = opts.startDate;
|
|
145
|
+
if (opts?.dueDate) task.dueDate = opts.dueDate;
|
|
146
|
+
task.tags[ownerId.toString()] = opts?.tags ?? [];
|
|
147
|
+
|
|
148
|
+
const inserted = await taskRepo.insertNew(task);
|
|
149
|
+
return inserted ?? task;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Creates shared demo tasks visible to both users exactly once to avoid duplicates.
|
|
154
|
+
*
|
|
155
|
+
* @param user1Id The primary owner of some shared tasks
|
|
156
|
+
* @param user2Id The collaborator for shared tasks
|
|
157
|
+
*/
|
|
158
|
+
private static async createExampleTasks(user1Id: ObjectId, user2Id: ObjectId) {
|
|
159
|
+
// Shared parent task (owned by user1, shared with user2)
|
|
160
|
+
const parent = await this.createTask(user1Id, 'Plan weekend trip', {
|
|
161
|
+
description: 'Decide destination and plan activities for the weekend.',
|
|
162
|
+
sharedWith: [user2Id],
|
|
163
|
+
tags: ['planning', 'fun']
|
|
164
|
+
});
|
|
165
|
+
const child1 = await this.createTask(user1Id, 'Book hotel', {
|
|
166
|
+
parentTaskId: parent._id,
|
|
167
|
+
tags: ['booking']
|
|
168
|
+
});
|
|
169
|
+
await this.createTask(user1Id, 'Create itinerary', {
|
|
170
|
+
parentTaskId: parent._id,
|
|
171
|
+
tags: ['planning']
|
|
172
|
+
});
|
|
173
|
+
await this.createTask(user1Id, 'Pack bags', { parentTaskId: parent._id });
|
|
174
|
+
await this.createTask(user1Id, 'Buy snacks', {
|
|
175
|
+
parentTaskId: child1._id,
|
|
176
|
+
completed: true,
|
|
177
|
+
tags: ['food']
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// Shared task assigned to user2 (owned by user1)
|
|
181
|
+
await this.createTask(user1Id, 'Buy groceries for BBQ', {
|
|
182
|
+
sharedWith: [user2Id],
|
|
183
|
+
assignedTo: user2Id,
|
|
184
|
+
tags: ['home', 'bbq']
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// A shared planning task owned by user2
|
|
188
|
+
await this.createTask(user2Id, 'Plan potluck dinner', {
|
|
189
|
+
sharedWith: [user1Id],
|
|
190
|
+
assignedTo: user1Id,
|
|
191
|
+
tags: ['food', 'planning']
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Creates non-shared demo tasks for each user.
|
|
197
|
+
*
|
|
198
|
+
* @param user1Id The first user
|
|
199
|
+
* @param user2Id The second user
|
|
200
|
+
*/
|
|
201
|
+
private static async createNonSharedTasks(user1Id: ObjectId, user2Id: ObjectId) {
|
|
202
|
+
const now = new Date();
|
|
203
|
+
const futureDue = new Date(now.getTime());
|
|
204
|
+
futureDue.setMonth(futureDue.getMonth() + 4);
|
|
205
|
+
const pastDue = new Date(now.getTime());
|
|
206
|
+
const pastDueStart = new Date(now.getTime());
|
|
207
|
+
pastDue.setDate(pastDue.getDate() - 7);
|
|
208
|
+
pastDueStart.setDate(pastDueStart.getDate() - 14);
|
|
209
|
+
|
|
210
|
+
// User 1: A completed solo task
|
|
211
|
+
await this.createTask(user1Id, 'Renew car registration', {
|
|
212
|
+
completed: true,
|
|
213
|
+
tags: ['admin']
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// User 2: Own parent task with subtasks (not shared)
|
|
217
|
+
const u2Parent = await this.createTask(user2Id, 'Home improvement project', {
|
|
218
|
+
description: 'Small updates around the house.',
|
|
219
|
+
tags: ['home']
|
|
220
|
+
});
|
|
221
|
+
await this.createTask(user2Id, 'Paint living room walls', {
|
|
222
|
+
parentTaskId: u2Parent._id,
|
|
223
|
+
completed: true,
|
|
224
|
+
tags: ['paint']
|
|
225
|
+
});
|
|
226
|
+
await this.createTask(user2Id, 'Replace light fixtures', {
|
|
227
|
+
parentTaskId: u2Parent._id,
|
|
228
|
+
tags: ['electric']
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// Root task with a future due date (>= 4 months out)
|
|
232
|
+
await this.createTask(user1Id, 'Schedule annual physical', {
|
|
233
|
+
description: 'Book an appointment and add to calendar.',
|
|
234
|
+
dueDate: futureDue,
|
|
235
|
+
tags: ['admin']
|
|
236
|
+
});
|
|
237
|
+
await this.createTask(user2Id, 'Schedule annual physical', {
|
|
238
|
+
description: 'Book an appointment and add to calendar.',
|
|
239
|
+
dueDate: futureDue,
|
|
240
|
+
tags: ['admin']
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
// Past-due task
|
|
244
|
+
await this.createTask(user1Id, 'Submit expense report', {
|
|
245
|
+
description: 'Collect receipts and submit to finance.',
|
|
246
|
+
startDate: pastDueStart,
|
|
247
|
+
dueDate: pastDue,
|
|
248
|
+
tags: ['admin']
|
|
249
|
+
});
|
|
250
|
+
await this.createTask(user2Id, 'Submit expense report', {
|
|
251
|
+
description: 'Collect receipts and submit to finance.',
|
|
252
|
+
startDate: pastDueStart,
|
|
253
|
+
dueDate: pastDue,
|
|
254
|
+
tags: ['admin']
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ObjectId } from 'bson';
|
|
2
|
+
/**
|
|
3
|
+
* Entry point for seeding demo accounts across projects.
|
|
4
|
+
*
|
|
5
|
+
* This class exposes static helpers that delegate to project-specific
|
|
6
|
+
* implementations (e.g., dashboard).
|
|
7
|
+
*/
|
|
8
|
+
export default class DemoAccountsService {
|
|
9
|
+
/**
|
|
10
|
+
* Seeds demo accounts for the Dashboard project only.
|
|
11
|
+
*
|
|
12
|
+
* @param demoUser1Id The first demo user ID
|
|
13
|
+
* @param demoUser2Id The second demo user ID
|
|
14
|
+
*/
|
|
15
|
+
static seedDashboardDemoAccounts(demoUser1Id: ObjectId, demoUser2Id: ObjectId): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=DemoAccountsService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DemoAccountsService.d.ts","sourceRoot":"","sources":["../../../src/services/DemoAccountsService/DemoAccountsService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAGhC;;;;;GAKG;AACH,MAAM,CAAC,OAAO,OAAO,mBAAmB;IACtC;;;;;OAKG;WACU,yBAAyB,CACpC,WAAW,EAAE,QAAQ,EACrB,WAAW,EAAE,QAAQ,GACpB,OAAO,CAAC,IAAI,CAAC;CAGjB"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import DashboardDemoAccountsService from './DashboardDemoAccountsService.js';
|
|
2
|
+
/**
|
|
3
|
+
* Entry point for seeding demo accounts across projects.
|
|
4
|
+
*
|
|
5
|
+
* This class exposes static helpers that delegate to project-specific
|
|
6
|
+
* implementations (e.g., dashboard).
|
|
7
|
+
*/
|
|
8
|
+
export default class DemoAccountsService {
|
|
9
|
+
/**
|
|
10
|
+
* Seeds demo accounts for the Dashboard project only.
|
|
11
|
+
*
|
|
12
|
+
* @param demoUser1Id The first demo user ID
|
|
13
|
+
* @param demoUser2Id The second demo user ID
|
|
14
|
+
*/
|
|
15
|
+
static async seedDashboardDemoAccounts(demoUser1Id, demoUser2Id) {
|
|
16
|
+
await DashboardDemoAccountsService.seedDemoAccounts(demoUser1Id, demoUser2Id);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=DemoAccountsService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DemoAccountsService.js","sourceRoot":"","sources":["../../../src/services/DemoAccountsService/DemoAccountsService.ts"],"names":[],"mappings":"AACA,OAAO,4BAA4B,MAAM,mCAAmC,CAAC;AAE7E;;;;;GAKG;AACH,MAAM,CAAC,OAAO,OAAO,mBAAmB;IACtC;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAC,yBAAyB,CACpC,WAAqB,EACrB,WAAqB;QAErB,MAAM,4BAA4B,CAAC,gBAAgB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IAChF,CAAC;CACF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ObjectId } from 'bson';
|
|
2
|
+
import DashboardDemoAccountsService from './DashboardDemoAccountsService.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Entry point for seeding demo accounts across projects.
|
|
6
|
+
*
|
|
7
|
+
* This class exposes static helpers that delegate to project-specific
|
|
8
|
+
* implementations (e.g., dashboard).
|
|
9
|
+
*/
|
|
10
|
+
export default class DemoAccountsService {
|
|
11
|
+
/**
|
|
12
|
+
* Seeds demo accounts for the Dashboard project only.
|
|
13
|
+
*
|
|
14
|
+
* @param demoUser1Id The first demo user ID
|
|
15
|
+
* @param demoUser2Id The second demo user ID
|
|
16
|
+
*/
|
|
17
|
+
static async seedDashboardDemoAccounts(
|
|
18
|
+
demoUser1Id: ObjectId,
|
|
19
|
+
demoUser2Id: ObjectId
|
|
20
|
+
): Promise<void> {
|
|
21
|
+
await DashboardDemoAccountsService.seedDemoAccounts(demoUser1Id, demoUser2Id);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/DemoAccountsService/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/DemoAccountsService/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as DemoAccountsService } from './DemoAccountsService.js';
|
package/lib/util/DocumentDb.d.ts
CHANGED
|
@@ -7,8 +7,24 @@ export default class DocumentDb {
|
|
|
7
7
|
private static DB_NAME;
|
|
8
8
|
private static mongoClient;
|
|
9
9
|
private static db;
|
|
10
|
+
/**
|
|
11
|
+
* Gets or creates the MongoDB client instance.
|
|
12
|
+
*
|
|
13
|
+
* @returns A promise that resolves to the MongoDB client.
|
|
14
|
+
*/
|
|
10
15
|
private static getClient;
|
|
16
|
+
/**
|
|
17
|
+
* Gets a MongoDB collection with the specified type.
|
|
18
|
+
*
|
|
19
|
+
* @param collectionName - The name of the collection to retrieve.
|
|
20
|
+
* @returns A promise that resolves to the typed MongoDB collection.
|
|
21
|
+
*/
|
|
11
22
|
static getCollection<TDocType extends Document>(collectionName: string): Promise<Collection<TDocType>>;
|
|
23
|
+
/**
|
|
24
|
+
* Closes the active MongoDB connection.
|
|
25
|
+
*
|
|
26
|
+
* @returns A promise that resolves when the connection is closed.
|
|
27
|
+
*/
|
|
12
28
|
static closeDbConnection(): Promise<void>;
|
|
13
29
|
}
|
|
14
30
|
//# sourceMappingURL=DocumentDb.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocumentDb.d.ts","sourceRoot":"","sources":["../../src/util/DocumentDb.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAChC,OAAO,EAAE,UAAU,EAAmB,MAAM,SAAS,CAAC;AAEtD;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,UAAU;IAC7B,OAAO,CAAC,MAAM,CAAC,OAAO,CAAa;IAEnC,OAAO,CAAC,MAAM,CAAC,WAAW,CAA0B;IAEpD,OAAO,CAAC,MAAM,CAAC,EAAE,CAAiB;
|
|
1
|
+
{"version":3,"file":"DocumentDb.d.ts","sourceRoot":"","sources":["../../src/util/DocumentDb.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAChC,OAAO,EAAE,UAAU,EAAmB,MAAM,SAAS,CAAC;AAEtD;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,UAAU;IAC7B,OAAO,CAAC,MAAM,CAAC,OAAO,CAAa;IAEnC,OAAO,CAAC,MAAM,CAAC,WAAW,CAA0B;IAEpD,OAAO,CAAC,MAAM,CAAC,EAAE,CAAiB;IAElC;;;;OAIG;mBACkB,SAAS;IAiB9B;;;;;OAKG;WACU,aAAa,CAAC,QAAQ,SAAS,QAAQ,EAClD,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IAQhC;;;;OAIG;WACU,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;CAKhD"}
|
package/lib/util/DocumentDb.js
CHANGED
|
@@ -7,6 +7,11 @@ export default class DocumentDb {
|
|
|
7
7
|
static DB_NAME = 'default';
|
|
8
8
|
static mongoClient;
|
|
9
9
|
static db;
|
|
10
|
+
/**
|
|
11
|
+
* Gets or creates the MongoDB client instance.
|
|
12
|
+
*
|
|
13
|
+
* @returns A promise that resolves to the MongoDB client.
|
|
14
|
+
*/
|
|
10
15
|
static async getClient() {
|
|
11
16
|
if (!ConfigService.isInitialized) {
|
|
12
17
|
// Hard-coded local for now until there are move envs.
|
|
@@ -23,6 +28,12 @@ export default class DocumentDb {
|
|
|
23
28
|
await this.mongoClient.connect();
|
|
24
29
|
return this.mongoClient;
|
|
25
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Gets a MongoDB collection with the specified type.
|
|
33
|
+
*
|
|
34
|
+
* @param collectionName - The name of the collection to retrieve.
|
|
35
|
+
* @returns A promise that resolves to the typed MongoDB collection.
|
|
36
|
+
*/
|
|
26
37
|
static async getCollection(collectionName) {
|
|
27
38
|
const client = await this.getClient();
|
|
28
39
|
if (!DocumentDb.db) {
|
|
@@ -30,6 +41,11 @@ export default class DocumentDb {
|
|
|
30
41
|
}
|
|
31
42
|
return DocumentDb.db.collection(collectionName);
|
|
32
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Closes the active MongoDB connection.
|
|
46
|
+
*
|
|
47
|
+
* @returns A promise that resolves when the connection is closed.
|
|
48
|
+
*/
|
|
33
49
|
static async closeDbConnection() {
|
|
34
50
|
if (DocumentDb.mongoClient) {
|
|
35
51
|
await DocumentDb.mongoClient.close();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocumentDb.js","sourceRoot":"","sources":["../../src/util/DocumentDb.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAAkB,WAAW,EAAE,MAAM,SAAS,CAAC;AAEtD;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,UAAU;IACrB,MAAM,CAAC,OAAO,GAAG,SAAS,CAAC;IAE3B,MAAM,CAAC,WAAW,CAA0B;IAE5C,MAAM,CAAC,EAAE,CAAiB;
|
|
1
|
+
{"version":3,"file":"DocumentDb.js","sourceRoot":"","sources":["../../src/util/DocumentDb.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAAkB,WAAW,EAAE,MAAM,SAAS,CAAC;AAEtD;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,UAAU;IACrB,MAAM,CAAC,OAAO,GAAG,SAAS,CAAC;IAE3B,MAAM,CAAC,WAAW,CAA0B;IAE5C,MAAM,CAAC,EAAE,CAAiB;IAElC;;;;OAIG;IACK,MAAM,CAAC,KAAK,CAAC,SAAS;QAC5B,IAAI,CAAC,aAAa,CAAC,aAAa,EAAE,CAAC;YACjC,sDAAsD;YACtD,MAAM,aAAa,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACzC,CAAC;QACD,MAAM,EAAE,MAAM,EAAE,GAAG,aAAa,CAAC;QACjC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,MAAM,uBAAuB,GAAG,iBAAiB,MAAM,CAAC,iBAAiB,IAAI,MAAM,CAAC,iBAAiB,IAAI,MAAM,CAAC,QAAQ,+BAA+B,CAAC;YACxJ,IAAI,CAAC,WAAW,GAAG,IAAI,WAAW,CAAC,uBAAuB,CAAC,CAAC;QAC9D,CAAC;QACD,uEAAuE;QACvE,mEAAmE;QACnE,aAAa;QACb,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAC,aAAa,CACxB,cAAsB;QAEtB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QACtC,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC;YACnB,UAAU,CAAC,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAChD,CAAC;QACD,OAAO,UAAU,CAAC,EAAE,CAAC,UAAU,CAAW,cAAc,CAAC,CAAC;IAC5D,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,KAAK,CAAC,iBAAiB;QAC5B,IAAI,UAAU,CAAC,WAAW,EAAE,CAAC;YAC3B,MAAM,UAAU,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;QACvC,CAAC;IACH,CAAC"}
|
package/lib/util/DocumentDb.ts
CHANGED
|
@@ -12,6 +12,11 @@ export default class DocumentDb {
|
|
|
12
12
|
|
|
13
13
|
private static db: Db | undefined;
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Gets or creates the MongoDB client instance.
|
|
17
|
+
*
|
|
18
|
+
* @returns A promise that resolves to the MongoDB client.
|
|
19
|
+
*/
|
|
15
20
|
private static async getClient(): Promise<MongoClient> {
|
|
16
21
|
if (!ConfigService.isInitialized) {
|
|
17
22
|
// Hard-coded local for now until there are move envs.
|
|
@@ -29,6 +34,12 @@ export default class DocumentDb {
|
|
|
29
34
|
return this.mongoClient;
|
|
30
35
|
}
|
|
31
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Gets a MongoDB collection with the specified type.
|
|
39
|
+
*
|
|
40
|
+
* @param collectionName - The name of the collection to retrieve.
|
|
41
|
+
* @returns A promise that resolves to the typed MongoDB collection.
|
|
42
|
+
*/
|
|
32
43
|
static async getCollection<TDocType extends Document>(
|
|
33
44
|
collectionName: string
|
|
34
45
|
): Promise<Collection<TDocType>> {
|
|
@@ -39,6 +50,11 @@ export default class DocumentDb {
|
|
|
39
50
|
return DocumentDb.db.collection<TDocType>(collectionName);
|
|
40
51
|
}
|
|
41
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Closes the active MongoDB connection.
|
|
55
|
+
*
|
|
56
|
+
* @returns A promise that resolves when the connection is closed.
|
|
57
|
+
*/
|
|
42
58
|
static async closeDbConnection(): Promise<void> {
|
|
43
59
|
if (DocumentDb.mongoClient) {
|
|
44
60
|
await DocumentDb.mongoClient.close();
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@aneuhold/be-ts-db-lib",
|
|
3
3
|
"author": "Anton G. Neuhold Jr.",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "2.0.
|
|
5
|
+
"version": "2.0.80",
|
|
6
6
|
"description": "A backend database library meant to actually interact with various databases in personal projects",
|
|
7
7
|
"packageManager": "pnpm@10.12.1",
|
|
8
8
|
"type": "module",
|