@overmap-ai/core 1.0.51-add-submitted-at-to-form-revisions.1 → 1.0.51-add-teams.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.
Files changed (41) hide show
  1. package/dist/forms/builder/constants.d.ts +1 -0
  2. package/dist/forms/builder/utils.d.ts +1 -1
  3. package/dist/forms/fields/QrField/QrField.d.ts +21 -0
  4. package/dist/forms/fields/QrField/QrInput.d.ts +10 -0
  5. package/dist/forms/fields/QrField/index.d.ts +2 -0
  6. package/dist/forms/fields/constants.d.ts +8 -0
  7. package/dist/forms/fields/index.d.ts +1 -0
  8. package/dist/forms/renderer/FormSubmissionBrowser/FormSubmissionBrowser.d.ts +5 -5
  9. package/dist/forms/renderer/FormSubmissionViewer/FormSubmissionViewer.d.ts +3 -3
  10. package/dist/forms/typings.d.ts +5 -2
  11. package/dist/overmap-core.js +1119 -457
  12. package/dist/overmap-core.js.map +1 -1
  13. package/dist/overmap-core.umd.cjs +1120 -459
  14. package/dist/overmap-core.umd.cjs.map +1 -1
  15. package/dist/sdk/sdk.d.ts +2 -1
  16. package/dist/sdk/services/TeamService.d.ts +12 -0
  17. package/dist/sdk/services/UserFormSubmissionService.d.ts +9 -2
  18. package/dist/sdk/services/index.d.ts +1 -0
  19. package/dist/store/slices/categorySlice.d.ts +4 -1
  20. package/dist/store/slices/documentSlice.d.ts +4 -1
  21. package/dist/store/slices/formRevisionSlice.d.ts +66 -0
  22. package/dist/store/slices/formSlice.d.ts +110 -0
  23. package/dist/store/slices/formSubmissionSlice.d.ts +47 -0
  24. package/dist/store/slices/index.d.ts +4 -1
  25. package/dist/store/slices/issueSlice.d.ts +4 -1
  26. package/dist/store/slices/projectFileSlice.d.ts +4 -1
  27. package/dist/store/slices/teamSlice.d.ts +19 -0
  28. package/dist/store/slices/utils.d.ts +1 -0
  29. package/dist/store/slices/workspaceSlice.d.ts +4 -1
  30. package/dist/store/store.d.ts +13 -4
  31. package/dist/style.css +5 -0
  32. package/dist/typings/files.d.ts +11 -1
  33. package/dist/typings/models/attachments.d.ts +8 -11
  34. package/dist/typings/models/base.d.ts +10 -0
  35. package/dist/typings/models/forms.d.ts +6 -11
  36. package/dist/typings/models/index.d.ts +1 -0
  37. package/dist/typings/models/teams.d.ts +10 -0
  38. package/dist/utils/file.d.ts +2 -0
  39. package/dist/utils/forms.d.ts +2 -0
  40. package/package.json +2 -1
  41. package/dist/store/slices/userFormSlice.d.ts +0 -145
@@ -8,7 +8,7 @@ var _a;
8
8
  import * as React from "react";
9
9
  import React__default, { useState, useEffect, useRef, memo, useMemo, useCallback, createContext, createElement, useContext, forwardRef, Children, isValidElement, cloneElement, Fragment as Fragment$1, useLayoutEffect, useReducer, lazy, Suspense } from "react";
10
10
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
11
- import { unsafeShowToast, AlertDialogProvider, ToastProvider, DefaultTheme, Flex as Flex$1, IconButton, RiIcon, Text as Text$1, useSeverityColor, Checkbox, TextArea, Select, useToast, Badge, MultiSelect, useViewportSize, Overlay, ButtonGroup, Spinner, IconColorUtility, Tooltip, Popover, useSize, ToggleButton, Separator, OvermapItem, Button, ButtonList, divButtonProps, OvermapDropdownMenu, Input, useAlertDialog } from "@overmap-ai/blocks";
11
+ import { unsafeShowToast, AlertDialogProvider, ToastProvider, DefaultTheme, Flex as Flex$1, IconButton, RiIcon, Text as Text$1, useSeverityColor, Checkbox, TextArea, Select, useToast, Badge, MultiSelect, Overlay, Button, Spinner, useViewportSize, ButtonGroup, IconColorUtility, Tooltip, Popover, useSize, ToggleButton, Separator, OvermapItem, ButtonList, divButtonProps, OvermapDropdownMenu, Input, useAlertDialog } from "@overmap-ai/blocks";
12
12
  import { DepGraph } from "dependency-graph";
13
13
  import { offline as offline$1 } from "@redux-offline/redux-offline";
14
14
  import offlineConfig from "@redux-offline/redux-offline/lib/defaults";
@@ -27,6 +27,7 @@ import { useField, useFormikContext, useFormik, FormikProvider } from "formik";
27
27
  import get from "lodash.get";
28
28
  import Linkify from "linkify-react";
29
29
  import { DragDropContext, Droppable, Draggable } from "@hello-pangea/dnd";
30
+ import QrScannerAPI from "qr-scanner";
30
31
  import { read, utils } from "xlsx";
31
32
  import { pdfjs, Document, Page } from "react-pdf";
32
33
  import "react-pdf/dist/Page/AnnotationLayer.css";
@@ -677,15 +678,15 @@ const wrapMigration = (migrator) => (state) => {
677
678
  };
678
679
  const migrations = [initialVersioning, signOut, signOut, createOutboxState];
679
680
  const manifest = Object.fromEntries(migrations.map((migration2, i) => [i, wrapMigration(migration2)]));
