@overmap-ai/core 1.0.58-no-hardcoding-api-urls.0 → 1.0.58-sign-up-hotfix.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.
@@ -1728,6 +1728,16 @@ var __publicField = (obj, key, value) => {
1728
1728
  }
1729
1729
  prevAssets = null;
1730
1730
  },
1731
+ updateAssets: (state, action) => {
1732
+ for (const asset of action.payload) {
1733
+ if (asset.offline_id in state.assets) {
1734
+ state.assets[asset.offline_id] = asset;
1735
+ } else {
1736
+ throw new Error(`Tried to update asset with ID that doesn't exist: ${asset.offline_id}`);
1737
+ }
1738
+ }
1739
+ prevAssets = null;
1740
+ },
1731
1741
  removeAsset: (state, action) => {
1732
1742
  if (action.payload in state.assets) {
1733
1743
  delete state.assets[action.payload];
@@ -1736,6 +1746,16 @@ var __publicField = (obj, key, value) => {
1736
1746
  }
1737
1747
  prevAssets = null;
1738
1748
  },
1749
+ removeAssets: (state, action) => {
1750
+ for (const assetId of action.payload) {
1751
+ if (assetId in state.assets) {
1752
+ delete state.assets[assetId];
1753
+ } else {
1754
+ throw new Error(`Failed to remove asset because ID doesn't exist: ${assetId}`);
1755
+ }
1756
+ }
1757
+ prevAssets = null;
1758
+ },
1739
1759
  removeAllAssetsOfType: (state, action) => {
1740
1760
  var _a2;
1741
1761
  for (const componentId in state.assets) {
@@ -1759,7 +1779,9 @@ var __publicField = (obj, key, value) => {
1759
1779
  const {
1760
1780
  addAsset,
1761
1781
  updateAsset,
1782
+ updateAssets,
1762
1783
  removeAsset,
1784
+ removeAssets,
1763
1785
  addAssetsInBatches,
1764
1786
  setAssets,
1765
1787
  removeAllAssetsOfType,
@@ -3800,17 +3822,15 @@ var __publicField = (obj, key, value) => {
3800
3822
  (_state, search) => search
3801
3823
  ],
3802
3824
  (userForms, revisions, search) => {
3803
- const { searchTerm, maxResults, favorites, owner_organization, owner_user } = search;
3825
+ const { searchTerm, maxResults, favorites, organization } = search;
3804
3826
  const favoriteMatches = [];
3805
3827
  const regularMatches = [];
3806
3828
  for (const [userFormId, userForm] of Object.entries(userForms)) {
3807
3829
  if (favorites !== void 0 && userForm.favorite != favorites)
3808
3830
  continue;
3809
- if (Number.isInteger(owner_organization) && owner_organization !== userForm.owner_organization) {
3831
+ if (Number.isInteger(organization) && organization !== userForm.organization) {
3810
3832
  continue;
3811
3833
  }
3812
- if (Number.isInteger(owner_user) && owner_user !== userForm.owner_user)
3813
- continue;
3814
3834
  const latestRevision = _selectLatestFormRevision(revisions, userFormId);
3815
3835
  if (latestRevision.title.toLowerCase().includes(searchTerm.toLowerCase())) {
3816
3836
  if (userForm.favorite) {
@@ -4595,10 +4615,6 @@ var __publicField = (obj, key, value) => {
4595
4615
  throw new Error(`Failed to update index_workspace of issue ${issue.offline_id} to main workspace`);
4596
4616
  }
4597
4617
  }
4598
- const indexedForms = Object.values(draft.formReducer.forms).filter((form) => form.index_workspace === workspaceId);
4599
- for (const form of indexedForms) {
4600
- form.index_workspace = mainWorkspace.offline_id;
4601
- }
4602
4618
  }
4603
4619
  const rootReducer = (state, action) => {
4604
4620
  if (action.type === "auth/setLoggedIn" && !action.payload) {
@@ -5368,6 +5384,15 @@ var __publicField = (obj, key, value) => {
5368
5384
  store.dispatch(setCategories(result));
5369
5385
  }
5370
5386
  }
5387
+ function chunkArray(arr, chunkSize) {
5388
+ const chunks = [];
5389
+ let index2 = 0;
5390
+ const arrLength = arr.length;
5391
+ while (index2 < arrLength) {
5392
+ chunks.push(arr.slice(index2, index2 += chunkSize));
5393
+ }
5394
+ return chunks;
5395
+ }
5371
5396
  class AssetService extends BaseApiService {
5372
5397
  // Basic CRUD functions
5373
5398
  add(asset, workspaceId) {
@@ -5444,36 +5469,55 @@ var __publicField = (obj, key, value) => {
5444
5469
  throw err;
5445
5470
  });
5446
5471
  }
5447
- async addBatch(assetsToCreate, workspaceId, assetTypeId) {
5448
- const fullAssets = assetsToCreate.map((asset) => {
5449
- return { ...offline(asset), submitted_at: (/* @__PURE__ */ new Date()).toISOString() };
5450
- });
5472
+ // TODO: payload does not require asset_type
5473
+ bulkAdd(assetsToCreate, workspaceId, assetTypeId, batchSize) {
5451
5474
  const { store } = this.client;
5452
- store.dispatch(addAssetsInBatches(fullAssets));
5453
- const promise = this.client.enqueueRequest({
5454
- description: "Batch create assets",
5455
- method: HttpMethod.POST,
5456
- url: `/assets/types/${assetTypeId}/add-assets/`,
5457
- queryParams: {
5458
- workspace_id: workspaceId.toString()
5459
- },
5460
- payload: {
5461
- assets: fullAssets
5462
- },
5463
- blockers: [assetTypeId],
5464
- blocks: fullAssets.map((c) => c.offline_id)
5475
+ const submittedAt = (/* @__PURE__ */ new Date()).toISOString();
5476
+ const transactionId = uuid.v4();
5477
+ const assetBatches = chunkArray(assetsToCreate, batchSize).map((assetBatch) => {
5478
+ const assetPayloads = assetBatch.map((assetPayload) => {
5479
+ return offline({
5480
+ ...assetPayload,
5481
+ submitted_at: submittedAt
5482
+ });
5483
+ });
5484
+ return {
5485
+ batchId: uuid.v4(),
5486
+ payload: {
5487
+ transaction_id: transactionId,
5488
+ assets: assetPayloads
5489
+ }
5490
+ };
5465
5491
  });
5466
- void promise.then((result) => {
5467
- for (const assets of Object.values(result)) {
5468
- store.dispatch(updateAsset(assets));
5469
- }
5470
- }).catch((e) => {
5471
- for (const asset of fullAssets) {
5472
- store.dispatch(removeAsset(asset.offline_id));
5473
- }
5474
- throw e;
5492
+ const batchPromises = [];
5493
+ let prevBatchId = null;
5494
+ for (const assetBatch of assetBatches) {
5495
+ const { batchId, payload } = assetBatch;
5496
+ const batchAssetOfflineIds = payload.assets.map((c) => c.offline_id);
5497
+ const blockers = [assetTypeId];
5498
+ if (prevBatchId)
5499
+ blockers.push(prevBatchId);
5500
+ const blocks2 = batchAssetOfflineIds;
5501
+ blocks2.push(batchId);
5502
+ const promise = this.client.enqueueRequest({
5503
+ description: "Batch create assets",
5504
+ method: HttpMethod.POST,
5505
+ url: `/assets/types/${assetTypeId}/add-assets/`,
5506
+ queryParams: {
5507
+ workspace_id: workspaceId.toString()
5508
+ },
5509
+ payload,
5510
+ blockers,
5511
+ blocks: blocks2
5512
+ });
5513
+ prevBatchId = assetBatch.batchId;
5514
+ batchPromises.push(promise);
5515
+ }
5516
+ void Promise.all(batchPromises).then((result) => {
5517
+ const allCreatedAssets = result.flat();
5518
+ store.dispatch(addAssetsInBatches(allCreatedAssets));
5475
5519
  });
5476
- return promise;
5520
+ return batchPromises;
5477
5521
  }
5478
5522
  async refreshStore() {
5479
5523
  const { store } = this.client;
@@ -6607,6 +6651,7 @@ var __publicField = (obj, key, value) => {
6607
6651
  store.dispatch(addOrReplaceProjects(projects));
6608
6652
  store.dispatch(addOrReplaceWorkspaces(workspaces));
6609
6653
  }
6654
+ console.debug("currentProjectId", currentProjectId);
6610
6655
  if (!currentProjectId) {
6611
6656
  store.dispatch(setIsFetchingInitialData(false));
6612
6657
  } else {
@@ -6965,8 +7010,7 @@ var __publicField = (obj, key, value) => {
6965
7010
  });
6966
7011
  }
6967
7012
  }
6968
- const separateImageFromFields = async (payload) => {
6969
- const { fields } = payload;
7013
+ const separateImageFromFields = async (fields) => {
6970
7014
  const images = {};
6971
7015
  const newFields = [];
6972
7016
  for (const section of fields) {
@@ -6992,11 +7036,7 @@ var __publicField = (obj, key, value) => {
6992
7036
  }
6993
7037
  newFields.push({ ...section, fields: newSectionFields });
6994
7038
  }
6995
- const payloadWithoutImage = {
6996
- ...payload,
6997
- fields: newFields
6998
- };
6999
- return { payloadWithoutImage, images };
7039
+ return { fields: newFields, images };
7000
7040
  };
7001
7041
  class UserFormService extends BaseApiService {
7002
7042
  constructor() {
@@ -7030,93 +7070,90 @@ var __publicField = (obj, key, value) => {
7030
7070
  });
7031
7071
  });
7032
7072
  }
7033
- async add(state, initialRevision, url, ownerUser, ownerOrganization, assetTypeId, issueTypeId) {
7034
- if (!!ownerUser === !!ownerOrganization) {
7035
- throw new Error("Exactly one of ownerUser and ownerOrganization must be defined.");
7036
- }
7037
- const ownerAttrs = {
7038
- owner_user: ownerUser,
7039
- owner_organization: ownerOrganization
7040
- };
7041
- const currentUser = state.userReducer.currentUser;
7042
- const activeWorkspaceId = state.workspaceReducer.activeWorkspaceId;
7043
- const submittedAt = (/* @__PURE__ */ new Date()).toISOString();
7044
- const offlineFormPayload = offline({ ...ownerAttrs });
7045
- const offlineRevisionPayload = offline({ ...initialRevision, submitted_at: submittedAt });
7046
- const retForm = {
7047
- ...offlineFormPayload,
7048
- index_workspace: activeWorkspaceId,
7049
- favorite: true,
7050
- submitted_at: submittedAt,
7051
- created_by: currentUser.id,
7052
- ...assetTypeId && { asset_type: assetTypeId },
7053
- ...issueTypeId && { issue_type: issueTypeId },
7054
- ...ownerAttrs
7055
- };
7056
- const { payloadWithoutImage, images } = await separateImageFromFields(offlineRevisionPayload);
7057
- const retRevision = {
7058
- ...payloadWithoutImage,
7059
- created_by: currentUser.id,
7060
- form: retForm.offline_id,
7061
- revision: 0,
7062
- submitted_at: submittedAt
7063
- };
7073
+ async add(ownerId, form, initialRevision, urlPrefix) {
7064
7074
  const { store } = this.client;
7065
- store.dispatch(addForm(retForm));
7066
- store.dispatch(addFormRevision(retRevision));
7075
+ const { fields, images } = await separateImageFromFields(initialRevision.fields);
7076
+ const offlineFormRevision = offline({
7077
+ ...initialRevision,
7078
+ fields,
7079
+ created_by: form.created_by,
7080
+ form: form.offline_id,
7081
+ submitted_at: form.submitted_at,
7082
+ revision: "Pending"
7083
+ });
7084
+ store.dispatch(addForm(form));
7085
+ store.dispatch(addFormRevision(offlineFormRevision));
7067
7086
  const formPromise = this.client.enqueueRequest({
7068
7087
  description: "Create form",
7069
7088
  method: HttpMethod.POST,
7070
- url,
7071
- queryParams: activeWorkspaceId ? {
7072
- workspace_id: activeWorkspaceId
7073
- } : void 0,
7089
+ url: urlPrefix,
7074
7090
  payload: {
7075
- ...offlineFormPayload,
7076
- ...assetTypeId && { asset_type: assetTypeId },
7077
- ...issueTypeId && { issue_type: issueTypeId },
7078
- initial_revision: payloadWithoutImage
7091
+ // Sending exactly what is currently needed for the endpoint
7092
+ offline_id: form.offline_id,
7093
+ initial_revision: {
7094
+ offline_id: offlineFormRevision.offline_id,
7095
+ submitted_at: offlineFormRevision.submitted_at,
7096
+ title: offlineFormRevision.title,
7097
+ description: offlineFormRevision.description,
7098
+ fields: offlineFormRevision.fields
7099
+ }
7079
7100
  },
7080
- blockers: assetTypeId ? [assetTypeId] : issueTypeId ? [issueTypeId] : [],
7081
- blocks: [offlineFormPayload.offline_id, payloadWithoutImage.offline_id]
7101
+ blockers: [ownerId],
7102
+ blocks: [form.offline_id, offlineFormRevision.offline_id]
7082
7103
  });
7083
- const attachImagesPromises = this.getAttachImagePromises(images, offlineRevisionPayload.offline_id);
7104
+ const attachImagesPromises = this.getAttachImagePromises(images, offlineFormRevision.offline_id);
7084
7105
  void formPromise.catch((e) => {
7085
- store.dispatch(deleteForm(retForm.offline_id));
7086
- store.dispatch(deleteFormRevision(retRevision.offline_id));
7106
+ store.dispatch(deleteForm(form.offline_id));
7107
+ store.dispatch(deleteFormRevision(offlineFormRevision.offline_id));
7087
7108
  throw e;
7088
7109
  });
7089
7110
  const settledPromise = Promise.all([formPromise, ...attachImagesPromises]).then(() => formPromise);
7090
- return [retForm, retRevision, formPromise, settledPromise];
7111
+ return [form, offlineFormRevision, formPromise, settledPromise];
7091
7112
  }
7092
- async addForOrganization(initialRevision, attachedTo) {
7113
+ addForOrganization(organizationId, initialRevision) {
7093
7114
  const state = this.client.store.getState();
7094
- const activeOrganizationId = state.organizationReducer.activeOrganizationId;
7095
- if (!activeOrganizationId) {
7096
- throw new Error("Cannot add forms for organization when there is no active organization.");
7097
- }
7098
- return await this.add(
7099
- state,
7115
+ const offlineForm = offline({
7116
+ favorite: false,
7117
+ created_by: state.userReducer.currentUser.id,
7118
+ submitted_at: (/* @__PURE__ */ new Date()).toISOString(),
7119
+ organization: organizationId
7120
+ });
7121
+ return this.add(
7122
+ organizationId.toString(),
7123
+ offlineForm,
7100
7124
  initialRevision,
7101
- `/forms/in-organization/${activeOrganizationId}/`,
7102
- void 0,
7103
- activeOrganizationId,
7104
- attachedTo && "assetTypeId" in attachedTo ? attachedTo.assetTypeId : void 0,
7105
- attachedTo && "issueTypeId" in attachedTo ? attachedTo.issueTypeId : void 0
7125
+ `/organizations/${organizationId}/create-form/`
7106
7126
  );
7107
7127
  }
7108
- async addForCurrentUser(initialRevision, attachedTo) {
7128
+ addForProject(projectId, initialRevision) {
7109
7129
  const state = this.client.store.getState();
7110
- const currentUser = state.userReducer.currentUser;
7111
- return await this.add(
7112
- state,
7113
- initialRevision,
7114
- "/forms/my-forms/",
7115
- currentUser.id,
7116
- void 0,
7117
- attachedTo && "assetTypeId" in attachedTo ? attachedTo.assetTypeId : void 0,
7118
- attachedTo && "issueTypeId" in attachedTo ? attachedTo.issueTypeId : void 0
7119
- );
7130
+ const offlineForm = offline({
7131
+ favorite: false,
7132
+ created_by: state.userReducer.currentUser.id,
7133
+ submitted_at: (/* @__PURE__ */ new Date()).toISOString(),
7134
+ project: projectId
7135
+ });
7136
+ return this.add(projectId.toString(), offlineForm, initialRevision, `/projects/${projectId}/create-form/`);
7137
+ }
7138
+ addForIssueType(issueTypeId, initialRevision) {
7139
+ const state = this.client.store.getState();
7140
+ const offlineForm = offline({
7141
+ favorite: false,
7142
+ created_by: state.userReducer.currentUser.id,
7143
+ submitted_at: (/* @__PURE__ */ new Date()).toISOString(),
7144
+ issue_type: issueTypeId
7145
+ });
7146
+ return this.add(issueTypeId, offlineForm, initialRevision, `/issues/types/${issueTypeId}/create-form/`);
7147
+ }
7148
+ addForAssetType(assetTypeId, initialRevision) {
7149
+ const state = this.client.store.getState();
7150
+ const offlineForm = offline({
7151
+ favorite: false,
7152
+ created_by: state.userReducer.currentUser.id,
7153
+ submitted_at: (/* @__PURE__ */ new Date()).toISOString(),
7154
+ asset_type: assetTypeId
7155
+ });
7156
+ return this.add(assetTypeId, offlineForm, initialRevision, `/assets/types/${assetTypeId}/create-form/`);
7120
7157
  }
7121
7158
  async createRevision(formId2, revision) {
7122
7159
  const offlineRevision = offline(revision);
@@ -7127,9 +7164,10 @@ var __publicField = (obj, key, value) => {
7127
7164
  throw new Error("Cannot create form revision when there is no active project.");
7128
7165
  }
7129
7166
  const currentUserId = state.userReducer.currentUser.id;
7130
- const { payloadWithoutImage, images } = await separateImageFromFields(offlineRevision);
7167
+ const { fields, images } = await separateImageFromFields(offlineRevision.fields);
7131
7168
  const fullRevision = {
7132
- ...payloadWithoutImage,
7169
+ ...offlineRevision,
7170
+ fields,
7133
7171
  created_by: currentUserId,
7134
7172
  revision: "Pending",
7135
7173
  form: formId2,
@@ -7140,9 +7178,14 @@ var __publicField = (obj, key, value) => {
7140
7178
  description: "Create form revision",
7141
7179
  method: HttpMethod.PATCH,
7142
7180
  url: `/forms/${formId2}/`,
7143
- payload: { initial_revision: payloadWithoutImage },
7144
- queryParams: {
7145
- project_id: activeProjectId.toString()
7181
+ payload: {
7182
+ initial_revision: {
7183
+ offline_id: fullRevision.offline_id,
7184
+ submitted_at: fullRevision.submitted_at,
7185
+ title: fullRevision.title,
7186
+ description: fullRevision.description,
7187
+ fields: fullRevision.fields
7188
+ }
7146
7189
  },
7147
7190
  blockers: [formId2],
7148
7191
  blocks: [offlineRevision.offline_id]
@@ -7227,16 +7270,68 @@ var __publicField = (obj, key, value) => {
7227
7270
  }
7228
7271
  async refreshStore() {
7229
7272
  const { store } = this.client;
7230
- const result = await this.client.enqueueRequest({
7231
- description: "Fetch user forms",
7273
+ const activeProjectId = store.getState().projectReducer.activeProjectId;
7274
+ if (!activeProjectId) {
7275
+ throw new Error("No active project");
7276
+ }
7277
+ const forms = [];
7278
+ const revisions = [];
7279
+ const attachments = [];
7280
+ const projectFormsResult = await this.client.enqueueRequest({
7281
+ description: "Fetch project forms",
7232
7282
  method: HttpMethod.GET,
7233
- url: `/forms/in-project/${store.getState().projectReducer.activeProjectId}/forms/`,
7234
- blockers: [],
7283
+ url: `/projects/${activeProjectId}/forms/`,
7284
+ blockers: [activeProjectId.toString()],
7285
+ blocks: []
7286
+ });
7287
+ for (const form of projectFormsResult.forms)
7288
+ forms.push(form);
7289
+ for (const revision of projectFormsResult.revisions)
7290
+ revisions.push(revision);
7291
+ for (const attachment of projectFormsResult.attachments)
7292
+ attachments.push(attachment);
7293
+ const organizationFormsResult = await this.client.enqueueRequest({
7294
+ description: "Fetch organization forms",
7295
+ method: HttpMethod.GET,
7296
+ url: `/projects/${activeProjectId}/organizations/forms/`,
7297
+ blockers: [activeProjectId.toString()],
7298
+ blocks: []
7299
+ });
7300
+ for (const form of organizationFormsResult.forms)
7301
+ forms.push(form);
7302
+ for (const revision of organizationFormsResult.revisions)
7303
+ revisions.push(revision);
7304
+ for (const attachment of organizationFormsResult.attachments)
7305
+ attachments.push(attachment);
7306
+ const assetTypeFormsResult = await this.client.enqueueRequest({
7307
+ description: "Fetch asset type forms",
7308
+ method: HttpMethod.GET,
7309
+ url: `/projects/${activeProjectId}/asset-types/forms/`,
7310
+ blockers: [activeProjectId.toString()],
7311
+ blocks: []
7312
+ });
7313
+ for (const form of assetTypeFormsResult.forms)
7314
+ forms.push(form);
7315
+ for (const revision of assetTypeFormsResult.latest_revisions)
7316
+ revisions.push(revision);
7317
+ for (const attachment of assetTypeFormsResult.attachments)
7318
+ attachments.push(attachment);
7319
+ const issueTypeFormsResult = await this.client.enqueueRequest({
7320
+ description: "Fetch issue type forms",
7321
+ method: HttpMethod.GET,
7322
+ url: `/projects/${activeProjectId}/issue-types/forms/`,
7323
+ blockers: [activeProjectId.toString()],
7235
7324
  blocks: []
7236
7325
  });
7237
- store.dispatch(setForms(Object.values(result.forms)));
7238
- store.dispatch(setFormRevisions(Object.values(result.revisions)));
7239
- store.dispatch(setFormRevisionAttachments(Object.values(result.attachments)));
7326
+ for (const form of issueTypeFormsResult.forms)
7327
+ forms.push(form);
7328
+ for (const revision of issueTypeFormsResult.latest_revisions)
7329
+ revisions.push(revision);
7330
+ for (const attachment of issueTypeFormsResult.attachments)
7331
+ attachments.push(attachment);
7332
+ store.dispatch(setForms(forms));
7333
+ store.dispatch(setFormRevisions(revisions));
7334
+ store.dispatch(setFormRevisionAttachments(attachments));
7240
7335
  }
7241
7336
  }
7242
7337
  const isArrayOfFiles = (value) => {
@@ -7339,100 +7434,120 @@ var __publicField = (obj, key, value) => {
7339
7434
  }
7340
7435
  // Note currently the bulkAdd method is specific to form submissions for assets
7341
7436
  // TODO: adapt the support bulk adding to any model type
7342
- async bulkAdd(args) {
7343
- const { formRevision, values: argsValues, assetOfflineIds } = args;
7437
+ async bulkAdd(args, batchSize) {
7344
7438
  const { store } = this.client;
7345
- const offlineSubmissions = [];
7346
- const offlineAttachments = [];
7347
- const submissionOfflineIds = [];
7348
- const submissionsPayload = [];
7349
- const attachmentsPayload = [];
7350
- const { values, files } = separateFilesFromValues(argsValues);
7439
+ const { formRevision, commonFieldValues, fieldValuesByAsset } = args;
7440
+ const allFilesRecord = {};
7441
+ const { values: fileSeperatedCommonFieldValues, files: commonFiles } = separateFilesFromValues(commonFieldValues);
7351
7442
  const submittedAt = (/* @__PURE__ */ new Date()).toISOString();
7352
- const createdBy = store.getState().userReducer.currentUser.id;
7353
- for (const assetId of assetOfflineIds) {
7354
- const submission = offline({
7355
- form_revision: formRevision,
7356
- values,
7357
- created_by: createdBy,
7358
- submitted_at: submittedAt,
7359
- asset: assetId
7360
- });
7361
- submissionOfflineIds.push(submission.offline_id);
7362
- submissionsPayload.push({ offline_id: submission.offline_id, asset_id: assetId });
7363
- offlineSubmissions.push(submission);
7364
- for (const [fieldIdentifier, fileArray] of Object.entries(files)) {
7365
- for (const file of fileArray) {
7366
- const sha1 = await hashFile(file);
7367
- await this.client.files.addCache(file, sha1);
7368
- const offlineAttachment = offline({
7369
- file_name: file.name,
7370
- file_sha1: sha1,
7371
- file: URL.createObjectURL(file),
7372
- submission: submission.offline_id,
7373
- field_identifier: fieldIdentifier
7443
+ const transactionId = uuid.v4();
7444
+ const assetIdBatches = chunkArray(Object.keys(fieldValuesByAsset), batchSize);
7445
+ const bulkAddBatches = await Promise.all(
7446
+ assetIdBatches.map(async (assetIdBatch) => {
7447
+ const batchId = uuid.v4();
7448
+ const submissionPayloads = [];
7449
+ const attachmentPayloads = [];
7450
+ const files = { ...commonFiles };
7451
+ for (const assetId of assetIdBatch) {
7452
+ const { values: fileSeperatedSubmissionSpecificValues, files: submissionSpecificFiles } = separateFilesFromValues(fieldValuesByAsset[assetId] ?? {});
7453
+ Object.assign(files, submissionSpecificFiles);
7454
+ const submissionPayload = offline({
7455
+ asset_id: assetId,
7456
+ form_data: fileSeperatedSubmissionSpecificValues
7374
7457
  });
7375
- offlineAttachments.push(offlineAttachment);
7376
- attachmentsPayload.push({
7377
- offline_id: offlineAttachment.offline_id,
7378
- submission_id: submission.offline_id,
7458
+ submissionPayloads.push(submissionPayload);
7459
+ for (const [fieldIdentifier, fileArray] of Object.entries(files)) {
7460
+ for (const file of fileArray) {
7461
+ const sha1 = await hashFile(file);
7462
+ await this.client.files.addCache(file, sha1);
7463
+ const attachmentPayload = offline({
7464
+ submission_id: submissionPayload.offline_id,
7465
+ sha1,
7466
+ name: file.name,
7467
+ field_identifier: fieldIdentifier
7468
+ });
7469
+ attachmentPayloads.push(attachmentPayload);
7470
+ }
7471
+ }
7472
+ }
7473
+ const filePaylods = [];
7474
+ for (const file of Object.values(files).flat()) {
7475
+ const sha1 = await hashFile(file);
7476
+ const filePayload = {
7379
7477
  sha1,
7380
- name: file.name,
7381
- field_identifier: fieldIdentifier
7478
+ extension: file.name.split(".").pop() || "",
7479
+ file_type: file.type,
7480
+ size: file.size
7481
+ };
7482
+ allFilesRecord[sha1] = filePayload;
7483
+ filePaylods.push(filePayload);
7484
+ }
7485
+ return {
7486
+ batchId,
7487
+ payload: {
7488
+ transaction_id: transactionId,
7489
+ form_data: fileSeperatedCommonFieldValues,
7490
+ submitted_at: submittedAt,
7491
+ submissions: submissionPayloads,
7492
+ attachments: attachmentPayloads,
7493
+ files: filePaylods
7494
+ }
7495
+ };
7496
+ })
7497
+ );
7498
+ const batchPromises = [];
7499
+ let prevBatchId = null;
7500
+ for (const batch of bulkAddBatches) {
7501
+ const { payload, batchId } = batch;
7502
+ const batchAssetIds = payload.submissions.map((x) => x.asset_id);
7503
+ const batchSubmissionOfflineIds = payload.submissions.map((x) => x.offline_id);
7504
+ const batchAttachmentsOfflineIds = payload.attachments.map((x) => x.offline_id);
7505
+ const blockers = batchAssetIds;
7506
+ if (prevBatchId)
7507
+ blockers.push(prevBatchId);
7508
+ const blocks2 = [...batchSubmissionOfflineIds, ...batchAttachmentsOfflineIds, batchId];
7509
+ const promise = this.client.enqueueRequest({
7510
+ description: "Bulk add form submissions",
7511
+ method: HttpMethod.POST,
7512
+ url: `/forms/revisions/${formRevision}/bulk-respond/`,
7513
+ payload,
7514
+ blockers,
7515
+ blocks: blocks2
7516
+ });
7517
+ void promise.then(({ presigned_urls }) => {
7518
+ for (const [sha1, presignedUrl] of Object.entries(presigned_urls)) {
7519
+ const file = allFilesRecord[sha1];
7520
+ if (!file)
7521
+ continue;
7522
+ void this.client.enqueueRequest({
7523
+ url: presignedUrl.url,
7524
+ description: "Upload file",
7525
+ method: HttpMethod.POST,
7526
+ isExternalUrl: true,
7527
+ isAuthNeeded: false,
7528
+ attachmentHash: sha1,
7529
+ blockers: [`s3-${file.sha1}.${file.extension}`],
7530
+ blocks: [sha1],
7531
+ s3url: presignedUrl
7382
7532
  });
7383
7533
  }
7384
- }
7385
- }
7386
- const filesRecord = {};
7387
- for (const file of Object.values(files).flat()) {
7388
- const sha1 = await hashFile(file);
7389
- filesRecord[sha1] = {
7390
- sha1,
7391
- extension: file.name.split(".").pop() || "",
7392
- file_type: file.type,
7393
- size: file.size
7394
- };
7395
- }
7396
- store.dispatch(addFormSubmissions(offlineSubmissions));
7397
- store.dispatch(addFormSubmissionAttachments(offlineAttachments));
7398
- const promise = this.client.enqueueRequest({
7399
- description: "Bulk add form submissions",
7400
- method: HttpMethod.POST,
7401
- url: `/forms/revisions/${formRevision}/bulk-respond/`,
7402
- payload: {
7403
- form_data: values,
7404
- submitted_at: submittedAt,
7405
- submissions: submissionsPayload,
7406
- attachments: attachmentsPayload,
7407
- files: Object.values(filesRecord)
7408
- },
7409
- blockers: assetOfflineIds,
7410
- blocks: submissionOfflineIds
7411
- });
7412
- promise.then(({ submissions, attachments, presigned_urls }) => {
7413
- store.dispatch(updateFormSubmissions(submissions));
7414
- store.dispatch(updateFormSubmissionAttachments(attachments));
7415
- for (const [sha1, presigned_url] of Object.entries(presigned_urls)) {
7416
- const file = filesRecord[sha1];
7417
- if (!file)
7418
- continue;
7419
- void this.client.enqueueRequest({
7420
- url: presigned_url.url,
7421
- description: "Upload file",
7422
- method: HttpMethod.POST,
7423
- isExternalUrl: true,
7424
- isAuthNeeded: false,
7425
- attachmentHash: sha1,
7426
- blockers: [`s3-${file.sha1}.${file.extension}`],
7427
- blocks: [sha1],
7428
- s3url: presigned_url
7429
- });
7430
- }
7431
- }).catch(() => {
7432
- store.dispatch(deleteFormSubmissions(submissionOfflineIds));
7433
- store.dispatch(deleteFormSubmissionAttachments(offlineAttachments.map((x) => x.offline_id)));
7534
+ });
7535
+ prevBatchId = batchId;
7536
+ batchPromises.push(promise);
7537
+ }
7538
+ void Promise.all(batchPromises).then((results) => {
7539
+ const createdSubmissions = [];
7540
+ const createdAttachments = [];
7541
+ for (const result of results) {
7542
+ for (const createdSubmission of result.submissions)
7543
+ createdSubmissions.push(createdSubmission);
7544
+ for (const createdAttachment of result.attachments)
7545
+ createdAttachments.push(createdAttachment);
7546
+ }
7547
+ store.dispatch(addFormSubmissions(createdSubmissions));
7548
+ store.dispatch(addFormSubmissionAttachments(createdAttachments));
7434
7549
  });
7435
- return [offlineSubmissions, promise.then(({ submissions }) => submissions)];
7550
+ return batchPromises;
7436
7551
  }
7437
7552
  update(submission) {
7438
7553
  const { store } = this.client;
@@ -8642,8 +8757,8 @@ var __publicField = (obj, key, value) => {
8642
8757
  }
8643
8758
  const makeClient = (apiUrl, store) => new OvermapSDK(apiUrl, store);
8644
8759
  const SDKContext = React.createContext({});
8645
- const SDKProvider = React.memo(({ children, apiUrl, store }) => {
8646
- const client = React.useMemo(() => makeClient(apiUrl, store), [apiUrl, store]);
8760
+ const SDKProvider = React.memo(({ children, API_URL, store }) => {
8761
+ const client = React.useMemo(() => makeClient(API_URL, store), [API_URL, store]);
8647
8762
  React.useEffect(() => {
8648
8763
  setClientStore(store);
8649
8764
  }, [store]);
@@ -8654,9 +8769,11 @@ var __publicField = (obj, key, value) => {
8654
8769
  return React.useContext(SDKContext);
8655
8770
  };
8656
8771
  const OvermapContext = React.createContext(null);
8772
+ const PRODUCTION_URL = "https://api.wordn.io";
8773
+ const STAGING_URL = "https://test-api.hemora.ca";
8657
8774
  const OvermapProvider = (props) => {
8658
- const { children, disableDefaultTheme = false, store, apiUrl } = props;
8659
- let ret = /* @__PURE__ */ jsxRuntime.jsx(blocks.AlertDialogProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(blocks.ToastProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(SDKProvider, { store, apiUrl, children }) }) });
8775
+ const { children, production, disableDefaultTheme = false, store } = props;
8776
+ let ret = /* @__PURE__ */ jsxRuntime.jsx(blocks.AlertDialogProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(blocks.ToastProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(SDKProvider, { API_URL: production ? PRODUCTION_URL : STAGING_URL, store, children }) }) });
8660
8777
  if (!disableDefaultTheme) {
8661
8778
  ret = /* @__PURE__ */ jsxRuntime.jsx(blocks.DefaultTheme, { children: ret });
8662
8779
  }
@@ -8785,6 +8902,12 @@ var __publicField = (obj, key, value) => {
8785
8902
  getFormValidators() {
8786
8903
  return [...this.formValidators];
8787
8904
  }
8905
+ encodeValueToJson(value) {
8906
+ return JSON.stringify(value);
8907
+ }
8908
+ decodeJsonToValue(json) {
8909
+ return JSON.parse(json);
8910
+ }
8788
8911
  }
8789
8912
  __publicField(BaseField, "fieldTypeName");
8790
8913
  __publicField(BaseField, "fieldTypeDescription");
@@ -13038,10 +13161,7 @@ var __publicField = (obj, key, value) => {
13038
13161
  helpText = showInputOnly ? null : helpText;
13039
13162
  label = showInputOnly ? "" : label;
13040
13163
  const color = blocks.useSeverityColor(severity);
13041
- const value = React.useMemo(
13042
- () => Array.isArray(fieldProps.value) ? fieldProps.value : [],
13043
- [fieldProps.value]
13044
- );
13164
+ const value = React.useMemo(() => Array.isArray(fieldProps.value) ? fieldProps.value : [], [fieldProps.value]);
13045
13165
  const { onChange, onBlur } = fieldProps;
13046
13166
  const droppableId = `${inputId}-droppable`;
13047
13167
  const { disabled } = rest;
@@ -13058,7 +13178,7 @@ var __publicField = (obj, key, value) => {
13058
13178
  );
13059
13179
  const handleChange = React.useCallback(
13060
13180
  (e) => {
13061
- if (value.findIndex((option) => option.value === e.target.value.trim()) >= 0) {
13181
+ if (value.findIndex((option) => option === e.target.value.trim()) >= 0) {
13062
13182
  setInternalError("All options must be unique");
13063
13183
  } else if (!e.target.value) {
13064
13184
  setInternalError("Option cannot be empty");
@@ -13077,7 +13197,7 @@ var __publicField = (obj, key, value) => {
13077
13197
  return;
13078
13198
  }
13079
13199
  const trimmedValue = intermediateValue.trim();
13080
- setValueAndTouched([...value, { value: trimmedValue, label: trimmedValue }]);
13200
+ setValueAndTouched([...value, trimmedValue]);
13081
13201
  setIntermediateValue("");
13082
13202
  }, [intermediateValue, internalError, setValueAndTouched, value]);
13083
13203
  const handleKeyDown = React.useCallback(
@@ -13147,7 +13267,7 @@ var __publicField = (obj, key, value) => {
13147
13267
  value.map((option, index2) => /* @__PURE__ */ jsxRuntime.jsx(
13148
13268
  dnd.Draggable,
13149
13269
  {
13150
- draggableId: `${option.value}-draggable`,
13270
+ draggableId: `${option}-draggable`,
13151
13271
  index: index2,
13152
13272
  isDragDisabled: disabled,
13153
13273
  children: ({ draggableProps, dragHandleProps, innerRef }) => /* @__PURE__ */ jsxRuntime.jsx(
@@ -13162,7 +13282,10 @@ var __publicField = (obj, key, value) => {
13162
13282
  mb: "1",
13163
13283
  asChild: true,
13164
13284
  children: /* @__PURE__ */ jsxRuntime.jsxs(blocks.Badge, { color: "gray", size: "2", children: [
13165
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: option.label }),
13285
+ /* @__PURE__ */ jsxRuntime.jsx("span", {
13286
+ // TODO: remove this, its just a saftey check for old compatibility of what was acceptable as a value for multi string
13287
+ children: typeof option === "object" && "label" in option ? option.label : option
13288
+ }),
13166
13289
  /* @__PURE__ */ jsxRuntime.jsx(
13167
13290
  blocks.IconButton,
13168
13291
  {
@@ -13182,7 +13305,7 @@ var __publicField = (obj, key, value) => {
13182
13305
  }
13183
13306
  )
13184
13307
  },
13185
- option.value
13308
+ option
13186
13309
  )),
13187
13310
  droppableProvided.placeholder
13188
13311
  ] }) })
@@ -14857,6 +14980,44 @@ var __publicField = (obj, key, value) => {
14857
14980
  meta: { readonly }
14858
14981
  };
14859
14982
  }
14983
+ function flattenFields(schema) {
14984
+ const allFields = [];
14985
+ for (const field of schema.fields) {
14986
+ if (field instanceof FieldSection) {
14987
+ for (const subField of field.fields) {
14988
+ allFields.push(subField);
14989
+ }
14990
+ } else {
14991
+ if (!(field instanceof BaseField)) {
14992
+ throw new Error(`Invalid field type: ${field.type}`);
14993
+ }
14994
+ allFields.push(field);
14995
+ }
14996
+ }
14997
+ return allFields;
14998
+ }
14999
+ function decodeFormValues(schema, values) {
15000
+ const allFields = flattenFields(schema);
15001
+ const result = {};
15002
+ for (const field of allFields) {
15003
+ const value = values[field.identifier] ?? null;
15004
+ if (value !== null) {
15005
+ result[field.identifier] = field.decodeJsonToValue(value);
15006
+ } else {
15007
+ result[field.identifier] = value;
15008
+ }
15009
+ }
15010
+ return result;
15011
+ }
15012
+ function encodeFormValues(schema, values) {
15013
+ const allFields = flattenFields(schema);
15014
+ const result = {};
15015
+ for (const field of allFields) {
15016
+ const value = values[field.identifier];
15017
+ result[field.identifier] = field.encodeValueToJson(value);
15018
+ }
15019
+ return result;
15020
+ }
14860
15021
  function valueIsFile(v) {
14861
15022
  return Array.isArray(v) && v.some((v2) => v2 instanceof File || v2 instanceof Promise);
14862
15023
  }
@@ -15233,7 +15394,6 @@ var __publicField = (obj, key, value) => {
15233
15394
  regularIcon
15234
15395
  };
15235
15396
  const orgOptionPrefix = "organization:";
15236
- const userOptionPrefix = "user:";
15237
15397
  const FormBrowser = React.memo(
15238
15398
  React.forwardRef((props, ref) => {
15239
15399
  const { maxResults = 20, ...entryProps } = props;
@@ -15244,9 +15404,7 @@ var __publicField = (obj, key, value) => {
15244
15404
  const ret = { maxResults, searchTerm: filter };
15245
15405
  if (ownerFilter) {
15246
15406
  if (ownerFilter.startsWith(orgOptionPrefix)) {
15247
- ret.owner_organization = parseInt(ownerFilter.slice(orgOptionPrefix.length));
15248
- } else if (ownerFilter.startsWith(userOptionPrefix)) {
15249
- ret.owner_user = parseInt(ownerFilter.slice(userOptionPrefix.length));
15407
+ ret.organization = parseInt(ownerFilter.slice(orgOptionPrefix.length));
15250
15408
  }
15251
15409
  }
15252
15410
  return ret;
@@ -15271,14 +15429,10 @@ var __publicField = (obj, key, value) => {
15271
15429
  const state = sdk.store.getState();
15272
15430
  const accumulator = {};
15273
15431
  for (const form of attachableUserFormMapping) {
15274
- const organization = selectOrganization(form.owner_organization || -1)(state);
15432
+ const organization = selectOrganization(form.organization || -1)(state);
15275
15433
  if (organization) {
15276
15434
  accumulator[`${orgOptionPrefix}${organization.id}`] = organization.name;
15277
15435
  }
15278
- const user = selectUser(form.owner_user || -1)(state);
15279
- if (user) {
15280
- accumulator[`${userOptionPrefix}${user.id}`] = user.username;
15281
- }
15282
15436
  }
15283
15437
  return Object.entries(accumulator).map(([value, label]) => ({ itemContent: label, value }));
15284
15438
  }, [sdk.store, attachableUserFormMapping]);
@@ -15320,11 +15474,7 @@ var __publicField = (obj, key, value) => {
15320
15474
  const FormBrowserEntry = (props) => {
15321
15475
  var _a2;
15322
15476
  const { form, onSelectForm, isFavoriteEditable, handleToggleFavorite } = props;
15323
- const ownerOrganization = (_a2 = useAppSelector(selectOrganization(form.owner_organization || -1))) == null ? void 0 : _a2.name;
15324
- const ownerUser = useAppSelector(selectUser(form.owner_user || -1));
15325
- const currentUserId = useAppSelector(selectCurrentUser).id;
15326
- const ownedByCurrentUser = !!ownerUser && ownerUser.id === currentUserId;
15327
- const owner = ownerOrganization ?? (ownedByCurrentUser ? "You" : ownerUser == null ? void 0 : ownerUser.username) ?? "Unknown";
15477
+ const ownerOrganization = (_a2 = useAppSelector(selectOrganization(form.organization || -1))) == null ? void 0 : _a2.name;
15328
15478
  const handleFavoriteClick = React.useCallback(
15329
15479
  (e) => {
15330
15480
  e.stopPropagation();
@@ -15355,10 +15505,10 @@ var __publicField = (obj, key, value) => {
15355
15505
  /* @__PURE__ */ jsxRuntime.jsx(blocks.Text, { noWrap: true, children: form.latestRevision.title }),
15356
15506
  form.latestRevision.description && /* @__PURE__ */ jsxRuntime.jsx(blocks.RiIcon, { icon: "RiQuestionLine" })
15357
15507
  ] }),
15358
- owner && /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { align: "center", gap: "2", children: [
15508
+ ownerOrganization && /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { align: "center", gap: "2", children: [
15359
15509
  /* @__PURE__ */ jsxRuntime.jsx(blocks.RiIcon, { icon: "RiUserLine" }),
15360
15510
  " ",
15361
- owner
15511
+ ownerOrganization
15362
15512
  ] })
15363
15513
  ] })
15364
15514
  }
@@ -16638,6 +16788,7 @@ var __publicField = (obj, key, value) => {
16638
16788
  StringInput,
16639
16789
  TextField,
16640
16790
  TextInput,
16791
+ decodeFormValues,
16641
16792
  deserialize,
16642
16793
  deserializeField,
16643
16794
  emptyBaseField,
@@ -16650,11 +16801,15 @@ var __publicField = (obj, key, value) => {
16650
16801
  emptySelectField,
16651
16802
  emptyStringField,
16652
16803
  emptyTextField,
16804
+ encodeFormValues,
16805
+ flattenFields,
16653
16806
  formRevisionToSchema,
16807
+ initialFormValues,
16654
16808
  isConditionMet,
16655
16809
  useFieldInput,
16656
16810
  useFieldInputs,
16657
16811
  useFormikInput,
16812
+ validateForm,
16658
16813
  valueIsFile
16659
16814
  }, Symbol.toStringTag, { value: "Module" }));
16660
16815
  exports2.APIError = APIError;
@@ -16845,6 +17000,7 @@ var __publicField = (obj, key, value) => {
16845
17000
  exports2.coordinatesToUrlText = coordinatesToUrlText;
16846
17001
  exports2.createOfflineAction = createOfflineAction;
16847
17002
  exports2.createPointMarker = createPointMarker;
17003
+ exports2.decodeFormValues = decodeFormValues;
16848
17004
  exports2.defaultBadgeColor = defaultBadgeColor;
16849
17005
  exports2.defaultStore = defaultStore;
16850
17006
  exports2.deleteAssetType = deleteAssetType;
@@ -16880,6 +17036,7 @@ var __publicField = (obj, key, value) => {
16880
17036
  exports2.emptySelectField = emptySelectField;
16881
17037
  exports2.emptyStringField = emptyStringField;
16882
17038
  exports2.emptyTextField = emptyTextField;
17039
+ exports2.encodeFormValues = encodeFormValues;
16883
17040
  exports2.enqueue = enqueue;
16884
17041
  exports2.enqueueRequest = enqueueRequest;
16885
17042
  exports2.errorColor = errorColor;
@@ -16887,6 +17044,7 @@ var __publicField = (obj, key, value) => {
16887
17044
  exports2.fileReducer = fileReducer;
16888
17045
  exports2.fileSlice = fileSlice;
16889
17046
  exports2.fileToBlob = fileToBlob;
17047
+ exports2.flattenFields = flattenFields;
16890
17048
  exports2.flipCoordinates = flipCoordinates;
16891
17049
  exports2.formReducer = formReducer;
16892
17050
  exports2.formRevisionReducer = formRevisionReducer;
@@ -16910,6 +17068,7 @@ var __publicField = (obj, key, value) => {
16910
17068
  exports2.hashFile = hashFile;
16911
17069
  exports2.hideAllCategories = hideAllCategories;
16912
17070
  exports2.hideCategory = hideCategory;
17071
+ exports2.initialFormValues = initialFormValues;
16913
17072
  exports2.isConditionMet = isConditionMet;
16914
17073
  exports2.isToday = isToday;
16915
17074
  exports2.issueReducer = issueReducer;
@@ -16963,6 +17122,7 @@ var __publicField = (obj, key, value) => {
16963
17122
  exports2.removeAssetAttachments = removeAssetAttachments;
16964
17123
  exports2.removeAssetTypeAttachment = removeAssetTypeAttachment;
16965
17124
  exports2.removeAssetTypeAttachments = removeAssetTypeAttachments;
17125
+ exports2.removeAssets = removeAssets;
16966
17126
  exports2.removeAttachmentsOfIssue = removeAttachmentsOfIssue;
16967
17127
  exports2.removeCategory = removeCategory;
16968
17128
  exports2.removeColor = removeColor;
@@ -17280,6 +17440,7 @@ var __publicField = (obj, key, value) => {
17280
17440
  exports2.updateAssetAttachments = updateAssetAttachments;
17281
17441
  exports2.updateAssetTypeAttachment = updateAssetTypeAttachment;
17282
17442
  exports2.updateAssetTypeAttachments = updateAssetTypeAttachments;
17443
+ exports2.updateAssets = updateAssets;
17283
17444
  exports2.updateConversation = updateConversation;
17284
17445
  exports2.updateDocumentAttachment = updateDocumentAttachment;
17285
17446
  exports2.updateDocumentAttachments = updateDocumentAttachments;
@@ -17310,6 +17471,7 @@ var __publicField = (obj, key, value) => {
17310
17471
  exports2.useSDK = useSDK;
17311
17472
  exports2.userReducer = userReducer;
17312
17473
  exports2.userSlice = userSlice;
17474
+ exports2.validateForm = validateForm;
17313
17475
  exports2.valueIsFile = valueIsFile;
17314
17476
  exports2.warningColor = warningColor;
17315
17477
  exports2.workspaceReducer = workspaceReducer;