@comapeo/core-react 9.0.1 → 10.0.0
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/README.md +1 -1
- package/dist/commonjs/contexts/ClientApi.d.ts +1 -3
- package/dist/commonjs/contexts/ClientApi.js +2 -2
- package/dist/commonjs/hooks/client.d.ts +74 -33
- package/dist/commonjs/hooks/client.js +40 -11
- package/dist/commonjs/hooks/documents.d.ts +41 -429
- package/dist/commonjs/hooks/documents.js +101 -51
- package/dist/commonjs/hooks/invites.d.ts +153 -55
- package/dist/commonjs/hooks/invites.js +69 -20
- package/dist/commonjs/hooks/maps.d.ts +98 -219
- package/dist/commonjs/hooks/maps.js +104 -37
- package/dist/commonjs/hooks/projects.d.ts +666 -223
- package/dist/commonjs/hooks/projects.js +264 -131
- package/dist/commonjs/index.d.ts +2 -2
- package/dist/commonjs/lib/map-shares-stores.d.ts +1 -1
- package/dist/commonjs/lib/map-shares-stores.js +2 -2
- package/dist/commonjs/lib/presets.d.ts +1 -3
- package/dist/commonjs/lib/react-query.d.ts +103 -0
- package/dist/commonjs/lib/react-query.js +187 -0
- package/dist/commonjs/lib/sync.d.ts +2 -5
- package/dist/commonjs/lib/sync.js +0 -1
- package/dist/commonjs/lib/types.d.ts +4 -6
- package/dist/esm/contexts/ClientApi.d.ts +1 -3
- package/dist/esm/contexts/ClientApi.js +1 -1
- package/dist/esm/hooks/client.d.ts +74 -33
- package/dist/esm/hooks/client.js +40 -11
- package/dist/esm/hooks/documents.d.ts +41 -429
- package/dist/esm/hooks/documents.js +101 -51
- package/dist/esm/hooks/invites.d.ts +153 -55
- package/dist/esm/hooks/invites.js +69 -20
- package/dist/esm/hooks/maps.d.ts +98 -219
- package/dist/esm/hooks/maps.js +105 -38
- package/dist/esm/hooks/projects.d.ts +666 -223
- package/dist/esm/hooks/projects.js +262 -129
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/lib/map-shares-stores.d.ts +1 -1
- package/dist/esm/lib/map-shares-stores.js +1 -1
- package/dist/esm/lib/presets.d.ts +1 -3
- package/dist/esm/lib/react-query.d.ts +103 -0
- package/dist/esm/lib/react-query.js +162 -0
- package/dist/esm/lib/sync.d.ts +2 -5
- package/dist/esm/lib/sync.js +1 -1
- package/dist/esm/lib/types.d.ts +4 -6
- package/docs/API.md +137 -81
- package/package.json +39 -35
- package/dist/commonjs/lib/react-query/client.d.ts +0 -65
- package/dist/commonjs/lib/react-query/client.js +0 -68
- package/dist/commonjs/lib/react-query/documents.d.ts +0 -1484
- package/dist/commonjs/lib/react-query/documents.js +0 -149
- package/dist/commonjs/lib/react-query/invites.d.ts +0 -88
- package/dist/commonjs/lib/react-query/invites.js +0 -95
- package/dist/commonjs/lib/react-query/maps.d.ts +0 -72
- package/dist/commonjs/lib/react-query/maps.js +0 -129
- package/dist/commonjs/lib/react-query/mutation-result.d.ts +0 -8
- package/dist/commonjs/lib/react-query/mutation-result.js +0 -22
- package/dist/commonjs/lib/react-query/projects.d.ts +0 -316
- package/dist/commonjs/lib/react-query/projects.js +0 -359
- package/dist/commonjs/lib/react-query/shared.d.ts +0 -9
- package/dist/commonjs/lib/react-query/shared.js +0 -23
- package/dist/esm/lib/react-query/client.d.ts +0 -65
- package/dist/esm/lib/react-query/client.js +0 -59
- package/dist/esm/lib/react-query/documents.d.ts +0 -1484
- package/dist/esm/lib/react-query/documents.js +0 -137
- package/dist/esm/lib/react-query/invites.d.ts +0 -88
- package/dist/esm/lib/react-query/invites.js +0 -85
- package/dist/esm/lib/react-query/maps.d.ts +0 -72
- package/dist/esm/lib/react-query/maps.js +0 -119
- package/dist/esm/lib/react-query/mutation-result.d.ts +0 -8
- package/dist/esm/lib/react-query/mutation-result.js +0 -19
- package/dist/esm/lib/react-query/projects.d.ts +0 -316
- package/dist/esm/lib/react-query/projects.js +0 -324
- package/dist/esm/lib/react-query/shared.d.ts +0 -9
- package/dist/esm/lib/react-query/shared.js +0 -18
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useMutation, useQueryClient, useSuspenseQuery, } from '@tanstack/react-query';
|
|
2
2
|
import { useEffect, useSyncExternalStore } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { baseMutationOptions, baseQueryOptions, filterMutationResult, getDocumentCreatedByQueryKey, getMediaServerOriginQueryKey, getMemberByIdQueryKey, getMembersQueryKey, getProjectByIdQueryKey, getProjectRoleQueryKey, getProjectSettingsQueryKey, getProjectsQueryKey, } from '../lib/react-query.js';
|
|
4
4
|
import { SyncStore } from '../lib/sync.js';
|
|
5
5
|
import { getBlobUrl, getIconUrl } from '../lib/urls.js';
|
|
6
6
|
import { useClientApi } from './client.js';
|
|
@@ -18,16 +18,15 @@ import { useClientApi } from './client.js';
|
|
|
18
18
|
* }
|
|
19
19
|
* ```
|
|
20
20
|
*/
|
|
21
|
-
export function useProjectSettings({ projectId }) {
|
|
22
|
-
const
|
|
23
|
-
const { data
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}));
|
|
21
|
+
export function useProjectSettings({ projectId, }) {
|
|
22
|
+
const { data: projectApi } = useSingleProject({ projectId });
|
|
23
|
+
const { data, error, isRefetching } = useSuspenseQuery({
|
|
24
|
+
...baseQueryOptions(),
|
|
25
|
+
queryKey: getProjectSettingsQueryKey({ projectId }),
|
|
26
|
+
queryFn: async () => {
|
|
27
|
+
return projectApi.$getProjectSettings();
|
|
28
|
+
},
|
|
29
|
+
});
|
|
31
30
|
return { data, error, isRefetching };
|
|
32
31
|
}
|
|
33
32
|
/**
|
|
@@ -44,13 +43,14 @@ export function useProjectSettings({ projectId }) {
|
|
|
44
43
|
* }
|
|
45
44
|
* ```
|
|
46
45
|
*/
|
|
47
|
-
export function useSingleProject({ projectId }) {
|
|
46
|
+
export function useSingleProject({ projectId, }) {
|
|
48
47
|
const clientApi = useClientApi();
|
|
49
48
|
const { data, error, isRefetching } = useSuspenseQuery({
|
|
50
|
-
...
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
...baseQueryOptions(),
|
|
50
|
+
queryKey: getProjectByIdQueryKey({ projectId }),
|
|
51
|
+
queryFn: async () => {
|
|
52
|
+
return clientApi.getProject(projectId);
|
|
53
|
+
},
|
|
54
54
|
// Keep project instances around indefinitely - shouldn't be a memory
|
|
55
55
|
// problem because these are only lightweight proxy objects, and project
|
|
56
56
|
// references are kept indefinitely on the backend anyway once they are
|
|
@@ -74,9 +74,13 @@ export function useSingleProject({ projectId }) {
|
|
|
74
74
|
*/
|
|
75
75
|
export function useManyProjects() {
|
|
76
76
|
const clientApi = useClientApi();
|
|
77
|
-
const { data, error, isRefetching } = useSuspenseQuery(
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
const { data, error, isRefetching } = useSuspenseQuery({
|
|
78
|
+
...baseQueryOptions(),
|
|
79
|
+
queryKey: getProjectsQueryKey(),
|
|
80
|
+
queryFn: async () => {
|
|
81
|
+
return clientApi.listProjects();
|
|
82
|
+
},
|
|
83
|
+
});
|
|
80
84
|
return { data, error, isRefetching };
|
|
81
85
|
}
|
|
82
86
|
/**
|
|
@@ -96,11 +100,13 @@ export function useManyProjects() {
|
|
|
96
100
|
*/
|
|
97
101
|
export function useSingleMember({ projectId, deviceId, }) {
|
|
98
102
|
const { data: projectApi } = useSingleProject({ projectId });
|
|
99
|
-
const { data, error, isRefetching } = useSuspenseQuery(
|
|
100
|
-
|
|
101
|
-
projectId,
|
|
102
|
-
|
|
103
|
-
|
|
103
|
+
const { data, error, isRefetching } = useSuspenseQuery({
|
|
104
|
+
...baseQueryOptions(),
|
|
105
|
+
queryKey: getMemberByIdQueryKey({ projectId, deviceId }),
|
|
106
|
+
queryFn: async () => {
|
|
107
|
+
return projectApi.$member.getById(deviceId);
|
|
108
|
+
},
|
|
109
|
+
});
|
|
104
110
|
return { data, error, isRefetching };
|
|
105
111
|
}
|
|
106
112
|
/**
|
|
@@ -111,15 +117,22 @@ export function useSingleMember({ projectId, deviceId, }) {
|
|
|
111
117
|
* @example
|
|
112
118
|
* ```tsx
|
|
113
119
|
* function BasicExample() {
|
|
114
|
-
* const
|
|
120
|
+
* const activeMembers1 = useManyMembers({ projectId: '...' })
|
|
121
|
+
* const activeMembers2 = useManyMembers({ projectId: '...', includeLeft: false })
|
|
115
122
|
*
|
|
116
|
-
*
|
|
123
|
+
* const allMembers = useManyMembers({ projectId: '...', includeLeft: true })
|
|
117
124
|
* }
|
|
118
125
|
* ```
|
|
119
126
|
*/
|
|
120
|
-
export function useManyMembers({ projectId }) {
|
|
127
|
+
export function useManyMembers({ projectId, includeLeft, }) {
|
|
121
128
|
const { data: projectApi } = useSingleProject({ projectId });
|
|
122
|
-
const { data, error, isRefetching } = useSuspenseQuery(
|
|
129
|
+
const { data, error, isRefetching } = useSuspenseQuery({
|
|
130
|
+
...baseQueryOptions(),
|
|
131
|
+
queryKey: getMembersQueryKey({ projectId, includeLeft }),
|
|
132
|
+
queryFn: async () => {
|
|
133
|
+
return projectApi.$member.getMany({ includeLeft });
|
|
134
|
+
},
|
|
135
|
+
});
|
|
123
136
|
return { data, error, isRefetching };
|
|
124
137
|
}
|
|
125
138
|
/**
|
|
@@ -225,14 +238,32 @@ export function useAttachmentUrl({ projectId, blobId, }) {
|
|
|
225
238
|
const blobUrl = getBlobUrl({ serverOrigin, projectId, blobId });
|
|
226
239
|
return { data: blobUrl, error, isRefetching };
|
|
227
240
|
}
|
|
241
|
+
// Used as a placeholder so that we can read the server port from the $blobs.getUrl() method
|
|
242
|
+
const FAKE_BLOB_ID = {
|
|
243
|
+
type: 'photo',
|
|
244
|
+
variant: 'original',
|
|
245
|
+
name: 'name',
|
|
246
|
+
driveId: 'drive-id',
|
|
247
|
+
};
|
|
228
248
|
/**
|
|
229
249
|
* @internal
|
|
230
250
|
* Hack to retrieve the media server origin (protocol + host).
|
|
231
251
|
*/
|
|
232
252
|
function useMediaServerOrigin({ projectApi }) {
|
|
233
|
-
const { data, error, isRefetching } = useSuspenseQuery(
|
|
234
|
-
|
|
235
|
-
|
|
253
|
+
const { data, error, isRefetching } = useSuspenseQuery({
|
|
254
|
+
...baseQueryOptions(),
|
|
255
|
+
// HACK: The server doesn't yet expose a method to get its origin, so we use
|
|
256
|
+
// the existing $blobs.getUrl() to get the origin with a fake BlobId. The origin
|
|
257
|
+
// is the same regardless of the blobId, so it's not necessary to include it
|
|
258
|
+
// as a dep for the query key.
|
|
259
|
+
queryKey: getMediaServerOriginQueryKey(),
|
|
260
|
+
queryFn: async () => {
|
|
261
|
+
const url = await projectApi.$blobs.getUrl(FAKE_BLOB_ID);
|
|
262
|
+
return new URL(url).origin;
|
|
263
|
+
},
|
|
264
|
+
staleTime: 'static',
|
|
265
|
+
gcTime: Infinity,
|
|
266
|
+
});
|
|
236
267
|
return { data, error, isRefetching };
|
|
237
268
|
}
|
|
238
269
|
// TODO: Eventually remove in favor of this information being provided by the backend when retrieving documents
|
|
@@ -256,7 +287,18 @@ function useMediaServerOrigin({ projectApi }) {
|
|
|
256
287
|
*/
|
|
257
288
|
export function useDocumentCreatedBy({ projectId, originalVersionId, }) {
|
|
258
289
|
const { data: projectApi } = useSingleProject({ projectId });
|
|
259
|
-
const { data, error, isRefetching } = useSuspenseQuery(
|
|
290
|
+
const { data, error, isRefetching } = useSuspenseQuery({
|
|
291
|
+
...baseQueryOptions(),
|
|
292
|
+
queryKey: getDocumentCreatedByQueryKey({
|
|
293
|
+
projectId,
|
|
294
|
+
originalVersionId,
|
|
295
|
+
}),
|
|
296
|
+
queryFn: async () => {
|
|
297
|
+
return projectApi.$originalVersionIdToDeviceId(originalVersionId);
|
|
298
|
+
},
|
|
299
|
+
staleTime: 'static',
|
|
300
|
+
gcTime: Infinity,
|
|
301
|
+
});
|
|
260
302
|
return { data, error, isRefetching };
|
|
261
303
|
}
|
|
262
304
|
/**
|
|
@@ -274,26 +316,50 @@ export function useDocumentCreatedBy({ projectId, originalVersionId, }) {
|
|
|
274
316
|
* }
|
|
275
317
|
* ```
|
|
276
318
|
*/
|
|
277
|
-
export function useOwnRoleInProject({ projectId }) {
|
|
319
|
+
export function useOwnRoleInProject({ projectId, }) {
|
|
278
320
|
const { data: projectApi } = useSingleProject({ projectId });
|
|
279
|
-
const { data, error, isRefetching } = useSuspenseQuery(
|
|
321
|
+
const { data, error, isRefetching } = useSuspenseQuery({
|
|
322
|
+
...baseQueryOptions(),
|
|
323
|
+
queryKey: getProjectRoleQueryKey({ projectId }),
|
|
324
|
+
queryFn: async () => {
|
|
325
|
+
return projectApi.$getOwnRole();
|
|
326
|
+
},
|
|
327
|
+
});
|
|
280
328
|
return { data, error, isRefetching };
|
|
281
329
|
}
|
|
282
330
|
export function useAddServerPeer({ projectId }) {
|
|
283
331
|
const queryClient = useQueryClient();
|
|
284
332
|
const { data: projectApi } = useSingleProject({ projectId });
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
333
|
+
return filterMutationResult(useMutation({
|
|
334
|
+
...baseMutationOptions(),
|
|
335
|
+
mutationFn: async ({ baseUrl, dangerouslyAllowInsecureConnections, }) => {
|
|
336
|
+
return projectApi.$member.addServerPeer(baseUrl, {
|
|
337
|
+
dangerouslyAllowInsecureConnections,
|
|
338
|
+
});
|
|
339
|
+
},
|
|
340
|
+
onSuccess: () => {
|
|
341
|
+
queryClient.invalidateQueries({
|
|
342
|
+
queryKey: getMembersQueryKey({ projectId }),
|
|
343
|
+
});
|
|
344
|
+
},
|
|
345
|
+
}));
|
|
289
346
|
}
|
|
290
347
|
export function useRemoveServerPeer({ projectId }) {
|
|
291
348
|
const queryClient = useQueryClient();
|
|
292
349
|
const { data: projectApi } = useSingleProject({ projectId });
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
350
|
+
return filterMutationResult(useMutation({
|
|
351
|
+
...baseMutationOptions(),
|
|
352
|
+
mutationFn: async ({ serverDeviceId, dangerouslyAllowInsecureConnections, }) => {
|
|
353
|
+
return projectApi.$member.removeServerPeer(serverDeviceId, {
|
|
354
|
+
dangerouslyAllowInsecureConnections,
|
|
355
|
+
});
|
|
356
|
+
},
|
|
357
|
+
onSuccess: () => {
|
|
358
|
+
queryClient.invalidateQueries({
|
|
359
|
+
queryKey: getMembersQueryKey({ projectId }),
|
|
360
|
+
});
|
|
361
|
+
},
|
|
362
|
+
}));
|
|
297
363
|
}
|
|
298
364
|
/**
|
|
299
365
|
* Create a new project.
|
|
@@ -301,10 +367,19 @@ export function useRemoveServerPeer({ projectId }) {
|
|
|
301
367
|
export function useCreateProject() {
|
|
302
368
|
const queryClient = useQueryClient();
|
|
303
369
|
const clientApi = useClientApi();
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
370
|
+
return filterMutationResult(useMutation({
|
|
371
|
+
...baseMutationOptions(),
|
|
372
|
+
mutationFn: async (opts) => {
|
|
373
|
+
// Have to avoid passing `undefined` explicitly
|
|
374
|
+
// See https://github.com/digidem/rpc-reflector/issues/21
|
|
375
|
+
return opts ? clientApi.createProject(opts) : clientApi.createProject();
|
|
376
|
+
},
|
|
377
|
+
onSuccess: () => {
|
|
378
|
+
queryClient.invalidateQueries({
|
|
379
|
+
queryKey: getProjectsQueryKey(),
|
|
380
|
+
});
|
|
381
|
+
},
|
|
382
|
+
}));
|
|
308
383
|
}
|
|
309
384
|
/**
|
|
310
385
|
* Leave an existing project.
|
|
@@ -312,10 +387,17 @@ export function useCreateProject() {
|
|
|
312
387
|
export function useLeaveProject() {
|
|
313
388
|
const queryClient = useQueryClient();
|
|
314
389
|
const clientApi = useClientApi();
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
390
|
+
return filterMutationResult(useMutation({
|
|
391
|
+
...baseMutationOptions(),
|
|
392
|
+
mutationFn: async ({ projectId }) => {
|
|
393
|
+
return clientApi.leaveProject(projectId);
|
|
394
|
+
},
|
|
395
|
+
onSuccess: () => {
|
|
396
|
+
queryClient.invalidateQueries({
|
|
397
|
+
queryKey: getProjectsQueryKey(),
|
|
398
|
+
});
|
|
399
|
+
},
|
|
400
|
+
}));
|
|
319
401
|
}
|
|
320
402
|
/**
|
|
321
403
|
* Update the categories of a project using an external file.
|
|
@@ -325,14 +407,17 @@ export function useLeaveProject() {
|
|
|
325
407
|
export function useImportProjectCategories({ projectId, }) {
|
|
326
408
|
const queryClient = useQueryClient();
|
|
327
409
|
const { data: projectApi } = useSingleProject({ projectId });
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
410
|
+
return filterMutationResult(useMutation({
|
|
411
|
+
...baseMutationOptions(),
|
|
412
|
+
mutationFn: ({ filePath }) => {
|
|
413
|
+
return projectApi.$importCategories({ filePath });
|
|
414
|
+
},
|
|
415
|
+
onSuccess: () => {
|
|
416
|
+
queryClient.invalidateQueries({
|
|
417
|
+
queryKey: getProjectByIdQueryKey({ projectId }),
|
|
418
|
+
});
|
|
419
|
+
},
|
|
332
420
|
}));
|
|
333
|
-
return status === 'error'
|
|
334
|
-
? { error, mutate, mutateAsync, reset, status }
|
|
335
|
-
: { error: null, mutate, mutateAsync, reset, status };
|
|
336
421
|
}
|
|
337
422
|
/**
|
|
338
423
|
* Update the configuration of a project using an external file.
|
|
@@ -343,23 +428,37 @@ export function useImportProjectCategories({ projectId, }) {
|
|
|
343
428
|
export function useImportProjectConfig({ projectId }) {
|
|
344
429
|
const queryClient = useQueryClient();
|
|
345
430
|
const { data: projectApi } = useSingleProject({ projectId });
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
431
|
+
return filterMutationResult(useMutation({
|
|
432
|
+
...baseMutationOptions(),
|
|
433
|
+
mutationFn: ({ configPath }) => {
|
|
434
|
+
return projectApi.importConfig({ configPath });
|
|
435
|
+
},
|
|
436
|
+
onSuccess: () => {
|
|
437
|
+
queryClient.invalidateQueries({
|
|
438
|
+
queryKey: getProjectByIdQueryKey({ projectId }),
|
|
439
|
+
});
|
|
440
|
+
},
|
|
441
|
+
}));
|
|
350
442
|
}
|
|
351
443
|
/**
|
|
352
444
|
* Update the settings of a project.
|
|
353
445
|
*
|
|
354
446
|
* @param opts.projectId Public ID of the project to apply changes to.
|
|
355
447
|
*/
|
|
356
|
-
export function useUpdateProjectSettings({ projectId }) {
|
|
448
|
+
export function useUpdateProjectSettings({ projectId, }) {
|
|
357
449
|
const queryClient = useQueryClient();
|
|
358
450
|
const { data: projectApi } = useSingleProject({ projectId });
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
451
|
+
return filterMutationResult(useMutation({
|
|
452
|
+
...baseMutationOptions(),
|
|
453
|
+
mutationFn: async (value) => {
|
|
454
|
+
return projectApi.$setProjectSettings(value);
|
|
455
|
+
},
|
|
456
|
+
onSuccess: () => {
|
|
457
|
+
queryClient.invalidateQueries({
|
|
458
|
+
queryKey: getProjectsQueryKey(),
|
|
459
|
+
});
|
|
460
|
+
},
|
|
461
|
+
}));
|
|
363
462
|
}
|
|
364
463
|
/**
|
|
365
464
|
* Change a project member's role.
|
|
@@ -378,10 +477,20 @@ export function useUpdateProjectSettings({ projectId }) {
|
|
|
378
477
|
export function useChangeMemberRole({ projectId }) {
|
|
379
478
|
const queryClient = useQueryClient();
|
|
380
479
|
const { data: projectApi } = useSingleProject({ projectId });
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
480
|
+
return filterMutationResult(useMutation({
|
|
481
|
+
...baseMutationOptions(),
|
|
482
|
+
mutationFn: async ({ deviceId, roleId, }) => {
|
|
483
|
+
return projectApi.$member.assignRole(deviceId, roleId);
|
|
484
|
+
},
|
|
485
|
+
onSuccess: () => {
|
|
486
|
+
queryClient.invalidateQueries({
|
|
487
|
+
queryKey: getMembersQueryKey({ projectId }),
|
|
488
|
+
});
|
|
489
|
+
queryClient.invalidateQueries({
|
|
490
|
+
queryKey: getProjectRoleQueryKey({ projectId }),
|
|
491
|
+
});
|
|
492
|
+
},
|
|
493
|
+
}));
|
|
385
494
|
}
|
|
386
495
|
/**
|
|
387
496
|
* Remove a member from a project, providing an optional reason for removal.
|
|
@@ -405,39 +514,55 @@ export function useChangeMemberRole({ projectId }) {
|
|
|
405
514
|
export function useRemoveMember({ projectId }) {
|
|
406
515
|
const queryClient = useQueryClient();
|
|
407
516
|
const { data: projectApi } = useSingleProject({ projectId });
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
517
|
+
return filterMutationResult(useMutation({
|
|
518
|
+
...baseMutationOptions(),
|
|
519
|
+
mutationFn: async ({ deviceId, reason, }) => {
|
|
520
|
+
// Have to avoid passing `undefined` explicitly
|
|
521
|
+
// See https://github.com/digidem/rpc-reflector/issues/21
|
|
522
|
+
return reason
|
|
523
|
+
? projectApi.$member.remove(deviceId, { reason })
|
|
524
|
+
: projectApi.$member.remove(deviceId);
|
|
525
|
+
},
|
|
526
|
+
onSuccess: () => {
|
|
527
|
+
queryClient.invalidateQueries({
|
|
528
|
+
queryKey: getMembersQueryKey({ projectId }),
|
|
529
|
+
});
|
|
530
|
+
},
|
|
531
|
+
}));
|
|
412
532
|
}
|
|
413
533
|
/**
|
|
414
534
|
* Set up listener for changes to your own role in a project.
|
|
415
535
|
* It is necessary to use this if you want the project role-related read hooks to update
|
|
416
536
|
* based on role change events that are received in the background.
|
|
417
537
|
*
|
|
418
|
-
*
|
|
538
|
+
*
|
|
419
539
|
*
|
|
420
540
|
* @example
|
|
421
541
|
* ```tsx
|
|
422
|
-
* function
|
|
542
|
+
* function ListenerComponent({ projectId }: { projectId: string }) {
|
|
543
|
+
* // Set up the listener
|
|
423
544
|
* useProjectOwnRoleChangeListener({ projectId })
|
|
424
545
|
* }
|
|
425
|
-
* ```
|
|
426
546
|
*
|
|
427
|
-
*
|
|
428
|
-
*
|
|
429
|
-
*
|
|
430
|
-
*
|
|
431
|
-
*
|
|
432
|
-
*
|
|
433
|
-
*
|
|
434
|
-
* console.log('New role:', event.role)
|
|
547
|
+
* // Handle role change events separately
|
|
548
|
+
* function EventHandlerComponent() {
|
|
549
|
+
* const { data: projectApi } = useSingleProject({ projectId })
|
|
550
|
+
*
|
|
551
|
+
* useEffect(() => {
|
|
552
|
+
* function handleRoleChangeEvent(event) {
|
|
553
|
+
* // Do something with event...
|
|
435
554
|
* }
|
|
436
|
-
*
|
|
555
|
+
*
|
|
556
|
+
* projectApi.addListener('own-role-change', handleRoleChangeEvent)
|
|
557
|
+
*
|
|
558
|
+
* return () => {
|
|
559
|
+
* projectApi.removeListener('own-role-change', handleRoleChangeEvent)
|
|
560
|
+
* }
|
|
561
|
+
* }, [projectApi])
|
|
437
562
|
* }
|
|
438
563
|
* ```
|
|
439
564
|
*/
|
|
440
|
-
export function useProjectOwnRoleChangeListener({ projectId,
|
|
565
|
+
export function useProjectOwnRoleChangeListener({ projectId, }) {
|
|
441
566
|
const queryClient = useQueryClient();
|
|
442
567
|
const { data: projectApi } = useSingleProject({ projectId });
|
|
443
568
|
useEffect(() => {
|
|
@@ -454,16 +579,6 @@ export function useProjectOwnRoleChangeListener({ projectId, listener, }) {
|
|
|
454
579
|
projectApi.removeListener('own-role-change', invalidateCache);
|
|
455
580
|
};
|
|
456
581
|
}, [projectApi, queryClient, projectId]);
|
|
457
|
-
useEffect(() => {
|
|
458
|
-
if (listener) {
|
|
459
|
-
projectApi.addListener('own-role-change', listener);
|
|
460
|
-
}
|
|
461
|
-
return () => {
|
|
462
|
-
if (listener) {
|
|
463
|
-
projectApi.removeListener('own-role-change', listener);
|
|
464
|
-
}
|
|
465
|
-
};
|
|
466
|
-
}, [projectApi, listener]);
|
|
467
582
|
}
|
|
468
583
|
/**
|
|
469
584
|
* Create a blob for a project.
|
|
@@ -472,10 +587,12 @@ export function useProjectOwnRoleChangeListener({ projectId, listener, }) {
|
|
|
472
587
|
*/
|
|
473
588
|
export function useCreateBlob({ projectId }) {
|
|
474
589
|
const { data: projectApi } = useSingleProject({ projectId });
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
590
|
+
return filterMutationResult(useMutation({
|
|
591
|
+
...baseMutationOptions(),
|
|
592
|
+
mutationFn: async ({ original, preview, thumbnail, metadata, }) => {
|
|
593
|
+
return projectApi.$blobs.create({ original, preview, thumbnail }, metadata);
|
|
594
|
+
},
|
|
595
|
+
}));
|
|
479
596
|
}
|
|
480
597
|
const PROJECT_SYNC_STORE_MAP = new WeakMap();
|
|
481
598
|
function useSyncStore({ projectId }) {
|
|
@@ -525,38 +642,50 @@ export function useDataSyncProgress({ projectId, }) {
|
|
|
525
642
|
}
|
|
526
643
|
export function useStartSync({ projectId }) {
|
|
527
644
|
const { data: projectApi } = useSingleProject({ projectId });
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
645
|
+
return filterMutationResult(useMutation({
|
|
646
|
+
...baseMutationOptions(),
|
|
647
|
+
mutationFn: async (opts) => {
|
|
648
|
+
// Have to avoid passing `undefined` explicitly
|
|
649
|
+
// See https://github.com/digidem/rpc-reflector/issues/21
|
|
650
|
+
return opts ? projectApi.$sync.start(opts) : projectApi.$sync.start();
|
|
651
|
+
},
|
|
652
|
+
}));
|
|
532
653
|
}
|
|
533
654
|
export function useStopSync({ projectId }) {
|
|
534
655
|
const { data: projectApi } = useSingleProject({ projectId });
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
656
|
+
return filterMutationResult(useMutation({
|
|
657
|
+
...baseMutationOptions(),
|
|
658
|
+
mutationFn: async () => {
|
|
659
|
+
return projectApi.$sync.stop();
|
|
660
|
+
},
|
|
661
|
+
}));
|
|
539
662
|
}
|
|
540
663
|
export function useConnectSyncServers({ projectId }) {
|
|
541
664
|
const { data: projectApi } = useSingleProject({ projectId });
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
665
|
+
return filterMutationResult(useMutation({
|
|
666
|
+
...baseMutationOptions(),
|
|
667
|
+
mutationFn: async () => {
|
|
668
|
+
return projectApi.$sync.connectServers();
|
|
669
|
+
},
|
|
670
|
+
}));
|
|
546
671
|
}
|
|
547
672
|
export function useDisconnectSyncServers({ projectId }) {
|
|
548
673
|
const { data: projectApi } = useSingleProject({ projectId });
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
674
|
+
return filterMutationResult(useMutation({
|
|
675
|
+
...baseMutationOptions(),
|
|
676
|
+
mutationFn: async () => {
|
|
677
|
+
return projectApi.$sync.disconnectServers();
|
|
678
|
+
},
|
|
679
|
+
}));
|
|
553
680
|
}
|
|
554
681
|
export function useSetAutostopDataSyncTimeout({ projectId, }) {
|
|
555
682
|
const { data: projectApi } = useSingleProject({ projectId });
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
683
|
+
return filterMutationResult(useMutation({
|
|
684
|
+
...baseMutationOptions(),
|
|
685
|
+
mutationFn: async ({ after }) => {
|
|
686
|
+
return projectApi.$sync.setAutostopDataSyncTimeout(after);
|
|
687
|
+
},
|
|
688
|
+
}));
|
|
560
689
|
}
|
|
561
690
|
/**
|
|
562
691
|
* Creates a GeoJson file with all the observations and/or tracks in the project.
|
|
@@ -565,10 +694,12 @@ export function useSetAutostopDataSyncTimeout({ projectId, }) {
|
|
|
565
694
|
*/
|
|
566
695
|
export function useExportGeoJSON({ projectId }) {
|
|
567
696
|
const { data: projectApi } = useSingleProject({ projectId });
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
697
|
+
return filterMutationResult(useMutation({
|
|
698
|
+
...baseMutationOptions(),
|
|
699
|
+
mutationFn: async (opts) => {
|
|
700
|
+
return projectApi.exportGeoJSONFile(opts.path, opts.exportOptions);
|
|
701
|
+
},
|
|
702
|
+
}));
|
|
572
703
|
}
|
|
573
704
|
/**
|
|
574
705
|
* Creates a zip file containing a GeoJson file with all the observations and/or tracks in the project and all associated attachments (photos and audio).
|
|
@@ -577,8 +708,10 @@ export function useExportGeoJSON({ projectId }) {
|
|
|
577
708
|
*/
|
|
578
709
|
export function useExportZipFile({ projectId }) {
|
|
579
710
|
const { data: projectApi } = useSingleProject({ projectId });
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
711
|
+
return filterMutationResult(useMutation({
|
|
712
|
+
...baseMutationOptions(),
|
|
713
|
+
mutationFn: async (opts) => {
|
|
714
|
+
return projectApi.exportZipFile(opts.path, opts.exportOptions);
|
|
715
|
+
},
|
|
716
|
+
}));
|
|
584
717
|
}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -6,6 +6,6 @@ export { useMapStyleUrl, useImportCustomMapFile, useRemoveCustomMapFile, useGetC
|
|
|
6
6
|
export type { SentMapShareState, ReceivedMapShareState, AbortMapShareOptions, CancelMapShareOptions, DeclineMapShareOptions, DownloadMapShareOptions, CreateAndSendMapShareOptions, } from './lib/map-shares-stores.js';
|
|
7
7
|
export { DeclineReason } from './lib/map-shares-stores.js';
|
|
8
8
|
export { useAddServerPeer, useAttachmentUrl, useConnectSyncServers, useCreateBlob, useCreateProject, useDataSyncProgress, useDisconnectSyncServers, useDocumentCreatedBy, useIconUrl, useImportProjectCategories, useImportProjectConfig, useLeaveProject, useManyMembers, useManyProjects, useOwnRoleInProject, useProjectOwnRoleChangeListener, useProjectSettings, useRemoveServerPeer, useRemoveMember, useSetAutostopDataSyncTimeout, useSingleMember, useSingleProject, useStartSync, useStopSync, useSyncState, useUpdateProjectSettings, useChangeMemberRole, useExportGeoJSON, useExportZipFile, } from './hooks/projects.js';
|
|
9
|
-
export {
|
|
10
|
-
export {
|
|
9
|
+
export type { SyncState } from './lib/sync.js';
|
|
10
|
+
export type { WriteableDocument, WriteableDocumentType, WriteableValue, } from './lib/types.js';
|
|
11
11
|
export { HTTPError, isHTTPError } from './lib/http.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { MapShare } from '@comapeo/core';
|
|
2
2
|
import type { MapeoClientApi } from '@comapeo/ipc';
|
|
3
3
|
import { type MapShareState as ServerMapShareState } from '@comapeo/map-server';
|
|
4
|
-
import {
|
|
4
|
+
import type { QueryClient } from '@tanstack/react-query';
|
|
5
5
|
import type { Simplify } from 'type-fest';
|
|
6
6
|
import type { MapServerApi } from '../contexts/MapServer.js';
|
|
7
7
|
type DistributedIntersection<T, U> = U extends unknown ? Simplify<T & U> : never;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CUSTOM_MAP_ID } from '@comapeo/map-server/constants.js';
|
|
2
2
|
import { errors } from '@comapeo/map-server/errors.js';
|
|
3
3
|
import ensureError from 'ensure-error';
|
|
4
|
-
import { invalidateMapQueries } from './react-query
|
|
4
|
+
import { invalidateMapQueries } from './react-query.js';
|
|
5
5
|
// ============================================
|
|
6
6
|
// ACTION OPTIONS TYPES
|
|
7
7
|
// These are defined here so that VSCode tooltips work for the mutation
|