@overmap-ai/core 1.0.44-tiptap.8 → 1.0.45-batch-bug-fixes.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -632,15 +632,15 @@ const wrapMigration = (migrator) => (state) => {
632
632
  };
633
633
  const migrations = [initialVersioning, signOut, signOut, createOutboxState];
634
634
  const manifest = Object.fromEntries(migrations.map((migration2, i) => [i, wrapMigration(migration2)]));
635
- const initialState$l = {
635
+ const initialState$m = {
636
636
  accessToken: "",
637
637
  refreshToken: "",
638
638
  isLoggedIn: false
639
639
  };
640
640
  const authSlice = createSlice({
641
641
  name: "auth",
642
- initialState: initialState$l,
643
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$l)),
642
+ initialState: initialState$m,
643
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$m)),
644
644
  reducers: {
645
645
  setTokens: (state, action) => {
646
646
  state.accessToken = action.payload.accessToken;
@@ -1371,7 +1371,7 @@ const getLocalRelativeDateString = memoize((date, min, max) => {
1371
1371
  return getLocalDateString(date);
1372
1372
  return relative.format(days, "days");
1373
1373
  });
1374
- const initialState$k = {
1374
+ const initialState$l = {
1375
1375
  categories: {},
1376
1376
  usedCategoryColors: [],
1377
1377
  categoryVisibility: {
@@ -1381,8 +1381,8 @@ const initialState$k = {
1381
1381
  };
1382
1382
  const categorySlice = createSlice({
1383
1383
  name: "categories",
1384
- initialState: initialState$k,
1385
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$k)),
1384
+ initialState: initialState$l,
1385
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$l)),
1386
1386
  reducers: {
1387
1387
  setCategories: (state, action) => {
1388
1388
  if (!Array.isArray(action.payload))
@@ -1550,14 +1550,14 @@ function removeAttachments(state, action) {
1550
1550
  delete state.attachments[attachmentId];
1551
1551
  }
1552
1552
  }
1553
- const initialState$j = {
1553
+ const initialState$k = {
1554
1554
  components: {},
1555
1555
  attachments: {}
1556
1556
  };
1557
1557
  const componentSlice = createSlice({
1558
1558
  name: "components",
1559
- initialState: initialState$j,
1560
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$j)),
1559
+ initialState: initialState$k,
1560
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$k)),
1561
1561
  reducers: {
1562
1562
  addComponent: (state, action) => {
1563
1563
  state.components[action.payload.offline_id] = action.payload;
@@ -1675,7 +1675,7 @@ const selectAttachmentsOfComponent = restructureCreateSelectorWithArgs(
1675
1675
  createSelector(
1676
1676
  [selectAllComponentAttachments, (_state, componentId) => componentId],
1677
1677
  (attachments, componentId) => {
1678
- return attachments.filter(({ component_id }) => componentId === component_id);
1678
+ return attachments.filter(({ component }) => componentId === component);
1679
1679
  }
1680
1680
  )
1681
1681
  );
@@ -1683,7 +1683,7 @@ const selectAttachmentsOfComponentByType = restructureCreateSelectorWithArgs(
1683
1683
  createSelector(
1684
1684
  [selectAllComponentAttachments, (_state, componentId) => componentId],
1685
1685
  (attachments, componentId) => {
1686
- const attachmentsOfComponent = attachments.filter(({ component_id }) => componentId === component_id);
1686
+ const attachmentsOfComponent = attachments.filter(({ component }) => componentId === component);
1687
1687
  const fileAttachments = attachmentsOfComponent.filter(
1688
1688
  // this null check here is necessary, there are cases where file_type is null or undefined
1689
1689
  ({ file_type }) => !file_type || !file_type.startsWith("image/")
@@ -1711,13 +1711,13 @@ const {
1711
1711
  removeAllComponentsOfType
1712
1712
  } = componentSlice.actions;
1713
1713
  const componentReducer = componentSlice.reducer;
1714
- const initialState$i = {
1714
+ const initialState$j = {
1715
1715
  completionsByComponentId: {}
1716
1716
  };
1717
1717
  const componentStageCompletionSlice = createSlice({
1718
1718
  name: "componentStageCompletions",
1719
- initialState: initialState$i,
1720
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$i)),
1719
+ initialState: initialState$j,
1720
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$j)),
1721
1721
  reducers: {
1722
1722
  addStageCompletion: (state, action) => {
1723
1723
  let stageToCompletionDateMapping = state.completionsByComponentId[action.payload.component];
@@ -1768,13 +1768,13 @@ const selectCompletedStageIdsForComponent = (component) => (state) => {
1768
1768
  return Object.keys(state.componentStageCompletionReducer.completionsByComponentId[component.offline_id] ?? {});
1769
1769
  };
1770
1770
  const componentStageCompletionReducer = componentStageCompletionSlice.reducer;
1771
- const initialState$h = {
1771
+ const initialState$i = {
1772
1772
  stages: {}
1773
1773
  };
1774
1774
  const componentStageSlice = createSlice({
1775
1775
  name: "componentStages",
1776
- initialState: initialState$h,
1777
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$h)),
1776
+ initialState: initialState$i,
1777
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$i)),
1778
1778
  reducers: {
1779
1779
  addStages: (state, action) => {
1780
1780
  Object.assign(state.stages, toOfflineIdRecord(action.payload));
@@ -1865,15 +1865,15 @@ const selectStageFormIdsFromStageIds = restructureCreateSelectorWithArgs(
1865
1865
  );
1866
1866
  const { addStages, updateStages, removeStages, linkStageToForm, unlinkStageToForm } = componentStageSlice.actions;
1867
1867
  const componentStageReducer = componentStageSlice.reducer;
1868
- const initialState$g = {
1868
+ const initialState$h = {
1869
1869
  componentTypes: {},
1870
1870
  hiddenComponentTypeIds: {},
1871
1871
  attachments: {}
1872
1872
  };
1873
1873
  const componentTypeSlice = createSlice({
1874
1874
  name: "componentTypes",
1875
- initialState: initialState$g,
1876
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$g)),
1875
+ initialState: initialState$h,
1876
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$h)),
1877
1877
  reducers: {
1878
1878
  addComponentType: (state, action) => {
1879
1879
  state.componentTypes[action.payload.offline_id] = action.payload;
@@ -1945,7 +1945,7 @@ const selectAttachmentsOfComponentType = restructureCreateSelectorWithArgs(
1945
1945
  createSelector(
1946
1946
  [selectAllComponentTypeAttachments, (_state, componentTypeId) => componentTypeId],
1947
1947
  (attachments, componentTypeId) => {
1948
- return attachments.filter(({ component_type_id }) => componentTypeId === component_type_id);
1948
+ return attachments.filter(({ component_type }) => componentTypeId === component_type);
1949
1949
  }
1950
1950
  )
1951
1951
  );
@@ -1954,7 +1954,7 @@ const selectAttachmentsOfComponentTypeByType = restructureCreateSelectorWithArgs
1954
1954
  [selectAllComponentTypeAttachments, (_state, componentTypeId) => componentTypeId],
1955
1955
  (attachments, componentTypeId) => {
1956
1956
  const attachmentsOfComponent = attachments.filter(
1957
- ({ component_type_id }) => component_type_id === componentTypeId
1957
+ ({ component_type }) => component_type === componentTypeId
1958
1958
  );
1959
1959
  const fileAttachments = attachmentsOfComponent.filter(
1960
1960
  // this null check here is necessary, there are cases where file_type is null or undefined
@@ -1981,13 +1981,13 @@ const {
1981
1981
  deleteComponentType
1982
1982
  } = componentTypeSlice.actions;
1983
1983
  const componentTypeReducer = componentTypeSlice.reducer;
1984
- const initialState$f = {
1984
+ const initialState$g = {
1985
1985
  workspaces: {},
1986
1986
  activeWorkspaceId: null
1987
1987
  };
1988
1988
  const workspaceSlice = createSlice({
1989
1989
  name: "workspace",
1990
- initialState: initialState$f,
1990
+ initialState: initialState$g,
1991
1991
  // The `reducers` field lets us define reducers and generate associated actions
1992
1992
  reducers: {
1993
1993
  setWorkspaces: (state, action) => {
@@ -2044,21 +2044,20 @@ const selectPermittedWorkspaceIds = createSelector(
2044
2044
  );
2045
2045
  const workspaceReducer = workspaceSlice.reducer;
2046
2046
  const maxRecentIssues = 10;
2047
- const initialState$e = {
2047
+ const initialState$f = {
2048
2048
  issues: {},
2049
2049
  attachments: {},
2050
2050
  comments: {},
2051
2051
  visibleStatuses: [IssueStatus.BACKLOG, IssueStatus.SELECTED],
2052
- isFetchingInitialData: false,
2053
2052
  visibleUserIds: null,
2054
2053
  recentIssueIds: [],
2055
2054
  activeIssueId: null
2056
2055
  };
2057
2056
  const issueSlice = createSlice({
2058
2057
  name: "issues",
2059
- initialState: initialState$e,
2058
+ initialState: initialState$f,
2060
2059
  extraReducers: (builder) => builder.addCase("RESET", (state) => {
2061
- Object.assign(state, initialState$e);
2060
+ Object.assign(state, initialState$f);
2062
2061
  }),
2063
2062
  reducers: {
2064
2063
  setIssues: (state, action) => {
@@ -2104,7 +2103,7 @@ const issueSlice = createSlice({
2104
2103
  },
2105
2104
  removeIssueAttachment: removeAttachment,
2106
2105
  removeAttachmentsOfIssue: (state, action) => {
2107
- const attachments = Object.values(state.attachments).filter((a) => a.issue_id === action.payload);
2106
+ const attachments = Object.values(state.attachments).filter((a) => a.issue === action.payload);
2108
2107
  for (const attachment of attachments) {
2109
2108
  delete state.attachments[attachment.offline_id];
2110
2109
  }
@@ -2112,9 +2111,6 @@ const issueSlice = createSlice({
2112
2111
  setVisibleStatuses: (state, action) => {
2113
2112
  state.visibleStatuses = action.payload;
2114
2113
  },
2115
- setIsFetchingInitialData: (state, action) => {
2116
- state.isFetchingInitialData = action.payload;
2117
- },
2118
2114
  setVisibleUserIds: (state, action) => {
2119
2115
  state.visibleUserIds = [...new Set(action.payload)];
2120
2116
  },
@@ -2173,7 +2169,6 @@ const {
2173
2169
  resetRecentIssues,
2174
2170
  setActiveIssueId,
2175
2171
  setIssueAttachments,
2176
- setIsFetchingInitialData,
2177
2172
  setIssueComments,
2178
2173
  setIssues,
2179
2174
  setVisibleStatuses,
@@ -2239,7 +2234,7 @@ const selectPhotoAttachmentsOfIssue = restructureCreateSelectorWithArgs(
2239
2234
  [selectIssueAttachmentMapping, (_state, issueId) => issueId],
2240
2235
  (attachmentMapping, issueId) => {
2241
2236
  return Object.values(attachmentMapping).filter(
2242
- (attachment) => attachment.issue_id === issueId && attachment.file_type && attachment.file_type.startsWith("image/")
2237
+ (attachment) => attachment.issue === issueId && attachment.file_type && attachment.file_type.startsWith("image/")
2243
2238
  );
2244
2239
  }
2245
2240
  )
@@ -2254,7 +2249,7 @@ const selectAttachmentsOfIssue = restructureCreateSelectorWithArgs(
2254
2249
  createSelector(
2255
2250
  [selectIssueAttachments, (_state, issueId) => issueId],
2256
2251
  (attachments, issueId) => {
2257
- return attachments.filter(({ issue_id }) => issueId === issue_id);
2252
+ return attachments.filter(({ issue }) => issueId === issue);
2258
2253
  }
2259
2254
  )
2260
2255
  );
@@ -2262,12 +2257,12 @@ const selectAttachmentsOfIssueByType = restructureCreateSelectorWithArgs(
2262
2257
  createSelector(
2263
2258
  [selectIssueAttachments, (_state, issueId) => issueId],
2264
2259
  (attachments, issueId) => {
2265
- const attachmentsOfComponent = attachments.filter(({ issue_id }) => issue_id === issueId);
2266
- const fileAttachments = attachmentsOfComponent.filter(
2260
+ const attachmentsOfIssue = attachments.filter(({ issue }) => issue === issueId);
2261
+ const fileAttachments = attachmentsOfIssue.filter(
2267
2262
  // this null check here is necessary, there are cases where file_type is null or undefined
2268
2263
  ({ file_type }) => !file_type || !file_type.startsWith("image/")
2269
2264
  );
2270
- const imageAttachments = attachmentsOfComponent.filter(
2265
+ const imageAttachments = attachmentsOfIssue.filter(
2271
2266
  // this null check here is necessary, there are cases where file_type is null or undefined
2272
2267
  ({ file_type }) => file_type && file_type.startsWith("image/")
2273
2268
  );
@@ -2284,7 +2279,7 @@ const selectFileAttachmentsOfIssue = restructureCreateSelectorWithArgs(
2284
2279
  return Object.values(attachmentMapping).filter(
2285
2280
  (attachment) => (
2286
2281
  // Files with file_type that is null or not an image file
2287
- attachment.issue_id === issueId && (!attachment.file_type || !attachment.file_type.startsWith("image/"))
2282
+ attachment.issue === issueId && (!attachment.file_type || !attachment.file_type.startsWith("image/"))
2288
2283
  )
2289
2284
  );
2290
2285
  }
@@ -2295,7 +2290,6 @@ const selectIssue = restructureCreateSelectorWithArgs(
2295
2290
  return mapping[id];
2296
2291
  })
2297
2292
  );
2298
- const selectIsFetchingInitialData = (state) => state.issueReducer.isFetchingInitialData;
2299
2293
  const selectAllAttachments = createSelector([selectIssueAttachmentMapping], (mapping) => Object.values(mapping));
2300
2294
  const searchIssues = restructureCreateSelectorWithArgs(
2301
2295
  createSelector(
@@ -2387,15 +2381,15 @@ const selectRecentIssuesAsSearchResults = createSelector(
2387
2381
  }
2388
2382
  );
2389
2383
  const issueReducer = issueSlice.reducer;
2390
- const initialState$d = {
2384
+ const initialState$e = {
2391
2385
  s3Urls: {}
2392
2386
  };
2393
2387
  const msPerHour = 1e3 * 60 * 60;
2394
2388
  const msPerWeek = msPerHour * 24 * 7;
2395
2389
  const fileSlice = createSlice({
2396
2390
  name: "file",
2397
- initialState: initialState$d,
2398
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$d)),
2391
+ initialState: initialState$e,
2392
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$e)),
2399
2393
  reducers: {
2400
2394
  setUploadUrl: (state, action) => {
2401
2395
  const { url, fields, sha1 } = action.payload;
@@ -2422,7 +2416,7 @@ const selectUploadUrl = (sha1) => (state) => {
2422
2416
  return url;
2423
2417
  };
2424
2418
  const fileReducer = fileSlice.reducer;
2425
- const initialState$c = {
2419
+ const initialState$d = {
2426
2420
  // TODO: Change first MapStyle.SATELLITE to MaptStyle.None when project creation map is fixed
2427
2421
  mapStyle: MapStyle.SATELLITE,
2428
2422
  showTooltips: false,
@@ -2430,8 +2424,8 @@ const initialState$c = {
2430
2424
  };
2431
2425
  const mapSlice = createSlice({
2432
2426
  name: "map",
2433
- initialState: initialState$c,
2434
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$c)),
2427
+ initialState: initialState$d,
2428
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$d)),
2435
2429
  reducers: {
2436
2430
  setMapStyle: (state, action) => {
2437
2431
  state.mapStyle = action.payload;
@@ -2473,7 +2467,24 @@ var VerificationCodeType = /* @__PURE__ */ ((VerificationCodeType2) => {
2473
2467
  VerificationCodeType2[VerificationCodeType2["RESET_PASSWORD"] = 10] = "RESET_PASSWORD";
2474
2468
  return VerificationCodeType2;
2475
2469
  })(VerificationCodeType || {});
2476
- const initialState$b = {
2470
+ var PaddleCheckoutEvent = /* @__PURE__ */ ((PaddleCheckoutEvent2) => {
2471
+ PaddleCheckoutEvent2["COMPLETED"] = "checkout.completed";
2472
+ PaddleCheckoutEvent2["CLOSED"] = "checkout.closed";
2473
+ return PaddleCheckoutEvent2;
2474
+ })(PaddleCheckoutEvent || {});
2475
+ var LicenseLevel = /* @__PURE__ */ ((LicenseLevel2) => {
2476
+ LicenseLevel2[LicenseLevel2["PRO"] = 0] = "PRO";
2477
+ return LicenseLevel2;
2478
+ })(LicenseLevel || {});
2479
+ var LicenseStatus = /* @__PURE__ */ ((LicenseStatus2) => {
2480
+ LicenseStatus2[LicenseStatus2["ACTIVE"] = 0] = "ACTIVE";
2481
+ LicenseStatus2[LicenseStatus2["PAUSED"] = 2] = "PAUSED";
2482
+ LicenseStatus2[LicenseStatus2["CANCELLED"] = 4] = "CANCELLED";
2483
+ LicenseStatus2[LicenseStatus2["INACTIVE"] = 6] = "INACTIVE";
2484
+ LicenseStatus2[LicenseStatus2["PAST_DUE"] = 8] = "PAST_DUE";
2485
+ return LicenseStatus2;
2486
+ })(LicenseStatus || {});
2487
+ const initialState$c = {
2477
2488
  users: {},
2478
2489
  currentUser: {
2479
2490
  id: 0,
@@ -2484,8 +2495,8 @@ const initialState$b = {
2484
2495
  };
2485
2496
  const userSlice = createSlice({
2486
2497
  name: "users",
2487
- initialState: initialState$b,
2488
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$b)),
2498
+ initialState: initialState$c,
2499
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$c)),
2489
2500
  reducers: {
2490
2501
  setUsers: (state, action) => {
2491
2502
  const usersMapping = {};
@@ -2547,13 +2558,13 @@ const selectUser = (userId) => (state) => {
2547
2558
  const selectUsersAsMapping = (state) => state.userReducer.users;
2548
2559
  const selectFavouriteProjects = (state) => state.userReducer.currentUser.profile.favourite_project_ids;
2549
2560
  const userReducer = userSlice.reducer;
2550
- const initialState$a = {
2561
+ const initialState$b = {
2551
2562
  organizationAccesses: {}
2552
2563
  };
2553
2564
  const organizationAccessSlice = createSlice({
2554
2565
  name: "organizationAccess",
2555
- initialState: initialState$a,
2556
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$a)),
2566
+ initialState: initialState$b,
2567
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$b)),
2557
2568
  reducers: {
2558
2569
  setOrganizationAccesses: (state, action) => {
2559
2570
  if (!Array.isArray(action.payload))
@@ -2616,151 +2627,64 @@ const selectOrganizationAccessUserMapping = (state) => {
2616
2627
  return organizationAccesses;
2617
2628
  };
2618
2629
  const organizationAccessReducer = organizationAccessSlice.reducer;
2619
- const initialState$9 = {
2620
- organizations: {},
2621
- activeOrganizationId: null
2630
+ const initialState$a = {
2631
+ licenses: {}
2622
2632
  };
2623
- const organizationSlice = createSlice({
2624
- name: "organizations",
2625
- initialState: initialState$9,
2626
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$9)),
2633
+ const licenseSlice = createSlice({
2634
+ name: "license",
2635
+ initialState: initialState$a,
2636
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$a)),
2627
2637
  reducers: {
2628
- setOrganizations: (state, action) => {
2629
- for (const org of action.payload) {
2630
- state.organizations[org.id] = org;
2638
+ setLicenses: (state, action) => {
2639
+ if (!Array.isArray(action.payload))
2640
+ throw new Error("Expected an array of Licenses");
2641
+ if (action.payload.filter(onlyUniqueOfflineIds).length !== action.payload.length) {
2642
+ throw new Error("Tried to use setLicenses reducer with duplicate ID's");
2631
2643
  }
2632
- },
2633
- updateActiveOrganization: (state, action) => {
2634
- if (!state.activeOrganizationId) {
2635
- throw new Error("Cannot update name of active organization. Active organization ID does not exist");
2644
+ const licenses = {};
2645
+ for (const license of action.payload) {
2646
+ licenses[license.offline_id] = license;
2636
2647
  }
2637
- if (state.activeOrganizationId !== action.payload.id) {
2638
- throw new Error("Tried updating active organization with different organization");
2648
+ state.licenses = licenses;
2649
+ },
2650
+ addLicenses: (state, action) => {
2651
+ for (const license of action.payload) {
2652
+ state.licenses[license.offline_id] = license;
2639
2653
  }
2640
- state.organizations[state.activeOrganizationId] = action.payload;
2641
2654
  },
2642
- setActiveOrganizationId: (state, action) => {
2643
- state.activeOrganizationId = action.payload;
2655
+ updateLicense: (state, action) => {
2656
+ if (!(action.payload.offline_id in state.licenses)) {
2657
+ throw new Error("Tried to update license that does not exist.");
2658
+ }
2659
+ state.licenses[action.payload.offline_id] = action.payload;
2644
2660
  }
2645
2661
  }
2646
2662
  });
2647
- const { setOrganizations, setActiveOrganizationId, updateActiveOrganization } = organizationSlice.actions;
2648
- const selectActiveOrganizationId = (state) => {
2649
- return state.organizationReducer.activeOrganizationId;
2650
- };
2651
- const selectOrganizations = (state) => {
2652
- return Object.values(state.organizationReducer.organizations);
2663
+ const { setLicenses, addLicenses, updateLicense } = licenseSlice.actions;
2664
+ const selectLicenses = (state) => {
2665
+ return state.licenseReducer.licenses;
2653
2666
  };
2654
- const selectOrganizationsWithAccess = createSelector(
2655
- [selectOrganizations],
2656
- (organizations) => Object.values(organizations).filter((organization) => organization.has_access)
2667
+ const selectLicense = (licenseId) => (state) => state.licenseReducer.licenses[licenseId];
2668
+ const selectActiveLicense = (state) => Object.values(state.licenseReducer.licenses).find(
2669
+ (license) => license.project === state.projectReducer.activeProjectId
2670
+ ) ?? null;
2671
+ const selectLicenseForProject = (projectId) => (state) => Object.values(state.licenseReducer.licenses).find((license) => license.project === projectId);
2672
+ const selectActiveStatusLicenses = createSelector(
2673
+ [selectLicenses],
2674
+ (licenses) => Object.values(licenses).filter((license) => license.is_active)
2657
2675
  );
2658
- const selectActiveOrganization = (state) => {
2659
- const id = selectActiveOrganizationId(state);
2660
- if (!id) {
2661
- return null;
2662
- }
2663
- const organization = state.organizationReducer.organizations[id];
2664
- if (!organization) {
2665
- return null;
2666
- }
2667
- return organization;
2668
- };
2669
- const selectOrganizationUsersIds = createSelector(
2670
- [selectOrganizationAccesses],
2671
- (organizationAccesses) => Object.values(organizationAccesses).map((organizationAccess) => organizationAccess.user)
2672
- );
2673
- const selectOrganizationUsersAsMapping = createSelector(
2674
- [selectOrganizationUsersIds, selectUsersAsMapping],
2675
- (organizationUserIds, users) => organizationUserIds.reduce((accum, userId) => ({ ...accum, [userId]: users[userId] }), {})
2676
+ const selectLicensesForProjectsMapping = createSelector(
2677
+ [selectLicenses],
2678
+ (licenses) => Object.values(licenses).filter((license) => license.project).reduce((accum, license) => ({ ...accum, [license.project]: license }), {})
2676
2679
  );
2677
- const selectSortedOrganizationUsers = createSelector(
2678
- [selectCurrentUser, selectOrganizationUsersAsMapping, selectOrganizationAccessUserMapping],
2679
- (currentUser, userMapping, organizationAccessMapping) => {
2680
- return Object.values(userMapping).sort((userA, userB) => {
2681
- if (userA.id === currentUser.id) {
2682
- return -1;
2683
- } else if (userB.id === currentUser.id) {
2684
- return 1;
2685
- }
2686
- const organizationAccessesA = organizationAccessMapping[userA.id];
2687
- const organizationAccessesB = organizationAccessMapping[userB.id];
2688
- if ((organizationAccessesA == null ? void 0 : organizationAccessesA.access_level) === (organizationAccessesB == null ? void 0 : organizationAccessesB.access_level)) {
2689
- return userA.username.localeCompare(userB.username);
2690
- }
2691
- if ((organizationAccessesA == null ? void 0 : organizationAccessesA.access_level) === OrganizationAccessLevel.ADMIN) {
2692
- return -1;
2693
- }
2694
- return 1;
2695
- });
2696
- }
2697
- );
2698
- const selectOrganization = (id) => (state) => {
2699
- return state.organizationReducer.organizations[id];
2700
- };
2701
- const organizationReducer = organizationSlice.reducer;
2702
- const createOfflineAction = (request2, baseUrl) => {
2703
- const requestWithUuid = request2.uuid ? request2 : { ...request2, uuid: v4() };
2704
- return {
2705
- payload: requestWithUuid,
2706
- type: "",
2707
- meta: {
2708
- offline: {
2709
- effect: {
2710
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2711
- request: requestWithUuid,
2712
- BASE_URL: baseUrl
2713
- }
2714
- }
2715
- }
2716
- };
2717
- };
2718
- const initialState$8 = {
2719
- deletedRequests: [],
2720
- latestRetryTime: 0
2721
- };
2722
- const outboxSlice = createSlice({
2723
- name: "outbox",
2724
- initialState: initialState$8,
2725
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$8)),
2726
- reducers: {
2727
- // enqueueActions is a reducer that does nothing but enqueue API request to the Redux Offline outbox
2728
- // Whenever an issue is being created, a reducer addIssue() is responsible for adding it to the offline store
2729
- // Then this reducer enqueueRequest() is responsible for adding the actual request data to the outbox
2730
- enqueueRequest: {
2731
- reducer: (state, _action) => {
2732
- return state;
2733
- },
2734
- prepare: (payload) => {
2735
- console.debug("Preparing to enqueue request", payload);
2736
- const { BASE_URL, ...rest } = payload;
2737
- return createOfflineAction(rest, BASE_URL);
2738
- }
2739
- },
2740
- markForDeletion(state, action) {
2741
- state.deletedRequests.push(action.payload);
2742
- },
2743
- markAsDeleted(state, action) {
2744
- const index2 = state.deletedRequests.indexOf(action.payload);
2745
- if (index2 !== -1)
2746
- state.deletedRequests.splice(index2, 1);
2747
- },
2748
- _setLatestRetryTime: (state, action) => {
2749
- state.latestRetryTime = action.payload;
2750
- }
2751
- }
2752
- });
2753
- const selectDeletedRequests = (state) => state.outboxReducer.deletedRequests;
2754
- const selectLatestRetryTime = (state) => state.outboxReducer.latestRetryTime;
2755
- const { enqueueRequest, markForDeletion, markAsDeleted, _setLatestRetryTime } = outboxSlice.actions;
2756
- const outboxReducer = outboxSlice.reducer;
2757
- const initialState$7 = {
2680
+ const licenseReducer = licenseSlice.reducer;
2681
+ const initialState$9 = {
2758
2682
  projectAccesses: {}
2759
2683
  };
2760
2684
  const projectAccessSlice = createSlice({
2761
2685
  name: "projectAccess",
2762
- initialState: initialState$7,
2763
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$7)),
2686
+ initialState: initialState$9,
2687
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$9)),
2764
2688
  reducers: {
2765
2689
  setProjectAccesses: (state, action) => {
2766
2690
  if (!Array.isArray(action.payload))
@@ -2828,7 +2752,7 @@ const selectProjectAccessUserMapping = (state) => {
2828
2752
  return projectAccesses;
2829
2753
  };
2830
2754
  const projectAccessReducer = projectAccessSlice.reducer;
2831
- const initialState$6 = {
2755
+ const initialState$8 = {
2832
2756
  projects: {},
2833
2757
  activeProjectId: null,
2834
2758
  recentProjectIds: [],
@@ -2837,7 +2761,7 @@ const initialState$6 = {
2837
2761
  };
2838
2762
  const projectSlice = createSlice({
2839
2763
  name: "projects",
2840
- initialState: initialState$6,
2764
+ initialState: initialState$8,
2841
2765
  reducers: {
2842
2766
  setProjects: (state, action) => {
2843
2767
  const projectsMap = {};
@@ -2883,6 +2807,27 @@ const projectSlice = createSlice({
2883
2807
  } else {
2884
2808
  throw new Error("Accept project invite: user is not in this project");
2885
2809
  }
2810
+ },
2811
+ addActiveProjectIssuesCount: (state, action) => {
2812
+ if (!state.activeProjectId || !(state.activeProjectId in state.projects)) {
2813
+ throw new Error("Update issues count: no active project");
2814
+ }
2815
+ if (!state.projects[state.activeProjectId].issues_count) {
2816
+ state.projects[state.activeProjectId].issues_count = action.payload;
2817
+ } else {
2818
+ state.projects[state.activeProjectId].issues_count += action.payload;
2819
+ }
2820
+ },
2821
+ addActiveProjectFormSubmissionsCount: (state, action) => {
2822
+ if (state.activeProjectId && state.activeProjectId in state.projects) {
2823
+ if (!state.projects[state.activeProjectId].form_submissions_count) {
2824
+ state.projects[state.activeProjectId].form_submissions_count = action.payload;
2825
+ } else {
2826
+ state.projects[state.activeProjectId].form_submissions_count += action.payload;
2827
+ }
2828
+ } else {
2829
+ throw new Error("Update form submissions count: no active project");
2830
+ }
2886
2831
  }
2887
2832
  }
2888
2833
  });
@@ -2893,7 +2838,9 @@ const {
2893
2838
  setActiveProjectId,
2894
2839
  setCreateProjectType,
2895
2840
  deleteProject,
2896
- acceptProjectInvite
2841
+ acceptProjectInvite,
2842
+ addActiveProjectIssuesCount,
2843
+ addActiveProjectFormSubmissionsCount
2897
2844
  } = projectSlice.actions;
2898
2845
  const selectProjects = (state) => state.projectReducer.projects;
2899
2846
  const selectActiveProjectId = (state) => state.projectReducer.activeProjectId;
@@ -2957,6 +2904,171 @@ const selectSortedProjectUsers = createSelector(
2957
2904
  });
2958
2905
  }
2959
2906
  );
2907
+ const initialState$7 = {
2908
+ organizations: {},
2909
+ activeOrganizationId: null
2910
+ };
2911
+ const organizationSlice = createSlice({
2912
+ name: "organizations",
2913
+ initialState: initialState$7,
2914
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$7)),
2915
+ reducers: {
2916
+ setOrganizations: (state, action) => {
2917
+ for (const org of action.payload) {
2918
+ state.organizations[org.id] = org;
2919
+ }
2920
+ },
2921
+ updateActiveOrganization: (state, action) => {
2922
+ if (!state.activeOrganizationId) {
2923
+ throw new Error("Cannot update name of active organization. Active organization ID does not exist");
2924
+ }
2925
+ if (state.activeOrganizationId !== action.payload.id) {
2926
+ throw new Error("Tried updating active organization with different organization");
2927
+ }
2928
+ state.organizations[state.activeOrganizationId] = action.payload;
2929
+ },
2930
+ setActiveOrganizationId: (state, action) => {
2931
+ state.activeOrganizationId = action.payload;
2932
+ }
2933
+ }
2934
+ });
2935
+ const { setOrganizations, setActiveOrganizationId, updateActiveOrganization } = organizationSlice.actions;
2936
+ const selectActiveOrganizationId = (state) => {
2937
+ return state.organizationReducer.activeOrganizationId;
2938
+ };
2939
+ const selectOrganizations = (state) => {
2940
+ return Object.values(state.organizationReducer.organizations);
2941
+ };
2942
+ const selectOrganizationsMapping = (state) => {
2943
+ return state.organizationReducer.organizations;
2944
+ };
2945
+ const selectOrganizationsWithAccess = createSelector(
2946
+ [selectOrganizations],
2947
+ (organizations) => Object.values(organizations).filter((organization) => organization.has_access)
2948
+ );
2949
+ const selectActiveOrganization = (state) => {
2950
+ const id = selectActiveOrganizationId(state);
2951
+ if (!id) {
2952
+ return null;
2953
+ }
2954
+ const organization = state.organizationReducer.organizations[id];
2955
+ if (!organization) {
2956
+ return null;
2957
+ }
2958
+ return organization;
2959
+ };
2960
+ const selectOrganizationUsersIds = createSelector(
2961
+ [selectOrganizationAccesses],
2962
+ (organizationAccesses) => Object.values(organizationAccesses).map((organizationAccess) => organizationAccess.user)
2963
+ );
2964
+ const selectActiveOrganizationProjects = createSelector(
2965
+ [selectProjects, selectActiveOrganizationId],
2966
+ (projects, activeOrganizationId) => activeOrganizationId ? Object.values(projects).filter((project) => project.owner_organization === activeOrganizationId) : []
2967
+ );
2968
+ const selectActiveOrganizationLicenses = createSelector(
2969
+ [selectActiveOrganizationId, selectLicenses],
2970
+ (activeOrganizationId, licenses) => !activeOrganizationId ? [] : Object.values(licenses).filter((license) => license.organization_owner === activeOrganizationId)
2971
+ );
2972
+ const selectSortedOrganizationLicenses = createSelector(
2973
+ [selectActiveOrganizationLicenses, selectProjects],
2974
+ (licences, projects) => licences.sort((licenseA, licenseB) => {
2975
+ if (!licenseA.project) {
2976
+ return 1;
2977
+ }
2978
+ if (!licenseB.project) {
2979
+ return -1;
2980
+ }
2981
+ return projects[licenseA.project].name.toLowerCase().localeCompare(
2982
+ projects[licenseB.project].name.toLowerCase(),
2983
+ void 0,
2984
+ { numeric: true }
2985
+ );
2986
+ })
2987
+ );
2988
+ const selectOrganizationUsersAsMapping = createSelector(
2989
+ [selectOrganizationUsersIds, selectUsersAsMapping],
2990
+ (organizationUserIds, users) => organizationUserIds.reduce((accum, userId) => ({ ...accum, [userId]: users[userId] }), {})
2991
+ );
2992
+ const selectSortedOrganizationUsers = createSelector(
2993
+ [selectCurrentUser, selectOrganizationUsersAsMapping, selectOrganizationAccessUserMapping],
2994
+ (currentUser, userMapping, organizationAccessMapping) => {
2995
+ return Object.values(userMapping).sort((userA, userB) => {
2996
+ if (userA.id === currentUser.id) {
2997
+ return -1;
2998
+ } else if (userB.id === currentUser.id) {
2999
+ return 1;
3000
+ }
3001
+ const organizationAccessesA = organizationAccessMapping[userA.id];
3002
+ const organizationAccessesB = organizationAccessMapping[userB.id];
3003
+ if ((organizationAccessesA == null ? void 0 : organizationAccessesA.access_level) === (organizationAccessesB == null ? void 0 : organizationAccessesB.access_level)) {
3004
+ return userA.username.localeCompare(userB.username);
3005
+ }
3006
+ if ((organizationAccessesA == null ? void 0 : organizationAccessesA.access_level) === OrganizationAccessLevel.ADMIN) {
3007
+ return -1;
3008
+ }
3009
+ return 1;
3010
+ });
3011
+ }
3012
+ );
3013
+ const selectOrganization = (id) => (state) => {
3014
+ return state.organizationReducer.organizations[id];
3015
+ };
3016
+ const organizationReducer = organizationSlice.reducer;
3017
+ const createOfflineAction = (request2, baseUrl) => {
3018
+ const requestWithUuid = request2.uuid ? request2 : { ...request2, uuid: v4() };
3019
+ return {
3020
+ payload: requestWithUuid,
3021
+ type: "",
3022
+ meta: {
3023
+ offline: {
3024
+ effect: {
3025
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3026
+ request: requestWithUuid,
3027
+ BASE_URL: baseUrl
3028
+ }
3029
+ }
3030
+ }
3031
+ };
3032
+ };
3033
+ const initialState$6 = {
3034
+ deletedRequests: [],
3035
+ latestRetryTime: 0
3036
+ };
3037
+ const outboxSlice = createSlice({
3038
+ name: "outbox",
3039
+ initialState: initialState$6,
3040
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$6)),
3041
+ reducers: {
3042
+ // enqueueActions is a reducer that does nothing but enqueue API request to the Redux Offline outbox
3043
+ // Whenever an issue is being created, a reducer addIssue() is responsible for adding it to the offline store
3044
+ // Then this reducer enqueueRequest() is responsible for adding the actual request data to the outbox
3045
+ enqueueRequest: {
3046
+ reducer: (state, _action) => {
3047
+ return state;
3048
+ },
3049
+ prepare: (payload) => {
3050
+ console.debug("Preparing to enqueue request", payload);
3051
+ const { BASE_URL, ...rest } = payload;
3052
+ return createOfflineAction(rest, BASE_URL);
3053
+ }
3054
+ },
3055
+ markForDeletion(state, action) {
3056
+ state.deletedRequests.push(action.payload);
3057
+ },
3058
+ markAsDeleted(state, action) {
3059
+ const index2 = state.deletedRequests.indexOf(action.payload);
3060
+ if (index2 !== -1)
3061
+ state.deletedRequests.splice(index2, 1);
3062
+ },
3063
+ _setLatestRetryTime: (state, action) => {
3064
+ state.latestRetryTime = action.payload;
3065
+ }
3066
+ }
3067
+ });
3068
+ const selectDeletedRequests = (state) => state.outboxReducer.deletedRequests;
3069
+ const selectLatestRetryTime = (state) => state.outboxReducer.latestRetryTime;
3070
+ const { enqueueRequest, markForDeletion, markAsDeleted, _setLatestRetryTime } = outboxSlice.actions;
3071
+ const outboxReducer = outboxSlice.reducer;
2960
3072
  const initialState$5 = {
2961
3073
  projectFiles: {},
2962
3074
  activeProjectFileId: null,
@@ -3093,7 +3205,9 @@ const initialState$3 = {
3093
3205
  Components: false,
3094
3206
  Experimental: false
3095
3207
  },
3096
- appearance: "dark"
3208
+ appearance: "dark",
3209
+ isFetchingInitialData: false,
3210
+ isLoading: false
3097
3211
  };
3098
3212
  const settingSlice = createSlice({
3099
3213
  name: "settings",
@@ -3117,6 +3231,12 @@ const settingSlice = createSlice({
3117
3231
  },
3118
3232
  setAppearance: (state, action) => {
3119
3233
  state.appearance = action.payload;
3234
+ },
3235
+ setIsFetchingInitialData: (state, action) => {
3236
+ state.isFetchingInitialData = action.payload;
3237
+ },
3238
+ setIsLoading: (state, action) => {
3239
+ state.isLoading = action.payload;
3120
3240
  }
3121
3241
  }
3122
3242
  });
@@ -3125,7 +3245,9 @@ const {
3125
3245
  setEnablePlacementMode,
3126
3246
  setSectionExpanded,
3127
3247
  setEnableClustering,
3128
- setAppearance
3248
+ setAppearance,
3249
+ setIsFetchingInitialData,
3250
+ setIsLoading
3129
3251
  } = settingSlice.actions;
3130
3252
  const selectEnablePlacementMode = (state) => state.settingReducer.placementMode;
3131
3253
  const selectEnableDuplicateIssues = (state) => state.settingReducer.useIssueTemplate;
@@ -3134,6 +3256,8 @@ const selectExpandedSections = (state) => state.settingReducer.expandedSections;
3134
3256
  const selectEnableClustering = (state) => state.settingReducer.enableClustering;
3135
3257
  const selectAppearance = (state) => state.settingReducer.appearance;
3136
3258
  const settingReducer = settingSlice.reducer;
3259
+ const selectIsFetchingInitialData = (state) => state.settingReducer.isFetchingInitialData;
3260
+ const selectIsLoading = (state) => state.settingReducer.isLoading;
3137
3261
  const LATEST_REVISION_CACHE = {};
3138
3262
  function considerCachingRevision(revision, formId2, preferPending = false) {
3139
3263
  var _a2;
@@ -3552,7 +3676,8 @@ const overmapReducers = {
3552
3676
  userFormReducer,
3553
3677
  userReducer,
3554
3678
  workspaceReducer,
3555
- emailDomainsReducer
3679
+ emailDomainsReducer,
3680
+ licenseReducer
3556
3681
  };
3557
3682
  const overmapReducer = combineReducers(overmapReducers);
3558
3683
  const resetStore = "RESET";
@@ -4092,7 +4217,7 @@ class AttachmentService extends BaseApiService {
4092
4217
  }
4093
4218
  // Attachments aren't models, so we use the OptimisticGenericResult type instead
4094
4219
  async addIssueAttachment(attachmentPayload) {
4095
- const { description: description2, issue_id, file_sha1, offline_id } = attachmentPayload;
4220
+ const { description: description2, issue, file_sha1, offline_id } = attachmentPayload;
4096
4221
  if (!attachmentPayload.file.objectURL) {
4097
4222
  throw new Error("Expected attachmentPayload.file.objectURL to be defined.");
4098
4223
  }
@@ -4108,12 +4233,12 @@ class AttachmentService extends BaseApiService {
4108
4233
  const promise = this.enqueueRequest({
4109
4234
  description: "Create attachment",
4110
4235
  method: HttpMethod.POST,
4111
- url: `/issues/${issue_id}/attach/`,
4112
- blocks: [offline_id, issue_id],
4236
+ url: `/issues/${issue}/attach/`,
4237
+ blocks: [offline_id, issue],
4113
4238
  blockers: [file_sha1],
4114
4239
  payload: {
4115
4240
  offline_id,
4116
- issue: issue_id,
4241
+ issue,
4117
4242
  description: description2 ?? "",
4118
4243
  submitted_at: (/* @__PURE__ */ new Date()).getTime() / 1e3,
4119
4244
  ...fileProps
@@ -4126,7 +4251,7 @@ class AttachmentService extends BaseApiService {
4126
4251
  return [offlineAttachment, promise];
4127
4252
  }
4128
4253
  async addComponentAttachment(attachmentPayload) {
4129
- const { description: description2, component_id, file_sha1, offline_id } = attachmentPayload;
4254
+ const { description: description2, component, file_sha1, offline_id } = attachmentPayload;
4130
4255
  if (!attachmentPayload.file.objectURL) {
4131
4256
  throw new Error("Expected attachmentPayload.file.objectURL to be defined.");
4132
4257
  }
@@ -4142,12 +4267,12 @@ class AttachmentService extends BaseApiService {
4142
4267
  const promise = this.enqueueRequest({
4143
4268
  description: "Create attachment",
4144
4269
  method: HttpMethod.POST,
4145
- url: `/components/${component_id}/attach/`,
4146
- blocks: [offline_id, component_id],
4270
+ url: `/components/${component}/attach/`,
4271
+ blocks: [offline_id, component],
4147
4272
  blockers: [file_sha1],
4148
4273
  payload: {
4149
4274
  offline_id,
4150
- component: component_id,
4275
+ component,
4151
4276
  description: description2 ?? "",
4152
4277
  submitted_at: (/* @__PURE__ */ new Date()).getTime() / 1e3,
4153
4278
  ...fileProps
@@ -4160,7 +4285,7 @@ class AttachmentService extends BaseApiService {
4160
4285
  return [offlineAttachment, promise];
4161
4286
  }
4162
4287
  async addComponentTypeAttachment(attachmentPayload) {
4163
- const { description: description2, component_type_id, file_sha1, offline_id } = attachmentPayload;
4288
+ const { description: description2, component_type, file_sha1, offline_id } = attachmentPayload;
4164
4289
  if (!attachmentPayload.file.objectURL) {
4165
4290
  throw new Error("Expected attachmentPayload.file.objectURL to be defined.");
4166
4291
  }
@@ -4176,12 +4301,12 @@ class AttachmentService extends BaseApiService {
4176
4301
  const promise = this.enqueueRequest({
4177
4302
  description: "Create attachment",
4178
4303
  method: HttpMethod.POST,
4179
- url: `/components/types/${component_type_id}/attach/`,
4180
- blocks: [offline_id, component_type_id],
4304
+ url: `/components/types/${component_type}/attach/`,
4305
+ blocks: [offline_id, component_type],
4181
4306
  blockers: [file_sha1],
4182
4307
  payload: {
4183
4308
  offline_id,
4184
- component_type: component_type_id,
4309
+ component_type,
4185
4310
  description: description2 ?? "",
4186
4311
  submitted_at: (/* @__PURE__ */ new Date()).getTime() / 1e3,
4187
4312
  ...fileProps
@@ -4207,7 +4332,7 @@ class AttachmentService extends BaseApiService {
4207
4332
  file: file2,
4208
4333
  file_name: file2.name,
4209
4334
  file_type: file2.type,
4210
- issue_id: issueId,
4335
+ issue: issueId,
4211
4336
  file_sha1: hash
4212
4337
  });
4213
4338
  return this.addIssueAttachment(attachment);
@@ -4226,7 +4351,7 @@ class AttachmentService extends BaseApiService {
4226
4351
  file: file2,
4227
4352
  file_name: file2.name,
4228
4353
  file_type: file2.type,
4229
- component_id: componentId,
4354
+ component: componentId,
4230
4355
  file_sha1: hash
4231
4356
  });
4232
4357
  return this.addComponentAttachment(attachment);
@@ -4245,7 +4370,7 @@ class AttachmentService extends BaseApiService {
4245
4370
  file: file2,
4246
4371
  file_name: file2.name,
4247
4372
  file_type: file2.type,
4248
- component_type_id: componentTypeId,
4373
+ component_type: componentTypeId,
4249
4374
  file_sha1: hash
4250
4375
  });
4251
4376
  return this.addComponentTypeAttachment(attachment);
@@ -5326,6 +5451,7 @@ class IssueService extends BaseApiService {
5326
5451
  });
5327
5452
  store.dispatch(addIssue(issuePayload));
5328
5453
  store.dispatch(addToRecentIssues(issuePayload.offline_id));
5454
+ store.dispatch(addActiveProjectIssuesCount(1));
5329
5455
  const promise = this.enqueueRequest({
5330
5456
  description: "Create issue",
5331
5457
  method: HttpMethod.POST,
@@ -5335,6 +5461,7 @@ class IssueService extends BaseApiService {
5335
5461
  },
5336
5462
  payload: issuePayload,
5337
5463
  blockers: [
5464
+ "add-issue",
5338
5465
  ...issuePayload.index_workspace ? [issuePayload.index_workspace] : [],
5339
5466
  ...issuePayload.visible_in_workspaces
5340
5467
  ],
@@ -5352,6 +5479,7 @@ class IssueService extends BaseApiService {
5352
5479
  });
5353
5480
  }
5354
5481
  store.dispatch(removeIssue(issuePayload.offline_id));
5482
+ store.dispatch(addActiveProjectIssuesCount(-1));
5355
5483
  throw error2;
5356
5484
  });
5357
5485
  return [issuePayload, promise];
@@ -5390,14 +5518,16 @@ class IssueService extends BaseApiService {
5390
5518
  return [fullIssue, promise];
5391
5519
  }
5392
5520
  async remove(id) {
5393
- const state = this.client.store.getState();
5521
+ const { store } = this.client;
5522
+ const state = store.getState();
5394
5523
  const backup = state.issueReducer.issues[id];
5395
5524
  if (!backup) {
5396
5525
  throw new Error(`No issue with id ${id} found in the store`);
5397
5526
  }
5398
- const attachments = Object.values(state.issueReducer.attachments).filter((a) => a.issue_id === id);
5527
+ const attachments = Object.values(state.issueReducer.attachments).filter((a) => a.issue === id);
5399
5528
  const attachmentsOfIssue = selectAttachmentsOfIssue(id)(state);
5400
5529
  this.client.store.dispatch(removeIssue(id));
5530
+ store.dispatch(addActiveProjectIssuesCount(-1));
5401
5531
  if (attachmentsOfIssue.length > 0) {
5402
5532
  this.client.store.dispatch(removeAttachmentsOfIssue(id));
5403
5533
  }
@@ -5412,6 +5542,7 @@ class IssueService extends BaseApiService {
5412
5542
  } catch (e) {
5413
5543
  this.client.store.dispatch(addIssue(backup));
5414
5544
  this.client.store.dispatch(addIssueAttachments(attachments));
5545
+ store.dispatch(addActiveProjectIssuesCount(1));
5415
5546
  throw e;
5416
5547
  }
5417
5548
  }
@@ -5487,7 +5618,9 @@ class MainService extends BaseApiService {
5487
5618
  owner_organization: projectData.organization_owner,
5488
5619
  owner_user: projectData.user_owner,
5489
5620
  bounds: projectData.bounds,
5490
- invited: projectData.invited || false
5621
+ invited: projectData.invited || false,
5622
+ issues_count: projectData.issues_count,
5623
+ form_submissions_count: projectData.form_submissions_count
5491
5624
  });
5492
5625
  if (currentProjectId === projectData.id && !projectData.invited) {
5493
5626
  isProjectIdValid = true;
@@ -5505,6 +5638,7 @@ class MainService extends BaseApiService {
5505
5638
  }
5506
5639
  store.dispatch(setCurrentUser(data.user));
5507
5640
  store.dispatch(addUsers(data.project_owners));
5641
+ store.dispatch(setLicenses(data.licenses));
5508
5642
  const organizationsData = data.organizations;
5509
5643
  store.dispatch(setOrganizations(organizationsData));
5510
5644
  const validProjects = projects.filter((project) => !project.invited);
@@ -5621,7 +5755,7 @@ class ProjectAccessService extends BaseApiService {
5621
5755
  method: HttpMethod.PATCH,
5622
5756
  url: `/access/${projectAccess.offline_id}/`,
5623
5757
  payload: projectAccess,
5624
- blockers: [projectAccess.offline_id],
5758
+ blockers: [projectAccess.offline_id, "change-access-level"],
5625
5759
  blocks: [projectAccess.offline_id]
5626
5760
  });
5627
5761
  }
@@ -5830,6 +5964,11 @@ class ProjectService extends BaseApiService {
5830
5964
  store.dispatch(removeProjectAccessesOfProject(project.id));
5831
5965
  store.dispatch({ type: "rehydrated/setRehydrated", payload: false });
5832
5966
  store.dispatch(deleteProject(project));
5967
+ const licenseSelector = selectLicenseForProject(project.id);
5968
+ const license = licenseSelector(state);
5969
+ if (license) {
5970
+ store.dispatch(updateLicense({ ...license, project: null }));
5971
+ }
5833
5972
  try {
5834
5973
  await this.enqueueRequest({
5835
5974
  description: "Delete project",
@@ -5845,6 +5984,9 @@ class ProjectService extends BaseApiService {
5845
5984
  store.dispatch(addOrReplaceProjectFiles(filesToDelete));
5846
5985
  store.dispatch(setActiveProjectId(activeProjectId));
5847
5986
  store.dispatch({ type: "rehydrated/setRehydrated", payload: true });
5987
+ if (license) {
5988
+ store.dispatch(updateLicense({ ...license, project: project.id }));
5989
+ }
5848
5990
  throw e;
5849
5991
  }
5850
5992
  }
@@ -6219,7 +6361,7 @@ class UserFormSubmissionService extends BaseApiService {
6219
6361
  method: HttpMethod.POST,
6220
6362
  url: `/forms/revisions/${payload.form_revision}/respond/`,
6221
6363
  payload: { ...payloadWithoutFiles, project: activeProjectId },
6222
- blockers: [payload.issue, payload.component, payload.component_stage].filter(
6364
+ blockers: [payload.issue, payload.component, payload.component_stage, "add-form-entry"].filter(
6223
6365
  (x) => x !== void 0
6224
6366
  ),
6225
6367
  blocks: [payload.offline_id]
@@ -6238,10 +6380,12 @@ class UserFormSubmissionService extends BaseApiService {
6238
6380
  };
6239
6381
  store.dispatch(updateOrCreateUserFormSubmission(offlineResultWithoutFiles));
6240
6382
  void promise.then((result) => {
6383
+ store.dispatch(addActiveProjectFormSubmissionsCount(1));
6241
6384
  store.dispatch(updateOrCreateUserFormSubmission(result));
6242
6385
  return result;
6243
6386
  }).catch(() => {
6244
6387
  store.dispatch(deleteUserFormSubmission(payload.offline_id));
6388
+ store.dispatch(addActiveProjectFormSubmissionsCount(-1));
6245
6389
  });
6246
6390
  const settledPromise = Promise.all([promise, ...attachFilesPromises]).then(() => promise);
6247
6391
  return [fullOfflineResult, settledPromise];
@@ -6275,6 +6419,7 @@ class UserFormSubmissionService extends BaseApiService {
6275
6419
  const state = store.getState();
6276
6420
  const submission = state.userFormReducer.submissions[submissionId];
6277
6421
  store.dispatch(deleteUserFormSubmission(submissionId));
6422
+ store.dispatch(addActiveProjectFormSubmissionsCount(-1));
6278
6423
  try {
6279
6424
  return await this.enqueueRequest({
6280
6425
  description: "Delete user form submissions",
@@ -6285,6 +6430,7 @@ class UserFormSubmissionService extends BaseApiService {
6285
6430
  });
6286
6431
  } catch (e) {
6287
6432
  if (submission) {
6433
+ store.dispatch(addActiveProjectFormSubmissionsCount(1));
6288
6434
  store.dispatch(updateOrCreateUserFormSubmission(submission));
6289
6435
  }
6290
6436
  throw e;
@@ -6321,7 +6467,7 @@ class WorkspaceService extends BaseApiService {
6321
6467
  method: HttpMethod.POST,
6322
6468
  url: `/projects/${store.getState().projectReducer.activeProjectId}/workspaces/`,
6323
6469
  payload: offlineWorkspace,
6324
- blockers: [],
6470
+ blockers: ["add-workspace"],
6325
6471
  blocks: [offlineWorkspace.offline_id]
6326
6472
  });
6327
6473
  void promise.then((result) => {
@@ -6747,6 +6893,122 @@ class OrganizationService extends BaseApiService {
6747
6893
  });
6748
6894
  }
6749
6895
  }
6896
+ class LicenseService extends BaseApiService {
6897
+ async fetchLicensesForOrganization(organizationId, showLoading = false) {
6898
+ if (showLoading) {
6899
+ this.client.store.dispatch(setIsFetchingInitialData(true));
6900
+ }
6901
+ const result = await this.enqueueRequest({
6902
+ description: "Get licenses",
6903
+ method: HttpMethod.GET,
6904
+ url: `/organizations/${organizationId}/licenses/`,
6905
+ isAuthNeeded: true,
6906
+ blockers: [organizationId.toString()],
6907
+ blocks: ["add-issue", "add-form-entry", "change-access-level", "add-workspace"]
6908
+ });
6909
+ if (showLoading) {
6910
+ this.client.store.dispatch(setIsFetchingInitialData(false));
6911
+ }
6912
+ this.client.store.dispatch(addLicenses(result));
6913
+ return result;
6914
+ }
6915
+ async getLicense(license) {
6916
+ const result = await this.enqueueRequest({
6917
+ description: "Get license",
6918
+ method: HttpMethod.GET,
6919
+ url: `/billing/${license.offline_id}/`,
6920
+ isAuthNeeded: true,
6921
+ blockers: [
6922
+ license.organization_owner ? license.organization_owner.toString() : license.user_owner ? license.user_owner.toString() : ""
6923
+ ],
6924
+ blocks: []
6925
+ });
6926
+ this.client.store.dispatch(updateLicense(result));
6927
+ return result;
6928
+ }
6929
+ async pauseLicense(license) {
6930
+ const result = await this.enqueueRequest({
6931
+ description: "Pause license",
6932
+ method: HttpMethod.DELETE,
6933
+ url: `/billing/${license.offline_id}/suspend/`,
6934
+ isAuthNeeded: true,
6935
+ blockers: [
6936
+ license.organization_owner ? license.organization_owner.toString() : license.user_owner ? license.user_owner.toString() : ""
6937
+ ],
6938
+ blocks: []
6939
+ });
6940
+ this.client.store.dispatch(updateLicense(result));
6941
+ return result;
6942
+ }
6943
+ async resumeLicense(license) {
6944
+ const result = await this.enqueueRequest({
6945
+ description: "Resume license",
6946
+ method: HttpMethod.PATCH,
6947
+ url: `/billing/${license.offline_id}/suspend/`,
6948
+ isAuthNeeded: true,
6949
+ blockers: [
6950
+ license.organization_owner ? license.organization_owner.toString() : license.user_owner ? license.user_owner.toString() : ""
6951
+ ],
6952
+ blocks: []
6953
+ });
6954
+ this.client.store.dispatch(updateLicense(result));
6955
+ return result;
6956
+ }
6957
+ async cancelLicense(license) {
6958
+ const result = await this.enqueueRequest({
6959
+ description: "Cancel license",
6960
+ method: HttpMethod.DELETE,
6961
+ url: `/billing/${license.offline_id}/`,
6962
+ isAuthNeeded: true,
6963
+ blockers: [
6964
+ license.organization_owner ? license.organization_owner.toString() : license.user_owner ? license.user_owner.toString() : ""
6965
+ ],
6966
+ blocks: []
6967
+ });
6968
+ this.client.store.dispatch(updateLicense(result));
6969
+ return result;
6970
+ }
6971
+ async attachLicenseToProject(license, project) {
6972
+ const result = await this.enqueueRequest({
6973
+ description: "Attach license",
6974
+ method: HttpMethod.PATCH,
6975
+ url: `/billing/${license.offline_id}/project/`,
6976
+ isAuthNeeded: true,
6977
+ payload: { project: project.id },
6978
+ blockers: [
6979
+ license.organization_owner ? license.organization_owner.toString() : license.user_owner ? license.user_owner.toString() : "",
6980
+ project.id ? project.id.toString() : ""
6981
+ ],
6982
+ blocks: ["add-issue", "add-form-entry", "change-access-level", "add-workspace"]
6983
+ });
6984
+ this.client.store.dispatch(updateLicense(result));
6985
+ return result;
6986
+ }
6987
+ async detachLicenseFromProject(license) {
6988
+ const result = await this.enqueueRequest({
6989
+ description: "Detach license",
6990
+ method: HttpMethod.DELETE,
6991
+ url: `/billing/${license.offline_id}/project/`,
6992
+ isAuthNeeded: true,
6993
+ blockers: [
6994
+ license.organization_owner ? license.organization_owner.toString() : license.user_owner ? license.user_owner.toString() : ""
6995
+ ],
6996
+ blocks: ["add-issue", "add-form-entry", "change-access-level", "add-workspace"]
6997
+ });
6998
+ this.client.store.dispatch(updateLicense(result));
6999
+ return result;
7000
+ }
7001
+ async getLatestTransaction(license) {
7002
+ return await this.enqueueRequest({
7003
+ description: "Get latest transaction",
7004
+ method: HttpMethod.GET,
7005
+ url: `/billing/${license.offline_id}/transaction/`,
7006
+ isAuthNeeded: true,
7007
+ blockers: [license.offline_id],
7008
+ blocks: [license.offline_id]
7009
+ });
7010
+ }
7011
+ }
6750
7012
  class OvermapSDK {
6751
7013
  constructor(apiUrl, store) {
6752
7014
  __publicField(this, "API_URL");
@@ -6772,6 +7034,7 @@ class OvermapSDK {
6772
7034
  __publicField(this, "projectFiles", new ProjectFileService(this));
6773
7035
  __publicField(this, "emailVerification", new EmailVerificationService(this));
6774
7036
  __publicField(this, "emailDomains", new EmailDomainsService(this));
7037
+ __publicField(this, "licenses", new LicenseService(this));
6775
7038
  this.API_URL = apiUrl;
6776
7039
  this.store = store;
6777
7040
  }
@@ -6856,8 +7119,8 @@ class BaseFormElement {
6856
7119
  }
6857
7120
  }
6858
7121
  const emptyBaseField = {
6859
- label: "Question",
6860
- description: "Optional description",
7122
+ label: "",
7123
+ description: "",
6861
7124
  required: false
6862
7125
  };
6863
7126
  class BaseField extends BaseFormElement {
@@ -10790,18 +11053,20 @@ __publicField(_DateField, "fieldTypeName", "Date");
10790
11053
  __publicField(_DateField, "fieldTypeDescription", "Allows specifying a date.");
10791
11054
  __publicField(_DateField, "Icon", CalendarIcon);
10792
11055
  let DateField = _DateField;
11056
+ const SHORT_TEXT_FIELD_MAX_LENGTH = 500;
11057
+ const LONG_TEXT_FIELD_MAX_LENGTH = 1e4;
10793
11058
  const valueIsFormikUserFormRevision = (form) => {
10794
11059
  return "fields" in form;
10795
11060
  };
10796
11061
  class StringOrTextField extends BaseField {
10797
11062
  constructor(options) {
10798
- const { minLength, maxLength = 5e3, placeholder = "", ...base } = options;
11063
+ const { minLength, maxLength, placeholder = "", ...base } = options;
10799
11064
  super(base);
10800
11065
  __publicField(this, "minLength");
10801
11066
  __publicField(this, "maxLength");
10802
11067
  __publicField(this, "placeholder");
10803
11068
  this.minLength = minLength ? Math.max(minLength, 0) : void 0;
10804
- this.maxLength = maxLength ? Math.max(maxLength, 0) : 5e3;
11069
+ this.maxLength = maxLength ? Math.max(maxLength, 0) : LONG_TEXT_FIELD_MAX_LENGTH;
10805
11070
  this.placeholder = placeholder;
10806
11071
  }
10807
11072
  static getFieldCreationSchema(parentPath = "") {
@@ -10830,7 +11095,7 @@ class StringOrTextField extends BaseField {
10830
11095
  required: false,
10831
11096
  identifier: `${path}maximum_length`,
10832
11097
  minimum: 1,
10833
- maximum: 5e3,
11098
+ maximum: LONG_TEXT_FIELD_MAX_LENGTH,
10834
11099
  // TODO: depends on short vs long text
10835
11100
  formValidators: [this._validateMax(parentPath)],
10836
11101
  // TODO: default: 500 (see: "Short text fields can hold up to 500 characters on a single line.")
@@ -10959,13 +11224,13 @@ StringInput.displayName = "StringInput";
10959
11224
  const emptyStringField = {
10960
11225
  ...emptyBaseField,
10961
11226
  type: "string",
10962
- maximum_length: 500,
11227
+ maximum_length: SHORT_TEXT_FIELD_MAX_LENGTH,
10963
11228
  input_type: "text"
10964
11229
  };
10965
11230
  const _StringField = class _StringField extends StringOrTextField {
10966
11231
  constructor(options) {
10967
11232
  const { inputType = "text", ...rest } = options;
10968
- const maxLength = options.maxLength ? Math.min(500, options.maxLength) : 500;
11233
+ const maxLength = options.maxLength ? Math.min(SHORT_TEXT_FIELD_MAX_LENGTH, options.maxLength) : SHORT_TEXT_FIELD_MAX_LENGTH;
10969
11234
  const minLength = options.minLength ? Math.min(options.minLength, maxLength) : void 0;
10970
11235
  super({ ...rest, maxLength, minLength, type: "string" });
10971
11236
  __publicField(this, "inputType");
@@ -10991,7 +11256,7 @@ const _StringField = class _StringField extends StringOrTextField {
10991
11256
  }
10992
11257
  };
10993
11258
  __publicField(_StringField, "fieldTypeName", "Short Text");
10994
- __publicField(_StringField, "fieldTypeDescription", "Short text fields can hold up to 500 characters on a single line.");
11259
+ __publicField(_StringField, "fieldTypeDescription", `Short text fields can hold up to ${SHORT_TEXT_FIELD_MAX_LENGTH} characters on a single line.`);
10995
11260
  __publicField(_StringField, "Icon", InputIcon);
10996
11261
  let StringField = _StringField;
10997
11262
  const TextInput = memo((props) => {
@@ -11026,11 +11291,11 @@ TextInput.displayName = "TextInput";
11026
11291
  const emptyTextField = {
11027
11292
  ...emptyBaseField,
11028
11293
  type: "text",
11029
- maximum_length: 1e4
11294
+ maximum_length: LONG_TEXT_FIELD_MAX_LENGTH
11030
11295
  };
11031
11296
  const _TextField = class _TextField extends StringOrTextField {
11032
11297
  constructor(options) {
11033
- const maxLength = options.maxLength ? Math.min(emptyTextField.maximum_length, options.maxLength) : emptyTextField.maximum_length;
11298
+ const maxLength = options.maxLength ? Math.min(LONG_TEXT_FIELD_MAX_LENGTH, options.maxLength) : LONG_TEXT_FIELD_MAX_LENGTH;
11034
11299
  const minLength = options.minLength ? Math.min(options.minLength, maxLength) : void 0;
11035
11300
  super({ ...options, maxLength, minLength, type: "text" });
11036
11301
  }
@@ -11053,7 +11318,7 @@ const _TextField = class _TextField extends StringOrTextField {
11053
11318
  }
11054
11319
  };
11055
11320
  __publicField(_TextField, "fieldTypeName", "Paragraph");
11056
- __publicField(_TextField, "fieldTypeDescription", "Paragraph fields can hold up to 5000 characters and can have multiple lines.");
11321
+ __publicField(_TextField, "fieldTypeDescription", `Paragraph fields can hold up to ${LONG_TEXT_FIELD_MAX_LENGTH} characters and can have multiple lines.`);
11057
11322
  __publicField(_TextField, "Icon", RowsIcon);
11058
11323
  let TextField = _TextField;
11059
11324
  const SelectInput = memo((props) => {
@@ -13653,14 +13918,16 @@ const FieldActions = memo((props) => {
13653
13918
  key: "duplicate",
13654
13919
  text: "Duplicate",
13655
13920
  buttonProps: { onClick: duplicate }
13656
- },
13657
- {
13921
+ }
13922
+ ];
13923
+ if (index2 !== 0) {
13924
+ actions2.push({
13658
13925
  Icon: TrashIcon,
13659
13926
  key: "delete",
13660
13927
  text: "Delete",
13661
13928
  buttonProps: { onClick: remove2 }
13662
- }
13663
- ];
13929
+ });
13930
+ }
13664
13931
  if (type !== "section") {
13665
13932
  actions2.unshift({
13666
13933
  Icon: ImageIcon,
@@ -14785,6 +15052,9 @@ export {
14785
15052
  IssuePriority,
14786
15053
  IssueService,
14787
15054
  IssueStatus,
15055
+ LicenseLevel,
15056
+ LicenseService,
15057
+ LicenseStatus,
14788
15058
  MainService,
14789
15059
  MapStyle,
14790
15060
  MultiSelectField,
@@ -14802,6 +15072,7 @@ export {
14802
15072
  OvermapProvider,
14803
15073
  OvermapSDK,
14804
15074
  PDFViewer,
15075
+ PaddleCheckoutEvent,
14805
15076
  PatchField,
14806
15077
  PatchFormProvider,
14807
15078
  ProjectAccessLevel,
@@ -14828,6 +15099,8 @@ export {
14828
15099
  YELLOW,
14829
15100
  _setLatestRetryTime,
14830
15101
  acceptProjectInvite,
15102
+ addActiveProjectFormSubmissionsCount,
15103
+ addActiveProjectIssuesCount,
14831
15104
  addCategory,
14832
15105
  addComponent,
14833
15106
  addComponentAttachment,
@@ -14841,6 +15114,7 @@ export {
14841
15114
  addIssue,
14842
15115
  addIssueAttachment,
14843
15116
  addIssueAttachments,
15117
+ addLicenses,
14844
15118
  addOrReplaceCategories,
14845
15119
  addOrReplaceIssueComment,
14846
15120
  addOrReplaceProjectFile,
@@ -14940,6 +15214,8 @@ export {
14940
15214
  issueReducer,
14941
15215
  issueSlice,
14942
15216
  issueToSearchResult,
15217
+ licenseReducer,
15218
+ licenseSlice,
14943
15219
  linkStageToForm,
14944
15220
  literalToCoordinates,
14945
15221
  logOnlyOnce,
@@ -15011,13 +15287,17 @@ export {
15011
15287
  searchIssues,
15012
15288
  selectAccessToken,
15013
15289
  selectActiveIssueId,
15290
+ selectActiveLicense,
15014
15291
  selectActiveOrganization,
15015
15292
  selectActiveOrganizationAccess,
15016
15293
  selectActiveOrganizationId,
15294
+ selectActiveOrganizationLicenses,
15295
+ selectActiveOrganizationProjects,
15017
15296
  selectActiveProject,
15018
15297
  selectActiveProjectAccess,
15019
15298
  selectActiveProjectFileId,
15020
15299
  selectActiveProjectId,
15300
+ selectActiveStatusLicenses,
15021
15301
  selectActiveWorkspace,
15022
15302
  selectActiveWorkspaceId,
15023
15303
  selectAllAttachments,
@@ -15073,6 +15353,7 @@ export {
15073
15353
  selectHiddenComponentTypeIds,
15074
15354
  selectIsFetchingInitialData,
15075
15355
  selectIsImportingProjectFile,
15356
+ selectIsLoading,
15076
15357
  selectIsLoggedIn,
15077
15358
  selectIssue,
15078
15359
  selectIssueAttachmentMapping,
@@ -15083,6 +15364,10 @@ export {
15083
15364
  selectLatestRetryTime,
15084
15365
  selectLatestRevisionByFormId,
15085
15366
  selectLatestRevisionsFromComponentTypeIds,
15367
+ selectLicense,
15368
+ selectLicenseForProject,
15369
+ selectLicenses,
15370
+ selectLicensesForProjectsMapping,
15086
15371
  selectMainWorkspace,
15087
15372
  selectMapStyle,
15088
15373
  selectNumberOfComponentTypesMatchingCaseInsensitiveName,
@@ -15097,6 +15382,7 @@ export {
15097
15382
  selectOrganizationUsersAsMapping,
15098
15383
  selectOrganizationUsersIds,
15099
15384
  selectOrganizations,
15385
+ selectOrganizationsMapping,
15100
15386
  selectOrganizationsWithAccess,
15101
15387
  selectPermittedWorkspaceIds,
15102
15388
  selectPhotoAttachmentsOfIssue,
@@ -15118,6 +15404,7 @@ export {
15118
15404
  selectRevisionsForForm,
15119
15405
  selectShowTooltips,
15120
15406
  selectSortedEmailDomains,
15407
+ selectSortedOrganizationLicenses,
15121
15408
  selectSortedOrganizationUsers,
15122
15409
  selectSortedProjectUsers,
15123
15410
  selectSortedProjects,
@@ -15162,9 +15449,11 @@ export {
15162
15449
  setEnablePlacementMode,
15163
15450
  setIsFetchingInitialData,
15164
15451
  setIsImportingProjectFile,
15452
+ setIsLoading,
15165
15453
  setIssueAttachments,
15166
15454
  setIssueComments,
15167
15455
  setIssues,
15456
+ setLicenses,
15168
15457
  setLoggedIn,
15169
15458
  setMapStyle,
15170
15459
  setOrganizationAccesses,
@@ -15206,6 +15495,7 @@ export {
15206
15495
  updateComponentTypeAttachment,
15207
15496
  updateIssue,
15208
15497
  updateIssueAttachment,
15498
+ updateLicense,
15209
15499
  updateOrCreateProject,
15210
15500
  updateOrCreateUserFormSubmission,
15211
15501
  updateOrganizationAccess,