@datalayer/core 0.0.14 → 0.0.16
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/lib/components/checkout/StripeCheckout.js +19 -23
- package/lib/components/context/OrganizationSelect.js +12 -15
- package/lib/components/context/SpaceSelect.js +24 -25
- package/lib/hooks/useAuthorization.js +4 -2
- package/lib/hooks/useCache.d.ts +932 -285
- package/lib/hooks/useCache.js +5735 -2761
- package/lib/hooks/useCache0.d.ts +312 -0
- package/lib/hooks/useCache0.js +3189 -0
- package/lib/hooks/useIAM.js +18 -17
- package/lib/models/Runtime.d.ts +49 -49
- package/package.json +1 -1
- package/lib/sdk/index.d.ts +0 -27
- package/lib/sdk/index.js +0 -33
|
@@ -0,0 +1,3189 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/************************************
|
|
6
|
+
*
|
|
7
|
+
* DEPRECATED - use useCache instead.
|
|
8
|
+
*
|
|
9
|
+
***********************************/
|
|
10
|
+
import { URLExt } from '@jupyterlab/coreutils';
|
|
11
|
+
import { BOOTSTRAP_USER_ONBOARDING, LinkedInUser, asContact, asDatasource, asInbound, asInvite, asOrganization, asOutbound, asPage, asSecret, asSpace, asSurvey, asTeam, asToken, asUsage, asUser, } from '../models';
|
|
12
|
+
import { useCoreStore, useIAMStore } from '../state';
|
|
13
|
+
import { asDisplayName, namesAsInitials, asArray } from '../utils';
|
|
14
|
+
import { IAMProvidersSpecs } from '../models';
|
|
15
|
+
import { newUserMock } from './../mocks';
|
|
16
|
+
import { useDatalayer } from './useDatalayer';
|
|
17
|
+
import { useAuthorization } from './useAuthorization';
|
|
18
|
+
import { useUploadForm } from './useUpload';
|
|
19
|
+
import { OUTPUTSHOT_PLACEHOLDER_DEFAULT_SVG } from './assets';
|
|
20
|
+
const CONTACTS_BY_HANDLE = new Map();
|
|
21
|
+
const CONTACTS_BY_ID = new Map();
|
|
22
|
+
const COURSES_BY_ID = new Map();
|
|
23
|
+
const COURSES_ENROLLMENTS_BY_ID = new Map();
|
|
24
|
+
const COURSES_INSTRUCTORS_BY_ID = new Map();
|
|
25
|
+
const DATASOURCES_BY_ID = new Map();
|
|
26
|
+
const INBOUNDS_BY_HANDLE = new Map();
|
|
27
|
+
const INBOUNDS_BY_ID = new Map();
|
|
28
|
+
const INVITES_BY_TOKEN = new Map();
|
|
29
|
+
const ORGANISATIONS_BY_HANDLE = new Map();
|
|
30
|
+
const ORGANISATIONS_BY_ID = new Map();
|
|
31
|
+
const ORGANISATIONS_FOR_USER_BY_ID = new Map();
|
|
32
|
+
const OUTBOUNDS_BY_ID = new Map();
|
|
33
|
+
const PAGES_BY_ID = new Map();
|
|
34
|
+
const PUBLIC_COURSES_BY_ID = new Map();
|
|
35
|
+
const PUBLIC_ITEMS_BY_ID = new Map();
|
|
36
|
+
const SCHOOLS_BY_ID = new Map();
|
|
37
|
+
const SECRETS_BY_ID = new Map();
|
|
38
|
+
const SPACES_BY_HANDLE_BY_ORGANISATION_HANDLE = new Map();
|
|
39
|
+
const SPACES_BY_ID_BY_ORGANISATION_ID = new Map();
|
|
40
|
+
const SPACES_FOR_USER_BY_HANDLE = new Map();
|
|
41
|
+
const SPACES_FOR_USER_BY_ID = new Map();
|
|
42
|
+
const SPACE_ASSIGNMENTS_BY_ID = new Map();
|
|
43
|
+
const SPACE_CELLS_BY_ID = new Map();
|
|
44
|
+
const SPACE_DATASETS_BY_ID = new Map();
|
|
45
|
+
const SPACE_DOCUMENTS_BY_ID = new Map();
|
|
46
|
+
const SPACE_ENVIRONMENTS_BY_ID = new Map();
|
|
47
|
+
const SPACE_EXERCISES_BY_ID = new Map();
|
|
48
|
+
const SPACE_ITEMS_CACHE = new Map();
|
|
49
|
+
const SPACE_LESSONS_BY_ID = new Map();
|
|
50
|
+
const SPACE_NOTEBOOKS_BY_ID = new Map();
|
|
51
|
+
const STUDENTS_BY_ID = new Map();
|
|
52
|
+
const STUDENT_ASSIGNMENTS_BY_ID = new Map();
|
|
53
|
+
const TEAMS_BY_HANDLE = new Map();
|
|
54
|
+
const TEAMS_BY_ID = new Map();
|
|
55
|
+
const TEAMS_BY_ORGANIZATION_BY_ID = new Map();
|
|
56
|
+
const TOKENS_BY_ID = new Map();
|
|
57
|
+
const USERS_BY_HANDLE = new Map();
|
|
58
|
+
const USERS_BY_ID = new Map();
|
|
59
|
+
const DEFAULT_SEARCH_OPTS = {
|
|
60
|
+
q: '*',
|
|
61
|
+
types: ['page'],
|
|
62
|
+
max: 3,
|
|
63
|
+
public: true,
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Callbacks to Datalayer service.
|
|
67
|
+
*
|
|
68
|
+
* It assumes to be used within a {@link Router} component. If not
|
|
69
|
+
* you must set the options `loginRoute` to `null` (raise an error _Unauthorized_
|
|
70
|
+
* instead of redirecting to the login page).
|
|
71
|
+
*
|
|
72
|
+
* @deprecated use useCache instead.
|
|
73
|
+
*/
|
|
74
|
+
export const useCache0 = ({ loginRoute = '/login' } = {}) => {
|
|
75
|
+
const coreStore = useCoreStore();
|
|
76
|
+
const { configuration } = coreStore;
|
|
77
|
+
const { user } = useIAMStore();
|
|
78
|
+
const { requestDatalayer } = useDatalayer({ loginRoute });
|
|
79
|
+
const { checkIsOrganizationMember } = useAuthorization();
|
|
80
|
+
// Hook for notebook upload/creation
|
|
81
|
+
const { isLoading: notebookUploadLoading, uploadAndSubmit: uploadNotebook, progress: notebookUploadProgress, reset: resetNotebookUpload, } = useUploadForm(`${coreStore.configuration.spacerRunUrl}/api/spacer/v1/notebooks`);
|
|
82
|
+
// Caches -------------------------------------------------------------------
|
|
83
|
+
const clearAllCaches = () => {
|
|
84
|
+
CONTACTS_BY_HANDLE.clear();
|
|
85
|
+
CONTACTS_BY_ID.clear();
|
|
86
|
+
COURSES_BY_ID.clear();
|
|
87
|
+
COURSES_ENROLLMENTS_BY_ID.clear();
|
|
88
|
+
COURSES_INSTRUCTORS_BY_ID.clear();
|
|
89
|
+
DATASOURCES_BY_ID.clear();
|
|
90
|
+
INBOUNDS_BY_HANDLE.clear();
|
|
91
|
+
INBOUNDS_BY_ID.clear();
|
|
92
|
+
INVITES_BY_TOKEN.clear();
|
|
93
|
+
ORGANISATIONS_BY_HANDLE.clear();
|
|
94
|
+
ORGANISATIONS_BY_ID.clear();
|
|
95
|
+
ORGANISATIONS_FOR_USER_BY_ID.clear();
|
|
96
|
+
PAGES_BY_ID.clear();
|
|
97
|
+
OUTBOUNDS_BY_ID.clear();
|
|
98
|
+
PUBLIC_COURSES_BY_ID.clear();
|
|
99
|
+
PUBLIC_ITEMS_BY_ID.clear();
|
|
100
|
+
SCHOOLS_BY_ID.clear();
|
|
101
|
+
SECRETS_BY_ID.clear();
|
|
102
|
+
SPACES_BY_HANDLE_BY_ORGANISATION_HANDLE.clear();
|
|
103
|
+
SPACES_BY_ID_BY_ORGANISATION_ID.clear();
|
|
104
|
+
SPACES_FOR_USER_BY_HANDLE.clear();
|
|
105
|
+
SPACES_FOR_USER_BY_ID.clear();
|
|
106
|
+
SPACE_ASSIGNMENTS_BY_ID.clear();
|
|
107
|
+
SPACE_CELLS_BY_ID.clear();
|
|
108
|
+
SPACE_DATASETS_BY_ID.clear();
|
|
109
|
+
SPACE_DOCUMENTS_BY_ID.clear();
|
|
110
|
+
SPACE_ENVIRONMENTS_BY_ID.clear();
|
|
111
|
+
SPACE_EXERCISES_BY_ID.clear();
|
|
112
|
+
SPACE_ITEMS_CACHE.clear();
|
|
113
|
+
SPACE_LESSONS_BY_ID.clear();
|
|
114
|
+
SPACE_NOTEBOOKS_BY_ID.clear();
|
|
115
|
+
STUDENTS_BY_ID.clear();
|
|
116
|
+
STUDENT_ASSIGNMENTS_BY_ID.clear();
|
|
117
|
+
TOKENS_BY_ID.clear();
|
|
118
|
+
USERS_BY_HANDLE.clear();
|
|
119
|
+
USERS_BY_ID.clear();
|
|
120
|
+
};
|
|
121
|
+
const clearCachedItems = () => {
|
|
122
|
+
PUBLIC_ITEMS_BY_ID.clear();
|
|
123
|
+
SPACE_ASSIGNMENTS_BY_ID.clear();
|
|
124
|
+
SPACE_DATASETS_BY_ID.clear();
|
|
125
|
+
SPACE_DOCUMENTS_BY_ID.clear();
|
|
126
|
+
SPACE_ENVIRONMENTS_BY_ID.clear();
|
|
127
|
+
SPACE_EXERCISES_BY_ID.clear();
|
|
128
|
+
SPACE_ITEMS_CACHE.clear();
|
|
129
|
+
SPACE_ITEMS_CACHE.clear();
|
|
130
|
+
SPACE_LESSONS_BY_ID.clear();
|
|
131
|
+
SPACE_NOTEBOOKS_BY_ID.clear();
|
|
132
|
+
SPACE_CELLS_BY_ID.clear();
|
|
133
|
+
SPACE_CELLS_BY_ID.clear();
|
|
134
|
+
};
|
|
135
|
+
// Authentication ------------------------------------------------------------------
|
|
136
|
+
const login = (handle, password) => {
|
|
137
|
+
return requestDatalayer({
|
|
138
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/login`,
|
|
139
|
+
method: 'POST',
|
|
140
|
+
body: {
|
|
141
|
+
handle,
|
|
142
|
+
password,
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
};
|
|
146
|
+
const logout = () => {
|
|
147
|
+
clearAllCaches();
|
|
148
|
+
return requestDatalayer({
|
|
149
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/logout`,
|
|
150
|
+
method: 'GET',
|
|
151
|
+
});
|
|
152
|
+
};
|
|
153
|
+
// Join ------------------------------------------------------------------
|
|
154
|
+
const requestJoin = (handle, email, firstName, lastName, password, passwordConfirm) => {
|
|
155
|
+
return requestDatalayer({
|
|
156
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/join/request`,
|
|
157
|
+
method: 'POST',
|
|
158
|
+
body: {
|
|
159
|
+
handle,
|
|
160
|
+
email,
|
|
161
|
+
firstName,
|
|
162
|
+
lastName,
|
|
163
|
+
password,
|
|
164
|
+
passwordConfirm,
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
};
|
|
168
|
+
const requestJoinToken = (handle, email, firstName, lastName, password, passwordConfirm) => {
|
|
169
|
+
return requestDatalayer({
|
|
170
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/join/request/token`,
|
|
171
|
+
method: 'POST',
|
|
172
|
+
body: {
|
|
173
|
+
handle,
|
|
174
|
+
email,
|
|
175
|
+
firstName,
|
|
176
|
+
lastName,
|
|
177
|
+
password,
|
|
178
|
+
passwordConfirm,
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
};
|
|
182
|
+
const joinWithInvite = (formValues, token) => {
|
|
183
|
+
return requestDatalayer({
|
|
184
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/join/invites/token`,
|
|
185
|
+
method: 'POST',
|
|
186
|
+
body: {
|
|
187
|
+
...formValues,
|
|
188
|
+
token,
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
};
|
|
192
|
+
const confirmJoinWithToken = (userHandle, token) => {
|
|
193
|
+
return requestDatalayer({
|
|
194
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/join/users/${userHandle}/tokens/${token}`,
|
|
195
|
+
method: 'GET',
|
|
196
|
+
});
|
|
197
|
+
};
|
|
198
|
+
// Password ------------------------------------------------------------------
|
|
199
|
+
const changePassword = (handle, password, passwordConfirm) => {
|
|
200
|
+
return requestDatalayer({
|
|
201
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/password`,
|
|
202
|
+
method: 'PUT',
|
|
203
|
+
body: {
|
|
204
|
+
handle,
|
|
205
|
+
password,
|
|
206
|
+
passwordConfirm,
|
|
207
|
+
},
|
|
208
|
+
});
|
|
209
|
+
};
|
|
210
|
+
const createTokenForPasswordChange = (handle, password, passwordConfirm) => {
|
|
211
|
+
return requestDatalayer({
|
|
212
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/password/token`,
|
|
213
|
+
method: 'POST',
|
|
214
|
+
body: {
|
|
215
|
+
handle,
|
|
216
|
+
password,
|
|
217
|
+
passwordConfirm,
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
};
|
|
221
|
+
const confirmPassworkWithToken = (userHandle, token) => {
|
|
222
|
+
return requestDatalayer({
|
|
223
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/password/confirm/users/${userHandle}/tokens/${token}`,
|
|
224
|
+
method: 'PUT',
|
|
225
|
+
});
|
|
226
|
+
};
|
|
227
|
+
// OAuth2 -------------------------------------------------------------------
|
|
228
|
+
const getOAuth2AuthorizationURL = async (queryArgs) => {
|
|
229
|
+
return requestDatalayer({
|
|
230
|
+
url: URLExt.join(configuration.iamRunUrl, 'api/iam/v1/oauth2/authz/url') +
|
|
231
|
+
URLExt.objectToQueryString(queryArgs),
|
|
232
|
+
notifyOnError: false,
|
|
233
|
+
});
|
|
234
|
+
};
|
|
235
|
+
const getOAuth2AuthorizationLinkURL = async (queryArgs) => {
|
|
236
|
+
return requestDatalayer({
|
|
237
|
+
url: URLExt.join(configuration.iamRunUrl, 'api/iam/v1/oauth2/authz/url/link') + URLExt.objectToQueryString(queryArgs),
|
|
238
|
+
});
|
|
239
|
+
};
|
|
240
|
+
// IAM Providers ------------------------------------------------------------
|
|
241
|
+
const getGitHubProfile = async (accessToken) => {
|
|
242
|
+
return fetch(IAMProvidersSpecs.GitHub.userInfoURL, {
|
|
243
|
+
method: 'GET',
|
|
244
|
+
headers: {
|
|
245
|
+
Accept: 'application/vnd.github+json',
|
|
246
|
+
Authorization: `Bearer ${accessToken}`,
|
|
247
|
+
'X-GitHub-Api-Version': '2022-11-28',
|
|
248
|
+
},
|
|
249
|
+
}).then(resp => resp.json());
|
|
250
|
+
};
|
|
251
|
+
/*
|
|
252
|
+
* CORS is not supported @see https://github.com/linkedin-developers/linkedin-api-js-client
|
|
253
|
+
*/
|
|
254
|
+
const getLinkedinProfile = async (accessToken) => {
|
|
255
|
+
return proxyGET(IAMProvidersSpecs.LinkedIn.userInfoURL, accessToken).then(resp => {
|
|
256
|
+
return new LinkedInUser(resp.response);
|
|
257
|
+
});
|
|
258
|
+
};
|
|
259
|
+
const postLinkedinShare = async (linkedinUser, postText, accessToken) => {
|
|
260
|
+
const POST_SHARE_REQUEST = {
|
|
261
|
+
author: linkedinUser.getUrn(),
|
|
262
|
+
lifecycleState: 'PUBLISHED',
|
|
263
|
+
specificContent: {
|
|
264
|
+
'com.linkedin.ugc.ShareContent': {
|
|
265
|
+
shareCommentary: {
|
|
266
|
+
text: postText,
|
|
267
|
+
},
|
|
268
|
+
shareMediaCategory: 'NONE',
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
visibility: {
|
|
272
|
+
'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC',
|
|
273
|
+
},
|
|
274
|
+
};
|
|
275
|
+
return proxyPOST(IAMProvidersSpecs.LinkedIn.postShareURL, POST_SHARE_REQUEST, accessToken);
|
|
276
|
+
};
|
|
277
|
+
const postLinkedinShareWithUpload = async (linkedinUser, postText, uploadObject, accessToken) => {
|
|
278
|
+
const REGISTER_UPLOAD_REQUEST = {
|
|
279
|
+
registerUploadRequest: {
|
|
280
|
+
recipes: ['urn:li:digitalmediaRecipe:feedshare-image'],
|
|
281
|
+
owner: linkedinUser.getUrn(),
|
|
282
|
+
serviceRelationships: [
|
|
283
|
+
{
|
|
284
|
+
relationshipType: 'OWNER',
|
|
285
|
+
identifier: 'urn:li:userGeneratedContent',
|
|
286
|
+
},
|
|
287
|
+
],
|
|
288
|
+
},
|
|
289
|
+
};
|
|
290
|
+
return proxyPOST(IAMProvidersSpecs.LinkedIn.registerUploadURL, REGISTER_UPLOAD_REQUEST, accessToken).then(registerUploadReponse => {
|
|
291
|
+
/*
|
|
292
|
+
{
|
|
293
|
+
"value": {
|
|
294
|
+
"uploadMechanism": {
|
|
295
|
+
"com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest": {
|
|
296
|
+
"headers": {},
|
|
297
|
+
"uploadUrl": "https://api.linkedin.com/mediaUpload/C5522AQGTYER3k3ByHQ/feedshare-uploadedImage/0?ca=vector_feedshare&cn=uploads&m=AQJbrN86Zm265gAAAWemyz2pxPSgONtBiZdchrgG872QltnfYjnMdb2j3A&app=1953784&sync=0&v=beta&ut=2H-IhpbfXrRow1"
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
"mediaArtifact": "urn:li:digitalmediaMediaArtifact:(urn:li:digitalmediaAsset:C5522AQGTYER3k3ByHQ,urn:li:digitalmediaMediaArtifactClass:feedshare-uploadedImage)",
|
|
301
|
+
"asset": "urn:li:digitalmediaAsset:C5522AQGTYER3k3ByHQ"
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
*/
|
|
305
|
+
const asset = registerUploadReponse.response.value.asset;
|
|
306
|
+
const uploadURL = registerUploadReponse.response.value.uploadMechanism['com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest'].uploadUrl;
|
|
307
|
+
const UPLOAD_OBJECT_REQUEST = {
|
|
308
|
+
uploadURL: uploadURL,
|
|
309
|
+
content: uploadObject,
|
|
310
|
+
userURN: linkedinUser.getUrn(),
|
|
311
|
+
};
|
|
312
|
+
return proxyPUT(uploadURL, UPLOAD_OBJECT_REQUEST, accessToken).then(resp => {
|
|
313
|
+
const share = {
|
|
314
|
+
author: linkedinUser.getUrn(),
|
|
315
|
+
lifecycleState: 'PUBLISHED',
|
|
316
|
+
specificContent: {
|
|
317
|
+
'com.linkedin.ugc.ShareContent': {
|
|
318
|
+
shareCommentary: {
|
|
319
|
+
text: postText,
|
|
320
|
+
},
|
|
321
|
+
shareMediaCategory: 'IMAGE',
|
|
322
|
+
media: [
|
|
323
|
+
{
|
|
324
|
+
status: 'READY',
|
|
325
|
+
description: {
|
|
326
|
+
text: 'Datalayer Notebook',
|
|
327
|
+
},
|
|
328
|
+
media: asset,
|
|
329
|
+
title: {
|
|
330
|
+
text: 'Datalayer Notebook',
|
|
331
|
+
},
|
|
332
|
+
},
|
|
333
|
+
],
|
|
334
|
+
},
|
|
335
|
+
},
|
|
336
|
+
visibility: {
|
|
337
|
+
'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC',
|
|
338
|
+
},
|
|
339
|
+
};
|
|
340
|
+
return proxyPOST(IAMProvidersSpecs.LinkedIn.postShareURL, share, accessToken);
|
|
341
|
+
});
|
|
342
|
+
});
|
|
343
|
+
};
|
|
344
|
+
// Proxy -------------------------------------------------------------------
|
|
345
|
+
const proxyGET = async (url, token) => {
|
|
346
|
+
return requestDatalayer({
|
|
347
|
+
url: URLExt.join(configuration.iamRunUrl, 'api/iam/v1/proxy/request'),
|
|
348
|
+
method: 'POST',
|
|
349
|
+
body: {
|
|
350
|
+
request_method: 'GET',
|
|
351
|
+
request_url: url,
|
|
352
|
+
request_token: token,
|
|
353
|
+
},
|
|
354
|
+
});
|
|
355
|
+
};
|
|
356
|
+
const proxyPOST = async (url, body, token) => {
|
|
357
|
+
return requestDatalayer({
|
|
358
|
+
url: URLExt.join(configuration.iamRunUrl, 'api/iam/v1/proxy/request'),
|
|
359
|
+
method: 'POST',
|
|
360
|
+
body: {
|
|
361
|
+
request_method: 'POST',
|
|
362
|
+
request_url: url,
|
|
363
|
+
request_token: token,
|
|
364
|
+
request_body: body,
|
|
365
|
+
},
|
|
366
|
+
});
|
|
367
|
+
};
|
|
368
|
+
const proxyPUT = async (url, body, token) => {
|
|
369
|
+
return requestDatalayer({
|
|
370
|
+
url: URLExt.join(configuration.iamRunUrl, 'api/iam/v1/proxy/request'),
|
|
371
|
+
method: 'POST',
|
|
372
|
+
body: {
|
|
373
|
+
request_method: 'PUT',
|
|
374
|
+
request_url: url,
|
|
375
|
+
request_token: token,
|
|
376
|
+
request_body: body,
|
|
377
|
+
},
|
|
378
|
+
});
|
|
379
|
+
};
|
|
380
|
+
// Waiting List -------------------------------------------------------------
|
|
381
|
+
const registerToWaitingList = (formData) => {
|
|
382
|
+
requestDatalayer({
|
|
383
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/waitinglist/register`,
|
|
384
|
+
method: 'POST',
|
|
385
|
+
body: {
|
|
386
|
+
firstName: formData.firstName,
|
|
387
|
+
lastName: formData.lastName,
|
|
388
|
+
email: formData.email,
|
|
389
|
+
affiliation: formData.affiliation || '',
|
|
390
|
+
},
|
|
391
|
+
})
|
|
392
|
+
.then(resp => {
|
|
393
|
+
// Special case, make the error very explicit to the user...
|
|
394
|
+
if (!resp.success) {
|
|
395
|
+
alert('Sorry, something has gone wrong... Please send an email to eric@datalayer.io to register to the waiting list.');
|
|
396
|
+
}
|
|
397
|
+
})
|
|
398
|
+
.catch(err => {
|
|
399
|
+
// Special case, make the error very explicit to the user...
|
|
400
|
+
console.error(err);
|
|
401
|
+
alert('Sorry, something has gone wrong... Please send an email to eric@datalayer.io to register to the waiting list.');
|
|
402
|
+
});
|
|
403
|
+
};
|
|
404
|
+
// Profile ------------------------------------------------------------------
|
|
405
|
+
const getMe = async (token) => {
|
|
406
|
+
const resp = await requestDatalayer({
|
|
407
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/me`,
|
|
408
|
+
method: 'GET',
|
|
409
|
+
token,
|
|
410
|
+
});
|
|
411
|
+
const me = resp.me;
|
|
412
|
+
if (me) {
|
|
413
|
+
const user = asUser(me);
|
|
414
|
+
return user;
|
|
415
|
+
}
|
|
416
|
+
return null;
|
|
417
|
+
};
|
|
418
|
+
const updateMe = (email, firstName, lastName) => {
|
|
419
|
+
return requestDatalayer({
|
|
420
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/me`,
|
|
421
|
+
method: 'PUT',
|
|
422
|
+
body: {
|
|
423
|
+
email,
|
|
424
|
+
firstName,
|
|
425
|
+
lastName,
|
|
426
|
+
},
|
|
427
|
+
});
|
|
428
|
+
};
|
|
429
|
+
const whoami = () => {
|
|
430
|
+
return requestDatalayer({
|
|
431
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/whoami`,
|
|
432
|
+
method: 'GET',
|
|
433
|
+
});
|
|
434
|
+
};
|
|
435
|
+
const requestEmailUpdate = email => {
|
|
436
|
+
return requestDatalayer({
|
|
437
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/me/email`,
|
|
438
|
+
method: 'PUT',
|
|
439
|
+
body: {
|
|
440
|
+
email,
|
|
441
|
+
},
|
|
442
|
+
});
|
|
443
|
+
};
|
|
444
|
+
const confirmEmailUpdate = token => {
|
|
445
|
+
return requestDatalayer({
|
|
446
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/me/email`,
|
|
447
|
+
method: 'POST',
|
|
448
|
+
body: {
|
|
449
|
+
token,
|
|
450
|
+
},
|
|
451
|
+
});
|
|
452
|
+
};
|
|
453
|
+
// Onboarding ---------------------------------------------------------------
|
|
454
|
+
const updateUserOnboarding = (onboarding) => {
|
|
455
|
+
return requestDatalayer({
|
|
456
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/onboardings`,
|
|
457
|
+
method: 'PUT',
|
|
458
|
+
body: {
|
|
459
|
+
onboarding,
|
|
460
|
+
},
|
|
461
|
+
});
|
|
462
|
+
};
|
|
463
|
+
// Settings -----------------------------------------------------------------
|
|
464
|
+
const updateUserSettings = (userId, settings) => {
|
|
465
|
+
return requestDatalayer({
|
|
466
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/users/${userId}/settings`,
|
|
467
|
+
method: 'PUT',
|
|
468
|
+
body: {
|
|
469
|
+
aiagents_url_s: settings.aiAgentsUrl,
|
|
470
|
+
can_invite_b: settings.canInvite || false,
|
|
471
|
+
},
|
|
472
|
+
});
|
|
473
|
+
};
|
|
474
|
+
// Pages ------------------------------------------------------------------
|
|
475
|
+
const toPage = (s) => {
|
|
476
|
+
if (s) {
|
|
477
|
+
const page = asPage(s);
|
|
478
|
+
PAGES_BY_ID.set(s.uid, page);
|
|
479
|
+
return page;
|
|
480
|
+
}
|
|
481
|
+
};
|
|
482
|
+
const createPage = (page) => {
|
|
483
|
+
return requestDatalayer({
|
|
484
|
+
url: `${configuration.libraryRunUrl}/api/library/v1/pages`,
|
|
485
|
+
method: 'POST',
|
|
486
|
+
body: { ...page },
|
|
487
|
+
}).then(resp => {
|
|
488
|
+
if (resp.success) {
|
|
489
|
+
if (resp.page) {
|
|
490
|
+
const pageId = resp.page.uid;
|
|
491
|
+
PAGES_BY_ID.set(pageId, {
|
|
492
|
+
...page,
|
|
493
|
+
id: pageId,
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
return resp;
|
|
498
|
+
});
|
|
499
|
+
};
|
|
500
|
+
const updatePage = (page) => {
|
|
501
|
+
return requestDatalayer({
|
|
502
|
+
url: `${configuration.libraryRunUrl}/api/library/v1/pages/${page.id}`,
|
|
503
|
+
method: 'PUT',
|
|
504
|
+
body: {
|
|
505
|
+
name: page.name,
|
|
506
|
+
description: page.description,
|
|
507
|
+
tags: page.tags,
|
|
508
|
+
},
|
|
509
|
+
}).then(resp => {
|
|
510
|
+
if (resp.success) {
|
|
511
|
+
if (resp.page) {
|
|
512
|
+
toPage(resp.page);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
return resp;
|
|
516
|
+
});
|
|
517
|
+
};
|
|
518
|
+
const deletePage = (page) => {
|
|
519
|
+
return requestDatalayer({
|
|
520
|
+
url: `${configuration.libraryRunUrl}/api/library/v1/pages/${page.id}`,
|
|
521
|
+
method: 'DELETE',
|
|
522
|
+
});
|
|
523
|
+
};
|
|
524
|
+
const getPage = (pageId) => PAGES_BY_ID.get(pageId);
|
|
525
|
+
const clearCachedPages = () => PAGES_BY_ID.clear();
|
|
526
|
+
const refreshPage = (pageId) => {
|
|
527
|
+
return requestDatalayer({
|
|
528
|
+
url: `${configuration.libraryRunUrl}/api/library/v1/pages/${pageId}`,
|
|
529
|
+
method: 'GET',
|
|
530
|
+
}).then(resp => {
|
|
531
|
+
if (resp.success) {
|
|
532
|
+
if (resp.page) {
|
|
533
|
+
toPage(resp.page);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
return resp;
|
|
537
|
+
});
|
|
538
|
+
};
|
|
539
|
+
const getPages = () => {
|
|
540
|
+
return Array.from(PAGES_BY_ID.values());
|
|
541
|
+
};
|
|
542
|
+
const refreshPages = () => {
|
|
543
|
+
return requestDatalayer({
|
|
544
|
+
url: `${configuration.libraryRunUrl}/api/library/v1/pages`,
|
|
545
|
+
method: 'GET',
|
|
546
|
+
}).then(resp => {
|
|
547
|
+
if (resp.success) {
|
|
548
|
+
const pages = resp.pages;
|
|
549
|
+
if (pages) {
|
|
550
|
+
PAGES_BY_ID.clear();
|
|
551
|
+
pages.forEach(page => {
|
|
552
|
+
toPage(page);
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
return resp;
|
|
557
|
+
});
|
|
558
|
+
};
|
|
559
|
+
// Datasources ------------------------------------------------------------------
|
|
560
|
+
const toDatasource = (s) => {
|
|
561
|
+
if (s) {
|
|
562
|
+
const datasource = asDatasource(s);
|
|
563
|
+
DATASOURCES_BY_ID.set(s.uid, datasource);
|
|
564
|
+
return datasource;
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
const createDatasource = (datasource) => {
|
|
568
|
+
return requestDatalayer({
|
|
569
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/datasources`,
|
|
570
|
+
method: 'POST',
|
|
571
|
+
body: { ...datasource },
|
|
572
|
+
}).then(resp => {
|
|
573
|
+
if (resp.success) {
|
|
574
|
+
if (resp.datasource) {
|
|
575
|
+
toDatasource(resp.datasource);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
return resp;
|
|
579
|
+
});
|
|
580
|
+
};
|
|
581
|
+
const updateDatasource = (datasource) => {
|
|
582
|
+
return requestDatalayer({
|
|
583
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/datasources/${datasource.id}`,
|
|
584
|
+
method: 'PUT',
|
|
585
|
+
body: { ...datasource },
|
|
586
|
+
}).then(resp => {
|
|
587
|
+
if (resp.success) {
|
|
588
|
+
if (resp.datasource) {
|
|
589
|
+
toDatasource(resp.datasource);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
return resp;
|
|
593
|
+
});
|
|
594
|
+
};
|
|
595
|
+
const getDatasource = (datasourceId) => DATASOURCES_BY_ID.get(datasourceId);
|
|
596
|
+
const clearCachedDatasources = () => DATASOURCES_BY_ID.clear();
|
|
597
|
+
const refreshDatasource = (datasourceId) => {
|
|
598
|
+
return requestDatalayer({
|
|
599
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/datasources/${datasourceId}`,
|
|
600
|
+
method: 'GET',
|
|
601
|
+
}).then(resp => {
|
|
602
|
+
if (resp.success) {
|
|
603
|
+
if (resp.datasource) {
|
|
604
|
+
toDatasource(resp.datasource);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
return resp;
|
|
608
|
+
});
|
|
609
|
+
};
|
|
610
|
+
const getDatasources = () => {
|
|
611
|
+
return Array.from(DATASOURCES_BY_ID.values());
|
|
612
|
+
};
|
|
613
|
+
const refreshDatasources = () => {
|
|
614
|
+
return requestDatalayer({
|
|
615
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/datasources`,
|
|
616
|
+
method: 'GET',
|
|
617
|
+
}).then(resp => {
|
|
618
|
+
if (resp.success) {
|
|
619
|
+
const datasources = resp.datasources;
|
|
620
|
+
if (datasources) {
|
|
621
|
+
SECRETS_BY_ID.clear();
|
|
622
|
+
datasources.forEach(datasource => {
|
|
623
|
+
toDatasource(datasource);
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
return resp;
|
|
628
|
+
});
|
|
629
|
+
};
|
|
630
|
+
// Secrets ------------------------------------------------------------------
|
|
631
|
+
const toSecret = (s) => {
|
|
632
|
+
if (s) {
|
|
633
|
+
const secret = asSecret(s);
|
|
634
|
+
SECRETS_BY_ID.set(s.uid, secret);
|
|
635
|
+
return secret;
|
|
636
|
+
}
|
|
637
|
+
};
|
|
638
|
+
const createSecret = (secret) => {
|
|
639
|
+
return requestDatalayer({
|
|
640
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/secrets`,
|
|
641
|
+
method: 'POST',
|
|
642
|
+
body: { ...secret },
|
|
643
|
+
}).then(resp => {
|
|
644
|
+
if (resp.success) {
|
|
645
|
+
if (resp.secret) {
|
|
646
|
+
toSecret(resp.secret);
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
return resp;
|
|
650
|
+
});
|
|
651
|
+
};
|
|
652
|
+
const updateSecret = (secret) => {
|
|
653
|
+
return requestDatalayer({
|
|
654
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/secrets/${secret.id}`,
|
|
655
|
+
method: 'PUT',
|
|
656
|
+
body: { ...secret },
|
|
657
|
+
}).then(resp => {
|
|
658
|
+
if (resp.success) {
|
|
659
|
+
if (resp.secret) {
|
|
660
|
+
toSecret(resp.secret);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
return resp;
|
|
664
|
+
});
|
|
665
|
+
};
|
|
666
|
+
const deleteSecret = (secret) => {
|
|
667
|
+
return requestDatalayer({
|
|
668
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/secrets/${secret.id}`,
|
|
669
|
+
method: 'DELETE',
|
|
670
|
+
});
|
|
671
|
+
};
|
|
672
|
+
const getSecret = (secretId) => SECRETS_BY_ID.get(secretId);
|
|
673
|
+
const clearCachedSecrets = () => SECRETS_BY_ID.clear();
|
|
674
|
+
const refreshSecret = (secretId) => {
|
|
675
|
+
return requestDatalayer({
|
|
676
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/secrets/${secretId}`,
|
|
677
|
+
method: 'GET',
|
|
678
|
+
}).then(resp => {
|
|
679
|
+
if (resp.success) {
|
|
680
|
+
if (resp.secret) {
|
|
681
|
+
toSecret(resp.secret);
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
return resp;
|
|
685
|
+
});
|
|
686
|
+
};
|
|
687
|
+
const getSecrets = () => {
|
|
688
|
+
return Array.from(SECRETS_BY_ID.values());
|
|
689
|
+
};
|
|
690
|
+
const refreshSecrets = () => {
|
|
691
|
+
return requestDatalayer({
|
|
692
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/secrets`,
|
|
693
|
+
method: 'GET',
|
|
694
|
+
}).then(resp => {
|
|
695
|
+
if (resp.success) {
|
|
696
|
+
const secrets = resp.secrets;
|
|
697
|
+
if (secrets) {
|
|
698
|
+
SECRETS_BY_ID.clear();
|
|
699
|
+
secrets.forEach(secret => {
|
|
700
|
+
toSecret(secret);
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
return resp;
|
|
705
|
+
});
|
|
706
|
+
};
|
|
707
|
+
// Tokens ------------------------------------------------------------------
|
|
708
|
+
const toToken = (s) => {
|
|
709
|
+
if (s) {
|
|
710
|
+
const token = asToken(s);
|
|
711
|
+
TOKENS_BY_ID.set(s.uid, token);
|
|
712
|
+
return token;
|
|
713
|
+
}
|
|
714
|
+
};
|
|
715
|
+
const createToken = (token) => {
|
|
716
|
+
return requestDatalayer({
|
|
717
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/tokens`,
|
|
718
|
+
method: 'POST',
|
|
719
|
+
body: {
|
|
720
|
+
...token,
|
|
721
|
+
expirationDate: token.expirationDate.getTime(),
|
|
722
|
+
},
|
|
723
|
+
}).then(resp => {
|
|
724
|
+
if (resp.success) {
|
|
725
|
+
if (resp.token) {
|
|
726
|
+
toToken(resp.token);
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
return resp;
|
|
730
|
+
});
|
|
731
|
+
};
|
|
732
|
+
const updateToken = (token) => {
|
|
733
|
+
return requestDatalayer({
|
|
734
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/tokens/${token.id}`,
|
|
735
|
+
method: 'PUT',
|
|
736
|
+
body: { ...token },
|
|
737
|
+
}).then(resp => {
|
|
738
|
+
if (resp.success) {
|
|
739
|
+
if (resp.token) {
|
|
740
|
+
toToken(resp.token);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
return resp;
|
|
744
|
+
});
|
|
745
|
+
};
|
|
746
|
+
const getToken = (tokenId) => TOKENS_BY_ID.get(tokenId);
|
|
747
|
+
const clearCachedTokens = () => TOKENS_BY_ID.clear();
|
|
748
|
+
const refreshToken = (tokenId) => {
|
|
749
|
+
return requestDatalayer({
|
|
750
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/tokens/${tokenId}`,
|
|
751
|
+
method: 'GET',
|
|
752
|
+
}).then(resp => {
|
|
753
|
+
if (resp.success) {
|
|
754
|
+
if (resp.token) {
|
|
755
|
+
toToken(resp.token);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
return resp;
|
|
759
|
+
});
|
|
760
|
+
};
|
|
761
|
+
const getTokens = () => {
|
|
762
|
+
return Array.from(TOKENS_BY_ID.values());
|
|
763
|
+
};
|
|
764
|
+
const refreshTokens = () => {
|
|
765
|
+
return requestDatalayer({
|
|
766
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/tokens`,
|
|
767
|
+
method: 'GET',
|
|
768
|
+
}).then(resp => {
|
|
769
|
+
if (resp.success) {
|
|
770
|
+
const tokens = resp.tokens;
|
|
771
|
+
if (tokens) {
|
|
772
|
+
TOKENS_BY_ID.clear();
|
|
773
|
+
tokens.forEach(token => {
|
|
774
|
+
toToken(token);
|
|
775
|
+
});
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
return resp;
|
|
779
|
+
});
|
|
780
|
+
};
|
|
781
|
+
// Layout -------------------------------------------------------------------
|
|
782
|
+
const refreshLayout = (accountHandle, spaceHandle, user) => {
|
|
783
|
+
return requestDatalayer({
|
|
784
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/layouts/accounts/${accountHandle}${spaceHandle !== undefined ? '/spaces/' + spaceHandle : ''}`,
|
|
785
|
+
method: 'GET',
|
|
786
|
+
}).then(resp => {
|
|
787
|
+
if (resp.success) {
|
|
788
|
+
if (resp.user) {
|
|
789
|
+
toUser(resp.user);
|
|
790
|
+
}
|
|
791
|
+
let organization = undefined;
|
|
792
|
+
if (resp.organization) {
|
|
793
|
+
organization = toOrganization(resp.organization);
|
|
794
|
+
if (user && checkIsOrganizationMember(user, organization)) {
|
|
795
|
+
ORGANISATIONS_FOR_USER_BY_ID.set(organization.id, organization);
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
if (resp.space) {
|
|
799
|
+
const space = toSpace(resp.space);
|
|
800
|
+
if (organization) {
|
|
801
|
+
let osById = SPACES_BY_ID_BY_ORGANISATION_ID.get(organization.id);
|
|
802
|
+
if (!osById) {
|
|
803
|
+
osById = new Map();
|
|
804
|
+
SPACES_BY_ID_BY_ORGANISATION_ID.set(organization.id, osById);
|
|
805
|
+
}
|
|
806
|
+
osById.set(space.id, space);
|
|
807
|
+
let osByHandle = SPACES_BY_HANDLE_BY_ORGANISATION_HANDLE.get(organization.handle);
|
|
808
|
+
if (!osByHandle) {
|
|
809
|
+
osByHandle = new Map();
|
|
810
|
+
SPACES_BY_HANDLE_BY_ORGANISATION_HANDLE.set(organization.handle, osByHandle);
|
|
811
|
+
}
|
|
812
|
+
osByHandle.set(space.handle, space);
|
|
813
|
+
}
|
|
814
|
+
else {
|
|
815
|
+
SPACES_FOR_USER_BY_HANDLE.set(space.handle, space);
|
|
816
|
+
SPACES_FOR_USER_BY_ID.set(space.id, space);
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
return resp;
|
|
821
|
+
});
|
|
822
|
+
};
|
|
823
|
+
// Invites -------------------------------------------------------------------
|
|
824
|
+
const requestInvite = (firstName, lastName, email, socialUrl) => {
|
|
825
|
+
return requestDatalayer({
|
|
826
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/invites/request`,
|
|
827
|
+
method: 'POST',
|
|
828
|
+
body: {
|
|
829
|
+
first_name: firstName,
|
|
830
|
+
last_name: lastName,
|
|
831
|
+
email: email,
|
|
832
|
+
social_url: socialUrl,
|
|
833
|
+
},
|
|
834
|
+
});
|
|
835
|
+
};
|
|
836
|
+
const sendInvite = (invite) => {
|
|
837
|
+
return requestDatalayer({
|
|
838
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/invites`,
|
|
839
|
+
method: 'POST',
|
|
840
|
+
body: {
|
|
841
|
+
email: invite.to.email,
|
|
842
|
+
firstName: invite.to.firstName,
|
|
843
|
+
lastName: invite.to.lastName,
|
|
844
|
+
message: invite.message,
|
|
845
|
+
brand: invite.brand,
|
|
846
|
+
},
|
|
847
|
+
});
|
|
848
|
+
};
|
|
849
|
+
const getInvite = (token) => INVITES_BY_TOKEN.get(token);
|
|
850
|
+
const clearCachedInvites = () => INVITES_BY_TOKEN.clear();
|
|
851
|
+
const refreshInvite = (token) => {
|
|
852
|
+
return requestDatalayer({
|
|
853
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/invites/tokens/${token}`,
|
|
854
|
+
method: 'GET',
|
|
855
|
+
}).then(resp => {
|
|
856
|
+
if (resp.success) {
|
|
857
|
+
const i = resp.invite;
|
|
858
|
+
if (i) {
|
|
859
|
+
const invite = asInvite(i);
|
|
860
|
+
if (invite.token) {
|
|
861
|
+
INVITES_BY_TOKEN.set(invite.token, invite);
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
return resp;
|
|
866
|
+
});
|
|
867
|
+
};
|
|
868
|
+
const getInvites = () => {
|
|
869
|
+
return Array.from(INVITES_BY_TOKEN.values());
|
|
870
|
+
};
|
|
871
|
+
const refreshInvites = (accountId) => {
|
|
872
|
+
return requestDatalayer({
|
|
873
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/invites/users/${accountId}`,
|
|
874
|
+
method: 'GET',
|
|
875
|
+
}).then(resp => {
|
|
876
|
+
if (resp.success) {
|
|
877
|
+
resp.invites.forEach(i => {
|
|
878
|
+
const invite = asInvite(i);
|
|
879
|
+
if (invite.token) {
|
|
880
|
+
INVITES_BY_TOKEN.set(invite.token, invite);
|
|
881
|
+
}
|
|
882
|
+
});
|
|
883
|
+
}
|
|
884
|
+
return resp;
|
|
885
|
+
});
|
|
886
|
+
};
|
|
887
|
+
const putInvite = (token) => {
|
|
888
|
+
return requestDatalayer({
|
|
889
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/invites/tokens/${token}`,
|
|
890
|
+
method: 'PUT',
|
|
891
|
+
});
|
|
892
|
+
};
|
|
893
|
+
// Accounts -------------------------------------------------------------------
|
|
894
|
+
const refreshAccount = (accountHandle) => {
|
|
895
|
+
return requestDatalayer({
|
|
896
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/accounts/${accountHandle}`,
|
|
897
|
+
method: 'GET',
|
|
898
|
+
}).then(resp => {
|
|
899
|
+
if (resp.success) {
|
|
900
|
+
if (resp.user) {
|
|
901
|
+
toUser(resp.user);
|
|
902
|
+
}
|
|
903
|
+
if (resp.organization) {
|
|
904
|
+
toOrganization(resp.organization);
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
return resp;
|
|
908
|
+
});
|
|
909
|
+
};
|
|
910
|
+
// Contacts ---------------------------------------------------------------------
|
|
911
|
+
const toContact = (c) => {
|
|
912
|
+
if (c) {
|
|
913
|
+
const contact = asContact(c);
|
|
914
|
+
CONTACTS_BY_ID.set(contact.id, contact);
|
|
915
|
+
CONTACTS_BY_HANDLE.set(contact.handle, contact);
|
|
916
|
+
return contact;
|
|
917
|
+
}
|
|
918
|
+
};
|
|
919
|
+
const getContactById = (contactId) => CONTACTS_BY_ID.get(contactId);
|
|
920
|
+
const getContactByHandle = (contactHandle) => CONTACTS_BY_HANDLE.get(contactHandle);
|
|
921
|
+
const createContact = (contact) => {
|
|
922
|
+
return requestDatalayer({
|
|
923
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/contacts`,
|
|
924
|
+
method: 'POST',
|
|
925
|
+
body: {
|
|
926
|
+
contact,
|
|
927
|
+
},
|
|
928
|
+
}).then(resp => {
|
|
929
|
+
if (resp.success) {
|
|
930
|
+
toContact(resp.contact);
|
|
931
|
+
}
|
|
932
|
+
return resp;
|
|
933
|
+
});
|
|
934
|
+
};
|
|
935
|
+
const updateContact = (contactId, contact) => {
|
|
936
|
+
return requestDatalayer({
|
|
937
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/contacts/${contactId}`,
|
|
938
|
+
method: 'PUT',
|
|
939
|
+
body: {
|
|
940
|
+
contact,
|
|
941
|
+
},
|
|
942
|
+
}).then(resp => {
|
|
943
|
+
if (resp.success) {
|
|
944
|
+
toContact(resp.contact);
|
|
945
|
+
}
|
|
946
|
+
return resp;
|
|
947
|
+
});
|
|
948
|
+
};
|
|
949
|
+
const refreshContact = (contactId) => {
|
|
950
|
+
return requestDatalayer({
|
|
951
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/contacts/${contactId}`,
|
|
952
|
+
method: 'GET',
|
|
953
|
+
}).then(resp => {
|
|
954
|
+
if (resp.success) {
|
|
955
|
+
toContact(resp.contact);
|
|
956
|
+
}
|
|
957
|
+
return resp;
|
|
958
|
+
});
|
|
959
|
+
};
|
|
960
|
+
const searchContacts = (query) => {
|
|
961
|
+
return requestDatalayer({
|
|
962
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/contacts/search`,
|
|
963
|
+
method: 'POST',
|
|
964
|
+
body: {
|
|
965
|
+
query,
|
|
966
|
+
},
|
|
967
|
+
}).then(resp => {
|
|
968
|
+
if (resp.success) {
|
|
969
|
+
const contacts = resp.contacts.map(contact => toContact(contact));
|
|
970
|
+
resp.contacts = contacts;
|
|
971
|
+
}
|
|
972
|
+
return resp;
|
|
973
|
+
});
|
|
974
|
+
};
|
|
975
|
+
const assignTagToContact = (contactId, tagName) => {
|
|
976
|
+
return requestDatalayer({
|
|
977
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/contacts/${contactId}/tags/${tagName}`,
|
|
978
|
+
method: 'POST',
|
|
979
|
+
});
|
|
980
|
+
};
|
|
981
|
+
const unassignTagFromContact = (contactId, tagName) => {
|
|
982
|
+
return requestDatalayer({
|
|
983
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/contacts/${contactId}/tags/${tagName}`,
|
|
984
|
+
method: 'DELETE',
|
|
985
|
+
});
|
|
986
|
+
};
|
|
987
|
+
const deleteContact = (contactId) => {
|
|
988
|
+
return requestDatalayer({
|
|
989
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/contacts/${contactId}`,
|
|
990
|
+
method: 'DELETE',
|
|
991
|
+
});
|
|
992
|
+
};
|
|
993
|
+
const sendInviteToContact = (contact, message) => {
|
|
994
|
+
return requestDatalayer({
|
|
995
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/contacts/invites`,
|
|
996
|
+
method: 'POST',
|
|
997
|
+
body: {
|
|
998
|
+
contactId: contact.id,
|
|
999
|
+
message,
|
|
1000
|
+
},
|
|
1001
|
+
});
|
|
1002
|
+
};
|
|
1003
|
+
// Contacts Enrich ----------------------------------------------------------
|
|
1004
|
+
const enrichContactEmail = (contactId, useDomain) => {
|
|
1005
|
+
return requestDatalayer({
|
|
1006
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/contacts/${contactId}/enrich/email?useDomain=${useDomain}`,
|
|
1007
|
+
method: 'GET',
|
|
1008
|
+
});
|
|
1009
|
+
};
|
|
1010
|
+
const enrichContactLinkedin = contactId => {
|
|
1011
|
+
return requestDatalayer({
|
|
1012
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/contacts/${contactId}/enrich/linkedin`,
|
|
1013
|
+
method: 'GET',
|
|
1014
|
+
});
|
|
1015
|
+
};
|
|
1016
|
+
const sendLinkedinConnectionRequest = (contact, message) => {
|
|
1017
|
+
return requestDatalayer({
|
|
1018
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/contacts/${contact.id}/connect/linkedin`,
|
|
1019
|
+
method: 'POST',
|
|
1020
|
+
body: {
|
|
1021
|
+
message,
|
|
1022
|
+
},
|
|
1023
|
+
}).then(resp => {
|
|
1024
|
+
if (resp.success) {
|
|
1025
|
+
toContact(resp.contact);
|
|
1026
|
+
}
|
|
1027
|
+
return resp;
|
|
1028
|
+
});
|
|
1029
|
+
};
|
|
1030
|
+
// Contacts Links -----------------------------------------------------------
|
|
1031
|
+
const linkUserWithContact = (userId, contactId) => {
|
|
1032
|
+
return requestDatalayer({
|
|
1033
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/users/${userId}/contacts/${contactId}/link`,
|
|
1034
|
+
method: 'POST',
|
|
1035
|
+
});
|
|
1036
|
+
};
|
|
1037
|
+
const unlinkUserFromContact = (userId, contactId) => {
|
|
1038
|
+
return requestDatalayer({
|
|
1039
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/users/${userId}/contacts/${contactId}/link`,
|
|
1040
|
+
method: 'DELETE',
|
|
1041
|
+
});
|
|
1042
|
+
};
|
|
1043
|
+
// Users --------------------------------------------------------------------
|
|
1044
|
+
const toUser = (u) => {
|
|
1045
|
+
if (u) {
|
|
1046
|
+
const user = asUser(u);
|
|
1047
|
+
USERS_BY_ID.set(user.id, user);
|
|
1048
|
+
USERS_BY_HANDLE.set(user.handle, user);
|
|
1049
|
+
return user;
|
|
1050
|
+
}
|
|
1051
|
+
};
|
|
1052
|
+
const getUser = (id) => USERS_BY_ID.get(id);
|
|
1053
|
+
const getUserByHandle = (handle) => USERS_BY_HANDLE.get(handle);
|
|
1054
|
+
const refreshUser = (userId) => {
|
|
1055
|
+
return requestDatalayer({
|
|
1056
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/users/${userId}`,
|
|
1057
|
+
method: 'GET',
|
|
1058
|
+
}).then(resp => {
|
|
1059
|
+
if (resp.success) {
|
|
1060
|
+
toUser(resp.user);
|
|
1061
|
+
}
|
|
1062
|
+
return resp;
|
|
1063
|
+
});
|
|
1064
|
+
};
|
|
1065
|
+
const searchUsers = (namingPattern) => {
|
|
1066
|
+
return requestDatalayer({
|
|
1067
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/users/search`,
|
|
1068
|
+
method: 'POST',
|
|
1069
|
+
body: {
|
|
1070
|
+
namingPattern,
|
|
1071
|
+
},
|
|
1072
|
+
}).then(resp => {
|
|
1073
|
+
if (resp.success) {
|
|
1074
|
+
const users = resp.users.map(user => toUser(user));
|
|
1075
|
+
resp.users = users;
|
|
1076
|
+
}
|
|
1077
|
+
return resp;
|
|
1078
|
+
});
|
|
1079
|
+
};
|
|
1080
|
+
// User Roles ---------------------------------------------------------------
|
|
1081
|
+
const assignRoleToUser = (userId, roleName) => {
|
|
1082
|
+
return requestDatalayer({
|
|
1083
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/users/${userId}/roles/${roleName}`,
|
|
1084
|
+
method: 'POST',
|
|
1085
|
+
});
|
|
1086
|
+
};
|
|
1087
|
+
const unassignRoleFromUser = (userId, roleName) => {
|
|
1088
|
+
return requestDatalayer({
|
|
1089
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/users/${userId}/roles/${roleName}`,
|
|
1090
|
+
method: 'DELETE',
|
|
1091
|
+
});
|
|
1092
|
+
};
|
|
1093
|
+
// Organizations -------------------------------------------------------------------
|
|
1094
|
+
const toOrganization = (org) => {
|
|
1095
|
+
const organization = asOrganization(org);
|
|
1096
|
+
ORGANISATIONS_BY_ID.set(organization.id, organization);
|
|
1097
|
+
ORGANISATIONS_BY_HANDLE.set(organization.handle, organization);
|
|
1098
|
+
return organization;
|
|
1099
|
+
};
|
|
1100
|
+
const createOrganization = (organization) => {
|
|
1101
|
+
return requestDatalayer({
|
|
1102
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/organizations`,
|
|
1103
|
+
method: 'POST',
|
|
1104
|
+
body: {
|
|
1105
|
+
handle: organization.handle,
|
|
1106
|
+
name: organization.name,
|
|
1107
|
+
description: organization.description,
|
|
1108
|
+
},
|
|
1109
|
+
}).then(resp => {
|
|
1110
|
+
const organization = toOrganization(resp.organization);
|
|
1111
|
+
ORGANISATIONS_FOR_USER_BY_ID.set(organization.id, organization);
|
|
1112
|
+
return resp;
|
|
1113
|
+
});
|
|
1114
|
+
};
|
|
1115
|
+
const getOrganizationById = (organizationId) => ORGANISATIONS_BY_ID.get(organizationId);
|
|
1116
|
+
const getOrganizationByHandle = (organizationHandle) => ORGANISATIONS_BY_HANDLE.get(organizationHandle);
|
|
1117
|
+
const clearCachedOrganizations = () => {
|
|
1118
|
+
ORGANISATIONS_BY_HANDLE.clear();
|
|
1119
|
+
ORGANISATIONS_BY_ID.clear();
|
|
1120
|
+
ORGANISATIONS_FOR_USER_BY_ID.clear();
|
|
1121
|
+
};
|
|
1122
|
+
const refreshOrganization = (user, organizationId) => {
|
|
1123
|
+
return requestDatalayer({
|
|
1124
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/organizations/${organizationId}`,
|
|
1125
|
+
method: 'GET',
|
|
1126
|
+
}).then(resp => {
|
|
1127
|
+
if (resp.success) {
|
|
1128
|
+
const org = resp.organization;
|
|
1129
|
+
if (org) {
|
|
1130
|
+
const organization = toOrganization(org);
|
|
1131
|
+
if (checkIsOrganizationMember(user, organization)) {
|
|
1132
|
+
ORGANISATIONS_FOR_USER_BY_ID.set(organizationId, organization);
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
return resp;
|
|
1137
|
+
});
|
|
1138
|
+
};
|
|
1139
|
+
const updateOrganization = (organization) => {
|
|
1140
|
+
return requestDatalayer({
|
|
1141
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/organizations/${organization.id}`,
|
|
1142
|
+
method: 'PUT',
|
|
1143
|
+
body: {
|
|
1144
|
+
name: organization.name,
|
|
1145
|
+
description: organization.description,
|
|
1146
|
+
},
|
|
1147
|
+
}).then(resp => {
|
|
1148
|
+
if (resp.success) {
|
|
1149
|
+
const org = getOrganizationById(organization.id);
|
|
1150
|
+
if (org) {
|
|
1151
|
+
org.name = organization.name;
|
|
1152
|
+
org.description = organization.description;
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
return resp;
|
|
1156
|
+
});
|
|
1157
|
+
};
|
|
1158
|
+
const getUserOrganizations = () => Array.from(ORGANISATIONS_FOR_USER_BY_ID.values());
|
|
1159
|
+
const getUserOrganizationById = (organizationId) => ORGANISATIONS_FOR_USER_BY_ID.get(organizationId);
|
|
1160
|
+
const refreshUserOrganizations = (user) => {
|
|
1161
|
+
return requestDatalayer({
|
|
1162
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/organizations`,
|
|
1163
|
+
method: 'GET',
|
|
1164
|
+
}).then(resp => {
|
|
1165
|
+
if (resp.success) {
|
|
1166
|
+
resp.organizations.forEach(org => {
|
|
1167
|
+
const organization = toOrganization(org);
|
|
1168
|
+
if (checkIsOrganizationMember(user, organization)) {
|
|
1169
|
+
ORGANISATIONS_FOR_USER_BY_ID.set(organization.id, organization);
|
|
1170
|
+
}
|
|
1171
|
+
});
|
|
1172
|
+
}
|
|
1173
|
+
return resp;
|
|
1174
|
+
});
|
|
1175
|
+
};
|
|
1176
|
+
const addMemberToOrganization = (organizationId, userId) => {
|
|
1177
|
+
return requestDatalayer({
|
|
1178
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/organizations/${organizationId}/members/${userId}`,
|
|
1179
|
+
method: 'POST',
|
|
1180
|
+
});
|
|
1181
|
+
};
|
|
1182
|
+
const removeMemberFromOrganization = (organizationId, userId) => {
|
|
1183
|
+
return requestDatalayer({
|
|
1184
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/organizations/${organizationId}/members/${userId}`,
|
|
1185
|
+
method: 'DELETE',
|
|
1186
|
+
});
|
|
1187
|
+
};
|
|
1188
|
+
const addRoleToOrganizationMember = (organizationId, userId, roleName) => {
|
|
1189
|
+
return requestDatalayer({
|
|
1190
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/organizations/${organizationId}/members/${userId}/roles/${roleName}`,
|
|
1191
|
+
method: 'POST',
|
|
1192
|
+
});
|
|
1193
|
+
};
|
|
1194
|
+
const removeRoleFromOrganizationMember = (organizationId, userId, roleName) => {
|
|
1195
|
+
return requestDatalayer({
|
|
1196
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/organizations/${organizationId}/members/${userId}/roles/${roleName}`,
|
|
1197
|
+
method: 'DELETE',
|
|
1198
|
+
});
|
|
1199
|
+
};
|
|
1200
|
+
// Teams -------------------------------------------------------------------
|
|
1201
|
+
const toTeam = (org, organizationId) => {
|
|
1202
|
+
const team = asTeam(org, organizationId);
|
|
1203
|
+
TEAMS_BY_ID.set(team.id, team);
|
|
1204
|
+
TEAMS_BY_HANDLE.set(team.handle, team);
|
|
1205
|
+
return team;
|
|
1206
|
+
};
|
|
1207
|
+
const createTeam = (team, organization) => {
|
|
1208
|
+
return requestDatalayer({
|
|
1209
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/teams`,
|
|
1210
|
+
method: 'POST',
|
|
1211
|
+
body: {
|
|
1212
|
+
handle: team.handle,
|
|
1213
|
+
name: team.name,
|
|
1214
|
+
description: team.description,
|
|
1215
|
+
organizationId: organization.id,
|
|
1216
|
+
},
|
|
1217
|
+
}).then(resp => {
|
|
1218
|
+
const team = toTeam(resp.team, organization.id);
|
|
1219
|
+
TEAMS_BY_HANDLE.set(team.handle, team);
|
|
1220
|
+
TEAMS_BY_ID.set(team.id, team);
|
|
1221
|
+
return resp;
|
|
1222
|
+
});
|
|
1223
|
+
};
|
|
1224
|
+
const getTeamById = (teamId) => TEAMS_BY_ID.get(teamId);
|
|
1225
|
+
const getTeamByHandle = (teamHandle) => TEAMS_BY_HANDLE.get(teamHandle);
|
|
1226
|
+
const clearCachedTeams = () => {
|
|
1227
|
+
TEAMS_BY_HANDLE.clear();
|
|
1228
|
+
TEAMS_BY_ID.clear();
|
|
1229
|
+
};
|
|
1230
|
+
const refreshTeam = (teamId, organizationId) => {
|
|
1231
|
+
return requestDatalayer({
|
|
1232
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/teams/${teamId}`,
|
|
1233
|
+
method: 'GET',
|
|
1234
|
+
}).then(resp => {
|
|
1235
|
+
if (resp.success) {
|
|
1236
|
+
const t = resp.team;
|
|
1237
|
+
if (t) {
|
|
1238
|
+
const team = toTeam(t, organizationId);
|
|
1239
|
+
TEAMS_BY_HANDLE.set(team.handle, team);
|
|
1240
|
+
TEAMS_BY_ID.set(team.id, team);
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
return resp;
|
|
1244
|
+
});
|
|
1245
|
+
};
|
|
1246
|
+
const updateTeam = (team) => {
|
|
1247
|
+
return requestDatalayer({
|
|
1248
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/teams/${team.id}`,
|
|
1249
|
+
method: 'PUT',
|
|
1250
|
+
body: {
|
|
1251
|
+
name: team.name,
|
|
1252
|
+
description: team.description,
|
|
1253
|
+
},
|
|
1254
|
+
}).then(resp => {
|
|
1255
|
+
if (resp.success) {
|
|
1256
|
+
const t = resp.team;
|
|
1257
|
+
if (t) {
|
|
1258
|
+
const tt = toTeam(t, team.organization.id);
|
|
1259
|
+
TEAMS_BY_HANDLE.set(team.handle, tt);
|
|
1260
|
+
TEAMS_BY_ID.set(team.id, tt);
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
return resp;
|
|
1264
|
+
});
|
|
1265
|
+
};
|
|
1266
|
+
const getTeamsByOrganizationId = (organizationId) => TEAMS_BY_ORGANIZATION_BY_ID.get(organizationId);
|
|
1267
|
+
const refreshTeams = (organizationId) => {
|
|
1268
|
+
return requestDatalayer({
|
|
1269
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/organizations/${organizationId}/teams`,
|
|
1270
|
+
method: 'GET',
|
|
1271
|
+
}).then(resp => {
|
|
1272
|
+
if (resp.success) {
|
|
1273
|
+
const teams = resp.teams.map(t => {
|
|
1274
|
+
const team = toTeam(t, organizationId);
|
|
1275
|
+
TEAMS_BY_HANDLE.set(team.handle, team);
|
|
1276
|
+
TEAMS_BY_ID.set(team.id, team);
|
|
1277
|
+
return team;
|
|
1278
|
+
});
|
|
1279
|
+
TEAMS_BY_ORGANIZATION_BY_ID.set(organizationId, teams);
|
|
1280
|
+
}
|
|
1281
|
+
return resp;
|
|
1282
|
+
});
|
|
1283
|
+
};
|
|
1284
|
+
const addMemberToTeam = (teamId, userId) => {
|
|
1285
|
+
return requestDatalayer({
|
|
1286
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/teams/${teamId}/members/${userId}`,
|
|
1287
|
+
method: 'POST',
|
|
1288
|
+
});
|
|
1289
|
+
};
|
|
1290
|
+
const removeMemberFromTeam = (teamId, userId) => {
|
|
1291
|
+
return requestDatalayer({
|
|
1292
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/teams/${teamId}/members/${userId}`,
|
|
1293
|
+
method: 'DELETE',
|
|
1294
|
+
});
|
|
1295
|
+
};
|
|
1296
|
+
const addRoleToTeamMember = (teamId, userId, roleName) => {
|
|
1297
|
+
return requestDatalayer({
|
|
1298
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/teams/${teamId}/members/${userId}/roles/${roleName}`,
|
|
1299
|
+
method: 'POST',
|
|
1300
|
+
});
|
|
1301
|
+
};
|
|
1302
|
+
const removeRoleFromTeamMember = (teamId, userId, roleName) => {
|
|
1303
|
+
return requestDatalayer({
|
|
1304
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/teams/${teamId}/members/${userId}/roles/${roleName}`,
|
|
1305
|
+
method: 'DELETE',
|
|
1306
|
+
});
|
|
1307
|
+
};
|
|
1308
|
+
// Schools -------------------------------------------------------------------
|
|
1309
|
+
const getSchools = () => {
|
|
1310
|
+
return Array.from(SCHOOLS_BY_ID.values());
|
|
1311
|
+
};
|
|
1312
|
+
const refreshSchools = () => {
|
|
1313
|
+
return requestDatalayer({
|
|
1314
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/organizations/schools`,
|
|
1315
|
+
method: 'GET',
|
|
1316
|
+
}).then(resp => {
|
|
1317
|
+
if (resp.success) {
|
|
1318
|
+
resp.orgs.forEach(s => {
|
|
1319
|
+
const dean = undefined;
|
|
1320
|
+
const students = new Array();
|
|
1321
|
+
const members = new Array();
|
|
1322
|
+
const courses = new Array();
|
|
1323
|
+
const school = {
|
|
1324
|
+
id: s.uid,
|
|
1325
|
+
type: 'school',
|
|
1326
|
+
handle: s.handle_s,
|
|
1327
|
+
name: s.name_t,
|
|
1328
|
+
description: s.description_t,
|
|
1329
|
+
dean,
|
|
1330
|
+
members,
|
|
1331
|
+
students,
|
|
1332
|
+
courses,
|
|
1333
|
+
public: s.public_b,
|
|
1334
|
+
creationDate: new Date(s.creation_ts_dt),
|
|
1335
|
+
setMembers(members) {
|
|
1336
|
+
this.members = members;
|
|
1337
|
+
},
|
|
1338
|
+
};
|
|
1339
|
+
SCHOOLS_BY_ID.set(school.id, school);
|
|
1340
|
+
});
|
|
1341
|
+
}
|
|
1342
|
+
return resp;
|
|
1343
|
+
});
|
|
1344
|
+
};
|
|
1345
|
+
// Spaces -------------------------------------------------------------------
|
|
1346
|
+
const toSpace = (spc) => {
|
|
1347
|
+
const space = asSpace(spc);
|
|
1348
|
+
return space;
|
|
1349
|
+
};
|
|
1350
|
+
const createSpace = (space, organization) => {
|
|
1351
|
+
const seedSpaceId = space.variant === 'course' ? space.seedSpace?.id : undefined;
|
|
1352
|
+
return requestDatalayer({
|
|
1353
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/spaces`,
|
|
1354
|
+
method: 'POST',
|
|
1355
|
+
body: {
|
|
1356
|
+
name: space.name,
|
|
1357
|
+
description: space.description,
|
|
1358
|
+
variant: space.variant,
|
|
1359
|
+
public: space.public,
|
|
1360
|
+
spaceHandle: space.handle,
|
|
1361
|
+
organizationId: organization?.id,
|
|
1362
|
+
seedSpaceId,
|
|
1363
|
+
},
|
|
1364
|
+
}).then(resp => {
|
|
1365
|
+
const spc = resp.space;
|
|
1366
|
+
if (spc) {
|
|
1367
|
+
const space = toSpace(spc);
|
|
1368
|
+
if (organization) {
|
|
1369
|
+
let os = SPACES_BY_ID_BY_ORGANISATION_ID.get(organization.id);
|
|
1370
|
+
if (!os) {
|
|
1371
|
+
os = new Map();
|
|
1372
|
+
SPACES_BY_ID_BY_ORGANISATION_ID.set(organization.id, os);
|
|
1373
|
+
}
|
|
1374
|
+
os.set(space.id, space);
|
|
1375
|
+
}
|
|
1376
|
+
else {
|
|
1377
|
+
SPACES_FOR_USER_BY_HANDLE.set(space.handle, space);
|
|
1378
|
+
SPACES_FOR_USER_BY_ID.set(space.id, space);
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
return resp;
|
|
1382
|
+
});
|
|
1383
|
+
};
|
|
1384
|
+
const getOrganizationSpace = (organizationId, spaceId) => {
|
|
1385
|
+
const organizationSpaces = SPACES_BY_ID_BY_ORGANISATION_ID.get(organizationId);
|
|
1386
|
+
return organizationSpaces ? organizationSpaces.get(spaceId) : undefined;
|
|
1387
|
+
};
|
|
1388
|
+
const getOrganizationSpaceByHandle = (organizationHandle, spaceHandle) => {
|
|
1389
|
+
const organizationSpaces = SPACES_BY_HANDLE_BY_ORGANISATION_HANDLE.get(organizationHandle);
|
|
1390
|
+
return organizationSpaces ? organizationSpaces.get(spaceHandle) : undefined;
|
|
1391
|
+
};
|
|
1392
|
+
const refreshOrganizationSpace = (organizationId, spaceId) => {
|
|
1393
|
+
return requestDatalayer({
|
|
1394
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/spaces/${spaceId}/organizations/${organizationId}`,
|
|
1395
|
+
method: 'GET',
|
|
1396
|
+
}).then(resp => {
|
|
1397
|
+
if (resp.success) {
|
|
1398
|
+
const spc = resp.space;
|
|
1399
|
+
if (spc) {
|
|
1400
|
+
const space = toSpace(spc);
|
|
1401
|
+
let os = SPACES_BY_ID_BY_ORGANISATION_ID.get(organizationId);
|
|
1402
|
+
if (!os) {
|
|
1403
|
+
os = new Map();
|
|
1404
|
+
SPACES_BY_ID_BY_ORGANISATION_ID.set(organizationId, os);
|
|
1405
|
+
}
|
|
1406
|
+
os.set(space.id, space);
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
return resp;
|
|
1410
|
+
});
|
|
1411
|
+
};
|
|
1412
|
+
const exportSpace = (spaceId) => {
|
|
1413
|
+
return requestDatalayer({
|
|
1414
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/spaces/${spaceId}/export`,
|
|
1415
|
+
method: 'GET',
|
|
1416
|
+
});
|
|
1417
|
+
};
|
|
1418
|
+
const updateOrganizationSpace = (organization, space) => {
|
|
1419
|
+
return requestDatalayer({
|
|
1420
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/spaces/${space.id}/organizations/${organization.id}`,
|
|
1421
|
+
method: 'PUT',
|
|
1422
|
+
body: {
|
|
1423
|
+
name: space.name,
|
|
1424
|
+
description: space.description,
|
|
1425
|
+
},
|
|
1426
|
+
}).then(resp => {
|
|
1427
|
+
if (resp.success) {
|
|
1428
|
+
const spc = getOrganizationSpace(organization.id, space.id);
|
|
1429
|
+
if (spc) {
|
|
1430
|
+
spc.name = space.name;
|
|
1431
|
+
spc.description = space.description;
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
return resp;
|
|
1435
|
+
});
|
|
1436
|
+
};
|
|
1437
|
+
const getOrganizationSpaces = (organizationId) => {
|
|
1438
|
+
const spaces = SPACES_BY_ID_BY_ORGANISATION_ID.get(organizationId);
|
|
1439
|
+
if (spaces) {
|
|
1440
|
+
return Array.from(spaces.values());
|
|
1441
|
+
}
|
|
1442
|
+
return [];
|
|
1443
|
+
};
|
|
1444
|
+
const refreshOrganizationSpaces = (organizationId) => {
|
|
1445
|
+
return requestDatalayer({
|
|
1446
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/spaces/organizations/${organizationId}`,
|
|
1447
|
+
method: 'GET',
|
|
1448
|
+
}).then(resp => {
|
|
1449
|
+
if (resp.success) {
|
|
1450
|
+
resp.spaces.forEach(org => {
|
|
1451
|
+
const space = toSpace(org);
|
|
1452
|
+
let organizationSpaces = SPACES_BY_ID_BY_ORGANISATION_ID.get(organizationId);
|
|
1453
|
+
if (!organizationSpaces) {
|
|
1454
|
+
organizationSpaces = new Map();
|
|
1455
|
+
SPACES_BY_ID_BY_ORGANISATION_ID.set(organizationId, organizationSpaces);
|
|
1456
|
+
}
|
|
1457
|
+
organizationSpaces.set(space.id, space);
|
|
1458
|
+
});
|
|
1459
|
+
}
|
|
1460
|
+
return resp;
|
|
1461
|
+
});
|
|
1462
|
+
};
|
|
1463
|
+
const getUserSpaces = () => Array.from(SPACES_FOR_USER_BY_ID.values());
|
|
1464
|
+
const refreshUserSpaces = () => {
|
|
1465
|
+
return requestDatalayer({
|
|
1466
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/spaces/users/me`,
|
|
1467
|
+
method: 'GET',
|
|
1468
|
+
}).then(resp => {
|
|
1469
|
+
if (resp.success) {
|
|
1470
|
+
resp.spaces.forEach(spc => {
|
|
1471
|
+
const space = toSpace(spc);
|
|
1472
|
+
SPACES_FOR_USER_BY_HANDLE.set(space.handle, space);
|
|
1473
|
+
SPACES_FOR_USER_BY_ID.set(space.id, space);
|
|
1474
|
+
});
|
|
1475
|
+
}
|
|
1476
|
+
return resp;
|
|
1477
|
+
});
|
|
1478
|
+
};
|
|
1479
|
+
const getUserSpace = (userId) => SPACES_FOR_USER_BY_ID.get(userId);
|
|
1480
|
+
const getUserSpaceByHandle = (userHandle) => SPACES_FOR_USER_BY_HANDLE.get(userHandle);
|
|
1481
|
+
const refreshUserSpace = (userId, spaceId) => {
|
|
1482
|
+
return requestDatalayer({
|
|
1483
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/spaces/${spaceId}/users/${userId}`,
|
|
1484
|
+
method: 'GET',
|
|
1485
|
+
}).then(resp => {
|
|
1486
|
+
if (resp.success) {
|
|
1487
|
+
const spc = resp.space;
|
|
1488
|
+
if (spc) {
|
|
1489
|
+
const space = toSpace(spc);
|
|
1490
|
+
SPACES_FOR_USER_BY_HANDLE.set(space.handle, space);
|
|
1491
|
+
SPACES_FOR_USER_BY_ID.set(spaceId, space);
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
return resp;
|
|
1495
|
+
});
|
|
1496
|
+
};
|
|
1497
|
+
const updateSpace = (space) => {
|
|
1498
|
+
return requestDatalayer({
|
|
1499
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/spaces/${space.id}/users/${user?.id}`,
|
|
1500
|
+
method: 'PUT',
|
|
1501
|
+
body: {
|
|
1502
|
+
name: space.name,
|
|
1503
|
+
description: space.description,
|
|
1504
|
+
},
|
|
1505
|
+
}).then(resp => {
|
|
1506
|
+
if (resp.success) {
|
|
1507
|
+
const spc = getUserSpace(space.id);
|
|
1508
|
+
if (spc) {
|
|
1509
|
+
spc.name = space.name;
|
|
1510
|
+
spc.description = space.description;
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
return resp;
|
|
1514
|
+
});
|
|
1515
|
+
};
|
|
1516
|
+
const addMemberToOrganizationSpace = (organizationId, spaceId, accountId) => {
|
|
1517
|
+
return requestDatalayer({
|
|
1518
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/spaces/${spaceId}/organizations/${organizationId}/members/${accountId}`,
|
|
1519
|
+
method: 'POST',
|
|
1520
|
+
});
|
|
1521
|
+
};
|
|
1522
|
+
const removeMemberFromOrganizationSpace = (organizationId, spaceId, accountId) => {
|
|
1523
|
+
return requestDatalayer({
|
|
1524
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/spaces/${spaceId}/organizations/${organizationId}/members/${accountId}`,
|
|
1525
|
+
method: 'DELETE',
|
|
1526
|
+
}).then(resp => {
|
|
1527
|
+
// if (resp.success) {
|
|
1528
|
+
// OR.delete(accountHandle);
|
|
1529
|
+
// }
|
|
1530
|
+
return resp;
|
|
1531
|
+
});
|
|
1532
|
+
};
|
|
1533
|
+
const makeSpacePublic = (spaceId) => {
|
|
1534
|
+
return requestDatalayer({
|
|
1535
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/spaces/${spaceId}/public`,
|
|
1536
|
+
method: 'PUT',
|
|
1537
|
+
});
|
|
1538
|
+
};
|
|
1539
|
+
const makeSpacePrivate = (spaceId) => {
|
|
1540
|
+
return requestDatalayer({
|
|
1541
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/spaces/${spaceId}/private`,
|
|
1542
|
+
method: 'PUT',
|
|
1543
|
+
});
|
|
1544
|
+
};
|
|
1545
|
+
// Courses -------------------------------------------------------------------
|
|
1546
|
+
const toStudentItem = (raw_student_item, itemId) => {
|
|
1547
|
+
const studentItem = {
|
|
1548
|
+
id: raw_student_item.uid,
|
|
1549
|
+
type: 'student_item',
|
|
1550
|
+
student: user,
|
|
1551
|
+
points: raw_student_item.points_i ?? 0,
|
|
1552
|
+
completed: raw_student_item.completed_b,
|
|
1553
|
+
itemId,
|
|
1554
|
+
itemType: raw_student_item.item_type_s,
|
|
1555
|
+
pass: raw_student_item.pass_b,
|
|
1556
|
+
codeStudent: raw_student_item.code_student_t,
|
|
1557
|
+
invalid: raw_student_item.invalid_b,
|
|
1558
|
+
invalidReason: raw_student_item.invalid_reason_t,
|
|
1559
|
+
nbgrades: raw_student_item.nbgrades,
|
|
1560
|
+
nbgradesTotalPoints: raw_student_item.nbgrades_total_points_f,
|
|
1561
|
+
nbgradesTotalScore: raw_student_item.nbgrades_total_score_f,
|
|
1562
|
+
};
|
|
1563
|
+
return studentItem;
|
|
1564
|
+
};
|
|
1565
|
+
const toStudent = (raw_student, courseId) => {
|
|
1566
|
+
let student = undefined;
|
|
1567
|
+
if (raw_student) {
|
|
1568
|
+
const user = toUser(raw_student);
|
|
1569
|
+
if (user) {
|
|
1570
|
+
let studentItems;
|
|
1571
|
+
if (raw_student.student_items) {
|
|
1572
|
+
studentItems = new Map();
|
|
1573
|
+
raw_student.student_items.forEach(raw_student_item => {
|
|
1574
|
+
const itemId = raw_student_item.item_uid;
|
|
1575
|
+
const studentItem = toStudentItem(raw_student_item, itemId);
|
|
1576
|
+
studentItems?.set(itemId, studentItem);
|
|
1577
|
+
});
|
|
1578
|
+
}
|
|
1579
|
+
student = {
|
|
1580
|
+
...user,
|
|
1581
|
+
studentItems,
|
|
1582
|
+
};
|
|
1583
|
+
STUDENTS_BY_ID.set(courseId + '-' + student.id, student);
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
return student;
|
|
1587
|
+
};
|
|
1588
|
+
const toCourse = (raw_course, cache) => {
|
|
1589
|
+
const owner = newUserMock();
|
|
1590
|
+
USERS_BY_ID.set(owner.id, owner);
|
|
1591
|
+
let instructor = undefined;
|
|
1592
|
+
if (raw_course.members) {
|
|
1593
|
+
let raw_instructor = raw_course.members;
|
|
1594
|
+
if (Array.isArray(raw_instructor)) {
|
|
1595
|
+
raw_instructor = raw_instructor[0];
|
|
1596
|
+
}
|
|
1597
|
+
instructor = {
|
|
1598
|
+
id: raw_instructor.uid,
|
|
1599
|
+
handle: raw_instructor.handle_s,
|
|
1600
|
+
email: raw_instructor.email_s,
|
|
1601
|
+
firstName: raw_instructor.first_name_t,
|
|
1602
|
+
lastName: raw_instructor.last_name_t,
|
|
1603
|
+
initials: namesAsInitials(raw_instructor.to_first_name_t, raw_instructor.to_last_name_t),
|
|
1604
|
+
displayName: asDisplayName(raw_instructor.first_name_t, raw_instructor.last_name_t),
|
|
1605
|
+
roles: [],
|
|
1606
|
+
iamProviders: [],
|
|
1607
|
+
setRoles: (roles) => { },
|
|
1608
|
+
unsubscribedFromOutbounds: false,
|
|
1609
|
+
onboarding: BOOTSTRAP_USER_ONBOARDING,
|
|
1610
|
+
linkedContactId: undefined,
|
|
1611
|
+
events: [],
|
|
1612
|
+
settings: {},
|
|
1613
|
+
};
|
|
1614
|
+
USERS_BY_ID.set(instructor.id, instructor);
|
|
1615
|
+
}
|
|
1616
|
+
let students = undefined;
|
|
1617
|
+
if (raw_course.students) {
|
|
1618
|
+
students = new Map();
|
|
1619
|
+
raw_course.students.forEach(raw_stud => {
|
|
1620
|
+
const student = toStudent(raw_stud, raw_course.uid);
|
|
1621
|
+
if (student) {
|
|
1622
|
+
students.set(student.id, student);
|
|
1623
|
+
}
|
|
1624
|
+
});
|
|
1625
|
+
}
|
|
1626
|
+
let itemIds = new Array();
|
|
1627
|
+
let raw_item_uids = raw_course.item_uids_s;
|
|
1628
|
+
if (raw_item_uids && raw_item_uids !== '()') {
|
|
1629
|
+
raw_item_uids = raw_item_uids.replace('(', '').replace(')', '');
|
|
1630
|
+
itemIds = raw_item_uids.split(' ');
|
|
1631
|
+
}
|
|
1632
|
+
const items = new Array();
|
|
1633
|
+
if (raw_course.items) {
|
|
1634
|
+
raw_course.items.forEach(item => {
|
|
1635
|
+
const i = toItem(item);
|
|
1636
|
+
items.push(i);
|
|
1637
|
+
});
|
|
1638
|
+
}
|
|
1639
|
+
const course = {
|
|
1640
|
+
id: raw_course.uid,
|
|
1641
|
+
handle: raw_course.handle_s,
|
|
1642
|
+
type: 'space',
|
|
1643
|
+
variant: 'course',
|
|
1644
|
+
name: raw_course.name_t,
|
|
1645
|
+
description: raw_course.description_t,
|
|
1646
|
+
creationDate: new Date(raw_course.creation_ts_dt),
|
|
1647
|
+
public: raw_course.public_b ?? false,
|
|
1648
|
+
items,
|
|
1649
|
+
itemIds,
|
|
1650
|
+
instructor,
|
|
1651
|
+
students,
|
|
1652
|
+
owner,
|
|
1653
|
+
};
|
|
1654
|
+
cache.set(course.id, course);
|
|
1655
|
+
return course;
|
|
1656
|
+
};
|
|
1657
|
+
const getCourse = (courseId) => COURSES_BY_ID.get(courseId);
|
|
1658
|
+
const updateCourse = (courseId, name, description) => {
|
|
1659
|
+
return requestDatalayer({
|
|
1660
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/courses/${courseId}`,
|
|
1661
|
+
method: 'PUT',
|
|
1662
|
+
body: {
|
|
1663
|
+
name,
|
|
1664
|
+
description,
|
|
1665
|
+
},
|
|
1666
|
+
});
|
|
1667
|
+
};
|
|
1668
|
+
const refreshCourse = (courseId) => {
|
|
1669
|
+
return requestDatalayer({
|
|
1670
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/courses/${courseId}`,
|
|
1671
|
+
method: 'GET',
|
|
1672
|
+
}).then(resp => {
|
|
1673
|
+
if (resp.success) {
|
|
1674
|
+
const raw_course = resp.course;
|
|
1675
|
+
if (raw_course) {
|
|
1676
|
+
toCourse(raw_course, COURSES_BY_ID);
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
return resp;
|
|
1680
|
+
});
|
|
1681
|
+
};
|
|
1682
|
+
const enrollStudentToCourse = (courseId, studentId) => {
|
|
1683
|
+
return requestDatalayer({
|
|
1684
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/courses/${courseId}/enrollments/students/${studentId}`,
|
|
1685
|
+
method: 'POST',
|
|
1686
|
+
});
|
|
1687
|
+
};
|
|
1688
|
+
const removeStudentFromCourse = (courseId, studentId) => {
|
|
1689
|
+
return requestDatalayer({
|
|
1690
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/courses/${courseId}/enrollments/students/${studentId}`,
|
|
1691
|
+
method: 'DELETE',
|
|
1692
|
+
}).then(resp => {
|
|
1693
|
+
if (resp.success) {
|
|
1694
|
+
STUDENTS_BY_ID.delete(courseId);
|
|
1695
|
+
}
|
|
1696
|
+
return resp;
|
|
1697
|
+
});
|
|
1698
|
+
};
|
|
1699
|
+
const getStudent = (courseId, studentId) => STUDENTS_BY_ID.get(courseId + '-' + studentId);
|
|
1700
|
+
const refreshStudent = (courseId, studentHandle) => {
|
|
1701
|
+
return requestDatalayer({
|
|
1702
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/courses/${courseId}/enrollments/students/${studentHandle}`,
|
|
1703
|
+
method: 'GET',
|
|
1704
|
+
}).then(resp => {
|
|
1705
|
+
if (resp.success) {
|
|
1706
|
+
toStudent(resp.student, courseId);
|
|
1707
|
+
}
|
|
1708
|
+
return resp;
|
|
1709
|
+
});
|
|
1710
|
+
};
|
|
1711
|
+
const getPublicCourses = () => Array.from(PUBLIC_COURSES_BY_ID.values());
|
|
1712
|
+
const refreshPublicCourses = () => {
|
|
1713
|
+
return requestDatalayer({
|
|
1714
|
+
url: `${configuration.libraryRunUrl}/api/library/v1/courses/public`,
|
|
1715
|
+
method: 'GET',
|
|
1716
|
+
}).then(resp => {
|
|
1717
|
+
if (resp.success) {
|
|
1718
|
+
resp.courses.forEach(course => {
|
|
1719
|
+
toCourse(course, PUBLIC_COURSES_BY_ID);
|
|
1720
|
+
});
|
|
1721
|
+
}
|
|
1722
|
+
return resp;
|
|
1723
|
+
});
|
|
1724
|
+
};
|
|
1725
|
+
const getInstructorCourses = () => Array.from(COURSES_INSTRUCTORS_BY_ID.values());
|
|
1726
|
+
const refreshInstructorCourses = () => {
|
|
1727
|
+
return requestDatalayer({
|
|
1728
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/instructors/${user?.id}/courses`,
|
|
1729
|
+
method: 'GET',
|
|
1730
|
+
}).then(resp => {
|
|
1731
|
+
if (resp.success) {
|
|
1732
|
+
resp.courses.forEach(course => {
|
|
1733
|
+
toCourse(course, COURSES_INSTRUCTORS_BY_ID);
|
|
1734
|
+
});
|
|
1735
|
+
}
|
|
1736
|
+
return resp;
|
|
1737
|
+
});
|
|
1738
|
+
};
|
|
1739
|
+
const getCoursesEnrollments = () => Array.from(COURSES_ENROLLMENTS_BY_ID.values());
|
|
1740
|
+
const refreshCoursesEnrollments = () => {
|
|
1741
|
+
return requestDatalayer({
|
|
1742
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/courses/enrollments/me`,
|
|
1743
|
+
method: 'GET',
|
|
1744
|
+
}).then(resp => {
|
|
1745
|
+
if (resp.success) {
|
|
1746
|
+
resp.enrollments.forEach(enrollment => {
|
|
1747
|
+
toCourse(enrollment, COURSES_ENROLLMENTS_BY_ID);
|
|
1748
|
+
});
|
|
1749
|
+
}
|
|
1750
|
+
return resp;
|
|
1751
|
+
});
|
|
1752
|
+
};
|
|
1753
|
+
const confirmCourseItemCompletion = (courseId, itemType, itemId, completed) => {
|
|
1754
|
+
return requestDatalayer({
|
|
1755
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/assignments/${courseId}/types/${itemType}/items/${itemId}/complete`,
|
|
1756
|
+
method: 'PUT',
|
|
1757
|
+
body: {
|
|
1758
|
+
completed,
|
|
1759
|
+
},
|
|
1760
|
+
});
|
|
1761
|
+
};
|
|
1762
|
+
const setCourseItems = (courseId, itemIds) => {
|
|
1763
|
+
return requestDatalayer({
|
|
1764
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/courses/${courseId}/items`,
|
|
1765
|
+
method: 'PUT',
|
|
1766
|
+
body: {
|
|
1767
|
+
itemIds,
|
|
1768
|
+
},
|
|
1769
|
+
});
|
|
1770
|
+
};
|
|
1771
|
+
// Surveys ---------------------------------------------------------------------
|
|
1772
|
+
const getUserSurveys = (userId) => {
|
|
1773
|
+
return requestDatalayer({
|
|
1774
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/surveys/users/${userId}`,
|
|
1775
|
+
method: 'GET',
|
|
1776
|
+
}).then(resp => {
|
|
1777
|
+
if (resp.success && resp.surveys) {
|
|
1778
|
+
const surveyArray = resp.surveys.map(survey => asSurvey(survey));
|
|
1779
|
+
const surveysMap = new Map();
|
|
1780
|
+
surveyArray.forEach(survey => surveysMap.set(survey.name, survey));
|
|
1781
|
+
resp.surveys = surveyArray;
|
|
1782
|
+
resp.surveysMap = surveysMap;
|
|
1783
|
+
}
|
|
1784
|
+
return resp;
|
|
1785
|
+
});
|
|
1786
|
+
};
|
|
1787
|
+
// Inbounds ---------------------------------------------------------------------
|
|
1788
|
+
const toInbound = (u) => {
|
|
1789
|
+
if (u) {
|
|
1790
|
+
const inbound = asInbound(u);
|
|
1791
|
+
INBOUNDS_BY_ID.set(inbound.id, inbound);
|
|
1792
|
+
INBOUNDS_BY_HANDLE.set(inbound.handle, inbound);
|
|
1793
|
+
return inbound;
|
|
1794
|
+
}
|
|
1795
|
+
};
|
|
1796
|
+
const getInbound = (id) => INBOUNDS_BY_ID.get(id);
|
|
1797
|
+
const getInboundByHandle = (handle) => INBOUNDS_BY_HANDLE.get(handle);
|
|
1798
|
+
const refreshInbound = (userId) => {
|
|
1799
|
+
return requestDatalayer({
|
|
1800
|
+
url: `${configuration.inboundsRunUrl}/api/inbounds/v1/inbounds/${userId}`,
|
|
1801
|
+
method: 'GET',
|
|
1802
|
+
}).then(resp => {
|
|
1803
|
+
if (resp.success) {
|
|
1804
|
+
toInbound(resp.user);
|
|
1805
|
+
}
|
|
1806
|
+
return resp;
|
|
1807
|
+
});
|
|
1808
|
+
};
|
|
1809
|
+
const getInbounds = () => {
|
|
1810
|
+
return requestDatalayer({
|
|
1811
|
+
url: `${configuration.inboundsRunUrl}/api/inbounds/v1/inbounds`,
|
|
1812
|
+
method: 'GET',
|
|
1813
|
+
}).then(resp => {
|
|
1814
|
+
if (resp.success) {
|
|
1815
|
+
const inbounds = resp.inbounds.map(user => toInbound(user));
|
|
1816
|
+
resp.inbounds = inbounds;
|
|
1817
|
+
}
|
|
1818
|
+
return resp;
|
|
1819
|
+
});
|
|
1820
|
+
};
|
|
1821
|
+
// Outbounds ---------------------------------------------------------------------
|
|
1822
|
+
const toOutbound = (u) => {
|
|
1823
|
+
if (u) {
|
|
1824
|
+
const user = asOutbound(u);
|
|
1825
|
+
OUTBOUNDS_BY_ID.set(user.id, user);
|
|
1826
|
+
return user;
|
|
1827
|
+
}
|
|
1828
|
+
};
|
|
1829
|
+
const getOutbound = (id) => OUTBOUNDS_BY_ID.get(id);
|
|
1830
|
+
const refreshOutbound = (outboundId) => {
|
|
1831
|
+
return requestDatalayer({
|
|
1832
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/outbounds/${outboundId}`,
|
|
1833
|
+
method: 'GET',
|
|
1834
|
+
}).then(resp => {
|
|
1835
|
+
if (resp.success) {
|
|
1836
|
+
const outbound = toOutbound(resp.outbound);
|
|
1837
|
+
resp.outbound = outbound;
|
|
1838
|
+
}
|
|
1839
|
+
return resp;
|
|
1840
|
+
});
|
|
1841
|
+
};
|
|
1842
|
+
const getOutbounds = () => {
|
|
1843
|
+
return requestDatalayer({
|
|
1844
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/outbounds`,
|
|
1845
|
+
method: 'GET',
|
|
1846
|
+
}).then(resp => {
|
|
1847
|
+
if (resp.success) {
|
|
1848
|
+
const outbounds = resp.outbounds.map(outbound => toOutbound(outbound));
|
|
1849
|
+
resp.outbounds = outbounds;
|
|
1850
|
+
}
|
|
1851
|
+
return resp;
|
|
1852
|
+
});
|
|
1853
|
+
};
|
|
1854
|
+
const draftBulkEmailsOutbounds = (params) => {
|
|
1855
|
+
return requestDatalayer({
|
|
1856
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/outbounds/emails/bulk/draft`,
|
|
1857
|
+
method: 'POST',
|
|
1858
|
+
body: params,
|
|
1859
|
+
});
|
|
1860
|
+
};
|
|
1861
|
+
const tryBulkEmailsOutbounds = (outboundId) => {
|
|
1862
|
+
return requestDatalayer({
|
|
1863
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/outbounds/${outboundId}/try`,
|
|
1864
|
+
method: 'POST',
|
|
1865
|
+
body: {},
|
|
1866
|
+
});
|
|
1867
|
+
};
|
|
1868
|
+
const launchBulkEmailsOutbounds = (outboundId) => {
|
|
1869
|
+
return requestDatalayer({
|
|
1870
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/outbounds/${outboundId}/launch`,
|
|
1871
|
+
method: 'POST',
|
|
1872
|
+
body: {},
|
|
1873
|
+
});
|
|
1874
|
+
};
|
|
1875
|
+
const sendOutboundEmailToUser = (userId, recipient, subject, content) => {
|
|
1876
|
+
return requestDatalayer({
|
|
1877
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/outbounds/email`,
|
|
1878
|
+
method: 'POST',
|
|
1879
|
+
body: {
|
|
1880
|
+
userId,
|
|
1881
|
+
recipient,
|
|
1882
|
+
subject,
|
|
1883
|
+
content,
|
|
1884
|
+
},
|
|
1885
|
+
});
|
|
1886
|
+
};
|
|
1887
|
+
const enableUserMFA = () => {
|
|
1888
|
+
return requestDatalayer({
|
|
1889
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/mfa`,
|
|
1890
|
+
method: 'PUT',
|
|
1891
|
+
});
|
|
1892
|
+
};
|
|
1893
|
+
const disableUserMFA = () => {
|
|
1894
|
+
return requestDatalayer({
|
|
1895
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/mfa`,
|
|
1896
|
+
method: 'DELETE',
|
|
1897
|
+
});
|
|
1898
|
+
};
|
|
1899
|
+
const validateUserMFACode = (userUid, code) => {
|
|
1900
|
+
return requestDatalayer({
|
|
1901
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/mfa`,
|
|
1902
|
+
method: 'POST',
|
|
1903
|
+
body: {
|
|
1904
|
+
userUid,
|
|
1905
|
+
code,
|
|
1906
|
+
},
|
|
1907
|
+
});
|
|
1908
|
+
};
|
|
1909
|
+
const subscribeUserToOutbounds = (userId) => {
|
|
1910
|
+
return requestDatalayer({
|
|
1911
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/outbounds/users/${userId}`,
|
|
1912
|
+
method: 'PUT',
|
|
1913
|
+
});
|
|
1914
|
+
};
|
|
1915
|
+
const unsubscribeUserFromOutbounds = (userId) => {
|
|
1916
|
+
return requestDatalayer({
|
|
1917
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/outbounds/users/${userId}`,
|
|
1918
|
+
method: 'DELETE',
|
|
1919
|
+
});
|
|
1920
|
+
};
|
|
1921
|
+
const unsubscribeContactFromOutbounds = (contactId) => {
|
|
1922
|
+
return requestDatalayer({
|
|
1923
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/contacts/unsubscribe/${contactId}`,
|
|
1924
|
+
method: 'GET',
|
|
1925
|
+
});
|
|
1926
|
+
};
|
|
1927
|
+
const unsubscribeInviteeFromOutbounds = (token) => {
|
|
1928
|
+
return requestDatalayer({
|
|
1929
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/outbounds/unsubscribe/${token}`,
|
|
1930
|
+
method: 'GET',
|
|
1931
|
+
});
|
|
1932
|
+
};
|
|
1933
|
+
const deleteOutbound = (outboundId) => {
|
|
1934
|
+
return requestDatalayer({
|
|
1935
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/outbounds/${outboundId}`,
|
|
1936
|
+
method: 'DELETE',
|
|
1937
|
+
});
|
|
1938
|
+
};
|
|
1939
|
+
// Items --------------------------------------------------------------
|
|
1940
|
+
const toItem = (item) => {
|
|
1941
|
+
if (!item.type_s) {
|
|
1942
|
+
console.error('No type_s found on item', item);
|
|
1943
|
+
return {};
|
|
1944
|
+
}
|
|
1945
|
+
switch (item.type_s) {
|
|
1946
|
+
case 'assignment':
|
|
1947
|
+
return toAssignment(item);
|
|
1948
|
+
case 'cell':
|
|
1949
|
+
return toCell(item);
|
|
1950
|
+
case 'dataset':
|
|
1951
|
+
return toDataset(item);
|
|
1952
|
+
case 'document':
|
|
1953
|
+
return toDocument(item);
|
|
1954
|
+
case 'exercise':
|
|
1955
|
+
return toExercise(item);
|
|
1956
|
+
case 'lesson':
|
|
1957
|
+
return toLesson(item);
|
|
1958
|
+
case 'notebook':
|
|
1959
|
+
return toNotebook(item);
|
|
1960
|
+
case 'page':
|
|
1961
|
+
return toPage(item);
|
|
1962
|
+
default:
|
|
1963
|
+
return {};
|
|
1964
|
+
}
|
|
1965
|
+
};
|
|
1966
|
+
const clearCachedPublicItems = () => PUBLIC_ITEMS_BY_ID.clear();
|
|
1967
|
+
const getPublicItems = () => Array.from(PUBLIC_ITEMS_BY_ID.values());
|
|
1968
|
+
const refreshPublicItems = () => {
|
|
1969
|
+
return requestDatalayer({
|
|
1970
|
+
url: `${configuration.libraryRunUrl}/api/library/v1/items/public`,
|
|
1971
|
+
method: 'GET',
|
|
1972
|
+
}).then(resp => {
|
|
1973
|
+
if (resp.success) {
|
|
1974
|
+
resp.items.forEach(i => {
|
|
1975
|
+
const item = toItem(i);
|
|
1976
|
+
PUBLIC_ITEMS_BY_ID.set(item.id, item);
|
|
1977
|
+
});
|
|
1978
|
+
}
|
|
1979
|
+
return resp;
|
|
1980
|
+
});
|
|
1981
|
+
};
|
|
1982
|
+
const getSpaceItems = () => Array.from(SPACE_ITEMS_CACHE.values());
|
|
1983
|
+
const refreshSpaceItems = (spaceId) => {
|
|
1984
|
+
return requestDatalayer({
|
|
1985
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/spaces/${spaceId}/items`,
|
|
1986
|
+
method: 'GET',
|
|
1987
|
+
}).then(resp => {
|
|
1988
|
+
if (resp.success) {
|
|
1989
|
+
if (resp.items) {
|
|
1990
|
+
asArray(resp.items).forEach(itm => {
|
|
1991
|
+
const item = toItem(itm);
|
|
1992
|
+
SPACE_ITEMS_CACHE.set(item.id, item);
|
|
1993
|
+
});
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
return resp;
|
|
1997
|
+
});
|
|
1998
|
+
};
|
|
1999
|
+
const makeItemPublic = (id) => {
|
|
2000
|
+
return requestDatalayer({
|
|
2001
|
+
url: `${configuration.libraryRunUrl}/api/library/v1/items/${id}/public`,
|
|
2002
|
+
method: 'PUT',
|
|
2003
|
+
});
|
|
2004
|
+
};
|
|
2005
|
+
const makeItemPrivate = (id) => {
|
|
2006
|
+
return requestDatalayer({
|
|
2007
|
+
url: `${configuration.libraryRunUrl}/api/library/v1/items/${id}/private`,
|
|
2008
|
+
method: 'PUT',
|
|
2009
|
+
});
|
|
2010
|
+
};
|
|
2011
|
+
const deleteItem = (itemId) => {
|
|
2012
|
+
return requestDatalayer({
|
|
2013
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/spaces/items/${itemId}`,
|
|
2014
|
+
method: 'DELETE',
|
|
2015
|
+
}).then(resp => {
|
|
2016
|
+
if (resp.success) {
|
|
2017
|
+
SPACE_ASSIGNMENTS_BY_ID.delete(itemId);
|
|
2018
|
+
SPACE_CELLS_BY_ID.delete(itemId);
|
|
2019
|
+
SPACE_DATASETS_BY_ID.delete(itemId);
|
|
2020
|
+
SPACE_DOCUMENTS_BY_ID.delete(itemId);
|
|
2021
|
+
SPACE_ENVIRONMENTS_BY_ID.delete(itemId);
|
|
2022
|
+
SPACE_EXERCISES_BY_ID.delete(itemId);
|
|
2023
|
+
SPACE_ITEMS_CACHE.delete(itemId);
|
|
2024
|
+
SPACE_LESSONS_BY_ID.delete(itemId);
|
|
2025
|
+
SPACE_NOTEBOOKS_BY_ID.delete(itemId);
|
|
2026
|
+
}
|
|
2027
|
+
return resp;
|
|
2028
|
+
});
|
|
2029
|
+
};
|
|
2030
|
+
// Search ------------------------------------------------------------------
|
|
2031
|
+
const searchPublicItems = (opts = DEFAULT_SEARCH_OPTS) => {
|
|
2032
|
+
const { q, types, max } = opts;
|
|
2033
|
+
const queryArgs = {
|
|
2034
|
+
q,
|
|
2035
|
+
types: `${types.join(' ')}`,
|
|
2036
|
+
max: max.toFixed(0).toString(),
|
|
2037
|
+
public: 'true',
|
|
2038
|
+
};
|
|
2039
|
+
return requestDatalayer({
|
|
2040
|
+
url: `${configuration.libraryRunUrl}/api/library/v1/search${URLExt.objectToQueryString(queryArgs)}`,
|
|
2041
|
+
method: 'GET',
|
|
2042
|
+
}).then(resp => {
|
|
2043
|
+
if (resp.success) {
|
|
2044
|
+
const items = new Array();
|
|
2045
|
+
resp.items.forEach(i => {
|
|
2046
|
+
const item = toItem(i);
|
|
2047
|
+
items.push(item);
|
|
2048
|
+
});
|
|
2049
|
+
resp.items = items;
|
|
2050
|
+
}
|
|
2051
|
+
return resp;
|
|
2052
|
+
});
|
|
2053
|
+
};
|
|
2054
|
+
// Datasets ------------------------------------------------------------------
|
|
2055
|
+
const toDataset = raw_dataset => {
|
|
2056
|
+
const owner = newUserMock();
|
|
2057
|
+
USERS_BY_ID.set(owner.id, owner);
|
|
2058
|
+
const dataset = {
|
|
2059
|
+
id: raw_dataset.uid,
|
|
2060
|
+
type: 'dataset',
|
|
2061
|
+
name: raw_dataset.name_t,
|
|
2062
|
+
description: raw_dataset.description_t,
|
|
2063
|
+
fileName: raw_dataset.file_name_s,
|
|
2064
|
+
datasetExtension: raw_dataset.dataset_extension_s,
|
|
2065
|
+
contentLength: raw_dataset.content_length_i,
|
|
2066
|
+
contentType: raw_dataset.content_type_s,
|
|
2067
|
+
mimeType: raw_dataset.mimetype_s,
|
|
2068
|
+
path: raw_dataset.s3_path_s,
|
|
2069
|
+
cdnUrl: raw_dataset.cdn_url_s,
|
|
2070
|
+
creationDate: new Date(raw_dataset.creation_ts_dt),
|
|
2071
|
+
public: raw_dataset.public_b ?? false,
|
|
2072
|
+
lastPublicationDate: raw_dataset.creation_ts_dt
|
|
2073
|
+
? new Date(raw_dataset.creation_ts_dt)
|
|
2074
|
+
: undefined,
|
|
2075
|
+
owner,
|
|
2076
|
+
space: {
|
|
2077
|
+
handle: raw_dataset.handle_s,
|
|
2078
|
+
},
|
|
2079
|
+
organization: {
|
|
2080
|
+
handle: raw_dataset.handle_s,
|
|
2081
|
+
},
|
|
2082
|
+
};
|
|
2083
|
+
SPACE_DATASETS_BY_ID.set(dataset.id, dataset);
|
|
2084
|
+
return dataset;
|
|
2085
|
+
};
|
|
2086
|
+
const getDataset = id => SPACE_DATASETS_BY_ID.get(id);
|
|
2087
|
+
const refreshDataset = (id) => {
|
|
2088
|
+
return requestDatalayer({
|
|
2089
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/spaces/items/${id}`,
|
|
2090
|
+
method: 'GET',
|
|
2091
|
+
}).then(resp => {
|
|
2092
|
+
if (resp.success) {
|
|
2093
|
+
const d = resp.item;
|
|
2094
|
+
if (d) {
|
|
2095
|
+
toDataset(d);
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
return resp;
|
|
2099
|
+
});
|
|
2100
|
+
};
|
|
2101
|
+
const getSpaceDatasets = () => Array.from(SPACE_DATASETS_BY_ID.values());
|
|
2102
|
+
const refreshSpaceDatasets = (space, organization) => {
|
|
2103
|
+
const url = `${configuration.spacerRunUrl}/api/spacer/v1/spaces/${space.id}/items/types/dataset`;
|
|
2104
|
+
return requestDatalayer({
|
|
2105
|
+
url,
|
|
2106
|
+
method: 'GET',
|
|
2107
|
+
}).then(resp => {
|
|
2108
|
+
if (resp.success) {
|
|
2109
|
+
resp.items.forEach(d => {
|
|
2110
|
+
toDataset(d);
|
|
2111
|
+
});
|
|
2112
|
+
}
|
|
2113
|
+
return resp;
|
|
2114
|
+
});
|
|
2115
|
+
};
|
|
2116
|
+
const updateDataset = (id, name, description) => {
|
|
2117
|
+
return requestDatalayer({
|
|
2118
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/datasets/${id}`,
|
|
2119
|
+
method: 'PUT',
|
|
2120
|
+
body: {
|
|
2121
|
+
name,
|
|
2122
|
+
description,
|
|
2123
|
+
},
|
|
2124
|
+
});
|
|
2125
|
+
};
|
|
2126
|
+
// Cells ------------------------------------------------------------------
|
|
2127
|
+
const toCell = cl => {
|
|
2128
|
+
const owner = newUserMock();
|
|
2129
|
+
USERS_BY_ID.set(owner.id, owner);
|
|
2130
|
+
const cell = {
|
|
2131
|
+
id: cl.uid,
|
|
2132
|
+
type: 'cell',
|
|
2133
|
+
name: cl.name_t,
|
|
2134
|
+
description: cl.description_t,
|
|
2135
|
+
source: cl.source_t,
|
|
2136
|
+
creationDate: new Date(cl.creation_ts_dt),
|
|
2137
|
+
public: cl.public_b ?? false,
|
|
2138
|
+
lastPublicationDate: cl.last_publication_ts_dt
|
|
2139
|
+
? new Date(cl.last_publication_ts_dt)
|
|
2140
|
+
: undefined,
|
|
2141
|
+
outputshotUrl: cl.outputshot_url_s || '',
|
|
2142
|
+
outputshotData: OUTPUTSHOT_PLACEHOLDER_DEFAULT_SVG,
|
|
2143
|
+
owner,
|
|
2144
|
+
space: {
|
|
2145
|
+
handle: cl.handle_s,
|
|
2146
|
+
},
|
|
2147
|
+
organization: {
|
|
2148
|
+
handle: cl.handle_s,
|
|
2149
|
+
},
|
|
2150
|
+
};
|
|
2151
|
+
SPACE_CELLS_BY_ID.set(cell.id, cell);
|
|
2152
|
+
return cell;
|
|
2153
|
+
};
|
|
2154
|
+
const getCell = (id) => SPACE_CELLS_BY_ID.get(id);
|
|
2155
|
+
const refreshCell = (id) => {
|
|
2156
|
+
return requestDatalayer({
|
|
2157
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/spaces/items/${id}`,
|
|
2158
|
+
method: 'GET',
|
|
2159
|
+
}).then(resp => {
|
|
2160
|
+
if (resp.success) {
|
|
2161
|
+
const cell = resp.item;
|
|
2162
|
+
if (cell) {
|
|
2163
|
+
toCell(cell);
|
|
2164
|
+
}
|
|
2165
|
+
}
|
|
2166
|
+
return resp;
|
|
2167
|
+
});
|
|
2168
|
+
};
|
|
2169
|
+
const getSpaceCells = () => Array.from(SPACE_CELLS_BY_ID.values());
|
|
2170
|
+
const refreshSpaceCells = (space, organization) => {
|
|
2171
|
+
const url = `${configuration.spacerRunUrl}/api/spacer/v1/spaces/${space.id}/items/types/cell`;
|
|
2172
|
+
return requestDatalayer({
|
|
2173
|
+
url,
|
|
2174
|
+
method: 'GET',
|
|
2175
|
+
}).then(resp => {
|
|
2176
|
+
if (resp.success) {
|
|
2177
|
+
resp.items.forEach(cell => {
|
|
2178
|
+
toCell(cell);
|
|
2179
|
+
});
|
|
2180
|
+
}
|
|
2181
|
+
return resp;
|
|
2182
|
+
});
|
|
2183
|
+
};
|
|
2184
|
+
const updateCell = (cell) => {
|
|
2185
|
+
return requestDatalayer({
|
|
2186
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/cells/${cell.id}`,
|
|
2187
|
+
method: 'PUT',
|
|
2188
|
+
body: cell,
|
|
2189
|
+
});
|
|
2190
|
+
};
|
|
2191
|
+
const cloneCell = (cellId) => {
|
|
2192
|
+
return requestDatalayer({
|
|
2193
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/cells/${cellId}/clone`,
|
|
2194
|
+
method: 'POST',
|
|
2195
|
+
}).then(resp => {
|
|
2196
|
+
if (resp.success) {
|
|
2197
|
+
toCell(resp.cell);
|
|
2198
|
+
}
|
|
2199
|
+
return resp;
|
|
2200
|
+
});
|
|
2201
|
+
};
|
|
2202
|
+
// Notebooks ------------------------------------------------------------------
|
|
2203
|
+
const toNotebook = raw_notebook => {
|
|
2204
|
+
const owner = newUserMock();
|
|
2205
|
+
USERS_BY_ID.set(owner.id, owner);
|
|
2206
|
+
const notebook = {
|
|
2207
|
+
id: raw_notebook.uid,
|
|
2208
|
+
type: 'notebook',
|
|
2209
|
+
name: raw_notebook.name_t,
|
|
2210
|
+
description: raw_notebook.description_t,
|
|
2211
|
+
nbformat: raw_notebook.model_s
|
|
2212
|
+
? JSON.parse(raw_notebook.model_s)
|
|
2213
|
+
: undefined,
|
|
2214
|
+
public: raw_notebook.public_b ?? false,
|
|
2215
|
+
creationDate: new Date(raw_notebook.creation_ts_dt),
|
|
2216
|
+
lastUpdateDate: raw_notebook.last_update_ts_dt
|
|
2217
|
+
? new Date(raw_notebook.last_update_ts_dt)
|
|
2218
|
+
: undefined,
|
|
2219
|
+
lastPublicationDate: raw_notebook.creation_ts_dt
|
|
2220
|
+
? new Date(raw_notebook.creation_ts_dt)
|
|
2221
|
+
: undefined,
|
|
2222
|
+
datasets: [],
|
|
2223
|
+
owner,
|
|
2224
|
+
space: {
|
|
2225
|
+
handle: raw_notebook.handle_s,
|
|
2226
|
+
},
|
|
2227
|
+
organization: {
|
|
2228
|
+
handle: raw_notebook.handle_s,
|
|
2229
|
+
},
|
|
2230
|
+
};
|
|
2231
|
+
SPACE_NOTEBOOKS_BY_ID.set(notebook.id, notebook);
|
|
2232
|
+
return notebook;
|
|
2233
|
+
};
|
|
2234
|
+
const getNotebook = notebookId => SPACE_NOTEBOOKS_BY_ID.get(notebookId);
|
|
2235
|
+
const refreshNotebook = (notebookId) => {
|
|
2236
|
+
return requestDatalayer({
|
|
2237
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/notebooks/${notebookId}`,
|
|
2238
|
+
method: 'GET',
|
|
2239
|
+
}).then(resp => {
|
|
2240
|
+
if (resp.success) {
|
|
2241
|
+
const notebook = resp.notebook;
|
|
2242
|
+
if (notebook) {
|
|
2243
|
+
toNotebook(notebook);
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
return resp;
|
|
2247
|
+
});
|
|
2248
|
+
};
|
|
2249
|
+
const getSpaceNotebooks = () => Array.from(SPACE_NOTEBOOKS_BY_ID.values());
|
|
2250
|
+
const getSpaceNotebook = id => SPACE_NOTEBOOKS_BY_ID.get(id);
|
|
2251
|
+
const refreshSpaceNotebooks = (space, organization) => {
|
|
2252
|
+
const url = `${configuration.spacerRunUrl}/api/spacer/v1/spaces/${space.id}/items/types/notebook`;
|
|
2253
|
+
return requestDatalayer({
|
|
2254
|
+
url,
|
|
2255
|
+
method: 'GET',
|
|
2256
|
+
}).then(resp => {
|
|
2257
|
+
if (resp.success) {
|
|
2258
|
+
resp.items.forEach(n => {
|
|
2259
|
+
toNotebook(n);
|
|
2260
|
+
});
|
|
2261
|
+
}
|
|
2262
|
+
return resp;
|
|
2263
|
+
});
|
|
2264
|
+
};
|
|
2265
|
+
const cloneNotebook = (notebookId) => {
|
|
2266
|
+
return requestDatalayer({
|
|
2267
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/notebooks/${notebookId}/clone`,
|
|
2268
|
+
method: 'POST',
|
|
2269
|
+
}).then(resp => {
|
|
2270
|
+
if (resp.success) {
|
|
2271
|
+
toNotebook(resp.notebook);
|
|
2272
|
+
}
|
|
2273
|
+
return resp;
|
|
2274
|
+
});
|
|
2275
|
+
};
|
|
2276
|
+
const createNotebook = async (spaceId, name, description, notebookType = 'notebook') => {
|
|
2277
|
+
// Create FormData for the upload
|
|
2278
|
+
const formData = new FormData();
|
|
2279
|
+
formData.append('spaceId', spaceId);
|
|
2280
|
+
formData.append('notebookType', notebookType);
|
|
2281
|
+
formData.append('name', name);
|
|
2282
|
+
formData.append('description', description || '');
|
|
2283
|
+
try {
|
|
2284
|
+
const resp = await uploadNotebook(formData);
|
|
2285
|
+
if (resp.success) {
|
|
2286
|
+
if (resp.notebook) {
|
|
2287
|
+
toNotebook(resp.notebook);
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
2290
|
+
return resp;
|
|
2291
|
+
}
|
|
2292
|
+
catch (error) {
|
|
2293
|
+
console.error('Failed to create notebook:', error);
|
|
2294
|
+
return { success: false, error };
|
|
2295
|
+
}
|
|
2296
|
+
};
|
|
2297
|
+
const updateNotebook = (id, name, description) => {
|
|
2298
|
+
return requestDatalayer({
|
|
2299
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/notebooks/${id}`,
|
|
2300
|
+
method: 'PUT',
|
|
2301
|
+
body: {
|
|
2302
|
+
name,
|
|
2303
|
+
description,
|
|
2304
|
+
},
|
|
2305
|
+
});
|
|
2306
|
+
};
|
|
2307
|
+
const updateNotebookModel = (notebookId, nbformat) => {
|
|
2308
|
+
return requestDatalayer({
|
|
2309
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/notebooks/${notebookId}/model`,
|
|
2310
|
+
method: 'PUT',
|
|
2311
|
+
body: {
|
|
2312
|
+
nbformat,
|
|
2313
|
+
},
|
|
2314
|
+
});
|
|
2315
|
+
};
|
|
2316
|
+
// Documents ------------------------------------------------------------------
|
|
2317
|
+
const toDocument = doc => {
|
|
2318
|
+
const owner = newUserMock();
|
|
2319
|
+
USERS_BY_ID.set(owner.id, owner);
|
|
2320
|
+
const document = {
|
|
2321
|
+
id: doc.uid,
|
|
2322
|
+
type: 'document',
|
|
2323
|
+
name: doc.name_t,
|
|
2324
|
+
description: doc.description_t,
|
|
2325
|
+
model: doc.model_s ? JSON.parse(doc.model_s) : undefined,
|
|
2326
|
+
public: doc.public_b ?? false,
|
|
2327
|
+
creationDate: new Date(doc.creation_ts_dt),
|
|
2328
|
+
lastUpdateDate: doc.last_update_ts_dt
|
|
2329
|
+
? new Date(doc.last_update_ts_dt)
|
|
2330
|
+
: undefined,
|
|
2331
|
+
lastPublicationDate: doc.creation_ts_dt
|
|
2332
|
+
? new Date(doc.creation_ts_dt)
|
|
2333
|
+
: undefined,
|
|
2334
|
+
owner,
|
|
2335
|
+
space: {
|
|
2336
|
+
handle: doc.handle_s,
|
|
2337
|
+
},
|
|
2338
|
+
organization: {
|
|
2339
|
+
handle: doc.handle_s,
|
|
2340
|
+
},
|
|
2341
|
+
};
|
|
2342
|
+
SPACE_DOCUMENTS_BY_ID.set(document.id, document);
|
|
2343
|
+
return document;
|
|
2344
|
+
};
|
|
2345
|
+
const getDocument = id => SPACE_DOCUMENTS_BY_ID.get(id);
|
|
2346
|
+
const refreshDocument = (id) => {
|
|
2347
|
+
return requestDatalayer({
|
|
2348
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/lexicals/${id}`,
|
|
2349
|
+
method: 'GET',
|
|
2350
|
+
}).then(resp => {
|
|
2351
|
+
if (resp.success) {
|
|
2352
|
+
const document = resp.document;
|
|
2353
|
+
if (document) {
|
|
2354
|
+
toDocument(document);
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
return resp;
|
|
2358
|
+
});
|
|
2359
|
+
};
|
|
2360
|
+
const getSpaceDocuments = () => Array.from(SPACE_DOCUMENTS_BY_ID.values());
|
|
2361
|
+
const getSpaceDocument = id => SPACE_DOCUMENTS_BY_ID.get(id);
|
|
2362
|
+
const refreshSpaceDocuments = (space, organization) => {
|
|
2363
|
+
const url = `${configuration.spacerRunUrl}/api/spacer/v1/spaces/${space.id}/items/types/document`;
|
|
2364
|
+
return requestDatalayer({
|
|
2365
|
+
url,
|
|
2366
|
+
method: 'GET',
|
|
2367
|
+
}).then(resp => {
|
|
2368
|
+
if (resp.success) {
|
|
2369
|
+
resp.items.forEach(n => {
|
|
2370
|
+
toDocument(n);
|
|
2371
|
+
});
|
|
2372
|
+
}
|
|
2373
|
+
return resp;
|
|
2374
|
+
});
|
|
2375
|
+
};
|
|
2376
|
+
const cloneDocument = (documentId) => {
|
|
2377
|
+
return requestDatalayer({
|
|
2378
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/lexicals/${documentId}/clone`,
|
|
2379
|
+
method: 'POST',
|
|
2380
|
+
}).then(resp => {
|
|
2381
|
+
if (resp.success) {
|
|
2382
|
+
toDocument(resp.document);
|
|
2383
|
+
}
|
|
2384
|
+
return resp;
|
|
2385
|
+
});
|
|
2386
|
+
};
|
|
2387
|
+
const updateDocument = (id, name, description) => {
|
|
2388
|
+
return requestDatalayer({
|
|
2389
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/lexicals/${id}`,
|
|
2390
|
+
method: 'PUT',
|
|
2391
|
+
body: {
|
|
2392
|
+
name,
|
|
2393
|
+
description,
|
|
2394
|
+
},
|
|
2395
|
+
});
|
|
2396
|
+
};
|
|
2397
|
+
const updateDocumentModel = (id, model) => {
|
|
2398
|
+
return requestDatalayer({
|
|
2399
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/lexicals/${id}/model`,
|
|
2400
|
+
method: 'PUT',
|
|
2401
|
+
body: {
|
|
2402
|
+
model,
|
|
2403
|
+
},
|
|
2404
|
+
});
|
|
2405
|
+
};
|
|
2406
|
+
// Environments ------------------------------------------------------------------
|
|
2407
|
+
const toEnvironment = (env, cache) => {
|
|
2408
|
+
const owner = newUserMock();
|
|
2409
|
+
USERS_BY_ID.set(owner.id, owner);
|
|
2410
|
+
const environment = {
|
|
2411
|
+
id: env.uid,
|
|
2412
|
+
type: 'environment',
|
|
2413
|
+
name: env.name_t,
|
|
2414
|
+
description: env.description_t,
|
|
2415
|
+
creationDate: new Date(env.creation_ts_dt),
|
|
2416
|
+
public: env.public_b ?? false,
|
|
2417
|
+
lastPublicationDate: env.creation_ts_dt
|
|
2418
|
+
? new Date(env.creation_ts_dt)
|
|
2419
|
+
: undefined,
|
|
2420
|
+
owner,
|
|
2421
|
+
space: {
|
|
2422
|
+
handle: env.handle_s,
|
|
2423
|
+
},
|
|
2424
|
+
organization: {
|
|
2425
|
+
handle: env.handle_s,
|
|
2426
|
+
},
|
|
2427
|
+
};
|
|
2428
|
+
cache.set(environment.id, environment);
|
|
2429
|
+
return environment;
|
|
2430
|
+
};
|
|
2431
|
+
const getEnvironment = (id) => SPACE_ENVIRONMENTS_BY_ID.get(id);
|
|
2432
|
+
const refreshEnvironment = (id) => {
|
|
2433
|
+
return requestDatalayer({
|
|
2434
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/spaces/items/${id}`,
|
|
2435
|
+
method: 'GET',
|
|
2436
|
+
}).then(resp => {
|
|
2437
|
+
if (resp.success) {
|
|
2438
|
+
const env = resp.item;
|
|
2439
|
+
if (env) {
|
|
2440
|
+
toEnvironment(env, SPACE_ENVIRONMENTS_BY_ID);
|
|
2441
|
+
}
|
|
2442
|
+
}
|
|
2443
|
+
return resp;
|
|
2444
|
+
});
|
|
2445
|
+
};
|
|
2446
|
+
const getSpaceEnvironments = () => Array.from(SPACE_ENVIRONMENTS_BY_ID.values());
|
|
2447
|
+
const refreshSpaceEnvironments = (space, organization) => {
|
|
2448
|
+
const url = `${configuration.spacerRunUrl}/api/spacer/v1/spaces/${space.id}/items/types/environment`;
|
|
2449
|
+
return requestDatalayer({
|
|
2450
|
+
url,
|
|
2451
|
+
method: 'GET',
|
|
2452
|
+
}).then(resp => {
|
|
2453
|
+
if (resp.success) {
|
|
2454
|
+
resp.items.forEach(d => {
|
|
2455
|
+
toEnvironment(d, SPACE_ENVIRONMENTS_BY_ID);
|
|
2456
|
+
});
|
|
2457
|
+
}
|
|
2458
|
+
return resp;
|
|
2459
|
+
});
|
|
2460
|
+
};
|
|
2461
|
+
// Lessons ------------------------------------------------------------------
|
|
2462
|
+
const toLesson = raw_lesson => {
|
|
2463
|
+
const owner = newUserMock();
|
|
2464
|
+
USERS_BY_ID.set(owner.id, owner);
|
|
2465
|
+
const lesson = {
|
|
2466
|
+
id: raw_lesson.uid,
|
|
2467
|
+
type: 'lesson',
|
|
2468
|
+
name: raw_lesson.name_t,
|
|
2469
|
+
description: raw_lesson.description_t,
|
|
2470
|
+
nbformat: raw_lesson.model_s ? JSON.parse(raw_lesson.model_s) : undefined,
|
|
2471
|
+
public: raw_lesson.public_b ?? false,
|
|
2472
|
+
creationDate: new Date(raw_lesson.creation_ts_dt),
|
|
2473
|
+
lastUpdateDate: raw_lesson.last_update_ts_dt
|
|
2474
|
+
? new Date(raw_lesson.last_update_ts_dt)
|
|
2475
|
+
: undefined,
|
|
2476
|
+
lastPublicationDate: raw_lesson.creation_ts_dt
|
|
2477
|
+
? new Date(raw_lesson.creation_ts_dt)
|
|
2478
|
+
: undefined,
|
|
2479
|
+
owner,
|
|
2480
|
+
space: {
|
|
2481
|
+
handle: raw_lesson.handle_s,
|
|
2482
|
+
},
|
|
2483
|
+
organization: {
|
|
2484
|
+
handle: raw_lesson.handle_s,
|
|
2485
|
+
},
|
|
2486
|
+
datasets: [],
|
|
2487
|
+
};
|
|
2488
|
+
SPACE_LESSONS_BY_ID.set(lesson.id, lesson);
|
|
2489
|
+
return lesson;
|
|
2490
|
+
};
|
|
2491
|
+
const getLesson = id => SPACE_LESSONS_BY_ID.get(id);
|
|
2492
|
+
const refreshLesson = (id) => {
|
|
2493
|
+
return requestDatalayer({
|
|
2494
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/lessons/${id}`,
|
|
2495
|
+
method: 'GET',
|
|
2496
|
+
}).then(resp => {
|
|
2497
|
+
if (resp.success) {
|
|
2498
|
+
const lesson = resp.lesson;
|
|
2499
|
+
if (lesson) {
|
|
2500
|
+
toLesson(lesson);
|
|
2501
|
+
}
|
|
2502
|
+
}
|
|
2503
|
+
return resp;
|
|
2504
|
+
});
|
|
2505
|
+
};
|
|
2506
|
+
const getSpaceLessons = () => Array.from(SPACE_LESSONS_BY_ID.values());
|
|
2507
|
+
const getSpaceLesson = id => SPACE_LESSONS_BY_ID.get(id);
|
|
2508
|
+
const refreshSpaceLessons = (space, organization) => {
|
|
2509
|
+
const url = `${configuration.spacerRunUrl}/api/spacer/v1/spaces/${space.id}/items/types/lesson`;
|
|
2510
|
+
return requestDatalayer({
|
|
2511
|
+
url,
|
|
2512
|
+
method: 'GET',
|
|
2513
|
+
}).then(resp => {
|
|
2514
|
+
if (resp.success) {
|
|
2515
|
+
resp.items.forEach(n => {
|
|
2516
|
+
toLesson(n);
|
|
2517
|
+
});
|
|
2518
|
+
}
|
|
2519
|
+
return resp;
|
|
2520
|
+
});
|
|
2521
|
+
};
|
|
2522
|
+
const cloneLesson = (lessonId) => {
|
|
2523
|
+
return requestDatalayer({
|
|
2524
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/notebooks/${lessonId}/clone`,
|
|
2525
|
+
method: 'POST',
|
|
2526
|
+
}).then(resp => {
|
|
2527
|
+
if (resp.success) {
|
|
2528
|
+
toLesson(resp.notebook);
|
|
2529
|
+
}
|
|
2530
|
+
return resp;
|
|
2531
|
+
});
|
|
2532
|
+
};
|
|
2533
|
+
// Exercises ------------------------------------------------------------------
|
|
2534
|
+
const toExercise = (ex) => {
|
|
2535
|
+
const owner = newUserMock();
|
|
2536
|
+
USERS_BY_ID.set(owner.id, owner);
|
|
2537
|
+
const exercise = {
|
|
2538
|
+
id: ex.uid,
|
|
2539
|
+
type: 'exercise',
|
|
2540
|
+
name: ex.name_t,
|
|
2541
|
+
description: ex.description_t,
|
|
2542
|
+
help: ex.help_t,
|
|
2543
|
+
codePre: ex.code_pre_t,
|
|
2544
|
+
codeQuestion: ex.code_question_t,
|
|
2545
|
+
codeSolution: ex.code_solution_t,
|
|
2546
|
+
codeTest: ex.code_test_t,
|
|
2547
|
+
public: ex.public_b ?? false,
|
|
2548
|
+
creationDate: new Date(ex.creation_ts_dt),
|
|
2549
|
+
lastUpdateDate: ex.last_update_ts_dt
|
|
2550
|
+
? new Date(ex.last_update_ts_dt)
|
|
2551
|
+
: undefined,
|
|
2552
|
+
lastPublicationDate: ex.creation_ts_dt
|
|
2553
|
+
? new Date(ex.creation_ts_dt)
|
|
2554
|
+
: undefined,
|
|
2555
|
+
owner,
|
|
2556
|
+
space: {
|
|
2557
|
+
handle: ex.handle_s,
|
|
2558
|
+
},
|
|
2559
|
+
organization: {
|
|
2560
|
+
handle: ex.handle_s,
|
|
2561
|
+
},
|
|
2562
|
+
datasets: [],
|
|
2563
|
+
};
|
|
2564
|
+
SPACE_EXERCISES_BY_ID.set(exercise.id, exercise);
|
|
2565
|
+
return exercise;
|
|
2566
|
+
};
|
|
2567
|
+
const getExercise = (id) => SPACE_EXERCISES_BY_ID.get(id);
|
|
2568
|
+
const refreshExercise = (id) => {
|
|
2569
|
+
return requestDatalayer({
|
|
2570
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/spaces/items/${id}`,
|
|
2571
|
+
method: 'GET',
|
|
2572
|
+
}).then(resp => {
|
|
2573
|
+
if (resp.success) {
|
|
2574
|
+
const exercise = resp.item;
|
|
2575
|
+
if (exercise) {
|
|
2576
|
+
toExercise(exercise);
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2579
|
+
return resp;
|
|
2580
|
+
});
|
|
2581
|
+
};
|
|
2582
|
+
const getSpaceExercises = () => {
|
|
2583
|
+
return Array.from(SPACE_EXERCISES_BY_ID.values());
|
|
2584
|
+
};
|
|
2585
|
+
const refreshSpaceExercises = (space, organization) => {
|
|
2586
|
+
const url = `${configuration.spacerRunUrl}/api/spacer/v1/spaces/${space.id}/items/types/exercise`;
|
|
2587
|
+
return requestDatalayer({
|
|
2588
|
+
url,
|
|
2589
|
+
method: 'GET',
|
|
2590
|
+
}).then(resp => {
|
|
2591
|
+
if (resp.success) {
|
|
2592
|
+
resp.items.forEach(d => {
|
|
2593
|
+
toExercise(d);
|
|
2594
|
+
});
|
|
2595
|
+
}
|
|
2596
|
+
return resp;
|
|
2597
|
+
});
|
|
2598
|
+
};
|
|
2599
|
+
const cloneExercise = (exerciseId) => {
|
|
2600
|
+
return requestDatalayer({
|
|
2601
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/exercises/${exerciseId}/clone`,
|
|
2602
|
+
method: 'POST',
|
|
2603
|
+
}).then(resp => {
|
|
2604
|
+
if (resp.success) {
|
|
2605
|
+
toExercise(resp.exercise);
|
|
2606
|
+
}
|
|
2607
|
+
return resp;
|
|
2608
|
+
});
|
|
2609
|
+
};
|
|
2610
|
+
const updateExercise = ({ id, name, description, help, codePre, codeSolution, codeQuestion, codeTest, }) => {
|
|
2611
|
+
return requestDatalayer({
|
|
2612
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/exercises/${id}`,
|
|
2613
|
+
method: 'PUT',
|
|
2614
|
+
body: {
|
|
2615
|
+
name,
|
|
2616
|
+
description,
|
|
2617
|
+
help,
|
|
2618
|
+
codePre,
|
|
2619
|
+
codeSolution,
|
|
2620
|
+
codeQuestion,
|
|
2621
|
+
codeTest,
|
|
2622
|
+
},
|
|
2623
|
+
});
|
|
2624
|
+
};
|
|
2625
|
+
const updateExercisePoints = (id, codeStudent, points) => {
|
|
2626
|
+
return requestDatalayer({
|
|
2627
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/exercises/${id}/points`,
|
|
2628
|
+
method: 'PUT',
|
|
2629
|
+
body: {
|
|
2630
|
+
codeStudent,
|
|
2631
|
+
points,
|
|
2632
|
+
},
|
|
2633
|
+
});
|
|
2634
|
+
};
|
|
2635
|
+
// Assignments ------------------------------------------------------------------
|
|
2636
|
+
const toAssignment = (raw_assignment) => {
|
|
2637
|
+
const owner = newUserMock();
|
|
2638
|
+
USERS_BY_ID.set(owner.id, owner);
|
|
2639
|
+
let studentItem = undefined;
|
|
2640
|
+
if (raw_assignment.student_items) {
|
|
2641
|
+
raw_assignment.student_items.forEach(student_item => {
|
|
2642
|
+
studentItem = {
|
|
2643
|
+
id: student_item.uid,
|
|
2644
|
+
type: 'student_item',
|
|
2645
|
+
itemId: student_item.item_uid,
|
|
2646
|
+
itemType: student_item.item_type_s,
|
|
2647
|
+
nbgrades: student_item.nbgrades,
|
|
2648
|
+
nbgradesTotalPoints: student_item.nbgrades_total_points_f,
|
|
2649
|
+
nbgradesTotalScore: student_item.nbgrades_total_score_f,
|
|
2650
|
+
};
|
|
2651
|
+
});
|
|
2652
|
+
}
|
|
2653
|
+
USERS_BY_ID.set(owner.id, owner);
|
|
2654
|
+
const assignment = {
|
|
2655
|
+
id: raw_assignment.uid,
|
|
2656
|
+
type: 'assignment',
|
|
2657
|
+
name: raw_assignment.name_t,
|
|
2658
|
+
description: raw_assignment.description_t,
|
|
2659
|
+
nbformat: raw_assignment.model_s
|
|
2660
|
+
? JSON.parse(raw_assignment.model_s)
|
|
2661
|
+
: undefined,
|
|
2662
|
+
public: raw_assignment.public_b ?? false,
|
|
2663
|
+
creationDate: new Date(raw_assignment.creation_ts_dt),
|
|
2664
|
+
lastUpdateDate: raw_assignment.last_update_ts_dt
|
|
2665
|
+
? new Date(raw_assignment.last_update_ts_dt)
|
|
2666
|
+
: undefined,
|
|
2667
|
+
lastPublicationDate: raw_assignment.creation_ts_dt
|
|
2668
|
+
? new Date(raw_assignment.creation_ts_dt)
|
|
2669
|
+
: undefined,
|
|
2670
|
+
studentItem,
|
|
2671
|
+
datasets: [],
|
|
2672
|
+
owner,
|
|
2673
|
+
space: {
|
|
2674
|
+
handle: raw_assignment.handle_s,
|
|
2675
|
+
},
|
|
2676
|
+
organization: {
|
|
2677
|
+
handle: raw_assignment.handle_s,
|
|
2678
|
+
},
|
|
2679
|
+
};
|
|
2680
|
+
SPACE_ASSIGNMENTS_BY_ID.set(assignment.id, assignment);
|
|
2681
|
+
STUDENT_ASSIGNMENTS_BY_ID.set(assignment.id, assignment);
|
|
2682
|
+
return assignment;
|
|
2683
|
+
};
|
|
2684
|
+
const getAssignment = assignmentId => SPACE_ASSIGNMENTS_BY_ID.get(assignmentId);
|
|
2685
|
+
const refreshAssignment = (assignmentId) => {
|
|
2686
|
+
return requestDatalayer({
|
|
2687
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/assignments/${assignmentId}`,
|
|
2688
|
+
method: 'GET',
|
|
2689
|
+
}).then(resp => {
|
|
2690
|
+
if (resp.success) {
|
|
2691
|
+
const assignment = resp.assignment;
|
|
2692
|
+
if (assignment) {
|
|
2693
|
+
toAssignment(assignment);
|
|
2694
|
+
}
|
|
2695
|
+
}
|
|
2696
|
+
return resp;
|
|
2697
|
+
});
|
|
2698
|
+
};
|
|
2699
|
+
const getAssignmentForStudent = (assignmentId) => STUDENT_ASSIGNMENTS_BY_ID.get(assignmentId);
|
|
2700
|
+
const refreshAssignmentForStudent = (courseId, user, assignmentId) => {
|
|
2701
|
+
return requestDatalayer({
|
|
2702
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/assignments/${assignmentId}/courses/${courseId}/students/${user.id}`,
|
|
2703
|
+
method: 'GET',
|
|
2704
|
+
}).then(resp => {
|
|
2705
|
+
if (resp.success) {
|
|
2706
|
+
const assignment = resp.assignment;
|
|
2707
|
+
if (assignment) {
|
|
2708
|
+
toAssignment(assignment);
|
|
2709
|
+
}
|
|
2710
|
+
}
|
|
2711
|
+
return resp;
|
|
2712
|
+
});
|
|
2713
|
+
};
|
|
2714
|
+
const resetAssignmentForStudent = (courseId, user, assignmentId) => {
|
|
2715
|
+
return requestDatalayer({
|
|
2716
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/assignments/${assignmentId}/reset`,
|
|
2717
|
+
method: 'POST',
|
|
2718
|
+
}).then(resp => {
|
|
2719
|
+
if (resp.success) {
|
|
2720
|
+
const assignment = resp.assignment;
|
|
2721
|
+
if (assignment) {
|
|
2722
|
+
toAssignment(assignment);
|
|
2723
|
+
}
|
|
2724
|
+
}
|
|
2725
|
+
return resp;
|
|
2726
|
+
});
|
|
2727
|
+
};
|
|
2728
|
+
const gradeAssignmentForStudent = (courseId, user, assignmentId, model) => {
|
|
2729
|
+
return requestDatalayer({
|
|
2730
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/assignments/${assignmentId}/students/${user.id}/grade`,
|
|
2731
|
+
method: 'PUT',
|
|
2732
|
+
body: {
|
|
2733
|
+
model,
|
|
2734
|
+
},
|
|
2735
|
+
}).then(resp => {
|
|
2736
|
+
if (resp.success) {
|
|
2737
|
+
const assignment = resp.assignment;
|
|
2738
|
+
if (assignment) {
|
|
2739
|
+
toAssignment(assignment);
|
|
2740
|
+
}
|
|
2741
|
+
}
|
|
2742
|
+
return resp;
|
|
2743
|
+
});
|
|
2744
|
+
};
|
|
2745
|
+
const getSpaceAssignments = () => Array.from(SPACE_ASSIGNMENTS_BY_ID.values());
|
|
2746
|
+
const getSpaceAssignment = id => SPACE_ASSIGNMENTS_BY_ID.get(id);
|
|
2747
|
+
const refreshSpaceAssignments = (space, organization) => {
|
|
2748
|
+
const url = `${configuration.spacerRunUrl}/api/spacer/v1/spaces/${space.id}/items/types/assignment`;
|
|
2749
|
+
return requestDatalayer({
|
|
2750
|
+
url,
|
|
2751
|
+
method: 'GET',
|
|
2752
|
+
}).then(resp => {
|
|
2753
|
+
if (resp.success) {
|
|
2754
|
+
resp.items.forEach(n => {
|
|
2755
|
+
toAssignment(n);
|
|
2756
|
+
});
|
|
2757
|
+
}
|
|
2758
|
+
return resp;
|
|
2759
|
+
});
|
|
2760
|
+
};
|
|
2761
|
+
const cloneAssignment = (assignmentId) => {
|
|
2762
|
+
return requestDatalayer({
|
|
2763
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/notebooks/${assignmentId}/clone`,
|
|
2764
|
+
method: 'POST',
|
|
2765
|
+
}).then(resp => {
|
|
2766
|
+
if (resp.success) {
|
|
2767
|
+
toAssignment(resp.notebook);
|
|
2768
|
+
}
|
|
2769
|
+
return resp;
|
|
2770
|
+
});
|
|
2771
|
+
};
|
|
2772
|
+
const getAssignmentStudentVersion = assignmentId => {
|
|
2773
|
+
return requestDatalayer({
|
|
2774
|
+
url: `${configuration.spacerRunUrl}/api/spacer/v1/assignments/${assignmentId}/student_version`,
|
|
2775
|
+
method: 'GET',
|
|
2776
|
+
});
|
|
2777
|
+
};
|
|
2778
|
+
// Prices -------------------------------------------------------------------
|
|
2779
|
+
const refreshStripePrices = () => {
|
|
2780
|
+
return requestDatalayer({
|
|
2781
|
+
url: `${configuration.iamRunUrl}/api/iam/stripe/v1/prices`,
|
|
2782
|
+
method: 'GET',
|
|
2783
|
+
});
|
|
2784
|
+
};
|
|
2785
|
+
// Checkout -------------------------------------------------------------------
|
|
2786
|
+
const createCheckoutSession = (product, location) => {
|
|
2787
|
+
return requestDatalayer({
|
|
2788
|
+
url: `${configuration.iamRunUrl}/api/iam/stripe/v1/checkout/session`,
|
|
2789
|
+
method: 'POST',
|
|
2790
|
+
body: {
|
|
2791
|
+
price_id: product?.id,
|
|
2792
|
+
return_url: `${location.protocol}//${location.host}${location.pathname.split('/').slice(0, -1).join('/')}`,
|
|
2793
|
+
},
|
|
2794
|
+
})
|
|
2795
|
+
.then(data => data.client_secret)
|
|
2796
|
+
.catch(error => {
|
|
2797
|
+
console.error('Failed to create Stripe checkout session.', error);
|
|
2798
|
+
});
|
|
2799
|
+
};
|
|
2800
|
+
// Credits -------------------------------------------------------------------
|
|
2801
|
+
const burnCredit = credits => {
|
|
2802
|
+
return requestDatalayer({
|
|
2803
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/usage/credits`,
|
|
2804
|
+
method: 'DELETE',
|
|
2805
|
+
body: {
|
|
2806
|
+
credits,
|
|
2807
|
+
},
|
|
2808
|
+
});
|
|
2809
|
+
};
|
|
2810
|
+
const getUserCredits = userId => {
|
|
2811
|
+
return requestDatalayer({
|
|
2812
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/usage/credits/users/${userId}`,
|
|
2813
|
+
method: 'GET',
|
|
2814
|
+
});
|
|
2815
|
+
};
|
|
2816
|
+
const updateUserCredits = (userId, credits, brand) => {
|
|
2817
|
+
return requestDatalayer({
|
|
2818
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/usage/credits/users/${userId}`,
|
|
2819
|
+
method: 'PUT',
|
|
2820
|
+
body: {
|
|
2821
|
+
credits,
|
|
2822
|
+
brand,
|
|
2823
|
+
},
|
|
2824
|
+
});
|
|
2825
|
+
};
|
|
2826
|
+
const updateUserCreditsQuota = (userId, quota) => {
|
|
2827
|
+
return requestDatalayer({
|
|
2828
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/usage/quota`,
|
|
2829
|
+
method: 'PUT',
|
|
2830
|
+
body: {
|
|
2831
|
+
user_uid: userId,
|
|
2832
|
+
quota,
|
|
2833
|
+
reset: '0',
|
|
2834
|
+
},
|
|
2835
|
+
});
|
|
2836
|
+
};
|
|
2837
|
+
// Usages -------------------------------------------------------------------
|
|
2838
|
+
/**
|
|
2839
|
+
* Get user usages
|
|
2840
|
+
*/
|
|
2841
|
+
const getUsages = async () => {
|
|
2842
|
+
const data = await requestDatalayer({
|
|
2843
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/usage/user`,
|
|
2844
|
+
method: 'GET',
|
|
2845
|
+
});
|
|
2846
|
+
data.usages = (data.usages ?? []).map(u => asUsage(u));
|
|
2847
|
+
return data;
|
|
2848
|
+
};
|
|
2849
|
+
/**
|
|
2850
|
+
* Get user usages
|
|
2851
|
+
*/
|
|
2852
|
+
const getUsagesForUser = async (userId) => {
|
|
2853
|
+
const data = await requestDatalayer({
|
|
2854
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/usage/users/${userId}`,
|
|
2855
|
+
method: 'GET',
|
|
2856
|
+
});
|
|
2857
|
+
data.usages = (data.usages ?? []).map(u => asUsage(u));
|
|
2858
|
+
return data;
|
|
2859
|
+
};
|
|
2860
|
+
/**
|
|
2861
|
+
* Get platform usages
|
|
2862
|
+
*/
|
|
2863
|
+
const getPlatformUsages = async () => {
|
|
2864
|
+
const data = await requestDatalayer({
|
|
2865
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/usage/platform`,
|
|
2866
|
+
method: 'GET',
|
|
2867
|
+
});
|
|
2868
|
+
data.usages = (data.usages ?? []).map(u => asUsage(u));
|
|
2869
|
+
return data;
|
|
2870
|
+
};
|
|
2871
|
+
// Support ------------------------------------------------------------------
|
|
2872
|
+
const requestPlatformSupport = (subject, message, email, brand) => {
|
|
2873
|
+
return requestDatalayer({
|
|
2874
|
+
url: `${configuration.supportRunUrl}/api/support/v1/support/request`,
|
|
2875
|
+
method: 'POST',
|
|
2876
|
+
body: {
|
|
2877
|
+
subject,
|
|
2878
|
+
message,
|
|
2879
|
+
email,
|
|
2880
|
+
brand,
|
|
2881
|
+
},
|
|
2882
|
+
});
|
|
2883
|
+
};
|
|
2884
|
+
const requestPlatformSupport2 = (accountHandle, firstName, lastName, email, message) => {
|
|
2885
|
+
return requestDatalayer({
|
|
2886
|
+
url: `${configuration.supportRunUrl}/api/support/v1/support/request2`,
|
|
2887
|
+
method: 'POST',
|
|
2888
|
+
body: {
|
|
2889
|
+
accountHandle,
|
|
2890
|
+
firstName,
|
|
2891
|
+
lastName,
|
|
2892
|
+
email,
|
|
2893
|
+
message,
|
|
2894
|
+
},
|
|
2895
|
+
});
|
|
2896
|
+
};
|
|
2897
|
+
// Growth ------------------------------------------------------------------
|
|
2898
|
+
const getGrowthKPI = () => {
|
|
2899
|
+
return requestDatalayer({
|
|
2900
|
+
url: `${configuration.growthRunUrl}/api/growth/v1/kpis`,
|
|
2901
|
+
method: 'GET',
|
|
2902
|
+
});
|
|
2903
|
+
};
|
|
2904
|
+
// --------------------------------------------------------------------------
|
|
2905
|
+
return {
|
|
2906
|
+
// Authentication & Profile
|
|
2907
|
+
login,
|
|
2908
|
+
logout,
|
|
2909
|
+
getMe,
|
|
2910
|
+
updateMe,
|
|
2911
|
+
whoami,
|
|
2912
|
+
requestJoin,
|
|
2913
|
+
requestJoinToken,
|
|
2914
|
+
joinWithInvite,
|
|
2915
|
+
confirmJoinWithToken,
|
|
2916
|
+
changePassword,
|
|
2917
|
+
createTokenForPasswordChange,
|
|
2918
|
+
confirmPassworkWithToken,
|
|
2919
|
+
requestEmailUpdate,
|
|
2920
|
+
confirmEmailUpdate,
|
|
2921
|
+
getOAuth2AuthorizationURL,
|
|
2922
|
+
getOAuth2AuthorizationLinkURL,
|
|
2923
|
+
getGitHubProfile,
|
|
2924
|
+
getLinkedinProfile,
|
|
2925
|
+
postLinkedinShare,
|
|
2926
|
+
postLinkedinShareWithUpload,
|
|
2927
|
+
registerToWaitingList,
|
|
2928
|
+
// Proxy
|
|
2929
|
+
proxyGET,
|
|
2930
|
+
proxyPOST,
|
|
2931
|
+
proxyPUT,
|
|
2932
|
+
// Users
|
|
2933
|
+
getUser,
|
|
2934
|
+
getUserByHandle,
|
|
2935
|
+
searchUsers,
|
|
2936
|
+
refreshUser,
|
|
2937
|
+
assignRoleToUser,
|
|
2938
|
+
unassignRoleFromUser,
|
|
2939
|
+
updateUserOnboarding,
|
|
2940
|
+
updateUserSettings,
|
|
2941
|
+
getUserCredits,
|
|
2942
|
+
updateUserCredits,
|
|
2943
|
+
updateUserCreditsQuota,
|
|
2944
|
+
getUserSurveys,
|
|
2945
|
+
getUsages,
|
|
2946
|
+
getUsagesForUser,
|
|
2947
|
+
// Organizations
|
|
2948
|
+
createOrganization,
|
|
2949
|
+
getOrganizationById,
|
|
2950
|
+
getOrganizationByHandle,
|
|
2951
|
+
getUserOrganizations,
|
|
2952
|
+
getUserOrganizationById,
|
|
2953
|
+
updateOrganization,
|
|
2954
|
+
refreshOrganization,
|
|
2955
|
+
refreshUserOrganizations,
|
|
2956
|
+
addMemberToOrganization,
|
|
2957
|
+
removeMemberFromOrganization,
|
|
2958
|
+
addRoleToOrganizationMember,
|
|
2959
|
+
removeRoleFromOrganizationMember,
|
|
2960
|
+
clearCachedOrganizations,
|
|
2961
|
+
// Teams
|
|
2962
|
+
createTeam,
|
|
2963
|
+
getTeamById,
|
|
2964
|
+
getTeamByHandle,
|
|
2965
|
+
getTeamsByOrganizationId,
|
|
2966
|
+
updateTeam,
|
|
2967
|
+
refreshTeam,
|
|
2968
|
+
refreshTeams,
|
|
2969
|
+
addMemberToTeam,
|
|
2970
|
+
removeMemberFromTeam,
|
|
2971
|
+
addRoleToTeamMember,
|
|
2972
|
+
removeRoleFromTeamMember,
|
|
2973
|
+
clearCachedTeams,
|
|
2974
|
+
// Schools
|
|
2975
|
+
getSchools,
|
|
2976
|
+
refreshSchools,
|
|
2977
|
+
// Spaces
|
|
2978
|
+
createSpace,
|
|
2979
|
+
getOrganizationSpace,
|
|
2980
|
+
getOrganizationSpaceByHandle,
|
|
2981
|
+
getOrganizationSpaces,
|
|
2982
|
+
getUserSpace,
|
|
2983
|
+
getUserSpaceByHandle,
|
|
2984
|
+
getUserSpaces,
|
|
2985
|
+
updateSpace,
|
|
2986
|
+
updateOrganizationSpace,
|
|
2987
|
+
refreshOrganizationSpace,
|
|
2988
|
+
refreshOrganizationSpaces,
|
|
2989
|
+
refreshUserSpace,
|
|
2990
|
+
refreshUserSpaces,
|
|
2991
|
+
refreshLayout,
|
|
2992
|
+
exportSpace,
|
|
2993
|
+
addMemberToOrganizationSpace,
|
|
2994
|
+
removeMemberFromOrganizationSpace,
|
|
2995
|
+
makeSpacePublic,
|
|
2996
|
+
makeSpacePrivate,
|
|
2997
|
+
// Courses
|
|
2998
|
+
getCourse,
|
|
2999
|
+
updateCourse,
|
|
3000
|
+
refreshCourse,
|
|
3001
|
+
getPublicCourses,
|
|
3002
|
+
refreshPublicCourses,
|
|
3003
|
+
getInstructorCourses,
|
|
3004
|
+
refreshInstructorCourses,
|
|
3005
|
+
getCoursesEnrollments,
|
|
3006
|
+
refreshCoursesEnrollments,
|
|
3007
|
+
enrollStudentToCourse,
|
|
3008
|
+
removeStudentFromCourse,
|
|
3009
|
+
getStudent,
|
|
3010
|
+
refreshStudent,
|
|
3011
|
+
confirmCourseItemCompletion,
|
|
3012
|
+
setCourseItems,
|
|
3013
|
+
// Notebooks
|
|
3014
|
+
createNotebook,
|
|
3015
|
+
getNotebook,
|
|
3016
|
+
getSpaceNotebook,
|
|
3017
|
+
getSpaceNotebooks,
|
|
3018
|
+
updateNotebook,
|
|
3019
|
+
updateNotebookModel,
|
|
3020
|
+
cloneNotebook,
|
|
3021
|
+
refreshNotebook,
|
|
3022
|
+
refreshSpaceNotebooks,
|
|
3023
|
+
// Documents
|
|
3024
|
+
getDocument,
|
|
3025
|
+
getSpaceDocument,
|
|
3026
|
+
getSpaceDocuments,
|
|
3027
|
+
updateDocument,
|
|
3028
|
+
updateDocumentModel,
|
|
3029
|
+
cloneDocument,
|
|
3030
|
+
refreshDocument,
|
|
3031
|
+
refreshSpaceDocuments,
|
|
3032
|
+
// Cells
|
|
3033
|
+
getCell,
|
|
3034
|
+
getSpaceCells,
|
|
3035
|
+
updateCell,
|
|
3036
|
+
cloneCell,
|
|
3037
|
+
refreshCell,
|
|
3038
|
+
refreshSpaceCells,
|
|
3039
|
+
// Datasets
|
|
3040
|
+
getDataset,
|
|
3041
|
+
getSpaceDatasets,
|
|
3042
|
+
updateDataset,
|
|
3043
|
+
refreshDataset,
|
|
3044
|
+
refreshSpaceDatasets,
|
|
3045
|
+
// Environments
|
|
3046
|
+
getEnvironment,
|
|
3047
|
+
getSpaceEnvironments,
|
|
3048
|
+
refreshEnvironment,
|
|
3049
|
+
refreshSpaceEnvironments,
|
|
3050
|
+
// Lessons
|
|
3051
|
+
getLesson,
|
|
3052
|
+
getSpaceLesson,
|
|
3053
|
+
getSpaceLessons,
|
|
3054
|
+
cloneLesson,
|
|
3055
|
+
refreshLesson,
|
|
3056
|
+
refreshSpaceLessons,
|
|
3057
|
+
// Exercises
|
|
3058
|
+
getExercise,
|
|
3059
|
+
getSpaceExercises,
|
|
3060
|
+
updateExercise,
|
|
3061
|
+
updateExercisePoints,
|
|
3062
|
+
cloneExercise,
|
|
3063
|
+
refreshExercise,
|
|
3064
|
+
refreshSpaceExercises,
|
|
3065
|
+
// Assignments
|
|
3066
|
+
getAssignment,
|
|
3067
|
+
getAssignmentForStudent,
|
|
3068
|
+
getAssignmentStudentVersion,
|
|
3069
|
+
getSpaceAssignment,
|
|
3070
|
+
getSpaceAssignments,
|
|
3071
|
+
cloneAssignment,
|
|
3072
|
+
refreshAssignment,
|
|
3073
|
+
refreshAssignmentForStudent,
|
|
3074
|
+
refreshSpaceAssignments,
|
|
3075
|
+
gradeAssignmentForStudent,
|
|
3076
|
+
resetAssignmentForStudent,
|
|
3077
|
+
// Items (Generic)
|
|
3078
|
+
getPublicItems,
|
|
3079
|
+
getSpaceItems,
|
|
3080
|
+
searchPublicItems,
|
|
3081
|
+
makeItemPublic,
|
|
3082
|
+
makeItemPrivate,
|
|
3083
|
+
deleteItem,
|
|
3084
|
+
refreshPublicItems,
|
|
3085
|
+
refreshSpaceItems,
|
|
3086
|
+
clearCachedPublicItems,
|
|
3087
|
+
clearCachedItems,
|
|
3088
|
+
// Pages
|
|
3089
|
+
createPage,
|
|
3090
|
+
getPage,
|
|
3091
|
+
getPages,
|
|
3092
|
+
updatePage,
|
|
3093
|
+
deletePage,
|
|
3094
|
+
refreshPage,
|
|
3095
|
+
refreshPages,
|
|
3096
|
+
clearCachedPages,
|
|
3097
|
+
// Datasources
|
|
3098
|
+
createDatasource,
|
|
3099
|
+
getDatasource,
|
|
3100
|
+
getDatasources,
|
|
3101
|
+
updateDatasource,
|
|
3102
|
+
refreshDatasource,
|
|
3103
|
+
refreshDatasources,
|
|
3104
|
+
clearCachedDatasources,
|
|
3105
|
+
// Secrets
|
|
3106
|
+
createSecret,
|
|
3107
|
+
getSecret,
|
|
3108
|
+
getSecrets,
|
|
3109
|
+
updateSecret,
|
|
3110
|
+
deleteSecret,
|
|
3111
|
+
refreshSecret,
|
|
3112
|
+
refreshSecrets,
|
|
3113
|
+
clearCachedSecrets,
|
|
3114
|
+
// Tokens
|
|
3115
|
+
createToken,
|
|
3116
|
+
getToken,
|
|
3117
|
+
getTokens,
|
|
3118
|
+
updateToken,
|
|
3119
|
+
refreshToken,
|
|
3120
|
+
refreshTokens,
|
|
3121
|
+
clearCachedTokens,
|
|
3122
|
+
// Invites
|
|
3123
|
+
requestInvite,
|
|
3124
|
+
sendInvite,
|
|
3125
|
+
getInvite,
|
|
3126
|
+
getInvites,
|
|
3127
|
+
putInvite,
|
|
3128
|
+
refreshInvite,
|
|
3129
|
+
refreshInvites,
|
|
3130
|
+
refreshAccount,
|
|
3131
|
+
clearCachedInvites,
|
|
3132
|
+
// Contacts
|
|
3133
|
+
createContact,
|
|
3134
|
+
getContactById,
|
|
3135
|
+
getContactByHandle,
|
|
3136
|
+
updateContact,
|
|
3137
|
+
deleteContact,
|
|
3138
|
+
searchContacts,
|
|
3139
|
+
refreshContact,
|
|
3140
|
+
assignTagToContact,
|
|
3141
|
+
unassignTagFromContact,
|
|
3142
|
+
sendInviteToContact,
|
|
3143
|
+
enrichContactEmail,
|
|
3144
|
+
enrichContactLinkedin,
|
|
3145
|
+
sendLinkedinConnectionRequest,
|
|
3146
|
+
linkUserWithContact,
|
|
3147
|
+
unlinkUserFromContact,
|
|
3148
|
+
// Inbounds
|
|
3149
|
+
getInbound,
|
|
3150
|
+
getInboundByHandle,
|
|
3151
|
+
getInbounds,
|
|
3152
|
+
refreshInbound,
|
|
3153
|
+
toInbound,
|
|
3154
|
+
// Outbounds
|
|
3155
|
+
getOutbound,
|
|
3156
|
+
getOutbounds,
|
|
3157
|
+
refreshOutbound,
|
|
3158
|
+
draftBulkEmailsOutbounds,
|
|
3159
|
+
tryBulkEmailsOutbounds,
|
|
3160
|
+
launchBulkEmailsOutbounds,
|
|
3161
|
+
sendOutboundEmailToUser,
|
|
3162
|
+
deleteOutbound,
|
|
3163
|
+
subscribeUserToOutbounds,
|
|
3164
|
+
unsubscribeUserFromOutbounds,
|
|
3165
|
+
unsubscribeContactFromOutbounds,
|
|
3166
|
+
unsubscribeInviteeFromOutbounds,
|
|
3167
|
+
toOutbound,
|
|
3168
|
+
// MFA
|
|
3169
|
+
enableUserMFA,
|
|
3170
|
+
disableUserMFA,
|
|
3171
|
+
validateUserMFACode,
|
|
3172
|
+
// Checkout & Credits
|
|
3173
|
+
createCheckoutSession,
|
|
3174
|
+
burnCredit,
|
|
3175
|
+
refreshStripePrices,
|
|
3176
|
+
// Support & Growth
|
|
3177
|
+
requestPlatformSupport,
|
|
3178
|
+
requestPlatformSupport2,
|
|
3179
|
+
getGrowthKPI,
|
|
3180
|
+
getPlatformUsages,
|
|
3181
|
+
// Cache Management
|
|
3182
|
+
clearAllCaches,
|
|
3183
|
+
// Upload
|
|
3184
|
+
notebookUploadLoading,
|
|
3185
|
+
notebookUploadProgress,
|
|
3186
|
+
resetNotebookUpload,
|
|
3187
|
+
};
|
|
3188
|
+
};
|
|
3189
|
+
export default useCache0;
|