680
- const initialState$n = {
681
+ const initialState$q = {
681
682
  accessToken: "",
682
683
  refreshToken: "",
683
684
  isLoggedIn: false
684
685
  };
685
686
  const authSlice = createSlice({
686
687
  name: "auth",
687
- initialState: initialState$n,
688
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$n)),
688
+ initialState: initialState$q,
689
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$q)),
689
690
  reducers: {
690
691
  setTokens: (state, action) => {
691
692
  state.accessToken = action.payload.accessToken;
@@ -850,6 +851,19 @@ function downloadInMemoryFile(filename, text) {
850
851
  element.click();
851
852
  document.body.removeChild(element);
852
853
  }
854
+ const constructUploadedFilePayloads = async (files) => {
855
+ const filePayloads = {};
856
+ for (const file of files) {
857
+ const sha1 = await hashFile(file);
858
+ filePayloads[sha1] = {
859
+ sha1,
860
+ extension: file.name.split(".").pop() || "",
861
+ file_type: file.type,
862
+ size: file.size
863
+ };
864
+ }
865
+ return Object.values(filePayloads);
866
+ };
853
867
  const fileToBlob = async (dataUrl) => {
854
868
  return (await fetch(dataUrl)).blob();
855
869
  };
@@ -1416,7 +1430,7 @@ const getLocalRelativeDateString = memoize((date, min, max) => {
1416
1430
  return getLocalDateString(date);
1417
1431
  return relative.format(days, "days");
1418
1432
  });
1419
- const initialState$m = {
1433
+ const initialState$p = {
1420
1434
  categories: {},
1421
1435
  usedCategoryColors: [],
1422
1436
  categoryVisibility: {
@@ -1426,8 +1440,8 @@ const initialState$m = {
1426
1440
  };
1427
1441
  const categorySlice = createSlice({
1428
1442
  name: "categories",
1429
- initialState: initialState$m,
1430
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$m)),
1443
+ initialState: initialState$p,
1444
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$p)),
1431
1445
  reducers: {
1432
1446
  setCategories: (state, action) => {
1433
1447
  if (!Array.isArray(action.payload))
@@ -1596,14 +1610,14 @@ function removeAttachments(state, action) {
1596
1610
  delete state.attachments[attachmentId];
1597
1611
  }
1598
1612
  }
1599
- const initialState$l = {
1613
+ const initialState$o = {
1600
1614
  components: {},
1601
1615
  attachments: {}
1602
1616
  };
1603
1617
  const componentSlice = createSlice({
1604
1618
  name: "components",
1605
- initialState: initialState$l,
1606
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$l)),
1619
+ initialState: initialState$o,
1620
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$o)),
1607
1621
  reducers: {
1608
1622
  addComponent: (state, action) => {
1609
1623
  state.components[action.payload.offline_id] = action.payload;
@@ -1759,13 +1773,13 @@ const {
1759
1773
  removeAllComponentsOfType
1760
1774
  } = componentSlice.actions;
1761
1775
  const componentReducer = componentSlice.reducer;
1762
- const initialState$k = {
1776
+ const initialState$n = {
1763
1777
  completionsByComponentId: {}
1764
1778
  };
1765
1779
  const componentStageCompletionSlice = createSlice({
1766
1780
  name: "componentStageCompletions",
1767
- initialState: initialState$k,
1768
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$k)),
1781
+ initialState: initialState$n,
1782
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$n)),
1769
1783
  reducers: {
1770
1784
  addStageCompletion: (state, action) => {
1771
1785
  let stageToCompletionDateMapping = state.completionsByComponentId[action.payload.component];
@@ -1816,13 +1830,13 @@ const selectCompletedStageIdsForComponent = (component) => (state) => {
1816
1830
  return Object.keys(state.componentStageCompletionReducer.completionsByComponentId[component.offline_id] ?? {});
1817
1831
  };
1818
1832
  const componentStageCompletionReducer = componentStageCompletionSlice.reducer;
1819
- const initialState$j = {
1833
+ const initialState$m = {
1820
1834
  stages: {}
1821
1835
  };
1822
1836
  const componentStageSlice = createSlice({
1823
1837
  name: "componentStages",
1824
- initialState: initialState$j,
1825
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$j)),
1838
+ initialState: initialState$m,
1839
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$m)),
1826
1840
  reducers: {
1827
1841
  addStages: (state, action) => {
1828
1842
  Object.assign(state.stages, toOfflineIdRecord(action.payload));
@@ -1932,15 +1946,15 @@ const selectStageFormIdsFromStageIds = restructureCreateSelectorWithArgs(
1932
1946
  );
1933
1947
  const { addStages, updateStages, removeStages, linkStageToForm, unlinkStageToForm } = componentStageSlice.actions;
1934
1948
  const componentStageReducer = componentStageSlice.reducer;
1935
- const initialState$i = {
1949
+ const initialState$l = {
1936
1950
  componentTypes: {},
1937
1951
  hiddenComponentTypeIds: {},
1938
1952
  attachments: {}
1939
1953
  };
1940
1954
  const componentTypeSlice = createSlice({
1941
1955
  name: "componentTypes",
1942
- initialState: initialState$i,
1943
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$i)),
1956
+ initialState: initialState$l,
1957
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$l)),
1944
1958
  reducers: {
1945
1959
  addComponentType: (state, action) => {
1946
1960
  state.componentTypes[action.payload.offline_id] = action.payload;
@@ -2051,13 +2065,13 @@ const {
2051
2065
  deleteComponentType
2052
2066
  } = componentTypeSlice.actions;
2053
2067
  const componentTypeReducer = componentTypeSlice.reducer;
2054
- const initialState$h = {
2068
+ const initialState$k = {
2055
2069
  workspaces: {},
2056
2070
  activeWorkspaceId: null
2057
2071
  };
2058
2072
  const workspaceSlice = createSlice({
2059
2073
  name: "workspace",
2060
- initialState: initialState$h,
2074
+ initialState: initialState$k,
2061
2075
  // The `reducers` field lets us define reducers and generate associated actions
2062
2076
  reducers: {
2063
2077
  setWorkspaces: (state, action) => {
@@ -2114,7 +2128,7 @@ const selectPermittedWorkspaceIds = createSelector(
2114
2128
  );
2115
2129
  const workspaceReducer = workspaceSlice.reducer;
2116
2130
  const maxRecentIssues = 10;
2117
- const initialState$g = {
2131
+ const initialState$j = {
2118
2132
  issues: {},
2119
2133
  attachments: {},
2120
2134
  comments: {},
@@ -2126,9 +2140,9 @@ const initialState$g = {
2126
2140
  };
2127
2141
  const issueSlice = createSlice({
2128
2142
  name: "issues",
2129
- initialState: initialState$g,
2143
+ initialState: initialState$j,
2130
2144
  extraReducers: (builder) => builder.addCase("RESET", (state) => {
2131
- Object.assign(state, initialState$g);
2145
+ Object.assign(state, initialState$j);
2132
2146
  }),
2133
2147
  reducers: {
2134
2148
  setIssues: (state, action) => {
@@ -2536,15 +2550,15 @@ const selectRecentIssuesAsSearchResults = createSelector(
2536
2550
  }
2537
2551
  );
2538
2552
  const issueReducer = issueSlice.reducer;
2539
- const initialState$f = {
2553
+ const initialState$i = {
2540
2554
  s3Urls: {}
2541
2555
  };
2542
2556
  const msPerHour = 1e3 * 60 * 60;
2543
2557
  const msPerWeek = msPerHour * 24 * 7;
2544
2558
  const fileSlice = createSlice({
2545
2559
  name: "file",
2546
- initialState: initialState$f,
2547
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$f)),
2560
+ initialState: initialState$i,
2561
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$i)),
2548
2562
  reducers: {
2549
2563
  setUploadUrl: (state, action) => {
2550
2564
  const { url, fields, sha1 } = action.payload;
@@ -2571,7 +2585,7 @@ const selectUploadUrl = (sha1) => (state) => {
2571
2585
  return url;
2572
2586
  };
2573
2587
  const fileReducer = fileSlice.reducer;
2574
- const initialState$e = {
2588
+ const initialState$h = {
2575
2589
  // TODO: Change first MapStyle.SATELLITE to MaptStyle.None when project creation map is fixed
2576
2590
  mapStyle: MapStyle.SATELLITE,
2577
2591
  showTooltips: false,
@@ -2579,8 +2593,8 @@ const initialState$e = {
2579
2593
  };
2580
2594
  const mapSlice = createSlice({
2581
2595
  name: "map",
2582
- initialState: initialState$e,
2583
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$e)),
2596
+ initialState: initialState$h,
2597
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$h)),
2584
2598
  reducers: {
2585
2599
  setMapStyle: (state, action) => {
2586
2600
  state.mapStyle = action.payload;
@@ -2649,7 +2663,7 @@ var LicenseStatus = /* @__PURE__ */ ((LicenseStatus2) => {
2649
2663
  LicenseStatus2[LicenseStatus2["PAST_DUE"] = 8] = "PAST_DUE";
2650
2664
  return LicenseStatus2;
2651
2665
  })(LicenseStatus || {});
2652
- const initialState$d = {
2666
+ const initialState$g = {
2653
2667
  users: {},
2654
2668
  currentUser: {
2655
2669
  id: 0,
@@ -2660,8 +2674,8 @@ const initialState$d = {
2660
2674
  };
2661
2675
  const userSlice = createSlice({
2662
2676
  name: "users",
2663
- initialState: initialState$d,
2664
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$d)),
2677
+ initialState: initialState$g,
2678
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$g)),
2665
2679
  reducers: {
2666
2680
  setUsers: (state, action) => {
2667
2681
  const usersMapping = {};
@@ -2723,13 +2737,13 @@ const selectUser = (userId) => (state) => {
2723
2737
  const selectUsersAsMapping = (state) => state.userReducer.users;
2724
2738
  const selectFavouriteProjects = (state) => state.userReducer.currentUser.profile.favourite_project_ids;
2725
2739
  const userReducer = userSlice.reducer;
2726
- const initialState$c = {
2740
+ const initialState$f = {
2727
2741
  organizationAccesses: {}
2728
2742
  };
2729
2743
  const organizationAccessSlice = createSlice({
2730
2744
  name: "organizationAccess",
2731
- initialState: initialState$c,
2732
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$c)),
2745
+ initialState: initialState$f,
2746
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$f)),
2733
2747
  reducers: {
2734
2748
  setOrganizationAccesses: (state, action) => {
2735
2749
  if (!Array.isArray(action.payload))
@@ -2792,13 +2806,13 @@ const selectOrganizationAccessUserMapping = (state) => {
2792
2806
  return organizationAccesses;
2793
2807
  };
2794
2808
  const organizationAccessReducer = organizationAccessSlice.reducer;
2795
- const initialState$b = {
2809
+ const initialState$e = {
2796
2810
  licenses: {}
2797
2811
  };
2798
2812
  const licenseSlice = createSlice({
2799
2813
  name: "license",
2800
- initialState: initialState$b,
2801
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$b)),
2814
+ initialState: initialState$e,
2815
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$e)),
2802
2816
  reducers: {
2803
2817
  setLicenses: (state, action) => {
2804
2818
  if (!Array.isArray(action.payload))
@@ -2843,13 +2857,13 @@ const selectLicensesForProjectsMapping = createSelector(
2843
2857
  (licenses) => Object.values(licenses).filter((license) => license.project).reduce((accum, license) => ({ ...accum, [license.project]: license }), {})
2844
2858
  );
2845
2859
  const licenseReducer = licenseSlice.reducer;
2846
- const initialState$a = {
2860
+ const initialState$d = {
2847
2861
  projectAccesses: {}
2848
2862
  };
2849
2863
  const projectAccessSlice = createSlice({
2850
2864
  name: "projectAccess",
2851
- initialState: initialState$a,
2852
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$a)),
2865
+ initialState: initialState$d,
2866
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$d)),
2853
2867
  reducers: {
2854
2868
  setProjectAccesses: (state, action) => {
2855
2869
  if (!Array.isArray(action.payload))
@@ -2917,7 +2931,7 @@ const selectProjectAccessUserMapping = (state) => {
2917
2931
  return projectAccesses;
2918
2932
  };
2919
2933
  const projectAccessReducer = projectAccessSlice.reducer;
2920
- const initialState$9 = {
2934
+ const initialState$c = {
2921
2935
  projects: {},
2922
2936
  activeProjectId: null,
2923
2937
  recentProjectIds: [],
@@ -2927,7 +2941,7 @@ const initialState$9 = {
2927
2941
  };
2928
2942
  const projectSlice = createSlice({
2929
2943
  name: "projects",
2930
- initialState: initialState$9,
2944
+ initialState: initialState$c,
2931
2945
  reducers: {
2932
2946
  setProjects: (state, action) => {
2933
2947
  const projectsMap = {};
@@ -3114,14 +3128,14 @@ const selectAttachmentsOfProjectByType = restructureCreateSelectorWithArgs(
3114
3128
  }
3115
3129
  )
3116
3130
  );
3117
- const initialState$8 = {
3131
+ const initialState$b = {
3118
3132
  organizations: {},
3119
3133
  activeOrganizationId: null
3120
3134
  };
3121
3135
  const organizationSlice = createSlice({
3122
3136
  name: "organizations",
3123
- initialState: initialState$8,
3124
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$8)),
3137
+ initialState: initialState$b,
3138
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$b)),
3125
3139
  reducers: {
3126
3140
  setOrganizations: (state, action) => {
3127
3141
  for (const org of action.payload) {
@@ -3240,14 +3254,14 @@ const createOfflineAction = (request2, baseUrl) => {
3240
3254
  }
3241
3255
  };
3242
3256
  };
3243
- const initialState$7 = {
3257
+ const initialState$a = {
3244
3258
  deletedRequests: [],
3245
3259
  latestRetryTime: 0
3246
3260
  };
3247
3261
  const outboxSlice = createSlice({
3248
3262
  name: "outbox",
3249
- initialState: initialState$7,
3250
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$7)),
3263
+ initialState: initialState$a,
3264
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$a)),
3251
3265
  reducers: {
3252
3266
  // enqueueActions is a reducer that does nothing but enqueue API request to the Redux Offline outbox
3253
3267
  // Whenever an issue is being created, a reducer addIssue() is responsible for adding it to the offline store
@@ -3279,7 +3293,7 @@ const selectDeletedRequests = (state) => state.outboxReducer.deletedRequests;
3279
3293
  const selectLatestRetryTime = (state) => state.outboxReducer.latestRetryTime;
3280
3294
  const { enqueueRequest, markForDeletion, markAsDeleted, _setLatestRetryTime } = outboxSlice.actions;
3281
3295
  const outboxReducer = outboxSlice.reducer;
3282
- const initialState$6 = {
3296
+ const initialState$9 = {
3283
3297
  projectFiles: {},
3284
3298
  activeProjectFileId: null,
3285
3299
  isImportingProjectFile: false,
@@ -3287,8 +3301,8 @@ const initialState$6 = {
3287
3301
  };
3288
3302
  const projectFileSlice = createSlice({
3289
3303
  name: "projectFiles",
3290
- initialState: initialState$6,
3291
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$6)),
3304
+ initialState: initialState$9,
3305
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$9)),
3292
3306
  reducers: {
3293
3307
  addOrReplaceProjectFiles: (state, action) => {
3294
3308
  for (let fileObj of action.payload) {
@@ -3389,12 +3403,12 @@ const selectProjectFiles = createSelector(
3389
3403
  const selectActiveProjectFileId = (state) => state.projectFileReducer.activeProjectFileId;
3390
3404
  const selectIsImportingProjectFile = (state) => state.projectFileReducer.isImportingProjectFile;
3391
3405
  const projectFileReducer = projectFileSlice.reducer;
3392
- const initialState$5 = {
3406
+ const initialState$8 = {
3393
3407
  isRehydrated: false
3394
3408
  };
3395
3409
  const rehydratedSlice = createSlice({
3396
3410
  name: "rehydrated",
3397
- initialState: initialState$5,
3411
+ initialState: initialState$8,
3398
3412
  // The `reducers` field lets us define reducers and generate associated actions
3399
3413
  reducers: {
3400
3414
  setRehydrated: (state, action) => {
@@ -3404,7 +3418,7 @@ const rehydratedSlice = createSlice({
3404
3418
  });
3405
3419
  const selectRehydrated = (state) => state.rehydratedReducer.isRehydrated;
3406
3420
  const rehydratedReducer = rehydratedSlice.reducer;
3407
- const initialState$4 = {
3421
+ const initialState$7 = {
3408
3422
  useIssueTemplate: false,
3409
3423
  placementMode: false,
3410
3424
  enableClustering: false,
@@ -3421,8 +3435,8 @@ const initialState$4 = {
3421
3435
  };
3422
3436
  const settingSlice = createSlice({
3423
3437
  name: "settings",
3424
- initialState: initialState$4,
3425
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$4)),
3438
+ initialState: initialState$7,
3439
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$7)),
3426
3440
  reducers: {
3427
3441
  setEnableDuplicateIssues: (state, action) => {
3428
3442
  state.useIssueTemplate = action.payload;
@@ -3468,146 +3482,231 @@ const selectAppearance = (state) => state.settingReducer.appearance;
3468
3482
  const settingReducer = settingSlice.reducer;
3469
3483
  const selectIsFetchingInitialData = (state) => state.settingReducer.isFetchingInitialData;
3470
3484
  const selectIsLoading = (state) => state.settingReducer.isLoading;
3471
- const LATEST_REVISION_CACHE = {};
3472
- function considerCachingRevision(revision, formId2, preferPending = false) {
3473
- var _a2;
3474
- if (!revision) {
3475
- if (!formId2) {
3476
- throw new Error("If revision is null, formId is required.");
3477
- }
3478
- const currentLatestRevision = getLatestRevisionFromCache(formId2);
3479
- if (currentLatestRevision)
3480
- return;
3481
- LATEST_REVISION_CACHE[formId2] = null;
3482
- return;
3483
- }
3484
- if (revision.revision === "Pending") {
3485
- if (preferPending) {
3486
- LATEST_REVISION_CACHE[revision.form] = revision;
3487
- }
3488
- return;
3489
- }
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;
3485
+ const formRevisionSortFn = (formRevisionA, formRevisionB) => {
3486
+ const revisionA = formRevisionA.revision;
3487
+ const revisionB = formRevisionB.revision;
3488
+ if (revisionA === "Pending" && revisionB === "Pending") {
3489
+ return formRevisionA.submitted_at < formRevisionB.submitted_at ? -1 : 1;
3490
+ } else if (revisionA === "Pending") {
3491
+ return 1;
3492
+ } else if (revisionB === "Pending") {
3493
+ return -1;
3494
+ } else {
3495
+ return revisionA < revisionB ? -1 : 1;
3493
3496
  }
3494
- }
3495
- function getLatestRevisionFromCache(formId2) {
3496
- return LATEST_REVISION_CACHE[formId2];
3497
- }
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)),
3497
+ };
3498
+ const initialState$6 = {
3499
+ formRevisions: {},
3500
+ attachments: {}
3501
+ };
3502
+ const formRevisionsSlice = createSlice({
3503
+ name: "formRevisions",
3504
+ initialState: initialState$6,
3505
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$6)),
3509
3506
  reducers: {
3510
- setUserForms: (state, action) => {
3511
- state.userForms = {};
3512
- action.payload.forEach((userForm) => {
3513
- state.userForms[userForm.offline_id] = userForm;
3514
- });
3515
- },
3516
- addUserForm: (state, action) => {
3517
- state.userForms[action.payload.offline_id] = action.payload;
3507
+ // revision related actions
3508
+ setFormRevision: (state, action) => {
3509
+ state.formRevisions[action.payload.offline_id] = action.payload;
3518
3510
  },
3519
- addUserForms: (state, action) => {
3520
- action.payload.forEach((userForm) => {
3521
- state.userForms[userForm.offline_id] = userForm;
3522
- });
3523
- },
3524
- addUserFormRevisions: (state, action) => {
3525
- action.payload.forEach((userFormRevision) => {
3526
- state.revisions[userFormRevision.offline_id] = userFormRevision;
3527
- considerCachingRevision(userFormRevision);
3528
- });
3529
- },
3530
- addUserFormRevision: (state, action) => {
3531
- state.revisions[action.payload.offline_id] = action.payload;
3532
- considerCachingRevision(action.payload);
3511
+ setFormRevisions: (state, action) => {
3512
+ state.formRevisions = {};
3513
+ for (const revision of action.payload) {
3514
+ state.formRevisions[revision.offline_id] = revision;
3515
+ }
3533
3516
  },
3534
- deleteUserFormRevision: (state, action) => {
3535
- delete state.revisions[action.payload];
3536
- delete LATEST_REVISION_CACHE[action.payload];
3517
+ addFormRevision: (state, action) => {
3518
+ if (state.formRevisions[action.payload.offline_id] !== void 0) {
3519
+ throw new Error(`Revision with offline_id ${action.payload.offline_id} already exists`);
3520
+ }
3521
+ state.formRevisions[action.payload.offline_id] = action.payload;
3537
3522
  },
3538
- deleteUserFormRevisions: (state, action) => {
3523
+ addFormRevisions: (state, action) => {
3539
3524
  for (const userFormRevision of action.payload) {
3540
- delete state.revisions[userFormRevision.offline_id];
3541
- delete LATEST_REVISION_CACHE[userFormRevision.offline_id];
3525
+ if (state.formRevisions[userFormRevision.offline_id] !== void 0) {
3526
+ throw new Error(`Revision with offline_id ${userFormRevision.offline_id} already exists`);
3527
+ }
3542
3528
  }
3543
- },
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];
3529
+ for (const userFormRevision of action.payload) {
3530
+ state.formRevisions[userFormRevision.offline_id] = userFormRevision;
3554
3531
  }
3555
3532
  },
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];
3533
+ // UserFormRevisions do not get updated
3534
+ deleteFormRevision: (state, action) => {
3535
+ if (state.formRevisions[action.payload] === void 0) {
3536
+ throw new Error(`Revision with offline_id ${action.payload} does not exist`);
3563
3537
  }
3538
+ delete state.formRevisions[action.payload];
3564
3539
  },
3565
- setUserFormSubmissionAttachments: (state, action) => {
3566
- state.submissionAttachments = {};
3567
- for (const attachment of action.payload) {
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];
3540
+ deleteFormRevisions: (state, action) => {
3541
+ for (const offlineId of action.payload) {
3542
+ if (state.formRevisions[offlineId] === void 0) {
3543
+ throw new Error(`Revision with offline_id ${offlineId} does not exist`);
3574
3544
  }
3575
3545
  }
3546
+ for (const offlineId of action.payload) {
3547
+ delete state.formRevisions[offlineId];
3548
+ }
3576
3549
  },
3577
- setUserFormRevisionAttachments: (state, action) => {
3578
- state.revisionAttachments = {};
3550
+ // attachment related actions
3551
+ setFormRevisionAttachments: (state, action) => {
3552
+ state.attachments = {};
3579
3553
  for (const attachment of action.payload) {
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
- }
3554
+ state.attachments[attachment.offline_id] = attachment;
3587
3555
  }
3588
3556
  },
3589
- deleteUserFormSubmission: (state, action) => {
3590
- delete state.submissions[action.payload];
3557
+ addFormRevisionAttachment: (state, action) => {
3558
+ if (state.attachments[action.payload.offline_id] !== void 0) {
3559
+ throw new Error(`Attachment with offline_id ${action.payload.offline_id} already exists`);
3560
+ }
3561
+ state.attachments[action.payload.offline_id] = action.payload;
3591
3562
  },
3592
- deleteUserFormSubmissions: (state, action) => {
3593
- for (const userFormSubmission of action.payload) {
3594
- delete state.submissions[userFormSubmission.offline_id];
3563
+ addFormRevisionAttachments: (state, action) => {
3564
+ for (const attachment of action.payload) {
3565
+ if (state.attachments[attachment.offline_id] !== void 0) {
3566
+ throw new Error(`Attachment with offline_id ${attachment.offline_id} already exists`);
3567
+ }
3568
+ }
3569
+ for (const attachment of action.payload) {
3570
+ state.attachments[attachment.offline_id] = attachment;
3595
3571
  }
3596
3572
  },
3597
- addUserFormSubmissions: (state, action) => {
3598
- for (const submission of action.payload) {
3599
- state.submissions[submission.offline_id] = submission;
3573
+ deleteFormRevisionAttachment: (state, action) => {
3574
+ if (state.attachments[action.payload] === void 0) {
3575
+ throw new Error(`Attachment with offline_id ${action.payload} does not exist`);
3600
3576
  }
3577
+ delete state.attachments[action.payload];
3601
3578
  },
3602
- setUserFormSubmissions: (state, action) => {
3603
- state.submissions = {};
3604
- action.payload.forEach((submission) => {
3605
- state.submissions[submission.offline_id] = submission;
3579
+ deleteFormRevisionAttachments: (state, action) => {
3580
+ for (const offlineId of action.payload) {
3581
+ if (state.attachments[offlineId] === void 0) {
3582
+ throw new Error(`Attachment with offline_id ${offlineId} does not exist`);
3583
+ }
3584
+ }
3585
+ for (const offlineId of action.payload) {
3586
+ delete state.attachments[offlineId];
3587
+ }
3588
+ }
3589
+ }
3590
+ });
3591
+ const {
3592
+ setFormRevision,
3593
+ setFormRevisions,
3594
+ addFormRevision,
3595
+ addFormRevisions,
3596
+ deleteFormRevision,
3597
+ deleteFormRevisions,
3598
+ setFormRevisionAttachments,
3599
+ addFormRevisionAttachment,
3600
+ addFormRevisionAttachments,
3601
+ deleteFormRevisionAttachment,
3602
+ deleteFormRevisionAttachments
3603
+ } = formRevisionsSlice.actions;
3604
+ const selectFormRevisionMapping = (state) => state.formRevisionReducer.formRevisions;
3605
+ const selectFormRevisions = createSelector(
3606
+ [selectFormRevisionMapping],
3607
+ (formRevisions) => Object.values(formRevisions)
3608
+ );
3609
+ const selectFormRevision = (formRevisionId) => (state) => {
3610
+ return state.formRevisionReducer.formRevisions[formRevisionId];
3611
+ };
3612
+ const _selectLatestFormRevision = (formRevisions, formId2) => {
3613
+ let ret = null;
3614
+ for (const candidate of Object.values(formRevisions)) {
3615
+ if (candidate.form === formId2 && (!ret || ret.revision < candidate.revision)) {
3616
+ ret = candidate;
3617
+ }
3618
+ }
3619
+ if (!ret) {
3620
+ throw new Error("No form revision found for form " + formId2);
3621
+ }
3622
+ return ret;
3623
+ };
3624
+ const selectLatestFormRevisionOfForm = restructureCreateSelectorWithArgs(
3625
+ createSelector([selectFormRevisions, (_state, formId2) => formId2], (revisions, formId2) => {
3626
+ return revisions.filter((revision) => revision.form === formId2).sort(formRevisionSortFn).pop();
3627
+ })
3628
+ );
3629
+ const selectFormRevisionsOfForm = restructureCreateSelectorWithArgs(
3630
+ createSelector([selectFormRevisions, (_state, formId2) => formId2], (revisions, formId2) => {
3631
+ return revisions.filter((revision) => {
3632
+ return revision.form === formId2;
3633
+ });
3634
+ })
3635
+ );
3636
+ const selectLatestFormRevisionsOfComponentTypes = restructureCreateSelectorWithArgs(
3637
+ createSelector(
3638
+ [
3639
+ (state) => state.formReducer.forms,
3640
+ selectFormRevisionMapping,
3641
+ (_state, componentTypeIds) => componentTypeIds
3642
+ ],
3643
+ (userForms, revisions, componentTypeIds) => {
3644
+ const componentTypeIdsSet = new Set(componentTypeIds);
3645
+ const formsOfComponentTypes = {};
3646
+ const ret = {};
3647
+ for (const form of Object.values(userForms)) {
3648
+ if (form.component_type && componentTypeIdsSet.has(form.component_type)) {
3649
+ formsOfComponentTypes[form.offline_id] = form;
3650
+ }
3651
+ }
3652
+ for (const revision of Object.values(revisions)) {
3653
+ const form = formsOfComponentTypes[revision.form];
3654
+ if (!form || !form.component_type || ret[form.component_type] && formRevisionSortFn(ret[form.component_type], revision) > 0)
3655
+ continue;
3656
+ ret[form.component_type] = revision;
3657
+ }
3658
+ return ret;
3659
+ }
3660
+ )
3661
+ );
3662
+ const selectLatestFormRevisionByForm = createSelector([selectFormRevisionMapping], (revisions) => {
3663
+ const latestRevisions = {};
3664
+ for (const revision of Object.values(revisions)) {
3665
+ const formId2 = revision.form;
3666
+ const currentLatestRevision = latestRevisions[formId2];
3667
+ if (!currentLatestRevision || currentLatestRevision.revision < revision.revision) {
3668
+ latestRevisions[formId2] = revision;
3669
+ }
3670
+ }
3671
+ return latestRevisions;
3672
+ });
3673
+ const selectUserFormRevisionAttachmentsMapping = (state) => {
3674
+ return state.formRevisionReducer.attachments;
3675
+ };
3676
+ const selectAttachmentsOfFormRevision = restructureCreateSelectorWithArgs(
3677
+ createSelector(
3678
+ [selectUserFormRevisionAttachmentsMapping, (_state, revisionId) => revisionId],
3679
+ (attachments, revisionId) => {
3680
+ return Object.values(attachments).filter((attachment) => attachment.revision === revisionId);
3681
+ }
3682
+ )
3683
+ );
3684
+ const formRevisionReducer = formRevisionsSlice.reducer;
3685
+ const initialState$5 = {
3686
+ forms: {}
3687
+ };
3688
+ const formSlice = createSlice({
3689
+ name: "forms",
3690
+ initialState: initialState$5,
3691
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$5)),
3692
+ reducers: {
3693
+ setForms: (state, action) => {
3694
+ state.forms = {};
3695
+ action.payload.forEach((userForm) => {
3696
+ state.forms[userForm.offline_id] = userForm;
3606
3697
  });
3607
3698
  },
3699
+ addForm: (state, action) => {
3700
+ state.forms[action.payload.offline_id] = action.payload;
3701
+ },
3702
+ addForms: (state, action) => {
3703
+ for (const userForm of action.payload) {
3704
+ state.forms[userForm.offline_id] = userForm;
3705
+ }
3706
+ },
3608
3707
  favoriteForm: (state, action) => {
3609
3708
  const { formId: formId2 } = action.payload;
3610
- const form = state.userForms[formId2];
3709
+ const form = state.forms[formId2];
3611
3710
  if (!form) {
3612
3711
  throw new Error("No form exists with the id " + formId2);
3613
3712
  }
@@ -3615,48 +3714,23 @@ const userFormSlice = createSlice({
3615
3714
  },
3616
3715
  unfavoriteForm: (state, action) => {
3617
3716
  const { formId: formId2 } = action.payload;
3618
- const form = state.userForms[formId2];
3717
+ const form = state.forms[formId2];
3619
3718
  if (!form) {
3620
3719
  throw new Error("No form exists with the id " + formId2);
3621
3720
  }
3622
3721
  form.favorite = false;
3623
3722
  },
3624
- deleteUserForm: (state, action) => {
3625
- delete state.userForms[action.payload];
3723
+ deleteForm: (state, action) => {
3724
+ delete state.forms[action.payload];
3626
3725
  }
3627
3726
  }
3628
3727
  });
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(
3728
+ const { setForms, addForm, addForms, favoriteForm, unfavoriteForm, deleteForm } = formSlice.actions;
3729
+ const selectFilteredForms = restructureCreateSelectorWithArgs(
3656
3730
  createSelector(
3657
3731
  [
3658
- (state) => state.userFormReducer.userForms,
3659
- (state) => state.userFormReducer.revisions,
3732
+ (state) => state.formReducer.forms,
3733
+ (state) => state.formRevisionReducer.formRevisions,
3660
3734
  (_state, search) => search
3661
3735
  ],
3662
3736
  (userForms, revisions, search) => {
@@ -3690,63 +3764,188 @@ const selectFilteredUserForms = restructureCreateSelectorWithArgs(
3690
3764
  { memoizeOptions: { equalityCheck: shallowEqual$1 } }
3691
3765
  )
3692
3766
  );
3693
- const selectFormRevision = (revisionId) => (state) => {
3694
- return state.userFormReducer.revisions[revisionId];
3767
+ const selectForm = (formId2) => (state) => {
3768
+ return state.formReducer.forms[formId2];
3695
3769
  };
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;
3770
+ const selectFormMapping = (state) => {
3771
+ return state.formReducer.forms;
3707
3772
  };
3708
- const selectLatestFormRevision = restructureCreateSelectorWithArgs(
3773
+ const selectFormOfComponentType = restructureCreateSelectorWithArgs(
3709
3774
  createSelector(
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);
3775
+ [selectFormMapping, (_state, componentTypeId) => componentTypeId],
3776
+ (userForms, componentTypeId) => {
3777
+ return Object.values(userForms).find((userForm) => userForm.component_type === componentTypeId);
3716
3778
  }
3717
3779
  )
3718
3780
  );
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
- })
3781
+ const selectFormsCount = createSelector([selectFormMapping], (userForms) => {
3782
+ return Object.keys(userForms).length;
3783
+ });
3784
+ const selectGeneralFormCount = createSelector([selectFormMapping], (userForms) => {
3785
+ return Object.values(userForms).filter((form) => !form.component_type).length;
3786
+ });
3787
+ const formReducer = formSlice.reducer;
3788
+ const initialState$4 = {
3789
+ formSubmissions: {},
3790
+ attachments: {}
3791
+ };
3792
+ const formSubmissionSlice = createSlice({
3793
+ name: "formSubmissions",
3794
+ initialState: initialState$4,
3795
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$4)),
3796
+ reducers: {
3797
+ setFormSubmission: (state, action) => {
3798
+ state.formSubmissions[action.payload.offline_id] = action.payload;
3799
+ },
3800
+ setFormSubmissions: (state, action) => {
3801
+ state.formSubmissions = {};
3802
+ for (const submission of action.payload) {
3803
+ state.formSubmissions[submission.offline_id] = submission;
3804
+ }
3805
+ },
3806
+ addFormSubmission: (state, action) => {
3807
+ if (action.payload.offline_id in state.formSubmissions) {
3808
+ throw new Error(`Submission with offline_id ${action.payload.offline_id} already exists`);
3809
+ }
3810
+ state.formSubmissions[action.payload.offline_id] = action.payload;
3811
+ },
3812
+ addFormSubmissions: (state, action) => {
3813
+ for (const submission of action.payload) {
3814
+ if (state.formSubmissions[submission.offline_id] !== void 0) {
3815
+ throw new Error(`Submission with offline_id ${submission.offline_id} already exists`);
3816
+ }
3817
+ }
3818
+ for (const submission of action.payload) {
3819
+ state.formSubmissions[submission.offline_id] = submission;
3820
+ }
3821
+ },
3822
+ updateFormSubmission: (state, action) => {
3823
+ if (state.formSubmissions[action.payload.offline_id] === void 0) {
3824
+ throw new Error(`Submission with offline_id ${action.payload.offline_id} does not exist`);
3825
+ }
3826
+ state.formSubmissions[action.payload.offline_id] = action.payload;
3827
+ },
3828
+ updateFormSubmissions: (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} does not exist`);
3832
+ }
3833
+ }
3834
+ for (const submission of action.payload) {
3835
+ state.formSubmissions[submission.offline_id] = submission;
3836
+ }
3837
+ },
3838
+ deleteFormSubmission: (state, action) => {
3839
+ if (state.formSubmissions[action.payload] === void 0) {
3840
+ throw new Error(`Submission with offline_id ${action.payload} does not exist`);
3841
+ }
3842
+ delete state.formSubmissions[action.payload];
3843
+ },
3844
+ deleteFormSubmissions: (state, action) => {
3845
+ for (const offlineId of action.payload) {
3846
+ if (state.formSubmissions[offlineId] === void 0) {
3847
+ throw new Error(`Submission with offline_id ${offlineId} does not exist`);
3848
+ }
3849
+ delete state.formSubmissions[offlineId];
3850
+ }
3851
+ for (const offlineId of action.payload) {
3852
+ delete state.formSubmissions[offlineId];
3853
+ }
3854
+ },
3855
+ // Attachments
3856
+ addFormSubmissionAttachment: (state, action) => {
3857
+ if (state.attachments[action.payload.offline_id] !== void 0) {
3858
+ throw new Error(`Attachment with offline_id ${action.payload.offline_id} already exists`);
3859
+ }
3860
+ state.attachments[action.payload.offline_id] = action.payload;
3861
+ },
3862
+ addFormSubmissionAttachments: (state, action) => {
3863
+ for (const attachment of action.payload) {
3864
+ if (state.attachments[attachment.offline_id] !== void 0) {
3865
+ throw new Error(`Attachment with offline_id ${attachment.offline_id} already exists`);
3866
+ }
3867
+ }
3868
+ for (const attachment of action.payload) {
3869
+ state.attachments[attachment.offline_id] = attachment;
3870
+ }
3871
+ },
3872
+ // We only need a multi set for attachments because they are not updated, only added and deleted
3873
+ setFormSubmissionAttachments: (state, action) => {
3874
+ state.attachments = {};
3875
+ for (const attachment of action.payload) {
3876
+ state.attachments[attachment.offline_id] = attachment;
3877
+ }
3878
+ },
3879
+ updateFormSubmissionAttachments: (state, action) => {
3880
+ for (const attachment of action.payload) {
3881
+ if (state.attachments[attachment.offline_id] === void 0) {
3882
+ throw new Error(`Attachment with offline_id ${attachment.offline_id} does not exist`);
3883
+ }
3884
+ }
3885
+ for (const attachment of action.payload) {
3886
+ state.attachments[attachment.offline_id] = attachment;
3887
+ }
3888
+ },
3889
+ // The delete actions for UserFormSubmissionAttachments are not used in the app, but are included for completeness
3890
+ // Could be used if editing a submission is ever supported, will be applicable for supporting tip tap content in submissions
3891
+ deleteFormSubmissionAttachment: (state, action) => {
3892
+ if (state.attachments[action.payload] === void 0) {
3893
+ throw new Error(`Attachment with offline_id ${action.payload} does not exist`);
3894
+ }
3895
+ delete state.attachments[action.payload];
3896
+ },
3897
+ deleteFormSubmissionAttachments: (state, action) => {
3898
+ for (const offlineId of action.payload) {
3899
+ if (state.attachments[offlineId] === void 0) {
3900
+ throw new Error(`Attachment with offline_id ${offlineId} does not exist`);
3901
+ }
3902
+ delete state.attachments[offlineId];
3903
+ }
3904
+ }
3905
+ }
3906
+ });
3907
+ const {
3908
+ setFormSubmission,
3909
+ setFormSubmissions,
3910
+ addFormSubmission,
3911
+ addFormSubmissions,
3912
+ updateFormSubmission,
3913
+ updateFormSubmissions,
3914
+ deleteFormSubmission,
3915
+ deleteFormSubmissions,
3916
+ addFormSubmissionAttachment,
3917
+ addFormSubmissionAttachments,
3918
+ setFormSubmissionAttachments,
3919
+ updateFormSubmissionAttachments,
3920
+ deleteFormSubmissionAttachment,
3921
+ deleteFormSubmissionAttachments
3922
+ } = formSubmissionSlice.actions;
3923
+ const selectFormSubmissionsMapping = (state) => {
3924
+ return state.formSubmissionReducer.formSubmissions;
3925
+ };
3926
+ const selectFormSubmissions = createSelector(
3927
+ [selectFormSubmissionsMapping],
3928
+ (submissions) => {
3929
+ return Object.values(submissions);
3930
+ }
3735
3931
  );
3736
- const selectSubmissionsForForm = restructureCreateSelectorWithArgs(
3932
+ const selectFormSubmission = (submissionId) => (state) => {
3933
+ return state.formSubmissionReducer.formSubmissions[submissionId];
3934
+ };
3935
+ const selectFormSubmissionsOfForm = restructureCreateSelectorWithArgs(
3737
3936
  createSelector(
3738
- [selectSubmissions, selectRevisionMapping, (_state, formId2) => formId2],
3937
+ [selectFormSubmissions, selectFormRevisionMapping, (_state, formId2) => formId2],
3739
3938
  (submissions, revisionMapping, formId2) => {
3740
- return Object.values(submissions).filter((submission) => {
3939
+ return submissions.filter((submission) => {
3741
3940
  const revision = revisionMapping[submission.form_revision];
3742
3941
  return (revision == null ? void 0 : revision.form) === formId2;
3743
3942
  });
3744
3943
  }
3745
3944
  )
3746
3945
  );
3747
- const selectSubmissionsForIssue = restructureCreateSelectorWithArgs(
3946
+ const selectFormSubmissionsOfIssue = restructureCreateSelectorWithArgs(
3748
3947
  createSelector(
3749
- [(state) => state.userFormReducer.submissions, (_state, issueId) => issueId],
3948
+ [selectFormSubmissions, (_state, issueId) => issueId],
3750
3949
  (submissions, issueId) => {
3751
3950
  return Object.values(submissions).filter((submission) => {
3752
3951
  return submission.issue === issueId;
@@ -3754,9 +3953,9 @@ const selectSubmissionsForIssue = restructureCreateSelectorWithArgs(
3754
3953
  }
3755
3954
  )
3756
3955
  );
3757
- const selectSubmissionsForComponent = restructureCreateSelectorWithArgs(
3956
+ const selectFormSubmissionsOfComponent = restructureCreateSelectorWithArgs(
3758
3957
  createSelector(
3759
- [selectSubmissions, (_state, componentId) => componentId],
3958
+ [selectFormSubmissions, (_state, componentId) => componentId],
3760
3959
  (submissions, componentId) => {
3761
3960
  return submissions.filter((submission) => {
3762
3961
  return submission.component === componentId;
@@ -3764,8 +3963,8 @@ const selectSubmissionsForComponent = restructureCreateSelectorWithArgs(
3764
3963
  }
3765
3964
  )
3766
3965
  );
3767
- const selectComponentSubmissionMapping = createSelector(
3768
- [selectSubmissionMapping, selectComponentsMapping],
3966
+ const selectFormSubmissionsByComponents = createSelector(
3967
+ [selectFormSubmissionsMapping, selectComponentsMapping],
3769
3968
  (submissions, components) => {
3770
3969
  var _a2;
3771
3970
  const componentSubmissionMapping = {};
@@ -3779,62 +3978,26 @@ const selectComponentSubmissionMapping = createSelector(
3779
3978
  }
3780
3979
  }
3781
3980
  return componentSubmissionMapping;
3782
- }
3783
- );
3784
- const selectUserFormMapping = (state) => {
3785
- return state.userFormReducer.userForms;
3786
- };
3787
- const selectComponentTypeForm = restructureCreateSelectorWithArgs(
3788
- createSelector(
3789
- [selectUserFormMapping, (_state, componentTypeId) => componentTypeId],
3790
- (userForms, componentTypeId) => {
3791
- return Object.values(userForms).find((userForm) => userForm.component_type === componentTypeId);
3792
- }
3793
- )
3981
+ }
3794
3982
  );
3795
- const selectLatestRevisionsFromComponentTypeIds = restructureCreateSelectorWithArgs(
3983
+ const selectFormSubmissionAttachmentsMapping = (state) => {
3984
+ return state.formSubmissionReducer.attachments;
3985
+ };
3986
+ const selectAttachmentsOfFormSubmission = restructureCreateSelectorWithArgs(
3796
3987
  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;
3988
+ [selectFormSubmissionAttachmentsMapping, (_state, submissionId) => submissionId],
3989
+ (attachmentsMapping, submissionId) => {
3990
+ return Object.values(attachmentsMapping).filter((attachment) => attachment.submission === submissionId);
3811
3991
  }
3812
3992
  )
3813
3993
  );
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;
3832
- const initialState$2 = {
3994
+ const formSubmissionReducer = formSubmissionSlice.reducer;
3995
+ const initialState$3 = {
3833
3996
  emailDomains: {}
3834
3997
  };
3835
3998
  const emailDomainsSlice = createSlice({
3836
3999
  name: "emailDomains",
3837
- initialState: initialState$2,
4000
+ initialState: initialState$3,
3838
4001
  reducers: {
3839
4002
  setEmailDomains: (state, action) => {
3840
4003
  const emailDomains = {};
@@ -3861,15 +4024,15 @@ const selectSortedEmailDomains = (state) => Object.values(state.emailDomainsRedu
3861
4024
  (ed1, ed2) => ed1.domain.localeCompare(ed2.domain)
3862
4025
  );
3863
4026
  const emailDomainsReducer = emailDomainsSlice.reducer;
3864
- const initialState$1 = {
4027
+ const initialState$2 = {
3865
4028
  documents: {},
3866
4029
  attachments: {}
3867
4030
  };
3868
4031
  const documentSlice = createSlice({
3869
4032
  name: "documents",
3870
- initialState: initialState$1,
4033
+ initialState: initialState$2,
3871
4034
  extraReducers: (builder) => builder.addCase("RESET", (state) => {
3872
- Object.assign(state, initialState$1);
4035
+ Object.assign(state, initialState$2);
3873
4036
  }),
3874
4037
  reducers: {
3875
4038
  setDocuments: (state, action) => {
@@ -4085,6 +4248,62 @@ const selectAttachmentsOfDocumentByType = restructureCreateSelectorWithArgs(
4085
4248
  )
4086
4249
  );
4087
4250
  const documentsReducer = documentSlice.reducer;
4251
+ const initialState$1 = {
4252
+ teams: {}
4253
+ };
4254
+ const teamSlice = createSlice({
4255
+ name: "teams",
4256
+ initialState: initialState$1,
4257
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$1)),
4258
+ reducers: {
4259
+ setTeam: (state, action) => {
4260
+ state.teams[action.payload.offline_id] = action.payload;
4261
+ },
4262
+ setTeams: (state, action) => {
4263
+ state.teams = {};
4264
+ for (const team of action.payload) {
4265
+ state.teams[team.offline_id] = team;
4266
+ }
4267
+ },
4268
+ addTeam: (state, action) => {
4269
+ if (state.teams[action.payload.offline_id]) {
4270
+ throw new Error(`Team with offline_id ${action.payload.offline_id} already exists`);
4271
+ }
4272
+ state.teams[action.payload.offline_id] = action.payload;
4273
+ },
4274
+ updateTeam: (state, action) => {
4275
+ if (!state.teams[action.payload.offline_id]) {
4276
+ throw new Error(`Team with offline_id ${action.payload.offline_id} does not exist`);
4277
+ }
4278
+ state.teams[action.payload.offline_id] = action.payload;
4279
+ },
4280
+ deleteTeam: (state, action) => {
4281
+ delete state.teams[action.payload];
4282
+ }
4283
+ }
4284
+ });
4285
+ const { setTeam, setTeams, addTeam, updateTeam, deleteTeam } = teamSlice.actions;
4286
+ const selectTeamsMapping = (state) => state.teamReducer.teams;
4287
+ const selectTeams = createSelector([selectTeamsMapping], (teams) => {
4288
+ return Object.values(teams);
4289
+ });
4290
+ const selectTeam = (teamId) => (state) => {
4291
+ return state.teamReducer.teams[teamId];
4292
+ };
4293
+ const selectTeamsOfOrganization = restructureCreateSelectorWithArgs(
4294
+ createSelector(
4295
+ [selectTeams, (_state, organizationId) => organizationId],
4296
+ (teams, organizationId) => {
4297
+ return teams.filter((team) => team.organization === organizationId);
4298
+ }
4299
+ )
4300
+ );
4301
+ const selectTeamsOfUser = restructureCreateSelectorWithArgs(
4302
+ createSelector([selectTeams, (_state, userId) => userId], (teams, userId) => {
4303
+ return teams.filter((team) => team.members.includes(userId));
4304
+ })
4305
+ );
4306
+ const teamReducer = teamSlice.reducer;
4088
4307
  const initialState = {
4089
4308
  version: 0
4090
4309
  };
@@ -4126,12 +4345,15 @@ const overmapReducers = {
4126
4345
  projectFileReducer,
4127
4346
  rehydratedReducer,
4128
4347
  settingReducer,
4129
- userFormReducer,
4348
+ formReducer,
4349
+ formRevisionReducer,
4350
+ formSubmissionReducer,
4130
4351
  userReducer,
4131
4352
  workspaceReducer,
4132
4353
  emailDomainsReducer,
4133
4354
  licenseReducer,
4134
- documentsReducer
4355
+ documentsReducer,
4356
+ teamReducer
4135
4357
  };
4136
4358
  const overmapReducer = combineReducers(overmapReducers);
4137
4359
  const resetStore = "RESET";
@@ -4179,9 +4401,7 @@ function handleWorkspaceRemoval(draft, action) {
4179
4401
  throw new Error(`Failed to update index_workspace of issue ${issue.offline_id} to main workspace`);
4180
4402
  }
4181
4403
  }
4182
- const indexedForms = Object.values(draft.userFormReducer.userForms).filter(
4183
- (form) => form.index_workspace === workspaceId
4184
- );
4404
+ const indexedForms = Object.values(draft.formReducer.forms).filter((form) => form.index_workspace === workspaceId);
4185
4405
  for (const form of indexedForms) {
4186
4406
  form.index_workspace = mainWorkspace.offline_id;
4187
4407
  }
@@ -6372,6 +6592,7 @@ class MainService extends BaseApiService {
6372
6592
  }
6373
6593
  if (currentOrgId) {
6374
6594
  await this.client.organizations.fetchInitialOrganizationData(currentOrgId, false);
6595
+ void this.client.teams.refreshStore();
6375
6596
  }
6376
6597
  if (!isProjectIdValid) {
6377
6598
  if (validProjects.length !== 0) {
@@ -6809,7 +7030,7 @@ class UserFormService extends BaseApiService {
6809
7030
  ...revisionAttachmentPayload,
6810
7031
  file: URL.createObjectURL(image)
6811
7032
  };
6812
- store.dispatch(addUserFormRevisionAttachment(offlinePayload));
7033
+ store.dispatch(addFormRevisionAttachment(offlinePayload));
6813
7034
  return attach;
6814
7035
  });
6815
7036
  });
@@ -6845,8 +7066,8 @@ class UserFormService extends BaseApiService {
6845
7066
  submitted_at: submittedAt
6846
7067
  };
6847
7068
  const { store } = this.client;
6848
- store.dispatch(addUserForm(retForm));
6849
- store.dispatch(addUserFormRevision(retRevision));
7069
+ store.dispatch(addForm(retForm));
7070
+ store.dispatch(addFormRevision(retRevision));
6850
7071
  const formPromise = this.enqueueRequest({
6851
7072
  description: "Create form",
6852
7073
  method: HttpMethod.POST,
@@ -6864,8 +7085,8 @@ class UserFormService extends BaseApiService {
6864
7085
  });
6865
7086
  const attachImagesPromises = this.getAttachImagePromises(images, offlineRevisionPayload.offline_id);
6866
7087
  void formPromise.catch((e) => {
6867
- store.dispatch(deleteUserForm(retForm.offline_id));
6868
- store.dispatch(deleteUserFormRevision(retRevision.offline_id));
7088
+ store.dispatch(deleteForm(retForm.offline_id));
7089
+ store.dispatch(deleteFormRevision(retRevision.offline_id));
6869
7090
  throw e;
6870
7091
  });
6871
7092
  const settledPromise = Promise.all([formPromise, ...attachImagesPromises]).then(() => formPromise);
@@ -6908,7 +7129,7 @@ class UserFormService extends BaseApiService {
6908
7129
  form: formId2,
6909
7130
  submitted_at: (/* @__PURE__ */ new Date()).toISOString()
6910
7131
  };
6911
- store.dispatch(addUserFormRevision(fullRevision));
7132
+ store.dispatch(addFormRevision(fullRevision));
6912
7133
  const promise = this.enqueueRequest({
6913
7134
  description: "Create form revision",
6914
7135
  method: HttpMethod.PATCH,
@@ -6922,9 +7143,9 @@ class UserFormService extends BaseApiService {
6922
7143
  });
6923
7144
  const attachImagesPromises = this.getAttachImagePromises(images, offlineRevision.offline_id);
6924
7145
  void promise.then((result) => {
6925
- store.dispatch(addUserFormRevision(result));
7146
+ store.dispatch(setFormRevision(result));
6926
7147
  }).catch(() => {
6927
- store.dispatch(deleteUserFormRevision(fullRevision.offline_id));
7148
+ store.dispatch(deleteFormRevision(fullRevision.offline_id));
6928
7149
  });
6929
7150
  const settledPromise = Promise.all([promise, ...attachImagesPromises]).then(() => promise);
6930
7151
  return [fullRevision, settledPromise];
@@ -6966,19 +7187,19 @@ class UserFormService extends BaseApiService {
6966
7187
  async delete(formId2) {
6967
7188
  const { store } = this.client;
6968
7189
  const state = store.getState();
6969
- const userForm = selectUserForm(formId2)(state);
7190
+ const userForm = selectForm(formId2)(state);
6970
7191
  if (!userForm) {
6971
7192
  throw new Error("Expected userForm to exist");
6972
7193
  }
6973
- const userFormSubmissions = selectSubmissionsForForm(formId2)(state);
7194
+ const userFormSubmissions = selectFormSubmissionsOfForm(formId2)(state);
6974
7195
  if (userFormSubmissions && userFormSubmissions.length > 0) {
6975
- store.dispatch(deleteUserFormSubmissions(userFormSubmissions));
7196
+ store.dispatch(deleteFormSubmissions(userFormSubmissions.map(({ offline_id }) => offline_id)));
6976
7197
  }
6977
- const userFormRevisions = selectRevisionsForForm(formId2)(state);
7198
+ const userFormRevisions = selectFormRevisionsOfForm(formId2)(state);
6978
7199
  if (userFormRevisions && userFormRevisions.length > 0) {
6979
- store.dispatch(deleteUserFormRevisions(userFormRevisions));
7200
+ store.dispatch(deleteFormRevisions(userFormRevisions.map(({ offline_id }) => offline_id)));
6980
7201
  }
6981
- store.dispatch(deleteUserForm(formId2));
7202
+ store.dispatch(deleteForm(formId2));
6982
7203
  try {
6983
7204
  return await this.enqueueRequest({
6984
7205
  description: "Delete form",
@@ -6988,12 +7209,12 @@ class UserFormService extends BaseApiService {
6988
7209
  blocks: []
6989
7210
  });
6990
7211
  } catch (e) {
6991
- store.dispatch(addUserForm(userForm));
7212
+ store.dispatch(addForm(userForm));
6992
7213
  if (userFormRevisions && userFormRevisions.length > 0) {
6993
- store.dispatch(addUserFormRevisions(userFormRevisions));
7214
+ store.dispatch(addFormRevisions(userFormRevisions));
6994
7215
  }
6995
7216
  if (userFormSubmissions && userFormSubmissions.length > 0) {
6996
- store.dispatch(addUserFormSubmissions(userFormSubmissions));
7217
+ store.dispatch(addFormSubmissions(userFormSubmissions));
6997
7218
  }
6998
7219
  throw e;
6999
7220
  }
@@ -7007,16 +7228,15 @@ class UserFormService extends BaseApiService {
7007
7228
  blockers: [],
7008
7229
  blocks: []
7009
7230
  });
7010
- store.dispatch(addUserForms(Object.values(result.forms)));
7011
- store.dispatch(addUserFormRevisions(Object.values(result.revisions)));
7012
- store.dispatch(setUserFormRevisionAttachments(Object.values(result.attachments)));
7231
+ store.dispatch(setForms(Object.values(result.forms)));
7232
+ store.dispatch(setFormRevisions(Object.values(result.revisions)));
7233
+ store.dispatch(setFormRevisionAttachments(Object.values(result.attachments)));
7013
7234
  }
7014
7235
  }
7015
7236
  const isArrayOfFiles = (value) => {
7016
7237
  return Array.isArray(value) && value[0] instanceof File;
7017
7238
  };
7018
- const separateFilesFromValues = (payload) => {
7019
- const { values } = payload;
7239
+ const separateFilesFromValues = (values) => {
7020
7240
  const files = {};
7021
7241
  const newValues = {};
7022
7242
  for (const key in values) {
@@ -7031,17 +7251,13 @@ const separateFilesFromValues = (payload) => {
7031
7251
  newValues[key] = value;
7032
7252
  }
7033
7253
  }
7034
- const payloadWithoutFiles = {
7035
- ...payload,
7036
- values: newValues
7037
- };
7038
- return { payloadWithoutFiles, files };
7254
+ return { values: newValues, files };
7039
7255
  };
7040
7256
  class UserFormSubmissionService extends BaseApiService {
7041
7257
  constructor() {
7042
7258
  super(...arguments);
7043
7259
  // Attach files to submission, after uploading them to S3
7044
- __publicField(this, "getAttachFilesPromises", (files, payload) => {
7260
+ __publicField(this, "getAttachFilesPromises", (files, submission) => {
7045
7261
  const { store } = this.client;
7046
7262
  return Object.entries(files).map(async ([key, fileArray]) => {
7047
7263
  const attachResults = [];
@@ -7051,24 +7267,27 @@ class UserFormSubmissionService extends BaseApiService {
7051
7267
  const [fileProps] = await this.client.files.uploadFileToS3(sha1);
7052
7268
  const submissionAttachmentPayload = offline({
7053
7269
  ...fileProps,
7054
- submission: payload.offline_id,
7270
+ submission: submission.offline_id,
7055
7271
  field_identifier: key
7056
7272
  });
7057
7273
  const attach = await this.enqueueRequest({
7058
7274
  description: "Attach file to form submission",
7059
7275
  method: HttpMethod.POST,
7060
- url: `/forms/submission/${payload.offline_id}/attachments/`,
7276
+ url: `/forms/submission/${submission.offline_id}/attachments/`,
7061
7277
  payload: submissionAttachmentPayload,
7062
- blockers: [payload.component, payload.component_stage, payload.issue, payload.form_revision].filter(
7063
- (x) => x !== void 0
7064
- ),
7278
+ blockers: [
7279
+ submission.component,
7280
+ submission.component_stage,
7281
+ submission.issue,
7282
+ submission.form_revision
7283
+ ].filter((x) => x !== void 0),
7065
7284
  blocks: [submissionAttachmentPayload.offline_id]
7066
7285
  });
7067
7286
  const offlinePayload = {
7068
7287
  ...submissionAttachmentPayload,
7069
7288
  file: URL.createObjectURL(file)
7070
7289
  };
7071
- store.dispatch(addUserFormSubmissionAttachment(offlinePayload));
7290
+ store.dispatch(addFormSubmissionAttachment(offlinePayload));
7072
7291
  attachResults.push(attach);
7073
7292
  }
7074
7293
  return attachResults;
@@ -7082,71 +7301,168 @@ class UserFormSubmissionService extends BaseApiService {
7082
7301
  if (!activeProjectId) {
7083
7302
  throw new Error("Expected an active project");
7084
7303
  }
7085
- const { payloadWithoutFiles, files } = separateFilesFromValues(payload);
7304
+ const { values, files } = separateFilesFromValues(payload.values);
7305
+ const offlineSubmission = {
7306
+ ...payload,
7307
+ values,
7308
+ created_by: state.userReducer.currentUser.id,
7309
+ submitted_at: (/* @__PURE__ */ new Date()).toISOString()
7310
+ };
7086
7311
  const promise = this.enqueueRequest({
7087
7312
  description: "Respond to form",
7088
7313
  method: HttpMethod.POST,
7089
7314
  url: `/forms/revisions/${payload.form_revision}/respond/`,
7090
- payload: { ...payloadWithoutFiles, project: activeProjectId },
7315
+ payload: { ...offlineSubmission, project: activeProjectId },
7091
7316
  blockers: [payload.issue, payload.component, payload.component_stage, "add-form-entry"].filter(
7092
7317
  (x) => x !== void 0
7093
7318
  ),
7094
7319
  blocks: [payload.offline_id]
7095
7320
  });
7096
- const attachFilesPromises = this.getAttachFilesPromises(files, payload);
7097
- const now = (/* @__PURE__ */ new Date()).toISOString();
7098
- const fullOfflineResult = {
7099
- ...payload,
7100
- created_by: state.userReducer.currentUser.id,
7101
- created_at: now,
7102
- updated_at: now
7103
- };
7104
- const offlineResultWithoutFiles = {
7105
- ...fullOfflineResult,
7106
- ...payloadWithoutFiles
7107
- };
7108
- store.dispatch(updateOrCreateUserFormSubmission(offlineResultWithoutFiles));
7321
+ const attachFilesPromises = this.getAttachFilesPromises(files, offlineSubmission);
7322
+ store.dispatch(addFormSubmission(offlineSubmission));
7109
7323
  void promise.then((result) => {
7110
7324
  store.dispatch(addActiveProjectFormSubmissionsCount(1));
7111
- store.dispatch(updateOrCreateUserFormSubmission(result));
7325
+ store.dispatch(setFormSubmission(result));
7112
7326
  return result;
7113
7327
  }).catch(() => {
7114
- store.dispatch(deleteUserFormSubmission(payload.offline_id));
7328
+ store.dispatch(deleteFormSubmission(payload.offline_id));
7115
7329
  store.dispatch(addActiveProjectFormSubmissionsCount(-1));
7116
7330
  });
7117
7331
  const settledPromise = Promise.all([promise, ...attachFilesPromises]).then(() => promise);
7118
- return [fullOfflineResult, settledPromise];
7332
+ return [offlineSubmission, settledPromise];
7119
7333
  }
7120
- update(submission) {
7334
+ // Note currently the bulkAdd method is specific to form submissions for components
7335
+ // TODO: adapt the support bulk adding to any model type
7336
+ async bulkAdd(args) {
7337
+ const { formRevision, values: argsValues, componentOfflineIds } = args;
7121
7338
  const { store } = this.client;
7122
- const { payloadWithoutFiles, files } = separateFilesFromValues(submission);
7123
- if (!("created_by" in payloadWithoutFiles) || !("created_at" in payloadWithoutFiles)) {
7124
- throw new Error("Expected payloadWithoutFiles to have created_by and created_at fields.");
7339
+ const offlineSubmissions = [];
7340
+ const offlineAttachments = [];
7341
+ const submissionOfflineIds = [];
7342
+ const submissionsPayload = [];
7343
+ const attachmentsPayload = [];
7344
+ const { values, files } = separateFilesFromValues(argsValues);
7345
+ const submittedAt = (/* @__PURE__ */ new Date()).toISOString();
7346
+ const createdBy = store.getState().userReducer.currentUser.id;
7347
+ for (const component_id of componentOfflineIds) {
7348
+ const submission = offline({
7349
+ form_revision: formRevision,
7350
+ values,
7351
+ created_by: createdBy,
7352
+ submitted_at: submittedAt,
7353
+ component: component_id
7354
+ });
7355
+ submissionOfflineIds.push(submission.offline_id);
7356
+ submissionsPayload.push({ offline_id: submission.offline_id, component_id });
7357
+ offlineSubmissions.push(submission);
7358
+ for (const [fieldIdentifier, fileArray] of Object.entries(files)) {
7359
+ for (const file of fileArray) {
7360
+ const sha1 = await hashFile(file);
7361
+ await this.client.files.addCache(file, sha1);
7362
+ const offlineAttachment = offline({
7363
+ file_name: file.name,
7364
+ file_sha1: sha1,
7365
+ file: URL.createObjectURL(file),
7366
+ submission: submission.offline_id,
7367
+ field_identifier: fieldIdentifier
7368
+ });
7369
+ offlineAttachments.push(offlineAttachment);
7370
+ attachmentsPayload.push({
7371
+ offline_id: offlineAttachment.offline_id,
7372
+ submission_id: submission.offline_id,
7373
+ sha1,
7374
+ name: file.name,
7375
+ field_identifier: fieldIdentifier
7376
+ });
7377
+ }
7378
+ }
7379
+ }
7380
+ const filesRecord = {};
7381
+ for (const file of Object.values(files).flat()) {
7382
+ const sha1 = await hashFile(file);
7383
+ filesRecord[sha1] = {
7384
+ sha1,
7385
+ extension: file.name.split(".").pop() || "",
7386
+ file_type: file.type,
7387
+ size: file.size
7388
+ };
7125
7389
  }
7390
+ store.dispatch(addFormSubmissions(offlineSubmissions));
7391
+ store.dispatch(addFormSubmissionAttachments(offlineAttachments));
7392
+ const promise = this.enqueueRequest({
7393
+ description: "Bulk add form submissions",
7394
+ method: HttpMethod.POST,
7395
+ url: `/forms/revisions/${formRevision}/bulk-respond/`,
7396
+ payload: {
7397
+ form_data: values,
7398
+ submitted_at: submittedAt,
7399
+ submissions: submissionsPayload,
7400
+ attachments: attachmentsPayload,
7401
+ files: Object.values(filesRecord)
7402
+ },
7403
+ blockers: componentOfflineIds,
7404
+ blocks: submissionOfflineIds
7405
+ });
7406
+ promise.then(({ submissions, attachments, presigned_urls }) => {
7407
+ store.dispatch(updateFormSubmissions(submissions));
7408
+ store.dispatch(updateFormSubmissionAttachments(attachments));
7409
+ for (const [sha1, presigned_url] of Object.entries(presigned_urls)) {
7410
+ const file = filesRecord[sha1];
7411
+ if (!file)
7412
+ continue;
7413
+ void this.enqueueRequest({
7414
+ url: presigned_url.url,
7415
+ description: "Upload file",
7416
+ method: HttpMethod.POST,
7417
+ isExternalUrl: true,
7418
+ isAuthNeeded: false,
7419
+ attachmentHash: sha1,
7420
+ blockers: [`s3-${file.sha1}.${file.extension}`],
7421
+ blocks: [sha1],
7422
+ s3url: presigned_url
7423
+ });
7424
+ }
7425
+ }).catch(() => {
7426
+ store.dispatch(deleteFormSubmissions(submissionOfflineIds));
7427
+ store.dispatch(deleteFormSubmissionAttachments(offlineAttachments.map((x) => x.offline_id)));
7428
+ });
7429
+ return [offlineSubmissions, promise.then(({ submissions }) => submissions)];
7430
+ }
7431
+ update(submission) {
7432
+ const { store } = this.client;
7433
+ const { values, files } = separateFilesFromValues(submission.values);
7126
7434
  const attachFilesPromises = this.getAttachFilesPromises(files, submission);
7127
- const fullResult = {
7128
- ...payloadWithoutFiles,
7129
- updated_at: (/* @__PURE__ */ new Date()).toISOString()
7435
+ const offlineSubmission = {
7436
+ ...submission,
7437
+ values
7130
7438
  };
7131
- store.dispatch(updateOrCreateUserFormSubmission(fullResult));
7439
+ const submissionToBeUpdated = store.getState().formSubmissionReducer.formSubmissions[submission.offline_id];
7440
+ store.dispatch(updateFormSubmission(offlineSubmission));
7132
7441
  const promise = this.enqueueRequest({
7133
7442
  description: "Patch form submission",
7134
7443
  method: HttpMethod.PATCH,
7135
7444
  url: `/forms/submissions/${submission.offline_id}/`,
7136
- payload: fullResult,
7137
- blockers: [fullResult.issue, fullResult.component, fullResult.component_stage].filter(
7445
+ payload: offlineSubmission,
7446
+ blockers: [offlineSubmission.issue, offlineSubmission.component, offlineSubmission.component_stage].filter(
7138
7447
  (x) => x !== void 0
7139
7448
  ),
7140
- blocks: [fullResult.offline_id]
7449
+ blocks: [offlineSubmission.offline_id]
7450
+ });
7451
+ promise.then((createdSubmission) => {
7452
+ store.dispatch(setFormSubmission(createdSubmission));
7453
+ }).catch(() => {
7454
+ store.dispatch(setFormSubmission(submissionToBeUpdated));
7141
7455
  });
7142
- return Promise.all([promise, ...attachFilesPromises]).then(() => promise);
7456
+ return [offlineSubmission, Promise.all([promise, ...attachFilesPromises]).then(() => promise)];
7143
7457
  }
7144
7458
  async delete(submissionId) {
7145
7459
  const { store } = this.client;
7146
7460
  const state = store.getState();
7147
- const submission = state.userFormReducer.submissions[submissionId];
7148
- store.dispatch(deleteUserFormSubmission(submissionId));
7461
+ const submission = state.formSubmissionReducer.formSubmissions[submissionId];
7462
+ const submissionAttachments = selectAttachmentsOfFormSubmission(submissionId)(state);
7463
+ store.dispatch(deleteFormSubmission(submissionId));
7149
7464
  store.dispatch(addActiveProjectFormSubmissionsCount(-1));
7465
+ store.dispatch(deleteFormSubmissionAttachments(submissionAttachments.map((x) => x.offline_id)));
7150
7466
  try {
7151
7467
  return await this.enqueueRequest({
7152
7468
  description: "Delete user form submissions",
@@ -7156,10 +7472,9 @@ class UserFormSubmissionService extends BaseApiService {
7156
7472
  blocks: []
7157
7473
  });
7158
7474
  } catch (e) {
7159
- if (submission) {
7160
- store.dispatch(addActiveProjectFormSubmissionsCount(1));
7161
- store.dispatch(updateOrCreateUserFormSubmission(submission));
7162
- }
7475
+ store.dispatch(addActiveProjectFormSubmissionsCount(1));
7476
+ store.dispatch(addFormSubmission(submission));
7477
+ store.dispatch(addFormSubmissionAttachments(submissionAttachments));
7163
7478
  throw e;
7164
7479
  }
7165
7480
  }
@@ -7173,7 +7488,7 @@ class UserFormSubmissionService extends BaseApiService {
7173
7488
  blockers: [],
7174
7489
  blocks: []
7175
7490
  });
7176
- store.dispatch(setUserFormSubmissions(submissions));
7491
+ store.dispatch(setFormSubmissions(submissions));
7177
7492
  const attachments = await this.enqueueRequest({
7178
7493
  description: "Fetch form attachments",
7179
7494
  method: HttpMethod.GET,
@@ -7181,7 +7496,7 @@ class UserFormSubmissionService extends BaseApiService {
7181
7496
  blockers: [],
7182
7497
  blocks: []
7183
7498
  });
7184
- store.dispatch(setUserFormSubmissionAttachments(attachments));
7499
+ store.dispatch(setFormSubmissionAttachments(attachments));
7185
7500
  }
7186
7501
  }
7187
7502
  class WorkspaceService extends BaseApiService {
@@ -7905,6 +8220,142 @@ class AgentService extends BaseApiService {
7905
8220
  });
7906
8221
  }
7907
8222
  }
8223
+ class TeamService extends BaseApiService {
8224
+ add(teamPayload) {
8225
+ const { store } = this.client;
8226
+ const state = store.getState();
8227
+ const activeOrganizationId = state.organizationReducer.activeOrganizationId;
8228
+ if (!activeOrganizationId) {
8229
+ throw new Error(`Expected active organization to be set, got ${activeOrganizationId}`);
8230
+ }
8231
+ const offlineTeam = offline({
8232
+ ...teamPayload,
8233
+ organization: activeOrganizationId,
8234
+ submitted_at: (/* @__PURE__ */ new Date()).toISOString()
8235
+ // TODO: uncomment once supported
8236
+ // created_by: state.userReducer.currentUser.id,
8237
+ });
8238
+ store.dispatch(addTeam(offlineTeam));
8239
+ const promise = this.enqueueRequest({
8240
+ description: "Create team",
8241
+ method: HttpMethod.POST,
8242
+ url: `/organizations/${activeOrganizationId}/teams/`,
8243
+ payload: offlineTeam,
8244
+ // No blocks since users and organizations are not offline
8245
+ blockers: [],
8246
+ blocks: [offlineTeam.offline_id]
8247
+ });
8248
+ promise.then((createdTeam) => {
8249
+ store.dispatch(setTeam(createdTeam));
8250
+ }).catch(() => {
8251
+ store.dispatch(deleteTeam(offlineTeam.offline_id));
8252
+ });
8253
+ return [offlineTeam, promise];
8254
+ }
8255
+ // TODO: @Audiopolis / Magnus - should we pass a offline_id as one arg and a UpdatedTeamProps as a second arg instead of this set up?
8256
+ update(team) {
8257
+ const { store } = this.client;
8258
+ const teamToBeUpdated = store.getState().teamReducer.teams[team.offline_id];
8259
+ const offlineUpdatedTeam = {
8260
+ ...teamToBeUpdated,
8261
+ ...team
8262
+ };
8263
+ store.dispatch(updateTeam(offlineUpdatedTeam));
8264
+ const promise = this.enqueueRequest({
8265
+ description: "Update team",
8266
+ method: HttpMethod.PATCH,
8267
+ url: `/organizations/teams/${team.offline_id}/`,
8268
+ payload: offlineUpdatedTeam,
8269
+ blockers: [team.offline_id],
8270
+ blocks: [team.offline_id]
8271
+ });
8272
+ promise.then((updatedTeam) => {
8273
+ store.dispatch(setTeam(updatedTeam));
8274
+ }).catch(() => {
8275
+ store.dispatch(setTeam(teamToBeUpdated));
8276
+ });
8277
+ return [offlineUpdatedTeam, promise];
8278
+ }
8279
+ async delete(teamId) {
8280
+ const { store } = this.client;
8281
+ const state = store.getState();
8282
+ const team = state.teamReducer.teams[teamId];
8283
+ if (!team) {
8284
+ throw new Error(`Expected team with id ${teamId} to exist`);
8285
+ }
8286
+ store.dispatch(deleteTeam(teamId));
8287
+ try {
8288
+ return await this.enqueueRequest({
8289
+ description: "Delete team",
8290
+ method: HttpMethod.DELETE,
8291
+ url: `/organizations/teams/${teamId}/`,
8292
+ blockers: [teamId],
8293
+ blocks: [teamId]
8294
+ });
8295
+ } catch (e) {
8296
+ store.dispatch(setTeam(team));
8297
+ throw e;
8298
+ }
8299
+ }
8300
+ async setMembers(teamId, members) {
8301
+ const { store } = this.client;
8302
+ const team = store.getState().teamReducer.teams[teamId];
8303
+ if (!team) {
8304
+ throw new Error(`Expected team with id ${teamId} to exist`);
8305
+ }
8306
+ if (members.length !== new Set(members).size) {
8307
+ throw new Error("Duplicate members found in the list");
8308
+ }
8309
+ store.dispatch(updateTeam({ ...team, members }));
8310
+ const promise = this.enqueueRequest({
8311
+ description: "Set team members",
8312
+ method: HttpMethod.PUT,
8313
+ url: `/organizations/teams/${teamId}/set-members/`,
8314
+ payload: {
8315
+ users: members
8316
+ },
8317
+ blockers: [teamId],
8318
+ blocks: [teamId]
8319
+ });
8320
+ promise.catch(() => {
8321
+ store.dispatch(setTeam(team));
8322
+ });
8323
+ return promise;
8324
+ }
8325
+ async addMembers(teamId, members) {
8326
+ const { store } = this.client;
8327
+ const team = store.getState().teamReducer.teams[teamId];
8328
+ if (!team) {
8329
+ throw new Error(`Expected team with id ${teamId} to exist`);
8330
+ }
8331
+ const newMembers = [...team.members, ...members];
8332
+ return this.setMembers(teamId, newMembers);
8333
+ }
8334
+ async removeMembers(teamId, members) {
8335
+ const { store } = this.client;
8336
+ const team = store.getState().teamReducer.teams[teamId];
8337
+ if (!team) {
8338
+ throw new Error(`Expected team with id ${teamId} to exist`);
8339
+ }
8340
+ const newMembers = team.members.filter((member) => !members.includes(member));
8341
+ return this.setMembers(teamId, newMembers);
8342
+ }
8343
+ async refreshStore() {
8344
+ const { store } = this.client;
8345
+ const activeOrganizationId = store.getState().organizationReducer.activeOrganizationId;
8346
+ if (!activeOrganizationId) {
8347
+ throw new Error(`Expected active organization to be set, got ${activeOrganizationId}`);
8348
+ }
8349
+ const result = await this.enqueueRequest({
8350
+ description: "Fetch teams",
8351
+ method: HttpMethod.GET,
8352
+ url: `/organizations/${activeOrganizationId}/teams/`,
8353
+ blockers: [],
8354
+ blocks: []
8355
+ });
8356
+ store.dispatch(setTeams(result));
8357
+ }
8358
+ }
7908
8359
  class OvermapSDK {
7909
8360
  constructor(apiUrl, store) {
7910
8361
  __publicField(this, "API_URL");
@@ -7934,6 +8385,7 @@ class OvermapSDK {
7934
8385
  __publicField(this, "emailDomains", new EmailDomainsService(this));
7935
8386
  __publicField(this, "licenses", new LicenseService(this));
7936
8387
  __publicField(this, "documents", new DocumentService(this));
8388
+ __publicField(this, "teams", new TeamService(this));
7937
8389
  this.API_URL = apiUrl;
7938
8390
  this.store = store;
7939
8391
  }
@@ -7975,7 +8427,7 @@ const tabTrigger = "_tabTrigger_1w0fq_69";
7975
8427
  const patchfieldBorder = "_patchfieldBorder_1w0fq_73";
7976
8428
  const title = "_title_1w0fq_73";
7977
8429
  const error = "_error_1w0fq_89";
7978
- const styles$c = {
8430
+ const styles$d = {
7979
8431
  description: description$2,
7980
8432
  floatingButtonContainer: floatingButtonContainer$2,
7981
8433
  FullScreenImageContainer: FullScreenImageContainer$2,
@@ -8096,7 +8548,7 @@ const fileName$1 = "_fileName_10o76_31";
8096
8548
  const longIconButton$1 = "_longIconButton_10o76_36";
8097
8549
  const previewImage$1 = "_previewImage_10o76_42";
8098
8550
  const FullScreenImage$1 = "_FullScreenImage_10o76_12";
8099
- const styles$b = {
8551
+ const styles$c = {
8100
8552
  description: description$1,
8101
8553
  floatingButtonContainer: floatingButtonContainer$1,
8102
8554
  FullScreenImageContainer: FullScreenImageContainer$1,
@@ -8120,7 +8572,7 @@ const FullScreenImagePreview = memo((props) => {
8120
8572
  /* @__PURE__ */ jsx(
8121
8573
  "button",
8122
8574
  {
8123
- className: styles$b.FullScreenImageContainer,
8575
+ className: styles$c.FullScreenImageContainer,
8124
8576
  type: "button",
8125
8577
  onClick: () => {
8126
8578
  setShowPreview(false);
@@ -8128,7 +8580,7 @@ const FullScreenImagePreview = memo((props) => {
8128
8580
  children: /* @__PURE__ */ jsx(
8129
8581
  "img",
8130
8582
  {
8131
- className: styles$b.FullScreenImage,
8583
+ className: styles$c.FullScreenImage,
8132
8584
  src: url,
8133
8585
  alt: name,
8134
8586
  onClick: (e) => {
@@ -8138,11 +8590,11 @@ const FullScreenImagePreview = memo((props) => {
8138
8590
  )
8139
8591
  }
8140
8592
  ),
8141
- /* @__PURE__ */ jsxs(Flex$1, { className: styles$b.TopBarContainer, align: "center", children: [
8593
+ /* @__PURE__ */ jsxs(Flex$1, { className: styles$c.TopBarContainer, align: "center", children: [
8142
8594
  /* @__PURE__ */ jsx(
8143
8595
  IconButton,
8144
8596
  {
8145
- className: styles$b.longIconButton,
8597
+ className: styles$c.longIconButton,
8146
8598
  variant: "soft",
8147
8599
  "aria-label": "Exit preview",
8148
8600
  onClick: () => {
@@ -8151,11 +8603,11 @@ const FullScreenImagePreview = memo((props) => {
8151
8603
  children: /* @__PURE__ */ jsx(RiIcon, { icon: "RiArrowLeftLine" })
8152
8604
  }
8153
8605
  ),
8154
- /* @__PURE__ */ jsx(Text$1, { className: styles$b.fileName, children: name }),
8606
+ /* @__PURE__ */ jsx(Text$1, { className: styles$c.fileName, children: name }),
8155
8607
  /* @__PURE__ */ jsx(
8156
8608
  IconButton,
8157
8609
  {
8158
- className: styles$b.longIconButton,
8610
+ className: styles$c.longIconButton,
8159
8611
  variant: "soft",
8160
8612
  "aria-label": `Download ${name}`,
8161
8613
  onClick: handleDownload,
@@ -8183,7 +8635,7 @@ const InputWithLabel = (props) => {
8183
8635
  /* @__PURE__ */ jsx(
8184
8636
  "img",
8185
8637
  {
8186
- className: styles$b.previewImage,
8638
+ className: styles$c.previewImage,
8187
8639
  src: resolvedImageURL,
8188
8640
  alt: resolvedImage.name,
8189
8641
  onClick: () => {
@@ -8211,7 +8663,7 @@ const InputWithHelpText = (props) => {
8211
8663
  const { helpText, children, severity } = props;
8212
8664
  return /* @__PURE__ */ jsxs(Flex$1, { direction: "column", gap: "1", children: [
8213
8665
  children,
8214
- /* @__PURE__ */ jsx(Flex$1, { direction: "column", children: /* @__PURE__ */ jsx(Text$1, { size: "1", severity, className: styles$b.description, children: helpText }) })
8666
+ /* @__PURE__ */ jsx(Flex$1, { direction: "column", children: /* @__PURE__ */ jsx(Text$1, { size: "1", severity, className: styles$c.description, children: helpText }) })
8215
8667
  ] });
8216
8668
  };
8217
8669
  const InputWithLabelAndHelpText = (props) => {
@@ -8445,6 +8897,9 @@ function RiArrowUpLine(props) {
8445
8897
  function RiCalendarLine(props) {
8446
8898
  return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24", "fill": "currentColor" }, "child": [{ "tag": "path", "attr": { "d": "M9 1V3H15V1H17V3H21C21.5523 3 22 3.44772 22 4V20C22 20.5523 21.5523 21 21 21H3C2.44772 21 2 20.5523 2 20V4C2 3.44772 2.44772 3 3 3H7V1H9ZM20 11H4V19H20V11ZM7 5H4V9H20V5H17V7H15V5H9V7H7V5Z" }, "child": [] }] })(props);
8447
8899
  }
8900
+ function RiQrCodeLine(props) {
8901
+ return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24", "fill": "currentColor" }, "child": [{ "tag": "path", "attr": { "d": "M16 17V16H13V13H16V15H18V17H17V19H15V21H13V18H15V17H16ZM21 21H17V19H19V17H21V21ZM3 3H11V11H3V3ZM5 5V9H9V5H5ZM13 3H21V11H13V3ZM15 5V9H19V5H15ZM3 13H11V21H3V13ZM5 15V19H9V15H5ZM18 13H21V15H18V13ZM6 6H8V8H6V6ZM6 16H8V18H6V16ZM16 6H18V8H16V6Z" }, "child": [] }] })(props);
8902
+ }
8448
8903
  function RiFileCopyLine(props) {
8449
8904
  return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24", "fill": "currentColor" }, "child": [{ "tag": "path", "attr": { "d": "M6.9998 6V3C6.9998 2.44772 7.44752 2 7.9998 2H19.9998C20.5521 2 20.9998 2.44772 20.9998 3V17C20.9998 17.5523 20.5521 18 19.9998 18H16.9998V20.9991C16.9998 21.5519 16.5499 22 15.993 22H4.00666C3.45059 22 3 21.5554 3 20.9991L3.0026 7.00087C3.0027 6.44811 3.45264 6 4.00942 6H6.9998ZM5.00242 8L5.00019 20H14.9998V8H5.00242ZM8.9998 6H16.9998V16H18.9998V4H8.9998V6Z" }, "child": [] }] })(props);
8450
8905
  }
@@ -9348,9 +9803,9 @@ const Inset = React.forwardRef((props, forwardedRef) => {
9348
9803
  return React.createElement("div", { ...insetProps, ref: forwardedRef, className: classNames("rt-Inset", className, withBreakpoints(side, "rt-r-side"), withBreakpoints(clip, "rt-r-clip"), withBreakpoints(p, "rt-r-p"), withBreakpoints(px, "rt-r-px"), withBreakpoints(py, "rt-r-py"), withBreakpoints(pt, "rt-r-pt"), withBreakpoints(pr, "rt-r-pr"), withBreakpoints(pb, "rt-r-pb"), withBreakpoints(pl, "rt-r-pl"), withMarginProps(marginProps)) });
9349
9804
  });
9350
9805
  Inset.displayName = "Inset";
9351
- const sizes$7 = ["1", "2", "3", "4", "5", "6", "7", "8", "9"];
9806
+ const sizes$8 = ["1", "2", "3", "4", "5", "6", "7", "8", "9"];
9352
9807
  const headingPropDefs = {
9353
- size: { type: "enum", values: sizes$7, default: "6", responsive: true },
9808
+ size: { type: "enum", values: sizes$8, default: "6", responsive: true },
9354
9809
  weight: { ...weightProp, default: "bold" },
9355
9810
  align: alignProp,
9356
9811
  trim: trimProp,
@@ -9363,9 +9818,9 @@ const Heading = React.forwardRef((props, forwardedRef) => {
9363
9818
  return React.createElement($5e63c961fc1ce211$export$8c6ed5c666ac1360, { "data-accent-color": color, ...headingProps, ref: forwardedRef, className: classNames("rt-Heading", className, withBreakpoints(size, "rt-r-size"), withBreakpoints(weight, "rt-r-weight"), withBreakpoints(align, "rt-r-ta"), withBreakpoints(trim, "rt-r-lt"), { "rt-high-contrast": highContrast }, withMarginProps(marginProps)) }, asChild ? children : React.createElement(Tag, null, children));
9364
9819
  });
9365
9820
  Heading.displayName = "Heading";
9366
- const sizes$6 = ["1", "2", "3", "4", "5", "6", "7", "8", "9"];
9821
+ const sizes$7 = ["1", "2", "3", "4", "5", "6", "7", "8", "9"];
9367
9822
  const textPropDefs = {
9368
- size: { type: "enum", values: sizes$6, default: void 0, responsive: true },
9823
+ size: { type: "enum", values: sizes$7, default: void 0, responsive: true },
9369
9824
  weight: weightProp,
9370
9825
  align: alignProp,
9371
9826
  trim: trimProp,
@@ -9378,6 +9833,21 @@ const Text = React.forwardRef((props, forwardedRef) => {
9378
9833
  return React.createElement($5e63c961fc1ce211$export$8c6ed5c666ac1360, { "data-accent-color": color, ...textProps, ref: forwardedRef, className: classNames("rt-Text", className, withBreakpoints(size, "rt-r-size"), withBreakpoints(weight, "rt-r-weight"), withBreakpoints(align, "rt-r-ta"), withBreakpoints(trim, "rt-r-lt"), { "rt-high-contrast": highContrast }, withMarginProps(marginProps)) }, asChild ? children : React.createElement(Tag, null, children));
9379
9834
  });
9380
9835
  Text.displayName = "Text";
9836
+ const sizes$6 = ["1", "2", "3", "4", "5", "6", "7", "8", "9"];
9837
+ const variants$4 = ["solid", "soft", "outline", "ghost"];
9838
+ const codePropDefs = {
9839
+ size: { type: "enum", values: sizes$6, default: void 0, responsive: true },
9840
+ variant: { type: "enum", values: variants$4, default: "soft" },
9841
+ weight: weightProp,
9842
+ color: colorProp,
9843
+ highContrast: highContrastProp
9844
+ };
9845
+ const Code = React.forwardRef((props, forwardedRef) => {
9846
+ const { rest: marginRest, ...marginProps } = extractMarginProps(props);
9847
+ const { className, size = codePropDefs.size.default, variant = codePropDefs.variant.default, weight = codePropDefs.weight.default, color = codePropDefs.color.default, highContrast = codePropDefs.highContrast.default, ...codeProps } = marginRest;
9848
+ return React.createElement("code", { "data-accent-color": color, ...codeProps, ref: forwardedRef, className: classNames("rt-Code", className, withBreakpoints(size, "rt-r-size"), `rt-variant-${variant}`, withBreakpoints(weight, "rt-r-weight"), { "rt-high-contrast": highContrast }, withMarginProps(marginProps)) });
9849
+ });
9850
+ Code.displayName = "Code";
9381
9851
  const Em = React.forwardRef((props, forwardedRef) => React.createElement("em", { ...props, ref: forwardedRef, className: classNames("rt-Em", props.className) }));
9382
9852
  Em.displayName = "Em";
9383
9853
  const Strong = React.forwardRef((props, forwardedRef) => React.createElement("strong", { ...props, ref: forwardedRef, className: classNames("rt-Strong", props.className) }));
@@ -11768,7 +12238,7 @@ __publicField(StringOrTextField, "_validateMax", (path) => (value, allValues) =>
11768
12238
  });
11769
12239
  const clickableLinkContainer = "_clickableLinkContainer_1ace7_1";
11770
12240
  const TextFieldInputCopy = "_TextFieldInputCopy_1ace7_5";
11771
- const styles$a = {
12241
+ const styles$b = {
11772
12242
  clickableLinkContainer,
11773
12243
  TextFieldInputCopy
11774
12244
  };
@@ -11797,13 +12267,13 @@ const StringInput = memo((props) => {
11797
12267
  placeholder: field.placeholder,
11798
12268
  color
11799
12269
  }
11800
- ) : /* @__PURE__ */ jsxs(TextField$1.Root, { className: styles$a.clickableLinkContainer, children: [
12270
+ ) : /* @__PURE__ */ jsxs(TextField$1.Root, { className: styles$b.clickableLinkContainer, children: [
11801
12271
  /* @__PURE__ */ jsx(
11802
12272
  "div",
11803
12273
  {
11804
12274
  className: classNames$1(
11805
12275
  "rt-TextFieldInput rt-r-size-2 rt-variant-surface",
11806
- styles$a.TextFieldInputCopy
12276
+ styles$b.TextFieldInputCopy
11807
12277
  ),
11808
12278
  children: /* @__PURE__ */ jsx(
11809
12279
  Linkify,
@@ -12375,8 +12845,7 @@ class BaseSelectField extends BaseField {
12375
12845
  description: "List possible options for the user to select from.",
12376
12846
  required: true,
12377
12847
  identifier: `${path}options`,
12378
- minimum_length: 2,
12379
- maximum_length: 20
12848
+ minimum_length: 2
12380
12849
  }),
12381
12850
  showDirectly: true
12382
12851
  }
@@ -12495,6 +12964,158 @@ __publicField(_MultiSelectField, "fieldTypeName", "Multi-select");
12495
12964
  __publicField(_MultiSelectField, "fieldTypeDescription", "Allows the user to select a multiple options from a list of options.");
12496
12965
  __publicField(_MultiSelectField, "Icon", RiCheckboxLine);
12497
12966
  let MultiSelectField = _MultiSelectField;
12967
+ const QrScannerWrapper = "_QrScannerWrapper_1puz3_1";
12968
+ const styles$a = {
12969
+ QrScannerWrapper
12970
+ };
12971
+ const QrInput = memo((props) => {
12972
+ const [{ inputId, labelId, label, helpText, size, severity, showInputOnly, field, fieldProps }, rest] = useFormikInput(props);
12973
+ const [showQrScanner, setShowQrScanner] = useState(false);
12974
+ const value = fieldProps.value;
12975
+ const handleQrScan = useCallback(
12976
+ (data) => {
12977
+ fieldProps.onChange({ target: { value: data } });
12978
+ setShowQrScanner(false);
12979
+ },
12980
+ [fieldProps]
12981
+ );
12982
+ const handleClearScanResult = useCallback(() => {
12983
+ fieldProps.onChange({ target: { value: "" } });
12984
+ }, [fieldProps]);
12985
+ const handleScanButtonClicked = useCallback(() => {
12986
+ setShowQrScanner(true);
12987
+ }, []);
12988
+ const handleQrScannerClose = useCallback(() => {
12989
+ setShowQrScanner(false);
12990
+ }, []);
12991
+ return /* @__PURE__ */ jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsxs(
12992
+ InputWithLabel,
12993
+ {
12994
+ size,
12995
+ severity,
12996
+ inputId,
12997
+ labelId,
12998
+ label: showInputOnly ? label : "",
12999
+ image: showInputOnly ? void 0 : field.image,
13000
+ flexProps: { direction: "column", justify: "start", align: "start", gap: "1" },
13001
+ children: [
13002
+ /* @__PURE__ */ jsx(
13003
+ Overlay,
13004
+ {
13005
+ open: showQrScanner,
13006
+ content: () => /* @__PURE__ */ jsx(QrScanner, { onQrScan: handleQrScan, onClose: handleQrScannerClose }),
13007
+ onOpenChange: setShowQrScanner
13008
+ }
13009
+ ),
13010
+ /* @__PURE__ */ jsxs(Flex, { width: "max-content", gap: "1", align: "center", children: [
13011
+ /* @__PURE__ */ jsxs(Button, { ...rest, variant: "soft", onClick: handleScanButtonClicked, children: [
13012
+ /* @__PURE__ */ jsx(RiIcon, { icon: "RiQrCodeLine" }),
13013
+ "Scan"
13014
+ ] }),
13015
+ value && /* @__PURE__ */ jsx(Text, { color: "jade", size: "1", children: /* @__PURE__ */ jsx(RiIcon, { icon: "RiCheckLine", style: { verticalAlign: "bottom" } }) })
13016
+ ] }),
13017
+ value && /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(Flex, { width: "max-content", gap: "2", align: "center", children: [
13018
+ /* @__PURE__ */ jsx(Code, { color: "gray", highContrast: true, children: value }),
13019
+ /* @__PURE__ */ jsx(
13020
+ IconButton,
13021
+ {
13022
+ severity: "info",
13023
+ variant: "ghost",
13024
+ "aria-label": "delete",
13025
+ size: "small",
13026
+ onClick: handleClearScanResult,
13027
+ children: /* @__PURE__ */ jsx(RiIcon, { icon: "RiCloseLine" })
13028
+ }
13029
+ )
13030
+ ] }) })
13031
+ ]
13032
+ }
13033
+ ) });
13034
+ });
13035
+ QrInput.displayName = "QrInput";
13036
+ const QrScanner = memo((props) => {
13037
+ const { onQrScan, onClose } = props;
13038
+ const videoRef = useRef(null);
13039
+ const [isScannerLoading, setIsScannerLoading] = useState(false);
13040
+ useEffect(() => {
13041
+ if (!videoRef.current)
13042
+ return;
13043
+ const qrScanner = new QrScannerAPI(
13044
+ videoRef.current,
13045
+ (result) => {
13046
+ const data = result.data;
13047
+ onQrScan(data);
13048
+ qrScanner.destroy();
13049
+ },
13050
+ {
13051
+ highlightCodeOutline: true,
13052
+ highlightScanRegion: true,
13053
+ maxScansPerSecond: 1
13054
+ }
13055
+ );
13056
+ setIsScannerLoading(true);
13057
+ qrScanner.start().then(() => {
13058
+ setIsScannerLoading(false);
13059
+ }).catch(() => {
13060
+ setIsScannerLoading(false);
13061
+ });
13062
+ }, [onQrScan]);
13063
+ return /* @__PURE__ */ jsxs(
13064
+ Flex,
13065
+ {
13066
+ className: styles$a.QrScannerWrapper,
13067
+ width: "100%",
13068
+ height: "100%",
13069
+ direction: "column",
13070
+ gap: "2",
13071
+ justify: "center",
13072
+ position: "relative",
13073
+ children: [
13074
+ /* @__PURE__ */ jsx(Flex, { width: "100%", position: "absolute", top: "0", p: "2", children: /* @__PURE__ */ jsx(IconButton, { "aria-label": "close", variant: "soft", severity: "info", highContrast: true, onClick: onClose, children: /* @__PURE__ */ jsx(RiIcon, { icon: "RiCloseLine" }) }) }),
13075
+ /* @__PURE__ */ jsxs(Box, { style: { maxWidth: "100%", maxHeight: "100%" }, position: "relative", children: [
13076
+ /* @__PURE__ */ jsx("video", { ref: videoRef, style: { width: "100%", height: "100%" } }),
13077
+ isScannerLoading && /* @__PURE__ */ jsx(
13078
+ Flex,
13079
+ {
13080
+ position: "absolute",
13081
+ inset: "0",
13082
+ style: { background: "var(--color-background)" },
13083
+ justify: "center",
13084
+ align: "center",
13085
+ children: /* @__PURE__ */ jsx(Spinner, {})
13086
+ }
13087
+ )
13088
+ ] })
13089
+ ]
13090
+ }
13091
+ );
13092
+ });
13093
+ QrScanner.displayName = "QrScanner";
13094
+ const emptyQrField = {
13095
+ ...emptyBaseField,
13096
+ type: "qr"
13097
+ };
13098
+ const _QrField = class _QrField extends BaseField {
13099
+ constructor(options) {
13100
+ super({ ...options, type: "qr" });
13101
+ __publicField(this, "onlyValidateAfterTouched", false);
13102
+ }
13103
+ serialize() {
13104
+ return super._serialize();
13105
+ }
13106
+ static deserialize(data) {
13107
+ if (data.type !== "qr")
13108
+ throw new Error("Type mismatch.");
13109
+ return new _QrField(data);
13110
+ }
13111
+ getInput(props) {
13112
+ return /* @__PURE__ */ jsx(QrInput, { ...props, field: this });
13113
+ }
13114
+ };
13115
+ __publicField(_QrField, "fieldTypeName", "QR");
13116
+ __publicField(_QrField, "fieldTypeDescription", "Used for scanning/reading QR codes.");
13117
+ __publicField(_QrField, "Icon", RiQrCodeLine);
13118
+ let QrField = _QrField;
12498
13119
  const FieldInputCloner = memo((props) => {
12499
13120
  const { field, ...rest } = props;
12500
13121
  const [{ value: identifier }] = useField(field.options.clonedFieldIdentifier);
@@ -13752,6 +14373,7 @@ const FieldTypeToClsMapping = {
13752
14373
  text: TextField,
13753
14374
  custom: CustomField,
13754
14375
  upload: UploadField,
14376
+ qr: QrField,
13755
14377
  // TODO: Underscore
13756
14378
  "multi-string": MultiStringField,
13757
14379
  "multi-select": MultiSelectField
@@ -13765,6 +14387,7 @@ const FieldTypeToEmptyFieldMapping = {
13765
14387
  text: emptyTextField,
13766
14388
  custom: emptyCustomField,
13767
14389
  upload: emptyUploadField,
14390
+ qr: emptyQrField,
13768
14391
  // TODO: Underscore
13769
14392
  "multi-string": emptyMultiStringField,
13770
14393
  "multi-select": emptyMultiSelectField
@@ -13852,7 +14475,7 @@ const FieldSectionLayout = memo((props) => {
13852
14475
  return /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(Flex$1, { direction: "column", gap: "3", children: [
13853
14476
  /* @__PURE__ */ jsxs(Flex$1, { direction: "column", children: [
13854
14477
  /* @__PURE__ */ jsx(Heading, { as: "h3", size: "3", children: label }),
13855
- /* @__PURE__ */ jsx(Text$1, { className: styles$b.description, children: description2 })
14478
+ /* @__PURE__ */ jsx(Text$1, { className: styles$c.description, children: description2 })
13856
14479
  ] }),
13857
14480
  inputs
13858
14481
  ] }) });
@@ -14039,7 +14662,7 @@ const initialFormValues = (fields, values) => {
14039
14662
  };
14040
14663
  const useAttachImagesToFormRevisionFields = (revision) => {
14041
14664
  const { sdk } = useSDK();
14042
- const attachments = useAppSelector(selectRevisionAttachments((revision == null ? void 0 : revision.offline_id) ?? ""));
14665
+ const attachments = useAppSelector(selectAttachmentsOfFormRevision((revision == null ? void 0 : revision.offline_id) ?? ""));
14043
14666
  return useMemo(() => {
14044
14667
  if (!revision || !attachments)
14045
14668
  return revision;
@@ -14095,7 +14718,7 @@ const FormRenderer = memo(
14095
14718
  [schema.title]
14096
14719
  );
14097
14720
  const Description = useMemo(
14098
- () => typeof schema.description === "string" ? /* @__PURE__ */ jsx(Text$1, { className: styles$b.description, children: schema.description }) : schema.description,
14721
+ () => typeof schema.description === "string" ? /* @__PURE__ */ jsx(Text$1, { className: styles$c.description, children: schema.description }) : schema.description,
14099
14722
  [schema.description]
14100
14723
  );
14101
14724
  const inputs = useFieldInputs(schema.fields, { formId: formId2, disabled: readonly });
@@ -14111,7 +14734,7 @@ const FormRenderer = memo(
14111
14734
  !hideDescription && Description
14112
14735
  ] }) }),
14113
14736
  inputs,
14114
- !readonly && /* @__PURE__ */ jsxs(Flex$1, { className: styles$b.floatingButtonContainer, align: "center", justify: "end", gap: "2", children: [
14737
+ !readonly && /* @__PURE__ */ jsxs(Flex$1, { className: styles$c.floatingButtonContainer, align: "center", justify: "end", gap: "2", children: [
14115
14738
  cancelText && /* @__PURE__ */ jsx(Button, { severity: "info", ...buttonProps, type: "button", onClick: onCancel, children: cancelText }),
14116
14739
  /* @__PURE__ */ jsx(Button, { ...buttonProps, type: "submit", disabled: !formik.isValid, children: submitText })
14117
14740
  ] })
@@ -14136,7 +14759,7 @@ const FormSubmissionViewer = memo(
14136
14759
  return formRevisionToSchema(revisionWithImages, { readonly: true });
14137
14760
  }, [revisionWithImages]);
14138
14761
  const submissionValuesWithAttachments = useMemo(() => {
14139
- const attachments = selectSubmissionAttachments(submission.offline_id)(sdk.store.getState()) ?? [];
14762
+ const attachments = selectAttachmentsOfFormSubmission(submission.offline_id)(sdk.store.getState()) ?? [];
14140
14763
  const downloadedAttachments = {};
14141
14764
  for (const attachment of attachments) {
14142
14765
  const promise = sdk.files.fetchFileFromUrl(attachment.file, attachment.file_sha1, attachment.file_name);
@@ -14186,8 +14809,8 @@ const FormBrowser = memo(
14186
14809
  }
14187
14810
  return ret;
14188
14811
  }, [filter, maxResults, ownerFilter]);
14189
- const userForms = useAppSelector(selectFilteredUserForms(ownerFilterOptions)) ?? [];
14190
- const userFormMapping = useAppSelector(selectUserFormMapping);
14812
+ const userForms = useAppSelector(selectFilteredForms(ownerFilterOptions)) ?? [];
14813
+ const userFormMapping = useAppSelector(selectFormMapping);
14191
14814
  const attachableUserForms = userForms.filter((form) => !form.component_type);
14192
14815
  const attachableUserFormMapping = Object.values(userFormMapping).filter(
14193
14816
  (form) => !form.component_type
@@ -14220,7 +14843,7 @@ const FormBrowser = memo(
14220
14843
  const handleChange = useCallback((e) => {
14221
14844
  setFilter(e.currentTarget.value);
14222
14845
  }, []);
14223
- const numberOfForms = useAppSelector(selectNumberOfGeneralUserForms) || 0;
14846
+ const numberOfForms = useAppSelector(selectGeneralFormCount) || 0;
14224
14847
  const numberOfHiddenForms = numberOfForms - attachableUserForms.length;
14225
14848
  const overflowMessage = attachableUserForms.length == maxResults && numberOfHiddenForms > 0 ? `Only the first ${maxResults} results are shown (${numberOfHiddenForms} hidden)` : numberOfHiddenForms > 0 && `${numberOfHiddenForms} hidden forms`;
14226
14849
  return /* @__PURE__ */ jsxs(Flex$1, { ref, direction: "column", gap: "2", children: [
@@ -14314,16 +14937,13 @@ const FormSubmissionBrowserEntry = memo((props) => {
14314
14937
  const { submission, onSubmissionClick, compact, labelType, rowDecorator } = props;
14315
14938
  const currentUser = useAppSelector(selectCurrentUser);
14316
14939
  const createdBy = useAppSelector(selectUser("created_by" in submission ? submission.created_by : currentUser.id));
14317
- const dateToUse = getCreatedAtOrSubmittedAtDate(submission);
14318
- const formattedDateTime = isToday(dateToUse) ? dateToUse.toLocaleTimeString([], {
14319
- hour: "2-digit",
14320
- minute: "2-digit"
14321
- }) : getLocalDateString(dateToUse);
14940
+ const dateToUse = submission.submitted_at;
14941
+ const formattedDateTime = getLocalDateString(dateToUse);
14322
14942
  const revision = useAppSelector(selectFormRevision(submission.form_revision));
14323
14943
  if (!revision) {
14324
14944
  throw new Error(`Could not find revision ${submission.form_revision} for submission ${submission.offline_id}.`);
14325
14945
  }
14326
- const latestRevisionNumber = (_a2 = useAppSelector(selectLatestFormRevision(revision.form))) == null ? void 0 : _a2.revision;
14946
+ const latestRevisionNumber = (_a2 = useAppSelector(selectLatestFormRevisionOfForm(revision.form))) == null ? void 0 : _a2.revision;
14327
14947
  const creatorProfileSrc = useFileSrc({
14328
14948
  file: (createdBy == null ? void 0 : createdBy.profile.file) ?? null,
14329
14949
  fileSha1: (createdBy == null ? void 0 : createdBy.profile.file_sha1) ?? null
@@ -14354,10 +14974,6 @@ const FormSubmissionBrowserEntry = memo((props) => {
14354
14974
  return row;
14355
14975
  });
14356
14976
  FormSubmissionBrowserEntry.displayName = "FormSubmissionBrowserEntry";
14357
- const getCreatedAtOrSubmittedAtDate = (submission) => {
14358
- const date = "created_at" in submission ? submission.created_at : submission.submitted_at;
14359
- return new Date(date);
14360
- };
14361
14977
  const FormSubmissionBrowser = memo((props) => {
14362
14978
  const {
14363
14979
  formId: formId2,
@@ -14371,10 +14987,10 @@ const FormSubmissionBrowser = memo((props) => {
14371
14987
  if (!!formId2 === !!propSubmissions) {
14372
14988
  throw new Error("Either formId or submissions must be provided, but not both.");
14373
14989
  }
14374
- const submissions = useAppSelector(propSubmissions ? () => propSubmissions : selectSubmissionsForForm(formId2));
14990
+ const submissions = useAppSelector(propSubmissions ? () => propSubmissions : selectFormSubmissionsOfForm(formId2));
14375
14991
  const sortedSubmissions = useMemo(
14376
14992
  () => submissions == null ? void 0 : submissions.sort((a, b) => {
14377
- return getCreatedAtOrSubmittedAtDate(b).getTime() - getCreatedAtOrSubmittedAtDate(a).getTime();
14993
+ return a.submitted_at.localeCompare(b.submitted_at);
14378
14994
  }),
14379
14995
  [submissions]
14380
14996
  );
@@ -15466,12 +16082,12 @@ const FormBuilder = memo(
15466
16082
  });
15467
16083
  const previewSchema = useMemo(() => formRevisionToSchema(formik.values), [formik.values]);
15468
16084
  return /* @__PURE__ */ jsx(Tabs.Root, { ref, defaultValue: "edit", children: /* @__PURE__ */ jsxs(Flex$1, { direction: "column", gap: "2", children: [
15469
- showTabs && /* @__PURE__ */ jsxs(Tabs.List, { className: classNames$1(styles$c.tabsList, tabsListClassName), children: [
15470
- /* @__PURE__ */ jsx(Tabs.Trigger, { className: styles$c.tabTrigger, value: "edit", children: /* @__PURE__ */ jsxs(Flex$1, { align: "center", gap: "2", children: [
16085
+ showTabs && /* @__PURE__ */ jsxs(Tabs.List, { className: classNames$1(styles$d.tabsList, tabsListClassName), children: [
16086
+ /* @__PURE__ */ jsx(Tabs.Trigger, { className: styles$d.tabTrigger, value: "edit", children: /* @__PURE__ */ jsxs(Flex$1, { align: "center", gap: "2", children: [
15471
16087
  /* @__PURE__ */ jsx(RiIcon, { icon: "RiPencilLine" }),
15472
16088
  "Edit"
15473
16089
  ] }) }),
15474
- /* @__PURE__ */ jsx(Tabs.Trigger, { className: styles$c.tabTrigger, value: "preview", children: /* @__PURE__ */ jsxs(Flex$1, { align: "center", gap: "2", children: [
16090
+ /* @__PURE__ */ jsx(Tabs.Trigger, { className: styles$d.tabTrigger, value: "preview", children: /* @__PURE__ */ jsxs(Flex$1, { align: "center", gap: "2", children: [
15475
16091
  /* @__PURE__ */ jsx(RiIcon, { icon: "RiEyeLine" }),
15476
16092
  "Preview"
15477
16093
  ] }) })
@@ -15495,8 +16111,8 @@ const FormBuilder = memo(
15495
16111
  render: ({ setValue, value, meta }) => /* @__PURE__ */ jsx(InputWithHelpText, { severity: "danger", helpText: meta.error ?? null, children: /* @__PURE__ */ jsx(
15496
16112
  Input,
15497
16113
  {
15498
- className: classNames$1(styles$c.title, {
15499
- [styles$c.error]: meta.error
16114
+ className: classNames$1(styles$d.title, {
16115
+ [styles$d.error]: meta.error
15500
16116
  }),
15501
16117
  placeholder: "Form title",
15502
16118
  value,
@@ -15518,7 +16134,7 @@ const FormBuilder = memo(
15518
16134
  render: ({ setValue, value }) => /* @__PURE__ */ jsx(
15519
16135
  TextArea,
15520
16136
  {
15521
- className: styles$c.description,
16137
+ className: styles$d.description,
15522
16138
  placeholder: "Explain the purpose of this form",
15523
16139
  value,
15524
16140
  onChange: (event) => {
@@ -15536,7 +16152,7 @@ const FormBuilder = memo(
15536
16152
  /* @__PURE__ */ jsx(FieldsEditor, { fieldsOnly }),
15537
16153
  /* @__PURE__ */ jsx(Text$1, { severity: "danger", size: "1", children: typeof formik.errors.fields === "string" && formik.errors.fields })
15538
16154
  ] }),
15539
- /* @__PURE__ */ jsxs(Flex$1, { className: styles$c.floatingButtonContainer, align: "center", justify: "end", gap: "2", children: [
16155
+ /* @__PURE__ */ jsxs(Flex$1, { className: styles$d.floatingButtonContainer, align: "center", justify: "end", gap: "2", children: [
15540
16156
  onCancel && /* @__PURE__ */ jsx(Button, { type: "button", variant: "solid", severity: "info", onClick: onCancel, children: "Cancel" }),
15541
16157
  /* @__PURE__ */ jsx(Button, { type: "submit", children: "Save form" })
15542
16158
  ] })
@@ -15571,6 +16187,9 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
15571
16187
  NumberInput,
15572
16188
  PatchField,
15573
16189
  PatchFormProvider,
16190
+ QrField,
16191
+ QrInput,
16192
+ QrScanner,
15574
16193
  SelectField,
15575
16194
  SelectInput,
15576
16195
  StringField,
@@ -15585,6 +16204,7 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
15585
16204
  emptyMultiSelectField,
15586
16205
  emptyMultiStringField,
15587
16206
  emptyNumberField,
16207
+ emptyQrField,
15588
16208
  emptySelectField,
15589
16209
  emptyStringField,
15590
16210
  emptyTextField,
@@ -15675,6 +16295,9 @@ export {
15675
16295
  ProjectFileService,
15676
16296
  ProjectService,
15677
16297
  ProjectType,
16298
+ QrField,
16299
+ QrInput,
16300
+ QrScanner,
15678
16301
  SDKContext,
15679
16302
  SDKProvider,
15680
16303
  SUPPORTED_IMAGE_FILE_TYPES,
@@ -15685,6 +16308,7 @@ export {
15685
16308
  SpreadsheetViewer,
15686
16309
  StringField,
15687
16310
  StringInput,
16311
+ TeamService,
15688
16312
  TextField,
15689
16313
  TextInput,
15690
16314
  UserFormService,
@@ -15692,6 +16316,7 @@ export {
15692
16316
  VerificationCodeType,
15693
16317
  WorkspaceService,
15694
16318
  YELLOW,
16319
+ _selectLatestFormRevision,
15695
16320
  _setLatestRetryTime,
15696
16321
  acceptProjectInvite,
15697
16322
  addActiveProjectFormSubmissionsCount,
@@ -15709,6 +16334,16 @@ export {
15709
16334
  addDocuments,
15710
16335
  addEmailDomain,
15711
16336
  addFavouriteProjectId,
16337
+ addForm,
16338
+ addFormRevision,
16339
+ addFormRevisionAttachment,
16340
+ addFormRevisionAttachments,
16341
+ addFormRevisions,
16342
+ addFormSubmission,
16343
+ addFormSubmissionAttachment,
16344
+ addFormSubmissionAttachments,
16345
+ addFormSubmissions,
16346
+ addForms,
15712
16347
  addIssue,
15713
16348
  addIssueAttachment,
15714
16349
  addIssueAttachments,
@@ -15728,14 +16363,8 @@ export {
15728
16363
  addStageCompletion,
15729
16364
  addStageCompletions,
15730
16365
  addStages,
16366
+ addTeam,
15731
16367
  addToRecentIssues,
15732
- addUserForm,
15733
- addUserFormRevision,
15734
- addUserFormRevisionAttachment,
15735
- addUserFormRevisions,
15736
- addUserFormSubmissionAttachment,
15737
- addUserFormSubmissions,
15738
- addUserForms,
15739
16368
  addUsers,
15740
16369
  addWorkspace,
15741
16370
  areArraysEqual,
@@ -15756,6 +16385,7 @@ export {
15756
16385
  componentStageSlice,
15757
16386
  componentTypeReducer,
15758
16387
  componentTypeSlice,
16388
+ constructUploadedFilePayloads,
15759
16389
  coordinatesAreEqual,
15760
16390
  coordinatesToLiteral,
15761
16391
  coordinatesToPointGeometry,
@@ -15766,12 +16396,17 @@ export {
15766
16396
  defaultBadgeColor,
15767
16397
  defaultStore,
15768
16398
  deleteComponentType,
16399
+ deleteForm,
16400
+ deleteFormRevision,
16401
+ deleteFormRevisionAttachment,
16402
+ deleteFormRevisionAttachments,
16403
+ deleteFormRevisions,
16404
+ deleteFormSubmission,
16405
+ deleteFormSubmissionAttachment,
16406
+ deleteFormSubmissionAttachments,
16407
+ deleteFormSubmissions,
15769
16408
  deleteProject,
15770
- deleteUserForm,
15771
- deleteUserFormRevision,
15772
- deleteUserFormRevisions,
15773
- deleteUserFormSubmission,
15774
- deleteUserFormSubmissions,
16409
+ deleteTeam,
15775
16410
  dequeue,
15776
16411
  deserialize,
15777
16412
  deserializeField,
@@ -15789,6 +16424,7 @@ export {
15789
16424
  emptyMultiSelectField,
15790
16425
  emptyMultiStringField,
15791
16426
  emptyNumberField,
16427
+ emptyQrField,
15792
16428
  emptySelectField,
15793
16429
  emptyStringField,
15794
16430
  emptyTextField,
@@ -15800,7 +16436,13 @@ export {
15800
16436
  fileSlice,
15801
16437
  fileToBlob,
15802
16438
  flipCoordinates,
16439
+ formReducer,
16440
+ formRevisionReducer,
15803
16441
  formRevisionToSchema,
16442
+ formRevisionsSlice,
16443
+ formSlice,
16444
+ formSubmissionReducer,
16445
+ formSubmissionSlice,
15804
16446
  index as forms,
15805
16447
  fullComponentMarkerSize,
15806
16448
  generateBadgeColors,
@@ -15928,6 +16570,8 @@ export {
15928
16570
  selectAttachmentsOfComponentTypeByType,
15929
16571
  selectAttachmentsOfDocument,
15930
16572
  selectAttachmentsOfDocumentByType,
16573
+ selectAttachmentsOfFormRevision,
16574
+ selectAttachmentsOfFormSubmission,
15931
16575
  selectAttachmentsOfIssue,
15932
16576
  selectAttachmentsOfIssueByType,
15933
16577
  selectAttachmentsOfProject,
@@ -15945,11 +16589,9 @@ export {
15945
16589
  selectComponent,
15946
16590
  selectComponentAttachment,
15947
16591
  selectComponentAttachmentMapping,
15948
- selectComponentSubmissionMapping,
15949
16592
  selectComponentType,
15950
16593
  selectComponentTypeAttachment,
15951
16594
  selectComponentTypeAttachmentMapping,
15952
- selectComponentTypeForm,
15953
16595
  selectComponentTypeFromComponent,
15954
16596
  selectComponentTypeFromComponents,
15955
16597
  selectComponentTypeStagesMapping,
@@ -15979,8 +16621,24 @@ export {
15979
16621
  selectExpandedSections,
15980
16622
  selectFavouriteProjects,
15981
16623
  selectFileAttachmentsOfIssue,
15982
- selectFilteredUserForms,
16624
+ selectFilteredForms,
16625
+ selectForm,
16626
+ selectFormMapping,
16627
+ selectFormOfComponentType,
15983
16628
  selectFormRevision,
16629
+ selectFormRevisionMapping,
16630
+ selectFormRevisions,
16631
+ selectFormRevisionsOfForm,
16632
+ selectFormSubmission,
16633
+ selectFormSubmissionAttachmentsMapping,
16634
+ selectFormSubmissions,
16635
+ selectFormSubmissionsByComponents,
16636
+ selectFormSubmissionsMapping,
16637
+ selectFormSubmissionsOfComponent,
16638
+ selectFormSubmissionsOfForm,
16639
+ selectFormSubmissionsOfIssue,
16640
+ selectFormsCount,
16641
+ selectGeneralFormCount,
15984
16642
  selectHiddenCategoryCount,
15985
16643
  selectHiddenComponentTypeIds,
15986
16644
  selectIsFetchingInitialData,
@@ -15995,10 +16653,10 @@ export {
15995
16653
  selectIssueUpdateMapping,
15996
16654
  selectIssueUpdatesOfIssue,
15997
16655
  selectIssues,
15998
- selectLatestFormRevision,
16656
+ selectLatestFormRevisionByForm,
16657
+ selectLatestFormRevisionOfForm,
16658
+ selectLatestFormRevisionsOfComponentTypes,
15999
16659
  selectLatestRetryTime,
16000
- selectLatestRevisionByFormId,
16001
- selectLatestRevisionsFromComponentTypeIds,
16002
16660
  selectLicense,
16003
16661
  selectLicenseForProject,
16004
16662
  selectLicenses,
@@ -16007,8 +16665,6 @@ export {
16007
16665
  selectMapStyle,
16008
16666
  selectNumberOfComponentTypesMatchingCaseInsensitiveName,
16009
16667
  selectNumberOfComponentsOfComponentType,
16010
- selectNumberOfGeneralUserForms,
16011
- selectNumberOfUserForms,
16012
16668
  selectOrganization,
16013
16669
  selectOrganizationAccess,
16014
16670
  selectOrganizationAccessForUser,
@@ -16036,8 +16692,6 @@ export {
16036
16692
  selectRecentIssuesAsSearchResults,
16037
16693
  selectRecentProjects,
16038
16694
  selectRehydrated,
16039
- selectRevisionAttachments,
16040
- selectRevisionsForForm,
16041
16695
  selectRootDocuments,
16042
16696
  selectShowTooltips,
16043
16697
  selectSortedEmailDomains,
@@ -16052,16 +16706,15 @@ export {
16052
16706
  selectStagesFromComponentType,
16053
16707
  selectStagesFromComponentTypeIds,
16054
16708
  selectStagesFromStageIds,
16055
- selectSubmissionAttachments,
16056
- selectSubmissionsForComponent,
16057
- selectSubmissionsForForm,
16058
- selectSubmissionsForIssue,
16709
+ selectTeam,
16710
+ selectTeams,
16711
+ selectTeamsMapping,
16712
+ selectTeamsOfOrganization,
16713
+ selectTeamsOfUser,
16059
16714
  selectUploadUrl,
16060
16715
  selectUsedColors,
16061
16716
  selectUser,
16062
- selectUserForm,
16063
- selectUserFormMapping,
16064
- selectUserFormSubmission,
16717
+ selectUserFormRevisionAttachmentsMapping,
16065
16718
  selectUsersAsMapping,
16066
16719
  selectVisibleStatuses,
16067
16720
  selectVisibleUserIds,
@@ -16088,6 +16741,13 @@ export {
16088
16741
  setEnableClustering,
16089
16742
  setEnableDuplicateIssues,
16090
16743
  setEnablePlacementMode,
16744
+ setFormRevision,
16745
+ setFormRevisionAttachments,
16746
+ setFormRevisions,
16747
+ setFormSubmission,
16748
+ setFormSubmissionAttachments,
16749
+ setFormSubmissions,
16750
+ setForms,
16091
16751
  setIsFetchingInitialData,
16092
16752
  setIsImportingProjectFile,
16093
16753
  setIsLoading,
@@ -16109,12 +16769,11 @@ export {
16109
16769
  setSectionExpanded,
16110
16770
  setShowTooltips,
16111
16771
  setStageCompletions,
16772
+ setTeam,
16773
+ setTeams,
16112
16774
  setTokens,
16113
16775
  setTourStep,
16114
16776
  setUploadUrl,
16115
- setUserFormRevisionAttachments,
16116
- setUserFormSubmissionAttachments,
16117
- setUserFormSubmissions,
16118
16777
  setUsers,
16119
16778
  setVisibleStatuses,
16120
16779
  setVisibleUserIds,
@@ -16125,6 +16784,8 @@ export {
16125
16784
  slugify,
16126
16785
  spacesToDashesLower,
16127
16786
  successColor,
16787
+ teamReducer,
16788
+ teamSlice,
16128
16789
  toFileNameSafeString,
16129
16790
  toOfflineIdRecord,
16130
16791
  toggleComponentTypeVisibility,
@@ -16139,15 +16800,18 @@ export {
16139
16800
  updateComponentTypeAttachment,
16140
16801
  updateDocumentAttachment,
16141
16802
  updateDocuments,
16803
+ updateFormSubmission,
16804
+ updateFormSubmissionAttachments,
16805
+ updateFormSubmissions,
16142
16806
  updateIssue,
16143
16807
  updateIssueAttachment,
16144
16808
  updateLicense,
16145
16809
  updateOrCreateProject,
16146
- updateOrCreateUserFormSubmission,
16147
16810
  updateOrganizationAccess,
16148
16811
  updateProjectAccess,
16149
16812
  updateProjectAttachment,
16150
16813
  updateStages,
16814
+ updateTeam,
16151
16815
  useAppDispatch,
16152
16816
  useAppSelector,
16153
16817
  useFieldInput,
@@ -16157,8 +16821,6 @@ export {
16157
16821
  useFormikInput,
16158
16822
  useMemoCompare,
16159
16823
  useSDK,
16160
- userFormReducer,
16161
- userFormSlice,
16162
16824
  userReducer,
16163
16825
  userSlice,
16164
16826
  valueIsFile,