@overmap-ai/core 1.0.51-bulk-form-submission.0 → 1.0.51

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$p = {
680
+ const initialState$n = {
681
681
  accessToken: "",
682
682
  refreshToken: "",
683
683
  isLoggedIn: false
684
684
  };
685
685
  const authSlice = createSlice({
686
686
  name: "auth",
687
- initialState: initialState$p,
688
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$p)),
687
+ initialState: initialState$n,
688
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$n)),
689
689
  reducers: {
690
690
  setTokens: (state, action) => {
691
691
  state.accessToken = action.payload.accessToken;
@@ -850,19 +850,6 @@ 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
- };
866
853
  const fileToBlob = async (dataUrl) => {
867
854
  return (await fetch(dataUrl)).blob();
868
855
  };
@@ -1429,7 +1416,7 @@ const getLocalRelativeDateString = memoize((date, min, max) => {
1429
1416
  return getLocalDateString(date);
1430
1417
  return relative.format(days, "days");
1431
1418
  });
1432
- const initialState$o = {
1419
+ const initialState$m = {
1433
1420
  categories: {},
1434
1421
  usedCategoryColors: [],
1435
1422
  categoryVisibility: {
@@ -1439,8 +1426,8 @@ const initialState$o = {
1439
1426
  };
1440
1427
  const categorySlice = createSlice({
1441
1428
  name: "categories",
1442
- initialState: initialState$o,
1443
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$o)),
1429
+ initialState: initialState$m,
1430
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$m)),
1444
1431
  reducers: {
1445
1432
  setCategories: (state, action) => {
1446
1433
  if (!Array.isArray(action.payload))
@@ -1609,14 +1596,14 @@ function removeAttachments(state, action) {
1609
1596
  delete state.attachments[attachmentId];
1610
1597
  }
1611
1598
  }
1612
- const initialState$n = {
1599
+ const initialState$l = {
1613
1600
  components: {},
1614
1601
  attachments: {}
1615
1602
  };
1616
1603
  const componentSlice = createSlice({
1617
1604
  name: "components",
1618
- initialState: initialState$n,
1619
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$n)),
1605
+ initialState: initialState$l,
1606
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$l)),
1620
1607
  reducers: {
1621
1608
  addComponent: (state, action) => {
1622
1609
  state.components[action.payload.offline_id] = action.payload;
@@ -1772,13 +1759,13 @@ const {
1772
1759
  removeAllComponentsOfType
1773
1760
  } = componentSlice.actions;
1774
1761
  const componentReducer = componentSlice.reducer;
1775
- const initialState$m = {
1762
+ const initialState$k = {
1776
1763
  completionsByComponentId: {}
1777
1764
  };
1778
1765
  const componentStageCompletionSlice = createSlice({
1779
1766
  name: "componentStageCompletions",
1780
- initialState: initialState$m,
1781
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$m)),
1767
+ initialState: initialState$k,
1768
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$k)),
1782
1769
  reducers: {
1783
1770
  addStageCompletion: (state, action) => {
1784
1771
  let stageToCompletionDateMapping = state.completionsByComponentId[action.payload.component];
@@ -1829,13 +1816,13 @@ const selectCompletedStageIdsForComponent = (component) => (state) => {
1829
1816
  return Object.keys(state.componentStageCompletionReducer.completionsByComponentId[component.offline_id] ?? {});
1830
1817
  };
1831
1818
  const componentStageCompletionReducer = componentStageCompletionSlice.reducer;
1832
- const initialState$l = {
1819
+ const initialState$j = {
1833
1820
  stages: {}
1834
1821
  };
1835
1822
  const componentStageSlice = createSlice({
1836
1823
  name: "componentStages",
1837
- initialState: initialState$l,
1838
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$l)),
1824
+ initialState: initialState$j,
1825
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$j)),
1839
1826
  reducers: {
1840
1827
  addStages: (state, action) => {
1841
1828
  Object.assign(state.stages, toOfflineIdRecord(action.payload));
@@ -1945,15 +1932,15 @@ const selectStageFormIdsFromStageIds = restructureCreateSelectorWithArgs(
1945
1932
  );
1946
1933
  const { addStages, updateStages, removeStages, linkStageToForm, unlinkStageToForm } = componentStageSlice.actions;
1947
1934
  const componentStageReducer = componentStageSlice.reducer;
1948
- const initialState$k = {
1935
+ const initialState$i = {
1949
1936
  componentTypes: {},
1950
1937
  hiddenComponentTypeIds: {},
1951
1938
  attachments: {}
1952
1939
  };
1953
1940
  const componentTypeSlice = createSlice({
1954
1941
  name: "componentTypes",
1955
- initialState: initialState$k,
1956
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$k)),
1942
+ initialState: initialState$i,
1943
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$i)),
1957
1944
  reducers: {
1958
1945
  addComponentType: (state, action) => {
1959
1946
  state.componentTypes[action.payload.offline_id] = action.payload;
@@ -2064,13 +2051,13 @@ const {
2064
2051
  deleteComponentType
2065
2052
  } = componentTypeSlice.actions;
2066
2053
  const componentTypeReducer = componentTypeSlice.reducer;
2067
- const initialState$j = {
2054
+ const initialState$h = {
2068
2055
  workspaces: {},
2069
2056
  activeWorkspaceId: null
2070
2057
  };
2071
2058
  const workspaceSlice = createSlice({
2072
2059
  name: "workspace",
2073
- initialState: initialState$j,
2060
+ initialState: initialState$h,
2074
2061
  // The `reducers` field lets us define reducers and generate associated actions
2075
2062
  reducers: {
2076
2063
  setWorkspaces: (state, action) => {
@@ -2127,7 +2114,7 @@ const selectPermittedWorkspaceIds = createSelector(
2127
2114
  );
2128
2115
  const workspaceReducer = workspaceSlice.reducer;
2129
2116
  const maxRecentIssues = 10;
2130
- const initialState$i = {
2117
+ const initialState$g = {
2131
2118
  issues: {},
2132
2119
  attachments: {},
2133
2120
  comments: {},
@@ -2139,9 +2126,9 @@ const initialState$i = {
2139
2126
  };
2140
2127
  const issueSlice = createSlice({
2141
2128
  name: "issues",
2142
- initialState: initialState$i,
2129
+ initialState: initialState$g,
2143
2130
  extraReducers: (builder) => builder.addCase("RESET", (state) => {
2144
- Object.assign(state, initialState$i);
2131
+ Object.assign(state, initialState$g);
2145
2132
  }),
2146
2133
  reducers: {
2147
2134
  setIssues: (state, action) => {
@@ -2549,15 +2536,15 @@ const selectRecentIssuesAsSearchResults = createSelector(
2549
2536
  }
2550
2537
  );
2551
2538
  const issueReducer = issueSlice.reducer;
2552
- const initialState$h = {
2539
+ const initialState$f = {
2553
2540
  s3Urls: {}
2554
2541
  };
2555
2542
  const msPerHour = 1e3 * 60 * 60;
2556
2543
  const msPerWeek = msPerHour * 24 * 7;
2557
2544
  const fileSlice = createSlice({
2558
2545
  name: "file",
2559
- initialState: initialState$h,
2560
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$h)),
2546
+ initialState: initialState$f,
2547
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$f)),
2561
2548
  reducers: {
2562
2549
  setUploadUrl: (state, action) => {
2563
2550
  const { url, fields, sha1 } = action.payload;
@@ -2584,7 +2571,7 @@ const selectUploadUrl = (sha1) => (state) => {
2584
2571
  return url;
2585
2572
  };
2586
2573
  const fileReducer = fileSlice.reducer;
2587
- const initialState$g = {
2574
+ const initialState$e = {
2588
2575
  // TODO: Change first MapStyle.SATELLITE to MaptStyle.None when project creation map is fixed
2589
2576
  mapStyle: MapStyle.SATELLITE,
2590
2577
  showTooltips: false,
@@ -2592,8 +2579,8 @@ const initialState$g = {
2592
2579
  };
2593
2580
  const mapSlice = createSlice({
2594
2581
  name: "map",
2595
- initialState: initialState$g,
2596
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$g)),
2582
+ initialState: initialState$e,
2583
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$e)),
2597
2584
  reducers: {
2598
2585
  setMapStyle: (state, action) => {
2599
2586
  state.mapStyle = action.payload;
@@ -2662,7 +2649,7 @@ var LicenseStatus = /* @__PURE__ */ ((LicenseStatus2) => {
2662
2649
  LicenseStatus2[LicenseStatus2["PAST_DUE"] = 8] = "PAST_DUE";
2663
2650
  return LicenseStatus2;
2664
2651
  })(LicenseStatus || {});
2665
- const initialState$f = {
2652
+ const initialState$d = {
2666
2653
  users: {},
2667
2654
  currentUser: {
2668
2655
  id: 0,
@@ -2673,8 +2660,8 @@ const initialState$f = {
2673
2660
  };
2674
2661
  const userSlice = createSlice({
2675
2662
  name: "users",
2676
- initialState: initialState$f,
2677
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$f)),
2663
+ initialState: initialState$d,
2664
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$d)),
2678
2665
  reducers: {
2679
2666
  setUsers: (state, action) => {
2680
2667
  const usersMapping = {};
@@ -2736,13 +2723,13 @@ const selectUser = (userId) => (state) => {
2736
2723
  const selectUsersAsMapping = (state) => state.userReducer.users;
2737
2724
  const selectFavouriteProjects = (state) => state.userReducer.currentUser.profile.favourite_project_ids;
2738
2725
  const userReducer = userSlice.reducer;
2739
- const initialState$e = {
2726
+ const initialState$c = {
2740
2727
  organizationAccesses: {}
2741
2728
  };
2742
2729
  const organizationAccessSlice = createSlice({
2743
2730
  name: "organizationAccess",
2744
- initialState: initialState$e,
2745
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$e)),
2731
+ initialState: initialState$c,
2732
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$c)),
2746
2733
  reducers: {
2747
2734
  setOrganizationAccesses: (state, action) => {
2748
2735
  if (!Array.isArray(action.payload))
@@ -2805,13 +2792,13 @@ const selectOrganizationAccessUserMapping = (state) => {
2805
2792
  return organizationAccesses;
2806
2793
  };
2807
2794
  const organizationAccessReducer = organizationAccessSlice.reducer;
2808
- const initialState$d = {
2795
+ const initialState$b = {
2809
2796
  licenses: {}
2810
2797
  };
2811
2798
  const licenseSlice = createSlice({
2812
2799
  name: "license",
2813
- initialState: initialState$d,
2814
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$d)),
2800
+ initialState: initialState$b,
2801
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$b)),
2815
2802
  reducers: {
2816
2803
  setLicenses: (state, action) => {
2817
2804
  if (!Array.isArray(action.payload))
@@ -2856,13 +2843,13 @@ const selectLicensesForProjectsMapping = createSelector(
2856
2843
  (licenses) => Object.values(licenses).filter((license) => license.project).reduce((accum, license) => ({ ...accum, [license.project]: license }), {})
2857
2844
  );
2858
2845
  const licenseReducer = licenseSlice.reducer;
2859
- const initialState$c = {
2846
+ const initialState$a = {
2860
2847
  projectAccesses: {}
2861
2848
  };
2862
2849
  const projectAccessSlice = createSlice({
2863
2850
  name: "projectAccess",
2864
- initialState: initialState$c,
2865
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$c)),
2851
+ initialState: initialState$a,
2852
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$a)),
2866
2853
  reducers: {
2867
2854
  setProjectAccesses: (state, action) => {
2868
2855
  if (!Array.isArray(action.payload))
@@ -2930,7 +2917,7 @@ const selectProjectAccessUserMapping = (state) => {
2930
2917
  return projectAccesses;
2931
2918
  };
2932
2919
  const projectAccessReducer = projectAccessSlice.reducer;
2933
- const initialState$b = {
2920
+ const initialState$9 = {
2934
2921
  projects: {},
2935
2922
  activeProjectId: null,
2936
2923
  recentProjectIds: [],
@@ -2940,7 +2927,7 @@ const initialState$b = {
2940
2927
  };
2941
2928
  const projectSlice = createSlice({
2942
2929
  name: "projects",
2943
- initialState: initialState$b,
2930
+ initialState: initialState$9,
2944
2931
  reducers: {
2945
2932
  setProjects: (state, action) => {
2946
2933
  const projectsMap = {};
@@ -3127,14 +3114,14 @@ const selectAttachmentsOfProjectByType = restructureCreateSelectorWithArgs(
3127
3114
  }
3128
3115
  )
3129
3116
  );
3130
- const initialState$a = {
3117
+ const initialState$8 = {
3131
3118
  organizations: {},
3132
3119
  activeOrganizationId: null
3133
3120
  };
3134
3121
  const organizationSlice = createSlice({
3135
3122
  name: "organizations",
3136
- initialState: initialState$a,
3137
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$a)),
3123
+ initialState: initialState$8,
3124
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$8)),
3138
3125
  reducers: {
3139
3126
  setOrganizations: (state, action) => {
3140
3127
  for (const org of action.payload) {
@@ -3253,14 +3240,14 @@ const createOfflineAction = (request2, baseUrl) => {
3253
3240
  }
3254
3241
  };
3255
3242
  };
3256
- const initialState$9 = {
3243
+ const initialState$7 = {
3257
3244
  deletedRequests: [],
3258
3245
  latestRetryTime: 0
3259
3246
  };
3260
3247
  const outboxSlice = createSlice({
3261
3248
  name: "outbox",
3262
- initialState: initialState$9,
3263
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$9)),
3249
+ initialState: initialState$7,
3250
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$7)),
3264
3251
  reducers: {
3265
3252
  // enqueueActions is a reducer that does nothing but enqueue API request to the Redux Offline outbox
3266
3253
  // Whenever an issue is being created, a reducer addIssue() is responsible for adding it to the offline store
@@ -3292,7 +3279,7 @@ const selectDeletedRequests = (state) => state.outboxReducer.deletedRequests;
3292
3279
  const selectLatestRetryTime = (state) => state.outboxReducer.latestRetryTime;
3293
3280
  const { enqueueRequest, markForDeletion, markAsDeleted, _setLatestRetryTime } = outboxSlice.actions;
3294
3281
  const outboxReducer = outboxSlice.reducer;
3295
- const initialState$8 = {
3282
+ const initialState$6 = {
3296
3283
  projectFiles: {},
3297
3284
  activeProjectFileId: null,
3298
3285
  isImportingProjectFile: false,
@@ -3300,8 +3287,8 @@ const initialState$8 = {
3300
3287
  };
3301
3288
  const projectFileSlice = createSlice({
3302
3289
  name: "projectFiles",
3303
- initialState: initialState$8,
3304
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$8)),
3290
+ initialState: initialState$6,
3291
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$6)),
3305
3292
  reducers: {
3306
3293
  addOrReplaceProjectFiles: (state, action) => {
3307
3294
  for (let fileObj of action.payload) {
@@ -3402,12 +3389,12 @@ const selectProjectFiles = createSelector(
3402
3389
  const selectActiveProjectFileId = (state) => state.projectFileReducer.activeProjectFileId;
3403
3390
  const selectIsImportingProjectFile = (state) => state.projectFileReducer.isImportingProjectFile;
3404
3391
  const projectFileReducer = projectFileSlice.reducer;
3405
- const initialState$7 = {
3392
+ const initialState$5 = {
3406
3393
  isRehydrated: false
3407
3394
  };
3408
3395
  const rehydratedSlice = createSlice({
3409
3396
  name: "rehydrated",
3410
- initialState: initialState$7,
3397
+ initialState: initialState$5,
3411
3398
  // The `reducers` field lets us define reducers and generate associated actions
3412
3399
  reducers: {
3413
3400
  setRehydrated: (state, action) => {
@@ -3417,7 +3404,7 @@ const rehydratedSlice = createSlice({
3417
3404
  });
3418
3405
  const selectRehydrated = (state) => state.rehydratedReducer.isRehydrated;
3419
3406
  const rehydratedReducer = rehydratedSlice.reducer;
3420
- const initialState$6 = {
3407
+ const initialState$4 = {
3421
3408
  useIssueTemplate: false,
3422
3409
  placementMode: false,
3423
3410
  enableClustering: false,
@@ -3434,8 +3421,8 @@ const initialState$6 = {
3434
3421
  };
3435
3422
  const settingSlice = createSlice({
3436
3423
  name: "settings",
3437
- initialState: initialState$6,
3438
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$6)),
3424
+ initialState: initialState$4,
3425
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$4)),
3439
3426
  reducers: {
3440
3427
  setEnableDuplicateIssues: (state, action) => {
3441
3428
  state.useIssueTemplate = action.payload;
@@ -3481,248 +3468,146 @@ const selectAppearance = (state) => state.settingReducer.appearance;
3481
3468
  const settingReducer = settingSlice.reducer;
3482
3469
  const selectIsFetchingInitialData = (state) => state.settingReducer.isFetchingInitialData;
3483
3470
  const selectIsLoading = (state) => state.settingReducer.isLoading;
3484
- const LATEST_FORM_REVISION_CACHE = {};
3485
- function considerCachingFormRevision(formRevision, formId2, preferPending = false) {
3471
+ const LATEST_REVISION_CACHE = {};
3472
+ function considerCachingRevision(revision, formId2, preferPending = false) {
3486
3473
  var _a2;
3487
- if (!formRevision) {
3474
+ if (!revision) {
3488
3475
  if (!formId2) {
3489
- throw new Error("If form revision is null, formId is required.");
3476
+ throw new Error("If revision is null, formId is required.");
3490
3477
  }
3491
- const currentLatestFormRevision = getLatestFormRevisionFromCache(formId2);
3492
- if (currentLatestFormRevision)
3478
+ const currentLatestRevision = getLatestRevisionFromCache(formId2);
3479
+ if (currentLatestRevision)
3493
3480
  return;
3494
- LATEST_FORM_REVISION_CACHE[formId2] = null;
3481
+ LATEST_REVISION_CACHE[formId2] = null;
3495
3482
  return;
3496
3483
  }
3497
- if (formRevision.revision === "Pending") {
3484
+ if (revision.revision === "Pending") {
3498
3485
  if (preferPending) {
3499
- LATEST_FORM_REVISION_CACHE[formRevision.form] = formRevision;
3486
+ LATEST_REVISION_CACHE[revision.form] = revision;
3500
3487
  }
3501
3488
  return;
3502
3489
  }
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;
3490
+ const cachedRevision = (_a2 = LATEST_REVISION_CACHE[revision.form]) == null ? void 0 : _a2.revision;
3491
+ if (revision.revision > (typeof cachedRevision === "number" ? cachedRevision : -1)) {
3492
+ LATEST_REVISION_CACHE[revision.form] = revision;
3506
3493
  }
3507
3494
  }
3508
- function getLatestFormRevisionFromCache(formId2) {
3509
- return LATEST_FORM_REVISION_CACHE[formId2];
3495
+ function getLatestRevisionFromCache(formId2) {
3496
+ return LATEST_REVISION_CACHE[formId2];
3510
3497
  }
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)),
3498
+ const initialState$3 = {
3499
+ userForms: {},
3500
+ revisions: {},
3501
+ submissions: {},
3502
+ submissionAttachments: {},
3503
+ revisionAttachments: {}
3504
+ };
3505
+ const userFormSlice = createSlice({
3506
+ name: "userForms",
3507
+ initialState: initialState$3,
3508
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$3)),
3519
3509
  reducers: {
3520
- // revision related actions
3521
- setFormRevision: (state, action) => {
3522
- state.formRevisions[action.payload.offline_id] = action.payload;
3523
- considerCachingFormRevision(action.payload);
3510
+ setUserForms: (state, action) => {
3511
+ state.userForms = {};
3512
+ action.payload.forEach((userForm) => {
3513
+ state.userForms[userForm.offline_id] = userForm;
3514
+ });
3524
3515
  },
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
- }
3516
+ addUserForm: (state, action) => {
3517
+ state.userForms[action.payload.offline_id] = action.payload;
3531
3518
  },
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);
3519
+ addUserForms: (state, action) => {
3520
+ action.payload.forEach((userForm) => {
3521
+ state.userForms[userForm.offline_id] = userForm;
3522
+ });
3538
3523
  },
3539
- // TODO: @Audiopolis / Magnus - do we want to standardize using PayloadAction?
3540
- addFormRevisions: (state, action) => {
3541
- for (const userFormRevision of action.payload) {
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);
3549
- }
3524
+ addUserFormRevisions: (state, action) => {
3525
+ action.payload.forEach((userFormRevision) => {
3526
+ state.revisions[userFormRevision.offline_id] = userFormRevision;
3527
+ considerCachingRevision(userFormRevision);
3528
+ });
3550
3529
  },
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`);
3555
- }
3556
- delete state.formRevisions[action.payload];
3557
- delete LATEST_FORM_REVISION_CACHE[action.payload];
3530
+ addUserFormRevision: (state, action) => {
3531
+ state.revisions[action.payload.offline_id] = action.payload;
3532
+ considerCachingRevision(action.payload);
3558
3533
  },
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];
3534
+ deleteUserFormRevision: (state, action) => {
3535
+ delete state.revisions[action.payload];
3536
+ delete LATEST_REVISION_CACHE[action.payload];
3537
+ },
3538
+ deleteUserFormRevisions: (state, action) => {
3539
+ for (const userFormRevision of action.payload) {
3540
+ delete state.revisions[userFormRevision.offline_id];
3541
+ delete LATEST_REVISION_CACHE[userFormRevision.offline_id];
3568
3542
  }
3569
3543
  },
3570
- // attachment related actions
3571
- setFormRevisionAttachments: (state, action) => {
3572
- state.attachments = {};
3573
- for (const attachment of action.payload) {
3574
- state.attachments[attachment.offline_id] = attachment;
3544
+ updateOrCreateUserFormSubmission: (state, action) => {
3545
+ state.submissions[action.payload.offline_id] = action.payload;
3546
+ },
3547
+ addUserFormSubmissionAttachment: (state, action) => {
3548
+ const submissionId = action.payload.submission;
3549
+ const submissionAttachments = state.submissionAttachments[submissionId];
3550
+ if (submissionAttachments) {
3551
+ submissionAttachments.push(action.payload);
3552
+ } else {
3553
+ state.submissionAttachments[submissionId] = [action.payload];
3575
3554
  }
3576
3555
  },
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`);
3556
+ addUserFormRevisionAttachment: (state, action) => {
3557
+ const revisionId = action.payload.revision;
3558
+ const revisionAttachments = state.revisionAttachments[revisionId];
3559
+ if (revisionAttachments) {
3560
+ revisionAttachments.push(action.payload);
3561
+ } else {
3562
+ state.revisionAttachments[revisionId] = [action.payload];
3580
3563
  }
3581
- state.attachments[action.payload.offline_id] = action.payload;
3582
3564
  },
3583
- addFormRevisionAttachments: (state, action) => {
3565
+ setUserFormSubmissionAttachments: (state, action) => {
3566
+ state.submissionAttachments = {};
3584
3567
  for (const attachment of action.payload) {
3585
- if (state.attachments[attachment.offline_id] !== void 0) {
3586
- throw new Error(`Attachment with offline_id ${attachment.offline_id} already exists`);
3568
+ const submissionId = attachment.submission;
3569
+ const submissionAttachments = state.submissionAttachments[submissionId];
3570
+ if (submissionAttachments) {
3571
+ submissionAttachments.push(attachment);
3572
+ } else {
3573
+ state.submissionAttachments[submissionId] = [attachment];
3587
3574
  }
3588
3575
  }
3576
+ },
3577
+ setUserFormRevisionAttachments: (state, action) => {
3578
+ state.revisionAttachments = {};
3589
3579
  for (const attachment of action.payload) {
3590
- state.attachments[attachment.offline_id] = attachment;
3580
+ const revisionId = attachment.revision;
3581
+ const revisionAttachments = state.revisionAttachments[revisionId];
3582
+ if (revisionAttachments) {
3583
+ revisionAttachments.push(attachment);
3584
+ } else {
3585
+ state.revisionAttachments[revisionId] = [attachment];
3586
+ }
3591
3587
  }
3592
3588
  },
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`);
3596
- }
3597
- delete state.attachments[action.payload];
3589
+ deleteUserFormSubmission: (state, action) => {
3590
+ delete state.submissions[action.payload];
3598
3591
  },
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];
3592
+ deleteUserFormSubmissions: (state, action) => {
3593
+ for (const userFormSubmission of action.payload) {
3594
+ delete state.submissions[userFormSubmission.offline_id];
3607
3595
  }
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
- }
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
- });
3714
3596
  },
3715
- addForm: (state, action) => {
3716
- state.forms[action.payload.offline_id] = action.payload;
3597
+ addUserFormSubmissions: (state, action) => {
3598
+ for (const submission of action.payload) {
3599
+ state.submissions[submission.offline_id] = submission;
3600
+ }
3717
3601
  },
3718
- addForms: (state, action) => {
3719
- action.payload.forEach((userForm) => {
3720
- state.forms[userForm.offline_id] = userForm;
3602
+ setUserFormSubmissions: (state, action) => {
3603
+ state.submissions = {};
3604
+ action.payload.forEach((submission) => {
3605
+ state.submissions[submission.offline_id] = submission;
3721
3606
  });
3722
3607
  },
3723
3608
  favoriteForm: (state, action) => {
3724
3609
  const { formId: formId2 } = action.payload;
3725
- const form = state.forms[formId2];
3610
+ const form = state.userForms[formId2];
3726
3611
  if (!form) {
3727
3612
  throw new Error("No form exists with the id " + formId2);
3728
3613
  }
@@ -3730,23 +3615,48 @@ const formSlice = createSlice({
3730
3615
  },
3731
3616
  unfavoriteForm: (state, action) => {
3732
3617
  const { formId: formId2 } = action.payload;
3733
- const form = state.forms[formId2];
3618
+ const form = state.userForms[formId2];
3734
3619
  if (!form) {
3735
3620
  throw new Error("No form exists with the id " + formId2);
3736
3621
  }
3737
3622
  form.favorite = false;
3738
3623
  },
3739
- deleteForm: (state, action) => {
3740
- delete state.forms[action.payload];
3624
+ deleteUserForm: (state, action) => {
3625
+ delete state.userForms[action.payload];
3741
3626
  }
3742
3627
  }
3743
3628
  });
3744
- const { setForms, addForm, addForms, favoriteForm, unfavoriteForm, deleteForm } = formSlice.actions;
3745
- const selectFilteredForms = restructureCreateSelectorWithArgs(
3629
+ const {
3630
+ addUserForm,
3631
+ addUserForms,
3632
+ addUserFormRevisions,
3633
+ updateOrCreateUserFormSubmission,
3634
+ addUserFormSubmissions,
3635
+ deleteUserFormSubmission,
3636
+ deleteUserFormSubmissions,
3637
+ favoriteForm,
3638
+ unfavoriteForm,
3639
+ deleteUserForm,
3640
+ deleteUserFormRevision,
3641
+ deleteUserFormRevisions,
3642
+ setUserFormSubmissions,
3643
+ addUserFormRevision,
3644
+ addUserFormSubmissionAttachment,
3645
+ addUserFormRevisionAttachment,
3646
+ setUserFormSubmissionAttachments,
3647
+ setUserFormRevisionAttachments
3648
+ } = userFormSlice.actions;
3649
+ const selectSubmissionAttachments = (submissionId) => (state) => {
3650
+ return state.userFormReducer.submissionAttachments[submissionId] || [];
3651
+ };
3652
+ const selectRevisionAttachments = (revisionId) => (state) => {
3653
+ return state.userFormReducer.revisionAttachments[revisionId] || [];
3654
+ };
3655
+ const selectFilteredUserForms = restructureCreateSelectorWithArgs(
3746
3656
  createSelector(
3747
3657
  [
3748
- (state) => state.formReducer.forms,
3749
- (state) => state.formRevisionReducer.formRevisions,
3658
+ (state) => state.userFormReducer.userForms,
3659
+ (state) => state.userFormReducer.revisions,
3750
3660
  (_state, search) => search
3751
3661
  ],
3752
3662
  (userForms, revisions, search) => {
@@ -3780,188 +3690,63 @@ const selectFilteredForms = restructureCreateSelectorWithArgs(
3780
3690
  { memoizeOptions: { equalityCheck: shallowEqual$1 } }
3781
3691
  )
3782
3692
  );
3783
- const selectForm = (formId2) => (state) => {
3784
- return state.formReducer.forms[formId2];
3693
+ const selectFormRevision = (revisionId) => (state) => {
3694
+ return state.userFormReducer.revisions[revisionId];
3785
3695
  };
3786
- const selectFormMapping = (state) => {
3787
- return state.formReducer.forms;
3696
+ const _selectLatestFormRevision = (revisions, formId2) => {
3697
+ let ret = null;
3698
+ for (const candidate of Object.values(revisions)) {
3699
+ if (candidate.form === formId2 && (!ret || ret.revision < candidate.revision)) {
3700
+ ret = candidate;
3701
+ }
3702
+ }
3703
+ if (!ret) {
3704
+ throw new Error("No revision found for form " + formId2);
3705
+ }
3706
+ return ret;
3788
3707
  };
3789
- const selectFormOfComponentType = restructureCreateSelectorWithArgs(
3708
+ const selectLatestFormRevision = restructureCreateSelectorWithArgs(
3790
3709
  createSelector(
3791
- [selectFormMapping, (_state, componentTypeId) => componentTypeId],
3792
- (userForms, componentTypeId) => {
3793
- return Object.values(userForms).find((userForm) => userForm.component_type === componentTypeId);
3710
+ [(state) => state.userFormReducer.revisions, (_state, formId2) => formId2],
3711
+ (revisions, formId2) => {
3712
+ if (!formId2) {
3713
+ throw new Error("formId is required");
3714
+ }
3715
+ return _selectLatestFormRevision(revisions, formId2);
3794
3716
  }
3795
3717
  )
3796
3718
  );
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
- }
3719
+ const selectUserForm = (formId2) => (state) => {
3720
+ return state.userFormReducer.userForms[formId2];
3721
+ };
3722
+ const selectSubmissionMapping = (state) => state.userFormReducer.submissions;
3723
+ const selectUserFormSubmission = (submissionId) => (state) => {
3724
+ return state.userFormReducer.submissions[submissionId];
3725
+ };
3726
+ const selectSubmissions = createSelector([selectSubmissionMapping], (submissions) => Object.values(submissions));
3727
+ const selectRevisionMapping = (state) => state.userFormReducer.revisions;
3728
+ const selectRevisions = createSelector([selectRevisionMapping], (revisions) => Object.values(revisions));
3729
+ const selectRevisionsForForm = restructureCreateSelectorWithArgs(
3730
+ createSelector([selectRevisions, (_state, formId2) => formId2], (revisions, formId2) => {
3731
+ return revisions.filter((revision) => {
3732
+ return revision.form === formId2;
3733
+ });
3734
+ })
3947
3735
  );
3948
- const selectFormSubmission = (submissionId) => (state) => {
3949
- return state.formSubmissionReducer.formSubmissions[submissionId];
3950
- };
3951
- const selectFormSubmissionsOfForm = restructureCreateSelectorWithArgs(
3736
+ const selectSubmissionsForForm = restructureCreateSelectorWithArgs(
3952
3737
  createSelector(
3953
- [selectFormSubmissions, selectFormRevisionMapping, (_state, formId2) => formId2],
3738
+ [selectSubmissions, selectRevisionMapping, (_state, formId2) => formId2],
3954
3739
  (submissions, revisionMapping, formId2) => {
3955
- return submissions.filter((submission) => {
3740
+ return Object.values(submissions).filter((submission) => {
3956
3741
  const revision = revisionMapping[submission.form_revision];
3957
3742
  return (revision == null ? void 0 : revision.form) === formId2;
3958
3743
  });
3959
3744
  }
3960
3745
  )
3961
3746
  );
3962
- const selectFormSubmissionsOfIssue = restructureCreateSelectorWithArgs(
3747
+ const selectSubmissionsForIssue = restructureCreateSelectorWithArgs(
3963
3748
  createSelector(
3964
- [selectFormSubmissions, (_state, issueId) => issueId],
3749
+ [(state) => state.userFormReducer.submissions, (_state, issueId) => issueId],
3965
3750
  (submissions, issueId) => {
3966
3751
  return Object.values(submissions).filter((submission) => {
3967
3752
  return submission.issue === issueId;
@@ -3969,9 +3754,9 @@ const selectFormSubmissionsOfIssue = restructureCreateSelectorWithArgs(
3969
3754
  }
3970
3755
  )
3971
3756
  );
3972
- const selectFormSubmissionsOfComponent = restructureCreateSelectorWithArgs(
3757
+ const selectSubmissionsForComponent = restructureCreateSelectorWithArgs(
3973
3758
  createSelector(
3974
- [selectFormSubmissions, (_state, componentId) => componentId],
3759
+ [selectSubmissions, (_state, componentId) => componentId],
3975
3760
  (submissions, componentId) => {
3976
3761
  return submissions.filter((submission) => {
3977
3762
  return submission.component === componentId;
@@ -3979,8 +3764,8 @@ const selectFormSubmissionsOfComponent = restructureCreateSelectorWithArgs(
3979
3764
  }
3980
3765
  )
3981
3766
  );
3982
- const selectFormSubmissionsByComponents = createSelector(
3983
- [selectFormSubmissionsMapping, selectComponentsMapping],
3767
+ const selectComponentSubmissionMapping = createSelector(
3768
+ [selectSubmissionMapping, selectComponentsMapping],
3984
3769
  (submissions, components) => {
3985
3770
  var _a2;
3986
3771
  const componentSubmissionMapping = {};
@@ -3996,18 +3781,54 @@ const selectFormSubmissionsByComponents = createSelector(
3996
3781
  return componentSubmissionMapping;
3997
3782
  }
3998
3783
  );
3999
- const selectFormSubmissionAttachmentsMapping = (state) => {
4000
- return state.formSubmissionReducer.attachments;
3784
+ const selectUserFormMapping = (state) => {
3785
+ return state.userFormReducer.userForms;
4001
3786
  };
4002
- const selectAttachmentsOfFormSubmission = restructureCreateSelectorWithArgs(
3787
+ const selectComponentTypeForm = restructureCreateSelectorWithArgs(
4003
3788
  createSelector(
4004
- [selectFormSubmissionAttachmentsMapping, (_state, submissionId) => submissionId],
4005
- (attachmentsMapping, submissionId) => {
4006
- return Object.values(attachmentsMapping).filter((attachment) => attachment.submission === submissionId);
3789
+ [selectUserFormMapping, (_state, componentTypeId) => componentTypeId],
3790
+ (userForms, componentTypeId) => {
3791
+ return Object.values(userForms).find((userForm) => userForm.component_type === componentTypeId);
3792
+ }
3793
+ )
3794
+ );
3795
+ const selectLatestRevisionsFromComponentTypeIds = restructureCreateSelectorWithArgs(
3796
+ createSelector(
3797
+ [
3798
+ selectUserFormMapping,
3799
+ selectRevisionMapping,
3800
+ (_state, componentTypeIds) => componentTypeIds
3801
+ ],
3802
+ (userForms, revisions, componentTypeIds) => {
3803
+ const componentTypeIdsSet = new Set(componentTypeIds);
3804
+ const ret = {};
3805
+ for (const form of Object.values(userForms)) {
3806
+ if (form.component_type && componentTypeIdsSet.has(form.component_type)) {
3807
+ ret[form.component_type] = _selectLatestFormRevision(revisions, form.offline_id);
3808
+ }
3809
+ }
3810
+ return ret;
4007
3811
  }
4008
3812
  )
4009
3813
  );
4010
- const formSubmissionReducer = formSubmissionSlice.reducer;
3814
+ const selectLatestRevisionByFormId = createSelector([selectRevisionMapping], (revisions) => {
3815
+ const latestRevisions = {};
3816
+ for (const revision of Object.values(revisions)) {
3817
+ const formId2 = revision.form;
3818
+ const currentLatestRevision = latestRevisions[formId2];
3819
+ if (!currentLatestRevision || currentLatestRevision.revision < revision.revision) {
3820
+ latestRevisions[formId2] = revision;
3821
+ }
3822
+ }
3823
+ return latestRevisions;
3824
+ });
3825
+ const selectNumberOfUserForms = createSelector([selectUserFormMapping], (userForms) => {
3826
+ return Object.keys(userForms).length;
3827
+ });
3828
+ const selectNumberOfGeneralUserForms = createSelector([selectUserFormMapping], (userForms) => {
3829
+ return Object.values(userForms).filter((form) => !form.component_type).length;
3830
+ });
3831
+ const userFormReducer = userFormSlice.reducer;
4011
3832
  const initialState$2 = {
4012
3833
  emailDomains: {}
4013
3834
  };
@@ -4305,9 +4126,7 @@ const overmapReducers = {
4305
4126
  projectFileReducer,
4306
4127
  rehydratedReducer,
4307
4128
  settingReducer,
4308
- formReducer,
4309
- formRevisionReducer,
4310
- formSubmissionReducer,
4129
+ userFormReducer,
4311
4130
  userReducer,
4312
4131
  workspaceReducer,
4313
4132
  emailDomainsReducer,
@@ -4360,7 +4179,9 @@ function handleWorkspaceRemoval(draft, action) {
4360
4179
  throw new Error(`Failed to update index_workspace of issue ${issue.offline_id} to main workspace`);
4361
4180
  }
4362
4181
  }
4363
- const indexedForms = Object.values(draft.formReducer.forms).filter((form) => form.index_workspace === workspaceId);
4182
+ const indexedForms = Object.values(draft.userFormReducer.userForms).filter(
4183
+ (form) => form.index_workspace === workspaceId
4184
+ );
4364
4185
  for (const form of indexedForms) {
4365
4186
  form.index_workspace = mainWorkspace.offline_id;
4366
4187
  }
@@ -6988,7 +6809,7 @@ class UserFormService extends BaseApiService {
6988
6809
  ...revisionAttachmentPayload,
6989
6810
  file: URL.createObjectURL(image)
6990
6811
  };
6991
- store.dispatch(addFormRevisionAttachment(offlinePayload));
6812
+ store.dispatch(addUserFormRevisionAttachment(offlinePayload));
6992
6813
  return attach;
6993
6814
  });
6994
6815
  });
@@ -7022,8 +6843,8 @@ class UserFormService extends BaseApiService {
7022
6843
  revision: 0
7023
6844
  };
7024
6845
  const { store } = this.client;
7025
- store.dispatch(addForm(retForm));
7026
- store.dispatch(addFormRevision(retRevision));
6846
+ store.dispatch(addUserForm(retForm));
6847
+ store.dispatch(addUserFormRevision(retRevision));
7027
6848
  const formPromise = this.enqueueRequest({
7028
6849
  description: "Create form",
7029
6850
  method: HttpMethod.POST,
@@ -7041,8 +6862,8 @@ class UserFormService extends BaseApiService {
7041
6862
  });
7042
6863
  const attachImagesPromises = this.getAttachImagePromises(images, offlineRevisionPayload.offline_id);
7043
6864
  void formPromise.catch((e) => {
7044
- store.dispatch(deleteForm(retForm.offline_id));
7045
- store.dispatch(deleteFormRevision(retRevision.offline_id));
6865
+ store.dispatch(deleteUserForm(retForm.offline_id));
6866
+ store.dispatch(deleteUserFormRevision(retRevision.offline_id));
7046
6867
  throw e;
7047
6868
  });
7048
6869
  const settledPromise = Promise.all([formPromise, ...attachImagesPromises]).then(() => formPromise);
@@ -7084,7 +6905,7 @@ class UserFormService extends BaseApiService {
7084
6905
  revision: "Pending",
7085
6906
  form: formId2
7086
6907
  };
7087
- store.dispatch(addFormRevision(fullRevision));
6908
+ store.dispatch(addUserFormRevision(fullRevision));
7088
6909
  const promise = this.enqueueRequest({
7089
6910
  description: "Create form revision",
7090
6911
  method: HttpMethod.PATCH,
@@ -7098,9 +6919,9 @@ class UserFormService extends BaseApiService {
7098
6919
  });
7099
6920
  const attachImagesPromises = this.getAttachImagePromises(images, offlineRevision.offline_id);
7100
6921
  void promise.then((result) => {
7101
- store.dispatch(setFormRevision(result));
6922
+ store.dispatch(addUserFormRevision(result));
7102
6923
  }).catch(() => {
7103
- store.dispatch(deleteFormRevision(fullRevision.offline_id));
6924
+ store.dispatch(deleteUserFormRevision(fullRevision.offline_id));
7104
6925
  });
7105
6926
  const settledPromise = Promise.all([promise, ...attachImagesPromises]).then(() => promise);
7106
6927
  return [fullRevision, settledPromise];
@@ -7142,19 +6963,19 @@ class UserFormService extends BaseApiService {
7142
6963
  async delete(formId2) {
7143
6964
  const { store } = this.client;
7144
6965
  const state = store.getState();
7145
- const userForm = selectForm(formId2)(state);
6966
+ const userForm = selectUserForm(formId2)(state);
7146
6967
  if (!userForm) {
7147
6968
  throw new Error("Expected userForm to exist");
7148
6969
  }
7149
- const userFormSubmissions = selectFormSubmissionsOfForm(formId2)(state);
6970
+ const userFormSubmissions = selectSubmissionsForForm(formId2)(state);
7150
6971
  if (userFormSubmissions && userFormSubmissions.length > 0) {
7151
- store.dispatch(deleteFormSubmissions(userFormSubmissions.map(({ offline_id }) => offline_id)));
6972
+ store.dispatch(deleteUserFormSubmissions(userFormSubmissions));
7152
6973
  }
7153
- const userFormRevisions = selectFormRevisionsOfForm(formId2)(state);
6974
+ const userFormRevisions = selectRevisionsForForm(formId2)(state);
7154
6975
  if (userFormRevisions && userFormRevisions.length > 0) {
7155
- store.dispatch(deleteFormRevisions(userFormRevisions.map(({ offline_id }) => offline_id)));
6976
+ store.dispatch(deleteUserFormRevisions(userFormRevisions));
7156
6977
  }
7157
- store.dispatch(deleteForm(formId2));
6978
+ store.dispatch(deleteUserForm(formId2));
7158
6979
  try {
7159
6980
  return await this.enqueueRequest({
7160
6981
  description: "Delete form",
@@ -7164,12 +6985,12 @@ class UserFormService extends BaseApiService {
7164
6985
  blocks: []
7165
6986
  });
7166
6987
  } catch (e) {
7167
- store.dispatch(addForm(userForm));
6988
+ store.dispatch(addUserForm(userForm));
7168
6989
  if (userFormRevisions && userFormRevisions.length > 0) {
7169
- store.dispatch(addFormRevisions(userFormRevisions));
6990
+ store.dispatch(addUserFormRevisions(userFormRevisions));
7170
6991
  }
7171
6992
  if (userFormSubmissions && userFormSubmissions.length > 0) {
7172
- store.dispatch(addFormSubmissions(userFormSubmissions));
6993
+ store.dispatch(addUserFormSubmissions(userFormSubmissions));
7173
6994
  }
7174
6995
  throw e;
7175
6996
  }
@@ -7183,15 +7004,16 @@ class UserFormService extends BaseApiService {
7183
7004
  blockers: [],
7184
7005
  blocks: []
7185
7006
  });
7186
- store.dispatch(setForms(Object.values(result.forms)));
7187
- store.dispatch(setFormRevisions(Object.values(result.revisions)));
7188
- store.dispatch(setFormRevisionAttachments(Object.values(result.attachments)));
7007
+ store.dispatch(addUserForms(Object.values(result.forms)));
7008
+ store.dispatch(addUserFormRevisions(Object.values(result.revisions)));
7009
+ store.dispatch(setUserFormRevisionAttachments(Object.values(result.attachments)));
7189
7010
  }
7190
7011
  }
7191
7012
  const isArrayOfFiles = (value) => {
7192
7013
  return Array.isArray(value) && value[0] instanceof File;
7193
7014
  };
7194
- const separateFilesFromValues = (values) => {
7015
+ const separateFilesFromValues = (payload) => {
7016
+ const { values } = payload;
7195
7017
  const files = {};
7196
7018
  const newValues = {};
7197
7019
  for (const key in values) {
@@ -7206,13 +7028,17 @@ const separateFilesFromValues = (values) => {
7206
7028
  newValues[key] = value;
7207
7029
  }
7208
7030
  }
7209
- return { values: newValues, files };
7031
+ const payloadWithoutFiles = {
7032
+ ...payload,
7033
+ values: newValues
7034
+ };
7035
+ return { payloadWithoutFiles, files };
7210
7036
  };
7211
7037
  class UserFormSubmissionService extends BaseApiService {
7212
7038
  constructor() {
7213
7039
  super(...arguments);
7214
7040
  // Attach files to submission, after uploading them to S3
7215
- __publicField(this, "getAttachFilesPromises", (files, submission) => {
7041
+ __publicField(this, "getAttachFilesPromises", (files, payload) => {
7216
7042
  const { store } = this.client;
7217
7043
  return Object.entries(files).map(async ([key, fileArray]) => {
7218
7044
  const attachResults = [];
@@ -7222,27 +7048,24 @@ class UserFormSubmissionService extends BaseApiService {
7222
7048
  const [fileProps] = await this.client.files.uploadFileToS3(sha1);
7223
7049
  const submissionAttachmentPayload = offline({
7224
7050
  ...fileProps,
7225
- submission: submission.offline_id,
7051
+ submission: payload.offline_id,
7226
7052
  field_identifier: key
7227
7053
  });
7228
7054
  const attach = await this.enqueueRequest({
7229
7055
  description: "Attach file to form submission",
7230
7056
  method: HttpMethod.POST,
7231
- url: `/forms/submission/${submission.offline_id}/attachments/`,
7057
+ url: `/forms/submission/${payload.offline_id}/attachments/`,
7232
7058
  payload: submissionAttachmentPayload,
7233
- blockers: [
7234
- submission.component,
7235
- submission.component_stage,
7236
- submission.issue,
7237
- submission.form_revision
7238
- ].filter((x) => x !== void 0),
7059
+ blockers: [payload.component, payload.component_stage, payload.issue, payload.form_revision].filter(
7060
+ (x) => x !== void 0
7061
+ ),
7239
7062
  blocks: [submissionAttachmentPayload.offline_id]
7240
7063
  });
7241
7064
  const offlinePayload = {
7242
7065
  ...submissionAttachmentPayload,
7243
7066
  file: URL.createObjectURL(file)
7244
7067
  };
7245
- store.dispatch(addFormSubmissionAttachment(offlinePayload));
7068
+ store.dispatch(addUserFormSubmissionAttachment(offlinePayload));
7246
7069
  attachResults.push(attach);
7247
7070
  }
7248
7071
  return attachResults;
@@ -7256,165 +7079,70 @@ class UserFormSubmissionService extends BaseApiService {
7256
7079
  if (!activeProjectId) {
7257
7080
  throw new Error("Expected an active project");
7258
7081
  }
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
- };
7082
+ const { payloadWithoutFiles, files } = separateFilesFromValues(payload);
7266
7083
  const promise = this.enqueueRequest({
7267
7084
  description: "Respond to form",
7268
7085
  method: HttpMethod.POST,
7269
7086
  url: `/forms/revisions/${payload.form_revision}/respond/`,
7270
- payload: { ...offlineSubmission, project: activeProjectId },
7087
+ payload: { ...payloadWithoutFiles, project: activeProjectId },
7271
7088
  blockers: [payload.issue, payload.component, payload.component_stage, "add-form-entry"].filter(
7272
7089
  (x) => x !== void 0
7273
7090
  ),
7274
7091
  blocks: [payload.offline_id]
7275
7092
  });
7276
- const attachFilesPromises = this.getAttachFilesPromises(files, offlineSubmission);
7277
- store.dispatch(addFormSubmission(offlineSubmission));
7093
+ const attachFilesPromises = this.getAttachFilesPromises(files, payload);
7094
+ const now = (/* @__PURE__ */ new Date()).toISOString();
7095
+ const fullOfflineResult = {
7096
+ ...payload,
7097
+ created_by: state.userReducer.currentUser.id,
7098
+ created_at: now,
7099
+ updated_at: now
7100
+ };
7101
+ const offlineResultWithoutFiles = {
7102
+ ...fullOfflineResult,
7103
+ ...payloadWithoutFiles
7104
+ };
7105
+ store.dispatch(updateOrCreateUserFormSubmission(offlineResultWithoutFiles));
7278
7106
  void promise.then((result) => {
7279
7107
  store.dispatch(addActiveProjectFormSubmissionsCount(1));
7280
- store.dispatch(setFormSubmission(result));
7108
+ store.dispatch(updateOrCreateUserFormSubmission(result));
7281
7109
  return result;
7282
7110
  }).catch(() => {
7283
- store.dispatch(deleteFormSubmission(payload.offline_id));
7111
+ store.dispatch(deleteUserFormSubmission(payload.offline_id));
7284
7112
  store.dispatch(addActiveProjectFormSubmissionsCount(-1));
7285
7113
  });
7286
7114
  const settledPromise = Promise.all([promise, ...attachFilesPromises]).then(() => promise);
7287
- return [offlineSubmission, settledPromise];
7288
- }
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;
7293
- const { store } = this.client;
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
- }
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)];
7115
+ return [fullOfflineResult, settledPromise];
7385
7116
  }
7386
7117
  update(submission) {
7387
7118
  const { store } = this.client;
7388
- const { values, files } = separateFilesFromValues(submission.values);
7119
+ const { payloadWithoutFiles, files } = separateFilesFromValues(submission);
7120
+ if (!("created_by" in payloadWithoutFiles) || !("created_at" in payloadWithoutFiles)) {
7121
+ throw new Error("Expected payloadWithoutFiles to have created_by and created_at fields.");
7122
+ }
7389
7123
  const attachFilesPromises = this.getAttachFilesPromises(files, submission);
7390
- const offlineSubmission = {
7391
- ...submission,
7392
- values
7124
+ const fullResult = {
7125
+ ...payloadWithoutFiles,
7126
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
7393
7127
  };
7394
- const submissionToBeUpdated = store.getState().formSubmissionReducer.formSubmissions[submission.offline_id];
7395
- store.dispatch(updateFormSubmission(offlineSubmission));
7128
+ store.dispatch(updateOrCreateUserFormSubmission(fullResult));
7396
7129
  const promise = this.enqueueRequest({
7397
7130
  description: "Patch form submission",
7398
7131
  method: HttpMethod.PATCH,
7399
7132
  url: `/forms/submissions/${submission.offline_id}/`,
7400
- payload: offlineSubmission,
7401
- blockers: [offlineSubmission.issue, offlineSubmission.component, offlineSubmission.component_stage].filter(
7133
+ payload: fullResult,
7134
+ blockers: [fullResult.issue, fullResult.component, fullResult.component_stage].filter(
7402
7135
  (x) => x !== void 0
7403
7136
  ),
7404
- blocks: [offlineSubmission.offline_id]
7137
+ blocks: [fullResult.offline_id]
7405
7138
  });
7406
- promise.then((createdSubmission) => {
7407
- store.dispatch(setFormSubmission(createdSubmission));
7408
- }).catch(() => {
7409
- store.dispatch(setFormSubmission(submissionToBeUpdated));
7410
- });
7411
- return [offlineSubmission, Promise.all([promise, ...attachFilesPromises]).then(() => promise)];
7139
+ return Promise.all([promise, ...attachFilesPromises]).then(() => promise);
7412
7140
  }
7413
7141
  async delete(submissionId) {
7414
7142
  const { store } = this.client;
7415
7143
  const state = store.getState();
7416
- const submission = state.formSubmissionReducer.formSubmissions[submissionId];
7417
- store.dispatch(deleteFormSubmission(submissionId));
7144
+ const submission = state.userFormReducer.submissions[submissionId];
7145
+ store.dispatch(deleteUserFormSubmission(submissionId));
7418
7146
  store.dispatch(addActiveProjectFormSubmissionsCount(-1));
7419
7147
  try {
7420
7148
  return await this.enqueueRequest({
@@ -7425,8 +7153,10 @@ class UserFormSubmissionService extends BaseApiService {
7425
7153
  blocks: []
7426
7154
  });
7427
7155
  } catch (e) {
7428
- store.dispatch(addActiveProjectFormSubmissionsCount(1));
7429
- store.dispatch(addFormSubmission(submission));
7156
+ if (submission) {
7157
+ store.dispatch(addActiveProjectFormSubmissionsCount(1));
7158
+ store.dispatch(updateOrCreateUserFormSubmission(submission));
7159
+ }
7430
7160
  throw e;
7431
7161
  }
7432
7162
  }
@@ -7440,7 +7170,7 @@ class UserFormSubmissionService extends BaseApiService {
7440
7170
  blockers: [],
7441
7171
  blocks: []
7442
7172
  });
7443
- store.dispatch(setFormSubmissions(submissions));
7173
+ store.dispatch(setUserFormSubmissions(submissions));
7444
7174
  const attachments = await this.enqueueRequest({
7445
7175
  description: "Fetch form attachments",
7446
7176
  method: HttpMethod.GET,
@@ -7448,7 +7178,7 @@ class UserFormSubmissionService extends BaseApiService {
7448
7178
  blockers: [],
7449
7179
  blocks: []
7450
7180
  });
7451
- store.dispatch(setFormSubmissionAttachments(attachments));
7181
+ store.dispatch(setUserFormSubmissionAttachments(attachments));
7452
7182
  }
7453
7183
  }
7454
7184
  class WorkspaceService extends BaseApiService {
@@ -14306,7 +14036,7 @@ const initialFormValues = (fields, values) => {
14306
14036
  };
14307
14037
  const useAttachImagesToFormRevisionFields = (revision) => {
14308
14038
  const { sdk } = useSDK();
14309
- const attachments = useAppSelector(selectAttachmentsOfFormRevision((revision == null ? void 0 : revision.offline_id) ?? ""));
14039
+ const attachments = useAppSelector(selectRevisionAttachments((revision == null ? void 0 : revision.offline_id) ?? ""));
14310
14040
  return useMemo(() => {
14311
14041
  if (!revision || !attachments)
14312
14042
  return revision;
@@ -14403,7 +14133,7 @@ const FormSubmissionViewer = memo(
14403
14133
  return formRevisionToSchema(revisionWithImages, { readonly: true });
14404
14134
  }, [revisionWithImages]);
14405
14135
  const submissionValuesWithAttachments = useMemo(() => {
14406
- const attachments = selectAttachmentsOfFormSubmission(submission.offline_id)(sdk.store.getState()) ?? [];
14136
+ const attachments = selectSubmissionAttachments(submission.offline_id)(sdk.store.getState()) ?? [];
14407
14137
  const downloadedAttachments = {};
14408
14138
  for (const attachment of attachments) {
14409
14139
  const promise = sdk.files.fetchFileFromUrl(attachment.file, attachment.file_sha1, attachment.file_name);
@@ -14453,8 +14183,8 @@ const FormBrowser = memo(
14453
14183
  }
14454
14184
  return ret;
14455
14185
  }, [filter, maxResults, ownerFilter]);
14456
- const userForms = useAppSelector(selectFilteredForms(ownerFilterOptions)) ?? [];
14457
- const userFormMapping = useAppSelector(selectFormMapping);
14186
+ const userForms = useAppSelector(selectFilteredUserForms(ownerFilterOptions)) ?? [];
14187
+ const userFormMapping = useAppSelector(selectUserFormMapping);
14458
14188
  const attachableUserForms = userForms.filter((form) => !form.component_type);
14459
14189
  const attachableUserFormMapping = Object.values(userFormMapping).filter(
14460
14190
  (form) => !form.component_type
@@ -14487,7 +14217,7 @@ const FormBrowser = memo(
14487
14217
  const handleChange = useCallback((e) => {
14488
14218
  setFilter(e.currentTarget.value);
14489
14219
  }, []);
14490
- const numberOfForms = useAppSelector(selectGeneralFormCount) || 0;
14220
+ const numberOfForms = useAppSelector(selectNumberOfGeneralUserForms) || 0;
14491
14221
  const numberOfHiddenForms = numberOfForms - attachableUserForms.length;
14492
14222
  const overflowMessage = attachableUserForms.length == maxResults && numberOfHiddenForms > 0 ? `Only the first ${maxResults} results are shown (${numberOfHiddenForms} hidden)` : numberOfHiddenForms > 0 && `${numberOfHiddenForms} hidden forms`;
14493
14223
  return /* @__PURE__ */ jsxs(Flex$1, { ref, direction: "column", gap: "2", children: [
@@ -14581,13 +14311,16 @@ const FormSubmissionBrowserEntry = memo((props) => {
14581
14311
  const { submission, onSubmissionClick, compact, labelType, rowDecorator } = props;
14582
14312
  const currentUser = useAppSelector(selectCurrentUser);
14583
14313
  const createdBy = useAppSelector(selectUser("created_by" in submission ? submission.created_by : currentUser.id));
14584
- const dateToUse = submission.submitted_at;
14585
- const formattedDateTime = getLocalDateString(dateToUse);
14314
+ const dateToUse = getCreatedAtOrSubmittedAtDate(submission);
14315
+ const formattedDateTime = isToday(dateToUse) ? dateToUse.toLocaleTimeString([], {
14316
+ hour: "2-digit",
14317
+ minute: "2-digit"
14318
+ }) : getLocalDateString(dateToUse);
14586
14319
  const revision = useAppSelector(selectFormRevision(submission.form_revision));
14587
14320
  if (!revision) {
14588
14321
  throw new Error(`Could not find revision ${submission.form_revision} for submission ${submission.offline_id}.`);
14589
14322
  }
14590
- const latestRevisionNumber = (_a2 = useAppSelector(selectLatestFormRevisionOfForm(revision.form))) == null ? void 0 : _a2.revision;
14323
+ const latestRevisionNumber = (_a2 = useAppSelector(selectLatestFormRevision(revision.form))) == null ? void 0 : _a2.revision;
14591
14324
  const creatorProfileSrc = useFileSrc({
14592
14325
  file: (createdBy == null ? void 0 : createdBy.profile.file) ?? null,
14593
14326
  fileSha1: (createdBy == null ? void 0 : createdBy.profile.file_sha1) ?? null
@@ -14618,6 +14351,10 @@ const FormSubmissionBrowserEntry = memo((props) => {
14618
14351
  return row;
14619
14352
  });
14620
14353
  FormSubmissionBrowserEntry.displayName = "FormSubmissionBrowserEntry";
14354
+ const getCreatedAtOrSubmittedAtDate = (submission) => {
14355
+ const date = "created_at" in submission ? submission.created_at : submission.submitted_at;
14356
+ return new Date(date);
14357
+ };
14621
14358
  const FormSubmissionBrowser = memo((props) => {
14622
14359
  const {
14623
14360
  formId: formId2,
@@ -14631,10 +14368,10 @@ const FormSubmissionBrowser = memo((props) => {
14631
14368
  if (!!formId2 === !!propSubmissions) {
14632
14369
  throw new Error("Either formId or submissions must be provided, but not both.");
14633
14370
  }
14634
- const submissions = useAppSelector(propSubmissions ? () => propSubmissions : selectFormSubmissionsOfForm(formId2));
14371
+ const submissions = useAppSelector(propSubmissions ? () => propSubmissions : selectSubmissionsForForm(formId2));
14635
14372
  const sortedSubmissions = useMemo(
14636
14373
  () => submissions == null ? void 0 : submissions.sort((a, b) => {
14637
- return a.submitted_at.localeCompare(b.submitted_at);
14374
+ return getCreatedAtOrSubmittedAtDate(b).getTime() - getCreatedAtOrSubmittedAtDate(a).getTime();
14638
14375
  }),
14639
14376
  [submissions]
14640
14377
  );
@@ -15952,7 +15689,6 @@ export {
15952
15689
  VerificationCodeType,
15953
15690
  WorkspaceService,
15954
15691
  YELLOW,
15955
- _selectLatestFormRevision,
15956
15692
  _setLatestRetryTime,
15957
15693
  acceptProjectInvite,
15958
15694
  addActiveProjectFormSubmissionsCount,
@@ -15970,16 +15706,6 @@ export {
15970
15706
  addDocuments,
15971
15707
  addEmailDomain,
15972
15708
  addFavouriteProjectId,
15973
- addForm,
15974
- addFormRevision,
15975
- addFormRevisionAttachment,
15976
- addFormRevisionAttachments,
15977
- addFormRevisions,
15978
- addFormSubmission,
15979
- addFormSubmissionAttachment,
15980
- addFormSubmissionAttachments,
15981
- addFormSubmissions,
15982
- addForms,
15983
15709
  addIssue,
15984
15710
  addIssueAttachment,
15985
15711
  addIssueAttachments,
@@ -16000,6 +15726,13 @@ export {
16000
15726
  addStageCompletions,
16001
15727
  addStages,
16002
15728
  addToRecentIssues,
15729
+ addUserForm,
15730
+ addUserFormRevision,
15731
+ addUserFormRevisionAttachment,
15732
+ addUserFormRevisions,
15733
+ addUserFormSubmissionAttachment,
15734
+ addUserFormSubmissions,
15735
+ addUserForms,
16003
15736
  addUsers,
16004
15737
  addWorkspace,
16005
15738
  areArraysEqual,
@@ -16020,7 +15753,6 @@ export {
16020
15753
  componentStageSlice,
16021
15754
  componentTypeReducer,
16022
15755
  componentTypeSlice,
16023
- constructUploadedFilePayloads,
16024
15756
  coordinatesAreEqual,
16025
15757
  coordinatesToLiteral,
16026
15758
  coordinatesToPointGeometry,
@@ -16031,16 +15763,12 @@ export {
16031
15763
  defaultBadgeColor,
16032
15764
  defaultStore,
16033
15765
  deleteComponentType,
16034
- deleteForm,
16035
- deleteFormRevision,
16036
- deleteFormRevisionAttachment,
16037
- deleteFormRevisionAttachments,
16038
- deleteFormRevisions,
16039
- deleteFormSubmission,
16040
- deleteFormSubmissionAttachment,
16041
- deleteFormSubmissionAttachments,
16042
- deleteFormSubmissions,
16043
15766
  deleteProject,
15767
+ deleteUserForm,
15768
+ deleteUserFormRevision,
15769
+ deleteUserFormRevisions,
15770
+ deleteUserFormSubmission,
15771
+ deleteUserFormSubmissions,
16044
15772
  dequeue,
16045
15773
  deserialize,
16046
15774
  deserializeField,
@@ -16069,13 +15797,7 @@ export {
16069
15797
  fileSlice,
16070
15798
  fileToBlob,
16071
15799
  flipCoordinates,
16072
- formReducer,
16073
- formRevisionReducer,
16074
15800
  formRevisionToSchema,
16075
- formRevisionsSlice,
16076
- formSlice,
16077
- formSubmissionReducer,
16078
- formSubmissionSlice,
16079
15801
  index as forms,
16080
15802
  fullComponentMarkerSize,
16081
15803
  generateBadgeColors,
@@ -16203,8 +15925,6 @@ export {
16203
15925
  selectAttachmentsOfComponentTypeByType,
16204
15926
  selectAttachmentsOfDocument,
16205
15927
  selectAttachmentsOfDocumentByType,
16206
- selectAttachmentsOfFormRevision,
16207
- selectAttachmentsOfFormSubmission,
16208
15928
  selectAttachmentsOfIssue,
16209
15929
  selectAttachmentsOfIssueByType,
16210
15930
  selectAttachmentsOfProject,
@@ -16222,9 +15942,11 @@ export {
16222
15942
  selectComponent,
16223
15943
  selectComponentAttachment,
16224
15944
  selectComponentAttachmentMapping,
15945
+ selectComponentSubmissionMapping,
16225
15946
  selectComponentType,
16226
15947
  selectComponentTypeAttachment,
16227
15948
  selectComponentTypeAttachmentMapping,
15949
+ selectComponentTypeForm,
16228
15950
  selectComponentTypeFromComponent,
16229
15951
  selectComponentTypeFromComponents,
16230
15952
  selectComponentTypeStagesMapping,
@@ -16254,24 +15976,8 @@ export {
16254
15976
  selectExpandedSections,
16255
15977
  selectFavouriteProjects,
16256
15978
  selectFileAttachmentsOfIssue,
16257
- selectFilteredForms,
16258
- selectForm,
16259
- selectFormMapping,
16260
- selectFormOfComponentType,
15979
+ selectFilteredUserForms,
16261
15980
  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,
16275
15981
  selectHiddenCategoryCount,
16276
15982
  selectHiddenComponentTypeIds,
16277
15983
  selectIsFetchingInitialData,
@@ -16286,10 +15992,10 @@ export {
16286
15992
  selectIssueUpdateMapping,
16287
15993
  selectIssueUpdatesOfIssue,
16288
15994
  selectIssues,
16289
- selectLatestFormRevisionByForm,
16290
- selectLatestFormRevisionOfForm,
16291
- selectLatestFormRevisionsOfComponentTypes,
15995
+ selectLatestFormRevision,
16292
15996
  selectLatestRetryTime,
15997
+ selectLatestRevisionByFormId,
15998
+ selectLatestRevisionsFromComponentTypeIds,
16293
15999
  selectLicense,
16294
16000
  selectLicenseForProject,
16295
16001
  selectLicenses,
@@ -16298,6 +16004,8 @@ export {
16298
16004
  selectMapStyle,
16299
16005
  selectNumberOfComponentTypesMatchingCaseInsensitiveName,
16300
16006
  selectNumberOfComponentsOfComponentType,
16007
+ selectNumberOfGeneralUserForms,
16008
+ selectNumberOfUserForms,
16301
16009
  selectOrganization,
16302
16010
  selectOrganizationAccess,
16303
16011
  selectOrganizationAccessForUser,
@@ -16325,6 +16033,8 @@ export {
16325
16033
  selectRecentIssuesAsSearchResults,
16326
16034
  selectRecentProjects,
16327
16035
  selectRehydrated,
16036
+ selectRevisionAttachments,
16037
+ selectRevisionsForForm,
16328
16038
  selectRootDocuments,
16329
16039
  selectShowTooltips,
16330
16040
  selectSortedEmailDomains,
@@ -16339,10 +16049,16 @@ export {
16339
16049
  selectStagesFromComponentType,
16340
16050
  selectStagesFromComponentTypeIds,
16341
16051
  selectStagesFromStageIds,
16052
+ selectSubmissionAttachments,
16053
+ selectSubmissionsForComponent,
16054
+ selectSubmissionsForForm,
16055
+ selectSubmissionsForIssue,
16342
16056
  selectUploadUrl,
16343
16057
  selectUsedColors,
16344
16058
  selectUser,
16345
- selectUserFormRevisionAttachmentsMapping,
16059
+ selectUserForm,
16060
+ selectUserFormMapping,
16061
+ selectUserFormSubmission,
16346
16062
  selectUsersAsMapping,
16347
16063
  selectVisibleStatuses,
16348
16064
  selectVisibleUserIds,
@@ -16369,13 +16085,6 @@ export {
16369
16085
  setEnableClustering,
16370
16086
  setEnableDuplicateIssues,
16371
16087
  setEnablePlacementMode,
16372
- setFormRevision,
16373
- setFormRevisionAttachments,
16374
- setFormRevisions,
16375
- setFormSubmission,
16376
- setFormSubmissionAttachments,
16377
- setFormSubmissions,
16378
- setForms,
16379
16088
  setIsFetchingInitialData,
16380
16089
  setIsImportingProjectFile,
16381
16090
  setIsLoading,
@@ -16400,6 +16109,9 @@ export {
16400
16109
  setTokens,
16401
16110
  setTourStep,
16402
16111
  setUploadUrl,
16112
+ setUserFormRevisionAttachments,
16113
+ setUserFormSubmissionAttachments,
16114
+ setUserFormSubmissions,
16403
16115
  setUsers,
16404
16116
  setVisibleStatuses,
16405
16117
  setVisibleUserIds,
@@ -16424,13 +16136,11 @@ export {
16424
16136
  updateComponentTypeAttachment,
16425
16137
  updateDocumentAttachment,
16426
16138
  updateDocuments,
16427
- updateFormSubmission,
16428
- updateFormSubmissionAttachments,
16429
- updateFormSubmissions,
16430
16139
  updateIssue,
16431
16140
  updateIssueAttachment,
16432
16141
  updateLicense,
16433
16142
  updateOrCreateProject,
16143
+ updateOrCreateUserFormSubmission,
16434
16144
  updateOrganizationAccess,
16435
16145
  updateProjectAccess,
16436
16146
  updateProjectAttachment,
@@ -16444,6 +16154,8 @@ export {
16444
16154
  useFormikInput,
16445
16155
  useMemoCompare,
16446
16156
  useSDK,
16157
+ userFormReducer,
16158
+ userFormSlice,
16447
16159
  userReducer,
16448
16160
  userSlice,
16449
16161
  valueIsFile,