@overmap-ai/core 1.0.50-bulk-form-submission.3 → 1.0.50-document-attachments.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.
@@ -631,15 +631,15 @@ const wrapMigration = (migrator) => (state) => {
631
631
  };
632
632
  const migrations = [initialVersioning, signOut, signOut, createOutboxState];
633
633
  const manifest = Object.fromEntries(migrations.map((migration2, i) => [i, wrapMigration(migration2)]));
634
- const initialState$p = {
634
+ const initialState$n = {
635
635
  accessToken: "",
636
636
  refreshToken: "",
637
637
  isLoggedIn: false
638
638
  };
639
639
  const authSlice = createSlice({
640
640
  name: "auth",
641
- initialState: initialState$p,
642
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$p)),
641
+ initialState: initialState$n,
642
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$n)),
643
643
  reducers: {
644
644
  setTokens: (state, action) => {
645
645
  state.accessToken = action.payload.accessToken;
@@ -804,19 +804,6 @@ function downloadInMemoryFile(filename, text) {
804
804
  element.click();
805
805
  document.body.removeChild(element);
806
806
  }
807
- const constructUploadedFilePayloads = async (files) => {
808
- const filePayloads = {};
809
- for (const file of files) {
810
- const sha1 = await hashFile(file);
811
- filePayloads[sha1] = {
812
- sha1,
813
- extension: file.name.split(".").pop() || "",
814
- file_type: file.type,
815
- size: file.size
816
- };
817
- }
818
- return Object.values(filePayloads);
819
- };
820
807
  const fileToBlob = async (dataUrl) => {
821
808
  return (await fetch(dataUrl)).blob();
822
809
  };
@@ -1383,7 +1370,7 @@ const getLocalRelativeDateString = memoize((date, min, max) => {
1383
1370
  return getLocalDateString(date);
1384
1371
  return relative.format(days, "days");
1385
1372
  });
1386
- const initialState$o = {
1373
+ const initialState$m = {
1387
1374
  categories: {},
1388
1375
  usedCategoryColors: [],
1389
1376
  categoryVisibility: {
@@ -1393,8 +1380,8 @@ const initialState$o = {
1393
1380
  };
1394
1381
  const categorySlice = createSlice({
1395
1382
  name: "categories",
1396
- initialState: initialState$o,
1397
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$o)),
1383
+ initialState: initialState$m,
1384
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$m)),
1398
1385
  reducers: {
1399
1386
  setCategories: (state, action) => {
1400
1387
  if (!Array.isArray(action.payload))
@@ -1563,14 +1550,14 @@ function removeAttachments(state, action) {
1563
1550
  delete state.attachments[attachmentId];
1564
1551
  }
1565
1552
  }
1566
- const initialState$n = {
1553
+ const initialState$l = {
1567
1554
  components: {},
1568
1555
  attachments: {}
1569
1556
  };
1570
1557
  const componentSlice = createSlice({
1571
1558
  name: "components",
1572
- initialState: initialState$n,
1573
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$n)),
1559
+ initialState: initialState$l,
1560
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$l)),
1574
1561
  reducers: {
1575
1562
  addComponent: (state, action) => {
1576
1563
  state.components[action.payload.offline_id] = action.payload;
@@ -1683,9 +1670,6 @@ const selectAllComponentAttachments = createSelector(
1683
1670
  [selectComponentAttachmentMapping],
1684
1671
  (mapping) => Object.values(mapping)
1685
1672
  );
1686
- const selectComponentAttachment = (attachmentId) => (state) => {
1687
- return state.componentReducer.attachments[attachmentId];
1688
- };
1689
1673
  const selectAttachmentsOfComponent = restructureCreateSelectorWithArgs(
1690
1674
  createSelector(
1691
1675
  [selectAllComponentAttachments, (_state, componentId) => componentId],
@@ -1726,13 +1710,13 @@ const {
1726
1710
  removeAllComponentsOfType
1727
1711
  } = componentSlice.actions;
1728
1712
  const componentReducer = componentSlice.reducer;
1729
- const initialState$m = {
1713
+ const initialState$k = {
1730
1714
  completionsByComponentId: {}
1731
1715
  };
1732
1716
  const componentStageCompletionSlice = createSlice({
1733
1717
  name: "componentStageCompletions",
1734
- initialState: initialState$m,
1735
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$m)),
1718
+ initialState: initialState$k,
1719
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$k)),
1736
1720
  reducers: {
1737
1721
  addStageCompletion: (state, action) => {
1738
1722
  let stageToCompletionDateMapping = state.completionsByComponentId[action.payload.component];
@@ -1783,13 +1767,13 @@ const selectCompletedStageIdsForComponent = (component) => (state) => {
1783
1767
  return Object.keys(state.componentStageCompletionReducer.completionsByComponentId[component.offline_id] ?? {});
1784
1768
  };
1785
1769
  const componentStageCompletionReducer = componentStageCompletionSlice.reducer;
1786
- const initialState$l = {
1770
+ const initialState$j = {
1787
1771
  stages: {}
1788
1772
  };
1789
1773
  const componentStageSlice = createSlice({
1790
1774
  name: "componentStages",
1791
- initialState: initialState$l,
1792
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$l)),
1775
+ initialState: initialState$j,
1776
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$j)),
1793
1777
  reducers: {
1794
1778
  addStages: (state, action) => {
1795
1779
  Object.assign(state.stages, toOfflineIdRecord(action.payload));
@@ -1899,15 +1883,15 @@ const selectStageFormIdsFromStageIds = restructureCreateSelectorWithArgs(
1899
1883
  );
1900
1884
  const { addStages, updateStages, removeStages, linkStageToForm, unlinkStageToForm } = componentStageSlice.actions;
1901
1885
  const componentStageReducer = componentStageSlice.reducer;
1902
- const initialState$k = {
1886
+ const initialState$i = {
1903
1887
  componentTypes: {},
1904
1888
  hiddenComponentTypeIds: {},
1905
1889
  attachments: {}
1906
1890
  };
1907
1891
  const componentTypeSlice = createSlice({
1908
1892
  name: "componentTypes",
1909
- initialState: initialState$k,
1910
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$k)),
1893
+ initialState: initialState$i,
1894
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$i)),
1911
1895
  reducers: {
1912
1896
  addComponentType: (state, action) => {
1913
1897
  state.componentTypes[action.payload.offline_id] = action.payload;
@@ -1975,9 +1959,6 @@ const selectAllComponentTypeAttachments = createSelector(
1975
1959
  [selectComponentTypeAttachmentMapping],
1976
1960
  (mapping) => Object.values(mapping)
1977
1961
  );
1978
- const selectComponentTypeAttachment = (attachmentId) => (state) => {
1979
- return state.componentTypeReducer.attachments[attachmentId];
1980
- };
1981
1962
  const selectAttachmentsOfComponentType = restructureCreateSelectorWithArgs(
1982
1963
  createSelector(
1983
1964
  [selectAllComponentTypeAttachments, (_state, componentTypeId) => componentTypeId],
@@ -2018,13 +1999,13 @@ const {
2018
1999
  deleteComponentType
2019
2000
  } = componentTypeSlice.actions;
2020
2001
  const componentTypeReducer = componentTypeSlice.reducer;
2021
- const initialState$j = {
2002
+ const initialState$h = {
2022
2003
  workspaces: {},
2023
2004
  activeWorkspaceId: null
2024
2005
  };
2025
2006
  const workspaceSlice = createSlice({
2026
2007
  name: "workspace",
2027
- initialState: initialState$j,
2008
+ initialState: initialState$h,
2028
2009
  // The `reducers` field lets us define reducers and generate associated actions
2029
2010
  reducers: {
2030
2011
  setWorkspaces: (state, action) => {
@@ -2081,7 +2062,7 @@ const selectPermittedWorkspaceIds = createSelector(
2081
2062
  );
2082
2063
  const workspaceReducer = workspaceSlice.reducer;
2083
2064
  const maxRecentIssues = 10;
2084
- const initialState$i = {
2065
+ const initialState$g = {
2085
2066
  issues: {},
2086
2067
  attachments: {},
2087
2068
  comments: {},
@@ -2093,9 +2074,9 @@ const initialState$i = {
2093
2074
  };
2094
2075
  const issueSlice = createSlice({
2095
2076
  name: "issues",
2096
- initialState: initialState$i,
2077
+ initialState: initialState$g,
2097
2078
  extraReducers: (builder) => builder.addCase("RESET", (state) => {
2098
- Object.assign(state, initialState$i);
2079
+ Object.assign(state, initialState$g);
2099
2080
  }),
2100
2081
  reducers: {
2101
2082
  setIssues: (state, action) => {
@@ -2372,9 +2353,6 @@ const selectAttachmentsOfIssue = restructureCreateSelectorWithArgs(
2372
2353
  }
2373
2354
  )
2374
2355
  );
2375
- const selectIssueAttachment = (attachmentId) => (root) => {
2376
- return root.issueReducer.attachments[attachmentId];
2377
- };
2378
2356
  const selectAttachmentsOfIssueByType = restructureCreateSelectorWithArgs(
2379
2357
  createSelector(
2380
2358
  [selectIssueAttachments, (_state, issueId) => issueId],
@@ -2503,15 +2481,15 @@ const selectRecentIssuesAsSearchResults = createSelector(
2503
2481
  }
2504
2482
  );
2505
2483
  const issueReducer = issueSlice.reducer;
2506
- const initialState$h = {
2484
+ const initialState$f = {
2507
2485
  s3Urls: {}
2508
2486
  };
2509
2487
  const msPerHour = 1e3 * 60 * 60;
2510
2488
  const msPerWeek = msPerHour * 24 * 7;
2511
2489
  const fileSlice = createSlice({
2512
2490
  name: "file",
2513
- initialState: initialState$h,
2514
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$h)),
2491
+ initialState: initialState$f,
2492
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$f)),
2515
2493
  reducers: {
2516
2494
  setUploadUrl: (state, action) => {
2517
2495
  const { url, fields, sha1 } = action.payload;
@@ -2538,7 +2516,7 @@ const selectUploadUrl = (sha1) => (state) => {
2538
2516
  return url;
2539
2517
  };
2540
2518
  const fileReducer = fileSlice.reducer;
2541
- const initialState$g = {
2519
+ const initialState$e = {
2542
2520
  // TODO: Change first MapStyle.SATELLITE to MaptStyle.None when project creation map is fixed
2543
2521
  mapStyle: MapStyle.SATELLITE,
2544
2522
  showTooltips: false,
@@ -2546,8 +2524,8 @@ const initialState$g = {
2546
2524
  };
2547
2525
  const mapSlice = createSlice({
2548
2526
  name: "map",
2549
- initialState: initialState$g,
2550
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$g)),
2527
+ initialState: initialState$e,
2528
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$e)),
2551
2529
  reducers: {
2552
2530
  setMapStyle: (state, action) => {
2553
2531
  state.mapStyle = action.payload;
@@ -2616,7 +2594,7 @@ var LicenseStatus = /* @__PURE__ */ ((LicenseStatus2) => {
2616
2594
  LicenseStatus2[LicenseStatus2["PAST_DUE"] = 8] = "PAST_DUE";
2617
2595
  return LicenseStatus2;
2618
2596
  })(LicenseStatus || {});
2619
- const initialState$f = {
2597
+ const initialState$d = {
2620
2598
  users: {},
2621
2599
  currentUser: {
2622
2600
  id: 0,
@@ -2627,8 +2605,8 @@ const initialState$f = {
2627
2605
  };
2628
2606
  const userSlice = createSlice({
2629
2607
  name: "users",
2630
- initialState: initialState$f,
2631
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$f)),
2608
+ initialState: initialState$d,
2609
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$d)),
2632
2610
  reducers: {
2633
2611
  setUsers: (state, action) => {
2634
2612
  const usersMapping = {};
@@ -2690,13 +2668,13 @@ const selectUser = (userId) => (state) => {
2690
2668
  const selectUsersAsMapping = (state) => state.userReducer.users;
2691
2669
  const selectFavouriteProjects = (state) => state.userReducer.currentUser.profile.favourite_project_ids;
2692
2670
  const userReducer = userSlice.reducer;
2693
- const initialState$e = {
2671
+ const initialState$c = {
2694
2672
  organizationAccesses: {}
2695
2673
  };
2696
2674
  const organizationAccessSlice = createSlice({
2697
2675
  name: "organizationAccess",
2698
- initialState: initialState$e,
2699
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$e)),
2676
+ initialState: initialState$c,
2677
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$c)),
2700
2678
  reducers: {
2701
2679
  setOrganizationAccesses: (state, action) => {
2702
2680
  if (!Array.isArray(action.payload))
@@ -2759,13 +2737,13 @@ const selectOrganizationAccessUserMapping = (state) => {
2759
2737
  return organizationAccesses;
2760
2738
  };
2761
2739
  const organizationAccessReducer = organizationAccessSlice.reducer;
2762
- const initialState$d = {
2740
+ const initialState$b = {
2763
2741
  licenses: {}
2764
2742
  };
2765
2743
  const licenseSlice = createSlice({
2766
2744
  name: "license",
2767
- initialState: initialState$d,
2768
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$d)),
2745
+ initialState: initialState$b,
2746
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$b)),
2769
2747
  reducers: {
2770
2748
  setLicenses: (state, action) => {
2771
2749
  if (!Array.isArray(action.payload))
@@ -2810,13 +2788,13 @@ const selectLicensesForProjectsMapping = createSelector(
2810
2788
  (licenses) => Object.values(licenses).filter((license) => license.project).reduce((accum, license) => ({ ...accum, [license.project]: license }), {})
2811
2789
  );
2812
2790
  const licenseReducer = licenseSlice.reducer;
2813
- const initialState$c = {
2791
+ const initialState$a = {
2814
2792
  projectAccesses: {}
2815
2793
  };
2816
2794
  const projectAccessSlice = createSlice({
2817
2795
  name: "projectAccess",
2818
- initialState: initialState$c,
2819
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$c)),
2796
+ initialState: initialState$a,
2797
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$a)),
2820
2798
  reducers: {
2821
2799
  setProjectAccesses: (state, action) => {
2822
2800
  if (!Array.isArray(action.payload))
@@ -2884,7 +2862,7 @@ const selectProjectAccessUserMapping = (state) => {
2884
2862
  return projectAccesses;
2885
2863
  };
2886
2864
  const projectAccessReducer = projectAccessSlice.reducer;
2887
- const initialState$b = {
2865
+ const initialState$9 = {
2888
2866
  projects: {},
2889
2867
  activeProjectId: null,
2890
2868
  recentProjectIds: [],
@@ -2894,7 +2872,7 @@ const initialState$b = {
2894
2872
  };
2895
2873
  const projectSlice = createSlice({
2896
2874
  name: "projects",
2897
- initialState: initialState$b,
2875
+ initialState: initialState$9,
2898
2876
  reducers: {
2899
2877
  setProjects: (state, action) => {
2900
2878
  const projectsMap = {};
@@ -3081,14 +3059,14 @@ const selectAttachmentsOfProjectByType = restructureCreateSelectorWithArgs(
3081
3059
  }
3082
3060
  )
3083
3061
  );
3084
- const initialState$a = {
3062
+ const initialState$8 = {
3085
3063
  organizations: {},
3086
3064
  activeOrganizationId: null
3087
3065
  };
3088
3066
  const organizationSlice = createSlice({
3089
3067
  name: "organizations",
3090
- initialState: initialState$a,
3091
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$a)),
3068
+ initialState: initialState$8,
3069
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$8)),
3092
3070
  reducers: {
3093
3071
  setOrganizations: (state, action) => {
3094
3072
  for (const org of action.payload) {
@@ -3207,14 +3185,14 @@ const createOfflineAction = (request2, baseUrl) => {
3207
3185
  }
3208
3186
  };
3209
3187
  };
3210
- const initialState$9 = {
3188
+ const initialState$7 = {
3211
3189
  deletedRequests: [],
3212
3190
  latestRetryTime: 0
3213
3191
  };
3214
3192
  const outboxSlice = createSlice({
3215
3193
  name: "outbox",
3216
- initialState: initialState$9,
3217
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$9)),
3194
+ initialState: initialState$7,
3195
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$7)),
3218
3196
  reducers: {
3219
3197
  // enqueueActions is a reducer that does nothing but enqueue API request to the Redux Offline outbox
3220
3198
  // Whenever an issue is being created, a reducer addIssue() is responsible for adding it to the offline store
@@ -3246,7 +3224,7 @@ const selectDeletedRequests = (state) => state.outboxReducer.deletedRequests;
3246
3224
  const selectLatestRetryTime = (state) => state.outboxReducer.latestRetryTime;
3247
3225
  const { enqueueRequest, markForDeletion, markAsDeleted, _setLatestRetryTime } = outboxSlice.actions;
3248
3226
  const outboxReducer = outboxSlice.reducer;
3249
- const initialState$8 = {
3227
+ const initialState$6 = {
3250
3228
  projectFiles: {},
3251
3229
  activeProjectFileId: null,
3252
3230
  isImportingProjectFile: false,
@@ -3254,8 +3232,8 @@ const initialState$8 = {
3254
3232
  };
3255
3233
  const projectFileSlice = createSlice({
3256
3234
  name: "projectFiles",
3257
- initialState: initialState$8,
3258
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$8)),
3235
+ initialState: initialState$6,
3236
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$6)),
3259
3237
  reducers: {
3260
3238
  addOrReplaceProjectFiles: (state, action) => {
3261
3239
  for (let fileObj of action.payload) {
@@ -3356,12 +3334,12 @@ const selectProjectFiles = createSelector(
3356
3334
  const selectActiveProjectFileId = (state) => state.projectFileReducer.activeProjectFileId;
3357
3335
  const selectIsImportingProjectFile = (state) => state.projectFileReducer.isImportingProjectFile;
3358
3336
  const projectFileReducer = projectFileSlice.reducer;
3359
- const initialState$7 = {
3337
+ const initialState$5 = {
3360
3338
  isRehydrated: false
3361
3339
  };
3362
3340
  const rehydratedSlice = createSlice({
3363
3341
  name: "rehydrated",
3364
- initialState: initialState$7,
3342
+ initialState: initialState$5,
3365
3343
  // The `reducers` field lets us define reducers and generate associated actions
3366
3344
  reducers: {
3367
3345
  setRehydrated: (state, action) => {
@@ -3371,7 +3349,7 @@ const rehydratedSlice = createSlice({
3371
3349
  });
3372
3350
  const selectRehydrated = (state) => state.rehydratedReducer.isRehydrated;
3373
3351
  const rehydratedReducer = rehydratedSlice.reducer;
3374
- const initialState$6 = {
3352
+ const initialState$4 = {
3375
3353
  useIssueTemplate: false,
3376
3354
  placementMode: false,
3377
3355
  enableClustering: false,
@@ -3388,8 +3366,8 @@ const initialState$6 = {
3388
3366
  };
3389
3367
  const settingSlice = createSlice({
3390
3368
  name: "settings",
3391
- initialState: initialState$6,
3392
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$6)),
3369
+ initialState: initialState$4,
3370
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$4)),
3393
3371
  reducers: {
3394
3372
  setEnableDuplicateIssues: (state, action) => {
3395
3373
  state.useIssueTemplate = action.payload;
@@ -3435,248 +3413,146 @@ const selectAppearance = (state) => state.settingReducer.appearance;
3435
3413
  const settingReducer = settingSlice.reducer;
3436
3414
  const selectIsFetchingInitialData = (state) => state.settingReducer.isFetchingInitialData;
3437
3415
  const selectIsLoading = (state) => state.settingReducer.isLoading;
3438
- const LATEST_FORM_REVISION_CACHE = {};
3439
- function considerCachingFormRevision(formRevision, formId2, preferPending = false) {
3416
+ const LATEST_REVISION_CACHE = {};
3417
+ function considerCachingRevision(revision, formId2, preferPending = false) {
3440
3418
  var _a2;
3441
- if (!formRevision) {
3419
+ if (!revision) {
3442
3420
  if (!formId2) {
3443
- throw new Error("If form revision is null, formId is required.");
3421
+ throw new Error("If revision is null, formId is required.");
3444
3422
  }
3445
- const currentLatestFormRevision = getLatestFormRevisionFromCache(formId2);
3446
- if (currentLatestFormRevision)
3423
+ const currentLatestRevision = getLatestRevisionFromCache(formId2);
3424
+ if (currentLatestRevision)
3447
3425
  return;
3448
- LATEST_FORM_REVISION_CACHE[formId2] = null;
3426
+ LATEST_REVISION_CACHE[formId2] = null;
3449
3427
  return;
3450
3428
  }
3451
- if (formRevision.revision === "Pending") {
3429
+ if (revision.revision === "Pending") {
3452
3430
  if (preferPending) {
3453
- LATEST_FORM_REVISION_CACHE[formRevision.form] = formRevision;
3431
+ LATEST_REVISION_CACHE[revision.form] = revision;
3454
3432
  }
3455
3433
  return;
3456
3434
  }
3457
- const cachedFormRevision = (_a2 = LATEST_FORM_REVISION_CACHE[formRevision.form]) == null ? void 0 : _a2.revision;
3458
- if (formRevision.revision > (typeof cachedFormRevision === "number" ? cachedFormRevision : -1)) {
3459
- LATEST_FORM_REVISION_CACHE[formRevision.form] = formRevision;
3435
+ const cachedRevision = (_a2 = LATEST_REVISION_CACHE[revision.form]) == null ? void 0 : _a2.revision;
3436
+ if (revision.revision > (typeof cachedRevision === "number" ? cachedRevision : -1)) {
3437
+ LATEST_REVISION_CACHE[revision.form] = revision;
3460
3438
  }
3461
3439
  }
3462
- function getLatestFormRevisionFromCache(formId2) {
3463
- return LATEST_FORM_REVISION_CACHE[formId2];
3440
+ function getLatestRevisionFromCache(formId2) {
3441
+ return LATEST_REVISION_CACHE[formId2];
3464
3442
  }
3465
- const initialState$5 = {
3466
- formRevisions: {},
3467
- attachments: {}
3468
- };
3469
- const formRevisionsSlice = createSlice({
3470
- name: "formRevisions",
3471
- initialState: initialState$5,
3472
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$5)),
3443
+ const initialState$3 = {
3444
+ userForms: {},
3445
+ revisions: {},
3446
+ submissions: {},
3447
+ submissionAttachments: {},
3448
+ revisionAttachments: {}
3449
+ };
3450
+ const userFormSlice = createSlice({
3451
+ name: "userForms",
3452
+ initialState: initialState$3,
3453
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$3)),
3473
3454
  reducers: {
3474
- // revision related actions
3475
- setFormRevision: (state, action) => {
3476
- state.formRevisions[action.payload.offline_id] = action.payload;
3477
- considerCachingFormRevision(action.payload);
3455
+ setUserForms: (state, action) => {
3456
+ state.userForms = {};
3457
+ action.payload.forEach((userForm) => {
3458
+ state.userForms[userForm.offline_id] = userForm;
3459
+ });
3478
3460
  },
3479
- setFormRevisions: (state, action) => {
3480
- state.formRevisions = {};
3481
- for (const revision of action.payload) {
3482
- state.formRevisions[revision.offline_id] = revision;
3483
- considerCachingFormRevision(revision);
3484
- }
3461
+ addUserForm: (state, action) => {
3462
+ state.userForms[action.payload.offline_id] = action.payload;
3485
3463
  },
3486
- addFormRevision: (state, action) => {
3487
- if (state.formRevisions[action.payload.offline_id] !== void 0) {
3488
- throw new Error(`Revision with offline_id ${action.payload.offline_id} already exists`);
3489
- }
3490
- state.formRevisions[action.payload.offline_id] = action.payload;
3491
- considerCachingFormRevision(action.payload);
3464
+ addUserForms: (state, action) => {
3465
+ action.payload.forEach((userForm) => {
3466
+ state.userForms[userForm.offline_id] = userForm;
3467
+ });
3492
3468
  },
3493
- // TODO: @Audiopolis / Magnus - do we want to standardize using PayloadAction?
3494
- addFormRevisions: (state, action) => {
3495
- for (const userFormRevision of action.payload) {
3496
- if (state.formRevisions[userFormRevision.offline_id] !== void 0) {
3497
- throw new Error(`Revision with offline_id ${userFormRevision.offline_id} already exists`);
3498
- }
3499
- }
3500
- for (const userFormRevision of action.payload) {
3501
- state.formRevisions[userFormRevision.offline_id] = userFormRevision;
3502
- considerCachingFormRevision(userFormRevision);
3503
- }
3469
+ addUserFormRevisions: (state, action) => {
3470
+ action.payload.forEach((userFormRevision) => {
3471
+ state.revisions[userFormRevision.offline_id] = userFormRevision;
3472
+ considerCachingRevision(userFormRevision);
3473
+ });
3504
3474
  },
3505
- // UserFormRevisions do not get updated
3506
- deleteFormRevision: (state, action) => {
3507
- if (state.formRevisions[action.payload] === void 0) {
3508
- throw new Error(`Revision with offline_id ${action.payload} does not exist`);
3509
- }
3510
- delete state.formRevisions[action.payload];
3511
- delete LATEST_FORM_REVISION_CACHE[action.payload];
3475
+ addUserFormRevision: (state, action) => {
3476
+ state.revisions[action.payload.offline_id] = action.payload;
3477
+ considerCachingRevision(action.payload);
3512
3478
  },
3513
- deleteFormRevisions: (state, action) => {
3514
- for (const offlineId of action.payload) {
3515
- if (state.formRevisions[offlineId] === void 0) {
3516
- throw new Error(`Revision with offline_id ${offlineId} does not exist`);
3517
- }
3518
- }
3519
- for (const offlineId of action.payload) {
3520
- delete state.formRevisions[offlineId];
3521
- delete LATEST_FORM_REVISION_CACHE[offlineId];
3479
+ deleteUserFormRevision: (state, action) => {
3480
+ delete state.revisions[action.payload];
3481
+ delete LATEST_REVISION_CACHE[action.payload];
3482
+ },
3483
+ deleteUserFormRevisions: (state, action) => {
3484
+ for (const userFormRevision of action.payload) {
3485
+ delete state.revisions[userFormRevision.offline_id];
3486
+ delete LATEST_REVISION_CACHE[userFormRevision.offline_id];
3522
3487
  }
3523
3488
  },
3524
- // attachment related actions
3525
- setFormRevisionAttachments: (state, action) => {
3526
- state.attachments = {};
3527
- for (const attachment of action.payload) {
3528
- state.attachments[attachment.offline_id] = attachment;
3489
+ updateOrCreateUserFormSubmission: (state, action) => {
3490
+ state.submissions[action.payload.offline_id] = action.payload;
3491
+ },
3492
+ addUserFormSubmissionAttachment: (state, action) => {
3493
+ const submissionId = action.payload.submission;
3494
+ const submissionAttachments = state.submissionAttachments[submissionId];
3495
+ if (submissionAttachments) {
3496
+ submissionAttachments.push(action.payload);
3497
+ } else {
3498
+ state.submissionAttachments[submissionId] = [action.payload];
3529
3499
  }
3530
3500
  },
3531
- addFormRevisionAttachment: (state, action) => {
3532
- if (state.attachments[action.payload.offline_id] !== void 0) {
3533
- throw new Error(`Attachment with offline_id ${action.payload.offline_id} already exists`);
3501
+ addUserFormRevisionAttachment: (state, action) => {
3502
+ const revisionId = action.payload.revision;
3503
+ const revisionAttachments = state.revisionAttachments[revisionId];
3504
+ if (revisionAttachments) {
3505
+ revisionAttachments.push(action.payload);
3506
+ } else {
3507
+ state.revisionAttachments[revisionId] = [action.payload];
3534
3508
  }
3535
- state.attachments[action.payload.offline_id] = action.payload;
3536
3509
  },
3537
- addFormRevisionAttachments: (state, action) => {
3510
+ setUserFormSubmissionAttachments: (state, action) => {
3511
+ state.submissionAttachments = {};
3538
3512
  for (const attachment of action.payload) {
3539
- if (state.attachments[attachment.offline_id] !== void 0) {
3540
- throw new Error(`Attachment with offline_id ${attachment.offline_id} already exists`);
3513
+ const submissionId = attachment.submission;
3514
+ const submissionAttachments = state.submissionAttachments[submissionId];
3515
+ if (submissionAttachments) {
3516
+ submissionAttachments.push(attachment);
3517
+ } else {
3518
+ state.submissionAttachments[submissionId] = [attachment];
3541
3519
  }
3542
3520
  }
3521
+ },
3522
+ setUserFormRevisionAttachments: (state, action) => {
3523
+ state.revisionAttachments = {};
3543
3524
  for (const attachment of action.payload) {
3544
- state.attachments[attachment.offline_id] = attachment;
3525
+ const revisionId = attachment.revision;
3526
+ const revisionAttachments = state.revisionAttachments[revisionId];
3527
+ if (revisionAttachments) {
3528
+ revisionAttachments.push(attachment);
3529
+ } else {
3530
+ state.revisionAttachments[revisionId] = [attachment];
3531
+ }
3545
3532
  }
3546
3533
  },
3547
- deleteFormRevisionAttachment: (state, action) => {
3548
- if (state.attachments[action.payload] === void 0) {
3549
- throw new Error(`Attachment with offline_id ${action.payload} does not exist`);
3550
- }
3551
- delete state.attachments[action.payload];
3534
+ deleteUserFormSubmission: (state, action) => {
3535
+ delete state.submissions[action.payload];
3552
3536
  },
3553
- deleteFormRevisionAttachments: (state, action) => {
3554
- for (const offlineId of action.payload) {
3555
- if (state.attachments[offlineId] === void 0) {
3556
- throw new Error(`Attachment with offline_id ${offlineId} does not exist`);
3557
- }
3558
- }
3559
- for (const offlineId of action.payload) {
3560
- delete state.attachments[offlineId];
3561
- }
3562
- }
3563
- }
3564
- });
3565
- const {
3566
- setFormRevision,
3567
- setFormRevisions,
3568
- addFormRevision,
3569
- addFormRevisions,
3570
- deleteFormRevision,
3571
- deleteFormRevisions,
3572
- setFormRevisionAttachments,
3573
- addFormRevisionAttachment,
3574
- addFormRevisionAttachments,
3575
- deleteFormRevisionAttachment,
3576
- deleteFormRevisionAttachments
3577
- } = formRevisionsSlice.actions;
3578
- const selectFormRevisionMapping = (state) => state.formRevisionReducer.formRevisions;
3579
- const selectFormRevisions = createSelector(
3580
- [selectFormRevisionMapping],
3581
- (formRevisions) => Object.values(formRevisions)
3582
- );
3583
- const selectFormRevision = (formRevisionId) => (state) => {
3584
- return state.formRevisionReducer.formRevisions[formRevisionId];
3585
- };
3586
- const _selectLatestFormRevision = (formRevisions, formId2) => {
3587
- let ret = null;
3588
- for (const candidate of Object.values(formRevisions)) {
3589
- if (candidate.form === formId2 && (!ret || ret.revision < candidate.revision)) {
3590
- ret = candidate;
3591
- }
3592
- }
3593
- if (!ret) {
3594
- throw new Error("No form revision found for form " + formId2);
3595
- }
3596
- return ret;
3597
- };
3598
- const selectLatestFormRevisionOfForm = restructureCreateSelectorWithArgs(
3599
- createSelector([selectFormRevisionMapping, (_state, formId2) => formId2], (revisions, formId2) => {
3600
- if (!formId2) {
3601
- throw new Error("formId is required");
3602
- }
3603
- return _selectLatestFormRevision(revisions, formId2);
3604
- })
3605
- );
3606
- const selectFormRevisionsOfForm = restructureCreateSelectorWithArgs(
3607
- createSelector([selectFormRevisions, (_state, formId2) => formId2], (revisions, formId2) => {
3608
- return revisions.filter((revision) => {
3609
- return revision.form === formId2;
3610
- });
3611
- })
3612
- );
3613
- const selectLatestFormRevisionsOfComponentTypes = restructureCreateSelectorWithArgs(
3614
- createSelector(
3615
- [
3616
- (state) => state.formReducer.forms,
3617
- selectFormRevisionMapping,
3618
- (_state, componentTypeIds) => componentTypeIds
3619
- ],
3620
- (userForms, revisions, componentTypeIds) => {
3621
- const componentTypeIdsSet = new Set(componentTypeIds);
3622
- const ret = {};
3623
- for (const form of Object.values(userForms)) {
3624
- if (form.component_type && componentTypeIdsSet.has(form.component_type)) {
3625
- ret[form.component_type] = _selectLatestFormRevision(revisions, form.offline_id);
3626
- }
3537
+ deleteUserFormSubmissions: (state, action) => {
3538
+ for (const userFormSubmission of action.payload) {
3539
+ delete state.submissions[userFormSubmission.offline_id];
3627
3540
  }
3628
- return ret;
3629
- }
3630
- )
3631
- );
3632
- const selectLatestFormRevisionByForm = createSelector([selectFormRevisionMapping], (revisions) => {
3633
- const latestRevisions = {};
3634
- for (const revision of Object.values(revisions)) {
3635
- const formId2 = revision.form;
3636
- const currentLatestRevision = latestRevisions[formId2];
3637
- if (!currentLatestRevision || currentLatestRevision.revision < revision.revision) {
3638
- latestRevisions[formId2] = revision;
3639
- }
3640
- }
3641
- return latestRevisions;
3642
- });
3643
- const selectUserFormRevisionAttachmentsMapping = (state) => {
3644
- return state.formRevisionReducer.attachments;
3645
- };
3646
- const selectAttachmentsOfFormRevision = restructureCreateSelectorWithArgs(
3647
- createSelector(
3648
- [selectUserFormRevisionAttachmentsMapping, (_state, revisionId) => revisionId],
3649
- (attachments, revisionId) => {
3650
- return Object.values(attachments).filter((attachment) => attachment.revision === revisionId);
3651
- }
3652
- )
3653
- );
3654
- const formRevisionReducer = formRevisionsSlice.reducer;
3655
- const initialState$4 = {
3656
- forms: {}
3657
- };
3658
- const formSlice = createSlice({
3659
- name: "forms",
3660
- initialState: initialState$4,
3661
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$4)),
3662
- reducers: {
3663
- setForms: (state, action) => {
3664
- state.forms = {};
3665
- action.payload.forEach((userForm) => {
3666
- state.forms[userForm.offline_id] = userForm;
3667
- });
3668
3541
  },
3669
- addForm: (state, action) => {
3670
- state.forms[action.payload.offline_id] = action.payload;
3542
+ addUserFormSubmissions: (state, action) => {
3543
+ for (const submission of action.payload) {
3544
+ state.submissions[submission.offline_id] = submission;
3545
+ }
3671
3546
  },
3672
- addForms: (state, action) => {
3673
- action.payload.forEach((userForm) => {
3674
- state.forms[userForm.offline_id] = userForm;
3547
+ setUserFormSubmissions: (state, action) => {
3548
+ state.submissions = {};
3549
+ action.payload.forEach((submission) => {
3550
+ state.submissions[submission.offline_id] = submission;
3675
3551
  });
3676
3552
  },
3677
3553
  favoriteForm: (state, action) => {
3678
3554
  const { formId: formId2 } = action.payload;
3679
- const form = state.forms[formId2];
3555
+ const form = state.userForms[formId2];
3680
3556
  if (!form) {
3681
3557
  throw new Error("No form exists with the id " + formId2);
3682
3558
  }
@@ -3684,23 +3560,48 @@ const formSlice = createSlice({
3684
3560
  },
3685
3561
  unfavoriteForm: (state, action) => {
3686
3562
  const { formId: formId2 } = action.payload;
3687
- const form = state.forms[formId2];
3563
+ const form = state.userForms[formId2];
3688
3564
  if (!form) {
3689
3565
  throw new Error("No form exists with the id " + formId2);
3690
3566
  }
3691
3567
  form.favorite = false;
3692
3568
  },
3693
- deleteForm: (state, action) => {
3694
- delete state.forms[action.payload];
3569
+ deleteUserForm: (state, action) => {
3570
+ delete state.userForms[action.payload];
3695
3571
  }
3696
3572
  }
3697
3573
  });
3698
- const { setForms, addForm, addForms, favoriteForm, unfavoriteForm, deleteForm } = formSlice.actions;
3699
- const selectFilteredForms = restructureCreateSelectorWithArgs(
3574
+ const {
3575
+ addUserForm,
3576
+ addUserForms,
3577
+ addUserFormRevisions,
3578
+ updateOrCreateUserFormSubmission,
3579
+ addUserFormSubmissions,
3580
+ deleteUserFormSubmission,
3581
+ deleteUserFormSubmissions,
3582
+ favoriteForm,
3583
+ unfavoriteForm,
3584
+ deleteUserForm,
3585
+ deleteUserFormRevision,
3586
+ deleteUserFormRevisions,
3587
+ setUserFormSubmissions,
3588
+ addUserFormRevision,
3589
+ addUserFormSubmissionAttachment,
3590
+ addUserFormRevisionAttachment,
3591
+ setUserFormSubmissionAttachments,
3592
+ setUserFormRevisionAttachments
3593
+ } = userFormSlice.actions;
3594
+ const selectSubmissionAttachments = (submissionId) => (state) => {
3595
+ return state.userFormReducer.submissionAttachments[submissionId] || [];
3596
+ };
3597
+ const selectRevisionAttachments = (revisionId) => (state) => {
3598
+ return state.userFormReducer.revisionAttachments[revisionId] || [];
3599
+ };
3600
+ const selectFilteredUserForms = restructureCreateSelectorWithArgs(
3700
3601
  createSelector(
3701
3602
  [
3702
- (state) => state.formReducer.forms,
3703
- (state) => state.formRevisionReducer.formRevisions,
3603
+ (state) => state.userFormReducer.userForms,
3604
+ (state) => state.userFormReducer.revisions,
3704
3605
  (_state, search) => search
3705
3606
  ],
3706
3607
  (userForms, revisions, search) => {
@@ -3734,188 +3635,63 @@ const selectFilteredForms = restructureCreateSelectorWithArgs(
3734
3635
  { memoizeOptions: { equalityCheck: shallowEqual$1 } }
3735
3636
  )
3736
3637
  );
3737
- const selectForm = (formId2) => (state) => {
3738
- return state.formReducer.forms[formId2];
3638
+ const selectFormRevision = (revisionId) => (state) => {
3639
+ return state.userFormReducer.revisions[revisionId];
3739
3640
  };
3740
- const selectFormMapping = (state) => {
3741
- return state.formReducer.forms;
3641
+ const _selectLatestFormRevision = (revisions, formId2) => {
3642
+ let ret = null;
3643
+ for (const candidate of Object.values(revisions)) {
3644
+ if (candidate.form === formId2 && (!ret || ret.revision < candidate.revision)) {
3645
+ ret = candidate;
3646
+ }
3647
+ }
3648
+ if (!ret) {
3649
+ throw new Error("No revision found for form " + formId2);
3650
+ }
3651
+ return ret;
3742
3652
  };
3743
- const selectFormOfComponentType = restructureCreateSelectorWithArgs(
3653
+ const selectLatestFormRevision = restructureCreateSelectorWithArgs(
3744
3654
  createSelector(
3745
- [selectFormMapping, (_state, componentTypeId) => componentTypeId],
3746
- (userForms, componentTypeId) => {
3747
- return Object.values(userForms).find((userForm) => userForm.component_type === componentTypeId);
3655
+ [(state) => state.userFormReducer.revisions, (_state, formId2) => formId2],
3656
+ (revisions, formId2) => {
3657
+ if (!formId2) {
3658
+ throw new Error("formId is required");
3659
+ }
3660
+ return _selectLatestFormRevision(revisions, formId2);
3748
3661
  }
3749
3662
  )
3750
3663
  );
3751
- const selectFormsCount = createSelector([selectFormMapping], (userForms) => {
3752
- return Object.keys(userForms).length;
3753
- });
3754
- const selectGeneralFormCount = createSelector([selectFormMapping], (userForms) => {
3755
- return Object.values(userForms).filter((form) => !form.component_type).length;
3756
- });
3757
- const formReducer = formSlice.reducer;
3758
- const initialState$3 = {
3759
- formSubmissions: {},
3760
- attachments: {}
3761
- };
3762
- const formSubmissionSlice = createSlice({
3763
- name: "formSubmissions",
3764
- initialState: initialState$3,
3765
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$3)),
3766
- reducers: {
3767
- setFormSubmission: (state, action) => {
3768
- state.formSubmissions[action.payload.offline_id] = action.payload;
3769
- },
3770
- setFormSubmissions: (state, action) => {
3771
- state.formSubmissions = {};
3772
- for (const submission of action.payload) {
3773
- state.formSubmissions[submission.offline_id] = submission;
3774
- }
3775
- },
3776
- addFormSubmission: (state, action) => {
3777
- if (state.formSubmissions[action.payload.offline_id] !== void 0) {
3778
- throw new Error(`Submission with offline_id ${action.payload.offline_id} already exists`);
3779
- }
3780
- state.formSubmissions[action.payload.offline_id] = action.payload;
3781
- },
3782
- addFormSubmissions: (state, action) => {
3783
- for (const submission of action.payload) {
3784
- if (state.formSubmissions[submission.offline_id] !== void 0) {
3785
- throw new Error(`Submission with offline_id ${submission.offline_id} already exists`);
3786
- }
3787
- }
3788
- for (const submission of action.payload) {
3789
- state.formSubmissions[submission.offline_id] = submission;
3790
- }
3791
- },
3792
- updateFormSubmission: (state, action) => {
3793
- if (state.formSubmissions[action.payload.offline_id] === void 0) {
3794
- throw new Error(`Submission with offline_id ${action.payload.offline_id} does not exist`);
3795
- }
3796
- state.formSubmissions[action.payload.offline_id] = action.payload;
3797
- },
3798
- updateFormSubmissions: (state, action) => {
3799
- for (const submission of action.payload) {
3800
- if (state.formSubmissions[submission.offline_id] === void 0) {
3801
- throw new Error(`Submission with offline_id ${submission.offline_id} does not exist`);
3802
- }
3803
- }
3804
- for (const submission of action.payload) {
3805
- state.formSubmissions[submission.offline_id] = submission;
3806
- }
3807
- },
3808
- deleteFormSubmission: (state, action) => {
3809
- if (state.formSubmissions[action.payload] === void 0) {
3810
- throw new Error(`Submission with offline_id ${action.payload} does not exist`);
3811
- }
3812
- delete state.formSubmissions[action.payload];
3813
- },
3814
- deleteFormSubmissions: (state, action) => {
3815
- for (const offlineId of action.payload) {
3816
- if (state.formSubmissions[offlineId] === void 0) {
3817
- throw new Error(`Submission with offline_id ${offlineId} does not exist`);
3818
- }
3819
- delete state.formSubmissions[offlineId];
3820
- }
3821
- for (const offlineId of action.payload) {
3822
- delete state.formSubmissions[offlineId];
3823
- }
3824
- },
3825
- // Attachments
3826
- addFormSubmissionAttachment: (state, action) => {
3827
- if (state.attachments[action.payload.offline_id] !== void 0) {
3828
- throw new Error(`Attachment with offline_id ${action.payload.offline_id} already exists`);
3829
- }
3830
- state.attachments[action.payload.offline_id] = action.payload;
3831
- },
3832
- addFormSubmissionAttachments: (state, action) => {
3833
- for (const attachment of action.payload) {
3834
- if (state.attachments[attachment.offline_id] !== void 0) {
3835
- throw new Error(`Attachment with offline_id ${attachment.offline_id} already exists`);
3836
- }
3837
- }
3838
- for (const attachment of action.payload) {
3839
- state.attachments[attachment.offline_id] = attachment;
3840
- }
3841
- },
3842
- // We only need a multi set for attachments because they are not updated, only added and deleted
3843
- setFormSubmissionAttachments: (state, action) => {
3844
- state.attachments = {};
3845
- for (const attachment of action.payload) {
3846
- state.attachments[attachment.offline_id] = attachment;
3847
- }
3848
- },
3849
- updateFormSubmissionAttachments: (state, action) => {
3850
- for (const attachment of action.payload) {
3851
- if (state.attachments[attachment.offline_id] === void 0) {
3852
- throw new Error(`Attachment with offline_id ${attachment.offline_id} does not exist`);
3853
- }
3854
- }
3855
- for (const attachment of action.payload) {
3856
- state.attachments[attachment.offline_id] = attachment;
3857
- }
3858
- },
3859
- // The delete actions for UserFormSubmissionAttachments are not used in the app, but are included for completeness
3860
- // Could be used if editing a submission is ever supported, will be applicable for supporting tip tap content in submissions
3861
- deleteFormSubmissionAttachment: (state, action) => {
3862
- if (state.attachments[action.payload] === void 0) {
3863
- throw new Error(`Attachment with offline_id ${action.payload} does not exist`);
3864
- }
3865
- delete state.attachments[action.payload];
3866
- },
3867
- deleteFormSubmissionAttachments: (state, action) => {
3868
- for (const offlineId of action.payload) {
3869
- if (state.attachments[offlineId] === void 0) {
3870
- throw new Error(`Attachment with offline_id ${offlineId} does not exist`);
3871
- }
3872
- delete state.attachments[offlineId];
3873
- }
3874
- }
3875
- }
3876
- });
3877
- const {
3878
- setFormSubmission,
3879
- setFormSubmissions,
3880
- addFormSubmission,
3881
- addFormSubmissions,
3882
- updateFormSubmission,
3883
- updateFormSubmissions,
3884
- deleteFormSubmission,
3885
- deleteFormSubmissions,
3886
- addFormSubmissionAttachment,
3887
- addFormSubmissionAttachments,
3888
- setFormSubmissionAttachments,
3889
- updateFormSubmissionAttachments,
3890
- deleteFormSubmissionAttachment,
3891
- deleteFormSubmissionAttachments
3892
- } = formSubmissionSlice.actions;
3893
- const selectFormSubmissionsMapping = (state) => {
3894
- return state.formSubmissionReducer.formSubmissions;
3895
- };
3896
- const selectFormSubmissions = createSelector(
3897
- [selectFormSubmissionsMapping],
3898
- (submissions) => {
3899
- return Object.values(submissions);
3900
- }
3664
+ const selectUserForm = (formId2) => (state) => {
3665
+ return state.userFormReducer.userForms[formId2];
3666
+ };
3667
+ const selectSubmissionMapping = (state) => state.userFormReducer.submissions;
3668
+ const selectUserFormSubmission = (submissionId) => (state) => {
3669
+ return state.userFormReducer.submissions[submissionId];
3670
+ };
3671
+ const selectSubmissions = createSelector([selectSubmissionMapping], (submissions) => Object.values(submissions));
3672
+ const selectRevisionMapping = (state) => state.userFormReducer.revisions;
3673
+ const selectRevisions = createSelector([selectRevisionMapping], (revisions) => Object.values(revisions));
3674
+ const selectRevisionsForForm = restructureCreateSelectorWithArgs(
3675
+ createSelector([selectRevisions, (_state, formId2) => formId2], (revisions, formId2) => {
3676
+ return revisions.filter((revision) => {
3677
+ return revision.form === formId2;
3678
+ });
3679
+ })
3901
3680
  );
3902
- const selectFormSubmission = (submissionId) => (state) => {
3903
- return state.formSubmissionReducer.formSubmissions[submissionId];
3904
- };
3905
- const selectFormSubmissionsOfForm = restructureCreateSelectorWithArgs(
3681
+ const selectSubmissionsForForm = restructureCreateSelectorWithArgs(
3906
3682
  createSelector(
3907
- [selectFormSubmissions, selectFormRevisionMapping, (_state, formId2) => formId2],
3683
+ [selectSubmissions, selectRevisionMapping, (_state, formId2) => formId2],
3908
3684
  (submissions, revisionMapping, formId2) => {
3909
- return submissions.filter((submission) => {
3685
+ return Object.values(submissions).filter((submission) => {
3910
3686
  const revision = revisionMapping[submission.form_revision];
3911
3687
  return (revision == null ? void 0 : revision.form) === formId2;
3912
3688
  });
3913
3689
  }
3914
3690
  )
3915
3691
  );
3916
- const selectFormSubmissionsOfIssue = restructureCreateSelectorWithArgs(
3692
+ const selectSubmissionsForIssue = restructureCreateSelectorWithArgs(
3917
3693
  createSelector(
3918
- [selectFormSubmissions, (_state, issueId) => issueId],
3694
+ [(state) => state.userFormReducer.submissions, (_state, issueId) => issueId],
3919
3695
  (submissions, issueId) => {
3920
3696
  return Object.values(submissions).filter((submission) => {
3921
3697
  return submission.issue === issueId;
@@ -3923,9 +3699,9 @@ const selectFormSubmissionsOfIssue = restructureCreateSelectorWithArgs(
3923
3699
  }
3924
3700
  )
3925
3701
  );
3926
- const selectFormSubmissionsOfComponent = restructureCreateSelectorWithArgs(
3702
+ const selectSubmissionsForComponent = restructureCreateSelectorWithArgs(
3927
3703
  createSelector(
3928
- [selectFormSubmissions, (_state, componentId) => componentId],
3704
+ [selectSubmissions, (_state, componentId) => componentId],
3929
3705
  (submissions, componentId) => {
3930
3706
  return submissions.filter((submission) => {
3931
3707
  return submission.component === componentId;
@@ -3933,8 +3709,8 @@ const selectFormSubmissionsOfComponent = restructureCreateSelectorWithArgs(
3933
3709
  }
3934
3710
  )
3935
3711
  );
3936
- const selectFormSubmissionsByComponents = createSelector(
3937
- [selectFormSubmissionsMapping, selectComponentsMapping],
3712
+ const selectComponentSubmissionMapping = createSelector(
3713
+ [selectSubmissionMapping, selectComponentsMapping],
3938
3714
  (submissions, components) => {
3939
3715
  var _a2;
3940
3716
  const componentSubmissionMapping = {};
@@ -3950,18 +3726,54 @@ const selectFormSubmissionsByComponents = createSelector(
3950
3726
  return componentSubmissionMapping;
3951
3727
  }
3952
3728
  );
3953
- const selectFormSubmissionAttachmentsMapping = (state) => {
3954
- return state.formSubmissionReducer.attachments;
3729
+ const selectUserFormMapping = (state) => {
3730
+ return state.userFormReducer.userForms;
3955
3731
  };
3956
- const selectAttachmentsOfFormSubmission = restructureCreateSelectorWithArgs(
3732
+ const selectComponentTypeForm = restructureCreateSelectorWithArgs(
3957
3733
  createSelector(
3958
- [selectFormSubmissionAttachmentsMapping, (_state, submissionId) => submissionId],
3959
- (attachmentsMapping, submissionId) => {
3960
- return Object.values(attachmentsMapping).filter((attachment) => attachment.submission === submissionId);
3734
+ [selectUserFormMapping, (_state, componentTypeId) => componentTypeId],
3735
+ (userForms, componentTypeId) => {
3736
+ return Object.values(userForms).find((userForm) => userForm.component_type === componentTypeId);
3737
+ }
3738
+ )
3739
+ );
3740
+ const selectLatestRevisionsFromComponentTypeIds = restructureCreateSelectorWithArgs(
3741
+ createSelector(
3742
+ [
3743
+ selectUserFormMapping,
3744
+ selectRevisionMapping,
3745
+ (_state, componentTypeIds) => componentTypeIds
3746
+ ],
3747
+ (userForms, revisions, componentTypeIds) => {
3748
+ const componentTypeIdsSet = new Set(componentTypeIds);
3749
+ const ret = {};
3750
+ for (const form of Object.values(userForms)) {
3751
+ if (form.component_type && componentTypeIdsSet.has(form.component_type)) {
3752
+ ret[form.component_type] = _selectLatestFormRevision(revisions, form.offline_id);
3753
+ }
3754
+ }
3755
+ return ret;
3961
3756
  }
3962
3757
  )
3963
3758
  );
3964
- const formSubmissionReducer = formSubmissionSlice.reducer;
3759
+ const selectLatestRevisionByFormId = createSelector([selectRevisionMapping], (revisions) => {
3760
+ const latestRevisions = {};
3761
+ for (const revision of Object.values(revisions)) {
3762
+ const formId2 = revision.form;
3763
+ const currentLatestRevision = latestRevisions[formId2];
3764
+ if (!currentLatestRevision || currentLatestRevision.revision < revision.revision) {
3765
+ latestRevisions[formId2] = revision;
3766
+ }
3767
+ }
3768
+ return latestRevisions;
3769
+ });
3770
+ const selectNumberOfUserForms = createSelector([selectUserFormMapping], (userForms) => {
3771
+ return Object.keys(userForms).length;
3772
+ });
3773
+ const selectNumberOfGeneralUserForms = createSelector([selectUserFormMapping], (userForms) => {
3774
+ return Object.values(userForms).filter((form) => !form.component_type).length;
3775
+ });
3776
+ const userFormReducer = userFormSlice.reducer;
3965
3777
  const initialState$2 = {
3966
3778
  emailDomains: {}
3967
3779
  };
@@ -4189,9 +4001,6 @@ const selectAllDocumentAttachments = createSelector(
4189
4001
  [selectDocumentAttachmentMapping],
4190
4002
  (mapping) => Object.values(mapping)
4191
4003
  );
4192
- const selectDocumentAttachment = (attachmentId) => (state) => {
4193
- return state.documentsReducer.attachments[attachmentId];
4194
- };
4195
4004
  const selectAttachmentsOfDocument = restructureCreateSelectorWithArgs(
4196
4005
  createSelector(
4197
4006
  [selectAllDocumentAttachments, (_state, documentId) => documentId],
@@ -4259,9 +4068,7 @@ const overmapReducers = {
4259
4068
  projectFileReducer,
4260
4069
  rehydratedReducer,
4261
4070
  settingReducer,
4262
- formReducer,
4263
- formRevisionReducer,
4264
- formSubmissionReducer,
4071
+ userFormReducer,
4265
4072
  userReducer,
4266
4073
  workspaceReducer,
4267
4074
  emailDomainsReducer,
@@ -4314,7 +4121,9 @@ function handleWorkspaceRemoval(draft, action) {
4314
4121
  throw new Error(`Failed to update index_workspace of issue ${issue.offline_id} to main workspace`);
4315
4122
  }
4316
4123
  }
4317
- const indexedForms = Object.values(draft.formReducer.forms).filter((form) => form.index_workspace === workspaceId);
4124
+ const indexedForms = Object.values(draft.userFormReducer.userForms).filter(
4125
+ (form) => form.index_workspace === workspaceId
4126
+ );
4318
4127
  for (const form of indexedForms) {
4319
4128
  form.index_workspace = mainWorkspace.offline_id;
4320
4129
  }
@@ -6951,7 +6760,7 @@ class UserFormService extends BaseApiService {
6951
6760
  ...revisionAttachmentPayload,
6952
6761
  file: URL.createObjectURL(image)
6953
6762
  };
6954
- store.dispatch(addFormRevisionAttachment(offlinePayload));
6763
+ store.dispatch(addUserFormRevisionAttachment(offlinePayload));
6955
6764
  return attach;
6956
6765
  });
6957
6766
  });
@@ -6985,8 +6794,8 @@ class UserFormService extends BaseApiService {
6985
6794
  revision: 0
6986
6795
  };
6987
6796
  const { store } = this.client;
6988
- store.dispatch(addForm(retForm));
6989
- store.dispatch(addFormRevision(retRevision));
6797
+ store.dispatch(addUserForm(retForm));
6798
+ store.dispatch(addUserFormRevision(retRevision));
6990
6799
  const formPromise = this.enqueueRequest({
6991
6800
  description: "Create form",
6992
6801
  method: HttpMethod.POST,
@@ -7004,8 +6813,8 @@ class UserFormService extends BaseApiService {
7004
6813
  });
7005
6814
  const attachImagesPromises = this.getAttachImagePromises(images, offlineRevisionPayload.offline_id);
7006
6815
  void formPromise.catch((e) => {
7007
- store.dispatch(deleteForm(retForm.offline_id));
7008
- store.dispatch(deleteFormRevision(retRevision.offline_id));
6816
+ store.dispatch(deleteUserForm(retForm.offline_id));
6817
+ store.dispatch(deleteUserFormRevision(retRevision.offline_id));
7009
6818
  throw e;
7010
6819
  });
7011
6820
  const settledPromise = Promise.all([formPromise, ...attachImagesPromises]).then(() => formPromise);
@@ -7047,7 +6856,7 @@ class UserFormService extends BaseApiService {
7047
6856
  revision: "Pending",
7048
6857
  form: formId2
7049
6858
  };
7050
- store.dispatch(addFormRevision(fullRevision));
6859
+ store.dispatch(addUserFormRevision(fullRevision));
7051
6860
  const promise = this.enqueueRequest({
7052
6861
  description: "Create form revision",
7053
6862
  method: HttpMethod.PATCH,
@@ -7061,9 +6870,9 @@ class UserFormService extends BaseApiService {
7061
6870
  });
7062
6871
  const attachImagesPromises = this.getAttachImagePromises(images, offlineRevision.offline_id);
7063
6872
  void promise.then((result) => {
7064
- store.dispatch(setFormRevision(result));
6873
+ store.dispatch(addUserFormRevision(result));
7065
6874
  }).catch(() => {
7066
- store.dispatch(deleteFormRevision(fullRevision.offline_id));
6875
+ store.dispatch(deleteUserFormRevision(fullRevision.offline_id));
7067
6876
  });
7068
6877
  const settledPromise = Promise.all([promise, ...attachImagesPromises]).then(() => promise);
7069
6878
  return [fullRevision, settledPromise];
@@ -7105,19 +6914,19 @@ class UserFormService extends BaseApiService {
7105
6914
  async delete(formId2) {
7106
6915
  const { store } = this.client;
7107
6916
  const state = store.getState();
7108
- const userForm = selectForm(formId2)(state);
6917
+ const userForm = selectUserForm(formId2)(state);
7109
6918
  if (!userForm) {
7110
6919
  throw new Error("Expected userForm to exist");
7111
6920
  }
7112
- const userFormSubmissions = selectFormSubmissionsOfForm(formId2)(state);
6921
+ const userFormSubmissions = selectSubmissionsForForm(formId2)(state);
7113
6922
  if (userFormSubmissions && userFormSubmissions.length > 0) {
7114
- store.dispatch(deleteFormSubmissions(userFormSubmissions.map(({ offline_id }) => offline_id)));
6923
+ store.dispatch(deleteUserFormSubmissions(userFormSubmissions));
7115
6924
  }
7116
- const userFormRevisions = selectFormRevisionsOfForm(formId2)(state);
6925
+ const userFormRevisions = selectRevisionsForForm(formId2)(state);
7117
6926
  if (userFormRevisions && userFormRevisions.length > 0) {
7118
- store.dispatch(deleteFormRevisions(userFormRevisions.map(({ offline_id }) => offline_id)));
6927
+ store.dispatch(deleteUserFormRevisions(userFormRevisions));
7119
6928
  }
7120
- store.dispatch(deleteForm(formId2));
6929
+ store.dispatch(deleteUserForm(formId2));
7121
6930
  try {
7122
6931
  return await this.enqueueRequest({
7123
6932
  description: "Delete form",
@@ -7127,12 +6936,12 @@ class UserFormService extends BaseApiService {
7127
6936
  blocks: []
7128
6937
  });
7129
6938
  } catch (e) {
7130
- store.dispatch(addForm(userForm));
6939
+ store.dispatch(addUserForm(userForm));
7131
6940
  if (userFormRevisions && userFormRevisions.length > 0) {
7132
- store.dispatch(addFormRevisions(userFormRevisions));
6941
+ store.dispatch(addUserFormRevisions(userFormRevisions));
7133
6942
  }
7134
6943
  if (userFormSubmissions && userFormSubmissions.length > 0) {
7135
- store.dispatch(addFormSubmissions(userFormSubmissions));
6944
+ store.dispatch(addUserFormSubmissions(userFormSubmissions));
7136
6945
  }
7137
6946
  throw e;
7138
6947
  }
@@ -7146,15 +6955,16 @@ class UserFormService extends BaseApiService {
7146
6955
  blockers: [],
7147
6956
  blocks: []
7148
6957
  });
7149
- store.dispatch(setForms(Object.values(result.forms)));
7150
- store.dispatch(setFormRevisions(Object.values(result.revisions)));
7151
- store.dispatch(setFormRevisionAttachments(Object.values(result.attachments)));
6958
+ store.dispatch(addUserForms(Object.values(result.forms)));
6959
+ store.dispatch(addUserFormRevisions(Object.values(result.revisions)));
6960
+ store.dispatch(setUserFormRevisionAttachments(Object.values(result.attachments)));
7152
6961
  }
7153
6962
  }
7154
6963
  const isArrayOfFiles = (value) => {
7155
6964
  return Array.isArray(value) && value[0] instanceof File;
7156
6965
  };
7157
- const separateFilesFromValues = (values) => {
6966
+ const separateFilesFromValues = (payload) => {
6967
+ const { values } = payload;
7158
6968
  const files = {};
7159
6969
  const newValues = {};
7160
6970
  for (const key in values) {
@@ -7169,13 +6979,17 @@ const separateFilesFromValues = (values) => {
7169
6979
  newValues[key] = value;
7170
6980
  }
7171
6981
  }
7172
- return { values: newValues, files };
6982
+ const payloadWithoutFiles = {
6983
+ ...payload,
6984
+ values: newValues
6985
+ };
6986
+ return { payloadWithoutFiles, files };
7173
6987
  };
7174
6988
  class UserFormSubmissionService extends BaseApiService {
7175
6989
  constructor() {
7176
6990
  super(...arguments);
7177
6991
  // Attach files to submission, after uploading them to S3
7178
- __publicField(this, "getAttachFilesPromises", (files, submission) => {
6992
+ __publicField(this, "getAttachFilesPromises", (files, payload) => {
7179
6993
  const { store } = this.client;
7180
6994
  return Object.entries(files).map(async ([key, fileArray]) => {
7181
6995
  const attachResults = [];
@@ -7185,27 +6999,24 @@ class UserFormSubmissionService extends BaseApiService {
7185
6999
  const [fileProps] = await this.client.files.uploadFileToS3(sha1);
7186
7000
  const submissionAttachmentPayload = offline({
7187
7001
  ...fileProps,
7188
- submission: submission.offline_id,
7002
+ submission: payload.offline_id,
7189
7003
  field_identifier: key
7190
7004
  });
7191
7005
  const attach = await this.enqueueRequest({
7192
7006
  description: "Attach file to form submission",
7193
7007
  method: HttpMethod.POST,
7194
- url: `/forms/submission/${submission.offline_id}/attachments/`,
7008
+ url: `/forms/submission/${payload.offline_id}/attachments/`,
7195
7009
  payload: submissionAttachmentPayload,
7196
- blockers: [
7197
- submission.component,
7198
- submission.component_stage,
7199
- submission.issue,
7200
- submission.form_revision
7201
- ].filter((x) => x !== void 0),
7010
+ blockers: [payload.component, payload.component_stage, payload.issue, payload.form_revision].filter(
7011
+ (x) => x !== void 0
7012
+ ),
7202
7013
  blocks: [submissionAttachmentPayload.offline_id]
7203
7014
  });
7204
7015
  const offlinePayload = {
7205
7016
  ...submissionAttachmentPayload,
7206
7017
  file: URL.createObjectURL(file)
7207
7018
  };
7208
- store.dispatch(addFormSubmissionAttachment(offlinePayload));
7019
+ store.dispatch(addUserFormSubmissionAttachment(offlinePayload));
7209
7020
  attachResults.push(attach);
7210
7021
  }
7211
7022
  return attachResults;
@@ -7219,165 +7030,70 @@ class UserFormSubmissionService extends BaseApiService {
7219
7030
  if (!activeProjectId) {
7220
7031
  throw new Error("Expected an active project");
7221
7032
  }
7222
- const { values, files } = separateFilesFromValues(payload.values);
7223
- const offlineSubmission = {
7224
- ...payload,
7225
- values,
7226
- created_by: state.userReducer.currentUser.id,
7227
- submitted_at: (/* @__PURE__ */ new Date()).toISOString()
7228
- };
7033
+ const { payloadWithoutFiles, files } = separateFilesFromValues(payload);
7229
7034
  const promise = this.enqueueRequest({
7230
7035
  description: "Respond to form",
7231
7036
  method: HttpMethod.POST,
7232
7037
  url: `/forms/revisions/${payload.form_revision}/respond/`,
7233
- payload: { ...offlineSubmission, project: activeProjectId },
7038
+ payload: { ...payloadWithoutFiles, project: activeProjectId },
7234
7039
  blockers: [payload.issue, payload.component, payload.component_stage, "add-form-entry"].filter(
7235
7040
  (x) => x !== void 0
7236
7041
  ),
7237
7042
  blocks: [payload.offline_id]
7238
7043
  });
7239
- const attachFilesPromises = this.getAttachFilesPromises(files, offlineSubmission);
7240
- store.dispatch(addFormSubmission(offlineSubmission));
7044
+ const attachFilesPromises = this.getAttachFilesPromises(files, payload);
7045
+ const now = (/* @__PURE__ */ new Date()).toISOString();
7046
+ const fullOfflineResult = {
7047
+ ...payload,
7048
+ created_by: state.userReducer.currentUser.id,
7049
+ created_at: now,
7050
+ updated_at: now
7051
+ };
7052
+ const offlineResultWithoutFiles = {
7053
+ ...fullOfflineResult,
7054
+ ...payloadWithoutFiles
7055
+ };
7056
+ store.dispatch(updateOrCreateUserFormSubmission(offlineResultWithoutFiles));
7241
7057
  void promise.then((result) => {
7242
7058
  store.dispatch(addActiveProjectFormSubmissionsCount(1));
7243
- store.dispatch(setFormSubmission(result));
7059
+ store.dispatch(updateOrCreateUserFormSubmission(result));
7244
7060
  return result;
7245
7061
  }).catch(() => {
7246
- store.dispatch(deleteFormSubmission(payload.offline_id));
7062
+ store.dispatch(deleteUserFormSubmission(payload.offline_id));
7247
7063
  store.dispatch(addActiveProjectFormSubmissionsCount(-1));
7248
7064
  });
7249
7065
  const settledPromise = Promise.all([promise, ...attachFilesPromises]).then(() => promise);
7250
- return [offlineSubmission, settledPromise];
7251
- }
7252
- // Note currently the bulkAdd method is specific to form submissions for components
7253
- // TODO: adapt the support bulk adding to any model type
7254
- async bulkAdd(args) {
7255
- const { form_revision, values: argsValues, componentOfflineIds } = args;
7256
- const { store } = this.client;
7257
- const offlineSubmissions = [];
7258
- const offlineAttachments = [];
7259
- const submissionOfflineIds = [];
7260
- const submissionsPayload = [];
7261
- const attachmentsPayload = [];
7262
- const { values, files } = separateFilesFromValues(argsValues);
7263
- const submittedAt = (/* @__PURE__ */ new Date()).toISOString();
7264
- const createdBy = store.getState().userReducer.currentUser.id;
7265
- for (const component_id of componentOfflineIds) {
7266
- const submission = offline({
7267
- form_revision,
7268
- values,
7269
- created_by: createdBy,
7270
- submitted_at: submittedAt,
7271
- component: component_id
7272
- });
7273
- submissionOfflineIds.push(submission.offline_id);
7274
- submissionsPayload.push({ offline_id: submission.offline_id, component_id });
7275
- offlineSubmissions.push(submission);
7276
- for (const [fieldIdentifier, fileArray] of Object.entries(files)) {
7277
- for (const file of fileArray) {
7278
- const sha1 = await hashFile(file);
7279
- await this.client.files.addCache(file, sha1);
7280
- const offlineAttachment = offline({
7281
- file_name: file.name,
7282
- file_sha1: sha1,
7283
- file: URL.createObjectURL(file),
7284
- submission: submission.offline_id,
7285
- field_identifier: fieldIdentifier
7286
- });
7287
- offlineAttachments.push(offlineAttachment);
7288
- attachmentsPayload.push({
7289
- offline_id: offlineAttachment.offline_id,
7290
- submission_id: submission.offline_id,
7291
- sha1,
7292
- name: file.name,
7293
- field_identifier: fieldIdentifier
7294
- });
7295
- }
7296
- }
7297
- }
7298
- const filesRecord = {};
7299
- for (const file of Object.values(files).flat()) {
7300
- const sha1 = await hashFile(file);
7301
- filesRecord[sha1] = {
7302
- sha1,
7303
- extension: file.name.split(".").pop() || "",
7304
- file_type: file.type,
7305
- size: file.size
7306
- };
7307
- }
7308
- store.dispatch(addFormSubmissions(offlineSubmissions));
7309
- store.dispatch(addFormSubmissionAttachments(offlineAttachments));
7310
- const promise = this.enqueueRequest({
7311
- description: "Bulk add form submissions",
7312
- method: HttpMethod.POST,
7313
- url: `/forms/revisions/${form_revision}/bulk-respond/`,
7314
- payload: {
7315
- form_data: values,
7316
- submitted_at: submittedAt,
7317
- submissions: submissionsPayload,
7318
- attachments: attachmentsPayload,
7319
- files: Object.values(filesRecord)
7320
- },
7321
- blockers: componentOfflineIds,
7322
- blocks: submissionOfflineIds
7323
- });
7324
- promise.then(({ submissions, attachments, presigned_urls }) => {
7325
- store.dispatch(updateFormSubmissions(submissions));
7326
- store.dispatch(updateFormSubmissionAttachments(attachments));
7327
- for (const [sha1, presigned_url] of Object.entries(presigned_urls)) {
7328
- const file = filesRecord[sha1];
7329
- if (!file)
7330
- continue;
7331
- void this.enqueueRequest({
7332
- url: presigned_url.url,
7333
- description: "Upload file",
7334
- method: HttpMethod.POST,
7335
- isExternalUrl: true,
7336
- isAuthNeeded: false,
7337
- attachmentHash: sha1,
7338
- blockers: [`s3-${file.sha1}.${file.extension}`],
7339
- blocks: [sha1],
7340
- s3url: presigned_url
7341
- });
7342
- }
7343
- }).catch(() => {
7344
- store.dispatch(deleteFormSubmissions(submissionOfflineIds));
7345
- store.dispatch(deleteFormSubmissionAttachments(offlineAttachments.map((x) => x.offline_id)));
7346
- });
7347
- return [offlineSubmissions, promise.then(({ submissions }) => submissions)];
7066
+ return [fullOfflineResult, settledPromise];
7348
7067
  }
7349
7068
  update(submission) {
7350
7069
  const { store } = this.client;
7351
- const { values, files } = separateFilesFromValues(submission.values);
7070
+ const { payloadWithoutFiles, files } = separateFilesFromValues(submission);
7071
+ if (!("created_by" in payloadWithoutFiles) || !("created_at" in payloadWithoutFiles)) {
7072
+ throw new Error("Expected payloadWithoutFiles to have created_by and created_at fields.");
7073
+ }
7352
7074
  const attachFilesPromises = this.getAttachFilesPromises(files, submission);
7353
- const offlineSubmission = {
7354
- ...submission,
7355
- values
7075
+ const fullResult = {
7076
+ ...payloadWithoutFiles,
7077
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
7356
7078
  };
7357
- const submissionToBeUpdated = store.getState().formSubmissionReducer.formSubmissions[submission.offline_id];
7358
- store.dispatch(updateFormSubmission(offlineSubmission));
7079
+ store.dispatch(updateOrCreateUserFormSubmission(fullResult));
7359
7080
  const promise = this.enqueueRequest({
7360
7081
  description: "Patch form submission",
7361
7082
  method: HttpMethod.PATCH,
7362
7083
  url: `/forms/submissions/${submission.offline_id}/`,
7363
- payload: offlineSubmission,
7364
- blockers: [offlineSubmission.issue, offlineSubmission.component, offlineSubmission.component_stage].filter(
7084
+ payload: fullResult,
7085
+ blockers: [fullResult.issue, fullResult.component, fullResult.component_stage].filter(
7365
7086
  (x) => x !== void 0
7366
7087
  ),
7367
- blocks: [offlineSubmission.offline_id]
7088
+ blocks: [fullResult.offline_id]
7368
7089
  });
7369
- promise.then((createdSubmission) => {
7370
- store.dispatch(setFormSubmission(createdSubmission));
7371
- }).catch(() => {
7372
- store.dispatch(setFormSubmission(submissionToBeUpdated));
7373
- });
7374
- return [offlineSubmission, Promise.all([promise, ...attachFilesPromises]).then(() => promise)];
7090
+ return Promise.all([promise, ...attachFilesPromises]).then(() => promise);
7375
7091
  }
7376
7092
  async delete(submissionId) {
7377
7093
  const { store } = this.client;
7378
7094
  const state = store.getState();
7379
- const submission = state.formSubmissionReducer.formSubmissions[submissionId];
7380
- store.dispatch(deleteFormSubmission(submissionId));
7095
+ const submission = state.userFormReducer.submissions[submissionId];
7096
+ store.dispatch(deleteUserFormSubmission(submissionId));
7381
7097
  store.dispatch(addActiveProjectFormSubmissionsCount(-1));
7382
7098
  try {
7383
7099
  return await this.enqueueRequest({
@@ -7388,8 +7104,10 @@ class UserFormSubmissionService extends BaseApiService {
7388
7104
  blocks: []
7389
7105
  });
7390
7106
  } catch (e) {
7391
- store.dispatch(addActiveProjectFormSubmissionsCount(1));
7392
- store.dispatch(addFormSubmission(submission));
7107
+ if (submission) {
7108
+ store.dispatch(addActiveProjectFormSubmissionsCount(1));
7109
+ store.dispatch(updateOrCreateUserFormSubmission(submission));
7110
+ }
7393
7111
  throw e;
7394
7112
  }
7395
7113
  }
@@ -7403,7 +7121,7 @@ class UserFormSubmissionService extends BaseApiService {
7403
7121
  blockers: [],
7404
7122
  blocks: []
7405
7123
  });
7406
- store.dispatch(setFormSubmissions(submissions));
7124
+ store.dispatch(setUserFormSubmissions(submissions));
7407
7125
  const attachments = await this.enqueueRequest({
7408
7126
  description: "Fetch form attachments",
7409
7127
  method: HttpMethod.GET,
@@ -7411,7 +7129,7 @@ class UserFormSubmissionService extends BaseApiService {
7411
7129
  blockers: [],
7412
7130
  blocks: []
7413
7131
  });
7414
- store.dispatch(setFormSubmissionAttachments(attachments));
7132
+ store.dispatch(setUserFormSubmissionAttachments(attachments));
7415
7133
  }
7416
7134
  }
7417
7135
  class WorkspaceService extends BaseApiService {
@@ -14270,7 +13988,7 @@ const initialFormValues = (fields, values) => {
14270
13988
  };
14271
13989
  const useAttachImagesToFormRevisionFields = (revision) => {
14272
13990
  const { sdk } = useSDK();
14273
- const attachments = useAppSelector(selectAttachmentsOfFormRevision((revision == null ? void 0 : revision.offline_id) ?? ""));
13991
+ const attachments = useAppSelector(selectRevisionAttachments((revision == null ? void 0 : revision.offline_id) ?? ""));
14274
13992
  return useMemo(() => {
14275
13993
  if (!revision || !attachments)
14276
13994
  return revision;
@@ -14367,7 +14085,7 @@ const FormSubmissionViewer = memo(
14367
14085
  return formRevisionToSchema(revisionWithImages, { readonly: true });
14368
14086
  }, [revisionWithImages]);
14369
14087
  const submissionValuesWithAttachments = useMemo(() => {
14370
- const attachments = selectAttachmentsOfFormSubmission(submission.offline_id)(sdk.store.getState()) ?? [];
14088
+ const attachments = selectSubmissionAttachments(submission.offline_id)(sdk.store.getState()) ?? [];
14371
14089
  const downloadedAttachments = {};
14372
14090
  for (const attachment of attachments) {
14373
14091
  const promise = sdk.files.fetchFileFromUrl(attachment.file, attachment.file_sha1, attachment.file_name);
@@ -14417,8 +14135,8 @@ const FormBrowser = memo(
14417
14135
  }
14418
14136
  return ret;
14419
14137
  }, [filter, maxResults, ownerFilter]);
14420
- const userForms = useAppSelector(selectFilteredForms(ownerFilterOptions)) ?? [];
14421
- const userFormMapping = useAppSelector(selectFormMapping);
14138
+ const userForms = useAppSelector(selectFilteredUserForms(ownerFilterOptions)) ?? [];
14139
+ const userFormMapping = useAppSelector(selectUserFormMapping);
14422
14140
  const attachableUserForms = userForms.filter((form) => !form.component_type);
14423
14141
  const attachableUserFormMapping = Object.values(userFormMapping).filter(
14424
14142
  (form) => !form.component_type
@@ -14451,7 +14169,7 @@ const FormBrowser = memo(
14451
14169
  const handleChange = useCallback((e) => {
14452
14170
  setFilter(e.currentTarget.value);
14453
14171
  }, []);
14454
- const numberOfForms = useAppSelector(selectGeneralFormCount) || 0;
14172
+ const numberOfForms = useAppSelector(selectNumberOfGeneralUserForms) || 0;
14455
14173
  const numberOfHiddenForms = numberOfForms - attachableUserForms.length;
14456
14174
  const overflowMessage = attachableUserForms.length == maxResults && numberOfHiddenForms > 0 ? `Only the first ${maxResults} results are shown (${numberOfHiddenForms} hidden)` : numberOfHiddenForms > 0 && `${numberOfHiddenForms} hidden forms`;
14457
14175
  return /* @__PURE__ */ jsxs(Flex$1, { ref, direction: "column", gap: "2", children: [
@@ -14545,13 +14263,16 @@ const FormSubmissionBrowserEntry = memo((props) => {
14545
14263
  const { submission, onSubmissionClick, compact, labelType, rowDecorator } = props;
14546
14264
  const currentUser = useAppSelector(selectCurrentUser);
14547
14265
  const createdBy = useAppSelector(selectUser("created_by" in submission ? submission.created_by : currentUser.id));
14548
- const dateToUse = submission.submitted_at;
14549
- const formattedDateTime = getLocalDateString(dateToUse);
14266
+ const dateToUse = getCreatedAtOrSubmittedAtDate(submission);
14267
+ const formattedDateTime = isToday(dateToUse) ? dateToUse.toLocaleTimeString([], {
14268
+ hour: "2-digit",
14269
+ minute: "2-digit"
14270
+ }) : getLocalDateString(dateToUse);
14550
14271
  const revision = useAppSelector(selectFormRevision(submission.form_revision));
14551
14272
  if (!revision) {
14552
14273
  throw new Error(`Could not find revision ${submission.form_revision} for submission ${submission.offline_id}.`);
14553
14274
  }
14554
- const latestRevisionNumber = (_a2 = useAppSelector(selectLatestFormRevisionOfForm(revision.form))) == null ? void 0 : _a2.revision;
14275
+ const latestRevisionNumber = (_a2 = useAppSelector(selectLatestFormRevision(revision.form))) == null ? void 0 : _a2.revision;
14555
14276
  const creatorProfileSrc = useFileSrc({
14556
14277
  file: (createdBy == null ? void 0 : createdBy.profile.file) ?? null,
14557
14278
  fileSha1: (createdBy == null ? void 0 : createdBy.profile.file_sha1) ?? null
@@ -14582,6 +14303,10 @@ const FormSubmissionBrowserEntry = memo((props) => {
14582
14303
  return row;
14583
14304
  });
14584
14305
  FormSubmissionBrowserEntry.displayName = "FormSubmissionBrowserEntry";
14306
+ const getCreatedAtOrSubmittedAtDate = (submission) => {
14307
+ const date = "created_at" in submission ? submission.created_at : submission.submitted_at;
14308
+ return new Date(date);
14309
+ };
14585
14310
  const FormSubmissionBrowser = memo((props) => {
14586
14311
  const {
14587
14312
  formId: formId2,
@@ -14595,10 +14320,10 @@ const FormSubmissionBrowser = memo((props) => {
14595
14320
  if (!!formId2 === !!propSubmissions) {
14596
14321
  throw new Error("Either formId or submissions must be provided, but not both.");
14597
14322
  }
14598
- const submissions = useAppSelector(propSubmissions ? () => propSubmissions : selectFormSubmissionsOfForm(formId2));
14323
+ const submissions = useAppSelector(propSubmissions ? () => propSubmissions : selectSubmissionsForForm(formId2));
14599
14324
  const sortedSubmissions = useMemo(
14600
14325
  () => submissions == null ? void 0 : submissions.sort((a, b) => {
14601
- return a.submitted_at.localeCompare(b.submitted_at);
14326
+ return getCreatedAtOrSubmittedAtDate(b).getTime() - getCreatedAtOrSubmittedAtDate(a).getTime();
14602
14327
  }),
14603
14328
  [submissions]
14604
14329
  );
@@ -15916,7 +15641,6 @@ export {
15916
15641
  VerificationCodeType,
15917
15642
  WorkspaceService,
15918
15643
  YELLOW,
15919
- _selectLatestFormRevision,
15920
15644
  _setLatestRetryTime,
15921
15645
  acceptProjectInvite,
15922
15646
  addActiveProjectFormSubmissionsCount,
@@ -15934,16 +15658,6 @@ export {
15934
15658
  addDocuments,
15935
15659
  addEmailDomain,
15936
15660
  addFavouriteProjectId,
15937
- addForm,
15938
- addFormRevision,
15939
- addFormRevisionAttachment,
15940
- addFormRevisionAttachments,
15941
- addFormRevisions,
15942
- addFormSubmission,
15943
- addFormSubmissionAttachment,
15944
- addFormSubmissionAttachments,
15945
- addFormSubmissions,
15946
- addForms,
15947
15661
  addIssue,
15948
15662
  addIssueAttachment,
15949
15663
  addIssueAttachments,
@@ -15964,6 +15678,13 @@ export {
15964
15678
  addStageCompletions,
15965
15679
  addStages,
15966
15680
  addToRecentIssues,
15681
+ addUserForm,
15682
+ addUserFormRevision,
15683
+ addUserFormRevisionAttachment,
15684
+ addUserFormRevisions,
15685
+ addUserFormSubmissionAttachment,
15686
+ addUserFormSubmissions,
15687
+ addUserForms,
15967
15688
  addUsers,
15968
15689
  addWorkspace,
15969
15690
  areArraysEqual,
@@ -15984,7 +15705,6 @@ export {
15984
15705
  componentStageSlice,
15985
15706
  componentTypeReducer,
15986
15707
  componentTypeSlice,
15987
- constructUploadedFilePayloads,
15988
15708
  coordinatesAreEqual,
15989
15709
  coordinatesToLiteral,
15990
15710
  coordinatesToPointGeometry,
@@ -15995,16 +15715,12 @@ export {
15995
15715
  defaultBadgeColor,
15996
15716
  defaultStore,
15997
15717
  deleteComponentType,
15998
- deleteForm,
15999
- deleteFormRevision,
16000
- deleteFormRevisionAttachment,
16001
- deleteFormRevisionAttachments,
16002
- deleteFormRevisions,
16003
- deleteFormSubmission,
16004
- deleteFormSubmissionAttachment,
16005
- deleteFormSubmissionAttachments,
16006
- deleteFormSubmissions,
16007
15718
  deleteProject,
15719
+ deleteUserForm,
15720
+ deleteUserFormRevision,
15721
+ deleteUserFormRevisions,
15722
+ deleteUserFormSubmission,
15723
+ deleteUserFormSubmissions,
16008
15724
  dequeue,
16009
15725
  deserialize,
16010
15726
  deserializeField,
@@ -16033,13 +15749,7 @@ export {
16033
15749
  fileSlice,
16034
15750
  fileToBlob,
16035
15751
  flipCoordinates,
16036
- formReducer,
16037
- formRevisionReducer,
16038
15752
  formRevisionToSchema,
16039
- formRevisionsSlice,
16040
- formSlice,
16041
- formSubmissionReducer,
16042
- formSubmissionSlice,
16043
15753
  index as forms,
16044
15754
  fullComponentMarkerSize,
16045
15755
  generateBadgeColors,
@@ -16167,8 +15877,6 @@ export {
16167
15877
  selectAttachmentsOfComponentTypeByType,
16168
15878
  selectAttachmentsOfDocument,
16169
15879
  selectAttachmentsOfDocumentByType,
16170
- selectAttachmentsOfFormRevision,
16171
- selectAttachmentsOfFormSubmission,
16172
15880
  selectAttachmentsOfIssue,
16173
15881
  selectAttachmentsOfIssueByType,
16174
15882
  selectAttachmentsOfProject,
@@ -16184,11 +15892,11 @@ export {
16184
15892
  selectCompletedStageIdsForComponent,
16185
15893
  selectCompletedStages,
16186
15894
  selectComponent,
16187
- selectComponentAttachment,
16188
15895
  selectComponentAttachmentMapping,
15896
+ selectComponentSubmissionMapping,
16189
15897
  selectComponentType,
16190
- selectComponentTypeAttachment,
16191
15898
  selectComponentTypeAttachmentMapping,
15899
+ selectComponentTypeForm,
16192
15900
  selectComponentTypeFromComponent,
16193
15901
  selectComponentTypeFromComponents,
16194
15902
  selectComponentTypeStagesMapping,
@@ -16204,7 +15912,6 @@ export {
16204
15912
  selectCurrentUser,
16205
15913
  selectDeletedRequests,
16206
15914
  selectDocument,
16207
- selectDocumentAttachment,
16208
15915
  selectDocumentAttachmentMapping,
16209
15916
  selectDocuments,
16210
15917
  selectDocumentsMapping,
@@ -16218,24 +15925,8 @@ export {
16218
15925
  selectExpandedSections,
16219
15926
  selectFavouriteProjects,
16220
15927
  selectFileAttachmentsOfIssue,
16221
- selectFilteredForms,
16222
- selectForm,
16223
- selectFormMapping,
16224
- selectFormOfComponentType,
15928
+ selectFilteredUserForms,
16225
15929
  selectFormRevision,
16226
- selectFormRevisionMapping,
16227
- selectFormRevisions,
16228
- selectFormRevisionsOfForm,
16229
- selectFormSubmission,
16230
- selectFormSubmissionAttachmentsMapping,
16231
- selectFormSubmissions,
16232
- selectFormSubmissionsByComponents,
16233
- selectFormSubmissionsMapping,
16234
- selectFormSubmissionsOfComponent,
16235
- selectFormSubmissionsOfForm,
16236
- selectFormSubmissionsOfIssue,
16237
- selectFormsCount,
16238
- selectGeneralFormCount,
16239
15930
  selectHiddenCategoryCount,
16240
15931
  selectHiddenComponentTypeIds,
16241
15932
  selectIsFetchingInitialData,
@@ -16243,17 +15934,16 @@ export {
16243
15934
  selectIsLoading,
16244
15935
  selectIsLoggedIn,
16245
15936
  selectIssue,
16246
- selectIssueAttachment,
16247
15937
  selectIssueAttachmentMapping,
16248
15938
  selectIssueAttachments,
16249
15939
  selectIssueMapping,
16250
15940
  selectIssueUpdateMapping,
16251
15941
  selectIssueUpdatesOfIssue,
16252
15942
  selectIssues,
16253
- selectLatestFormRevisionByForm,
16254
- selectLatestFormRevisionOfForm,
16255
- selectLatestFormRevisionsOfComponentTypes,
15943
+ selectLatestFormRevision,
16256
15944
  selectLatestRetryTime,
15945
+ selectLatestRevisionByFormId,
15946
+ selectLatestRevisionsFromComponentTypeIds,
16257
15947
  selectLicense,
16258
15948
  selectLicenseForProject,
16259
15949
  selectLicenses,
@@ -16262,6 +15952,8 @@ export {
16262
15952
  selectMapStyle,
16263
15953
  selectNumberOfComponentTypesMatchingCaseInsensitiveName,
16264
15954
  selectNumberOfComponentsOfComponentType,
15955
+ selectNumberOfGeneralUserForms,
15956
+ selectNumberOfUserForms,
16265
15957
  selectOrganization,
16266
15958
  selectOrganizationAccess,
16267
15959
  selectOrganizationAccessForUser,
@@ -16289,6 +15981,8 @@ export {
16289
15981
  selectRecentIssuesAsSearchResults,
16290
15982
  selectRecentProjects,
16291
15983
  selectRehydrated,
15984
+ selectRevisionAttachments,
15985
+ selectRevisionsForForm,
16292
15986
  selectRootDocuments,
16293
15987
  selectShowTooltips,
16294
15988
  selectSortedEmailDomains,
@@ -16303,10 +15997,16 @@ export {
16303
15997
  selectStagesFromComponentType,
16304
15998
  selectStagesFromComponentTypeIds,
16305
15999
  selectStagesFromStageIds,
16000
+ selectSubmissionAttachments,
16001
+ selectSubmissionsForComponent,
16002
+ selectSubmissionsForForm,
16003
+ selectSubmissionsForIssue,
16306
16004
  selectUploadUrl,
16307
16005
  selectUsedColors,
16308
16006
  selectUser,
16309
- selectUserFormRevisionAttachmentsMapping,
16007
+ selectUserForm,
16008
+ selectUserFormMapping,
16009
+ selectUserFormSubmission,
16310
16010
  selectUsersAsMapping,
16311
16011
  selectVisibleStatuses,
16312
16012
  selectVisibleUserIds,
@@ -16333,13 +16033,6 @@ export {
16333
16033
  setEnableClustering,
16334
16034
  setEnableDuplicateIssues,
16335
16035
  setEnablePlacementMode,
16336
- setFormRevision,
16337
- setFormRevisionAttachments,
16338
- setFormRevisions,
16339
- setFormSubmission,
16340
- setFormSubmissionAttachments,
16341
- setFormSubmissions,
16342
- setForms,
16343
16036
  setIsFetchingInitialData,
16344
16037
  setIsImportingProjectFile,
16345
16038
  setIsLoading,
@@ -16364,6 +16057,9 @@ export {
16364
16057
  setTokens,
16365
16058
  setTourStep,
16366
16059
  setUploadUrl,
16060
+ setUserFormRevisionAttachments,
16061
+ setUserFormSubmissionAttachments,
16062
+ setUserFormSubmissions,
16367
16063
  setUsers,
16368
16064
  setVisibleStatuses,
16369
16065
  setVisibleUserIds,
@@ -16388,13 +16084,11 @@ export {
16388
16084
  updateComponentTypeAttachment,
16389
16085
  updateDocumentAttachment,
16390
16086
  updateDocuments,
16391
- updateFormSubmission,
16392
- updateFormSubmissionAttachments,
16393
- updateFormSubmissions,
16394
16087
  updateIssue,
16395
16088
  updateIssueAttachment,
16396
16089
  updateLicense,
16397
16090
  updateOrCreateProject,
16091
+ updateOrCreateUserFormSubmission,
16398
16092
  updateOrganizationAccess,
16399
16093
  updateProjectAccess,
16400
16094
  updateProjectAttachment,
@@ -16408,6 +16102,8 @@ export {
16408
16102
  useFormikInput,
16409
16103
  useMemoCompare,
16410
16104
  useSDK,
16105
+ userFormReducer,
16106
+ userFormSlice,
16411
16107
  userReducer,
16412
16108
  userSlice,
16413
16109
  valueIsFile,