@overmap-ai/core 1.0.50-bulk-form-submission.3 → 1.0.50-document-attachments.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -631,15 +631,15 @@ const wrapMigration = (migrator) => (state) => {
631
631
  };
632
632
  const migrations = [initialVersioning, signOut, signOut, createOutboxState];
633
633
  const manifest = Object.fromEntries(migrations.map((migration2, i) => [i, wrapMigration(migration2)]));
634
- const initialState$p = {
634
+ const initialState$n = {
635
635
  accessToken: "",
636
636
  refreshToken: "",
637
637
  isLoggedIn: false
638
638
  };
639
639
  const authSlice = createSlice({
640
640
  name: "auth",
641
- initialState: initialState$p,
642
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$p)),
641
+ initialState: initialState$n,
642
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$n)),
643
643
  reducers: {
644
644
  setTokens: (state, action) => {
645
645
  state.accessToken = action.payload.accessToken;
@@ -804,19 +804,6 @@ function downloadInMemoryFile(filename, text) {
804
804
  element.click();
805
805
  document.body.removeChild(element);
806
806
  }
807
- const constructUploadedFilePayloads = async (files) => {
808
- const filePayloads = {};
809
- for (const file of files) {
810
- const sha1 = await hashFile(file);
811
- filePayloads[sha1] = {
812
- sha1,
813
- extension: file.name.split(".").pop() || "",
814
- file_type: file.type,
815
- size: file.size
816
- };
817
- }
818
- return Object.values(filePayloads);
819
- };
820
807
  const fileToBlob = async (dataUrl) => {
821
808
  return (await fetch(dataUrl)).blob();
822
809
  };
@@ -1383,7 +1370,7 @@ const getLocalRelativeDateString = memoize((date, min, max) => {
1383
1370
  return getLocalDateString(date);
1384
1371
  return relative.format(days, "days");
1385
1372
  });
1386
- const initialState$o = {
1373
+ const initialState$m = {
1387
1374
  categories: {},
1388
1375
  usedCategoryColors: [],
1389
1376
  categoryVisibility: {
@@ -1393,8 +1380,8 @@ const initialState$o = {
1393
1380
  };
1394
1381
  const categorySlice = createSlice({
1395
1382
  name: "categories",
1396
- initialState: initialState$o,
1397
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$o)),
1383
+ initialState: initialState$m,
1384
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$m)),
1398
1385
  reducers: {
1399
1386
  setCategories: (state, action) => {
1400
1387
  if (!Array.isArray(action.payload))
@@ -1563,14 +1550,14 @@ function removeAttachments(state, action) {
1563
1550
  delete state.attachments[attachmentId];
1564
1551
  }
1565
1552
  }
1566
- const initialState$n = {
1553
+ const initialState$l = {
1567
1554
  components: {},
1568
1555
  attachments: {}
1569
1556
  };
1570
1557
  const componentSlice = createSlice({
1571
1558
  name: "components",
1572
- initialState: initialState$n,
1573
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$n)),
1559
+ initialState: initialState$l,
1560
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$l)),
1574
1561
  reducers: {
1575
1562
  addComponent: (state, action) => {
1576
1563
  state.components[action.payload.offline_id] = action.payload;
@@ -1726,13 +1713,13 @@ const {
1726
1713
  removeAllComponentsOfType
1727
1714
  } = componentSlice.actions;
1728
1715
  const componentReducer = componentSlice.reducer;
1729
- const initialState$m = {
1716
+ const initialState$k = {
1730
1717
  completionsByComponentId: {}
1731
1718
  };
1732
1719
  const componentStageCompletionSlice = createSlice({
1733
1720
  name: "componentStageCompletions",
1734
- initialState: initialState$m,
1735
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$m)),
1721
+ initialState: initialState$k,
1722
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$k)),
1736
1723
  reducers: {
1737
1724
  addStageCompletion: (state, action) => {
1738
1725
  let stageToCompletionDateMapping = state.completionsByComponentId[action.payload.component];
@@ -1783,13 +1770,13 @@ const selectCompletedStageIdsForComponent = (component) => (state) => {
1783
1770
  return Object.keys(state.componentStageCompletionReducer.completionsByComponentId[component.offline_id] ?? {});
1784
1771
  };
1785
1772
  const componentStageCompletionReducer = componentStageCompletionSlice.reducer;
1786
- const initialState$l = {
1773
+ const initialState$j = {
1787
1774
  stages: {}
1788
1775
  };
1789
1776
  const componentStageSlice = createSlice({
1790
1777
  name: "componentStages",
1791
- initialState: initialState$l,
1792
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$l)),
1778
+ initialState: initialState$j,
1779
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$j)),
1793
1780
  reducers: {
1794
1781
  addStages: (state, action) => {
1795
1782
  Object.assign(state.stages, toOfflineIdRecord(action.payload));
@@ -1899,15 +1886,15 @@ const selectStageFormIdsFromStageIds = restructureCreateSelectorWithArgs(
1899
1886
  );
1900
1887
  const { addStages, updateStages, removeStages, linkStageToForm, unlinkStageToForm } = componentStageSlice.actions;
1901
1888
  const componentStageReducer = componentStageSlice.reducer;
1902
- const initialState$k = {
1889
+ const initialState$i = {
1903
1890
  componentTypes: {},
1904
1891
  hiddenComponentTypeIds: {},
1905
1892
  attachments: {}
1906
1893
  };
1907
1894
  const componentTypeSlice = createSlice({
1908
1895
  name: "componentTypes",
1909
- initialState: initialState$k,
1910
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$k)),
1896
+ initialState: initialState$i,
1897
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$i)),
1911
1898
  reducers: {
1912
1899
  addComponentType: (state, action) => {
1913
1900
  state.componentTypes[action.payload.offline_id] = action.payload;
@@ -1975,9 +1962,6 @@ const selectAllComponentTypeAttachments = createSelector(
1975
1962
  [selectComponentTypeAttachmentMapping],
1976
1963
  (mapping) => Object.values(mapping)
1977
1964
  );
1978
- const selectComponentTypeAttachment = (attachmentId) => (state) => {
1979
- return state.componentTypeReducer.attachments[attachmentId];
1980
- };
1981
1965
  const selectAttachmentsOfComponentType = restructureCreateSelectorWithArgs(
1982
1966
  createSelector(
1983
1967
  [selectAllComponentTypeAttachments, (_state, componentTypeId) => componentTypeId],
@@ -2018,13 +2002,13 @@ const {
2018
2002
  deleteComponentType
2019
2003
  } = componentTypeSlice.actions;
2020
2004
  const componentTypeReducer = componentTypeSlice.reducer;
2021
- const initialState$j = {
2005
+ const initialState$h = {
2022
2006
  workspaces: {},
2023
2007
  activeWorkspaceId: null
2024
2008
  };
2025
2009
  const workspaceSlice = createSlice({
2026
2010
  name: "workspace",
2027
- initialState: initialState$j,
2011
+ initialState: initialState$h,
2028
2012
  // The `reducers` field lets us define reducers and generate associated actions
2029
2013
  reducers: {
2030
2014
  setWorkspaces: (state, action) => {
@@ -2081,7 +2065,7 @@ const selectPermittedWorkspaceIds = createSelector(
2081
2065
  );
2082
2066
  const workspaceReducer = workspaceSlice.reducer;
2083
2067
  const maxRecentIssues = 10;
2084
- const initialState$i = {
2068
+ const initialState$g = {
2085
2069
  issues: {},
2086
2070
  attachments: {},
2087
2071
  comments: {},
@@ -2093,9 +2077,9 @@ const initialState$i = {
2093
2077
  };
2094
2078
  const issueSlice = createSlice({
2095
2079
  name: "issues",
2096
- initialState: initialState$i,
2080
+ initialState: initialState$g,
2097
2081
  extraReducers: (builder) => builder.addCase("RESET", (state) => {
2098
- Object.assign(state, initialState$i);
2082
+ Object.assign(state, initialState$g);
2099
2083
  }),
2100
2084
  reducers: {
2101
2085
  setIssues: (state, action) => {
@@ -2503,15 +2487,15 @@ const selectRecentIssuesAsSearchResults = createSelector(
2503
2487
  }
2504
2488
  );
2505
2489
  const issueReducer = issueSlice.reducer;
2506
- const initialState$h = {
2490
+ const initialState$f = {
2507
2491
  s3Urls: {}
2508
2492
  };
2509
2493
  const msPerHour = 1e3 * 60 * 60;
2510
2494
  const msPerWeek = msPerHour * 24 * 7;
2511
2495
  const fileSlice = createSlice({
2512
2496
  name: "file",
2513
- initialState: initialState$h,
2514
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$h)),
2497
+ initialState: initialState$f,
2498
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$f)),
2515
2499
  reducers: {
2516
2500
  setUploadUrl: (state, action) => {
2517
2501
  const { url, fields, sha1 } = action.payload;
@@ -2538,7 +2522,7 @@ const selectUploadUrl = (sha1) => (state) => {
2538
2522
  return url;
2539
2523
  };
2540
2524
  const fileReducer = fileSlice.reducer;
2541
- const initialState$g = {
2525
+ const initialState$e = {
2542
2526
  // TODO: Change first MapStyle.SATELLITE to MaptStyle.None when project creation map is fixed
2543
2527
  mapStyle: MapStyle.SATELLITE,
2544
2528
  showTooltips: false,
@@ -2546,8 +2530,8 @@ const initialState$g = {
2546
2530
  };
2547
2531
  const mapSlice = createSlice({
2548
2532
  name: "map",
2549
- initialState: initialState$g,
2550
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$g)),
2533
+ initialState: initialState$e,
2534
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$e)),
2551
2535
  reducers: {
2552
2536
  setMapStyle: (state, action) => {
2553
2537
  state.mapStyle = action.payload;
@@ -2616,7 +2600,7 @@ var LicenseStatus = /* @__PURE__ */ ((LicenseStatus2) => {
2616
2600
  LicenseStatus2[LicenseStatus2["PAST_DUE"] = 8] = "PAST_DUE";
2617
2601
  return LicenseStatus2;
2618
2602
  })(LicenseStatus || {});
2619
- const initialState$f = {
2603
+ const initialState$d = {
2620
2604
  users: {},
2621
2605
  currentUser: {
2622
2606
  id: 0,
@@ -2627,8 +2611,8 @@ const initialState$f = {
2627
2611
  };
2628
2612
  const userSlice = createSlice({
2629
2613
  name: "users",
2630
- initialState: initialState$f,
2631
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$f)),
2614
+ initialState: initialState$d,
2615
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$d)),
2632
2616
  reducers: {
2633
2617
  setUsers: (state, action) => {
2634
2618
  const usersMapping = {};
@@ -2690,13 +2674,13 @@ const selectUser = (userId) => (state) => {
2690
2674
  const selectUsersAsMapping = (state) => state.userReducer.users;
2691
2675
  const selectFavouriteProjects = (state) => state.userReducer.currentUser.profile.favourite_project_ids;
2692
2676
  const userReducer = userSlice.reducer;
2693
- const initialState$e = {
2677
+ const initialState$c = {
2694
2678
  organizationAccesses: {}
2695
2679
  };
2696
2680
  const organizationAccessSlice = createSlice({
2697
2681
  name: "organizationAccess",
2698
- initialState: initialState$e,
2699
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$e)),
2682
+ initialState: initialState$c,
2683
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$c)),
2700
2684
  reducers: {
2701
2685
  setOrganizationAccesses: (state, action) => {
2702
2686
  if (!Array.isArray(action.payload))
@@ -2759,13 +2743,13 @@ const selectOrganizationAccessUserMapping = (state) => {
2759
2743
  return organizationAccesses;
2760
2744
  };
2761
2745
  const organizationAccessReducer = organizationAccessSlice.reducer;
2762
- const initialState$d = {
2746
+ const initialState$b = {
2763
2747
  licenses: {}
2764
2748
  };
2765
2749
  const licenseSlice = createSlice({
2766
2750
  name: "license",
2767
- initialState: initialState$d,
2768
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$d)),
2751
+ initialState: initialState$b,
2752
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$b)),
2769
2753
  reducers: {
2770
2754
  setLicenses: (state, action) => {
2771
2755
  if (!Array.isArray(action.payload))
@@ -2810,13 +2794,13 @@ const selectLicensesForProjectsMapping = createSelector(
2810
2794
  (licenses) => Object.values(licenses).filter((license) => license.project).reduce((accum, license) => ({ ...accum, [license.project]: license }), {})
2811
2795
  );
2812
2796
  const licenseReducer = licenseSlice.reducer;
2813
- const initialState$c = {
2797
+ const initialState$a = {
2814
2798
  projectAccesses: {}
2815
2799
  };
2816
2800
  const projectAccessSlice = createSlice({
2817
2801
  name: "projectAccess",
2818
- initialState: initialState$c,
2819
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$c)),
2802
+ initialState: initialState$a,
2803
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$a)),
2820
2804
  reducers: {
2821
2805
  setProjectAccesses: (state, action) => {
2822
2806
  if (!Array.isArray(action.payload))
@@ -2884,7 +2868,7 @@ const selectProjectAccessUserMapping = (state) => {
2884
2868
  return projectAccesses;
2885
2869
  };
2886
2870
  const projectAccessReducer = projectAccessSlice.reducer;
2887
- const initialState$b = {
2871
+ const initialState$9 = {
2888
2872
  projects: {},
2889
2873
  activeProjectId: null,
2890
2874
  recentProjectIds: [],
@@ -2894,7 +2878,7 @@ const initialState$b = {
2894
2878
  };
2895
2879
  const projectSlice = createSlice({
2896
2880
  name: "projects",
2897
- initialState: initialState$b,
2881
+ initialState: initialState$9,
2898
2882
  reducers: {
2899
2883
  setProjects: (state, action) => {
2900
2884
  const projectsMap = {};
@@ -3081,14 +3065,14 @@ const selectAttachmentsOfProjectByType = restructureCreateSelectorWithArgs(
3081
3065
  }
3082
3066
  )
3083
3067
  );
3084
- const initialState$a = {
3068
+ const initialState$8 = {
3085
3069
  organizations: {},
3086
3070
  activeOrganizationId: null
3087
3071
  };
3088
3072
  const organizationSlice = createSlice({
3089
3073
  name: "organizations",
3090
- initialState: initialState$a,
3091
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$a)),
3074
+ initialState: initialState$8,
3075
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$8)),
3092
3076
  reducers: {
3093
3077
  setOrganizations: (state, action) => {
3094
3078
  for (const org of action.payload) {
@@ -3207,14 +3191,14 @@ const createOfflineAction = (request2, baseUrl) => {
3207
3191
  }
3208
3192
  };
3209
3193
  };
3210
- const initialState$9 = {
3194
+ const initialState$7 = {
3211
3195
  deletedRequests: [],
3212
3196
  latestRetryTime: 0
3213
3197
  };
3214
3198
  const outboxSlice = createSlice({
3215
3199
  name: "outbox",
3216
- initialState: initialState$9,
3217
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$9)),
3200
+ initialState: initialState$7,
3201
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$7)),
3218
3202
  reducers: {
3219
3203
  // enqueueActions is a reducer that does nothing but enqueue API request to the Redux Offline outbox
3220
3204
  // Whenever an issue is being created, a reducer addIssue() is responsible for adding it to the offline store
@@ -3246,7 +3230,7 @@ const selectDeletedRequests = (state) => state.outboxReducer.deletedRequests;
3246
3230
  const selectLatestRetryTime = (state) => state.outboxReducer.latestRetryTime;
3247
3231
  const { enqueueRequest, markForDeletion, markAsDeleted, _setLatestRetryTime } = outboxSlice.actions;
3248
3232
  const outboxReducer = outboxSlice.reducer;
3249
- const initialState$8 = {
3233
+ const initialState$6 = {
3250
3234
  projectFiles: {},
3251
3235
  activeProjectFileId: null,
3252
3236
  isImportingProjectFile: false,
@@ -3254,8 +3238,8 @@ const initialState$8 = {
3254
3238
  };
3255
3239
  const projectFileSlice = createSlice({
3256
3240
  name: "projectFiles",
3257
- initialState: initialState$8,
3258
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$8)),
3241
+ initialState: initialState$6,
3242
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$6)),
3259
3243
  reducers: {
3260
3244
  addOrReplaceProjectFiles: (state, action) => {
3261
3245
  for (let fileObj of action.payload) {
@@ -3356,12 +3340,12 @@ const selectProjectFiles = createSelector(
3356
3340
  const selectActiveProjectFileId = (state) => state.projectFileReducer.activeProjectFileId;
3357
3341
  const selectIsImportingProjectFile = (state) => state.projectFileReducer.isImportingProjectFile;
3358
3342
  const projectFileReducer = projectFileSlice.reducer;
3359
- const initialState$7 = {
3343
+ const initialState$5 = {
3360
3344
  isRehydrated: false
3361
3345
  };
3362
3346
  const rehydratedSlice = createSlice({
3363
3347
  name: "rehydrated",
3364
- initialState: initialState$7,
3348
+ initialState: initialState$5,
3365
3349
  // The `reducers` field lets us define reducers and generate associated actions
3366
3350
  reducers: {
3367
3351
  setRehydrated: (state, action) => {
@@ -3371,7 +3355,7 @@ const rehydratedSlice = createSlice({
3371
3355
  });
3372
3356
  const selectRehydrated = (state) => state.rehydratedReducer.isRehydrated;
3373
3357
  const rehydratedReducer = rehydratedSlice.reducer;
3374
- const initialState$6 = {
3358
+ const initialState$4 = {
3375
3359
  useIssueTemplate: false,
3376
3360
  placementMode: false,
3377
3361
  enableClustering: false,
@@ -3388,8 +3372,8 @@ const initialState$6 = {
3388
3372
  };
3389
3373
  const settingSlice = createSlice({
3390
3374
  name: "settings",
3391
- initialState: initialState$6,
3392
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$6)),
3375
+ initialState: initialState$4,
3376
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$4)),
3393
3377
  reducers: {
3394
3378
  setEnableDuplicateIssues: (state, action) => {
3395
3379
  state.useIssueTemplate = action.payload;
@@ -3435,248 +3419,146 @@ const selectAppearance = (state) => state.settingReducer.appearance;
3435
3419
  const settingReducer = settingSlice.reducer;
3436
3420
  const selectIsFetchingInitialData = (state) => state.settingReducer.isFetchingInitialData;
3437
3421
  const selectIsLoading = (state) => state.settingReducer.isLoading;
3438
- const LATEST_FORM_REVISION_CACHE = {};
3439
- function considerCachingFormRevision(formRevision, formId2, preferPending = false) {
3422
+ const LATEST_REVISION_CACHE = {};
3423
+ function considerCachingRevision(revision, formId2, preferPending = false) {
3440
3424
  var _a2;
3441
- if (!formRevision) {
3425
+ if (!revision) {
3442
3426
  if (!formId2) {
3443
- throw new Error("If form revision is null, formId is required.");
3427
+ throw new Error("If revision is null, formId is required.");
3444
3428
  }
3445
- const currentLatestFormRevision = getLatestFormRevisionFromCache(formId2);
3446
- if (currentLatestFormRevision)
3429
+ const currentLatestRevision = getLatestRevisionFromCache(formId2);
3430
+ if (currentLatestRevision)
3447
3431
  return;
3448
- LATEST_FORM_REVISION_CACHE[formId2] = null;
3432
+ LATEST_REVISION_CACHE[formId2] = null;
3449
3433
  return;
3450
3434
  }
3451
- if (formRevision.revision === "Pending") {
3435
+ if (revision.revision === "Pending") {
3452
3436
  if (preferPending) {
3453
- LATEST_FORM_REVISION_CACHE[formRevision.form] = formRevision;
3437
+ LATEST_REVISION_CACHE[revision.form] = revision;
3454
3438
  }
3455
3439
  return;
3456
3440
  }
3457
- const cachedFormRevision = (_a2 = LATEST_FORM_REVISION_CACHE[formRevision.form]) == null ? void 0 : _a2.revision;
3458
- if (formRevision.revision > (typeof cachedFormRevision === "number" ? cachedFormRevision : -1)) {
3459
- LATEST_FORM_REVISION_CACHE[formRevision.form] = formRevision;
3441
+ const cachedRevision = (_a2 = LATEST_REVISION_CACHE[revision.form]) == null ? void 0 : _a2.revision;
3442
+ if (revision.revision > (typeof cachedRevision === "number" ? cachedRevision : -1)) {
3443
+ LATEST_REVISION_CACHE[revision.form] = revision;
3460
3444
  }
3461
3445
  }
3462
- function getLatestFormRevisionFromCache(formId2) {
3463
- return LATEST_FORM_REVISION_CACHE[formId2];
3446
+ function getLatestRevisionFromCache(formId2) {
3447
+ return LATEST_REVISION_CACHE[formId2];
3464
3448
  }
3465
- const initialState$5 = {
3466
- formRevisions: {},
3467
- attachments: {}
3468
- };
3469
- const formRevisionsSlice = createSlice({
3470
- name: "formRevisions",
3471
- initialState: initialState$5,
3472
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$5)),
3449
+ const initialState$3 = {
3450
+ userForms: {},
3451
+ revisions: {},
3452
+ submissions: {},
3453
+ submissionAttachments: {},
3454
+ revisionAttachments: {}
3455
+ };
3456
+ const userFormSlice = createSlice({
3457
+ name: "userForms",
3458
+ initialState: initialState$3,
3459
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$3)),
3473
3460
  reducers: {
3474
- // revision related actions
3475
- setFormRevision: (state, action) => {
3476
- state.formRevisions[action.payload.offline_id] = action.payload;
3477
- considerCachingFormRevision(action.payload);
3461
+ setUserForms: (state, action) => {
3462
+ state.userForms = {};
3463
+ action.payload.forEach((userForm) => {
3464
+ state.userForms[userForm.offline_id] = userForm;
3465
+ });
3478
3466
  },
3479
- setFormRevisions: (state, action) => {
3480
- state.formRevisions = {};
3481
- for (const revision of action.payload) {
3482
- state.formRevisions[revision.offline_id] = revision;
3483
- considerCachingFormRevision(revision);
3484
- }
3467
+ addUserForm: (state, action) => {
3468
+ state.userForms[action.payload.offline_id] = action.payload;
3485
3469
  },
3486
- addFormRevision: (state, action) => {
3487
- if (state.formRevisions[action.payload.offline_id] !== void 0) {
3488
- throw new Error(`Revision with offline_id ${action.payload.offline_id} already exists`);
3489
- }
3490
- state.formRevisions[action.payload.offline_id] = action.payload;
3491
- considerCachingFormRevision(action.payload);
3470
+ addUserForms: (state, action) => {
3471
+ action.payload.forEach((userForm) => {
3472
+ state.userForms[userForm.offline_id] = userForm;
3473
+ });
3492
3474
  },
3493
- // TODO: @Audiopolis / Magnus - do we want to standardize using PayloadAction?
3494
- addFormRevisions: (state, action) => {
3495
- for (const userFormRevision of action.payload) {
3496
- if (state.formRevisions[userFormRevision.offline_id] !== void 0) {
3497
- throw new Error(`Revision with offline_id ${userFormRevision.offline_id} already exists`);
3498
- }
3499
- }
3500
- for (const userFormRevision of action.payload) {
3501
- state.formRevisions[userFormRevision.offline_id] = userFormRevision;
3502
- considerCachingFormRevision(userFormRevision);
3503
- }
3475
+ addUserFormRevisions: (state, action) => {
3476
+ action.payload.forEach((userFormRevision) => {
3477
+ state.revisions[userFormRevision.offline_id] = userFormRevision;
3478
+ considerCachingRevision(userFormRevision);
3479
+ });
3504
3480
  },
3505
- // UserFormRevisions do not get updated
3506
- deleteFormRevision: (state, action) => {
3507
- if (state.formRevisions[action.payload] === void 0) {
3508
- throw new Error(`Revision with offline_id ${action.payload} does not exist`);
3509
- }
3510
- delete state.formRevisions[action.payload];
3511
- delete LATEST_FORM_REVISION_CACHE[action.payload];
3481
+ addUserFormRevision: (state, action) => {
3482
+ state.revisions[action.payload.offline_id] = action.payload;
3483
+ considerCachingRevision(action.payload);
3512
3484
  },
3513
- deleteFormRevisions: (state, action) => {
3514
- for (const offlineId of action.payload) {
3515
- if (state.formRevisions[offlineId] === void 0) {
3516
- throw new Error(`Revision with offline_id ${offlineId} does not exist`);
3517
- }
3518
- }
3519
- for (const offlineId of action.payload) {
3520
- delete state.formRevisions[offlineId];
3521
- delete LATEST_FORM_REVISION_CACHE[offlineId];
3485
+ deleteUserFormRevision: (state, action) => {
3486
+ delete state.revisions[action.payload];
3487
+ delete LATEST_REVISION_CACHE[action.payload];
3488
+ },
3489
+ deleteUserFormRevisions: (state, action) => {
3490
+ for (const userFormRevision of action.payload) {
3491
+ delete state.revisions[userFormRevision.offline_id];
3492
+ delete LATEST_REVISION_CACHE[userFormRevision.offline_id];
3522
3493
  }
3523
3494
  },
3524
- // attachment related actions
3525
- setFormRevisionAttachments: (state, action) => {
3526
- state.attachments = {};
3527
- for (const attachment of action.payload) {
3528
- state.attachments[attachment.offline_id] = attachment;
3495
+ updateOrCreateUserFormSubmission: (state, action) => {
3496
+ state.submissions[action.payload.offline_id] = action.payload;
3497
+ },
3498
+ addUserFormSubmissionAttachment: (state, action) => {
3499
+ const submissionId = action.payload.submission;
3500
+ const submissionAttachments = state.submissionAttachments[submissionId];
3501
+ if (submissionAttachments) {
3502
+ submissionAttachments.push(action.payload);
3503
+ } else {
3504
+ state.submissionAttachments[submissionId] = [action.payload];
3529
3505
  }
3530
3506
  },
3531
- addFormRevisionAttachment: (state, action) => {
3532
- if (state.attachments[action.payload.offline_id] !== void 0) {
3533
- throw new Error(`Attachment with offline_id ${action.payload.offline_id} already exists`);
3507
+ addUserFormRevisionAttachment: (state, action) => {
3508
+ const revisionId = action.payload.revision;
3509
+ const revisionAttachments = state.revisionAttachments[revisionId];
3510
+ if (revisionAttachments) {
3511
+ revisionAttachments.push(action.payload);
3512
+ } else {
3513
+ state.revisionAttachments[revisionId] = [action.payload];
3534
3514
  }
3535
- state.attachments[action.payload.offline_id] = action.payload;
3536
3515
  },
3537
- addFormRevisionAttachments: (state, action) => {
3516
+ setUserFormSubmissionAttachments: (state, action) => {
3517
+ state.submissionAttachments = {};
3538
3518
  for (const attachment of action.payload) {
3539
- if (state.attachments[attachment.offline_id] !== void 0) {
3540
- throw new Error(`Attachment with offline_id ${attachment.offline_id} already exists`);
3519
+ const submissionId = attachment.submission;
3520
+ const submissionAttachments = state.submissionAttachments[submissionId];
3521
+ if (submissionAttachments) {
3522
+ submissionAttachments.push(attachment);
3523
+ } else {
3524
+ state.submissionAttachments[submissionId] = [attachment];
3541
3525
  }
3542
3526
  }
3527
+ },
3528
+ setUserFormRevisionAttachments: (state, action) => {
3529
+ state.revisionAttachments = {};
3543
3530
  for (const attachment of action.payload) {
3544
- state.attachments[attachment.offline_id] = attachment;
3531
+ const revisionId = attachment.revision;
3532
+ const revisionAttachments = state.revisionAttachments[revisionId];
3533
+ if (revisionAttachments) {
3534
+ revisionAttachments.push(attachment);
3535
+ } else {
3536
+ state.revisionAttachments[revisionId] = [attachment];
3537
+ }
3545
3538
  }
3546
3539
  },
3547
- deleteFormRevisionAttachment: (state, action) => {
3548
- if (state.attachments[action.payload] === void 0) {
3549
- throw new Error(`Attachment with offline_id ${action.payload} does not exist`);
3550
- }
3551
- delete state.attachments[action.payload];
3540
+ deleteUserFormSubmission: (state, action) => {
3541
+ delete state.submissions[action.payload];
3552
3542
  },
3553
- deleteFormRevisionAttachments: (state, action) => {
3554
- for (const offlineId of action.payload) {
3555
- if (state.attachments[offlineId] === void 0) {
3556
- throw new Error(`Attachment with offline_id ${offlineId} does not exist`);
3557
- }
3543
+ deleteUserFormSubmissions: (state, action) => {
3544
+ for (const userFormSubmission of action.payload) {
3545
+ delete state.submissions[userFormSubmission.offline_id];
3558
3546
  }
3559
- for (const offlineId of action.payload) {
3560
- delete state.attachments[offlineId];
3561
- }
3562
- }
3563
- }
3564
- });
3565
- const {
3566
- setFormRevision,
3567
- setFormRevisions,
3568
- addFormRevision,
3569
- addFormRevisions,
3570
- deleteFormRevision,
3571
- deleteFormRevisions,
3572
- setFormRevisionAttachments,
3573
- addFormRevisionAttachment,
3574
- addFormRevisionAttachments,
3575
- deleteFormRevisionAttachment,
3576
- deleteFormRevisionAttachments
3577
- } = formRevisionsSlice.actions;
3578
- const selectFormRevisionMapping = (state) => state.formRevisionReducer.formRevisions;
3579
- const selectFormRevisions = createSelector(
3580
- [selectFormRevisionMapping],
3581
- (formRevisions) => Object.values(formRevisions)
3582
- );
3583
- const selectFormRevision = (formRevisionId) => (state) => {
3584
- return state.formRevisionReducer.formRevisions[formRevisionId];
3585
- };
3586
- const _selectLatestFormRevision = (formRevisions, formId2) => {
3587
- let ret = null;
3588
- for (const candidate of Object.values(formRevisions)) {
3589
- if (candidate.form === formId2 && (!ret || ret.revision < candidate.revision)) {
3590
- ret = candidate;
3591
- }
3592
- }
3593
- if (!ret) {
3594
- throw new Error("No form revision found for form " + formId2);
3595
- }
3596
- return ret;
3597
- };
3598
- const selectLatestFormRevisionOfForm = restructureCreateSelectorWithArgs(
3599
- createSelector([selectFormRevisionMapping, (_state, formId2) => formId2], (revisions, formId2) => {
3600
- if (!formId2) {
3601
- throw new Error("formId is required");
3602
- }
3603
- return _selectLatestFormRevision(revisions, formId2);
3604
- })
3605
- );
3606
- const selectFormRevisionsOfForm = restructureCreateSelectorWithArgs(
3607
- createSelector([selectFormRevisions, (_state, formId2) => formId2], (revisions, formId2) => {
3608
- return revisions.filter((revision) => {
3609
- return revision.form === formId2;
3610
- });
3611
- })
3612
- );
3613
- const selectLatestFormRevisionsOfComponentTypes = restructureCreateSelectorWithArgs(
3614
- createSelector(
3615
- [
3616
- (state) => state.formReducer.forms,
3617
- selectFormRevisionMapping,
3618
- (_state, componentTypeIds) => componentTypeIds
3619
- ],
3620
- (userForms, revisions, componentTypeIds) => {
3621
- const componentTypeIdsSet = new Set(componentTypeIds);
3622
- const ret = {};
3623
- for (const form of Object.values(userForms)) {
3624
- if (form.component_type && componentTypeIdsSet.has(form.component_type)) {
3625
- ret[form.component_type] = _selectLatestFormRevision(revisions, form.offline_id);
3626
- }
3627
- }
3628
- return ret;
3629
- }
3630
- )
3631
- );
3632
- const selectLatestFormRevisionByForm = createSelector([selectFormRevisionMapping], (revisions) => {
3633
- const latestRevisions = {};
3634
- for (const revision of Object.values(revisions)) {
3635
- const formId2 = revision.form;
3636
- const currentLatestRevision = latestRevisions[formId2];
3637
- if (!currentLatestRevision || currentLatestRevision.revision < revision.revision) {
3638
- latestRevisions[formId2] = revision;
3639
- }
3640
- }
3641
- return latestRevisions;
3642
- });
3643
- const selectUserFormRevisionAttachmentsMapping = (state) => {
3644
- return state.formRevisionReducer.attachments;
3645
- };
3646
- const selectAttachmentsOfFormRevision = restructureCreateSelectorWithArgs(
3647
- createSelector(
3648
- [selectUserFormRevisionAttachmentsMapping, (_state, revisionId) => revisionId],
3649
- (attachments, revisionId) => {
3650
- return Object.values(attachments).filter((attachment) => attachment.revision === revisionId);
3651
- }
3652
- )
3653
- );
3654
- const formRevisionReducer = formRevisionsSlice.reducer;
3655
- const initialState$4 = {
3656
- forms: {}
3657
- };
3658
- const formSlice = createSlice({
3659
- name: "forms",
3660
- initialState: initialState$4,
3661
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$4)),
3662
- reducers: {
3663
- setForms: (state, action) => {
3664
- state.forms = {};
3665
- action.payload.forEach((userForm) => {
3666
- state.forms[userForm.offline_id] = userForm;
3667
- });
3668
3547
  },
3669
- addForm: (state, action) => {
3670
- state.forms[action.payload.offline_id] = action.payload;
3548
+ addUserFormSubmissions: (state, action) => {
3549
+ for (const submission of action.payload) {
3550
+ state.submissions[submission.offline_id] = submission;
3551
+ }
3671
3552
  },
3672
- addForms: (state, action) => {
3673
- action.payload.forEach((userForm) => {
3674
- state.forms[userForm.offline_id] = userForm;
3553
+ setUserFormSubmissions: (state, action) => {
3554
+ state.submissions = {};
3555
+ action.payload.forEach((submission) => {
3556
+ state.submissions[submission.offline_id] = submission;
3675
3557
  });
3676
3558
  },
3677
3559
  favoriteForm: (state, action) => {
3678
3560
  const { formId: formId2 } = action.payload;
3679
- const form = state.forms[formId2];
3561
+ const form = state.userForms[formId2];
3680
3562
  if (!form) {
3681
3563
  throw new Error("No form exists with the id " + formId2);
3682
3564
  }
@@ -3684,23 +3566,48 @@ const formSlice = createSlice({
3684
3566
  },
3685
3567
  unfavoriteForm: (state, action) => {
3686
3568
  const { formId: formId2 } = action.payload;
3687
- const form = state.forms[formId2];
3569
+ const form = state.userForms[formId2];
3688
3570
  if (!form) {
3689
3571
  throw new Error("No form exists with the id " + formId2);
3690
3572
  }
3691
3573
  form.favorite = false;
3692
3574
  },
3693
- deleteForm: (state, action) => {
3694
- delete state.forms[action.payload];
3575
+ deleteUserForm: (state, action) => {
3576
+ delete state.userForms[action.payload];
3695
3577
  }
3696
3578
  }
3697
3579
  });
3698
- const { setForms, addForm, addForms, favoriteForm, unfavoriteForm, deleteForm } = formSlice.actions;
3699
- const selectFilteredForms = restructureCreateSelectorWithArgs(
3580
+ const {
3581
+ addUserForm,
3582
+ addUserForms,
3583
+ addUserFormRevisions,
3584
+ updateOrCreateUserFormSubmission,
3585
+ addUserFormSubmissions,
3586
+ deleteUserFormSubmission,
3587
+ deleteUserFormSubmissions,
3588
+ favoriteForm,
3589
+ unfavoriteForm,
3590
+ deleteUserForm,
3591
+ deleteUserFormRevision,
3592
+ deleteUserFormRevisions,
3593
+ setUserFormSubmissions,
3594
+ addUserFormRevision,
3595
+ addUserFormSubmissionAttachment,
3596
+ addUserFormRevisionAttachment,
3597
+ setUserFormSubmissionAttachments,
3598
+ setUserFormRevisionAttachments
3599
+ } = userFormSlice.actions;
3600
+ const selectSubmissionAttachments = (submissionId) => (state) => {
3601
+ return state.userFormReducer.submissionAttachments[submissionId] || [];
3602
+ };
3603
+ const selectRevisionAttachments = (revisionId) => (state) => {
3604
+ return state.userFormReducer.revisionAttachments[revisionId] || [];
3605
+ };
3606
+ const selectFilteredUserForms = restructureCreateSelectorWithArgs(
3700
3607
  createSelector(
3701
3608
  [
3702
- (state) => state.formReducer.forms,
3703
- (state) => state.formRevisionReducer.formRevisions,
3609
+ (state) => state.userFormReducer.userForms,
3610
+ (state) => state.userFormReducer.revisions,
3704
3611
  (_state, search) => search
3705
3612
  ],
3706
3613
  (userForms, revisions, search) => {
@@ -3734,188 +3641,63 @@ const selectFilteredForms = restructureCreateSelectorWithArgs(
3734
3641
  { memoizeOptions: { equalityCheck: shallowEqual$1 } }
3735
3642
  )
3736
3643
  );
3737
- const selectForm = (formId2) => (state) => {
3738
- return state.formReducer.forms[formId2];
3644
+ const selectFormRevision = (revisionId) => (state) => {
3645
+ return state.userFormReducer.revisions[revisionId];
3739
3646
  };
3740
- const selectFormMapping = (state) => {
3741
- return state.formReducer.forms;
3647
+ const _selectLatestFormRevision = (revisions, formId2) => {
3648
+ let ret = null;
3649
+ for (const candidate of Object.values(revisions)) {
3650
+ if (candidate.form === formId2 && (!ret || ret.revision < candidate.revision)) {
3651
+ ret = candidate;
3652
+ }
3653
+ }
3654
+ if (!ret) {
3655
+ throw new Error("No revision found for form " + formId2);
3656
+ }
3657
+ return ret;
3742
3658
  };
3743
- const selectFormOfComponentType = restructureCreateSelectorWithArgs(
3659
+ const selectLatestFormRevision = restructureCreateSelectorWithArgs(
3744
3660
  createSelector(
3745
- [selectFormMapping, (_state, componentTypeId) => componentTypeId],
3746
- (userForms, componentTypeId) => {
3747
- return Object.values(userForms).find((userForm) => userForm.component_type === componentTypeId);
3661
+ [(state) => state.userFormReducer.revisions, (_state, formId2) => formId2],
3662
+ (revisions, formId2) => {
3663
+ if (!formId2) {
3664
+ throw new Error("formId is required");
3665
+ }
3666
+ return _selectLatestFormRevision(revisions, formId2);
3748
3667
  }
3749
3668
  )
3750
3669
  );
3751
- const selectFormsCount = createSelector([selectFormMapping], (userForms) => {
3752
- return Object.keys(userForms).length;
3753
- });
3754
- const selectGeneralFormCount = createSelector([selectFormMapping], (userForms) => {
3755
- return Object.values(userForms).filter((form) => !form.component_type).length;
3756
- });
3757
- const formReducer = formSlice.reducer;
3758
- const initialState$3 = {
3759
- formSubmissions: {},
3760
- attachments: {}
3761
- };
3762
- const formSubmissionSlice = createSlice({
3763
- name: "formSubmissions",
3764
- initialState: initialState$3,
3765
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$3)),
3766
- reducers: {
3767
- setFormSubmission: (state, action) => {
3768
- state.formSubmissions[action.payload.offline_id] = action.payload;
3769
- },
3770
- setFormSubmissions: (state, action) => {
3771
- state.formSubmissions = {};
3772
- for (const submission of action.payload) {
3773
- state.formSubmissions[submission.offline_id] = submission;
3774
- }
3775
- },
3776
- addFormSubmission: (state, action) => {
3777
- if (state.formSubmissions[action.payload.offline_id] !== void 0) {
3778
- throw new Error(`Submission with offline_id ${action.payload.offline_id} already exists`);
3779
- }
3780
- state.formSubmissions[action.payload.offline_id] = action.payload;
3781
- },
3782
- addFormSubmissions: (state, action) => {
3783
- for (const submission of action.payload) {
3784
- if (state.formSubmissions[submission.offline_id] !== void 0) {
3785
- throw new Error(`Submission with offline_id ${submission.offline_id} already exists`);
3786
- }
3787
- }
3788
- for (const submission of action.payload) {
3789
- state.formSubmissions[submission.offline_id] = submission;
3790
- }
3791
- },
3792
- updateFormSubmission: (state, action) => {
3793
- if (state.formSubmissions[action.payload.offline_id] === void 0) {
3794
- throw new Error(`Submission with offline_id ${action.payload.offline_id} does not exist`);
3795
- }
3796
- state.formSubmissions[action.payload.offline_id] = action.payload;
3797
- },
3798
- updateFormSubmissions: (state, action) => {
3799
- for (const submission of action.payload) {
3800
- if (state.formSubmissions[submission.offline_id] === void 0) {
3801
- throw new Error(`Submission with offline_id ${submission.offline_id} does not exist`);
3802
- }
3803
- }
3804
- for (const submission of action.payload) {
3805
- state.formSubmissions[submission.offline_id] = submission;
3806
- }
3807
- },
3808
- deleteFormSubmission: (state, action) => {
3809
- if (state.formSubmissions[action.payload] === void 0) {
3810
- throw new Error(`Submission with offline_id ${action.payload} does not exist`);
3811
- }
3812
- delete state.formSubmissions[action.payload];
3813
- },
3814
- deleteFormSubmissions: (state, action) => {
3815
- for (const offlineId of action.payload) {
3816
- if (state.formSubmissions[offlineId] === void 0) {
3817
- throw new Error(`Submission with offline_id ${offlineId} does not exist`);
3818
- }
3819
- delete state.formSubmissions[offlineId];
3820
- }
3821
- for (const offlineId of action.payload) {
3822
- delete state.formSubmissions[offlineId];
3823
- }
3824
- },
3825
- // Attachments
3826
- addFormSubmissionAttachment: (state, action) => {
3827
- if (state.attachments[action.payload.offline_id] !== void 0) {
3828
- throw new Error(`Attachment with offline_id ${action.payload.offline_id} already exists`);
3829
- }
3830
- state.attachments[action.payload.offline_id] = action.payload;
3831
- },
3832
- addFormSubmissionAttachments: (state, action) => {
3833
- for (const attachment of action.payload) {
3834
- if (state.attachments[attachment.offline_id] !== void 0) {
3835
- throw new Error(`Attachment with offline_id ${attachment.offline_id} already exists`);
3836
- }
3837
- }
3838
- for (const attachment of action.payload) {
3839
- state.attachments[attachment.offline_id] = attachment;
3840
- }
3841
- },
3842
- // We only need a multi set for attachments because they are not updated, only added and deleted
3843
- setFormSubmissionAttachments: (state, action) => {
3844
- state.attachments = {};
3845
- for (const attachment of action.payload) {
3846
- state.attachments[attachment.offline_id] = attachment;
3847
- }
3848
- },
3849
- updateFormSubmissionAttachments: (state, action) => {
3850
- for (const attachment of action.payload) {
3851
- if (state.attachments[attachment.offline_id] === void 0) {
3852
- throw new Error(`Attachment with offline_id ${attachment.offline_id} does not exist`);
3853
- }
3854
- }
3855
- for (const attachment of action.payload) {
3856
- state.attachments[attachment.offline_id] = attachment;
3857
- }
3858
- },
3859
- // The delete actions for UserFormSubmissionAttachments are not used in the app, but are included for completeness
3860
- // Could be used if editing a submission is ever supported, will be applicable for supporting tip tap content in submissions
3861
- deleteFormSubmissionAttachment: (state, action) => {
3862
- if (state.attachments[action.payload] === void 0) {
3863
- throw new Error(`Attachment with offline_id ${action.payload} does not exist`);
3864
- }
3865
- delete state.attachments[action.payload];
3866
- },
3867
- deleteFormSubmissionAttachments: (state, action) => {
3868
- for (const offlineId of action.payload) {
3869
- if (state.attachments[offlineId] === void 0) {
3870
- throw new Error(`Attachment with offline_id ${offlineId} does not exist`);
3871
- }
3872
- delete state.attachments[offlineId];
3873
- }
3874
- }
3875
- }
3876
- });
3877
- const {
3878
- setFormSubmission,
3879
- setFormSubmissions,
3880
- addFormSubmission,
3881
- addFormSubmissions,
3882
- updateFormSubmission,
3883
- updateFormSubmissions,
3884
- deleteFormSubmission,
3885
- deleteFormSubmissions,
3886
- addFormSubmissionAttachment,
3887
- addFormSubmissionAttachments,
3888
- setFormSubmissionAttachments,
3889
- updateFormSubmissionAttachments,
3890
- deleteFormSubmissionAttachment,
3891
- deleteFormSubmissionAttachments
3892
- } = formSubmissionSlice.actions;
3893
- const selectFormSubmissionsMapping = (state) => {
3894
- return state.formSubmissionReducer.formSubmissions;
3895
- };
3896
- const selectFormSubmissions = createSelector(
3897
- [selectFormSubmissionsMapping],
3898
- (submissions) => {
3899
- return Object.values(submissions);
3900
- }
3670
+ const selectUserForm = (formId2) => (state) => {
3671
+ return state.userFormReducer.userForms[formId2];
3672
+ };
3673
+ const selectSubmissionMapping = (state) => state.userFormReducer.submissions;
3674
+ const selectUserFormSubmission = (submissionId) => (state) => {
3675
+ return state.userFormReducer.submissions[submissionId];
3676
+ };
3677
+ const selectSubmissions = createSelector([selectSubmissionMapping], (submissions) => Object.values(submissions));
3678
+ const selectRevisionMapping = (state) => state.userFormReducer.revisions;
3679
+ const selectRevisions = createSelector([selectRevisionMapping], (revisions) => Object.values(revisions));
3680
+ const selectRevisionsForForm = restructureCreateSelectorWithArgs(
3681
+ createSelector([selectRevisions, (_state, formId2) => formId2], (revisions, formId2) => {
3682
+ return revisions.filter((revision) => {
3683
+ return revision.form === formId2;
3684
+ });
3685
+ })
3901
3686
  );
3902
- const selectFormSubmission = (submissionId) => (state) => {
3903
- return state.formSubmissionReducer.formSubmissions[submissionId];
3904
- };
3905
- const selectFormSubmissionsOfForm = restructureCreateSelectorWithArgs(
3687
+ const selectSubmissionsForForm = restructureCreateSelectorWithArgs(
3906
3688
  createSelector(
3907
- [selectFormSubmissions, selectFormRevisionMapping, (_state, formId2) => formId2],
3689
+ [selectSubmissions, selectRevisionMapping, (_state, formId2) => formId2],
3908
3690
  (submissions, revisionMapping, formId2) => {
3909
- return submissions.filter((submission) => {
3691
+ return Object.values(submissions).filter((submission) => {
3910
3692
  const revision = revisionMapping[submission.form_revision];
3911
3693
  return (revision == null ? void 0 : revision.form) === formId2;
3912
3694
  });
3913
3695
  }
3914
3696
  )
3915
3697
  );
3916
- const selectFormSubmissionsOfIssue = restructureCreateSelectorWithArgs(
3698
+ const selectSubmissionsForIssue = restructureCreateSelectorWithArgs(
3917
3699
  createSelector(
3918
- [selectFormSubmissions, (_state, issueId) => issueId],
3700
+ [(state) => state.userFormReducer.submissions, (_state, issueId) => issueId],
3919
3701
  (submissions, issueId) => {
3920
3702
  return Object.values(submissions).filter((submission) => {
3921
3703
  return submission.issue === issueId;
@@ -3923,9 +3705,9 @@ const selectFormSubmissionsOfIssue = restructureCreateSelectorWithArgs(
3923
3705
  }
3924
3706
  )
3925
3707
  );
3926
- const selectFormSubmissionsOfComponent = restructureCreateSelectorWithArgs(
3708
+ const selectSubmissionsForComponent = restructureCreateSelectorWithArgs(
3927
3709
  createSelector(
3928
- [selectFormSubmissions, (_state, componentId) => componentId],
3710
+ [selectSubmissions, (_state, componentId) => componentId],
3929
3711
  (submissions, componentId) => {
3930
3712
  return submissions.filter((submission) => {
3931
3713
  return submission.component === componentId;
@@ -3933,8 +3715,8 @@ const selectFormSubmissionsOfComponent = restructureCreateSelectorWithArgs(
3933
3715
  }
3934
3716
  )
3935
3717
  );
3936
- const selectFormSubmissionsByComponents = createSelector(
3937
- [selectFormSubmissionsMapping, selectComponentsMapping],
3718
+ const selectComponentSubmissionMapping = createSelector(
3719
+ [selectSubmissionMapping, selectComponentsMapping],
3938
3720
  (submissions, components) => {
3939
3721
  var _a2;
3940
3722
  const componentSubmissionMapping = {};
@@ -3950,18 +3732,54 @@ const selectFormSubmissionsByComponents = createSelector(
3950
3732
  return componentSubmissionMapping;
3951
3733
  }
3952
3734
  );
3953
- const selectFormSubmissionAttachmentsMapping = (state) => {
3954
- return state.formSubmissionReducer.attachments;
3735
+ const selectUserFormMapping = (state) => {
3736
+ return state.userFormReducer.userForms;
3955
3737
  };
3956
- const selectAttachmentsOfFormSubmission = restructureCreateSelectorWithArgs(
3738
+ const selectComponentTypeForm = restructureCreateSelectorWithArgs(
3957
3739
  createSelector(
3958
- [selectFormSubmissionAttachmentsMapping, (_state, submissionId) => submissionId],
3959
- (attachmentsMapping, submissionId) => {
3960
- return Object.values(attachmentsMapping).filter((attachment) => attachment.submission === submissionId);
3740
+ [selectUserFormMapping, (_state, componentTypeId) => componentTypeId],
3741
+ (userForms, componentTypeId) => {
3742
+ return Object.values(userForms).find((userForm) => userForm.component_type === componentTypeId);
3743
+ }
3744
+ )
3745
+ );
3746
+ const selectLatestRevisionsFromComponentTypeIds = restructureCreateSelectorWithArgs(
3747
+ createSelector(
3748
+ [
3749
+ selectUserFormMapping,
3750
+ selectRevisionMapping,
3751
+ (_state, componentTypeIds) => componentTypeIds
3752
+ ],
3753
+ (userForms, revisions, componentTypeIds) => {
3754
+ const componentTypeIdsSet = new Set(componentTypeIds);
3755
+ const ret = {};
3756
+ for (const form of Object.values(userForms)) {
3757
+ if (form.component_type && componentTypeIdsSet.has(form.component_type)) {
3758
+ ret[form.component_type] = _selectLatestFormRevision(revisions, form.offline_id);
3759
+ }
3760
+ }
3761
+ return ret;
3961
3762
  }
3962
3763
  )
3963
3764
  );
3964
- const formSubmissionReducer = formSubmissionSlice.reducer;
3765
+ const selectLatestRevisionByFormId = createSelector([selectRevisionMapping], (revisions) => {
3766
+ const latestRevisions = {};
3767
+ for (const revision of Object.values(revisions)) {
3768
+ const formId2 = revision.form;
3769
+ const currentLatestRevision = latestRevisions[formId2];
3770
+ if (!currentLatestRevision || currentLatestRevision.revision < revision.revision) {
3771
+ latestRevisions[formId2] = revision;
3772
+ }
3773
+ }
3774
+ return latestRevisions;
3775
+ });
3776
+ const selectNumberOfUserForms = createSelector([selectUserFormMapping], (userForms) => {
3777
+ return Object.keys(userForms).length;
3778
+ });
3779
+ const selectNumberOfGeneralUserForms = createSelector([selectUserFormMapping], (userForms) => {
3780
+ return Object.values(userForms).filter((form) => !form.component_type).length;
3781
+ });
3782
+ const userFormReducer = userFormSlice.reducer;
3965
3783
  const initialState$2 = {
3966
3784
  emailDomains: {}
3967
3785
  };
@@ -4259,9 +4077,7 @@ const overmapReducers = {
4259
4077
  projectFileReducer,
4260
4078
  rehydratedReducer,
4261
4079
  settingReducer,
4262
- formReducer,
4263
- formRevisionReducer,
4264
- formSubmissionReducer,
4080
+ userFormReducer,
4265
4081
  userReducer,
4266
4082
  workspaceReducer,
4267
4083
  emailDomainsReducer,
@@ -4314,7 +4130,9 @@ function handleWorkspaceRemoval(draft, action) {
4314
4130
  throw new Error(`Failed to update index_workspace of issue ${issue.offline_id} to main workspace`);
4315
4131
  }
4316
4132
  }
4317
- const indexedForms = Object.values(draft.formReducer.forms).filter((form) => form.index_workspace === workspaceId);
4133
+ const indexedForms = Object.values(draft.userFormReducer.userForms).filter(
4134
+ (form) => form.index_workspace === workspaceId
4135
+ );
4318
4136
  for (const form of indexedForms) {
4319
4137
  form.index_workspace = mainWorkspace.offline_id;
4320
4138
  }
@@ -6951,7 +6769,7 @@ class UserFormService extends BaseApiService {
6951
6769
  ...revisionAttachmentPayload,
6952
6770
  file: URL.createObjectURL(image)
6953
6771
  };
6954
- store.dispatch(addFormRevisionAttachment(offlinePayload));
6772
+ store.dispatch(addUserFormRevisionAttachment(offlinePayload));
6955
6773
  return attach;
6956
6774
  });
6957
6775
  });
@@ -6985,8 +6803,8 @@ class UserFormService extends BaseApiService {
6985
6803
  revision: 0
6986
6804
  };
6987
6805
  const { store } = this.client;
6988
- store.dispatch(addForm(retForm));
6989
- store.dispatch(addFormRevision(retRevision));
6806
+ store.dispatch(addUserForm(retForm));
6807
+ store.dispatch(addUserFormRevision(retRevision));
6990
6808
  const formPromise = this.enqueueRequest({
6991
6809
  description: "Create form",
6992
6810
  method: HttpMethod.POST,
@@ -7004,8 +6822,8 @@ class UserFormService extends BaseApiService {
7004
6822
  });
7005
6823
  const attachImagesPromises = this.getAttachImagePromises(images, offlineRevisionPayload.offline_id);
7006
6824
  void formPromise.catch((e) => {
7007
- store.dispatch(deleteForm(retForm.offline_id));
7008
- store.dispatch(deleteFormRevision(retRevision.offline_id));
6825
+ store.dispatch(deleteUserForm(retForm.offline_id));
6826
+ store.dispatch(deleteUserFormRevision(retRevision.offline_id));
7009
6827
  throw e;
7010
6828
  });
7011
6829
  const settledPromise = Promise.all([formPromise, ...attachImagesPromises]).then(() => formPromise);
@@ -7047,7 +6865,7 @@ class UserFormService extends BaseApiService {
7047
6865
  revision: "Pending",
7048
6866
  form: formId2
7049
6867
  };
7050
- store.dispatch(addFormRevision(fullRevision));
6868
+ store.dispatch(addUserFormRevision(fullRevision));
7051
6869
  const promise = this.enqueueRequest({
7052
6870
  description: "Create form revision",
7053
6871
  method: HttpMethod.PATCH,
@@ -7061,9 +6879,9 @@ class UserFormService extends BaseApiService {
7061
6879
  });
7062
6880
  const attachImagesPromises = this.getAttachImagePromises(images, offlineRevision.offline_id);
7063
6881
  void promise.then((result) => {
7064
- store.dispatch(setFormRevision(result));
6882
+ store.dispatch(addUserFormRevision(result));
7065
6883
  }).catch(() => {
7066
- store.dispatch(deleteFormRevision(fullRevision.offline_id));
6884
+ store.dispatch(deleteUserFormRevision(fullRevision.offline_id));
7067
6885
  });
7068
6886
  const settledPromise = Promise.all([promise, ...attachImagesPromises]).then(() => promise);
7069
6887
  return [fullRevision, settledPromise];
@@ -7105,19 +6923,19 @@ class UserFormService extends BaseApiService {
7105
6923
  async delete(formId2) {
7106
6924
  const { store } = this.client;
7107
6925
  const state = store.getState();
7108
- const userForm = selectForm(formId2)(state);
6926
+ const userForm = selectUserForm(formId2)(state);
7109
6927
  if (!userForm) {
7110
6928
  throw new Error("Expected userForm to exist");
7111
6929
  }
7112
- const userFormSubmissions = selectFormSubmissionsOfForm(formId2)(state);
6930
+ const userFormSubmissions = selectSubmissionsForForm(formId2)(state);
7113
6931
  if (userFormSubmissions && userFormSubmissions.length > 0) {
7114
- store.dispatch(deleteFormSubmissions(userFormSubmissions.map(({ offline_id }) => offline_id)));
6932
+ store.dispatch(deleteUserFormSubmissions(userFormSubmissions));
7115
6933
  }
7116
- const userFormRevisions = selectFormRevisionsOfForm(formId2)(state);
6934
+ const userFormRevisions = selectRevisionsForForm(formId2)(state);
7117
6935
  if (userFormRevisions && userFormRevisions.length > 0) {
7118
- store.dispatch(deleteFormRevisions(userFormRevisions.map(({ offline_id }) => offline_id)));
6936
+ store.dispatch(deleteUserFormRevisions(userFormRevisions));
7119
6937
  }
7120
- store.dispatch(deleteForm(formId2));
6938
+ store.dispatch(deleteUserForm(formId2));
7121
6939
  try {
7122
6940
  return await this.enqueueRequest({
7123
6941
  description: "Delete form",
@@ -7127,12 +6945,12 @@ class UserFormService extends BaseApiService {
7127
6945
  blocks: []
7128
6946
  });
7129
6947
  } catch (e) {
7130
- store.dispatch(addForm(userForm));
6948
+ store.dispatch(addUserForm(userForm));
7131
6949
  if (userFormRevisions && userFormRevisions.length > 0) {
7132
- store.dispatch(addFormRevisions(userFormRevisions));
6950
+ store.dispatch(addUserFormRevisions(userFormRevisions));
7133
6951
  }
7134
6952
  if (userFormSubmissions && userFormSubmissions.length > 0) {
7135
- store.dispatch(addFormSubmissions(userFormSubmissions));
6953
+ store.dispatch(addUserFormSubmissions(userFormSubmissions));
7136
6954
  }
7137
6955
  throw e;
7138
6956
  }
@@ -7146,15 +6964,16 @@ class UserFormService extends BaseApiService {
7146
6964
  blockers: [],
7147
6965
  blocks: []
7148
6966
  });
7149
- store.dispatch(setForms(Object.values(result.forms)));
7150
- store.dispatch(setFormRevisions(Object.values(result.revisions)));
7151
- store.dispatch(setFormRevisionAttachments(Object.values(result.attachments)));
6967
+ store.dispatch(addUserForms(Object.values(result.forms)));
6968
+ store.dispatch(addUserFormRevisions(Object.values(result.revisions)));
6969
+ store.dispatch(setUserFormRevisionAttachments(Object.values(result.attachments)));
7152
6970
  }
7153
6971
  }
7154
6972
  const isArrayOfFiles = (value) => {
7155
6973
  return Array.isArray(value) && value[0] instanceof File;
7156
6974
  };
7157
- const separateFilesFromValues = (values) => {
6975
+ const separateFilesFromValues = (payload) => {
6976
+ const { values } = payload;
7158
6977
  const files = {};
7159
6978
  const newValues = {};
7160
6979
  for (const key in values) {
@@ -7169,13 +6988,17 @@ const separateFilesFromValues = (values) => {
7169
6988
  newValues[key] = value;
7170
6989
  }
7171
6990
  }
7172
- return { values: newValues, files };
6991
+ const payloadWithoutFiles = {
6992
+ ...payload,
6993
+ values: newValues
6994
+ };
6995
+ return { payloadWithoutFiles, files };
7173
6996
  };
7174
6997
  class UserFormSubmissionService extends BaseApiService {
7175
6998
  constructor() {
7176
6999
  super(...arguments);
7177
7000
  // Attach files to submission, after uploading them to S3
7178
- __publicField(this, "getAttachFilesPromises", (files, submission) => {
7001
+ __publicField(this, "getAttachFilesPromises", (files, payload) => {
7179
7002
  const { store } = this.client;
7180
7003
  return Object.entries(files).map(async ([key, fileArray]) => {
7181
7004
  const attachResults = [];
@@ -7185,27 +7008,24 @@ class UserFormSubmissionService extends BaseApiService {
7185
7008
  const [fileProps] = await this.client.files.uploadFileToS3(sha1);
7186
7009
  const submissionAttachmentPayload = offline({
7187
7010
  ...fileProps,
7188
- submission: submission.offline_id,
7011
+ submission: payload.offline_id,
7189
7012
  field_identifier: key
7190
7013
  });
7191
7014
  const attach = await this.enqueueRequest({
7192
7015
  description: "Attach file to form submission",
7193
7016
  method: HttpMethod.POST,
7194
- url: `/forms/submission/${submission.offline_id}/attachments/`,
7017
+ url: `/forms/submission/${payload.offline_id}/attachments/`,
7195
7018
  payload: submissionAttachmentPayload,
7196
- blockers: [
7197
- submission.component,
7198
- submission.component_stage,
7199
- submission.issue,
7200
- submission.form_revision
7201
- ].filter((x) => x !== void 0),
7019
+ blockers: [payload.component, payload.component_stage, payload.issue, payload.form_revision].filter(
7020
+ (x) => x !== void 0
7021
+ ),
7202
7022
  blocks: [submissionAttachmentPayload.offline_id]
7203
7023
  });
7204
7024
  const offlinePayload = {
7205
7025
  ...submissionAttachmentPayload,
7206
7026
  file: URL.createObjectURL(file)
7207
7027
  };
7208
- store.dispatch(addFormSubmissionAttachment(offlinePayload));
7028
+ store.dispatch(addUserFormSubmissionAttachment(offlinePayload));
7209
7029
  attachResults.push(attach);
7210
7030
  }
7211
7031
  return attachResults;
@@ -7219,165 +7039,70 @@ class UserFormSubmissionService extends BaseApiService {
7219
7039
  if (!activeProjectId) {
7220
7040
  throw new Error("Expected an active project");
7221
7041
  }
7222
- const { values, files } = separateFilesFromValues(payload.values);
7223
- const offlineSubmission = {
7224
- ...payload,
7225
- values,
7226
- created_by: state.userReducer.currentUser.id,
7227
- submitted_at: (/* @__PURE__ */ new Date()).toISOString()
7228
- };
7042
+ const { payloadWithoutFiles, files } = separateFilesFromValues(payload);
7229
7043
  const promise = this.enqueueRequest({
7230
7044
  description: "Respond to form",
7231
7045
  method: HttpMethod.POST,
7232
7046
  url: `/forms/revisions/${payload.form_revision}/respond/`,
7233
- payload: { ...offlineSubmission, project: activeProjectId },
7047
+ payload: { ...payloadWithoutFiles, project: activeProjectId },
7234
7048
  blockers: [payload.issue, payload.component, payload.component_stage, "add-form-entry"].filter(
7235
7049
  (x) => x !== void 0
7236
7050
  ),
7237
7051
  blocks: [payload.offline_id]
7238
7052
  });
7239
- const attachFilesPromises = this.getAttachFilesPromises(files, offlineSubmission);
7240
- store.dispatch(addFormSubmission(offlineSubmission));
7053
+ const attachFilesPromises = this.getAttachFilesPromises(files, payload);
7054
+ const now = (/* @__PURE__ */ new Date()).toISOString();
7055
+ const fullOfflineResult = {
7056
+ ...payload,
7057
+ created_by: state.userReducer.currentUser.id,
7058
+ created_at: now,
7059
+ updated_at: now
7060
+ };
7061
+ const offlineResultWithoutFiles = {
7062
+ ...fullOfflineResult,
7063
+ ...payloadWithoutFiles
7064
+ };
7065
+ store.dispatch(updateOrCreateUserFormSubmission(offlineResultWithoutFiles));
7241
7066
  void promise.then((result) => {
7242
7067
  store.dispatch(addActiveProjectFormSubmissionsCount(1));
7243
- store.dispatch(setFormSubmission(result));
7068
+ store.dispatch(updateOrCreateUserFormSubmission(result));
7244
7069
  return result;
7245
7070
  }).catch(() => {
7246
- store.dispatch(deleteFormSubmission(payload.offline_id));
7071
+ store.dispatch(deleteUserFormSubmission(payload.offline_id));
7247
7072
  store.dispatch(addActiveProjectFormSubmissionsCount(-1));
7248
7073
  });
7249
7074
  const settledPromise = Promise.all([promise, ...attachFilesPromises]).then(() => promise);
7250
- return [offlineSubmission, settledPromise];
7251
- }
7252
- // Note currently the bulkAdd method is specific to form submissions for components
7253
- // TODO: adapt the support bulk adding to any model type
7254
- async bulkAdd(args) {
7255
- const { form_revision, values: argsValues, componentOfflineIds } = args;
7256
- const { store } = this.client;
7257
- const offlineSubmissions = [];
7258
- const offlineAttachments = [];
7259
- const submissionOfflineIds = [];
7260
- const submissionsPayload = [];
7261
- const attachmentsPayload = [];
7262
- const { values, files } = separateFilesFromValues(argsValues);
7263
- const submittedAt = (/* @__PURE__ */ new Date()).toISOString();
7264
- const createdBy = store.getState().userReducer.currentUser.id;
7265
- for (const component_id of componentOfflineIds) {
7266
- const submission = offline({
7267
- form_revision,
7268
- values,
7269
- created_by: createdBy,
7270
- submitted_at: submittedAt,
7271
- component: component_id
7272
- });
7273
- submissionOfflineIds.push(submission.offline_id);
7274
- submissionsPayload.push({ offline_id: submission.offline_id, component_id });
7275
- offlineSubmissions.push(submission);
7276
- for (const [fieldIdentifier, fileArray] of Object.entries(files)) {
7277
- for (const file of fileArray) {
7278
- const sha1 = await hashFile(file);
7279
- await this.client.files.addCache(file, sha1);
7280
- const offlineAttachment = offline({
7281
- file_name: file.name,
7282
- file_sha1: sha1,
7283
- file: URL.createObjectURL(file),
7284
- submission: submission.offline_id,
7285
- field_identifier: fieldIdentifier
7286
- });
7287
- offlineAttachments.push(offlineAttachment);
7288
- attachmentsPayload.push({
7289
- offline_id: offlineAttachment.offline_id,
7290
- submission_id: submission.offline_id,
7291
- sha1,
7292
- name: file.name,
7293
- field_identifier: fieldIdentifier
7294
- });
7295
- }
7296
- }
7297
- }
7298
- const filesRecord = {};
7299
- for (const file of Object.values(files).flat()) {
7300
- const sha1 = await hashFile(file);
7301
- filesRecord[sha1] = {
7302
- sha1,
7303
- extension: file.name.split(".").pop() || "",
7304
- file_type: file.type,
7305
- size: file.size
7306
- };
7307
- }
7308
- store.dispatch(addFormSubmissions(offlineSubmissions));
7309
- store.dispatch(addFormSubmissionAttachments(offlineAttachments));
7310
- const promise = this.enqueueRequest({
7311
- description: "Bulk add form submissions",
7312
- method: HttpMethod.POST,
7313
- url: `/forms/revisions/${form_revision}/bulk-respond/`,
7314
- payload: {
7315
- form_data: values,
7316
- submitted_at: submittedAt,
7317
- submissions: submissionsPayload,
7318
- attachments: attachmentsPayload,
7319
- files: Object.values(filesRecord)
7320
- },
7321
- blockers: componentOfflineIds,
7322
- blocks: submissionOfflineIds
7323
- });
7324
- promise.then(({ submissions, attachments, presigned_urls }) => {
7325
- store.dispatch(updateFormSubmissions(submissions));
7326
- store.dispatch(updateFormSubmissionAttachments(attachments));
7327
- for (const [sha1, presigned_url] of Object.entries(presigned_urls)) {
7328
- const file = filesRecord[sha1];
7329
- if (!file)
7330
- continue;
7331
- void this.enqueueRequest({
7332
- url: presigned_url.url,
7333
- description: "Upload file",
7334
- method: HttpMethod.POST,
7335
- isExternalUrl: true,
7336
- isAuthNeeded: false,
7337
- attachmentHash: sha1,
7338
- blockers: [`s3-${file.sha1}.${file.extension}`],
7339
- blocks: [sha1],
7340
- s3url: presigned_url
7341
- });
7342
- }
7343
- }).catch(() => {
7344
- store.dispatch(deleteFormSubmissions(submissionOfflineIds));
7345
- store.dispatch(deleteFormSubmissionAttachments(offlineAttachments.map((x) => x.offline_id)));
7346
- });
7347
- return [offlineSubmissions, promise.then(({ submissions }) => submissions)];
7075
+ return [fullOfflineResult, settledPromise];
7348
7076
  }
7349
7077
  update(submission) {
7350
7078
  const { store } = this.client;
7351
- const { values, files } = separateFilesFromValues(submission.values);
7079
+ const { payloadWithoutFiles, files } = separateFilesFromValues(submission);
7080
+ if (!("created_by" in payloadWithoutFiles) || !("created_at" in payloadWithoutFiles)) {
7081
+ throw new Error("Expected payloadWithoutFiles to have created_by and created_at fields.");
7082
+ }
7352
7083
  const attachFilesPromises = this.getAttachFilesPromises(files, submission);
7353
- const offlineSubmission = {
7354
- ...submission,
7355
- values
7084
+ const fullResult = {
7085
+ ...payloadWithoutFiles,
7086
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
7356
7087
  };
7357
- const submissionToBeUpdated = store.getState().formSubmissionReducer.formSubmissions[submission.offline_id];
7358
- store.dispatch(updateFormSubmission(offlineSubmission));
7088
+ store.dispatch(updateOrCreateUserFormSubmission(fullResult));
7359
7089
  const promise = this.enqueueRequest({
7360
7090
  description: "Patch form submission",
7361
7091
  method: HttpMethod.PATCH,
7362
7092
  url: `/forms/submissions/${submission.offline_id}/`,
7363
- payload: offlineSubmission,
7364
- blockers: [offlineSubmission.issue, offlineSubmission.component, offlineSubmission.component_stage].filter(
7093
+ payload: fullResult,
7094
+ blockers: [fullResult.issue, fullResult.component, fullResult.component_stage].filter(
7365
7095
  (x) => x !== void 0
7366
7096
  ),
7367
- blocks: [offlineSubmission.offline_id]
7097
+ blocks: [fullResult.offline_id]
7368
7098
  });
7369
- promise.then((createdSubmission) => {
7370
- store.dispatch(setFormSubmission(createdSubmission));
7371
- }).catch(() => {
7372
- store.dispatch(setFormSubmission(submissionToBeUpdated));
7373
- });
7374
- return [offlineSubmission, Promise.all([promise, ...attachFilesPromises]).then(() => promise)];
7099
+ return Promise.all([promise, ...attachFilesPromises]).then(() => promise);
7375
7100
  }
7376
7101
  async delete(submissionId) {
7377
7102
  const { store } = this.client;
7378
7103
  const state = store.getState();
7379
- const submission = state.formSubmissionReducer.formSubmissions[submissionId];
7380
- store.dispatch(deleteFormSubmission(submissionId));
7104
+ const submission = state.userFormReducer.submissions[submissionId];
7105
+ store.dispatch(deleteUserFormSubmission(submissionId));
7381
7106
  store.dispatch(addActiveProjectFormSubmissionsCount(-1));
7382
7107
  try {
7383
7108
  return await this.enqueueRequest({
@@ -7388,8 +7113,10 @@ class UserFormSubmissionService extends BaseApiService {
7388
7113
  blocks: []
7389
7114
  });
7390
7115
  } catch (e) {
7391
- store.dispatch(addActiveProjectFormSubmissionsCount(1));
7392
- store.dispatch(addFormSubmission(submission));
7116
+ if (submission) {
7117
+ store.dispatch(addActiveProjectFormSubmissionsCount(1));
7118
+ store.dispatch(updateOrCreateUserFormSubmission(submission));
7119
+ }
7393
7120
  throw e;
7394
7121
  }
7395
7122
  }
@@ -7403,7 +7130,7 @@ class UserFormSubmissionService extends BaseApiService {
7403
7130
  blockers: [],
7404
7131
  blocks: []
7405
7132
  });
7406
- store.dispatch(setFormSubmissions(submissions));
7133
+ store.dispatch(setUserFormSubmissions(submissions));
7407
7134
  const attachments = await this.enqueueRequest({
7408
7135
  description: "Fetch form attachments",
7409
7136
  method: HttpMethod.GET,
@@ -7411,7 +7138,7 @@ class UserFormSubmissionService extends BaseApiService {
7411
7138
  blockers: [],
7412
7139
  blocks: []
7413
7140
  });
7414
- store.dispatch(setFormSubmissionAttachments(attachments));
7141
+ store.dispatch(setUserFormSubmissionAttachments(attachments));
7415
7142
  }
7416
7143
  }
7417
7144
  class WorkspaceService extends BaseApiService {
@@ -14270,7 +13997,7 @@ const initialFormValues = (fields, values) => {
14270
13997
  };
14271
13998
  const useAttachImagesToFormRevisionFields = (revision) => {
14272
13999
  const { sdk } = useSDK();
14273
- const attachments = useAppSelector(selectAttachmentsOfFormRevision((revision == null ? void 0 : revision.offline_id) ?? ""));
14000
+ const attachments = useAppSelector(selectRevisionAttachments((revision == null ? void 0 : revision.offline_id) ?? ""));
14274
14001
  return useMemo(() => {
14275
14002
  if (!revision || !attachments)
14276
14003
  return revision;
@@ -14367,7 +14094,7 @@ const FormSubmissionViewer = memo(
14367
14094
  return formRevisionToSchema(revisionWithImages, { readonly: true });
14368
14095
  }, [revisionWithImages]);
14369
14096
  const submissionValuesWithAttachments = useMemo(() => {
14370
- const attachments = selectAttachmentsOfFormSubmission(submission.offline_id)(sdk.store.getState()) ?? [];
14097
+ const attachments = selectSubmissionAttachments(submission.offline_id)(sdk.store.getState()) ?? [];
14371
14098
  const downloadedAttachments = {};
14372
14099
  for (const attachment of attachments) {
14373
14100
  const promise = sdk.files.fetchFileFromUrl(attachment.file, attachment.file_sha1, attachment.file_name);
@@ -14417,8 +14144,8 @@ const FormBrowser = memo(
14417
14144
  }
14418
14145
  return ret;
14419
14146
  }, [filter, maxResults, ownerFilter]);
14420
- const userForms = useAppSelector(selectFilteredForms(ownerFilterOptions)) ?? [];
14421
- const userFormMapping = useAppSelector(selectFormMapping);
14147
+ const userForms = useAppSelector(selectFilteredUserForms(ownerFilterOptions)) ?? [];
14148
+ const userFormMapping = useAppSelector(selectUserFormMapping);
14422
14149
  const attachableUserForms = userForms.filter((form) => !form.component_type);
14423
14150
  const attachableUserFormMapping = Object.values(userFormMapping).filter(
14424
14151
  (form) => !form.component_type
@@ -14451,7 +14178,7 @@ const FormBrowser = memo(
14451
14178
  const handleChange = useCallback((e) => {
14452
14179
  setFilter(e.currentTarget.value);
14453
14180
  }, []);
14454
- const numberOfForms = useAppSelector(selectGeneralFormCount) || 0;
14181
+ const numberOfForms = useAppSelector(selectNumberOfGeneralUserForms) || 0;
14455
14182
  const numberOfHiddenForms = numberOfForms - attachableUserForms.length;
14456
14183
  const overflowMessage = attachableUserForms.length == maxResults && numberOfHiddenForms > 0 ? `Only the first ${maxResults} results are shown (${numberOfHiddenForms} hidden)` : numberOfHiddenForms > 0 && `${numberOfHiddenForms} hidden forms`;
14457
14184
  return /* @__PURE__ */ jsxs(Flex$1, { ref, direction: "column", gap: "2", children: [
@@ -14545,13 +14272,16 @@ const FormSubmissionBrowserEntry = memo((props) => {
14545
14272
  const { submission, onSubmissionClick, compact, labelType, rowDecorator } = props;
14546
14273
  const currentUser = useAppSelector(selectCurrentUser);
14547
14274
  const createdBy = useAppSelector(selectUser("created_by" in submission ? submission.created_by : currentUser.id));
14548
- const dateToUse = submission.submitted_at;
14549
- const formattedDateTime = getLocalDateString(dateToUse);
14275
+ const dateToUse = getCreatedAtOrSubmittedAtDate(submission);
14276
+ const formattedDateTime = isToday(dateToUse) ? dateToUse.toLocaleTimeString([], {
14277
+ hour: "2-digit",
14278
+ minute: "2-digit"
14279
+ }) : getLocalDateString(dateToUse);
14550
14280
  const revision = useAppSelector(selectFormRevision(submission.form_revision));
14551
14281
  if (!revision) {
14552
14282
  throw new Error(`Could not find revision ${submission.form_revision} for submission ${submission.offline_id}.`);
14553
14283
  }
14554
- const latestRevisionNumber = (_a2 = useAppSelector(selectLatestFormRevisionOfForm(revision.form))) == null ? void 0 : _a2.revision;
14284
+ const latestRevisionNumber = (_a2 = useAppSelector(selectLatestFormRevision(revision.form))) == null ? void 0 : _a2.revision;
14555
14285
  const creatorProfileSrc = useFileSrc({
14556
14286
  file: (createdBy == null ? void 0 : createdBy.profile.file) ?? null,
14557
14287
  fileSha1: (createdBy == null ? void 0 : createdBy.profile.file_sha1) ?? null
@@ -14582,6 +14312,10 @@ const FormSubmissionBrowserEntry = memo((props) => {
14582
14312
  return row;
14583
14313
  });
14584
14314
  FormSubmissionBrowserEntry.displayName = "FormSubmissionBrowserEntry";
14315
+ const getCreatedAtOrSubmittedAtDate = (submission) => {
14316
+ const date = "created_at" in submission ? submission.created_at : submission.submitted_at;
14317
+ return new Date(date);
14318
+ };
14585
14319
  const FormSubmissionBrowser = memo((props) => {
14586
14320
  const {
14587
14321
  formId: formId2,
@@ -14595,10 +14329,10 @@ const FormSubmissionBrowser = memo((props) => {
14595
14329
  if (!!formId2 === !!propSubmissions) {
14596
14330
  throw new Error("Either formId or submissions must be provided, but not both.");
14597
14331
  }
14598
- const submissions = useAppSelector(propSubmissions ? () => propSubmissions : selectFormSubmissionsOfForm(formId2));
14332
+ const submissions = useAppSelector(propSubmissions ? () => propSubmissions : selectSubmissionsForForm(formId2));
14599
14333
  const sortedSubmissions = useMemo(
14600
14334
  () => submissions == null ? void 0 : submissions.sort((a, b) => {
14601
- return a.submitted_at.localeCompare(b.submitted_at);
14335
+ return getCreatedAtOrSubmittedAtDate(b).getTime() - getCreatedAtOrSubmittedAtDate(a).getTime();
14602
14336
  }),
14603
14337
  [submissions]
14604
14338
  );
@@ -15916,7 +15650,6 @@ export {
15916
15650
  VerificationCodeType,
15917
15651
  WorkspaceService,
15918
15652
  YELLOW,
15919
- _selectLatestFormRevision,
15920
15653
  _setLatestRetryTime,
15921
15654
  acceptProjectInvite,
15922
15655
  addActiveProjectFormSubmissionsCount,
@@ -15934,16 +15667,6 @@ export {
15934
15667
  addDocuments,
15935
15668
  addEmailDomain,
15936
15669
  addFavouriteProjectId,
15937
- addForm,
15938
- addFormRevision,
15939
- addFormRevisionAttachment,
15940
- addFormRevisionAttachments,
15941
- addFormRevisions,
15942
- addFormSubmission,
15943
- addFormSubmissionAttachment,
15944
- addFormSubmissionAttachments,
15945
- addFormSubmissions,
15946
- addForms,
15947
15670
  addIssue,
15948
15671
  addIssueAttachment,
15949
15672
  addIssueAttachments,
@@ -15964,6 +15687,13 @@ export {
15964
15687
  addStageCompletions,
15965
15688
  addStages,
15966
15689
  addToRecentIssues,
15690
+ addUserForm,
15691
+ addUserFormRevision,
15692
+ addUserFormRevisionAttachment,
15693
+ addUserFormRevisions,
15694
+ addUserFormSubmissionAttachment,
15695
+ addUserFormSubmissions,
15696
+ addUserForms,
15967
15697
  addUsers,
15968
15698
  addWorkspace,
15969
15699
  areArraysEqual,
@@ -15984,7 +15714,6 @@ export {
15984
15714
  componentStageSlice,
15985
15715
  componentTypeReducer,
15986
15716
  componentTypeSlice,
15987
- constructUploadedFilePayloads,
15988
15717
  coordinatesAreEqual,
15989
15718
  coordinatesToLiteral,
15990
15719
  coordinatesToPointGeometry,
@@ -15995,16 +15724,12 @@ export {
15995
15724
  defaultBadgeColor,
15996
15725
  defaultStore,
15997
15726
  deleteComponentType,
15998
- deleteForm,
15999
- deleteFormRevision,
16000
- deleteFormRevisionAttachment,
16001
- deleteFormRevisionAttachments,
16002
- deleteFormRevisions,
16003
- deleteFormSubmission,
16004
- deleteFormSubmissionAttachment,
16005
- deleteFormSubmissionAttachments,
16006
- deleteFormSubmissions,
16007
15727
  deleteProject,
15728
+ deleteUserForm,
15729
+ deleteUserFormRevision,
15730
+ deleteUserFormRevisions,
15731
+ deleteUserFormSubmission,
15732
+ deleteUserFormSubmissions,
16008
15733
  dequeue,
16009
15734
  deserialize,
16010
15735
  deserializeField,
@@ -16033,13 +15758,7 @@ export {
16033
15758
  fileSlice,
16034
15759
  fileToBlob,
16035
15760
  flipCoordinates,
16036
- formReducer,
16037
- formRevisionReducer,
16038
15761
  formRevisionToSchema,
16039
- formRevisionsSlice,
16040
- formSlice,
16041
- formSubmissionReducer,
16042
- formSubmissionSlice,
16043
15762
  index as forms,
16044
15763
  fullComponentMarkerSize,
16045
15764
  generateBadgeColors,
@@ -16167,8 +15886,6 @@ export {
16167
15886
  selectAttachmentsOfComponentTypeByType,
16168
15887
  selectAttachmentsOfDocument,
16169
15888
  selectAttachmentsOfDocumentByType,
16170
- selectAttachmentsOfFormRevision,
16171
- selectAttachmentsOfFormSubmission,
16172
15889
  selectAttachmentsOfIssue,
16173
15890
  selectAttachmentsOfIssueByType,
16174
15891
  selectAttachmentsOfProject,
@@ -16186,9 +15903,10 @@ export {
16186
15903
  selectComponent,
16187
15904
  selectComponentAttachment,
16188
15905
  selectComponentAttachmentMapping,
15906
+ selectComponentSubmissionMapping,
16189
15907
  selectComponentType,
16190
- selectComponentTypeAttachment,
16191
15908
  selectComponentTypeAttachmentMapping,
15909
+ selectComponentTypeForm,
16192
15910
  selectComponentTypeFromComponent,
16193
15911
  selectComponentTypeFromComponents,
16194
15912
  selectComponentTypeStagesMapping,
@@ -16218,24 +15936,8 @@ export {
16218
15936
  selectExpandedSections,
16219
15937
  selectFavouriteProjects,
16220
15938
  selectFileAttachmentsOfIssue,
16221
- selectFilteredForms,
16222
- selectForm,
16223
- selectFormMapping,
16224
- selectFormOfComponentType,
15939
+ selectFilteredUserForms,
16225
15940
  selectFormRevision,
16226
- selectFormRevisionMapping,
16227
- selectFormRevisions,
16228
- selectFormRevisionsOfForm,
16229
- selectFormSubmission,
16230
- selectFormSubmissionAttachmentsMapping,
16231
- selectFormSubmissions,
16232
- selectFormSubmissionsByComponents,
16233
- selectFormSubmissionsMapping,
16234
- selectFormSubmissionsOfComponent,
16235
- selectFormSubmissionsOfForm,
16236
- selectFormSubmissionsOfIssue,
16237
- selectFormsCount,
16238
- selectGeneralFormCount,
16239
15941
  selectHiddenCategoryCount,
16240
15942
  selectHiddenComponentTypeIds,
16241
15943
  selectIsFetchingInitialData,
@@ -16250,10 +15952,10 @@ export {
16250
15952
  selectIssueUpdateMapping,
16251
15953
  selectIssueUpdatesOfIssue,
16252
15954
  selectIssues,
16253
- selectLatestFormRevisionByForm,
16254
- selectLatestFormRevisionOfForm,
16255
- selectLatestFormRevisionsOfComponentTypes,
15955
+ selectLatestFormRevision,
16256
15956
  selectLatestRetryTime,
15957
+ selectLatestRevisionByFormId,
15958
+ selectLatestRevisionsFromComponentTypeIds,
16257
15959
  selectLicense,
16258
15960
  selectLicenseForProject,
16259
15961
  selectLicenses,
@@ -16262,6 +15964,8 @@ export {
16262
15964
  selectMapStyle,
16263
15965
  selectNumberOfComponentTypesMatchingCaseInsensitiveName,
16264
15966
  selectNumberOfComponentsOfComponentType,
15967
+ selectNumberOfGeneralUserForms,
15968
+ selectNumberOfUserForms,
16265
15969
  selectOrganization,
16266
15970
  selectOrganizationAccess,
16267
15971
  selectOrganizationAccessForUser,
@@ -16289,6 +15993,8 @@ export {
16289
15993
  selectRecentIssuesAsSearchResults,
16290
15994
  selectRecentProjects,
16291
15995
  selectRehydrated,
15996
+ selectRevisionAttachments,
15997
+ selectRevisionsForForm,
16292
15998
  selectRootDocuments,
16293
15999
  selectShowTooltips,
16294
16000
  selectSortedEmailDomains,
@@ -16303,10 +16009,16 @@ export {
16303
16009
  selectStagesFromComponentType,
16304
16010
  selectStagesFromComponentTypeIds,
16305
16011
  selectStagesFromStageIds,
16012
+ selectSubmissionAttachments,
16013
+ selectSubmissionsForComponent,
16014
+ selectSubmissionsForForm,
16015
+ selectSubmissionsForIssue,
16306
16016
  selectUploadUrl,
16307
16017
  selectUsedColors,
16308
16018
  selectUser,
16309
- selectUserFormRevisionAttachmentsMapping,
16019
+ selectUserForm,
16020
+ selectUserFormMapping,
16021
+ selectUserFormSubmission,
16310
16022
  selectUsersAsMapping,
16311
16023
  selectVisibleStatuses,
16312
16024
  selectVisibleUserIds,
@@ -16333,13 +16045,6 @@ export {
16333
16045
  setEnableClustering,
16334
16046
  setEnableDuplicateIssues,
16335
16047
  setEnablePlacementMode,
16336
- setFormRevision,
16337
- setFormRevisionAttachments,
16338
- setFormRevisions,
16339
- setFormSubmission,
16340
- setFormSubmissionAttachments,
16341
- setFormSubmissions,
16342
- setForms,
16343
16048
  setIsFetchingInitialData,
16344
16049
  setIsImportingProjectFile,
16345
16050
  setIsLoading,
@@ -16364,6 +16069,9 @@ export {
16364
16069
  setTokens,
16365
16070
  setTourStep,
16366
16071
  setUploadUrl,
16072
+ setUserFormRevisionAttachments,
16073
+ setUserFormSubmissionAttachments,
16074
+ setUserFormSubmissions,
16367
16075
  setUsers,
16368
16076
  setVisibleStatuses,
16369
16077
  setVisibleUserIds,
@@ -16388,13 +16096,11 @@ export {
16388
16096
  updateComponentTypeAttachment,
16389
16097
  updateDocumentAttachment,
16390
16098
  updateDocuments,
16391
- updateFormSubmission,
16392
- updateFormSubmissionAttachments,
16393
- updateFormSubmissions,
16394
16099
  updateIssue,
16395
16100
  updateIssueAttachment,
16396
16101
  updateLicense,
16397
16102
  updateOrCreateProject,
16103
+ updateOrCreateUserFormSubmission,
16398
16104
  updateOrganizationAccess,
16399
16105
  updateProjectAccess,
16400
16106
  updateProjectAttachment,
@@ -16408,6 +16114,8 @@ export {
16408
16114
  useFormikInput,
16409
16115
  useMemoCompare,
16410
16116
  useSDK,
16117
+ userFormReducer,
16118
+ userFormSlice,
16411
16119
  userReducer,
16412
16120
  userSlice,
16413
16121
  valueIsFile,