@overmap-ai/core 1.0.41 → 1.0.43-projects-licensing.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))
@@ -1515,13 +1515,13 @@ const selectHiddenCategoryCount = (state) => {
1515
1515
  return hiddenCategoryCount;
1516
1516
  };
1517
1517
  const categoryReducer = categorySlice.reducer;
1518
- const initialState$j = {
1518
+ const initialState$k = {
1519
1519
  components: {}
1520
1520
  };
1521
1521
  const componentSlice = createSlice({
1522
1522
  name: "components",
1523
- initialState: initialState$j,
1524
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$j)),
1523
+ initialState: initialState$k,
1524
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$k)),
1525
1525
  reducers: {
1526
1526
  addComponent: (state, action) => {
1527
1527
  state.components[action.payload.offline_id] = action.payload;
@@ -1633,13 +1633,13 @@ const {
1633
1633
  removeAllComponentsOfType
1634
1634
  } = componentSlice.actions;
1635
1635
  const componentReducer = componentSlice.reducer;
1636
- const initialState$i = {
1636
+ const initialState$j = {
1637
1637
  completionsByComponentId: {}
1638
1638
  };
1639
1639
  const componentStageCompletionSlice = createSlice({
1640
1640
  name: "componentStageCompletions",
1641
- initialState: initialState$i,
1642
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$i)),
1641
+ initialState: initialState$j,
1642
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$j)),
1643
1643
  reducers: {
1644
1644
  addStageCompletion: (state, action) => {
1645
1645
  let stageToCompletionDateMapping = state.completionsByComponentId[action.payload.component];
@@ -1690,13 +1690,13 @@ const selectCompletedStageIdsForComponent = (component) => (state) => {
1690
1690
  return Object.keys(state.componentStageCompletionReducer.completionsByComponentId[component.offline_id] ?? {});
1691
1691
  };
1692
1692
  const componentStageCompletionReducer = componentStageCompletionSlice.reducer;
1693
- const initialState$h = {
1693
+ const initialState$i = {
1694
1694
  stages: {}
1695
1695
  };
1696
1696
  const componentStageSlice = createSlice({
1697
1697
  name: "componentStages",
1698
- initialState: initialState$h,
1699
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$h)),
1698
+ initialState: initialState$i,
1699
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$i)),
1700
1700
  reducers: {
1701
1701
  addStages: (state, action) => {
1702
1702
  Object.assign(state.stages, toOfflineIdRecord(action.payload));
@@ -1787,14 +1787,14 @@ const selectStageFormIdsFromStageIds = restructureCreateSelectorWithArgs(
1787
1787
  );
1788
1788
  const { addStages, updateStages, removeStages, linkStageToForm, unlinkStageToForm } = componentStageSlice.actions;
1789
1789
  const componentStageReducer = componentStageSlice.reducer;
1790
- const initialState$g = {
1790
+ const initialState$h = {
1791
1791
  componentTypes: {},
1792
1792
  hiddenComponentTypeIds: {}
1793
1793
  };
1794
1794
  const componentTypeSlice = createSlice({
1795
1795
  name: "componentTypes",
1796
- initialState: initialState$g,
1797
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$g)),
1796
+ initialState: initialState$h,
1797
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$h)),
1798
1798
  reducers: {
1799
1799
  addComponentType: (state, action) => {
1800
1800
  state.componentTypes[action.payload.offline_id] = action.payload;
@@ -1853,13 +1853,13 @@ const selectComponentTypesByName = restructureCreateSelectorWithArgs(
1853
1853
  const selectHiddenComponentTypeIds = (state) => state.componentTypeReducer.hiddenComponentTypeIds;
1854
1854
  const { addComponentType, setComponentTypes, toggleComponentTypeVisibility, deleteComponentType } = componentTypeSlice.actions;
1855
1855
  const componentTypeReducer = componentTypeSlice.reducer;
1856
- const initialState$f = {
1856
+ const initialState$g = {
1857
1857
  workspaces: {},
1858
1858
  activeWorkspaceId: null
1859
1859
  };
1860
1860
  const workspaceSlice = createSlice({
1861
1861
  name: "workspace",
1862
- initialState: initialState$f,
1862
+ initialState: initialState$g,
1863
1863
  // The `reducers` field lets us define reducers and generate associated actions
1864
1864
  reducers: {
1865
1865
  setWorkspaces: (state, action) => {
@@ -1916,21 +1916,20 @@ const selectPermittedWorkspaceIds = createSelector(
1916
1916
  );
1917
1917
  const workspaceReducer = workspaceSlice.reducer;
1918
1918
  const maxRecentIssues = 10;
1919
- const initialState$e = {
1919
+ const initialState$f = {
1920
1920
  issues: {},
1921
1921
  attachments: {},
1922
1922
  comments: {},
1923
1923
  visibleStatuses: [IssueStatus.BACKLOG, IssueStatus.SELECTED],
1924
- isFetchingInitialData: false,
1925
1924
  visibleUserIds: null,
1926
1925
  recentIssueIds: [],
1927
1926
  activeIssueId: null
1928
1927
  };
1929
1928
  const issueSlice = createSlice({
1930
1929
  name: "issues",
1931
- initialState: initialState$e,
1930
+ initialState: initialState$f,
1932
1931
  extraReducers: (builder) => builder.addCase("RESET", (state) => {
1933
- Object.assign(state, initialState$e);
1932
+ Object.assign(state, initialState$f);
1934
1933
  }),
1935
1934
  reducers: {
1936
1935
  setIssues: (state, action) => {
@@ -2009,9 +2008,6 @@ const issueSlice = createSlice({
2009
2008
  setVisibleStatuses: (state, action) => {
2010
2009
  state.visibleStatuses = action.payload;
2011
2010
  },
2012
- setIsFetchingInitialData: (state, action) => {
2013
- state.isFetchingInitialData = action.payload;
2014
- },
2015
2011
  setVisibleUserIds: (state, action) => {
2016
2012
  state.visibleUserIds = [...new Set(action.payload)];
2017
2013
  },
@@ -2070,7 +2066,6 @@ const {
2070
2066
  resetRecentIssues,
2071
2067
  setActiveIssueId,
2072
2068
  setAttachments,
2073
- setIsFetchingInitialData,
2074
2069
  setIssueComments,
2075
2070
  setIssues,
2076
2071
  setVisibleStatuses,
@@ -2169,7 +2164,6 @@ const selectIssue = restructureCreateSelectorWithArgs(
2169
2164
  return mapping[id];
2170
2165
  })
2171
2166
  );
2172
- const selectIsFetchingInitialData = (state) => state.issueReducer.isFetchingInitialData;
2173
2167
  const selectAllAttachments = createSelector([selectIssueAttachmentMapping], (mapping) => Object.values(mapping));
2174
2168
  const searchIssues = restructureCreateSelectorWithArgs(
2175
2169
  createSelector(
@@ -2261,15 +2255,15 @@ const selectRecentIssuesAsSearchResults = createSelector(
2261
2255
  }
2262
2256
  );
2263
2257
  const issueReducer = issueSlice.reducer;
2264
- const initialState$d = {
2258
+ const initialState$e = {
2265
2259
  s3Urls: {}
2266
2260
  };
2267
2261
  const msPerHour = 1e3 * 60 * 60;
2268
2262
  const msPerWeek = msPerHour * 24 * 7;
2269
2263
  const fileSlice = createSlice({
2270
2264
  name: "file",
2271
- initialState: initialState$d,
2272
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$d)),
2265
+ initialState: initialState$e,
2266
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$e)),
2273
2267
  reducers: {
2274
2268
  setUploadUrl: (state, action) => {
2275
2269
  const { url, fields, sha1 } = action.payload;
@@ -2296,7 +2290,7 @@ const selectUploadUrl = (sha1) => (state) => {
2296
2290
  return url;
2297
2291
  };
2298
2292
  const fileReducer = fileSlice.reducer;
2299
- const initialState$c = {
2293
+ const initialState$d = {
2300
2294
  // TODO: Change first MapStyle.SATELLITE to MaptStyle.None when project creation map is fixed
2301
2295
  mapStyle: MapStyle.SATELLITE,
2302
2296
  showTooltips: false,
@@ -2304,8 +2298,8 @@ const initialState$c = {
2304
2298
  };
2305
2299
  const mapSlice = createSlice({
2306
2300
  name: "map",
2307
- initialState: initialState$c,
2308
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$c)),
2301
+ initialState: initialState$d,
2302
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$d)),
2309
2303
  reducers: {
2310
2304
  setMapStyle: (state, action) => {
2311
2305
  state.mapStyle = action.payload;
@@ -2347,7 +2341,24 @@ var VerificationCodeType = /* @__PURE__ */ ((VerificationCodeType2) => {
2347
2341
  VerificationCodeType2[VerificationCodeType2["RESET_PASSWORD"] = 10] = "RESET_PASSWORD";
2348
2342
  return VerificationCodeType2;
2349
2343
  })(VerificationCodeType || {});
2350
- const initialState$b = {
2344
+ var PaddleCheckoutEvent = /* @__PURE__ */ ((PaddleCheckoutEvent2) => {
2345
+ PaddleCheckoutEvent2["COMPLETED"] = "checkout.completed";
2346
+ PaddleCheckoutEvent2["CLOSED"] = "checkout.closed";
2347
+ return PaddleCheckoutEvent2;
2348
+ })(PaddleCheckoutEvent || {});
2349
+ var LicenseLevel = /* @__PURE__ */ ((LicenseLevel2) => {
2350
+ LicenseLevel2[LicenseLevel2["PRO"] = 0] = "PRO";
2351
+ return LicenseLevel2;
2352
+ })(LicenseLevel || {});
2353
+ var LicenseStatus = /* @__PURE__ */ ((LicenseStatus2) => {
2354
+ LicenseStatus2[LicenseStatus2["ACTIVE"] = 0] = "ACTIVE";
2355
+ LicenseStatus2[LicenseStatus2["PAUSED"] = 2] = "PAUSED";
2356
+ LicenseStatus2[LicenseStatus2["CANCELLED"] = 4] = "CANCELLED";
2357
+ LicenseStatus2[LicenseStatus2["INACTIVE"] = 6] = "INACTIVE";
2358
+ LicenseStatus2[LicenseStatus2["PAST_DUE"] = 8] = "PAST_DUE";
2359
+ return LicenseStatus2;
2360
+ })(LicenseStatus || {});
2361
+ const initialState$c = {
2351
2362
  users: {},
2352
2363
  currentUser: {
2353
2364
  id: 0,
@@ -2358,8 +2369,8 @@ const initialState$b = {
2358
2369
  };
2359
2370
  const userSlice = createSlice({
2360
2371
  name: "users",
2361
- initialState: initialState$b,
2362
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$b)),
2372
+ initialState: initialState$c,
2373
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$c)),
2363
2374
  reducers: {
2364
2375
  setUsers: (state, action) => {
2365
2376
  const usersMapping = {};
@@ -2421,13 +2432,13 @@ const selectUser = (userId) => (state) => {
2421
2432
  const selectUsersAsMapping = (state) => state.userReducer.users;
2422
2433
  const selectFavouriteProjects = (state) => state.userReducer.currentUser.profile.favourite_project_ids;
2423
2434
  const userReducer = userSlice.reducer;
2424
- const initialState$a = {
2435
+ const initialState$b = {
2425
2436
  organizationAccesses: {}
2426
2437
  };
2427
2438
  const organizationAccessSlice = createSlice({
2428
2439
  name: "organizationAccess",
2429
- initialState: initialState$a,
2430
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$a)),
2440
+ initialState: initialState$b,
2441
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$b)),
2431
2442
  reducers: {
2432
2443
  setOrganizationAccesses: (state, action) => {
2433
2444
  if (!Array.isArray(action.payload))
@@ -2490,151 +2501,64 @@ const selectOrganizationAccessUserMapping = (state) => {
2490
2501
  return organizationAccesses;
2491
2502
  };
2492
2503
  const organizationAccessReducer = organizationAccessSlice.reducer;
2493
- const initialState$9 = {
2494
- organizations: {},
2495
- activeOrganizationId: null
2504
+ const initialState$a = {
2505
+ licenses: {}
2496
2506
  };
2497
- const organizationSlice = createSlice({
2498
- name: "organizations",
2499
- initialState: initialState$9,
2500
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$9)),
2507
+ const licenseSlice = createSlice({
2508
+ name: "license",
2509
+ initialState: initialState$a,
2510
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$a)),
2501
2511
  reducers: {
2502
- setOrganizations: (state, action) => {
2503
- for (const org of action.payload) {
2504
- state.organizations[org.id] = org;
2512
+ setLicenses: (state, action) => {
2513
+ if (!Array.isArray(action.payload))
2514
+ throw new Error("Expected an array of Licenses");
2515
+ if (action.payload.filter(onlyUniqueOfflineIds).length !== action.payload.length) {
2516
+ throw new Error("Tried to use setLicenses reducer with duplicate ID's");
2505
2517
  }
2506
- },
2507
- updateActiveOrganization: (state, action) => {
2508
- if (!state.activeOrganizationId) {
2509
- throw new Error("Cannot update name of active organization. Active organization ID does not exist");
2518
+ const licenses = {};
2519
+ for (const license of action.payload) {
2520
+ licenses[license.offline_id] = license;
2510
2521
  }
2511
- if (state.activeOrganizationId !== action.payload.id) {
2512
- throw new Error("Tried updating active organization with different organization");
2522
+ state.licenses = licenses;
2523
+ },
2524
+ addLicenses: (state, action) => {
2525
+ for (const license of action.payload) {
2526
+ state.licenses[license.offline_id] = license;
2513
2527
  }
2514
- state.organizations[state.activeOrganizationId] = action.payload;
2515
2528
  },
2516
- setActiveOrganizationId: (state, action) => {
2517
- state.activeOrganizationId = action.payload;
2529
+ updateLicense: (state, action) => {
2530
+ if (!(action.payload.offline_id in state.licenses)) {
2531
+ throw new Error("Tried to update license that does not exist.");
2532
+ }
2533
+ state.licenses[action.payload.offline_id] = action.payload;
2518
2534
  }
2519
2535
  }
2520
2536
  });
2521
- const { setOrganizations, setActiveOrganizationId, updateActiveOrganization } = organizationSlice.actions;
2522
- const selectActiveOrganizationId = (state) => {
2523
- return state.organizationReducer.activeOrganizationId;
2537
+ const { setLicenses, addLicenses, updateLicense } = licenseSlice.actions;
2538
+ const selectLicenses = (state) => {
2539
+ return state.licenseReducer.licenses;
2524
2540
  };
2525
- const selectOrganizations = (state) => {
2526
- return Object.values(state.organizationReducer.organizations);
2527
- };
2528
- const selectOrganizationsWithAccess = createSelector(
2529
- [selectOrganizations],
2530
- (organizations) => Object.values(organizations).filter((organization) => organization.has_access)
2541
+ const selectLicense = (licenseId) => (state) => state.licenseReducer.licenses[licenseId];
2542
+ const selectActiveLicense = (state) => Object.values(state.licenseReducer.licenses).find(
2543
+ (license) => license.project === state.projectReducer.activeProjectId
2544
+ ) ?? null;
2545
+ const selectLicenseForProject = (projectId) => (state) => Object.values(state.licenseReducer.licenses).find((license) => license.project === projectId) ?? null;
2546
+ const selectActiveStatusLicenses = createSelector(
2547
+ [selectLicenses],
2548
+ (licenses) => Object.values(licenses).filter((license) => license.is_active)
2531
2549
  );
2532
- const selectActiveOrganization = (state) => {
2533
- const id = selectActiveOrganizationId(state);
2534
- if (!id) {
2535
- return null;
2536
- }
2537
- const organization = state.organizationReducer.organizations[id];
2538
- if (!organization) {
2539
- return null;
2540
- }
2541
- return organization;
2542
- };
2543
- const selectOrganizationUsersIds = createSelector(
2544
- [selectOrganizationAccesses],
2545
- (organizationAccesses) => Object.values(organizationAccesses).map((organizationAccess) => organizationAccess.user)
2546
- );
2547
- const selectOrganizationUsersAsMapping = createSelector(
2548
- [selectOrganizationUsersIds, selectUsersAsMapping],
2549
- (organizationUserIds, users) => organizationUserIds.reduce((accum, userId) => ({ ...accum, [userId]: users[userId] }), {})
2550
+ const selectLicensesForProjectsMapping = createSelector(
2551
+ [selectLicenses],
2552
+ (licenses) => Object.values(licenses).filter((license) => license.project).reduce((accum, license) => ({ ...accum, [license.project]: license }), {})
2550
2553
  );
2551
- const selectSortedOrganizationUsers = createSelector(
2552
- [selectCurrentUser, selectOrganizationUsersAsMapping, selectOrganizationAccessUserMapping],
2553
- (currentUser, userMapping, organizationAccessMapping) => {
2554
- return Object.values(userMapping).sort((userA, userB) => {
2555
- if (userA.id === currentUser.id) {
2556
- return -1;
2557
- } else if (userB.id === currentUser.id) {
2558
- return 1;
2559
- }
2560
- const organizationAccessesA = organizationAccessMapping[userA.id];
2561
- const organizationAccessesB = organizationAccessMapping[userB.id];
2562
- if ((organizationAccessesA == null ? void 0 : organizationAccessesA.access_level) === (organizationAccessesB == null ? void 0 : organizationAccessesB.access_level)) {
2563
- return userA.username.localeCompare(userB.username);
2564
- }
2565
- if ((organizationAccessesA == null ? void 0 : organizationAccessesA.access_level) === OrganizationAccessLevel.ADMIN) {
2566
- return -1;
2567
- }
2568
- return 1;
2569
- });
2570
- }
2571
- );
2572
- const selectOrganization = (id) => (state) => {
2573
- return state.organizationReducer.organizations[id];
2574
- };
2575
- const organizationReducer = organizationSlice.reducer;
2576
- const createOfflineAction = (request2, baseUrl) => {
2577
- const requestWithUuid = request2.uuid ? request2 : { ...request2, uuid: v4() };
2578
- return {
2579
- payload: requestWithUuid,
2580
- type: "",
2581
- meta: {
2582
- offline: {
2583
- effect: {
2584
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2585
- request: requestWithUuid,
2586
- BASE_URL: baseUrl
2587
- }
2588
- }
2589
- }
2590
- };
2591
- };
2592
- const initialState$8 = {
2593
- deletedRequests: [],
2594
- latestRetryTime: 0
2595
- };
2596
- const outboxSlice = createSlice({
2597
- name: "outbox",
2598
- initialState: initialState$8,
2599
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$8)),
2600
- reducers: {
2601
- // enqueueActions is a reducer that does nothing but enqueue API request to the Redux Offline outbox
2602
- // Whenever an issue is being created, a reducer addIssue() is responsible for adding it to the offline store
2603
- // Then this reducer enqueueRequest() is responsible for adding the actual request data to the outbox
2604
- enqueueRequest: {
2605
- reducer: (state, _action) => {
2606
- return state;
2607
- },
2608
- prepare: (payload) => {
2609
- console.debug("Preparing to enqueue request", payload);
2610
- const { BASE_URL, ...rest } = payload;
2611
- return createOfflineAction(rest, BASE_URL);
2612
- }
2613
- },
2614
- markForDeletion(state, action) {
2615
- state.deletedRequests.push(action.payload);
2616
- },
2617
- markAsDeleted(state, action) {
2618
- const index2 = state.deletedRequests.indexOf(action.payload);
2619
- if (index2 !== -1)
2620
- state.deletedRequests.splice(index2, 1);
2621
- },
2622
- _setLatestRetryTime: (state, action) => {
2623
- state.latestRetryTime = action.payload;
2624
- }
2625
- }
2626
- });
2627
- const selectDeletedRequests = (state) => state.outboxReducer.deletedRequests;
2628
- const selectLatestRetryTime = (state) => state.outboxReducer.latestRetryTime;
2629
- const { enqueueRequest, markForDeletion, markAsDeleted, _setLatestRetryTime } = outboxSlice.actions;
2630
- const outboxReducer = outboxSlice.reducer;
2631
- const initialState$7 = {
2554
+ const licenseReducer = licenseSlice.reducer;
2555
+ const initialState$9 = {
2632
2556
  projectAccesses: {}
2633
2557
  };
2634
2558
  const projectAccessSlice = createSlice({
2635
2559
  name: "projectAccess",
2636
- initialState: initialState$7,
2637
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$7)),
2560
+ initialState: initialState$9,
2561
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$9)),
2638
2562
  reducers: {
2639
2563
  setProjectAccesses: (state, action) => {
2640
2564
  if (!Array.isArray(action.payload))
@@ -2702,7 +2626,7 @@ const selectProjectAccessUserMapping = (state) => {
2702
2626
  return projectAccesses;
2703
2627
  };
2704
2628
  const projectAccessReducer = projectAccessSlice.reducer;
2705
- const initialState$6 = {
2629
+ const initialState$8 = {
2706
2630
  projects: {},
2707
2631
  activeProjectId: null,
2708
2632
  recentProjectIds: [],
@@ -2711,7 +2635,7 @@ const initialState$6 = {
2711
2635
  };
2712
2636
  const projectSlice = createSlice({
2713
2637
  name: "projects",
2714
- initialState: initialState$6,
2638
+ initialState: initialState$8,
2715
2639
  reducers: {
2716
2640
  setProjects: (state, action) => {
2717
2641
  const projectsMap = {};
@@ -2757,6 +2681,27 @@ const projectSlice = createSlice({
2757
2681
  } else {
2758
2682
  throw new Error("Accept project invite: user is not in this project");
2759
2683
  }
2684
+ },
2685
+ addActiveProjectIssuesCount: (state, action) => {
2686
+ if (!state.activeProjectId || !(state.activeProjectId in state.projects)) {
2687
+ throw new Error("Update issues count: no active project");
2688
+ }
2689
+ if (!state.projects[state.activeProjectId].issues_count) {
2690
+ state.projects[state.activeProjectId].issues_count = action.payload;
2691
+ } else {
2692
+ state.projects[state.activeProjectId].issues_count += action.payload;
2693
+ }
2694
+ },
2695
+ addActiveProjectFormSubmissionsCount: (state, action) => {
2696
+ if (state.activeProjectId && state.activeProjectId in state.projects) {
2697
+ if (!state.projects[state.activeProjectId].form_submissions_count) {
2698
+ state.projects[state.activeProjectId].form_submissions_count = action.payload;
2699
+ } else {
2700
+ state.projects[state.activeProjectId].form_submissions_count += action.payload;
2701
+ }
2702
+ } else {
2703
+ throw new Error("Update form submissions count: no active project");
2704
+ }
2760
2705
  }
2761
2706
  }
2762
2707
  });
@@ -2767,7 +2712,9 @@ const {
2767
2712
  setActiveProjectId,
2768
2713
  setCreateProjectType,
2769
2714
  deleteProject,
2770
- acceptProjectInvite
2715
+ acceptProjectInvite,
2716
+ addActiveProjectIssuesCount,
2717
+ addActiveProjectFormSubmissionsCount
2771
2718
  } = projectSlice.actions;
2772
2719
  const selectProjects = (state) => state.projectReducer.projects;
2773
2720
  const selectActiveProjectId = (state) => state.projectReducer.activeProjectId;
@@ -2831,6 +2778,171 @@ const selectSortedProjectUsers = createSelector(
2831
2778
  });
2832
2779
  }
2833
2780
  );
2781
+ const initialState$7 = {
2782
+ organizations: {},
2783
+ activeOrganizationId: null
2784
+ };
2785
+ const organizationSlice = createSlice({
2786
+ name: "organizations",
2787
+ initialState: initialState$7,
2788
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$7)),
2789
+ reducers: {
2790
+ setOrganizations: (state, action) => {
2791
+ for (const org of action.payload) {
2792
+ state.organizations[org.id] = org;
2793
+ }
2794
+ },
2795
+ updateActiveOrganization: (state, action) => {
2796
+ if (!state.activeOrganizationId) {
2797
+ throw new Error("Cannot update name of active organization. Active organization ID does not exist");
2798
+ }
2799
+ if (state.activeOrganizationId !== action.payload.id) {
2800
+ throw new Error("Tried updating active organization with different organization");
2801
+ }
2802
+ state.organizations[state.activeOrganizationId] = action.payload;
2803
+ },
2804
+ setActiveOrganizationId: (state, action) => {
2805
+ state.activeOrganizationId = action.payload;
2806
+ }
2807
+ }
2808
+ });
2809
+ const { setOrganizations, setActiveOrganizationId, updateActiveOrganization } = organizationSlice.actions;
2810
+ const selectActiveOrganizationId = (state) => {
2811
+ return state.organizationReducer.activeOrganizationId;
2812
+ };
2813
+ const selectOrganizations = (state) => {
2814
+ return Object.values(state.organizationReducer.organizations);
2815
+ };
2816
+ const selectOrganizationsMapping = (state) => {
2817
+ return state.organizationReducer.organizations;
2818
+ };
2819
+ const selectOrganizationsWithAccess = createSelector(
2820
+ [selectOrganizations],
2821
+ (organizations) => Object.values(organizations).filter((organization) => organization.has_access)
2822
+ );
2823
+ const selectActiveOrganization = (state) => {
2824
+ const id = selectActiveOrganizationId(state);
2825
+ if (!id) {
2826
+ return null;
2827
+ }
2828
+ const organization = state.organizationReducer.organizations[id];
2829
+ if (!organization) {
2830
+ return null;
2831
+ }
2832
+ return organization;
2833
+ };
2834
+ const selectOrganizationUsersIds = createSelector(
2835
+ [selectOrganizationAccesses],
2836
+ (organizationAccesses) => Object.values(organizationAccesses).map((organizationAccess) => organizationAccess.user)
2837
+ );
2838
+ const selectActiveOrganizationProjects = createSelector(
2839
+ [selectProjects, selectActiveOrganizationId],
2840
+ (projects, activeOrganizationId) => activeOrganizationId ? Object.values(projects).filter((project) => project.owner_organization === activeOrganizationId) : []
2841
+ );
2842
+ const selectActiveOrganizationLicenses = createSelector(
2843
+ [selectActiveOrganizationId, selectLicenses],
2844
+ (activeOrganizationId, licenses) => !activeOrganizationId ? [] : Object.values(licenses).filter((license) => license.organization_owner === activeOrganizationId)
2845
+ );
2846
+ const selectSortedOrganizationLicenses = createSelector(
2847
+ [selectActiveOrganizationLicenses, selectProjects],
2848
+ (licences, projects) => licences.sort((licenseA, licenseB) => {
2849
+ if (!licenseA.project) {
2850
+ return 1;
2851
+ }
2852
+ if (!licenseB.project) {
2853
+ return -1;
2854
+ }
2855
+ return projects[licenseA.project].name.toLowerCase().localeCompare(
2856
+ projects[licenseB.project].name.toLowerCase(),
2857
+ void 0,
2858
+ { numeric: true }
2859
+ );
2860
+ })
2861
+ );
2862
+ const selectOrganizationUsersAsMapping = createSelector(
2863
+ [selectOrganizationUsersIds, selectUsersAsMapping],
2864
+ (organizationUserIds, users) => organizationUserIds.reduce((accum, userId) => ({ ...accum, [userId]: users[userId] }), {})
2865
+ );
2866
+ const selectSortedOrganizationUsers = createSelector(
2867
+ [selectCurrentUser, selectOrganizationUsersAsMapping, selectOrganizationAccessUserMapping],
2868
+ (currentUser, userMapping, organizationAccessMapping) => {
2869
+ return Object.values(userMapping).sort((userA, userB) => {
2870
+ if (userA.id === currentUser.id) {
2871
+ return -1;
2872
+ } else if (userB.id === currentUser.id) {
2873
+ return 1;
2874
+ }
2875
+ const organizationAccessesA = organizationAccessMapping[userA.id];
2876
+ const organizationAccessesB = organizationAccessMapping[userB.id];
2877
+ if ((organizationAccessesA == null ? void 0 : organizationAccessesA.access_level) === (organizationAccessesB == null ? void 0 : organizationAccessesB.access_level)) {
2878
+ return userA.username.localeCompare(userB.username);
2879
+ }
2880
+ if ((organizationAccessesA == null ? void 0 : organizationAccessesA.access_level) === OrganizationAccessLevel.ADMIN) {
2881
+ return -1;
2882
+ }
2883
+ return 1;
2884
+ });
2885
+ }
2886
+ );
2887
+ const selectOrganization = (id) => (state) => {
2888
+ return state.organizationReducer.organizations[id];
2889
+ };
2890
+ const organizationReducer = organizationSlice.reducer;
2891
+ const createOfflineAction = (request2, baseUrl) => {
2892
+ const requestWithUuid = request2.uuid ? request2 : { ...request2, uuid: v4() };
2893
+ return {
2894
+ payload: requestWithUuid,
2895
+ type: "",
2896
+ meta: {
2897
+ offline: {
2898
+ effect: {
2899
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2900
+ request: requestWithUuid,
2901
+ BASE_URL: baseUrl
2902
+ }
2903
+ }
2904
+ }
2905
+ };
2906
+ };
2907
+ const initialState$6 = {
2908
+ deletedRequests: [],
2909
+ latestRetryTime: 0
2910
+ };
2911
+ const outboxSlice = createSlice({
2912
+ name: "outbox",
2913
+ initialState: initialState$6,
2914
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$6)),
2915
+ reducers: {
2916
+ // enqueueActions is a reducer that does nothing but enqueue API request to the Redux Offline outbox
2917
+ // Whenever an issue is being created, a reducer addIssue() is responsible for adding it to the offline store
2918
+ // Then this reducer enqueueRequest() is responsible for adding the actual request data to the outbox
2919
+ enqueueRequest: {
2920
+ reducer: (state, _action) => {
2921
+ return state;
2922
+ },
2923
+ prepare: (payload) => {
2924
+ console.debug("Preparing to enqueue request", payload);
2925
+ const { BASE_URL, ...rest } = payload;
2926
+ return createOfflineAction(rest, BASE_URL);
2927
+ }
2928
+ },
2929
+ markForDeletion(state, action) {
2930
+ state.deletedRequests.push(action.payload);
2931
+ },
2932
+ markAsDeleted(state, action) {
2933
+ const index2 = state.deletedRequests.indexOf(action.payload);
2934
+ if (index2 !== -1)
2935
+ state.deletedRequests.splice(index2, 1);
2936
+ },
2937
+ _setLatestRetryTime: (state, action) => {
2938
+ state.latestRetryTime = action.payload;
2939
+ }
2940
+ }
2941
+ });
2942
+ const selectDeletedRequests = (state) => state.outboxReducer.deletedRequests;
2943
+ const selectLatestRetryTime = (state) => state.outboxReducer.latestRetryTime;
2944
+ const { enqueueRequest, markForDeletion, markAsDeleted, _setLatestRetryTime } = outboxSlice.actions;
2945
+ const outboxReducer = outboxSlice.reducer;
2834
2946
  const initialState$5 = {
2835
2947
  projectFiles: {},
2836
2948
  activeProjectFileId: null,
@@ -2967,7 +3079,9 @@ const initialState$3 = {
2967
3079
  Components: false,
2968
3080
  Experimental: false
2969
3081
  },
2970
- appearance: "dark"
3082
+ appearance: "dark",
3083
+ isFetchingInitialData: false,
3084
+ isLoading: false
2971
3085
  };
2972
3086
  const settingSlice = createSlice({
2973
3087
  name: "settings",
@@ -2991,6 +3105,12 @@ const settingSlice = createSlice({
2991
3105
  },
2992
3106
  setAppearance: (state, action) => {
2993
3107
  state.appearance = action.payload;
3108
+ },
3109
+ setIsFetchingInitialData: (state, action) => {
3110
+ state.isFetchingInitialData = action.payload;
3111
+ },
3112
+ setIsLoading: (state, action) => {
3113
+ state.isLoading = action.payload;
2994
3114
  }
2995
3115
  }
2996
3116
  });
@@ -2999,7 +3119,9 @@ const {
2999
3119
  setEnablePlacementMode,
3000
3120
  setSectionExpanded,
3001
3121
  setEnableClustering,
3002
- setAppearance
3122
+ setAppearance,
3123
+ setIsFetchingInitialData,
3124
+ setIsLoading
3003
3125
  } = settingSlice.actions;
3004
3126
  const selectEnablePlacementMode = (state) => state.settingReducer.placementMode;
3005
3127
  const selectEnableDuplicateIssues = (state) => state.settingReducer.useIssueTemplate;
@@ -3008,6 +3130,8 @@ const selectExpandedSections = (state) => state.settingReducer.expandedSections;
3008
3130
  const selectEnableClustering = (state) => state.settingReducer.enableClustering;
3009
3131
  const selectAppearance = (state) => state.settingReducer.appearance;
3010
3132
  const settingReducer = settingSlice.reducer;
3133
+ const selectIsFetchingInitialData = (state) => state.settingReducer.isFetchingInitialData;
3134
+ const selectIsLoading = (state) => state.settingReducer.isLoading;
3011
3135
  const LATEST_REVISION_CACHE = {};
3012
3136
  function considerCachingRevision(revision, formId2, preferPending = false) {
3013
3137
  var _a2;
@@ -3426,7 +3550,8 @@ const overmapReducers = {
3426
3550
  userFormReducer,
3427
3551
  userReducer,
3428
3552
  workspaceReducer,
3429
- emailDomainsReducer
3553
+ emailDomainsReducer,
3554
+ licenseReducer
3430
3555
  };
3431
3556
  const overmapReducer = combineReducers(overmapReducers);
3432
3557
  const resetStore = "RESET";
@@ -4913,6 +5038,7 @@ class IssueService extends BaseApiService {
4913
5038
  });
4914
5039
  store.dispatch(addIssue(issuePayload));
4915
5040
  store.dispatch(addToRecentIssues(issuePayload.offline_id));
5041
+ store.dispatch(addActiveProjectIssuesCount(1));
4916
5042
  const promise = this.enqueueRequest({
4917
5043
  description: "Create issue",
4918
5044
  method: HttpMethod.POST,
@@ -4922,6 +5048,7 @@ class IssueService extends BaseApiService {
4922
5048
  },
4923
5049
  payload: issuePayload,
4924
5050
  blockers: [
5051
+ "add-issue",
4925
5052
  ...issuePayload.index_workspace ? [issuePayload.index_workspace] : [],
4926
5053
  ...issuePayload.visible_in_workspaces
4927
5054
  ],
@@ -4939,6 +5066,7 @@ class IssueService extends BaseApiService {
4939
5066
  });
4940
5067
  }
4941
5068
  store.dispatch(removeIssue(issuePayload.offline_id));
5069
+ store.dispatch(addActiveProjectIssuesCount(-1));
4942
5070
  throw error2;
4943
5071
  });
4944
5072
  return [issuePayload, promise];
@@ -4977,16 +5105,18 @@ class IssueService extends BaseApiService {
4977
5105
  return [fullIssue, promise];
4978
5106
  }
4979
5107
  async remove(id) {
4980
- const state = this.client.store.getState();
5108
+ const { store } = this.client;
5109
+ const state = store.getState();
4981
5110
  const backup = state.issueReducer.issues[id];
4982
5111
  if (!backup) {
4983
5112
  throw new Error(`No issue with id ${id} found in the store`);
4984
5113
  }
4985
5114
  const attachments = Object.values(state.issueReducer.attachments).filter((a) => a.issue_id === id);
4986
5115
  const attachmentsOfIssue = selectPhotoAttachmentsOfIssue(id)(state);
4987
- this.client.store.dispatch(removeIssue(id));
5116
+ store.dispatch(removeIssue(id));
5117
+ store.dispatch(addActiveProjectIssuesCount(-1));
4988
5118
  if (attachmentsOfIssue) {
4989
- this.client.store.dispatch(removeAttachmentsOfIssue(id));
5119
+ store.dispatch(removeAttachmentsOfIssue(id));
4990
5120
  }
4991
5121
  try {
4992
5122
  return await this.enqueueRequest({
@@ -4997,8 +5127,9 @@ class IssueService extends BaseApiService {
4997
5127
  blocks: []
4998
5128
  });
4999
5129
  } catch (e) {
5000
- this.client.store.dispatch(addIssue(backup));
5001
- this.client.store.dispatch(addAttachments(attachments));
5130
+ store.dispatch(addIssue(backup));
5131
+ store.dispatch(addAttachments(attachments));
5132
+ store.dispatch(addActiveProjectIssuesCount(1));
5002
5133
  throw e;
5003
5134
  }
5004
5135
  }
@@ -5074,7 +5205,9 @@ class MainService extends BaseApiService {
5074
5205
  owner_organization: projectData.organization_owner,
5075
5206
  owner_user: projectData.user_owner,
5076
5207
  bounds: projectData.bounds,
5077
- invited: projectData.invited || false
5208
+ invited: projectData.invited || false,
5209
+ issues_count: projectData.issues_count,
5210
+ form_submissions_count: projectData.form_submissions_count
5078
5211
  });
5079
5212
  if (currentProjectId === projectData.id && !projectData.invited) {
5080
5213
  isProjectIdValid = true;
@@ -5092,6 +5225,7 @@ class MainService extends BaseApiService {
5092
5225
  }
5093
5226
  store.dispatch(setCurrentUser(data.user));
5094
5227
  store.dispatch(addUsers(data.project_owners));
5228
+ store.dispatch(setLicenses(data.licenses));
5095
5229
  const organizationsData = data.organizations;
5096
5230
  store.dispatch(setOrganizations(organizationsData));
5097
5231
  const validProjects = projects.filter((project) => !project.invited);
@@ -5205,7 +5339,7 @@ class ProjectAccessService extends BaseApiService {
5205
5339
  method: HttpMethod.PATCH,
5206
5340
  url: `/access/${projectAccess.offline_id}/`,
5207
5341
  payload: projectAccess,
5208
- blockers: [projectAccess.offline_id],
5342
+ blockers: [projectAccess.offline_id, "change-access-level"],
5209
5343
  blocks: [projectAccess.offline_id]
5210
5344
  });
5211
5345
  }
@@ -5404,6 +5538,7 @@ class ProjectService extends BaseApiService {
5404
5538
  if (!project) {
5405
5539
  throw new Error("Expected project to exist");
5406
5540
  }
5541
+ const license = selectLicenseForProject(project.id);
5407
5542
  const activeProjectId = state.projectReducer.activeProjectId;
5408
5543
  if (activeProjectId === projectId) {
5409
5544
  store.dispatch({ type: "project/setActiveProjectId", payload: null });
@@ -5414,6 +5549,9 @@ class ProjectService extends BaseApiService {
5414
5549
  store.dispatch(removeProjectAccessesOfProject(project.id));
5415
5550
  store.dispatch({ type: "rehydrated/setRehydrated", payload: false });
5416
5551
  store.dispatch(deleteProject(project));
5552
+ if (license) {
5553
+ store.dispatch(updateLicense({ ...license, project: null }));
5554
+ }
5417
5555
  try {
5418
5556
  await this.enqueueRequest({
5419
5557
  description: "Delete project",
@@ -5429,6 +5567,9 @@ class ProjectService extends BaseApiService {
5429
5567
  store.dispatch(addOrReplaceProjectFiles(filesToDelete));
5430
5568
  store.dispatch(setActiveProjectId(activeProjectId));
5431
5569
  store.dispatch({ type: "rehydrated/setRehydrated", payload: true });
5570
+ if (license) {
5571
+ store.dispatch(updateLicense({ ...license, project: project.id }));
5572
+ }
5432
5573
  throw e;
5433
5574
  }
5434
5575
  }
@@ -5803,7 +5944,7 @@ class UserFormSubmissionService extends BaseApiService {
5803
5944
  method: HttpMethod.POST,
5804
5945
  url: `/forms/revisions/${payload.form_revision}/respond/`,
5805
5946
  payload: { ...payloadWithoutFiles, project: activeProjectId },
5806
- blockers: [payload.issue, payload.component, payload.component_stage].filter(
5947
+ blockers: [payload.issue, payload.component, payload.component_stage, "add-form-entry"].filter(
5807
5948
  (x) => x !== void 0
5808
5949
  ),
5809
5950
  blocks: [payload.offline_id]
@@ -5822,10 +5963,12 @@ class UserFormSubmissionService extends BaseApiService {
5822
5963
  };
5823
5964
  store.dispatch(updateOrCreateUserFormSubmission(offlineResultWithoutFiles));
5824
5965
  void promise.then((result) => {
5966
+ store.dispatch(addActiveProjectFormSubmissionsCount(1));
5825
5967
  store.dispatch(updateOrCreateUserFormSubmission(result));
5826
5968
  return result;
5827
5969
  }).catch(() => {
5828
5970
  store.dispatch(deleteUserFormSubmission(payload.offline_id));
5971
+ store.dispatch(addActiveProjectFormSubmissionsCount(-1));
5829
5972
  });
5830
5973
  const settledPromise = Promise.all([promise, ...attachFilesPromises]).then(() => promise);
5831
5974
  return [fullOfflineResult, settledPromise];
@@ -5859,6 +6002,7 @@ class UserFormSubmissionService extends BaseApiService {
5859
6002
  const state = store.getState();
5860
6003
  const submission = state.userFormReducer.submissions[submissionId];
5861
6004
  store.dispatch(deleteUserFormSubmission(submissionId));
6005
+ store.dispatch(addActiveProjectFormSubmissionsCount(-1));
5862
6006
  try {
5863
6007
  return await this.enqueueRequest({
5864
6008
  description: "Delete user form submissions",
@@ -5869,6 +6013,7 @@ class UserFormSubmissionService extends BaseApiService {
5869
6013
  });
5870
6014
  } catch (e) {
5871
6015
  if (submission) {
6016
+ store.dispatch(addActiveProjectFormSubmissionsCount(1));
5872
6017
  store.dispatch(updateOrCreateUserFormSubmission(submission));
5873
6018
  }
5874
6019
  throw e;
@@ -5905,7 +6050,7 @@ class WorkspaceService extends BaseApiService {
5905
6050
  method: HttpMethod.POST,
5906
6051
  url: `/projects/${store.getState().projectReducer.activeProjectId}/workspaces/`,
5907
6052
  payload: offlineWorkspace,
5908
- blockers: [],
6053
+ blockers: ["add-workspace"],
5909
6054
  blocks: [offlineWorkspace.offline_id]
5910
6055
  });
5911
6056
  void promise.then((result) => {
@@ -6282,10 +6427,12 @@ class OrganizationService extends BaseApiService {
6282
6427
  const organizationAccesses = data.organization_accesses;
6283
6428
  const emailDomains = data.email_domains;
6284
6429
  const users = data.users;
6430
+ const licenses = data.licenses;
6285
6431
  store.dispatch(addUsers(users));
6286
6432
  store.dispatch(setActiveOrganizationId(activeOrganization.id));
6287
6433
  store.dispatch(setOrganizationAccesses(organizationAccesses));
6288
6434
  store.dispatch(setEmailDomains(emailDomains));
6435
+ store.dispatch(addLicenses(licenses));
6289
6436
  if (showLoading) {
6290
6437
  store.dispatch(setIsFetchingInitialData(false));
6291
6438
  }
@@ -6326,6 +6473,128 @@ class OrganizationService extends BaseApiService {
6326
6473
  });
6327
6474
  }
6328
6475
  }
6476
+ class LicenseService extends BaseApiService {
6477
+ async getLicensesForOrganization(organizationId, showLoading = false) {
6478
+ if (showLoading) {
6479
+ this.client.store.dispatch(setIsFetchingInitialData(true));
6480
+ }
6481
+ return this.enqueueRequest({
6482
+ description: "Get licenses",
6483
+ method: HttpMethod.GET,
6484
+ url: `/organizations/${organizationId}/licenses/`,
6485
+ isAuthNeeded: true,
6486
+ blockers: [organizationId.toString()],
6487
+ blocks: ["add-issue", "add-form-entry", "change-access-level", "add-workspace"]
6488
+ }).then((result) => {
6489
+ if (showLoading) {
6490
+ this.client.store.dispatch(setIsFetchingInitialData(false));
6491
+ }
6492
+ return result;
6493
+ });
6494
+ }
6495
+ async getLicense(license) {
6496
+ return this.enqueueRequest({
6497
+ description: "Get license",
6498
+ method: HttpMethod.GET,
6499
+ url: `/billing/${license.offline_id}/`,
6500
+ isAuthNeeded: true,
6501
+ blockers: [
6502
+ license.organization_owner ? license.organization_owner.toString() : license.user_owner ? license.user_owner.toString() : ""
6503
+ ],
6504
+ blocks: []
6505
+ }).then((result) => {
6506
+ this.client.store.dispatch(updateLicense(result));
6507
+ return result;
6508
+ });
6509
+ }
6510
+ async pauseLicense(license) {
6511
+ return this.enqueueRequest({
6512
+ description: "Pause license",
6513
+ method: HttpMethod.DELETE,
6514
+ url: `/billing/${license.offline_id}/suspend/`,
6515
+ isAuthNeeded: true,
6516
+ blockers: [
6517
+ license.organization_owner ? license.organization_owner.toString() : license.user_owner ? license.user_owner.toString() : ""
6518
+ ],
6519
+ blocks: []
6520
+ }).then((result) => {
6521
+ this.client.store.dispatch(updateLicense(result));
6522
+ return result;
6523
+ });
6524
+ }
6525
+ async resumeLicense(license) {
6526
+ return this.enqueueRequest({
6527
+ description: "Resume license",
6528
+ method: HttpMethod.PATCH,
6529
+ url: `/billing/${license.offline_id}/suspend/`,
6530
+ isAuthNeeded: true,
6531
+ blockers: [
6532
+ license.organization_owner ? license.organization_owner.toString() : license.user_owner ? license.user_owner.toString() : ""
6533
+ ],
6534
+ blocks: []
6535
+ }).then((result) => {
6536
+ this.client.store.dispatch(updateLicense(result));
6537
+ return result;
6538
+ });
6539
+ }
6540
+ async cancelLicense(license) {
6541
+ return this.enqueueRequest({
6542
+ description: "Cancel license",
6543
+ method: HttpMethod.DELETE,
6544
+ url: `/billing/${license.offline_id}/`,
6545
+ isAuthNeeded: true,
6546
+ blockers: [
6547
+ license.organization_owner ? license.organization_owner.toString() : license.user_owner ? license.user_owner.toString() : ""
6548
+ ],
6549
+ blocks: []
6550
+ }).then((result) => {
6551
+ this.client.store.dispatch(updateLicense(result));
6552
+ return result;
6553
+ });
6554
+ }
6555
+ async attachLicenseToProject(license, project) {
6556
+ return this.enqueueRequest({
6557
+ description: "Attach license",
6558
+ method: HttpMethod.PATCH,
6559
+ url: `/billing/${license.offline_id}/project/`,
6560
+ isAuthNeeded: true,
6561
+ payload: { project: project.id },
6562
+ blockers: [
6563
+ license.organization_owner ? license.organization_owner.toString() : license.user_owner ? license.user_owner.toString() : "",
6564
+ project.id ? project.id.toString() : ""
6565
+ ],
6566
+ blocks: ["add-issue", "add-form-entry", "change-access-level", "add-workspace"]
6567
+ }).then((result) => {
6568
+ this.client.store.dispatch(updateLicense(result));
6569
+ return result;
6570
+ });
6571
+ }
6572
+ async detachLicenseFromProject(license) {
6573
+ return this.enqueueRequest({
6574
+ description: "Detach license",
6575
+ method: HttpMethod.DELETE,
6576
+ url: `/billing/${license.offline_id}/project/`,
6577
+ isAuthNeeded: true,
6578
+ blockers: [
6579
+ license.organization_owner ? license.organization_owner.toString() : license.user_owner ? license.user_owner.toString() : ""
6580
+ ],
6581
+ blocks: ["add-issue", "add-form-entry", "change-access-level", "add-workspace"]
6582
+ }).then((result) => {
6583
+ this.client.store.dispatch(updateLicense(result));
6584
+ return result;
6585
+ });
6586
+ }
6587
+ async getLatestTransaction(license) {
6588
+ return this.enqueueRequest({
6589
+ description: "Get latest transaction",
6590
+ method: HttpMethod.GET,
6591
+ url: `/billing/${license.offline_id}/transaction/`,
6592
+ isAuthNeeded: true,
6593
+ blockers: [license.offline_id],
6594
+ blocks: [license.offline_id]
6595
+ });
6596
+ }
6597
+ }
6329
6598
  class OvermapSDK {
6330
6599
  constructor(apiUrl, store) {
6331
6600
  __publicField(this, "API_URL");
@@ -6351,6 +6620,7 @@ class OvermapSDK {
6351
6620
  __publicField(this, "projectFiles", new ProjectFileService(this));
6352
6621
  __publicField(this, "emailVerification", new EmailVerificationService(this));
6353
6622
  __publicField(this, "emailDomains", new EmailDomainsService(this));
6623
+ __publicField(this, "licenses", new LicenseService(this));
6354
6624
  this.API_URL = apiUrl;
6355
6625
  this.store = store;
6356
6626
  }
@@ -14364,6 +14634,9 @@ export {
14364
14634
  IssuePriority,
14365
14635
  IssueService,
14366
14636
  IssueStatus,
14637
+ LicenseLevel,
14638
+ LicenseService,
14639
+ LicenseStatus,
14367
14640
  MainService,
14368
14641
  MapStyle,
14369
14642
  MultiSelectField,
@@ -14381,6 +14654,7 @@ export {
14381
14654
  OvermapProvider,
14382
14655
  OvermapSDK,
14383
14656
  PDFViewer,
14657
+ PaddleCheckoutEvent,
14384
14658
  PatchField,
14385
14659
  PatchFormProvider,
14386
14660
  ProjectAccessLevel,
@@ -14407,6 +14681,8 @@ export {
14407
14681
  YELLOW,
14408
14682
  _setLatestRetryTime,
14409
14683
  acceptProjectInvite,
14684
+ addActiveProjectFormSubmissionsCount,
14685
+ addActiveProjectIssuesCount,
14410
14686
  addAttachment,
14411
14687
  addAttachments,
14412
14688
  addCategory,
@@ -14416,6 +14692,7 @@ export {
14416
14692
  addEmailDomain,
14417
14693
  addFavouriteProjectId,
14418
14694
  addIssue,
14695
+ addLicenses,
14419
14696
  addOrReplaceCategories,
14420
14697
  addOrReplaceIssueComment,
14421
14698
  addOrReplaceProjectFile,
@@ -14515,6 +14792,8 @@ export {
14515
14792
  issueReducer,
14516
14793
  issueSlice,
14517
14794
  issueToSearchResult,
14795
+ licenseReducer,
14796
+ licenseSlice,
14518
14797
  linkStageToForm,
14519
14798
  literalToCoordinates,
14520
14799
  logOnlyOnce,
@@ -14582,13 +14861,17 @@ export {
14582
14861
  searchIssues,
14583
14862
  selectAccessToken,
14584
14863
  selectActiveIssueId,
14864
+ selectActiveLicense,
14585
14865
  selectActiveOrganization,
14586
14866
  selectActiveOrganizationAccess,
14587
14867
  selectActiveOrganizationId,
14868
+ selectActiveOrganizationLicenses,
14869
+ selectActiveOrganizationProjects,
14588
14870
  selectActiveProject,
14589
14871
  selectActiveProjectAccess,
14590
14872
  selectActiveProjectFileId,
14591
14873
  selectActiveProjectId,
14874
+ selectActiveStatusLicenses,
14592
14875
  selectActiveWorkspace,
14593
14876
  selectActiveWorkspaceId,
14594
14877
  selectAllAttachments,
@@ -14634,6 +14917,7 @@ export {
14634
14917
  selectHiddenComponentTypeIds,
14635
14918
  selectIsFetchingInitialData,
14636
14919
  selectIsImportingProjectFile,
14920
+ selectIsLoading,
14637
14921
  selectIsLoggedIn,
14638
14922
  selectIssue,
14639
14923
  selectIssueAttachmentMapping,
@@ -14644,6 +14928,10 @@ export {
14644
14928
  selectLatestRetryTime,
14645
14929
  selectLatestRevisionByFormId,
14646
14930
  selectLatestRevisionsFromComponentTypeIds,
14931
+ selectLicense,
14932
+ selectLicenseForProject,
14933
+ selectLicenses,
14934
+ selectLicensesForProjectsMapping,
14647
14935
  selectMainWorkspace,
14648
14936
  selectMapStyle,
14649
14937
  selectNumberOfComponentTypesMatchingCaseInsensitiveName,
@@ -14658,6 +14946,7 @@ export {
14658
14946
  selectOrganizationUsersAsMapping,
14659
14947
  selectOrganizationUsersIds,
14660
14948
  selectOrganizations,
14949
+ selectOrganizationsMapping,
14661
14950
  selectOrganizationsWithAccess,
14662
14951
  selectPermittedWorkspaceIds,
14663
14952
  selectPhotoAttachmentsOfIssue,
@@ -14679,6 +14968,7 @@ export {
14679
14968
  selectRevisionsForForm,
14680
14969
  selectShowTooltips,
14681
14970
  selectSortedEmailDomains,
14971
+ selectSortedOrganizationLicenses,
14682
14972
  selectSortedOrganizationUsers,
14683
14973
  selectSortedProjectUsers,
14684
14974
  selectSortedProjects,
@@ -14722,8 +15012,10 @@ export {
14722
15012
  setEnablePlacementMode,
14723
15013
  setIsFetchingInitialData,
14724
15014
  setIsImportingProjectFile,
15015
+ setIsLoading,
14725
15016
  setIssueComments,
14726
15017
  setIssues,
15018
+ setLicenses,
14727
15019
  setLoggedIn,
14728
15020
  setMapStyle,
14729
15021
  setOrganizationAccesses,
@@ -14763,6 +15055,7 @@ export {
14763
15055
  updateAttachment,
14764
15056
  updateComponent,
14765
15057
  updateIssue,
15058
+ updateLicense,
14766
15059
  updateOrCreateProject,
14767
15060
  updateOrCreateUserFormSubmission,
14768
15061
  updateOrganizationAccess,