@mapcreator/api 0.0.0-co-edit.4 → 0.0.0-co-edit.5
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/cjs/api/apiCommon.d.ts +3 -1
- package/cjs/api/apiCommon.d.ts.map +1 -1
- package/cjs/api/apiCommon.js +6 -13
- package/cjs/api/apiCommon.js.map +1 -1
- package/cjs/api/job.d.ts +22 -3
- package/cjs/api/job.d.ts.map +1 -1
- package/cjs/api/job.js +29 -4
- package/cjs/api/job.js.map +1 -1
- package/cjs/api/jobRevision.d.ts +2 -0
- package/cjs/api/jobRevision.d.ts.map +1 -1
- package/cjs/api/jobRevision.js +40 -1
- package/cjs/api/jobRevision.js.map +1 -1
- package/cjs/api/organisation.d.ts +2 -2
- package/cjs/api/organisation.d.ts.map +1 -1
- package/cjs/api/organisation.js +2 -3
- package/cjs/api/organisation.js.map +1 -1
- package/cjs/api/resources.d.ts +22 -0
- package/cjs/api/resources.d.ts.map +1 -1
- package/cjs/api/resources.js +2 -0
- package/cjs/api/resources.js.map +1 -1
- package/cjs/api/user.d.ts +5 -3
- package/cjs/api/user.d.ts.map +1 -1
- package/cjs/api/user.js +9 -5
- package/cjs/api/user.js.map +1 -1
- package/esm/api/apiCommon.d.ts +3 -1
- package/esm/api/apiCommon.d.ts.map +1 -1
- package/esm/api/apiCommon.js +6 -13
- package/esm/api/apiCommon.js.map +1 -1
- package/esm/api/job.d.ts +22 -3
- package/esm/api/job.d.ts.map +1 -1
- package/esm/api/job.js +23 -4
- package/esm/api/job.js.map +1 -1
- package/esm/api/jobRevision.d.ts +2 -0
- package/esm/api/jobRevision.d.ts.map +1 -1
- package/esm/api/jobRevision.js +40 -2
- package/esm/api/jobRevision.js.map +1 -1
- package/esm/api/organisation.d.ts +2 -2
- package/esm/api/organisation.d.ts.map +1 -1
- package/esm/api/organisation.js +2 -3
- package/esm/api/organisation.js.map +1 -1
- package/esm/api/resources.d.ts +22 -0
- package/esm/api/resources.d.ts.map +1 -1
- package/esm/api/resources.js +2 -0
- package/esm/api/resources.js.map +1 -1
- package/esm/api/user.d.ts +5 -3
- package/esm/api/user.d.ts.map +1 -1
- package/esm/api/user.js +7 -4
- package/esm/api/user.js.map +1 -1
- package/package.json +2 -1
- package/src/api/apiCommon.ts +21 -16
- package/src/api/job.ts +46 -6
- package/src/api/jobRevision.ts +59 -1
- package/src/api/organisation.ts +6 -6
- package/src/api/resources.ts +30 -0
- package/src/api/user.ts +21 -9
package/src/api/job.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ApiJobShare, JobShare, JobShareVisibility } from './jobShare.js';
|
|
2
|
-
import { type JobSearchResult, listJobs } from './apiCommon.js';
|
|
2
|
+
import { type DashboardSortType, type JobSearchResult, listJobs } from './apiCommon.js';
|
|
3
3
|
import {
|
|
4
4
|
type ApiCommon,
|
|
5
5
|
type ApiCommonData,
|
|
@@ -23,6 +23,7 @@ export type Job = {
|
|
|
23
23
|
previewPath: string | undefined;
|
|
24
24
|
convertedJobId: number | null;
|
|
25
25
|
private: boolean;
|
|
26
|
+
jobOpenUserName: string | null;
|
|
26
27
|
|
|
27
28
|
userEmail: string | undefined; // ?
|
|
28
29
|
orgName: string | undefined; // ?
|
|
@@ -42,6 +43,7 @@ export type ApiJob = {
|
|
|
42
43
|
star: boolean; // TODO: not present in API specification!
|
|
43
44
|
converted_job_id?: number | null;
|
|
44
45
|
private: boolean;
|
|
46
|
+
job_open_user_name: string | null;
|
|
45
47
|
} & ApiCommonData;
|
|
46
48
|
} & Omit<ApiSuccess, 'data'> | ApiError;
|
|
47
49
|
|
|
@@ -58,9 +60,9 @@ export const jobRevivers: Revivers<ApiJob, Job> = {
|
|
|
58
60
|
convertedJobId: (data: ApiJobData) => data.converted_job_id ?? null,
|
|
59
61
|
};
|
|
60
62
|
|
|
61
|
-
export async function createJob(title: string, oldJobId?: number): Promise<Job> {
|
|
63
|
+
export async function createJob(title: string, jobTypeId = 9, oldJobId?: number): Promise<Job> {
|
|
62
64
|
const path = `/v1/jobs`;
|
|
63
|
-
const body = { title, job_type_id:
|
|
65
|
+
const body = { title, job_type_id: jobTypeId, ...oldJobId && { cloned_v4_job_id: oldJobId } };
|
|
64
66
|
const options = { revivers: jobRevivers };
|
|
65
67
|
|
|
66
68
|
// Technically, the returning `data` will contain only the following fields:
|
|
@@ -146,9 +148,47 @@ export async function uploadJobPreview(
|
|
|
146
148
|
}
|
|
147
149
|
|
|
148
150
|
export async function listFeaturedJobs(
|
|
149
|
-
|
|
151
|
+
search: string,
|
|
152
|
+
sort: DashboardSortType,
|
|
150
153
|
page: number,
|
|
151
|
-
options?: Record<string, unknown>,
|
|
152
154
|
): Promise<JobSearchResult> {
|
|
153
|
-
return listJobs(`/v1/jobs/featured`,
|
|
155
|
+
return listJobs(`/v1/jobs/featured`, search, sort, 'all', page);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export type JobCoEditEvent = {
|
|
159
|
+
jobId: number;
|
|
160
|
+
userName: string;
|
|
161
|
+
status: 'open' | 'close';
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
export type JobTakeoverEvent = {
|
|
165
|
+
userId: number;
|
|
166
|
+
userName: string;
|
|
167
|
+
requestedAt: string;
|
|
168
|
+
status: 'pending' | 'approved' | 'denied';
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
export async function openJob(jobId: number): Promise<Record<string, never>> {
|
|
172
|
+
return request<ApiCommon, Record<string, never>>(`/v1/jobs/${jobId}/open`, null, null, { method: 'POST' });
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export async function heartbeat(jobId: number): Promise<Record<string, never>> {
|
|
176
|
+
// TODO handle disconnections. Throw the right error so we can show a modal in the tool when the connection is down
|
|
177
|
+
return request<ApiCommon, Record<string, never>>(`/v1/jobs/${jobId}/heartbeat`, null, null, { method: 'POST' });
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export async function requestTakeover(jobId: number): Promise<Record<string, never>> {
|
|
181
|
+
return request<ApiCommon, Record<string, never>>(`/v1/jobs/${jobId}/takeover/request`, null, null, { method: 'POST' });
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export async function approveTakeover(jobId: number, userId: number): Promise<Record<string, never>> {
|
|
185
|
+
return request<ApiCommon, Record<string, never>>(`/v1/jobs/${jobId}/takeover/approve`, { user_id: userId }, null, { method: 'POST' });
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export async function denyTakeover(jobId: number, userId: number): Promise<Record<string, never>> {
|
|
189
|
+
return request<ApiCommon, Record<string, never>>(`/v1/jobs/${jobId}/takeover/deny`, { user_id: userId }, null, { method: 'POST' });
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export async function closeJob(jobId: number): Promise<Record<string, never>> {
|
|
193
|
+
return request<ApiCommon, Record<string, never>>(`/v1/jobs/${jobId}/close`, null, null, { method: 'POST' });
|
|
154
194
|
}
|
package/src/api/jobRevision.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { apiHost, authenticate, getAuthorizationHeaders, token } from '../oauth.
|
|
|
2
2
|
import { type ApiLayerData, type Layer, layerRevivers } from './layer.js';
|
|
3
3
|
import type { ApiMapstyleSetData } from './mapstyleSet.js';
|
|
4
4
|
import type { ApiLanguageData } from './language.js';
|
|
5
|
+
import type Echo from 'laravel-echo';
|
|
5
6
|
import {
|
|
6
7
|
APIError,
|
|
7
8
|
type ApiCommon,
|
|
@@ -13,6 +14,7 @@ import {
|
|
|
13
14
|
NetworkError,
|
|
14
15
|
type Revivers,
|
|
15
16
|
TimeoutError,
|
|
17
|
+
combineSignals,
|
|
16
18
|
defaultListHeader,
|
|
17
19
|
defaultTimeout,
|
|
18
20
|
deletedNoneParam,
|
|
@@ -225,11 +227,17 @@ export type JobRevisionOutput = { blob: Blob; filename?: string | undefined };
|
|
|
225
227
|
export async function getJobRevisionOutput(jobId: number): Promise<JobRevisionOutput> {
|
|
226
228
|
await createJobRevisionBuild(jobId);
|
|
227
229
|
|
|
230
|
+
return fetchOutput(jobId);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
async function fetchOutput(jobId: number, signal?: AbortSignal): Promise<JobRevisionOutput> {
|
|
228
234
|
const href = `${apiHost}/v1/jobs/${jobId}/revisions/${lastJobRevision}/result/output`;
|
|
229
235
|
const headers = getAuthorizationHeaders();
|
|
230
236
|
|
|
231
237
|
const timeout = defaultTimeout;
|
|
232
|
-
const { signal, cleanup } = makeTimeoutSignal(timeout);
|
|
238
|
+
const { signal: timeoutSignal, cleanup } = makeTimeoutSignal(timeout);
|
|
239
|
+
|
|
240
|
+
signal = signal ? combineSignals(signal, timeoutSignal) : timeoutSignal;
|
|
233
241
|
|
|
234
242
|
const response = await fetch(href, { headers, signal, ...!token && { credentials: 'include' } })
|
|
235
243
|
.catch((error: Error) => {
|
|
@@ -296,3 +304,53 @@ async function createJobRevisionBuild(jobId: number, skipValidation?: boolean):
|
|
|
296
304
|
|
|
297
305
|
return request<ApiCommon, string>(path, body, null, { method: 'POST' });
|
|
298
306
|
}
|
|
307
|
+
|
|
308
|
+
async function waitForJobToFinish(jobId: number, echo: Echo<'reverb'>, signal?: AbortSignal): Promise<void> {
|
|
309
|
+
signal?.throwIfAborted();
|
|
310
|
+
|
|
311
|
+
return new Promise((resolve, reject) => {
|
|
312
|
+
const channel = `jobresult.${jobId}`;
|
|
313
|
+
|
|
314
|
+
const onAbort = (): void => {
|
|
315
|
+
echo.leaveChannel(channel);
|
|
316
|
+
reject(signal?.reason);
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
const cleanup = (): void => {
|
|
320
|
+
echo.leaveChannel(channel);
|
|
321
|
+
signal?.removeEventListener('abort', onAbort);
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
type JobResultEvent =
|
|
325
|
+
| { revisionId: number; status: string }
|
|
326
|
+
| { revisionId: number; filePathSet: boolean };
|
|
327
|
+
|
|
328
|
+
const handler = (event: JobResultEvent): void => {
|
|
329
|
+
if ('filePathSet' in event) {
|
|
330
|
+
cleanup();
|
|
331
|
+
resolve();
|
|
332
|
+
} else if (event.status !== 'processing' && event.status !== 'queued' && event.status !== 'completed') {
|
|
333
|
+
cleanup();
|
|
334
|
+
reject(new APIError({ success: false, error: { type: 'API Error', message: event.status } }));
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
|
339
|
+
echo.channel(channel).listen('.JobResultEvent', handler);
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export async function getJobRevisionOutputForBackend(
|
|
344
|
+
jobId: number,
|
|
345
|
+
echo: Echo<'reverb'>,
|
|
346
|
+
signal?: AbortSignal,
|
|
347
|
+
): Promise<JobRevisionOutput> {
|
|
348
|
+
await createJobRevisionBuild(jobId);
|
|
349
|
+
const jobrevision = await getJobRevision(jobId);
|
|
350
|
+
|
|
351
|
+
if (jobrevision) {
|
|
352
|
+
await waitForJobToFinish(jobrevision.id, echo, signal);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
return fetchOutput(jobId);
|
|
356
|
+
}
|
package/src/api/organisation.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ApiJobShareArray, JobShare } from './jobShare.js';
|
|
2
|
-
import { type JobSearchResult, listJobs } from './apiCommon.js';
|
|
2
|
+
import { type DashboardFilterType, type DashboardSortType, type JobSearchResult, listJobs } from './apiCommon.js';
|
|
3
3
|
import {
|
|
4
4
|
type ApiCommonData,
|
|
5
5
|
type ApiError,
|
|
@@ -74,13 +74,13 @@ export async function getOrganisation(
|
|
|
74
74
|
|
|
75
75
|
export async function listOrganisationJobs(
|
|
76
76
|
organisationId: number | typeof myOrganisations,
|
|
77
|
-
|
|
77
|
+
search: string,
|
|
78
|
+
sort: DashboardSortType,
|
|
79
|
+
filter: DashboardFilterType,
|
|
78
80
|
page: number,
|
|
79
|
-
|
|
81
|
+
folderId: number | null
|
|
80
82
|
): Promise<JobSearchResult> {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
return listJobs(`/v1/organisations/${organisationId}/jobs`, title, page, search);
|
|
83
|
+
return listJobs(`/v1/organisations/${organisationId}/jobs`, search, sort, filter, page, folderId);
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
export async function listOrganisationShares(jobId: number): Promise<JobShare[]> {
|
package/src/api/resources.ts
CHANGED
|
@@ -51,6 +51,30 @@ export type CustomFeature =
|
|
|
51
51
|
| 'developer_menu'
|
|
52
52
|
| 'allow_editing_other_users_jobs';
|
|
53
53
|
|
|
54
|
+
export type ApiAccessibleOrganisationFolder = {
|
|
55
|
+
id: number;
|
|
56
|
+
organisation_id: number;
|
|
57
|
+
name: string;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export type AccessibleOrganisationFolder = {
|
|
61
|
+
id: number;
|
|
62
|
+
organisationId: number;
|
|
63
|
+
name: string;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export type ApiAccessibleOrganisation = {
|
|
67
|
+
id: number;
|
|
68
|
+
name: string;
|
|
69
|
+
job_folders: ApiAccessibleOrganisationFolder[];
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export type AccessibleOrganisation = {
|
|
73
|
+
id: number;
|
|
74
|
+
name: string;
|
|
75
|
+
jobFolders: AccessibleOrganisationFolder[];
|
|
76
|
+
};
|
|
77
|
+
|
|
54
78
|
export interface Resources {
|
|
55
79
|
organisation: Organisation;
|
|
56
80
|
user: User;
|
|
@@ -66,6 +90,7 @@ export interface Resources {
|
|
|
66
90
|
layers: Layer[];
|
|
67
91
|
fonts: Font[];
|
|
68
92
|
fontFamilies: FontFamily[];
|
|
93
|
+
accessibleOrganisations: AccessibleOrganisation[];
|
|
69
94
|
}
|
|
70
95
|
|
|
71
96
|
type ApiResources = {
|
|
@@ -88,6 +113,7 @@ type ApiResources = {
|
|
|
88
113
|
layers: ApiLayerData[];
|
|
89
114
|
fonts: ApiFontData[];
|
|
90
115
|
font_families: ApiFontFamilyData[];
|
|
116
|
+
accessible_organisations: ApiAccessibleOrganisation[];
|
|
91
117
|
} & ApiCommonData;
|
|
92
118
|
} & Omit<ApiSuccess, 'data'> | ApiError;
|
|
93
119
|
|
|
@@ -132,6 +158,10 @@ export async function loadResources(): Promise<Resources> {
|
|
|
132
158
|
svgSets: (raw.svgSets?.map(processData, getContext(svgSetRevivers)) ?? []) as SvgSet[],
|
|
133
159
|
fonts: (raw.fonts?.map(processData, getContext(fontRevivers)) ?? []) as Font[],
|
|
134
160
|
fontFamilies: (raw.fontFamilies?.map(processData, getContext(fontFamilyRevivers)) ?? []) as FontFamily[],
|
|
161
|
+
// TODO revivers and such
|
|
162
|
+
accessibleOrganisations: (raw.accessibleOrganisations?.map(
|
|
163
|
+
processData, getContext({})
|
|
164
|
+
) ?? []) as AccessibleOrganisation[],
|
|
135
165
|
};
|
|
136
166
|
}
|
|
137
167
|
|
package/src/api/user.ts
CHANGED
|
@@ -2,8 +2,9 @@ import { type ApiFontFamilyData, type FontFamily, fontFamilyRevivers } from './f
|
|
|
2
2
|
import { type ApiSvgSetData, type SvgSet, svgSetRevivers } from './svgSet.js';
|
|
3
3
|
import { type ApiLayerData, type Layer, layerRevivers } from './layer.js';
|
|
4
4
|
import { type ApiSvgData, type Svg, svgRevivers } from './svg.js';
|
|
5
|
-
import { type JobSearchResult, listJobs } from './apiCommon.js';
|
|
5
|
+
import { type DashboardFilterType, type DashboardSortType, type JobSearchResult, listJobs } from './apiCommon.js';
|
|
6
6
|
import type { ApiJobShareArray, JobShare } from './jobShare.js';
|
|
7
|
+
import type { AccessibleOrganisation, ApiAccessibleOrganisation } from './resources.js';
|
|
7
8
|
import type { RequireAtLeastOne } from 'type-fest';
|
|
8
9
|
import {
|
|
9
10
|
type ApiCommon,
|
|
@@ -210,21 +211,32 @@ export async function listUserHatchingSvgs(): Promise<Svg[]> {
|
|
|
210
211
|
|
|
211
212
|
export async function listUserJobs(
|
|
212
213
|
userId: number | typeof myUser,
|
|
213
|
-
|
|
214
|
+
search: string,
|
|
215
|
+
sort: DashboardSortType,
|
|
216
|
+
filter: DashboardFilterType,
|
|
214
217
|
page: number,
|
|
215
|
-
options?: Record<string, unknown>
|
|
216
218
|
): Promise<JobSearchResult> {
|
|
217
|
-
return listJobs(`/v1/users/${userId}/jobs`,
|
|
219
|
+
return listJobs(`/v1/users/${userId}/jobs`, search, sort, filter, page);
|
|
218
220
|
}
|
|
219
221
|
|
|
220
|
-
export async function
|
|
221
|
-
|
|
222
|
+
export async function listUserEditedJobs(
|
|
223
|
+
userId: number | typeof myUser,
|
|
224
|
+
search: string,
|
|
225
|
+
sort: DashboardSortType,
|
|
226
|
+
filter: DashboardFilterType,
|
|
227
|
+
page: number,
|
|
228
|
+
): Promise<JobSearchResult> {
|
|
229
|
+
return listJobs(`/v1/users/${userId}/edited-jobs`, search, sort, filter, page);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export async function listUserAccessibleOrganisations(): Promise<AccessibleOrganisation[]> {
|
|
233
|
+
const path = `/v1/users/${myUser}/accessible-organisations`;
|
|
222
234
|
|
|
223
|
-
type
|
|
224
|
-
data:
|
|
235
|
+
type ApiAccessibleOrganisationArray = {
|
|
236
|
+
data: ApiAccessibleOrganisation[];
|
|
225
237
|
} & Omit<ApiSuccess, 'data'> | ApiError;
|
|
226
238
|
|
|
227
|
-
return request<
|
|
239
|
+
return request<ApiAccessibleOrganisationArray, AccessibleOrganisation>(path);
|
|
228
240
|
}
|
|
229
241
|
|
|
230
242
|
export async function createUserFolder(name: string): Promise<JobFolder> {
|