@overmap-ai/core 1.0.50-fix-error-messaging.0 → 1.0.51-bulk-form-submission.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.
@@ -677,15 +677,15 @@ const wrapMigration = (migrator) => (state) => {
677
677
  };
678
678
  const migrations = [initialVersioning, signOut, signOut, createOutboxState];
679
679
  const manifest = Object.fromEntries(migrations.map((migration2, i) => [i, wrapMigration(migration2)]));
680
- const initialState$n = {
680
+ const initialState$p = {
681
681
  accessToken: "",
682
682
  refreshToken: "",
683
683
  isLoggedIn: false
684
684
  };
685
685
  const authSlice = createSlice({
686
686
  name: "auth",
687
- initialState: initialState$n,
688
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$n)),
687
+ initialState: initialState$p,
688
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$p)),
689
689
  reducers: {
690
690
  setTokens: (state, action) => {
691
691
  state.accessToken = action.payload.accessToken;
@@ -850,6 +850,19 @@ function downloadInMemoryFile(filename, text) {
850
850
  element.click();
851
851
  document.body.removeChild(element);
852
852
  }
853
+ const constructUploadedFilePayloads = async (files) => {
854
+ const filePayloads = {};
855
+ for (const file of files) {
856
+ const sha1 = await hashFile(file);
857
+ filePayloads[sha1] = {
858
+ sha1,
859
+ extension: file.name.split(".").pop() || "",
860
+ file_type: file.type,
861
+ size: file.size
862
+ };
863
+ }
864
+ return Object.values(filePayloads);
865
+ };
853
866
  const fileToBlob = async (dataUrl) => {
854
867
  return (await fetch(dataUrl)).blob();
855
868
  };
@@ -1416,7 +1429,7 @@ const getLocalRelativeDateString = memoize((date, min, max) => {
1416
1429
  return getLocalDateString(date);
1417
1430
  return relative.format(days, "days");
1418
1431
  });
1419
- const initialState$m = {
1432
+ const initialState$o = {
1420
1433
  categories: {},
1421
1434
  usedCategoryColors: [],
1422
1435
  categoryVisibility: {
@@ -1426,8 +1439,8 @@ const initialState$m = {
1426
1439
  };
1427
1440
  const categorySlice = createSlice({
1428
1441
  name: "categories",
1429
- initialState: initialState$m,
1430
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$m)),
1442
+ initialState: initialState$o,
1443
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$o)),
1431
1444
  reducers: {
1432
1445
  setCategories: (state, action) => {
1433
1446
  if (!Array.isArray(action.payload))
@@ -1561,6 +1574,7 @@ const selectHiddenCategoryCount = (state) => {
1561
1574
  };
1562
1575
  const categoryReducer = categorySlice.reducer;
1563
1576
  function setAttachments(state, action) {
1577
+ state.attachments = {};
1564
1578
  for (const attachment of action.payload) {
1565
1579
  state.attachments[attachment.offline_id] = attachment;
1566
1580
  }
@@ -1595,14 +1609,14 @@ function removeAttachments(state, action) {
1595
1609
  delete state.attachments[attachmentId];
1596
1610
  }
1597
1611
  }
1598
- const initialState$l = {
1612
+ const initialState$n = {
1599
1613
  components: {},
1600
1614
  attachments: {}
1601
1615
  };
1602
1616
  const componentSlice = createSlice({
1603
1617
  name: "components",
1604
- initialState: initialState$l,
1605
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$l)),
1618
+ initialState: initialState$n,
1619
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$n)),
1606
1620
  reducers: {
1607
1621
  addComponent: (state, action) => {
1608
1622
  state.components[action.payload.offline_id] = action.payload;
@@ -1715,6 +1729,9 @@ const selectAllComponentAttachments = createSelector(
1715
1729
  [selectComponentAttachmentMapping],
1716
1730
  (mapping) => Object.values(mapping)
1717
1731
  );
1732
+ const selectComponentAttachment = (attachmentId) => (state) => {
1733
+ return state.componentReducer.attachments[attachmentId];
1734
+ };
1718
1735
  const selectAttachmentsOfComponent = restructureCreateSelectorWithArgs(
1719
1736
  createSelector(
1720
1737
  [selectAllComponentAttachments, (_state, componentId) => componentId],
@@ -1755,13 +1772,13 @@ const {
1755
1772
  removeAllComponentsOfType
1756
1773
  } = componentSlice.actions;
1757
1774
  const componentReducer = componentSlice.reducer;
1758
- const initialState$k = {
1775
+ const initialState$m = {
1759
1776
  completionsByComponentId: {}
1760
1777
  };
1761
1778
  const componentStageCompletionSlice = createSlice({
1762
1779
  name: "componentStageCompletions",
1763
- initialState: initialState$k,
1764
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$k)),
1780
+ initialState: initialState$m,
1781
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$m)),
1765
1782
  reducers: {
1766
1783
  addStageCompletion: (state, action) => {
1767
1784
  let stageToCompletionDateMapping = state.completionsByComponentId[action.payload.component];
@@ -1812,13 +1829,13 @@ const selectCompletedStageIdsForComponent = (component) => (state) => {
1812
1829
  return Object.keys(state.componentStageCompletionReducer.completionsByComponentId[component.offline_id] ?? {});
1813
1830
  };
1814
1831
  const componentStageCompletionReducer = componentStageCompletionSlice.reducer;
1815
- const initialState$j = {
1832
+ const initialState$l = {
1816
1833
  stages: {}
1817
1834
  };
1818
1835
  const componentStageSlice = createSlice({
1819
1836
  name: "componentStages",
1820
- initialState: initialState$j,
1821
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$j)),
1837
+ initialState: initialState$l,
1838
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$l)),
1822
1839
  reducers: {
1823
1840
  addStages: (state, action) => {
1824
1841
  Object.assign(state.stages, toOfflineIdRecord(action.payload));
@@ -1928,15 +1945,15 @@ const selectStageFormIdsFromStageIds = restructureCreateSelectorWithArgs(
1928
1945
  );
1929
1946
  const { addStages, updateStages, removeStages, linkStageToForm, unlinkStageToForm } = componentStageSlice.actions;
1930
1947
  const componentStageReducer = componentStageSlice.reducer;
1931
- const initialState$i = {
1948
+ const initialState$k = {
1932
1949
  componentTypes: {},
1933
1950
  hiddenComponentTypeIds: {},
1934
1951
  attachments: {}
1935
1952
  };
1936
1953
  const componentTypeSlice = createSlice({
1937
1954
  name: "componentTypes",
1938
- initialState: initialState$i,
1939
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$i)),
1955
+ initialState: initialState$k,
1956
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$k)),
1940
1957
  reducers: {
1941
1958
  addComponentType: (state, action) => {
1942
1959
  state.componentTypes[action.payload.offline_id] = action.payload;
@@ -2004,6 +2021,9 @@ const selectAllComponentTypeAttachments = createSelector(
2004
2021
  [selectComponentTypeAttachmentMapping],
2005
2022
  (mapping) => Object.values(mapping)
2006
2023
  );
2024
+ const selectComponentTypeAttachment = (attachmentId) => (state) => {
2025
+ return state.componentTypeReducer.attachments[attachmentId];
2026
+ };
2007
2027
  const selectAttachmentsOfComponentType = restructureCreateSelectorWithArgs(
2008
2028
  createSelector(
2009
2029
  [selectAllComponentTypeAttachments, (_state, componentTypeId) => componentTypeId],
@@ -2044,13 +2064,13 @@ const {
2044
2064
  deleteComponentType
2045
2065
  } = componentTypeSlice.actions;
2046
2066
  const componentTypeReducer = componentTypeSlice.reducer;
2047
- const initialState$h = {
2067
+ const initialState$j = {
2048
2068
  workspaces: {},
2049
2069
  activeWorkspaceId: null
2050
2070
  };
2051
2071
  const workspaceSlice = createSlice({
2052
2072
  name: "workspace",
2053
- initialState: initialState$h,
2073
+ initialState: initialState$j,
2054
2074
  // The `reducers` field lets us define reducers and generate associated actions
2055
2075
  reducers: {
2056
2076
  setWorkspaces: (state, action) => {
@@ -2107,7 +2127,7 @@ const selectPermittedWorkspaceIds = createSelector(
2107
2127
  );
2108
2128
  const workspaceReducer = workspaceSlice.reducer;
2109
2129
  const maxRecentIssues = 10;
2110
- const initialState$g = {
2130
+ const initialState$i = {
2111
2131
  issues: {},
2112
2132
  attachments: {},
2113
2133
  comments: {},
@@ -2119,9 +2139,9 @@ const initialState$g = {
2119
2139
  };
2120
2140
  const issueSlice = createSlice({
2121
2141
  name: "issues",
2122
- initialState: initialState$g,
2142
+ initialState: initialState$i,
2123
2143
  extraReducers: (builder) => builder.addCase("RESET", (state) => {
2124
- Object.assign(state, initialState$g);
2144
+ Object.assign(state, initialState$i);
2125
2145
  }),
2126
2146
  reducers: {
2127
2147
  setIssues: (state, action) => {
@@ -2398,6 +2418,9 @@ const selectAttachmentsOfIssue = restructureCreateSelectorWithArgs(
2398
2418
  }
2399
2419
  )
2400
2420
  );
2421
+ const selectIssueAttachment = (attachmentId) => (root) => {
2422
+ return root.issueReducer.attachments[attachmentId];
2423
+ };
2401
2424
  const selectAttachmentsOfIssueByType = restructureCreateSelectorWithArgs(
2402
2425
  createSelector(
2403
2426
  [selectIssueAttachments, (_state, issueId) => issueId],
@@ -2526,15 +2549,15 @@ const selectRecentIssuesAsSearchResults = createSelector(
2526
2549
  }
2527
2550
  );
2528
2551
  const issueReducer = issueSlice.reducer;
2529
- const initialState$f = {
2552
+ const initialState$h = {
2530
2553
  s3Urls: {}
2531
2554
  };
2532
2555
  const msPerHour = 1e3 * 60 * 60;
2533
2556
  const msPerWeek = msPerHour * 24 * 7;
2534
2557
  const fileSlice = createSlice({
2535
2558
  name: "file",
2536
- initialState: initialState$f,
2537
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$f)),
2559
+ initialState: initialState$h,
2560
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$h)),
2538
2561
  reducers: {
2539
2562
  setUploadUrl: (state, action) => {
2540
2563
  const { url, fields, sha1 } = action.payload;
@@ -2561,7 +2584,7 @@ const selectUploadUrl = (sha1) => (state) => {
2561
2584
  return url;
2562
2585
  };
2563
2586
  const fileReducer = fileSlice.reducer;
2564
- const initialState$e = {
2587
+ const initialState$g = {
2565
2588
  // TODO: Change first MapStyle.SATELLITE to MaptStyle.None when project creation map is fixed
2566
2589
  mapStyle: MapStyle.SATELLITE,
2567
2590
  showTooltips: false,
@@ -2569,8 +2592,8 @@ const initialState$e = {
2569
2592
  };
2570
2593
  const mapSlice = createSlice({
2571
2594
  name: "map",
2572
- initialState: initialState$e,
2573
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$e)),
2595
+ initialState: initialState$g,
2596
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$g)),
2574
2597
  reducers: {
2575
2598
  setMapStyle: (state, action) => {
2576
2599
  state.mapStyle = action.payload;
@@ -2639,7 +2662,7 @@ var LicenseStatus = /* @__PURE__ */ ((LicenseStatus2) => {
2639
2662
  LicenseStatus2[LicenseStatus2["PAST_DUE"] = 8] = "PAST_DUE";
2640
2663
  return LicenseStatus2;
2641
2664
  })(LicenseStatus || {});
2642
- const initialState$d = {
2665
+ const initialState$f = {
2643
2666
  users: {},
2644
2667
  currentUser: {
2645
2668
  id: 0,
@@ -2650,8 +2673,8 @@ const initialState$d = {
2650
2673
  };
2651
2674
  const userSlice = createSlice({
2652
2675
  name: "users",
2653
- initialState: initialState$d,
2654
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$d)),
2676
+ initialState: initialState$f,
2677
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$f)),
2655
2678
  reducers: {
2656
2679
  setUsers: (state, action) => {
2657
2680
  const usersMapping = {};
@@ -2713,13 +2736,13 @@ const selectUser = (userId) => (state) => {
2713
2736
  const selectUsersAsMapping = (state) => state.userReducer.users;
2714
2737
  const selectFavouriteProjects = (state) => state.userReducer.currentUser.profile.favourite_project_ids;
2715
2738
  const userReducer = userSlice.reducer;
2716
- const initialState$c = {
2739
+ const initialState$e = {
2717
2740
  organizationAccesses: {}
2718
2741
  };
2719
2742
  const organizationAccessSlice = createSlice({
2720
2743
  name: "organizationAccess",
2721
- initialState: initialState$c,
2722
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$c)),
2744
+ initialState: initialState$e,
2745
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$e)),
2723
2746
  reducers: {
2724
2747
  setOrganizationAccesses: (state, action) => {
2725
2748
  if (!Array.isArray(action.payload))
@@ -2782,13 +2805,13 @@ const selectOrganizationAccessUserMapping = (state) => {
2782
2805
  return organizationAccesses;
2783
2806
  };
2784
2807
  const organizationAccessReducer = organizationAccessSlice.reducer;
2785
- const initialState$b = {
2808
+ const initialState$d = {
2786
2809
  licenses: {}
2787
2810
  };
2788
2811
  const licenseSlice = createSlice({
2789
2812
  name: "license",
2790
- initialState: initialState$b,
2791
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$b)),
2813
+ initialState: initialState$d,
2814
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$d)),
2792
2815
  reducers: {
2793
2816
  setLicenses: (state, action) => {
2794
2817
  if (!Array.isArray(action.payload))
@@ -2833,13 +2856,13 @@ const selectLicensesForProjectsMapping = createSelector(
2833
2856
  (licenses) => Object.values(licenses).filter((license) => license.project).reduce((accum, license) => ({ ...accum, [license.project]: license }), {})
2834
2857
  );
2835
2858
  const licenseReducer = licenseSlice.reducer;
2836
- const initialState$a = {
2859
+ const initialState$c = {
2837
2860
  projectAccesses: {}
2838
2861
  };
2839
2862
  const projectAccessSlice = createSlice({
2840
2863
  name: "projectAccess",
2841
- initialState: initialState$a,
2842
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$a)),
2864
+ initialState: initialState$c,
2865
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$c)),
2843
2866
  reducers: {
2844
2867
  setProjectAccesses: (state, action) => {
2845
2868
  if (!Array.isArray(action.payload))
@@ -2907,7 +2930,7 @@ const selectProjectAccessUserMapping = (state) => {
2907
2930
  return projectAccesses;
2908
2931
  };
2909
2932
  const projectAccessReducer = projectAccessSlice.reducer;
2910
- const initialState$9 = {
2933
+ const initialState$b = {
2911
2934
  projects: {},
2912
2935
  activeProjectId: null,
2913
2936
  recentProjectIds: [],
@@ -2917,7 +2940,7 @@ const initialState$9 = {
2917
2940
  };
2918
2941
  const projectSlice = createSlice({
2919
2942
  name: "projects",
2920
- initialState: initialState$9,
2943
+ initialState: initialState$b,
2921
2944
  reducers: {
2922
2945
  setProjects: (state, action) => {
2923
2946
  const projectsMap = {};
@@ -3104,14 +3127,14 @@ const selectAttachmentsOfProjectByType = restructureCreateSelectorWithArgs(
3104
3127
  }
3105
3128
  )
3106
3129
  );
3107
- const initialState$8 = {
3130
+ const initialState$a = {
3108
3131
  organizations: {},
3109
3132
  activeOrganizationId: null
3110
3133
  };
3111
3134
  const organizationSlice = createSlice({
3112
3135
  name: "organizations",
3113
- initialState: initialState$8,
3114
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$8)),
3136
+ initialState: initialState$a,
3137
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$a)),
3115
3138
  reducers: {
3116
3139
  setOrganizations: (state, action) => {
3117
3140
  for (const org of action.payload) {
@@ -3230,14 +3253,14 @@ const createOfflineAction = (request2, baseUrl) => {
3230
3253
  }
3231
3254
  };
3232
3255
  };
3233
- const initialState$7 = {
3256
+ const initialState$9 = {
3234
3257
  deletedRequests: [],
3235
3258
  latestRetryTime: 0
3236
3259
  };
3237
3260
  const outboxSlice = createSlice({
3238
3261
  name: "outbox",
3239
- initialState: initialState$7,
3240
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$7)),
3262
+ initialState: initialState$9,
3263
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$9)),
3241
3264
  reducers: {
3242
3265
  // enqueueActions is a reducer that does nothing but enqueue API request to the Redux Offline outbox
3243
3266
  // Whenever an issue is being created, a reducer addIssue() is responsible for adding it to the offline store
@@ -3269,7 +3292,7 @@ const selectDeletedRequests = (state) => state.outboxReducer.deletedRequests;
3269
3292
  const selectLatestRetryTime = (state) => state.outboxReducer.latestRetryTime;
3270
3293
  const { enqueueRequest, markForDeletion, markAsDeleted, _setLatestRetryTime } = outboxSlice.actions;
3271
3294
  const outboxReducer = outboxSlice.reducer;
3272
- const initialState$6 = {
3295
+ const initialState$8 = {
3273
3296
  projectFiles: {},
3274
3297
  activeProjectFileId: null,
3275
3298
  isImportingProjectFile: false,
@@ -3277,8 +3300,8 @@ const initialState$6 = {
3277
3300
  };
3278
3301
  const projectFileSlice = createSlice({
3279
3302
  name: "projectFiles",
3280
- initialState: initialState$6,
3281
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$6)),
3303
+ initialState: initialState$8,
3304
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$8)),
3282
3305
  reducers: {
3283
3306
  addOrReplaceProjectFiles: (state, action) => {
3284
3307
  for (let fileObj of action.payload) {
@@ -3379,12 +3402,12 @@ const selectProjectFiles = createSelector(
3379
3402
  const selectActiveProjectFileId = (state) => state.projectFileReducer.activeProjectFileId;
3380
3403
  const selectIsImportingProjectFile = (state) => state.projectFileReducer.isImportingProjectFile;
3381
3404
  const projectFileReducer = projectFileSlice.reducer;
3382
- const initialState$5 = {
3405
+ const initialState$7 = {
3383
3406
  isRehydrated: false
3384
3407
  };
3385
3408
  const rehydratedSlice = createSlice({
3386
3409
  name: "rehydrated",
3387
- initialState: initialState$5,
3410
+ initialState: initialState$7,
3388
3411
  // The `reducers` field lets us define reducers and generate associated actions
3389
3412
  reducers: {
3390
3413
  setRehydrated: (state, action) => {
@@ -3394,7 +3417,7 @@ const rehydratedSlice = createSlice({
3394
3417
  });
3395
3418
  const selectRehydrated = (state) => state.rehydratedReducer.isRehydrated;
3396
3419
  const rehydratedReducer = rehydratedSlice.reducer;
3397
- const initialState$4 = {
3420
+ const initialState$6 = {
3398
3421
  useIssueTemplate: false,
3399
3422
  placementMode: false,
3400
3423
  enableClustering: false,
@@ -3411,8 +3434,8 @@ const initialState$4 = {
3411
3434
  };
3412
3435
  const settingSlice = createSlice({
3413
3436
  name: "settings",
3414
- initialState: initialState$4,
3415
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$4)),
3437
+ initialState: initialState$6,
3438
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$6)),
3416
3439
  reducers: {
3417
3440
  setEnableDuplicateIssues: (state, action) => {
3418
3441
  state.useIssueTemplate = action.payload;
@@ -3458,146 +3481,248 @@ const selectAppearance = (state) => state.settingReducer.appearance;
3458
3481
  const settingReducer = settingSlice.reducer;
3459
3482
  const selectIsFetchingInitialData = (state) => state.settingReducer.isFetchingInitialData;
3460
3483
  const selectIsLoading = (state) => state.settingReducer.isLoading;
3461
- const LATEST_REVISION_CACHE = {};
3462
- function considerCachingRevision(revision, formId2, preferPending = false) {
3484
+ const LATEST_FORM_REVISION_CACHE = {};
3485
+ function considerCachingFormRevision(formRevision, formId2, preferPending = false) {
3463
3486
  var _a2;
3464
- if (!revision) {
3487
+ if (!formRevision) {
3465
3488
  if (!formId2) {
3466
- throw new Error("If revision is null, formId is required.");
3489
+ throw new Error("If form revision is null, formId is required.");
3467
3490
  }
3468
- const currentLatestRevision = getLatestRevisionFromCache(formId2);
3469
- if (currentLatestRevision)
3491
+ const currentLatestFormRevision = getLatestFormRevisionFromCache(formId2);
3492
+ if (currentLatestFormRevision)
3470
3493
  return;
3471
- LATEST_REVISION_CACHE[formId2] = null;
3494
+ LATEST_FORM_REVISION_CACHE[formId2] = null;
3472
3495
  return;
3473
3496
  }
3474
- if (revision.revision === "Pending") {
3497
+ if (formRevision.revision === "Pending") {
3475
3498
  if (preferPending) {
3476
- LATEST_REVISION_CACHE[revision.form] = revision;
3499
+ LATEST_FORM_REVISION_CACHE[formRevision.form] = formRevision;
3477
3500
  }
3478
3501
  return;
3479
3502
  }
3480
- const cachedRevision = (_a2 = LATEST_REVISION_CACHE[revision.form]) == null ? void 0 : _a2.revision;
3481
- if (revision.revision > (typeof cachedRevision === "number" ? cachedRevision : -1)) {
3482
- LATEST_REVISION_CACHE[revision.form] = revision;
3503
+ const cachedFormRevision = (_a2 = LATEST_FORM_REVISION_CACHE[formRevision.form]) == null ? void 0 : _a2.revision;
3504
+ if (formRevision.revision > (typeof cachedFormRevision === "number" ? cachedFormRevision : -1)) {
3505
+ LATEST_FORM_REVISION_CACHE[formRevision.form] = formRevision;
3483
3506
  }
3484
3507
  }
3485
- function getLatestRevisionFromCache(formId2) {
3486
- return LATEST_REVISION_CACHE[formId2];
3508
+ function getLatestFormRevisionFromCache(formId2) {
3509
+ return LATEST_FORM_REVISION_CACHE[formId2];
3487
3510
  }
3488
- const initialState$3 = {
3489
- userForms: {},
3490
- revisions: {},
3491
- submissions: {},
3492
- submissionAttachments: {},
3493
- revisionAttachments: {}
3494
- };
3495
- const userFormSlice = createSlice({
3496
- name: "userForms",
3497
- initialState: initialState$3,
3498
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$3)),
3511
+ const initialState$5 = {
3512
+ formRevisions: {},
3513
+ attachments: {}
3514
+ };
3515
+ const formRevisionsSlice = createSlice({
3516
+ name: "formRevisions",
3517
+ initialState: initialState$5,
3518
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$5)),
3499
3519
  reducers: {
3500
- setUserForms: (state, action) => {
3501
- state.userForms = {};
3502
- action.payload.forEach((userForm) => {
3503
- state.userForms[userForm.offline_id] = userForm;
3504
- });
3505
- },
3506
- addUserForm: (state, action) => {
3507
- state.userForms[action.payload.offline_id] = action.payload;
3508
- },
3509
- addUserForms: (state, action) => {
3510
- action.payload.forEach((userForm) => {
3511
- state.userForms[userForm.offline_id] = userForm;
3512
- });
3520
+ // revision related actions
3521
+ setFormRevision: (state, action) => {
3522
+ state.formRevisions[action.payload.offline_id] = action.payload;
3523
+ considerCachingFormRevision(action.payload);
3513
3524
  },
3514
- addUserFormRevisions: (state, action) => {
3515
- action.payload.forEach((userFormRevision) => {
3516
- state.revisions[userFormRevision.offline_id] = userFormRevision;
3517
- considerCachingRevision(userFormRevision);
3518
- });
3519
- },
3520
- addUserFormRevision: (state, action) => {
3521
- state.revisions[action.payload.offline_id] = action.payload;
3522
- considerCachingRevision(action.payload);
3525
+ setFormRevisions: (state, action) => {
3526
+ state.formRevisions = {};
3527
+ for (const revision of action.payload) {
3528
+ state.formRevisions[revision.offline_id] = revision;
3529
+ considerCachingFormRevision(revision);
3530
+ }
3523
3531
  },
3524
- deleteUserFormRevision: (state, action) => {
3525
- delete state.revisions[action.payload];
3526
- delete LATEST_REVISION_CACHE[action.payload];
3532
+ addFormRevision: (state, action) => {
3533
+ if (state.formRevisions[action.payload.offline_id] !== void 0) {
3534
+ throw new Error(`Revision with offline_id ${action.payload.offline_id} already exists`);
3535
+ }
3536
+ state.formRevisions[action.payload.offline_id] = action.payload;
3537
+ considerCachingFormRevision(action.payload);
3527
3538
  },
3528
- deleteUserFormRevisions: (state, action) => {
3539
+ // TODO: @Audiopolis / Magnus - do we want to standardize using PayloadAction?
3540
+ addFormRevisions: (state, action) => {
3529
3541
  for (const userFormRevision of action.payload) {
3530
- delete state.revisions[userFormRevision.offline_id];
3531
- delete LATEST_REVISION_CACHE[userFormRevision.offline_id];
3542
+ if (state.formRevisions[userFormRevision.offline_id] !== void 0) {
3543
+ throw new Error(`Revision with offline_id ${userFormRevision.offline_id} already exists`);
3544
+ }
3545
+ }
3546
+ for (const userFormRevision of action.payload) {
3547
+ state.formRevisions[userFormRevision.offline_id] = userFormRevision;
3548
+ considerCachingFormRevision(userFormRevision);
3532
3549
  }
3533
3550
  },
3534
- updateOrCreateUserFormSubmission: (state, action) => {
3535
- state.submissions[action.payload.offline_id] = action.payload;
3536
- },
3537
- addUserFormSubmissionAttachment: (state, action) => {
3538
- const submissionId = action.payload.submission;
3539
- const submissionAttachments = state.submissionAttachments[submissionId];
3540
- if (submissionAttachments) {
3541
- submissionAttachments.push(action.payload);
3542
- } else {
3543
- state.submissionAttachments[submissionId] = [action.payload];
3551
+ // UserFormRevisions do not get updated
3552
+ deleteFormRevision: (state, action) => {
3553
+ if (state.formRevisions[action.payload] === void 0) {
3554
+ throw new Error(`Revision with offline_id ${action.payload} does not exist`);
3544
3555
  }
3556
+ delete state.formRevisions[action.payload];
3557
+ delete LATEST_FORM_REVISION_CACHE[action.payload];
3545
3558
  },
3546
- addUserFormRevisionAttachment: (state, action) => {
3547
- const revisionId = action.payload.revision;
3548
- const revisionAttachments = state.revisionAttachments[revisionId];
3549
- if (revisionAttachments) {
3550
- revisionAttachments.push(action.payload);
3551
- } else {
3552
- state.revisionAttachments[revisionId] = [action.payload];
3559
+ deleteFormRevisions: (state, action) => {
3560
+ for (const offlineId of action.payload) {
3561
+ if (state.formRevisions[offlineId] === void 0) {
3562
+ throw new Error(`Revision with offline_id ${offlineId} does not exist`);
3563
+ }
3564
+ }
3565
+ for (const offlineId of action.payload) {
3566
+ delete state.formRevisions[offlineId];
3567
+ delete LATEST_FORM_REVISION_CACHE[offlineId];
3553
3568
  }
3554
3569
  },
3555
- setUserFormSubmissionAttachments: (state, action) => {
3556
- state.submissionAttachments = {};
3570
+ // attachment related actions
3571
+ setFormRevisionAttachments: (state, action) => {
3572
+ state.attachments = {};
3557
3573
  for (const attachment of action.payload) {
3558
- const submissionId = attachment.submission;
3559
- const submissionAttachments = state.submissionAttachments[submissionId];
3560
- if (submissionAttachments) {
3561
- submissionAttachments.push(attachment);
3562
- } else {
3563
- state.submissionAttachments[submissionId] = [attachment];
3564
- }
3574
+ state.attachments[attachment.offline_id] = attachment;
3575
+ }
3576
+ },
3577
+ addFormRevisionAttachment: (state, action) => {
3578
+ if (state.attachments[action.payload.offline_id] !== void 0) {
3579
+ throw new Error(`Attachment with offline_id ${action.payload.offline_id} already exists`);
3565
3580
  }
3581
+ state.attachments[action.payload.offline_id] = action.payload;
3566
3582
  },
3567
- setUserFormRevisionAttachments: (state, action) => {
3568
- state.revisionAttachments = {};
3583
+ addFormRevisionAttachments: (state, action) => {
3569
3584
  for (const attachment of action.payload) {
3570
- const revisionId = attachment.revision;
3571
- const revisionAttachments = state.revisionAttachments[revisionId];
3572
- if (revisionAttachments) {
3573
- revisionAttachments.push(attachment);
3574
- } else {
3575
- state.revisionAttachments[revisionId] = [attachment];
3585
+ if (state.attachments[attachment.offline_id] !== void 0) {
3586
+ throw new Error(`Attachment with offline_id ${attachment.offline_id} already exists`);
3576
3587
  }
3577
3588
  }
3589
+ for (const attachment of action.payload) {
3590
+ state.attachments[attachment.offline_id] = attachment;
3591
+ }
3578
3592
  },
3579
- deleteUserFormSubmission: (state, action) => {
3580
- delete state.submissions[action.payload];
3581
- },
3582
- deleteUserFormSubmissions: (state, action) => {
3583
- for (const userFormSubmission of action.payload) {
3584
- delete state.submissions[userFormSubmission.offline_id];
3593
+ deleteFormRevisionAttachment: (state, action) => {
3594
+ if (state.attachments[action.payload] === void 0) {
3595
+ throw new Error(`Attachment with offline_id ${action.payload} does not exist`);
3585
3596
  }
3597
+ delete state.attachments[action.payload];
3586
3598
  },
3587
- addUserFormSubmissions: (state, action) => {
3588
- for (const submission of action.payload) {
3589
- state.submissions[submission.offline_id] = submission;
3599
+ deleteFormRevisionAttachments: (state, action) => {
3600
+ for (const offlineId of action.payload) {
3601
+ if (state.attachments[offlineId] === void 0) {
3602
+ throw new Error(`Attachment with offline_id ${offlineId} does not exist`);
3603
+ }
3604
+ }
3605
+ for (const offlineId of action.payload) {
3606
+ delete state.attachments[offlineId];
3607
+ }
3608
+ }
3609
+ }
3610
+ });
3611
+ const {
3612
+ setFormRevision,
3613
+ setFormRevisions,
3614
+ addFormRevision,
3615
+ addFormRevisions,
3616
+ deleteFormRevision,
3617
+ deleteFormRevisions,
3618
+ setFormRevisionAttachments,
3619
+ addFormRevisionAttachment,
3620
+ addFormRevisionAttachments,
3621
+ deleteFormRevisionAttachment,
3622
+ deleteFormRevisionAttachments
3623
+ } = formRevisionsSlice.actions;
3624
+ const selectFormRevisionMapping = (state) => state.formRevisionReducer.formRevisions;
3625
+ const selectFormRevisions = createSelector(
3626
+ [selectFormRevisionMapping],
3627
+ (formRevisions) => Object.values(formRevisions)
3628
+ );
3629
+ const selectFormRevision = (formRevisionId) => (state) => {
3630
+ return state.formRevisionReducer.formRevisions[formRevisionId];
3631
+ };
3632
+ const _selectLatestFormRevision = (formRevisions, formId2) => {
3633
+ let ret = null;
3634
+ for (const candidate of Object.values(formRevisions)) {
3635
+ if (candidate.form === formId2 && (!ret || ret.revision < candidate.revision)) {
3636
+ ret = candidate;
3637
+ }
3638
+ }
3639
+ if (!ret) {
3640
+ throw new Error("No form revision found for form " + formId2);
3641
+ }
3642
+ return ret;
3643
+ };
3644
+ const selectLatestFormRevisionOfForm = restructureCreateSelectorWithArgs(
3645
+ createSelector([selectFormRevisionMapping, (_state, formId2) => formId2], (revisions, formId2) => {
3646
+ if (!formId2) {
3647
+ throw new Error("formId is required");
3648
+ }
3649
+ return _selectLatestFormRevision(revisions, formId2);
3650
+ })
3651
+ );
3652
+ const selectFormRevisionsOfForm = restructureCreateSelectorWithArgs(
3653
+ createSelector([selectFormRevisions, (_state, formId2) => formId2], (revisions, formId2) => {
3654
+ return revisions.filter((revision) => {
3655
+ return revision.form === formId2;
3656
+ });
3657
+ })
3658
+ );
3659
+ const selectLatestFormRevisionsOfComponentTypes = restructureCreateSelectorWithArgs(
3660
+ createSelector(
3661
+ [
3662
+ (state) => state.formReducer.forms,
3663
+ selectFormRevisionMapping,
3664
+ (_state, componentTypeIds) => componentTypeIds
3665
+ ],
3666
+ (userForms, revisions, componentTypeIds) => {
3667
+ const componentTypeIdsSet = new Set(componentTypeIds);
3668
+ const ret = {};
3669
+ for (const form of Object.values(userForms)) {
3670
+ if (form.component_type && componentTypeIdsSet.has(form.component_type)) {
3671
+ ret[form.component_type] = _selectLatestFormRevision(revisions, form.offline_id);
3672
+ }
3590
3673
  }
3674
+ return ret;
3675
+ }
3676
+ )
3677
+ );
3678
+ const selectLatestFormRevisionByForm = createSelector([selectFormRevisionMapping], (revisions) => {
3679
+ const latestRevisions = {};
3680
+ for (const revision of Object.values(revisions)) {
3681
+ const formId2 = revision.form;
3682
+ const currentLatestRevision = latestRevisions[formId2];
3683
+ if (!currentLatestRevision || currentLatestRevision.revision < revision.revision) {
3684
+ latestRevisions[formId2] = revision;
3685
+ }
3686
+ }
3687
+ return latestRevisions;
3688
+ });
3689
+ const selectUserFormRevisionAttachmentsMapping = (state) => {
3690
+ return state.formRevisionReducer.attachments;
3691
+ };
3692
+ const selectAttachmentsOfFormRevision = restructureCreateSelectorWithArgs(
3693
+ createSelector(
3694
+ [selectUserFormRevisionAttachmentsMapping, (_state, revisionId) => revisionId],
3695
+ (attachments, revisionId) => {
3696
+ return Object.values(attachments).filter((attachment) => attachment.revision === revisionId);
3697
+ }
3698
+ )
3699
+ );
3700
+ const formRevisionReducer = formRevisionsSlice.reducer;
3701
+ const initialState$4 = {
3702
+ forms: {}
3703
+ };
3704
+ const formSlice = createSlice({
3705
+ name: "forms",
3706
+ initialState: initialState$4,
3707
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$4)),
3708
+ reducers: {
3709
+ setForms: (state, action) => {
3710
+ state.forms = {};
3711
+ action.payload.forEach((userForm) => {
3712
+ state.forms[userForm.offline_id] = userForm;
3713
+ });
3591
3714
  },
3592
- setUserFormSubmissions: (state, action) => {
3593
- state.submissions = {};
3594
- action.payload.forEach((submission) => {
3595
- state.submissions[submission.offline_id] = submission;
3715
+ addForm: (state, action) => {
3716
+ state.forms[action.payload.offline_id] = action.payload;
3717
+ },
3718
+ addForms: (state, action) => {
3719
+ action.payload.forEach((userForm) => {
3720
+ state.forms[userForm.offline_id] = userForm;
3596
3721
  });
3597
3722
  },
3598
3723
  favoriteForm: (state, action) => {
3599
3724
  const { formId: formId2 } = action.payload;
3600
- const form = state.userForms[formId2];
3725
+ const form = state.forms[formId2];
3601
3726
  if (!form) {
3602
3727
  throw new Error("No form exists with the id " + formId2);
3603
3728
  }
@@ -3605,48 +3730,23 @@ const userFormSlice = createSlice({
3605
3730
  },
3606
3731
  unfavoriteForm: (state, action) => {
3607
3732
  const { formId: formId2 } = action.payload;
3608
- const form = state.userForms[formId2];
3733
+ const form = state.forms[formId2];
3609
3734
  if (!form) {
3610
3735
  throw new Error("No form exists with the id " + formId2);
3611
3736
  }
3612
3737
  form.favorite = false;
3613
3738
  },
3614
- deleteUserForm: (state, action) => {
3615
- delete state.userForms[action.payload];
3739
+ deleteForm: (state, action) => {
3740
+ delete state.forms[action.payload];
3616
3741
  }
3617
3742
  }
3618
3743
  });
3619
- const {
3620
- addUserForm,
3621
- addUserForms,
3622
- addUserFormRevisions,
3623
- updateOrCreateUserFormSubmission,
3624
- addUserFormSubmissions,
3625
- deleteUserFormSubmission,
3626
- deleteUserFormSubmissions,
3627
- favoriteForm,
3628
- unfavoriteForm,
3629
- deleteUserForm,
3630
- deleteUserFormRevision,
3631
- deleteUserFormRevisions,
3632
- setUserFormSubmissions,
3633
- addUserFormRevision,
3634
- addUserFormSubmissionAttachment,
3635
- addUserFormRevisionAttachment,
3636
- setUserFormSubmissionAttachments,
3637
- setUserFormRevisionAttachments
3638
- } = userFormSlice.actions;
3639
- const selectSubmissionAttachments = (submissionId) => (state) => {
3640
- return state.userFormReducer.submissionAttachments[submissionId] || [];
3641
- };
3642
- const selectRevisionAttachments = (revisionId) => (state) => {
3643
- return state.userFormReducer.revisionAttachments[revisionId] || [];
3644
- };
3645
- const selectFilteredUserForms = restructureCreateSelectorWithArgs(
3744
+ const { setForms, addForm, addForms, favoriteForm, unfavoriteForm, deleteForm } = formSlice.actions;
3745
+ const selectFilteredForms = restructureCreateSelectorWithArgs(
3646
3746
  createSelector(
3647
3747
  [
3648
- (state) => state.userFormReducer.userForms,
3649
- (state) => state.userFormReducer.revisions,
3748
+ (state) => state.formReducer.forms,
3749
+ (state) => state.formRevisionReducer.formRevisions,
3650
3750
  (_state, search) => search
3651
3751
  ],
3652
3752
  (userForms, revisions, search) => {
@@ -3680,63 +3780,188 @@ const selectFilteredUserForms = restructureCreateSelectorWithArgs(
3680
3780
  { memoizeOptions: { equalityCheck: shallowEqual$1 } }
3681
3781
  )
3682
3782
  );
3683
- const selectFormRevision = (revisionId) => (state) => {
3684
- return state.userFormReducer.revisions[revisionId];
3783
+ const selectForm = (formId2) => (state) => {
3784
+ return state.formReducer.forms[formId2];
3685
3785
  };
3686
- const _selectLatestFormRevision = (revisions, formId2) => {
3687
- let ret = null;
3688
- for (const candidate of Object.values(revisions)) {
3689
- if (candidate.form === formId2 && (!ret || ret.revision < candidate.revision)) {
3690
- ret = candidate;
3691
- }
3692
- }
3693
- if (!ret) {
3694
- throw new Error("No revision found for form " + formId2);
3695
- }
3696
- return ret;
3786
+ const selectFormMapping = (state) => {
3787
+ return state.formReducer.forms;
3697
3788
  };
3698
- const selectLatestFormRevision = restructureCreateSelectorWithArgs(
3789
+ const selectFormOfComponentType = restructureCreateSelectorWithArgs(
3699
3790
  createSelector(
3700
- [(state) => state.userFormReducer.revisions, (_state, formId2) => formId2],
3701
- (revisions, formId2) => {
3702
- if (!formId2) {
3703
- throw new Error("formId is required");
3704
- }
3705
- return _selectLatestFormRevision(revisions, formId2);
3791
+ [selectFormMapping, (_state, componentTypeId) => componentTypeId],
3792
+ (userForms, componentTypeId) => {
3793
+ return Object.values(userForms).find((userForm) => userForm.component_type === componentTypeId);
3706
3794
  }
3707
3795
  )
3708
3796
  );
3709
- const selectUserForm = (formId2) => (state) => {
3710
- return state.userFormReducer.userForms[formId2];
3711
- };
3712
- const selectSubmissionMapping = (state) => state.userFormReducer.submissions;
3713
- const selectUserFormSubmission = (submissionId) => (state) => {
3714
- return state.userFormReducer.submissions[submissionId];
3715
- };
3716
- const selectSubmissions = createSelector([selectSubmissionMapping], (submissions) => Object.values(submissions));
3717
- const selectRevisionMapping = (state) => state.userFormReducer.revisions;
3718
- const selectRevisions = createSelector([selectRevisionMapping], (revisions) => Object.values(revisions));
3719
- const selectRevisionsForForm = restructureCreateSelectorWithArgs(
3720
- createSelector([selectRevisions, (_state, formId2) => formId2], (revisions, formId2) => {
3721
- return revisions.filter((revision) => {
3722
- return revision.form === formId2;
3723
- });
3724
- })
3797
+ const selectFormsCount = createSelector([selectFormMapping], (userForms) => {
3798
+ return Object.keys(userForms).length;
3799
+ });
3800
+ const selectGeneralFormCount = createSelector([selectFormMapping], (userForms) => {
3801
+ return Object.values(userForms).filter((form) => !form.component_type).length;
3802
+ });
3803
+ const formReducer = formSlice.reducer;
3804
+ const initialState$3 = {
3805
+ formSubmissions: {},
3806
+ attachments: {}
3807
+ };
3808
+ const formSubmissionSlice = createSlice({
3809
+ name: "formSubmissions",
3810
+ initialState: initialState$3,
3811
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$3)),
3812
+ reducers: {
3813
+ setFormSubmission: (state, action) => {
3814
+ state.formSubmissions[action.payload.offline_id] = action.payload;
3815
+ },
3816
+ setFormSubmissions: (state, action) => {
3817
+ state.formSubmissions = {};
3818
+ for (const submission of action.payload) {
3819
+ state.formSubmissions[submission.offline_id] = submission;
3820
+ }
3821
+ },
3822
+ addFormSubmission: (state, action) => {
3823
+ if (state.formSubmissions[action.payload.offline_id] !== void 0) {
3824
+ throw new Error(`Submission with offline_id ${action.payload.offline_id} already exists`);
3825
+ }
3826
+ state.formSubmissions[action.payload.offline_id] = action.payload;
3827
+ },
3828
+ addFormSubmissions: (state, action) => {
3829
+ for (const submission of action.payload) {
3830
+ if (state.formSubmissions[submission.offline_id] !== void 0) {
3831
+ throw new Error(`Submission with offline_id ${submission.offline_id} already exists`);
3832
+ }
3833
+ }
3834
+ for (const submission of action.payload) {
3835
+ state.formSubmissions[submission.offline_id] = submission;
3836
+ }
3837
+ },
3838
+ updateFormSubmission: (state, action) => {
3839
+ if (state.formSubmissions[action.payload.offline_id] === void 0) {
3840
+ throw new Error(`Submission with offline_id ${action.payload.offline_id} does not exist`);
3841
+ }
3842
+ state.formSubmissions[action.payload.offline_id] = action.payload;
3843
+ },
3844
+ updateFormSubmissions: (state, action) => {
3845
+ for (const submission of action.payload) {
3846
+ if (state.formSubmissions[submission.offline_id] === void 0) {
3847
+ throw new Error(`Submission with offline_id ${submission.offline_id} does not exist`);
3848
+ }
3849
+ }
3850
+ for (const submission of action.payload) {
3851
+ state.formSubmissions[submission.offline_id] = submission;
3852
+ }
3853
+ },
3854
+ deleteFormSubmission: (state, action) => {
3855
+ if (state.formSubmissions[action.payload] === void 0) {
3856
+ throw new Error(`Submission with offline_id ${action.payload} does not exist`);
3857
+ }
3858
+ delete state.formSubmissions[action.payload];
3859
+ },
3860
+ deleteFormSubmissions: (state, action) => {
3861
+ for (const offlineId of action.payload) {
3862
+ if (state.formSubmissions[offlineId] === void 0) {
3863
+ throw new Error(`Submission with offline_id ${offlineId} does not exist`);
3864
+ }
3865
+ delete state.formSubmissions[offlineId];
3866
+ }
3867
+ for (const offlineId of action.payload) {
3868
+ delete state.formSubmissions[offlineId];
3869
+ }
3870
+ },
3871
+ // Attachments
3872
+ addFormSubmissionAttachment: (state, action) => {
3873
+ if (state.attachments[action.payload.offline_id] !== void 0) {
3874
+ throw new Error(`Attachment with offline_id ${action.payload.offline_id} already exists`);
3875
+ }
3876
+ state.attachments[action.payload.offline_id] = action.payload;
3877
+ },
3878
+ addFormSubmissionAttachments: (state, action) => {
3879
+ for (const attachment of action.payload) {
3880
+ if (state.attachments[attachment.offline_id] !== void 0) {
3881
+ throw new Error(`Attachment with offline_id ${attachment.offline_id} already exists`);
3882
+ }
3883
+ }
3884
+ for (const attachment of action.payload) {
3885
+ state.attachments[attachment.offline_id] = attachment;
3886
+ }
3887
+ },
3888
+ // We only need a multi set for attachments because they are not updated, only added and deleted
3889
+ setFormSubmissionAttachments: (state, action) => {
3890
+ state.attachments = {};
3891
+ for (const attachment of action.payload) {
3892
+ state.attachments[attachment.offline_id] = attachment;
3893
+ }
3894
+ },
3895
+ updateFormSubmissionAttachments: (state, action) => {
3896
+ for (const attachment of action.payload) {
3897
+ if (state.attachments[attachment.offline_id] === void 0) {
3898
+ throw new Error(`Attachment with offline_id ${attachment.offline_id} does not exist`);
3899
+ }
3900
+ }
3901
+ for (const attachment of action.payload) {
3902
+ state.attachments[attachment.offline_id] = attachment;
3903
+ }
3904
+ },
3905
+ // The delete actions for UserFormSubmissionAttachments are not used in the app, but are included for completeness
3906
+ // Could be used if editing a submission is ever supported, will be applicable for supporting tip tap content in submissions
3907
+ deleteFormSubmissionAttachment: (state, action) => {
3908
+ if (state.attachments[action.payload] === void 0) {
3909
+ throw new Error(`Attachment with offline_id ${action.payload} does not exist`);
3910
+ }
3911
+ delete state.attachments[action.payload];
3912
+ },
3913
+ deleteFormSubmissionAttachments: (state, action) => {
3914
+ for (const offlineId of action.payload) {
3915
+ if (state.attachments[offlineId] === void 0) {
3916
+ throw new Error(`Attachment with offline_id ${offlineId} does not exist`);
3917
+ }
3918
+ delete state.attachments[offlineId];
3919
+ }
3920
+ }
3921
+ }
3922
+ });
3923
+ const {
3924
+ setFormSubmission,
3925
+ setFormSubmissions,
3926
+ addFormSubmission,
3927
+ addFormSubmissions,
3928
+ updateFormSubmission,
3929
+ updateFormSubmissions,
3930
+ deleteFormSubmission,
3931
+ deleteFormSubmissions,
3932
+ addFormSubmissionAttachment,
3933
+ addFormSubmissionAttachments,
3934
+ setFormSubmissionAttachments,
3935
+ updateFormSubmissionAttachments,
3936
+ deleteFormSubmissionAttachment,
3937
+ deleteFormSubmissionAttachments
3938
+ } = formSubmissionSlice.actions;
3939
+ const selectFormSubmissionsMapping = (state) => {
3940
+ return state.formSubmissionReducer.formSubmissions;
3941
+ };
3942
+ const selectFormSubmissions = createSelector(
3943
+ [selectFormSubmissionsMapping],
3944
+ (submissions) => {
3945
+ return Object.values(submissions);
3946
+ }
3725
3947
  );
3726
- const selectSubmissionsForForm = restructureCreateSelectorWithArgs(
3948
+ const selectFormSubmission = (submissionId) => (state) => {
3949
+ return state.formSubmissionReducer.formSubmissions[submissionId];
3950
+ };
3951
+ const selectFormSubmissionsOfForm = restructureCreateSelectorWithArgs(
3727
3952
  createSelector(
3728
- [selectSubmissions, selectRevisionMapping, (_state, formId2) => formId2],
3953
+ [selectFormSubmissions, selectFormRevisionMapping, (_state, formId2) => formId2],
3729
3954
  (submissions, revisionMapping, formId2) => {
3730
- return Object.values(submissions).filter((submission) => {
3955
+ return submissions.filter((submission) => {
3731
3956
  const revision = revisionMapping[submission.form_revision];
3732
3957
  return (revision == null ? void 0 : revision.form) === formId2;
3733
3958
  });
3734
3959
  }
3735
3960
  )
3736
3961
  );
3737
- const selectSubmissionsForIssue = restructureCreateSelectorWithArgs(
3962
+ const selectFormSubmissionsOfIssue = restructureCreateSelectorWithArgs(
3738
3963
  createSelector(
3739
- [(state) => state.userFormReducer.submissions, (_state, issueId) => issueId],
3964
+ [selectFormSubmissions, (_state, issueId) => issueId],
3740
3965
  (submissions, issueId) => {
3741
3966
  return Object.values(submissions).filter((submission) => {
3742
3967
  return submission.issue === issueId;
@@ -3744,9 +3969,9 @@ const selectSubmissionsForIssue = restructureCreateSelectorWithArgs(
3744
3969
  }
3745
3970
  )
3746
3971
  );
3747
- const selectSubmissionsForComponent = restructureCreateSelectorWithArgs(
3972
+ const selectFormSubmissionsOfComponent = restructureCreateSelectorWithArgs(
3748
3973
  createSelector(
3749
- [selectSubmissions, (_state, componentId) => componentId],
3974
+ [selectFormSubmissions, (_state, componentId) => componentId],
3750
3975
  (submissions, componentId) => {
3751
3976
  return submissions.filter((submission) => {
3752
3977
  return submission.component === componentId;
@@ -3754,8 +3979,8 @@ const selectSubmissionsForComponent = restructureCreateSelectorWithArgs(
3754
3979
  }
3755
3980
  )
3756
3981
  );
3757
- const selectComponentSubmissionMapping = createSelector(
3758
- [selectSubmissionMapping, selectComponentsMapping],
3982
+ const selectFormSubmissionsByComponents = createSelector(
3983
+ [selectFormSubmissionsMapping, selectComponentsMapping],
3759
3984
  (submissions, components) => {
3760
3985
  var _a2;
3761
3986
  const componentSubmissionMapping = {};
@@ -3771,54 +3996,18 @@ const selectComponentSubmissionMapping = createSelector(
3771
3996
  return componentSubmissionMapping;
3772
3997
  }
3773
3998
  );
3774
- const selectUserFormMapping = (state) => {
3775
- return state.userFormReducer.userForms;
3999
+ const selectFormSubmissionAttachmentsMapping = (state) => {
4000
+ return state.formSubmissionReducer.attachments;
3776
4001
  };
3777
- const selectComponentTypeForm = restructureCreateSelectorWithArgs(
4002
+ const selectAttachmentsOfFormSubmission = restructureCreateSelectorWithArgs(
3778
4003
  createSelector(
3779
- [selectUserFormMapping, (_state, componentTypeId) => componentTypeId],
3780
- (userForms, componentTypeId) => {
3781
- return Object.values(userForms).find((userForm) => userForm.component_type === componentTypeId);
4004
+ [selectFormSubmissionAttachmentsMapping, (_state, submissionId) => submissionId],
4005
+ (attachmentsMapping, submissionId) => {
4006
+ return Object.values(attachmentsMapping).filter((attachment) => attachment.submission === submissionId);
3782
4007
  }
3783
4008
  )
3784
4009
  );
3785
- const selectLatestRevisionsFromComponentTypeIds = restructureCreateSelectorWithArgs(
3786
- createSelector(
3787
- [
3788
- selectUserFormMapping,
3789
- selectRevisionMapping,
3790
- (_state, componentTypeIds) => componentTypeIds
3791
- ],
3792
- (userForms, revisions, componentTypeIds) => {
3793
- const componentTypeIdsSet = new Set(componentTypeIds);
3794
- const ret = {};
3795
- for (const form of Object.values(userForms)) {
3796
- if (form.component_type && componentTypeIdsSet.has(form.component_type)) {
3797
- ret[form.component_type] = _selectLatestFormRevision(revisions, form.offline_id);
3798
- }
3799
- }
3800
- return ret;
3801
- }
3802
- )
3803
- );
3804
- const selectLatestRevisionByFormId = createSelector([selectRevisionMapping], (revisions) => {
3805
- const latestRevisions = {};
3806
- for (const revision of Object.values(revisions)) {
3807
- const formId2 = revision.form;
3808
- const currentLatestRevision = latestRevisions[formId2];
3809
- if (!currentLatestRevision || currentLatestRevision.revision < revision.revision) {
3810
- latestRevisions[formId2] = revision;
3811
- }
3812
- }
3813
- return latestRevisions;
3814
- });
3815
- const selectNumberOfUserForms = createSelector([selectUserFormMapping], (userForms) => {
3816
- return Object.keys(userForms).length;
3817
- });
3818
- const selectNumberOfGeneralUserForms = createSelector([selectUserFormMapping], (userForms) => {
3819
- return Object.values(userForms).filter((form) => !form.component_type).length;
3820
- });
3821
- const userFormReducer = userFormSlice.reducer;
4010
+ const formSubmissionReducer = formSubmissionSlice.reducer;
3822
4011
  const initialState$2 = {
3823
4012
  emailDomains: {}
3824
4013
  };
@@ -3852,7 +4041,8 @@ const selectSortedEmailDomains = (state) => Object.values(state.emailDomainsRedu
3852
4041
  );
3853
4042
  const emailDomainsReducer = emailDomainsSlice.reducer;
3854
4043
  const initialState$1 = {
3855
- documents: {}
4044
+ documents: {},
4045
+ attachments: {}
3856
4046
  };
3857
4047
  const documentSlice = createSlice({
3858
4048
  name: "documents",
@@ -3989,10 +4179,28 @@ const documentSlice = createSlice({
3989
4179
  }
3990
4180
  delete state.documents[documentId];
3991
4181
  }
3992
- }
4182
+ },
4183
+ setDocumentAttachments: setAttachments,
4184
+ addDocumentAttachment: addAttachment,
4185
+ addDocumentAttachments: addAttachments,
4186
+ updateDocumentAttachment: updateAttachment,
4187
+ removeDocumentAttachment: removeAttachment,
4188
+ removeDocumentAttachments: removeAttachments
3993
4189
  }
3994
4190
  });
3995
- const { setDocuments, addDocuments, updateDocuments, moveDocument, removeDocuments } = documentSlice.actions;
4191
+ const {
4192
+ setDocuments,
4193
+ addDocuments,
4194
+ updateDocuments,
4195
+ moveDocument,
4196
+ removeDocuments,
4197
+ setDocumentAttachments,
4198
+ addDocumentAttachment,
4199
+ addDocumentAttachments,
4200
+ updateDocumentAttachment,
4201
+ removeDocumentAttachment,
4202
+ removeDocumentAttachments
4203
+ } = documentSlice.actions;
3996
4204
  const selectDocumentsMapping = (state) => state.documentsReducer.documents;
3997
4205
  const selectDocuments = createSelector(
3998
4206
  [selectDocumentsMapping],
@@ -4022,6 +4230,39 @@ const selectRootDocuments = createSelector(
4022
4230
  [selectDocuments],
4023
4231
  (documents) => documents.filter((document2) => !document2.parent_document)
4024
4232
  );
4233
+ const selectDocumentAttachmentMapping = (state) => state.documentsReducer.attachments;
4234
+ const selectAllDocumentAttachments = createSelector(
4235
+ [selectDocumentAttachmentMapping],
4236
+ (mapping) => Object.values(mapping)
4237
+ );
4238
+ const selectDocumentAttachment = (attachmentId) => (state) => {
4239
+ return state.documentsReducer.attachments[attachmentId];
4240
+ };
4241
+ const selectAttachmentsOfDocument = restructureCreateSelectorWithArgs(
4242
+ createSelector(
4243
+ [selectAllDocumentAttachments, (_state, documentId) => documentId],
4244
+ (attachments, documentId) => {
4245
+ return attachments.filter(({ document: document2 }) => documentId === document2);
4246
+ }
4247
+ )
4248
+ );
4249
+ const selectAttachmentsOfDocumentByType = restructureCreateSelectorWithArgs(
4250
+ createSelector(
4251
+ [selectAllDocumentAttachments, (_state, documentId) => documentId],
4252
+ (attachments, documentId) => {
4253
+ const attachmentsOfProject = attachments.filter(({ document: document2 }) => documentId === document2);
4254
+ const fileAttachments = attachmentsOfProject.filter(
4255
+ // this null check here is necessary, there are cases where file_type is null or undefined
4256
+ ({ file_type }) => !file_type || !file_type.startsWith("image/")
4257
+ );
4258
+ const imageAttachments = attachmentsOfProject.filter(
4259
+ // this null check here is necessary, there are cases where file_type is null or undefined
4260
+ ({ file_type }) => file_type && file_type.startsWith("image/")
4261
+ );
4262
+ return { fileAttachments, imageAttachments };
4263
+ }
4264
+ )
4265
+ );
4025
4266
  const documentsReducer = documentSlice.reducer;
4026
4267
  const initialState = {
4027
4268
  version: 0
@@ -4064,7 +4305,9 @@ const overmapReducers = {
4064
4305
  projectFileReducer,
4065
4306
  rehydratedReducer,
4066
4307
  settingReducer,
4067
- userFormReducer,
4308
+ formReducer,
4309
+ formRevisionReducer,
4310
+ formSubmissionReducer,
4068
4311
  userReducer,
4069
4312
  workspaceReducer,
4070
4313
  emailDomainsReducer,
@@ -4117,9 +4360,7 @@ function handleWorkspaceRemoval(draft, action) {
4117
4360
  throw new Error(`Failed to update index_workspace of issue ${issue.offline_id} to main workspace`);
4118
4361
  }
4119
4362
  }
4120
- const indexedForms = Object.values(draft.userFormReducer.userForms).filter(
4121
- (form) => form.index_workspace === workspaceId
4122
- );
4363
+ const indexedForms = Object.values(draft.formReducer.forms).filter((form) => form.index_workspace === workspaceId);
4123
4364
  for (const form of indexedForms) {
4124
4365
  form.index_workspace = mainWorkspace.offline_id;
4125
4366
  }
@@ -4602,7 +4843,8 @@ class AttachmentService extends BaseApiService {
4602
4843
  issue_attachments: Object.values(state.issueReducer.attachments),
4603
4844
  component_attachments: Object.values(state.componentReducer.attachments),
4604
4845
  component_type_attachments: Object.values(state.componentTypeReducer.attachments),
4605
- project_attachments: Object.values(state.projectReducer.attachments)
4846
+ project_attachments: Object.values(state.projectReducer.attachments),
4847
+ document_attachments: Object.values(state.documentsReducer.attachments)
4606
4848
  };
4607
4849
  return [allAttachments, promise];
4608
4850
  }
@@ -4706,8 +4948,8 @@ class AttachmentService extends BaseApiService {
4706
4948
  });
4707
4949
  return [offlineAttachment, promise];
4708
4950
  }
4709
- async addProjectAttachment(attachmentPayload) {
4710
- const { description: description2, project, file_sha1, offline_id } = attachmentPayload;
4951
+ async addDocumentAttachment(attachmentPayload) {
4952
+ const { description: description2, document: document2, file_sha1, offline_id } = attachmentPayload;
4711
4953
  if (!attachmentPayload.file.objectURL) {
4712
4954
  throw new Error("Expected attachmentPayload.file.objectURL to be defined.");
4713
4955
  }
@@ -4720,24 +4962,24 @@ class AttachmentService extends BaseApiService {
4720
4962
  created_by: this.client.store.getState().userReducer.currentUser.id
4721
4963
  };
4722
4964
  await this.client.files.addCache(attachmentPayload.file, file_sha1);
4723
- this.client.store.dispatch(addProjectAttachment(offlineAttachment));
4965
+ this.client.store.dispatch(addDocumentAttachment(offlineAttachment));
4724
4966
  const [fileProps] = await this.client.files.uploadFileToS3(file_sha1);
4725
4967
  const promise = this.enqueueRequest({
4726
4968
  description: "Create attachment",
4727
4969
  method: HttpMethod.POST,
4728
- url: `/projects/${project}/attach/`,
4729
- blocks: [offline_id, project.toString()],
4970
+ url: `/documents/${document2}/attach/`,
4971
+ blocks: [offline_id, document2],
4730
4972
  blockers: [file_sha1],
4731
4973
  payload: {
4732
4974
  offline_id,
4733
- project,
4975
+ document: document2,
4734
4976
  description: description2 ?? "",
4735
4977
  submitted_at: (/* @__PURE__ */ new Date()).toISOString(),
4736
4978
  ...fileProps
4737
4979
  }
4738
4980
  });
4739
4981
  promise.catch((error2) => {
4740
- this.client.store.dispatch(removeProjectAttachment(offlineAttachment.offline_id));
4982
+ this.client.store.dispatch(removeDocumentAttachment(offlineAttachment.offline_id));
4741
4983
  throw error2;
4742
4984
  });
4743
4985
  return [offlineAttachment, promise];
@@ -4808,7 +5050,7 @@ class AttachmentService extends BaseApiService {
4808
5050
  return photoAttachmentPromise(file);
4809
5051
  });
4810
5052
  }
4811
- attachFilesToProject(filesToSubmit, projectId) {
5053
+ attachFilesToDocument(filesToSubmit, documentId) {
4812
5054
  return filesToSubmit.map((file) => {
4813
5055
  if (!(file instanceof File)) {
4814
5056
  throw new Error("Expected a File instance.");
@@ -4819,12 +5061,12 @@ class AttachmentService extends BaseApiService {
4819
5061
  file: file2,
4820
5062
  file_name: file2.name,
4821
5063
  file_type: file2.type,
4822
- project: projectId,
5064
+ document: documentId,
4823
5065
  file_sha1: hash,
4824
5066
  submitted_at: (/* @__PURE__ */ new Date()).toISOString(),
4825
5067
  created_by: this.client.store.getState().userReducer.currentUser.id
4826
5068
  });
4827
- return this.addProjectAttachment(attachment);
5069
+ return this.addDocumentAttachment(attachment);
4828
5070
  };
4829
5071
  return photoAttachmentPromise(file);
4830
5072
  });
@@ -5004,9 +5246,9 @@ class AttachmentService extends BaseApiService {
5004
5246
  const promise = performRequest2();
5005
5247
  return [offlineAttachment, promise];
5006
5248
  }
5007
- async replaceProjectAttachmentFile(attachmentId, newFile) {
5249
+ async replaceDocumentAttachmentFile(attachmentId, newFile) {
5008
5250
  const { store } = this.client;
5009
- const attachment = store.getState().projectReducer.attachments[attachmentId];
5251
+ const attachment = store.getState().documentsReducer.attachments[attachmentId];
5010
5252
  if (!attachment)
5011
5253
  throw new Error(`Attachment ${attachmentId} not found`);
5012
5254
  let oldFile = void 0;
@@ -5020,7 +5262,7 @@ class AttachmentService extends BaseApiService {
5020
5262
  throw new Error(`newFile["objectURL"] is unexpectedly ${newFile.objectURL}`);
5021
5263
  }
5022
5264
  store.dispatch(
5023
- updateProjectAttachment({
5265
+ updateDocumentAttachment({
5024
5266
  ...attachment,
5025
5267
  file_sha1: newSha1,
5026
5268
  file: URL.createObjectURL(newFile)
@@ -5028,13 +5270,13 @@ class AttachmentService extends BaseApiService {
5028
5270
  );
5029
5271
  await this.client.files.addCache(newFile, newSha1);
5030
5272
  const [fileProps] = await this.client.files.uploadFileToS3(newSha1).catch((e) => {
5031
- store.dispatch(updateProjectAttachment(attachment));
5273
+ store.dispatch(updateDocumentAttachment(attachment));
5032
5274
  throw e;
5033
5275
  });
5034
5276
  const promise2 = this.enqueueRequest({
5035
5277
  description: "Edit attachment",
5036
5278
  method: HttpMethod.PATCH,
5037
- url: `/attachments/projects/${attachment.offline_id}/`,
5279
+ url: `/attachments/documents/${attachment.offline_id}/`,
5038
5280
  isResponseBlob: false,
5039
5281
  payload: fileProps,
5040
5282
  blockers: [attachmentId, newSha1],
@@ -5047,7 +5289,7 @@ class AttachmentService extends BaseApiService {
5047
5289
  } catch (e) {
5048
5290
  if (oldFile) {
5049
5291
  store.dispatch(
5050
- updateProjectAttachment({
5292
+ updateDocumentAttachment({
5051
5293
  ...attachment,
5052
5294
  file_sha1: attachment.file_sha1,
5053
5295
  file: URL.createObjectURL(oldFile)
@@ -5117,20 +5359,20 @@ class AttachmentService extends BaseApiService {
5117
5359
  blocks: [componentTypeAttachmentId]
5118
5360
  });
5119
5361
  }
5120
- deleteProjectAttachment(projectAttachmentId) {
5362
+ deleteDocumentAttachment(documentAttachmentId) {
5121
5363
  const { store } = this.client;
5122
- const attachment = selectProjectAttachmentMapping(store.getState())[projectAttachmentId];
5364
+ const attachment = store.getState().documentsReducer.attachments[documentAttachmentId];
5123
5365
  if (!attachment) {
5124
- throw new Error(`Attachment ${projectAttachmentId} not found`);
5366
+ throw new Error(`Attachment ${documentAttachmentId} not found`);
5125
5367
  }
5126
- store.dispatch(removeProjectAttachment(projectAttachmentId));
5368
+ store.dispatch(removeDocumentAttachment(documentAttachmentId));
5127
5369
  void this.client.files.removeCache(attachment.file_sha1);
5128
5370
  return this.enqueueRequest({
5129
- description: "Delete attachment",
5371
+ description: "Delete document attachment",
5130
5372
  method: HttpMethod.DELETE,
5131
- url: `/attachments/projects/${projectAttachmentId}/`,
5132
- blockers: [projectAttachmentId],
5133
- blocks: [projectAttachmentId]
5373
+ url: `/attachments/documents/${documentAttachmentId}/`,
5374
+ blockers: [documentAttachmentId],
5375
+ blocks: [documentAttachmentId]
5134
5376
  });
5135
5377
  }
5136
5378
  }
@@ -6367,11 +6609,18 @@ class MainService extends BaseApiService {
6367
6609
  if (currentProjectId) {
6368
6610
  const [_offlineAttachments, promise] = this.client.attachments.fetchAll(currentProjectId);
6369
6611
  void promise.then((result) => {
6370
- const { issue_attachments, component_type_attachments, component_attachments, project_attachments } = result;
6612
+ const {
6613
+ issue_attachments,
6614
+ component_type_attachments,
6615
+ component_attachments,
6616
+ project_attachments,
6617
+ document_attachments
6618
+ } = result;
6371
6619
  store.dispatch(setIssueAttachments(issue_attachments));
6372
6620
  store.dispatch(setComponentAttachments(component_attachments));
6373
6621
  store.dispatch(setComponentTypeAttachments(component_type_attachments));
6374
6622
  store.dispatch(setProjectAttachments(project_attachments));
6623
+ store.dispatch(setDocumentAttachments(document_attachments));
6375
6624
  });
6376
6625
  void this.client.documents.refreshStore();
6377
6626
  void this.client.issueUpdates.refreshStore();
@@ -6739,7 +6988,7 @@ class UserFormService extends BaseApiService {
6739
6988
  ...revisionAttachmentPayload,
6740
6989
  file: URL.createObjectURL(image)
6741
6990
  };
6742
- store.dispatch(addUserFormRevisionAttachment(offlinePayload));
6991
+ store.dispatch(addFormRevisionAttachment(offlinePayload));
6743
6992
  return attach;
6744
6993
  });
6745
6994
  });
@@ -6773,8 +7022,8 @@ class UserFormService extends BaseApiService {
6773
7022
  revision: 0
6774
7023
  };
6775
7024
  const { store } = this.client;
6776
- store.dispatch(addUserForm(retForm));
6777
- store.dispatch(addUserFormRevision(retRevision));
7025
+ store.dispatch(addForm(retForm));
7026
+ store.dispatch(addFormRevision(retRevision));
6778
7027
  const formPromise = this.enqueueRequest({
6779
7028
  description: "Create form",
6780
7029
  method: HttpMethod.POST,
@@ -6792,8 +7041,8 @@ class UserFormService extends BaseApiService {
6792
7041
  });
6793
7042
  const attachImagesPromises = this.getAttachImagePromises(images, offlineRevisionPayload.offline_id);
6794
7043
  void formPromise.catch((e) => {
6795
- store.dispatch(deleteUserForm(retForm.offline_id));
6796
- store.dispatch(deleteUserFormRevision(retRevision.offline_id));
7044
+ store.dispatch(deleteForm(retForm.offline_id));
7045
+ store.dispatch(deleteFormRevision(retRevision.offline_id));
6797
7046
  throw e;
6798
7047
  });
6799
7048
  const settledPromise = Promise.all([formPromise, ...attachImagesPromises]).then(() => formPromise);
@@ -6835,7 +7084,7 @@ class UserFormService extends BaseApiService {
6835
7084
  revision: "Pending",
6836
7085
  form: formId2
6837
7086
  };
6838
- store.dispatch(addUserFormRevision(fullRevision));
7087
+ store.dispatch(addFormRevision(fullRevision));
6839
7088
  const promise = this.enqueueRequest({
6840
7089
  description: "Create form revision",
6841
7090
  method: HttpMethod.PATCH,
@@ -6849,9 +7098,9 @@ class UserFormService extends BaseApiService {
6849
7098
  });
6850
7099
  const attachImagesPromises = this.getAttachImagePromises(images, offlineRevision.offline_id);
6851
7100
  void promise.then((result) => {
6852
- store.dispatch(addUserFormRevision(result));
7101
+ store.dispatch(setFormRevision(result));
6853
7102
  }).catch(() => {
6854
- store.dispatch(deleteUserFormRevision(fullRevision.offline_id));
7103
+ store.dispatch(deleteFormRevision(fullRevision.offline_id));
6855
7104
  });
6856
7105
  const settledPromise = Promise.all([promise, ...attachImagesPromises]).then(() => promise);
6857
7106
  return [fullRevision, settledPromise];
@@ -6893,19 +7142,19 @@ class UserFormService extends BaseApiService {
6893
7142
  async delete(formId2) {
6894
7143
  const { store } = this.client;
6895
7144
  const state = store.getState();
6896
- const userForm = selectUserForm(formId2)(state);
7145
+ const userForm = selectForm(formId2)(state);
6897
7146
  if (!userForm) {
6898
7147
  throw new Error("Expected userForm to exist");
6899
7148
  }
6900
- const userFormSubmissions = selectSubmissionsForForm(formId2)(state);
7149
+ const userFormSubmissions = selectFormSubmissionsOfForm(formId2)(state);
6901
7150
  if (userFormSubmissions && userFormSubmissions.length > 0) {
6902
- store.dispatch(deleteUserFormSubmissions(userFormSubmissions));
7151
+ store.dispatch(deleteFormSubmissions(userFormSubmissions.map(({ offline_id }) => offline_id)));
6903
7152
  }
6904
- const userFormRevisions = selectRevisionsForForm(formId2)(state);
7153
+ const userFormRevisions = selectFormRevisionsOfForm(formId2)(state);
6905
7154
  if (userFormRevisions && userFormRevisions.length > 0) {
6906
- store.dispatch(deleteUserFormRevisions(userFormRevisions));
7155
+ store.dispatch(deleteFormRevisions(userFormRevisions.map(({ offline_id }) => offline_id)));
6907
7156
  }
6908
- store.dispatch(deleteUserForm(formId2));
7157
+ store.dispatch(deleteForm(formId2));
6909
7158
  try {
6910
7159
  return await this.enqueueRequest({
6911
7160
  description: "Delete form",
@@ -6915,12 +7164,12 @@ class UserFormService extends BaseApiService {
6915
7164
  blocks: []
6916
7165
  });
6917
7166
  } catch (e) {
6918
- store.dispatch(addUserForm(userForm));
7167
+ store.dispatch(addForm(userForm));
6919
7168
  if (userFormRevisions && userFormRevisions.length > 0) {
6920
- store.dispatch(addUserFormRevisions(userFormRevisions));
7169
+ store.dispatch(addFormRevisions(userFormRevisions));
6921
7170
  }
6922
7171
  if (userFormSubmissions && userFormSubmissions.length > 0) {
6923
- store.dispatch(addUserFormSubmissions(userFormSubmissions));
7172
+ store.dispatch(addFormSubmissions(userFormSubmissions));
6924
7173
  }
6925
7174
  throw e;
6926
7175
  }
@@ -6934,16 +7183,15 @@ class UserFormService extends BaseApiService {
6934
7183
  blockers: [],
6935
7184
  blocks: []
6936
7185
  });
6937
- store.dispatch(addUserForms(Object.values(result.forms)));
6938
- store.dispatch(addUserFormRevisions(Object.values(result.revisions)));
6939
- store.dispatch(setUserFormRevisionAttachments(Object.values(result.attachments)));
7186
+ store.dispatch(setForms(Object.values(result.forms)));
7187
+ store.dispatch(setFormRevisions(Object.values(result.revisions)));
7188
+ store.dispatch(setFormRevisionAttachments(Object.values(result.attachments)));
6940
7189
  }
6941
7190
  }
6942
7191
  const isArrayOfFiles = (value) => {
6943
7192
  return Array.isArray(value) && value[0] instanceof File;
6944
7193
  };
6945
- const separateFilesFromValues = (payload) => {
6946
- const { values } = payload;
7194
+ const separateFilesFromValues = (values) => {
6947
7195
  const files = {};
6948
7196
  const newValues = {};
6949
7197
  for (const key in values) {
@@ -6958,17 +7206,13 @@ const separateFilesFromValues = (payload) => {
6958
7206
  newValues[key] = value;
6959
7207
  }
6960
7208
  }
6961
- const payloadWithoutFiles = {
6962
- ...payload,
6963
- values: newValues
6964
- };
6965
- return { payloadWithoutFiles, files };
7209
+ return { values: newValues, files };
6966
7210
  };
6967
7211
  class UserFormSubmissionService extends BaseApiService {
6968
7212
  constructor() {
6969
7213
  super(...arguments);
6970
7214
  // Attach files to submission, after uploading them to S3
6971
- __publicField(this, "getAttachFilesPromises", (files, payload) => {
7215
+ __publicField(this, "getAttachFilesPromises", (files, submission) => {
6972
7216
  const { store } = this.client;
6973
7217
  return Object.entries(files).map(async ([key, fileArray]) => {
6974
7218
  const attachResults = [];
@@ -6978,24 +7222,27 @@ class UserFormSubmissionService extends BaseApiService {
6978
7222
  const [fileProps] = await this.client.files.uploadFileToS3(sha1);
6979
7223
  const submissionAttachmentPayload = offline({
6980
7224
  ...fileProps,
6981
- submission: payload.offline_id,
7225
+ submission: submission.offline_id,
6982
7226
  field_identifier: key
6983
7227
  });
6984
7228
  const attach = await this.enqueueRequest({
6985
7229
  description: "Attach file to form submission",
6986
7230
  method: HttpMethod.POST,
6987
- url: `/forms/submission/${payload.offline_id}/attachments/`,
7231
+ url: `/forms/submission/${submission.offline_id}/attachments/`,
6988
7232
  payload: submissionAttachmentPayload,
6989
- blockers: [payload.component, payload.component_stage, payload.issue, payload.form_revision].filter(
6990
- (x) => x !== void 0
6991
- ),
7233
+ blockers: [
7234
+ submission.component,
7235
+ submission.component_stage,
7236
+ submission.issue,
7237
+ submission.form_revision
7238
+ ].filter((x) => x !== void 0),
6992
7239
  blocks: [submissionAttachmentPayload.offline_id]
6993
7240
  });
6994
7241
  const offlinePayload = {
6995
7242
  ...submissionAttachmentPayload,
6996
7243
  file: URL.createObjectURL(file)
6997
7244
  };
6998
- store.dispatch(addUserFormSubmissionAttachment(offlinePayload));
7245
+ store.dispatch(addFormSubmissionAttachment(offlinePayload));
6999
7246
  attachResults.push(attach);
7000
7247
  }
7001
7248
  return attachResults;
@@ -7009,70 +7256,165 @@ class UserFormSubmissionService extends BaseApiService {
7009
7256
  if (!activeProjectId) {
7010
7257
  throw new Error("Expected an active project");
7011
7258
  }
7012
- const { payloadWithoutFiles, files } = separateFilesFromValues(payload);
7259
+ const { values, files } = separateFilesFromValues(payload.values);
7260
+ const offlineSubmission = {
7261
+ ...payload,
7262
+ values,
7263
+ created_by: state.userReducer.currentUser.id,
7264
+ submitted_at: (/* @__PURE__ */ new Date()).toISOString()
7265
+ };
7013
7266
  const promise = this.enqueueRequest({
7014
7267
  description: "Respond to form",
7015
7268
  method: HttpMethod.POST,
7016
7269
  url: `/forms/revisions/${payload.form_revision}/respond/`,
7017
- payload: { ...payloadWithoutFiles, project: activeProjectId },
7270
+ payload: { ...offlineSubmission, project: activeProjectId },
7018
7271
  blockers: [payload.issue, payload.component, payload.component_stage, "add-form-entry"].filter(
7019
7272
  (x) => x !== void 0
7020
7273
  ),
7021
7274
  blocks: [payload.offline_id]
7022
7275
  });
7023
- const attachFilesPromises = this.getAttachFilesPromises(files, payload);
7024
- const now = (/* @__PURE__ */ new Date()).toISOString();
7025
- const fullOfflineResult = {
7026
- ...payload,
7027
- created_by: state.userReducer.currentUser.id,
7028
- created_at: now,
7029
- updated_at: now
7030
- };
7031
- const offlineResultWithoutFiles = {
7032
- ...fullOfflineResult,
7033
- ...payloadWithoutFiles
7034
- };
7035
- store.dispatch(updateOrCreateUserFormSubmission(offlineResultWithoutFiles));
7276
+ const attachFilesPromises = this.getAttachFilesPromises(files, offlineSubmission);
7277
+ store.dispatch(addFormSubmission(offlineSubmission));
7036
7278
  void promise.then((result) => {
7037
7279
  store.dispatch(addActiveProjectFormSubmissionsCount(1));
7038
- store.dispatch(updateOrCreateUserFormSubmission(result));
7280
+ store.dispatch(setFormSubmission(result));
7039
7281
  return result;
7040
7282
  }).catch(() => {
7041
- store.dispatch(deleteUserFormSubmission(payload.offline_id));
7283
+ store.dispatch(deleteFormSubmission(payload.offline_id));
7042
7284
  store.dispatch(addActiveProjectFormSubmissionsCount(-1));
7043
7285
  });
7044
7286
  const settledPromise = Promise.all([promise, ...attachFilesPromises]).then(() => promise);
7045
- return [fullOfflineResult, settledPromise];
7287
+ return [offlineSubmission, settledPromise];
7046
7288
  }
7047
- update(submission) {
7289
+ // Note currently the bulkAdd method is specific to form submissions for components
7290
+ // TODO: adapt the support bulk adding to any model type
7291
+ async bulkAdd(args) {
7292
+ const { form_revision, values: argsValues, componentOfflineIds } = args;
7048
7293
  const { store } = this.client;
7049
- const { payloadWithoutFiles, files } = separateFilesFromValues(submission);
7050
- if (!("created_by" in payloadWithoutFiles) || !("created_at" in payloadWithoutFiles)) {
7051
- throw new Error("Expected payloadWithoutFiles to have created_by and created_at fields.");
7294
+ const offlineSubmissions = [];
7295
+ const offlineAttachments = [];
7296
+ const submissionOfflineIds = [];
7297
+ const submissionsPayload = [];
7298
+ const attachmentsPayload = [];
7299
+ const { values, files } = separateFilesFromValues(argsValues);
7300
+ const submittedAt = (/* @__PURE__ */ new Date()).toISOString();
7301
+ const createdBy = store.getState().userReducer.currentUser.id;
7302
+ for (const component_id of componentOfflineIds) {
7303
+ const submission = offline({
7304
+ form_revision,
7305
+ values,
7306
+ created_by: createdBy,
7307
+ submitted_at: submittedAt,
7308
+ component: component_id
7309
+ });
7310
+ submissionOfflineIds.push(submission.offline_id);
7311
+ submissionsPayload.push({ offline_id: submission.offline_id, component_id });
7312
+ offlineSubmissions.push(submission);
7313
+ for (const [fieldIdentifier, fileArray] of Object.entries(files)) {
7314
+ for (const file of fileArray) {
7315
+ const sha1 = await hashFile(file);
7316
+ await this.client.files.addCache(file, sha1);
7317
+ const offlineAttachment = offline({
7318
+ file_name: file.name,
7319
+ file_sha1: sha1,
7320
+ file: URL.createObjectURL(file),
7321
+ submission: submission.offline_id,
7322
+ field_identifier: fieldIdentifier
7323
+ });
7324
+ offlineAttachments.push(offlineAttachment);
7325
+ attachmentsPayload.push({
7326
+ offline_id: offlineAttachment.offline_id,
7327
+ submission_id: submission.offline_id,
7328
+ sha1,
7329
+ name: file.name,
7330
+ field_identifier: fieldIdentifier
7331
+ });
7332
+ }
7333
+ }
7052
7334
  }
7335
+ const filesRecord = {};
7336
+ for (const file of Object.values(files).flat()) {
7337
+ const sha1 = await hashFile(file);
7338
+ filesRecord[sha1] = {
7339
+ sha1,
7340
+ extension: file.name.split(".").pop() || "",
7341
+ file_type: file.type,
7342
+ size: file.size
7343
+ };
7344
+ }
7345
+ store.dispatch(addFormSubmissions(offlineSubmissions));
7346
+ store.dispatch(addFormSubmissionAttachments(offlineAttachments));
7347
+ const promise = this.enqueueRequest({
7348
+ description: "Bulk add form submissions",
7349
+ method: HttpMethod.POST,
7350
+ url: `/forms/revisions/${form_revision}/bulk-respond/`,
7351
+ payload: {
7352
+ form_data: values,
7353
+ submitted_at: submittedAt,
7354
+ submissions: submissionsPayload,
7355
+ attachments: attachmentsPayload,
7356
+ files: Object.values(filesRecord)
7357
+ },
7358
+ blockers: componentOfflineIds,
7359
+ blocks: submissionOfflineIds
7360
+ });
7361
+ promise.then(({ submissions, attachments, presigned_urls }) => {
7362
+ store.dispatch(updateFormSubmissions(submissions));
7363
+ store.dispatch(updateFormSubmissionAttachments(attachments));
7364
+ for (const [sha1, presigned_url] of Object.entries(presigned_urls)) {
7365
+ const file = filesRecord[sha1];
7366
+ if (!file)
7367
+ continue;
7368
+ void this.enqueueRequest({
7369
+ url: presigned_url.url,
7370
+ description: "Upload file",
7371
+ method: HttpMethod.POST,
7372
+ isExternalUrl: true,
7373
+ isAuthNeeded: false,
7374
+ attachmentHash: sha1,
7375
+ blockers: [`s3-${file.sha1}.${file.extension}`],
7376
+ blocks: [sha1],
7377
+ s3url: presigned_url
7378
+ });
7379
+ }
7380
+ }).catch(() => {
7381
+ store.dispatch(deleteFormSubmissions(submissionOfflineIds));
7382
+ store.dispatch(deleteFormSubmissionAttachments(offlineAttachments.map((x) => x.offline_id)));
7383
+ });
7384
+ return [offlineSubmissions, promise.then(({ submissions }) => submissions)];
7385
+ }
7386
+ update(submission) {
7387
+ const { store } = this.client;
7388
+ const { values, files } = separateFilesFromValues(submission.values);
7053
7389
  const attachFilesPromises = this.getAttachFilesPromises(files, submission);
7054
- const fullResult = {
7055
- ...payloadWithoutFiles,
7056
- updated_at: (/* @__PURE__ */ new Date()).toISOString()
7390
+ const offlineSubmission = {
7391
+ ...submission,
7392
+ values
7057
7393
  };
7058
- store.dispatch(updateOrCreateUserFormSubmission(fullResult));
7394
+ const submissionToBeUpdated = store.getState().formSubmissionReducer.formSubmissions[submission.offline_id];
7395
+ store.dispatch(updateFormSubmission(offlineSubmission));
7059
7396
  const promise = this.enqueueRequest({
7060
7397
  description: "Patch form submission",
7061
7398
  method: HttpMethod.PATCH,
7062
7399
  url: `/forms/submissions/${submission.offline_id}/`,
7063
- payload: fullResult,
7064
- blockers: [fullResult.issue, fullResult.component, fullResult.component_stage].filter(
7400
+ payload: offlineSubmission,
7401
+ blockers: [offlineSubmission.issue, offlineSubmission.component, offlineSubmission.component_stage].filter(
7065
7402
  (x) => x !== void 0
7066
7403
  ),
7067
- blocks: [fullResult.offline_id]
7404
+ blocks: [offlineSubmission.offline_id]
7405
+ });
7406
+ promise.then((createdSubmission) => {
7407
+ store.dispatch(setFormSubmission(createdSubmission));
7408
+ }).catch(() => {
7409
+ store.dispatch(setFormSubmission(submissionToBeUpdated));
7068
7410
  });
7069
- return Promise.all([promise, ...attachFilesPromises]).then(() => promise);
7411
+ return [offlineSubmission, Promise.all([promise, ...attachFilesPromises]).then(() => promise)];
7070
7412
  }
7071
7413
  async delete(submissionId) {
7072
7414
  const { store } = this.client;
7073
7415
  const state = store.getState();
7074
- const submission = state.userFormReducer.submissions[submissionId];
7075
- store.dispatch(deleteUserFormSubmission(submissionId));
7416
+ const submission = state.formSubmissionReducer.formSubmissions[submissionId];
7417
+ store.dispatch(deleteFormSubmission(submissionId));
7076
7418
  store.dispatch(addActiveProjectFormSubmissionsCount(-1));
7077
7419
  try {
7078
7420
  return await this.enqueueRequest({
@@ -7083,10 +7425,8 @@ class UserFormSubmissionService extends BaseApiService {
7083
7425
  blocks: []
7084
7426
  });
7085
7427
  } catch (e) {
7086
- if (submission) {
7087
- store.dispatch(addActiveProjectFormSubmissionsCount(1));
7088
- store.dispatch(updateOrCreateUserFormSubmission(submission));
7089
- }
7428
+ store.dispatch(addActiveProjectFormSubmissionsCount(1));
7429
+ store.dispatch(addFormSubmission(submission));
7090
7430
  throw e;
7091
7431
  }
7092
7432
  }
@@ -7100,7 +7440,7 @@ class UserFormSubmissionService extends BaseApiService {
7100
7440
  blockers: [],
7101
7441
  blocks: []
7102
7442
  });
7103
- store.dispatch(setUserFormSubmissions(submissions));
7443
+ store.dispatch(setFormSubmissions(submissions));
7104
7444
  const attachments = await this.enqueueRequest({
7105
7445
  description: "Fetch form attachments",
7106
7446
  method: HttpMethod.GET,
@@ -7108,7 +7448,7 @@ class UserFormSubmissionService extends BaseApiService {
7108
7448
  blockers: [],
7109
7449
  blocks: []
7110
7450
  });
7111
- store.dispatch(setUserFormSubmissionAttachments(attachments));
7451
+ store.dispatch(setFormSubmissionAttachments(attachments));
7112
7452
  }
7113
7453
  }
7114
7454
  class WorkspaceService extends BaseApiService {
@@ -13966,7 +14306,7 @@ const initialFormValues = (fields, values) => {
13966
14306
  };
13967
14307
  const useAttachImagesToFormRevisionFields = (revision) => {
13968
14308
  const { sdk } = useSDK();
13969
- const attachments = useAppSelector(selectRevisionAttachments((revision == null ? void 0 : revision.offline_id) ?? ""));
14309
+ const attachments = useAppSelector(selectAttachmentsOfFormRevision((revision == null ? void 0 : revision.offline_id) ?? ""));
13970
14310
  return useMemo(() => {
13971
14311
  if (!revision || !attachments)
13972
14312
  return revision;
@@ -14063,7 +14403,7 @@ const FormSubmissionViewer = memo(
14063
14403
  return formRevisionToSchema(revisionWithImages, { readonly: true });
14064
14404
  }, [revisionWithImages]);
14065
14405
  const submissionValuesWithAttachments = useMemo(() => {
14066
- const attachments = selectSubmissionAttachments(submission.offline_id)(sdk.store.getState()) ?? [];
14406
+ const attachments = selectAttachmentsOfFormSubmission(submission.offline_id)(sdk.store.getState()) ?? [];
14067
14407
  const downloadedAttachments = {};
14068
14408
  for (const attachment of attachments) {
14069
14409
  const promise = sdk.files.fetchFileFromUrl(attachment.file, attachment.file_sha1, attachment.file_name);
@@ -14113,8 +14453,8 @@ const FormBrowser = memo(
14113
14453
  }
14114
14454
  return ret;
14115
14455
  }, [filter, maxResults, ownerFilter]);
14116
- const userForms = useAppSelector(selectFilteredUserForms(ownerFilterOptions)) ?? [];
14117
- const userFormMapping = useAppSelector(selectUserFormMapping);
14456
+ const userForms = useAppSelector(selectFilteredForms(ownerFilterOptions)) ?? [];
14457
+ const userFormMapping = useAppSelector(selectFormMapping);
14118
14458
  const attachableUserForms = userForms.filter((form) => !form.component_type);
14119
14459
  const attachableUserFormMapping = Object.values(userFormMapping).filter(
14120
14460
  (form) => !form.component_type
@@ -14147,7 +14487,7 @@ const FormBrowser = memo(
14147
14487
  const handleChange = useCallback((e) => {
14148
14488
  setFilter(e.currentTarget.value);
14149
14489
  }, []);
14150
- const numberOfForms = useAppSelector(selectNumberOfGeneralUserForms) || 0;
14490
+ const numberOfForms = useAppSelector(selectGeneralFormCount) || 0;
14151
14491
  const numberOfHiddenForms = numberOfForms - attachableUserForms.length;
14152
14492
  const overflowMessage = attachableUserForms.length == maxResults && numberOfHiddenForms > 0 ? `Only the first ${maxResults} results are shown (${numberOfHiddenForms} hidden)` : numberOfHiddenForms > 0 && `${numberOfHiddenForms} hidden forms`;
14153
14493
  return /* @__PURE__ */ jsxs(Flex$1, { ref, direction: "column", gap: "2", children: [
@@ -14241,16 +14581,13 @@ const FormSubmissionBrowserEntry = memo((props) => {
14241
14581
  const { submission, onSubmissionClick, compact, labelType, rowDecorator } = props;
14242
14582
  const currentUser = useAppSelector(selectCurrentUser);
14243
14583
  const createdBy = useAppSelector(selectUser("created_by" in submission ? submission.created_by : currentUser.id));
14244
- const dateToUse = getCreatedAtOrSubmittedAtDate(submission);
14245
- const formattedDateTime = isToday(dateToUse) ? dateToUse.toLocaleTimeString([], {
14246
- hour: "2-digit",
14247
- minute: "2-digit"
14248
- }) : getLocalDateString(dateToUse);
14584
+ const dateToUse = submission.submitted_at;
14585
+ const formattedDateTime = getLocalDateString(dateToUse);
14249
14586
  const revision = useAppSelector(selectFormRevision(submission.form_revision));
14250
14587
  if (!revision) {
14251
14588
  throw new Error(`Could not find revision ${submission.form_revision} for submission ${submission.offline_id}.`);
14252
14589
  }
14253
- const latestRevisionNumber = (_a2 = useAppSelector(selectLatestFormRevision(revision.form))) == null ? void 0 : _a2.revision;
14590
+ const latestRevisionNumber = (_a2 = useAppSelector(selectLatestFormRevisionOfForm(revision.form))) == null ? void 0 : _a2.revision;
14254
14591
  const creatorProfileSrc = useFileSrc({
14255
14592
  file: (createdBy == null ? void 0 : createdBy.profile.file) ?? null,
14256
14593
  fileSha1: (createdBy == null ? void 0 : createdBy.profile.file_sha1) ?? null
@@ -14281,10 +14618,6 @@ const FormSubmissionBrowserEntry = memo((props) => {
14281
14618
  return row;
14282
14619
  });
14283
14620
  FormSubmissionBrowserEntry.displayName = "FormSubmissionBrowserEntry";
14284
- const getCreatedAtOrSubmittedAtDate = (submission) => {
14285
- const date = "created_at" in submission ? submission.created_at : submission.submitted_at;
14286
- return new Date(date);
14287
- };
14288
14621
  const FormSubmissionBrowser = memo((props) => {
14289
14622
  const {
14290
14623
  formId: formId2,
@@ -14298,10 +14631,10 @@ const FormSubmissionBrowser = memo((props) => {
14298
14631
  if (!!formId2 === !!propSubmissions) {
14299
14632
  throw new Error("Either formId or submissions must be provided, but not both.");
14300
14633
  }
14301
- const submissions = useAppSelector(propSubmissions ? () => propSubmissions : selectSubmissionsForForm(formId2));
14634
+ const submissions = useAppSelector(propSubmissions ? () => propSubmissions : selectFormSubmissionsOfForm(formId2));
14302
14635
  const sortedSubmissions = useMemo(
14303
14636
  () => submissions == null ? void 0 : submissions.sort((a, b) => {
14304
- return getCreatedAtOrSubmittedAtDate(b).getTime() - getCreatedAtOrSubmittedAtDate(a).getTime();
14637
+ return a.submitted_at.localeCompare(b.submitted_at);
14305
14638
  }),
14306
14639
  [submissions]
14307
14640
  );
@@ -15619,6 +15952,7 @@ export {
15619
15952
  VerificationCodeType,
15620
15953
  WorkspaceService,
15621
15954
  YELLOW,
15955
+ _selectLatestFormRevision,
15622
15956
  _setLatestRetryTime,
15623
15957
  acceptProjectInvite,
15624
15958
  addActiveProjectFormSubmissionsCount,
@@ -15631,9 +15965,21 @@ export {
15631
15965
  addComponentTypeAttachment,
15632
15966
  addComponentTypeAttachments,
15633
15967
  addComponentsInBatches,
15968
+ addDocumentAttachment,
15969
+ addDocumentAttachments,
15634
15970
  addDocuments,
15635
15971
  addEmailDomain,
15636
15972
  addFavouriteProjectId,
15973
+ addForm,
15974
+ addFormRevision,
15975
+ addFormRevisionAttachment,
15976
+ addFormRevisionAttachments,
15977
+ addFormRevisions,
15978
+ addFormSubmission,
15979
+ addFormSubmissionAttachment,
15980
+ addFormSubmissionAttachments,
15981
+ addFormSubmissions,
15982
+ addForms,
15637
15983
  addIssue,
15638
15984
  addIssueAttachment,
15639
15985
  addIssueAttachments,
@@ -15654,13 +16000,6 @@ export {
15654
16000
  addStageCompletions,
15655
16001
  addStages,
15656
16002
  addToRecentIssues,
15657
- addUserForm,
15658
- addUserFormRevision,
15659
- addUserFormRevisionAttachment,
15660
- addUserFormRevisions,
15661
- addUserFormSubmissionAttachment,
15662
- addUserFormSubmissions,
15663
- addUserForms,
15664
16003
  addUsers,
15665
16004
  addWorkspace,
15666
16005
  areArraysEqual,
@@ -15681,6 +16020,7 @@ export {
15681
16020
  componentStageSlice,
15682
16021
  componentTypeReducer,
15683
16022
  componentTypeSlice,
16023
+ constructUploadedFilePayloads,
15684
16024
  coordinatesAreEqual,
15685
16025
  coordinatesToLiteral,
15686
16026
  coordinatesToPointGeometry,
@@ -15691,12 +16031,16 @@ export {
15691
16031
  defaultBadgeColor,
15692
16032
  defaultStore,
15693
16033
  deleteComponentType,
16034
+ deleteForm,
16035
+ deleteFormRevision,
16036
+ deleteFormRevisionAttachment,
16037
+ deleteFormRevisionAttachments,
16038
+ deleteFormRevisions,
16039
+ deleteFormSubmission,
16040
+ deleteFormSubmissionAttachment,
16041
+ deleteFormSubmissionAttachments,
16042
+ deleteFormSubmissions,
15694
16043
  deleteProject,
15695
- deleteUserForm,
15696
- deleteUserFormRevision,
15697
- deleteUserFormRevisions,
15698
- deleteUserFormSubmission,
15699
- deleteUserFormSubmissions,
15700
16044
  dequeue,
15701
16045
  deserialize,
15702
16046
  deserializeField,
@@ -15725,7 +16069,13 @@ export {
15725
16069
  fileSlice,
15726
16070
  fileToBlob,
15727
16071
  flipCoordinates,
16072
+ formReducer,
16073
+ formRevisionReducer,
15728
16074
  formRevisionToSchema,
16075
+ formRevisionsSlice,
16076
+ formSlice,
16077
+ formSubmissionReducer,
16078
+ formSubmissionSlice,
15729
16079
  index as forms,
15730
16080
  fullComponentMarkerSize,
15731
16081
  generateBadgeColors,
@@ -15794,6 +16144,8 @@ export {
15794
16144
  removeComponentAttachments,
15795
16145
  removeComponentTypeAttachment,
15796
16146
  removeComponentTypeAttachments,
16147
+ removeDocumentAttachment,
16148
+ removeDocumentAttachments,
15797
16149
  removeDocuments,
15798
16150
  removeEmailDomain,
15799
16151
  removeFavouriteProjectId,
@@ -15841,6 +16193,7 @@ export {
15841
16193
  selectAllAttachments,
15842
16194
  selectAllComponentAttachments,
15843
16195
  selectAllComponentTypeAttachments,
16196
+ selectAllDocumentAttachments,
15844
16197
  selectAllProjectAttachments,
15845
16198
  selectAncestorIdsOfDocument,
15846
16199
  selectAppearance,
@@ -15848,6 +16201,10 @@ export {
15848
16201
  selectAttachmentsOfComponentByType,
15849
16202
  selectAttachmentsOfComponentType,
15850
16203
  selectAttachmentsOfComponentTypeByType,
16204
+ selectAttachmentsOfDocument,
16205
+ selectAttachmentsOfDocumentByType,
16206
+ selectAttachmentsOfFormRevision,
16207
+ selectAttachmentsOfFormSubmission,
15851
16208
  selectAttachmentsOfIssue,
15852
16209
  selectAttachmentsOfIssueByType,
15853
16210
  selectAttachmentsOfProject,
@@ -15863,11 +16220,11 @@ export {
15863
16220
  selectCompletedStageIdsForComponent,
15864
16221
  selectCompletedStages,
15865
16222
  selectComponent,
16223
+ selectComponentAttachment,
15866
16224
  selectComponentAttachmentMapping,
15867
- selectComponentSubmissionMapping,
15868
16225
  selectComponentType,
16226
+ selectComponentTypeAttachment,
15869
16227
  selectComponentTypeAttachmentMapping,
15870
- selectComponentTypeForm,
15871
16228
  selectComponentTypeFromComponent,
15872
16229
  selectComponentTypeFromComponents,
15873
16230
  selectComponentTypeStagesMapping,
@@ -15883,6 +16240,8 @@ export {
15883
16240
  selectCurrentUser,
15884
16241
  selectDeletedRequests,
15885
16242
  selectDocument,
16243
+ selectDocumentAttachment,
16244
+ selectDocumentAttachmentMapping,
15886
16245
  selectDocuments,
15887
16246
  selectDocumentsMapping,
15888
16247
  selectEmailDomainsAsMapping,
@@ -15895,8 +16254,24 @@ export {
15895
16254
  selectExpandedSections,
15896
16255
  selectFavouriteProjects,
15897
16256
  selectFileAttachmentsOfIssue,
15898
- selectFilteredUserForms,
16257
+ selectFilteredForms,
16258
+ selectForm,
16259
+ selectFormMapping,
16260
+ selectFormOfComponentType,
15899
16261
  selectFormRevision,
16262
+ selectFormRevisionMapping,
16263
+ selectFormRevisions,
16264
+ selectFormRevisionsOfForm,
16265
+ selectFormSubmission,
16266
+ selectFormSubmissionAttachmentsMapping,
16267
+ selectFormSubmissions,
16268
+ selectFormSubmissionsByComponents,
16269
+ selectFormSubmissionsMapping,
16270
+ selectFormSubmissionsOfComponent,
16271
+ selectFormSubmissionsOfForm,
16272
+ selectFormSubmissionsOfIssue,
16273
+ selectFormsCount,
16274
+ selectGeneralFormCount,
15900
16275
  selectHiddenCategoryCount,
15901
16276
  selectHiddenComponentTypeIds,
15902
16277
  selectIsFetchingInitialData,
@@ -15904,16 +16279,17 @@ export {
15904
16279
  selectIsLoading,
15905
16280
  selectIsLoggedIn,
15906
16281
  selectIssue,
16282
+ selectIssueAttachment,
15907
16283
  selectIssueAttachmentMapping,
15908
16284
  selectIssueAttachments,
15909
16285
  selectIssueMapping,
15910
16286
  selectIssueUpdateMapping,
15911
16287
  selectIssueUpdatesOfIssue,
15912
16288
  selectIssues,
15913
- selectLatestFormRevision,
16289
+ selectLatestFormRevisionByForm,
16290
+ selectLatestFormRevisionOfForm,
16291
+ selectLatestFormRevisionsOfComponentTypes,
15914
16292
  selectLatestRetryTime,
15915
- selectLatestRevisionByFormId,
15916
- selectLatestRevisionsFromComponentTypeIds,
15917
16293
  selectLicense,
15918
16294
  selectLicenseForProject,
15919
16295
  selectLicenses,
@@ -15922,8 +16298,6 @@ export {
15922
16298
  selectMapStyle,
15923
16299
  selectNumberOfComponentTypesMatchingCaseInsensitiveName,
15924
16300
  selectNumberOfComponentsOfComponentType,
15925
- selectNumberOfGeneralUserForms,
15926
- selectNumberOfUserForms,
15927
16301
  selectOrganization,
15928
16302
  selectOrganizationAccess,
15929
16303
  selectOrganizationAccessForUser,
@@ -15951,8 +16325,6 @@ export {
15951
16325
  selectRecentIssuesAsSearchResults,
15952
16326
  selectRecentProjects,
15953
16327
  selectRehydrated,
15954
- selectRevisionAttachments,
15955
- selectRevisionsForForm,
15956
16328
  selectRootDocuments,
15957
16329
  selectShowTooltips,
15958
16330
  selectSortedEmailDomains,
@@ -15967,16 +16339,10 @@ export {
15967
16339
  selectStagesFromComponentType,
15968
16340
  selectStagesFromComponentTypeIds,
15969
16341
  selectStagesFromStageIds,
15970
- selectSubmissionAttachments,
15971
- selectSubmissionsForComponent,
15972
- selectSubmissionsForForm,
15973
- selectSubmissionsForIssue,
15974
16342
  selectUploadUrl,
15975
16343
  selectUsedColors,
15976
16344
  selectUser,
15977
- selectUserForm,
15978
- selectUserFormMapping,
15979
- selectUserFormSubmission,
16345
+ selectUserFormRevisionAttachmentsMapping,
15980
16346
  selectUsersAsMapping,
15981
16347
  selectVisibleStatuses,
15982
16348
  selectVisibleUserIds,
@@ -15997,11 +16363,19 @@ export {
15997
16363
  setComponents,
15998
16364
  setCreateProjectType,
15999
16365
  setCurrentUser,
16366
+ setDocumentAttachments,
16000
16367
  setDocuments,
16001
16368
  setEmailDomains,
16002
16369
  setEnableClustering,
16003
16370
  setEnableDuplicateIssues,
16004
16371
  setEnablePlacementMode,
16372
+ setFormRevision,
16373
+ setFormRevisionAttachments,
16374
+ setFormRevisions,
16375
+ setFormSubmission,
16376
+ setFormSubmissionAttachments,
16377
+ setFormSubmissions,
16378
+ setForms,
16005
16379
  setIsFetchingInitialData,
16006
16380
  setIsImportingProjectFile,
16007
16381
  setIsLoading,
@@ -16026,9 +16400,6 @@ export {
16026
16400
  setTokens,
16027
16401
  setTourStep,
16028
16402
  setUploadUrl,
16029
- setUserFormRevisionAttachments,
16030
- setUserFormSubmissionAttachments,
16031
- setUserFormSubmissions,
16032
16403
  setUsers,
16033
16404
  setVisibleStatuses,
16034
16405
  setVisibleUserIds,
@@ -16051,12 +16422,15 @@ export {
16051
16422
  updateComponent,
16052
16423
  updateComponentAttachment,
16053
16424
  updateComponentTypeAttachment,
16425
+ updateDocumentAttachment,
16054
16426
  updateDocuments,
16427
+ updateFormSubmission,
16428
+ updateFormSubmissionAttachments,
16429
+ updateFormSubmissions,
16055
16430
  updateIssue,
16056
16431
  updateIssueAttachment,
16057
16432
  updateLicense,
16058
16433
  updateOrCreateProject,
16059
- updateOrCreateUserFormSubmission,
16060
16434
  updateOrganizationAccess,
16061
16435
  updateProjectAccess,
16062
16436
  updateProjectAttachment,
@@ -16070,8 +16444,6 @@ export {
16070
16444
  useFormikInput,
16071
16445
  useMemoCompare,
16072
16446
  useSDK,
16073
- userFormReducer,
16074
- userFormSlice,
16075
16447
  userReducer,
16076
16448
  userSlice,
16077
16449
  valueIsFile,