@overmap-ai/core 1.0.22 → 1.0.23-organization-management.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -617,15 +617,15 @@ const wrapMigration = (migrator) => (state) => {
617
617
  };
618
618
  const migrations = [initialVersioning, signOut, signOut, createOutboxState];
619
619
  const manifest = Object.fromEntries(migrations.map((migration2, i) => [i, wrapMigration(migration2)]));
620
- const initialState$k = {
620
+ const initialState$l = {
621
621
  accessToken: "",
622
622
  refreshToken: "",
623
623
  isLoggedIn: false
624
624
  };
625
625
  const authSlice = createSlice({
626
626
  name: "auth",
627
- initialState: initialState$k,
628
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$k)),
627
+ initialState: initialState$l,
628
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$l)),
629
629
  reducers: {
630
630
  setTokens: (state, action) => {
631
631
  state.accessToken = action.payload.accessToken;
@@ -1328,7 +1328,7 @@ const getLocalRelativeDateString = memoize((date, min, max) => {
1328
1328
  return getLocalDateString(date);
1329
1329
  return relative.format(days, "days");
1330
1330
  });
1331
- const initialState$j = {
1331
+ const initialState$k = {
1332
1332
  categories: {},
1333
1333
  usedCategoryColors: [],
1334
1334
  categoryVisibility: {
@@ -1338,8 +1338,8 @@ const initialState$j = {
1338
1338
  };
1339
1339
  const categorySlice = createSlice({
1340
1340
  name: "categories",
1341
- initialState: initialState$j,
1342
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$j)),
1341
+ initialState: initialState$k,
1342
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$k)),
1343
1343
  reducers: {
1344
1344
  setCategories: (state, action) => {
1345
1345
  if (!Array.isArray(action.payload))
@@ -1472,13 +1472,13 @@ const selectHiddenCategoryCount = (state) => {
1472
1472
  return hiddenCategoryCount;
1473
1473
  };
1474
1474
  const categoryReducer = categorySlice.reducer;
1475
- const initialState$i = {
1475
+ const initialState$j = {
1476
1476
  components: {}
1477
1477
  };
1478
1478
  const componentSlice = createSlice({
1479
1479
  name: "components",
1480
- initialState: initialState$i,
1481
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$i)),
1480
+ initialState: initialState$j,
1481
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$j)),
1482
1482
  reducers: {
1483
1483
  addComponent: (state, action) => {
1484
1484
  state.components[action.payload.offline_id] = action.payload;
@@ -1590,13 +1590,13 @@ const {
1590
1590
  removeAllComponentsOfType
1591
1591
  } = componentSlice.actions;
1592
1592
  const componentReducer = componentSlice.reducer;
1593
- const initialState$h = {
1593
+ const initialState$i = {
1594
1594
  completionsByComponentId: {}
1595
1595
  };
1596
1596
  const componentStageCompletionSlice = createSlice({
1597
1597
  name: "componentStageCompletions",
1598
- initialState: initialState$h,
1599
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$h)),
1598
+ initialState: initialState$i,
1599
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$i)),
1600
1600
  reducers: {
1601
1601
  addStageCompletion: (state, action) => {
1602
1602
  let stageToCompletionDateMapping = state.completionsByComponentId[action.payload.component];
@@ -1647,13 +1647,13 @@ const selectCompletedStageIdsForComponent = (component) => (state) => {
1647
1647
  return Object.keys(state.componentStageCompletionReducer.completionsByComponentId[component.offline_id] ?? {});
1648
1648
  };
1649
1649
  const componentStageCompletionReducer = componentStageCompletionSlice.reducer;
1650
- const initialState$g = {
1650
+ const initialState$h = {
1651
1651
  stages: {}
1652
1652
  };
1653
1653
  const componentStageSlice = createSlice({
1654
1654
  name: "componentStages",
1655
- initialState: initialState$g,
1656
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$g)),
1655
+ initialState: initialState$h,
1656
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$h)),
1657
1657
  reducers: {
1658
1658
  addStages: (state, action) => {
1659
1659
  Object.assign(state.stages, toOfflineIdRecord(action.payload));
@@ -1713,14 +1713,14 @@ const selectStagesFromStageIds = restructureCreateSelectorWithArgs(
1713
1713
  );
1714
1714
  const { addStages, updateStages, removeStages } = componentStageSlice.actions;
1715
1715
  const componentStageReducer = componentStageSlice.reducer;
1716
- const initialState$f = {
1716
+ const initialState$g = {
1717
1717
  componentTypes: {},
1718
1718
  hiddenComponentTypeIds: {}
1719
1719
  };
1720
1720
  const componentTypeSlice = createSlice({
1721
1721
  name: "componentTypes",
1722
- initialState: initialState$f,
1723
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$f)),
1722
+ initialState: initialState$g,
1723
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$g)),
1724
1724
  reducers: {
1725
1725
  addComponentType: (state, action) => {
1726
1726
  state.componentTypes[action.payload.offline_id] = action.payload;
@@ -1779,13 +1779,13 @@ const selectComponentTypesByName = restructureCreateSelectorWithArgs(
1779
1779
  const selectHiddenComponentTypeIds = (state) => state.componentTypeReducer.hiddenComponentTypeIds;
1780
1780
  const { addComponentType, setComponentTypes, toggleComponentTypeVisibility, deleteComponentType } = componentTypeSlice.actions;
1781
1781
  const componentTypeReducer = componentTypeSlice.reducer;
1782
- const initialState$e = {
1782
+ const initialState$f = {
1783
1783
  workspaces: {},
1784
1784
  activeWorkspaceId: null
1785
1785
  };
1786
1786
  const workspaceSlice = createSlice({
1787
1787
  name: "workspace",
1788
- initialState: initialState$e,
1788
+ initialState: initialState$f,
1789
1789
  // The `reducers` field lets us define reducers and generate associated actions
1790
1790
  reducers: {
1791
1791
  setWorkspaces: (state, action) => {
@@ -1842,7 +1842,7 @@ const selectPermittedWorkspaceIds = createSelector(
1842
1842
  );
1843
1843
  const workspaceReducer = workspaceSlice.reducer;
1844
1844
  const maxRecentIssues = 10;
1845
- const initialState$d = {
1845
+ const initialState$e = {
1846
1846
  issues: {},
1847
1847
  attachments: {},
1848
1848
  comments: {},
@@ -1854,9 +1854,9 @@ const initialState$d = {
1854
1854
  };
1855
1855
  const issueSlice = createSlice({
1856
1856
  name: "issues",
1857
- initialState: initialState$d,
1857
+ initialState: initialState$e,
1858
1858
  extraReducers: (builder) => builder.addCase("RESET", (state) => {
1859
- Object.assign(state, initialState$d);
1859
+ Object.assign(state, initialState$e);
1860
1860
  }),
1861
1861
  reducers: {
1862
1862
  setIssues: (state, action) => {
@@ -2187,15 +2187,15 @@ const selectRecentIssuesAsSearchResults = createSelector(
2187
2187
  }
2188
2188
  );
2189
2189
  const issueReducer = issueSlice.reducer;
2190
- const initialState$c = {
2190
+ const initialState$d = {
2191
2191
  s3Urls: {}
2192
2192
  };
2193
2193
  const msPerHour = 1e3 * 60 * 60;
2194
2194
  const msPerWeek = msPerHour * 24 * 7;
2195
2195
  const fileSlice = createSlice({
2196
2196
  name: "file",
2197
- initialState: initialState$c,
2198
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$c)),
2197
+ initialState: initialState$d,
2198
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$d)),
2199
2199
  reducers: {
2200
2200
  setUploadUrl: (state, action) => {
2201
2201
  const { url, fields, sha1 } = action.payload;
@@ -2222,7 +2222,7 @@ const selectUploadUrl = (sha1) => (state) => {
2222
2222
  return url;
2223
2223
  };
2224
2224
  const fileReducer = fileSlice.reducer;
2225
- const initialState$b = {
2225
+ const initialState$c = {
2226
2226
  // TODO: Change first MapStyle.SATELLITE to MaptStyle.None when project creation map is fixed
2227
2227
  mapStyle: MapStyle.SATELLITE,
2228
2228
  showTooltips: false,
@@ -2230,8 +2230,8 @@ const initialState$b = {
2230
2230
  };
2231
2231
  const mapSlice = createSlice({
2232
2232
  name: "map",
2233
- initialState: initialState$b,
2234
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$b)),
2233
+ initialState: initialState$c,
2234
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$c)),
2235
2235
  reducers: {
2236
2236
  setMapStyle: (state, action) => {
2237
2237
  state.mapStyle = action.payload;
@@ -2249,26 +2249,211 @@ const selectMapStyle = (state) => state.mapReducer.mapStyle;
2249
2249
  const selectShowTooltips = (state) => state.mapReducer.showTooltips;
2250
2250
  const selectCenterMapToProject = (state) => state.mapReducer.centerMapToProject;
2251
2251
  const mapReducer = mapSlice.reducer;
2252
+ var ProjectAccessLevel = /* @__PURE__ */ ((ProjectAccessLevel2) => {
2253
+ ProjectAccessLevel2[ProjectAccessLevel2["BASIC"] = 0] = "BASIC";
2254
+ ProjectAccessLevel2[ProjectAccessLevel2["ADMIN"] = 2] = "ADMIN";
2255
+ return ProjectAccessLevel2;
2256
+ })(ProjectAccessLevel || {});
2257
+ var OrganizationAccessLevel = /* @__PURE__ */ ((OrganizationAccessLevel2) => {
2258
+ OrganizationAccessLevel2[OrganizationAccessLevel2["BASIC"] = 0] = "BASIC";
2259
+ OrganizationAccessLevel2[OrganizationAccessLevel2["ADMIN"] = 2] = "ADMIN";
2260
+ return OrganizationAccessLevel2;
2261
+ })(OrganizationAccessLevel || {});
2262
+ var ProjectType = /* @__PURE__ */ ((ProjectType2) => {
2263
+ ProjectType2[ProjectType2["PERSONAL"] = 0] = "PERSONAL";
2264
+ ProjectType2[ProjectType2["ORGANIZATION"] = 2] = "ORGANIZATION";
2265
+ return ProjectType2;
2266
+ })(ProjectType || {});
2267
+ var VerificationCodeType = /* @__PURE__ */ ((VerificationCodeType2) => {
2268
+ VerificationCodeType2[VerificationCodeType2["USER_REGISTRATION"] = 0] = "USER_REGISTRATION";
2269
+ VerificationCodeType2[VerificationCodeType2["APPLICATION_INVITE"] = 2] = "APPLICATION_INVITE";
2270
+ VerificationCodeType2[VerificationCodeType2["PROJECT_INVITE"] = 4] = "PROJECT_INVITE";
2271
+ VerificationCodeType2[VerificationCodeType2["ORGANIZATION_INVITE"] = 6] = "ORGANIZATION_INVITE";
2272
+ VerificationCodeType2[VerificationCodeType2["ADD_EMAIL_DOMAIN"] = 8] = "ADD_EMAIL_DOMAIN";
2273
+ VerificationCodeType2[VerificationCodeType2["RESET_PASSWORD"] = 10] = "RESET_PASSWORD";
2274
+ return VerificationCodeType2;
2275
+ })(VerificationCodeType || {});
2276
+ const initialState$b = {
2277
+ users: {},
2278
+ currentUser: {
2279
+ id: 0,
2280
+ username: "",
2281
+ email: "",
2282
+ profile: { file: null, file_sha1: null, favourite_project_ids: [], tour_step: -1 }
2283
+ }
2284
+ };
2285
+ const userSlice = createSlice({
2286
+ name: "users",
2287
+ initialState: initialState$b,
2288
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$b)),
2289
+ reducers: {
2290
+ setUsers: (state, action) => {
2291
+ const usersMapping = {};
2292
+ action.payload.forEach((user) => {
2293
+ usersMapping[user.id] = user;
2294
+ });
2295
+ state.users = usersMapping;
2296
+ },
2297
+ addUsers: (state, action) => {
2298
+ action.payload.forEach((user) => {
2299
+ state.users[user.id] = user;
2300
+ });
2301
+ },
2302
+ setCurrentUser: (state, action) => {
2303
+ state.currentUser = action.payload;
2304
+ },
2305
+ setProfilePicture: (state, action) => {
2306
+ state.currentUser.profile.file = action.payload.file ?? null;
2307
+ state.currentUser.profile.file_sha1 = action.payload.file_sha1 ?? null;
2308
+ const currentUser = state.users[state.currentUser.id];
2309
+ if (!currentUser) {
2310
+ throw new Error("Unable to find current user in users slice");
2311
+ }
2312
+ currentUser.profile.file = action.payload.file ?? null;
2313
+ currentUser.profile.file_sha1 = action.payload.file_sha1 ?? null;
2314
+ },
2315
+ addFavouriteProjectId: (state, action) => {
2316
+ state.currentUser.profile.favourite_project_ids.push(action.payload);
2317
+ },
2318
+ removeFavouriteProjectId: (state, action) => {
2319
+ state.currentUser.profile.favourite_project_ids = state.currentUser.profile.favourite_project_ids.filter(
2320
+ (id) => id !== action.payload
2321
+ );
2322
+ },
2323
+ setTourStep: (state, action) => {
2324
+ state.currentUser.profile.tour_step = action.payload;
2325
+ },
2326
+ removeUser: (state, action) => {
2327
+ delete state.users[action.payload];
2328
+ }
2329
+ }
2330
+ });
2331
+ const {
2332
+ setCurrentUser,
2333
+ setProfilePicture,
2334
+ setUsers,
2335
+ addUsers,
2336
+ addFavouriteProjectId,
2337
+ removeFavouriteProjectId,
2338
+ setTourStep,
2339
+ removeUser
2340
+ } = userSlice.actions;
2341
+ const selectCurrentUser = (state) => state.userReducer.currentUser;
2342
+ const selectUser = (userId) => (state) => {
2343
+ if (userId === null)
2344
+ return void 0;
2345
+ return state.userReducer.users[userId];
2346
+ };
2347
+ const selectUsersAsMapping = (state) => state.userReducer.users;
2348
+ const selectFavouriteProjects = (state) => state.userReducer.currentUser.profile.favourite_project_ids;
2349
+ const userReducer = userSlice.reducer;
2252
2350
  const initialState$a = {
2351
+ organizationAccesses: {},
2352
+ activeOrganizationAccessId: null
2353
+ };
2354
+ const organizationAccessSlice = createSlice({
2355
+ name: "organizationAccess",
2356
+ initialState: initialState$a,
2357
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$a)),
2358
+ reducers: {
2359
+ setOrganizationAccesses: (state, action) => {
2360
+ if (!Array.isArray(action.payload))
2361
+ throw new Error("Expected an array of OrganizationAccess");
2362
+ if (action.payload.filter(onlyUniqueOfflineIds).length !== action.payload.length) {
2363
+ throw new Error("Tried to use setOrganizationAccesses reducer with duplicate ID's");
2364
+ }
2365
+ const organizationAccesses = {};
2366
+ for (const organizationAccess of action.payload) {
2367
+ organizationAccesses[organizationAccess.offline_id] = organizationAccess;
2368
+ }
2369
+ state.organizationAccesses = organizationAccesses;
2370
+ },
2371
+ updateOrganizationAccess: (state, action) => {
2372
+ if (action.payload.offline_id in state.organizationAccesses) {
2373
+ state.organizationAccesses[action.payload.offline_id] = action.payload;
2374
+ } else {
2375
+ throw new Error(
2376
+ `Tried to update organization access with ID that doesn't exist: ${action.payload.offline_id}`
2377
+ );
2378
+ }
2379
+ },
2380
+ removeOrganizationAccess: (state, action) => {
2381
+ if (action.payload.offline_id in state.organizationAccesses) {
2382
+ delete state.organizationAccesses[action.payload.offline_id];
2383
+ } else {
2384
+ throw new Error(
2385
+ `Tried to remove organization access with ID that doesn't exist: ${action.payload.offline_id}`
2386
+ );
2387
+ }
2388
+ },
2389
+ setActiveOrganizationAccessId: (state, action) => {
2390
+ state.activeOrganizationAccessId = action.payload;
2391
+ }
2392
+ }
2393
+ });
2394
+ const {
2395
+ setOrganizationAccesses,
2396
+ updateOrganizationAccess,
2397
+ removeOrganizationAccess,
2398
+ setActiveOrganizationAccessId
2399
+ } = organizationAccessSlice.actions;
2400
+ const selectOrganizationAccesses = (state) => {
2401
+ return state.organizationAccessReducer.organizationAccesses;
2402
+ };
2403
+ const selectOrganizationAccess = (organizationAccessId) => (state) => {
2404
+ return state.organizationAccessReducer.organizationAccesses[organizationAccessId];
2405
+ };
2406
+ const selectActiveOrganizationAccess = (state) => {
2407
+ const activeOrganizationAccessId = state.organizationAccessReducer.activeOrganizationAccessId;
2408
+ if (!activeOrganizationAccessId) {
2409
+ return null;
2410
+ }
2411
+ return state.organizationAccessReducer.organizationAccesses[activeOrganizationAccessId] ?? null;
2412
+ };
2413
+ const selectOrganizationAccessForUser = (user) => (state) => {
2414
+ return Object.values(state.organizationAccessReducer.organizationAccesses).find(
2415
+ (organizationAccess) => organizationAccess.user === user.id
2416
+ );
2417
+ };
2418
+ const selectOrganizationAccessUserMapping = (state) => {
2419
+ const organizationAccesses = {};
2420
+ Object.values(state.organizationAccessReducer.organizationAccesses).forEach(
2421
+ (organizationAccess) => {
2422
+ organizationAccesses[organizationAccess.user] = organizationAccess;
2423
+ }
2424
+ );
2425
+ return organizationAccesses;
2426
+ };
2427
+ const organizationAccessReducer = organizationAccessSlice.reducer;
2428
+ const initialState$9 = {
2253
2429
  organizations: {},
2254
- activeOrganizationId: null
2430
+ activeOrganizationId: 0
2255
2431
  };
2256
2432
  const organizationSlice = createSlice({
2257
2433
  name: "organizations",
2258
- initialState: initialState$a,
2259
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$a)),
2434
+ initialState: initialState$9,
2435
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$9)),
2260
2436
  reducers: {
2261
2437
  setOrganizations: (state, action) => {
2262
2438
  for (const org of action.payload) {
2263
2439
  state.organizations[org.id] = org;
2264
2440
  }
2265
2441
  },
2442
+ setActiveOrganization: (state, action) => {
2443
+ if (!state.activeOrganizationId) {
2444
+ throw new Error("Cannot update name of active organization. Active organization ID does not exist");
2445
+ }
2446
+ if (state.activeOrganizationId !== action.payload.id) {
2447
+ throw new Error("Tried updating active organization with different organization");
2448
+ }
2449
+ state.organizations[state.activeOrganizationId] = action.payload;
2450
+ },
2266
2451
  setActiveOrganizationId: (state, action) => {
2267
2452
  state.activeOrganizationId = action.payload;
2268
2453
  }
2269
2454
  }
2270
2455
  });
2271
- const { setOrganizations, setActiveOrganizationId } = organizationSlice.actions;
2456
+ const { setOrganizations, setActiveOrganizationId, setActiveOrganization } = organizationSlice.actions;
2272
2457
  const selectActiveOrganizationId = (state) => {
2273
2458
  return state.organizationReducer.activeOrganizationId;
2274
2459
  };
@@ -2286,6 +2471,34 @@ const selectActiveOrganization = (state) => {
2286
2471
  }
2287
2472
  return organization;
2288
2473
  };
2474
+ const selectOrganizationUsersIds = (state) => Object.values(state.organizationAccessReducer.organizationAccesses).map(
2475
+ (organizationAccess) => organizationAccess.user
2476
+ );
2477
+ const selectOrganizationUsersAsMapping = (state) => selectOrganizationUsersIds(state).reduce(
2478
+ (accum, userId) => ({ ...accum, [userId]: state.userReducer.users[userId] }),
2479
+ {}
2480
+ );
2481
+ const selectSortedOrganizationUsers = createSelector(
2482
+ [selectCurrentUser, selectOrganizationUsersAsMapping, selectOrganizationAccessUserMapping],
2483
+ (currentUser, userMapping, organizationAccessMapping) => {
2484
+ return Object.values(userMapping).sort((userA, userB) => {
2485
+ if (userA.id === currentUser.id) {
2486
+ return -1;
2487
+ } else if (userB.id === currentUser.id) {
2488
+ return 1;
2489
+ }
2490
+ const organizationAccessesA = organizationAccessMapping[userA.id];
2491
+ const organizationAccessesB = organizationAccessMapping[userB.id];
2492
+ if ((organizationAccessesA == null ? void 0 : organizationAccessesA.access_level) === (organizationAccessesB == null ? void 0 : organizationAccessesB.access_level)) {
2493
+ return userA.username.localeCompare(userB.username);
2494
+ }
2495
+ if ((organizationAccessesA == null ? void 0 : organizationAccessesA.access_level) === OrganizationAccessLevel.ADMIN) {
2496
+ return -1;
2497
+ }
2498
+ return 1;
2499
+ });
2500
+ }
2501
+ );
2289
2502
  const selectOrganization = (id) => (state) => {
2290
2503
  return state.organizationReducer.organizations[id];
2291
2504
  };
@@ -2306,14 +2519,14 @@ const createOfflineAction = (request2, baseUrl) => {
2306
2519
  }
2307
2520
  };
2308
2521
  };
2309
- const initialState$9 = {
2522
+ const initialState$8 = {
2310
2523
  deletedRequests: [],
2311
2524
  latestRetryTime: 0
2312
2525
  };
2313
2526
  const outboxSlice = createSlice({
2314
2527
  name: "outbox",
2315
- initialState: initialState$9,
2316
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$9)),
2528
+ initialState: initialState$8,
2529
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$8)),
2317
2530
  reducers: {
2318
2531
  // enqueueActions is a reducer that does nothing but enqueue API request to the Redux Offline outbox
2319
2532
  // Whenever an issue is being created, a reducer addIssue() is responsible for adding it to the offline store
@@ -2345,13 +2558,13 @@ const selectDeletedRequests = (state) => state.outboxReducer.deletedRequests;
2345
2558
  const selectLatestRetryTime = (state) => state.outboxReducer.latestRetryTime;
2346
2559
  const { enqueueRequest, markForDeletion, markAsDeleted, _setLatestRetryTime } = outboxSlice.actions;
2347
2560
  const outboxReducer = outboxSlice.reducer;
2348
- const initialState$8 = {
2561
+ const initialState$7 = {
2349
2562
  projectAccesses: {}
2350
2563
  };
2351
2564
  const projectAccessSlice = createSlice({
2352
2565
  name: "projectAccess",
2353
- initialState: initialState$8,
2354
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$8)),
2566
+ initialState: initialState$7,
2567
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$7)),
2355
2568
  reducers: {
2356
2569
  setProjectAccesses: (state, action) => {
2357
2570
  if (!Array.isArray(action.payload))
@@ -2384,11 +2597,11 @@ const projectAccessSlice = createSlice({
2384
2597
  }
2385
2598
  },
2386
2599
  removeProjectAccessesOfProject: (state, action) => {
2387
- for (const projectAccess of Object.values(state.projectAccesses)) {
2600
+ Object.values(state.projectAccesses).forEach((projectAccess) => {
2388
2601
  if (projectAccess.project === action.payload) {
2389
2602
  delete state.projectAccesses[projectAccess.offline_id];
2390
2603
  }
2391
- }
2604
+ });
2392
2605
  }
2393
2606
  }
2394
2607
  });
@@ -2413,37 +2626,13 @@ const selectProjectAccessForUser = (user) => (state) => {
2413
2626
  };
2414
2627
  const selectProjectAccessUserMapping = (state) => {
2415
2628
  const projectAccesses = {};
2416
- for (const projectAccess of Object.values(state.projectAccessReducer.projectAccesses)) {
2629
+ Object.values(state.projectAccessReducer.projectAccesses).forEach((projectAccess) => {
2417
2630
  projectAccesses[projectAccess.user] = projectAccess;
2418
- }
2631
+ });
2419
2632
  return projectAccesses;
2420
2633
  };
2421
2634
  const projectAccessReducer = projectAccessSlice.reducer;
2422
- var ProjectAccessLevel = /* @__PURE__ */ ((ProjectAccessLevel2) => {
2423
- ProjectAccessLevel2[ProjectAccessLevel2["BASIC"] = 0] = "BASIC";
2424
- ProjectAccessLevel2[ProjectAccessLevel2["ADMIN"] = 2] = "ADMIN";
2425
- return ProjectAccessLevel2;
2426
- })(ProjectAccessLevel || {});
2427
- var OrganizationAccessLevel = /* @__PURE__ */ ((OrganizationAccessLevel2) => {
2428
- OrganizationAccessLevel2[OrganizationAccessLevel2["BASIC"] = 0] = "BASIC";
2429
- OrganizationAccessLevel2[OrganizationAccessLevel2["ADMIN"] = 2] = "ADMIN";
2430
- return OrganizationAccessLevel2;
2431
- })(OrganizationAccessLevel || {});
2432
- var ProjectType = /* @__PURE__ */ ((ProjectType2) => {
2433
- ProjectType2[ProjectType2["PERSONAL"] = 0] = "PERSONAL";
2434
- ProjectType2[ProjectType2["ORGANIZATION"] = 2] = "ORGANIZATION";
2435
- return ProjectType2;
2436
- })(ProjectType || {});
2437
- var VerificationCodeType = /* @__PURE__ */ ((VerificationCodeType2) => {
2438
- VerificationCodeType2[VerificationCodeType2["USER_REGISTRATION"] = 0] = "USER_REGISTRATION";
2439
- VerificationCodeType2[VerificationCodeType2["APPLICATION_INVITE"] = 2] = "APPLICATION_INVITE";
2440
- VerificationCodeType2[VerificationCodeType2["PROJECT_INVITE"] = 4] = "PROJECT_INVITE";
2441
- VerificationCodeType2[VerificationCodeType2["ORGANIZATION_INVITE"] = 6] = "ORGANIZATION_INVITE";
2442
- VerificationCodeType2[VerificationCodeType2["ADD_EMAIL_DOMAIN"] = 8] = "ADD_EMAIL_DOMAIN";
2443
- VerificationCodeType2[VerificationCodeType2["RESET_PASSWORD"] = 10] = "RESET_PASSWORD";
2444
- return VerificationCodeType2;
2445
- })(VerificationCodeType || {});
2446
- const initialState$7 = {
2635
+ const initialState$6 = {
2447
2636
  projects: {},
2448
2637
  activeProjectId: null,
2449
2638
  recentProjectIds: [],
@@ -2452,7 +2641,7 @@ const initialState$7 = {
2452
2641
  };
2453
2642
  const projectSlice = createSlice({
2454
2643
  name: "projects",
2455
- initialState: initialState$7,
2644
+ initialState: initialState$6,
2456
2645
  reducers: {
2457
2646
  setProjects: (state, action) => {
2458
2647
  const projectsMap = {};
@@ -2509,14 +2698,42 @@ const selectActiveProject = (state) => {
2509
2698
  if (!activeProjectId) {
2510
2699
  return null;
2511
2700
  }
2512
- return state.projectReducer.projects[activeProjectId] ?? null;
2513
- };
2514
- const selectRecentProjects = (state) => {
2515
- return state.projectReducer.recentProjectIds;
2516
- };
2517
- const selectCreateProjectType = (state) => state.projectReducer.createProjectType;
2518
- const projectReducer = projectSlice.reducer;
2519
- const initialState$6 = {
2701
+ return state.projectReducer.projects[activeProjectId] ?? null;
2702
+ };
2703
+ const selectRecentProjects = (state) => {
2704
+ return state.projectReducer.recentProjectIds;
2705
+ };
2706
+ const selectCreateProjectType = (state) => state.projectReducer.createProjectType;
2707
+ const projectReducer = projectSlice.reducer;
2708
+ const selectProjectUsersIds = (state) => Object.values(state.projectAccessReducer.projectAccesses).map(
2709
+ (projectAccesses) => projectAccesses.user
2710
+ );
2711
+ const selectProjectUsersAsMapping = (state) => selectProjectUsersIds(state).reduce(
2712
+ (accum, userId) => ({ ...accum, [userId]: state.userReducer.users[userId] }),
2713
+ {}
2714
+ );
2715
+ const selectSortedProjectUsers = createSelector(
2716
+ [selectCurrentUser, selectProjectUsersAsMapping, selectProjectAccessUserMapping],
2717
+ (currentUser, userMapping, projectAccessMapping) => {
2718
+ return Object.values(userMapping).sort((userA, userB) => {
2719
+ if (userA.id === currentUser.id) {
2720
+ return -1;
2721
+ } else if (userB.id === currentUser.id) {
2722
+ return 1;
2723
+ }
2724
+ const projectAccessesA = projectAccessMapping[userA.id];
2725
+ const projectAccessesB = projectAccessMapping[userB.id];
2726
+ if ((projectAccessesA == null ? void 0 : projectAccessesA.access_level) === (projectAccessesB == null ? void 0 : projectAccessesB.access_level)) {
2727
+ return userA.username.localeCompare(userB.username);
2728
+ }
2729
+ if ((projectAccessesA == null ? void 0 : projectAccessesA.access_level) === ProjectAccessLevel.ADMIN) {
2730
+ return -1;
2731
+ }
2732
+ return 1;
2733
+ });
2734
+ }
2735
+ );
2736
+ const initialState$5 = {
2520
2737
  projectFiles: {},
2521
2738
  activeProjectFileId: null,
2522
2739
  isImportingProjectFile: false,
@@ -2524,8 +2741,8 @@ const initialState$6 = {
2524
2741
  };
2525
2742
  const projectFileSlice = createSlice({
2526
2743
  name: "projectFiles",
2527
- initialState: initialState$6,
2528
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$6)),
2744
+ initialState: initialState$5,
2745
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$5)),
2529
2746
  reducers: {
2530
2747
  addOrReplaceProjectFiles: (state, action) => {
2531
2748
  for (let fileObj of action.payload) {
@@ -2626,12 +2843,12 @@ const selectProjectFiles = createSelector(
2626
2843
  const selectActiveProjectFileId = (state) => state.projectFileReducer.activeProjectFileId;
2627
2844
  const selectIsImportingProjectFile = (state) => state.projectFileReducer.isImportingProjectFile;
2628
2845
  const projectFileReducer = projectFileSlice.reducer;
2629
- const initialState$5 = {
2846
+ const initialState$4 = {
2630
2847
  isRehydrated: false
2631
2848
  };
2632
2849
  const rehydratedSlice = createSlice({
2633
2850
  name: "rehydrated",
2634
- initialState: initialState$5,
2851
+ initialState: initialState$4,
2635
2852
  // The `reducers` field lets us define reducers and generate associated actions
2636
2853
  reducers: {
2637
2854
  setRehydrated: (state, action) => {
@@ -2641,7 +2858,7 @@ const rehydratedSlice = createSlice({
2641
2858
  });
2642
2859
  const selectRehydrated = (state) => state.rehydratedReducer.isRehydrated;
2643
2860
  const rehydratedReducer = rehydratedSlice.reducer;
2644
- const initialState$4 = {
2861
+ const initialState$3 = {
2645
2862
  useIssueTemplate: false,
2646
2863
  placementMode: false,
2647
2864
  enableClustering: true,
@@ -2656,8 +2873,8 @@ const initialState$4 = {
2656
2873
  };
2657
2874
  const settingSlice = createSlice({
2658
2875
  name: "settings",
2659
- initialState: initialState$4,
2660
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$4)),
2876
+ initialState: initialState$3,
2877
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$3)),
2661
2878
  reducers: {
2662
2879
  setEnableDuplicateIssues: (state, action) => {
2663
2880
  state.useIssueTemplate = action.payload;
@@ -2720,7 +2937,7 @@ function considerCachingRevision(revision, formId, preferPending = false) {
2720
2937
  function getLatestRevisionFromCache(formId) {
2721
2938
  return LATEST_REVISION_CACHE[formId];
2722
2939
  }
2723
- const initialState$3 = {
2940
+ const initialState$2 = {
2724
2941
  userForms: {},
2725
2942
  revisions: {},
2726
2943
  submissions: {},
@@ -2728,8 +2945,8 @@ const initialState$3 = {
2728
2945
  };
2729
2946
  const userFormSlice = createSlice({
2730
2947
  name: "userForms",
2731
- initialState: initialState$3,
2732
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$3)),
2948
+ initialState: initialState$2,
2949
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$2)),
2733
2950
  reducers: {
2734
2951
  setUserForms: (state, action) => {
2735
2952
  state.userForms = {};
@@ -2977,171 +3194,38 @@ const selectNumberOfUserForms = createSelector([selectUserFormMapping], (userFor
2977
3194
  return Object.keys(userForms).length;
2978
3195
  });
2979
3196
  const userFormReducer = userFormSlice.reducer;
2980
- const initialState$2 = {
2981
- users: {},
2982
- currentUser: {
2983
- id: 0,
2984
- username: "",
2985
- email: "",
2986
- profile: { file: null, file_sha1: null, favourite_project_ids: [], tour_step: -1 }
2987
- }
2988
- };
2989
- const userSlice = createSlice({
2990
- name: "users",
2991
- initialState: initialState$2,
2992
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$2)),
2993
- reducers: {
2994
- setUsers: (state, action) => {
2995
- const usersMapping = {};
2996
- action.payload.forEach((user) => {
2997
- usersMapping[user.id] = user;
2998
- });
2999
- state.users = usersMapping;
3000
- },
3001
- setCurrentUser: (state, action) => {
3002
- state.currentUser = action.payload;
3003
- },
3004
- setProfilePicture: (state, action) => {
3005
- state.currentUser.profile.file = action.payload.file ?? null;
3006
- state.currentUser.profile.file_sha1 = action.payload.file_sha1 ?? null;
3007
- const currentUser = state.users[state.currentUser.id];
3008
- if (!currentUser) {
3009
- throw new Error("Unable to find current user in users slice");
3010
- }
3011
- currentUser.profile.file = action.payload.file ?? null;
3012
- currentUser.profile.file_sha1 = action.payload.file_sha1 ?? null;
3013
- },
3014
- addFavouriteProjectId: (state, action) => {
3015
- state.currentUser.profile.favourite_project_ids.push(action.payload);
3016
- },
3017
- removeFavouriteProjectId: (state, action) => {
3018
- state.currentUser.profile.favourite_project_ids = state.currentUser.profile.favourite_project_ids.filter(
3019
- (id) => id !== action.payload
3020
- );
3021
- },
3022
- setTourStep: (state, action) => {
3023
- state.currentUser.profile.tour_step = action.payload;
3024
- },
3025
- removeUser: (state, action) => {
3026
- delete state.users[action.payload];
3027
- }
3028
- }
3029
- });
3030
- const {
3031
- setCurrentUser,
3032
- setProfilePicture,
3033
- setUsers,
3034
- addFavouriteProjectId,
3035
- removeFavouriteProjectId,
3036
- setTourStep,
3037
- removeUser
3038
- } = userSlice.actions;
3039
- const selectCurrentUser = (state) => state.userReducer.currentUser;
3040
- const selectUser = (userId) => (state) => {
3041
- if (userId === null)
3042
- return void 0;
3043
- return state.userReducer.users[userId];
3044
- };
3045
- const selectUsersAsMapping = (state) => state.userReducer.users;
3046
- const selectFavouriteProjects = (state) => state.userReducer.currentUser.profile.favourite_project_ids;
3047
- const selectSortedUsers = createSelector(
3048
- [selectCurrentUser, selectUsersAsMapping, selectProjectAccessUserMapping],
3049
- (currentUser, userMapping, projectAccessMapping) => {
3050
- return Object.values(userMapping).sort((userA, userB) => {
3051
- if (userA.id === currentUser.id) {
3052
- return -1;
3053
- } else if (userB.id === currentUser.id) {
3054
- return 1;
3055
- }
3056
- const projectAccessesA = projectAccessMapping[userA.id];
3057
- const projectAccessesB = projectAccessMapping[userB.id];
3058
- if ((projectAccessesA == null ? void 0 : projectAccessesA.access_level) === (projectAccessesB == null ? void 0 : projectAccessesB.access_level)) {
3059
- return userA.username.localeCompare(userB.username);
3060
- }
3061
- if ((projectAccessesA == null ? void 0 : projectAccessesA.access_level) === ProjectAccessLevel.ADMIN) {
3062
- return -1;
3063
- }
3064
- return 1;
3065
- });
3066
- }
3067
- );
3068
- const userReducer = userSlice.reducer;
3069
3197
  const initialState$1 = {
3070
- organizationAccesses: {},
3071
- activeOrganizationAccessId: null
3198
+ emailDomains: {}
3072
3199
  };
3073
- const organizationAccessSlice = createSlice({
3074
- name: "organizationAccess",
3200
+ const emailDomainsSlice = createSlice({
3201
+ name: "emailDomains",
3075
3202
  initialState: initialState$1,
3076
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$1)),
3077
3203
  reducers: {
3078
- setOrganizationAccesses: (state, action) => {
3079
- if (!Array.isArray(action.payload))
3080
- throw new Error("Expected an array of OrganizationAccess");
3081
- if (action.payload.filter(onlyUniqueOfflineIds).length !== action.payload.length) {
3082
- throw new Error("Tried to use setOrganizationAccesses reducer with duplicate ID's");
3083
- }
3084
- const organizationAccesses = {};
3085
- for (const organizationAccess of action.payload) {
3086
- organizationAccesses[organizationAccess.offline_id] = organizationAccess;
3087
- }
3088
- state.organizationAccesses = organizationAccesses;
3204
+ setEmailDomains: (state, action) => {
3205
+ const emailDomains = {};
3206
+ action.payload.forEach((emailDomain) => {
3207
+ emailDomains[emailDomain.offline_id] = emailDomain;
3208
+ });
3209
+ state.emailDomains = emailDomains;
3089
3210
  },
3090
- updateOrganizationAccess: (state, action) => {
3091
- if (action.payload.offline_id in state.organizationAccesses) {
3092
- state.organizationAccesses[action.payload.offline_id] = action.payload;
3093
- } else {
3094
- throw new Error(
3095
- `Tried to update organization access with ID that doesn't exist: ${action.payload.offline_id}`
3096
- );
3097
- }
3211
+ addEmailDomain: (state, action) => {
3212
+ state.emailDomains[action.payload.offline_id] = action.payload;
3098
3213
  },
3099
- removeOrganizationAccess: (state, action) => {
3100
- if (action.payload.offline_id in state.organizationAccesses) {
3101
- delete state.organizationAccesses[action.payload.offline_id];
3214
+ removeEmailDomain: (state, action) => {
3215
+ if (action.payload.offline_id in state.emailDomains) {
3216
+ delete state.emailDomains[action.payload.offline_id];
3102
3217
  } else {
3103
- throw new Error(
3104
- `Tried to remove organization access with ID that doesn't exist: ${action.payload.offline_id}`
3105
- );
3218
+ throw new Error(`Tried to remove email domain with ID that doesn't exist: ${action.payload.offline_id}`);
3106
3219
  }
3107
- },
3108
- setActiveOrganizationAccessId: (state, action) => {
3109
- state.activeOrganizationAccessId = action.payload;
3110
3220
  }
3111
3221
  }
3112
3222
  });
3113
- const {
3114
- setOrganizationAccesses,
3115
- updateOrganizationAccess,
3116
- removeOrganizationAccess,
3117
- setActiveOrganizationAccessId
3118
- } = organizationAccessSlice.actions;
3119
- const selectOrganizationAccesses = (state) => {
3120
- return state.organizationAccessReducer.organizationAccesses;
3121
- };
3122
- const selectOrganizationAccess = (organizationAccessId) => (state) => {
3123
- return state.organizationAccessReducer.organizationAccesses[organizationAccessId];
3124
- };
3125
- const selectActiveOrganizationAccess = (state) => {
3126
- const activeOrganizationAccessId = state.organizationAccessReducer.activeOrganizationAccessId;
3127
- if (!activeOrganizationAccessId) {
3128
- return null;
3129
- }
3130
- return state.organizationAccessReducer.organizationAccesses[activeOrganizationAccessId] ?? null;
3131
- };
3132
- const selectOrganizationAccessForUser = (user) => (state) => {
3133
- return Object.values(state.organizationAccessReducer.organizationAccesses).find(
3134
- (organizationAccess) => organizationAccess.user === user.id
3135
- );
3136
- };
3137
- const selectOrganizationAccessUserMapping = (state) => {
3138
- const organizationAccesses = {};
3139
- Object.values(state.organizationAccessReducer.organizationAccesses).forEach((organizationAccess) => {
3140
- organizationAccesses[organizationAccess.user] = organizationAccess;
3141
- });
3142
- return organizationAccesses;
3143
- };
3144
- const organizationAccessReducer = organizationAccessSlice.reducer;
3223
+ const { setEmailDomains, addEmailDomain, removeEmailDomain } = emailDomainsSlice.actions;
3224
+ const selectEmailDomainsAsMapping = (state) => state.emailDomainsReducer.emailDomains;
3225
+ const selectSortedEmailDomains = (state) => Object.values(state.emailDomainsReducer.emailDomains).sort(
3226
+ (ed1, ed2) => ed1.domain.localeCompare(ed2.domain)
3227
+ );
3228
+ const emailDomainsReducer = emailDomainsSlice.reducer;
3145
3229
  const initialState = {
3146
3230
  version: 0
3147
3231
  };
@@ -3178,7 +3262,8 @@ const overmapReducers = {
3178
3262
  settingReducer,
3179
3263
  userFormReducer,
3180
3264
  userReducer,
3181
- workspaceReducer
3265
+ workspaceReducer,
3266
+ emailDomainsReducer
3182
3267
  };
3183
3268
  const overmapReducer = combineReducers(overmapReducers);
3184
3269
  const resetStore = "RESET";
@@ -4707,7 +4792,7 @@ class MainService extends BaseApiService {
4707
4792
  return result;
4708
4793
  });
4709
4794
  }
4710
- async fetchUsers(projectId) {
4795
+ async fetchProjectUsers(projectId) {
4711
4796
  return this.enqueueRequest({
4712
4797
  description: "Fetch users",
4713
4798
  method: HttpMethod.GET,
@@ -4716,6 +4801,15 @@ class MainService extends BaseApiService {
4716
4801
  blocks: []
4717
4802
  });
4718
4803
  }
4804
+ async fetchOrganizationUsers(orgId) {
4805
+ return this.enqueueRequest({
4806
+ description: "Fetch organization users",
4807
+ method: HttpMethod.GET,
4808
+ url: `/organizations/${orgId}/users/`,
4809
+ blockers: [],
4810
+ blocks: []
4811
+ });
4812
+ }
4719
4813
  // TODO:
4720
4814
  // Don't accept updateStore in ComponentService.list. Just return the offline objects and promise. Here, if
4721
4815
  // overwrite, use setComponents. Otherwise, use bulkAddComponents.
@@ -4758,13 +4852,22 @@ class MainService extends BaseApiService {
4758
4852
  const firstOrg = organizationsData[0];
4759
4853
  const currProjObj = projects.find((project) => project.id === currentProjectId);
4760
4854
  const isOrgProject = !!(currProjObj == null ? void 0 : currProjObj.owner_organization);
4855
+ let currentOrgId = -1;
4761
4856
  if (isOrgProject && currProjObj.owner_organization) {
4762
- store.dispatch(setActiveOrganizationId(currProjObj.owner_organization));
4857
+ currentOrgId = currProjObj.owner_organization;
4763
4858
  } else if (firstOrg) {
4764
4859
  console.warn(
4765
4860
  "No active organization; using the first available one. TODO: No active organization in personal projects."
4766
4861
  );
4767
- store.dispatch(setActiveOrganizationId(firstOrg.id));
4862
+ currentOrgId = firstOrg.id;
4863
+ }
4864
+ if (currentOrgId !== -1) {
4865
+ store.dispatch(setActiveOrganizationId(currentOrgId));
4866
+ const orgUsersResultPromise = this.fetchOrganizationUsers(currentOrgId);
4867
+ const organizationAccessRefreshPromise = this.client.organizationAccess.refreshStore();
4868
+ const orgUsersResult = await orgUsersResultPromise;
4869
+ await organizationAccessRefreshPromise;
4870
+ store.dispatch(addUsers(orgUsersResult));
4768
4871
  }
4769
4872
  if (!isProjectIdValid) {
4770
4873
  if (projects.length !== 0) {
@@ -4787,13 +4890,11 @@ class MainService extends BaseApiService {
4787
4890
  }
4788
4891
  }
4789
4892
  if (currentProjectId) {
4790
- const usersResultPromise = this.fetchUsers(currentProjectId);
4893
+ const usersResultPromise = this.fetchProjectUsers(currentProjectId);
4791
4894
  const projectAccessRefreshPromise = this.client.projectAccesses.refreshStore();
4792
- const organizationAccessRefreshPromise = this.client.organizationAccess.refreshStore();
4793
4895
  const usersResult = await usersResultPromise;
4794
4896
  await projectAccessRefreshPromise;
4795
- await organizationAccessRefreshPromise;
4796
- store.dispatch(setUsers(usersResult));
4897
+ store.dispatch(addUsers(usersResult));
4797
4898
  }
4798
4899
  let currentWorkspaceId;
4799
4900
  const oldWorkspaceId = this.client.store.getState().workspaceReducer.activeWorkspaceId;
@@ -4819,6 +4920,7 @@ class MainService extends BaseApiService {
4819
4920
  void this.client.userForms.refreshStore().then(() => {
4820
4921
  void this.client.userFormSubmissions.refreshStore().then();
4821
4922
  });
4923
+ void this.client.emailDomains.refreshStore().then();
4822
4924
  }
4823
4925
  if (currentProjectId) {
4824
4926
  const [_offlineAttachments, promise] = this.client.attachments.fetchAll(currentProjectId);
@@ -4842,8 +4944,7 @@ class MainService extends BaseApiService {
4842
4944
  }
4843
4945
  }
4844
4946
  class ProjectAccessService extends BaseApiService {
4845
- fetchAll(projectId) {
4846
- const { store } = this.client;
4947
+ async fetchAll(projectId) {
4847
4948
  const promise = this.enqueueRequest({
4848
4949
  description: "Get project accesses",
4849
4950
  method: HttpMethod.GET,
@@ -4851,12 +4952,11 @@ class ProjectAccessService extends BaseApiService {
4851
4952
  blockers: [],
4852
4953
  blocks: []
4853
4954
  });
4854
- const offlineProjectAccesses = Object.values(store.getState().projectAccessReducer.projectAccesses);
4855
- return [offlineProjectAccesses, promise];
4955
+ return promise;
4856
4956
  }
4857
- update(projectAccess) {
4957
+ async update(projectAccess) {
4858
4958
  this.client.store.dispatch(updateProjectAccess(projectAccess));
4859
- const promise = this.enqueueRequest({
4959
+ return this.enqueueRequest({
4860
4960
  description: "Edit project access",
4861
4961
  method: HttpMethod.PATCH,
4862
4962
  url: `/access/${projectAccess.offline_id}/`,
@@ -4864,10 +4964,9 @@ class ProjectAccessService extends BaseApiService {
4864
4964
  blockers: [projectAccess.offline_id],
4865
4965
  blocks: [projectAccess.offline_id]
4866
4966
  });
4867
- return [projectAccess, promise];
4868
4967
  }
4869
4968
  // TODO: Re-add user to project if removal fails
4870
- remove(projectAccess) {
4969
+ async remove(projectAccess) {
4871
4970
  const { store } = this.client;
4872
4971
  store.dispatch(removeProjectAccess(projectAccess));
4873
4972
  store.dispatch(removeUser(projectAccess.user));
@@ -4887,7 +4986,7 @@ class ProjectAccessService extends BaseApiService {
4887
4986
  if (!projectId) {
4888
4987
  throw new Error("No active project");
4889
4988
  }
4890
- const [_offlineProjectAccesses, promise] = this.fetchAll(projectId);
4989
+ const promise = this.fetchAll(projectId);
4891
4990
  const result = await promise;
4892
4991
  const activeProjectAccess = result.find((projectAccess) => projectAccess.user === currentUser.id);
4893
4992
  if (!activeProjectAccess) {
@@ -5484,6 +5583,31 @@ class WorkspaceService extends BaseApiService {
5484
5583
  }
5485
5584
  }
5486
5585
  class OrganizationAccessService extends BaseApiService {
5586
+ async update(organizationAccess) {
5587
+ const promise = this.enqueueRequest({
5588
+ description: "Edit organization access",
5589
+ method: HttpMethod.PATCH,
5590
+ url: `/organizations/${organizationAccess.organization}/access/${organizationAccess.offline_id}/`,
5591
+ payload: organizationAccess,
5592
+ blockers: [organizationAccess.offline_id],
5593
+ blocks: [organizationAccess.offline_id]
5594
+ });
5595
+ void promise.then(() => {
5596
+ this.client.store.dispatch(updateOrganizationAccess(organizationAccess));
5597
+ });
5598
+ return promise;
5599
+ }
5600
+ async remove(organizationAccess) {
5601
+ this.client.store.dispatch(removeOrganizationAccess(organizationAccess));
5602
+ this.client.store.dispatch(removeUser(organizationAccess.user));
5603
+ return this.enqueueRequest({
5604
+ description: "Remove organization access",
5605
+ method: HttpMethod.DELETE,
5606
+ url: `/organizations/${organizationAccess.organization}/access/${organizationAccess.offline_id}/`,
5607
+ blockers: [organizationAccess.offline_id],
5608
+ blocks: []
5609
+ });
5610
+ }
5487
5611
  async refreshStore() {
5488
5612
  const { store } = this.client;
5489
5613
  const state = store.getState();
@@ -5731,6 +5855,86 @@ class EmailVerificationService extends BaseApiService {
5731
5855
  return this.enqueueRequest(requestDetails);
5732
5856
  }
5733
5857
  }
5858
+ class EmailDomainsService extends BaseApiService {
5859
+ async fetchAll(orgId) {
5860
+ return this.enqueueRequest({
5861
+ description: "Fetch email domains for organization",
5862
+ method: HttpMethod.GET,
5863
+ url: `/organizations/${orgId}/email-domains/`,
5864
+ blockers: [orgId.toString()],
5865
+ blocks: []
5866
+ });
5867
+ }
5868
+ async add(orgId, email) {
5869
+ return this.enqueueRequest({
5870
+ description: "Add email domain to organization",
5871
+ method: HttpMethod.POST,
5872
+ url: `/organizations/${orgId}/email-domains/`,
5873
+ payload: { email },
5874
+ blockers: [orgId.toString(), "create-org"],
5875
+ blocks: []
5876
+ });
5877
+ }
5878
+ async remove(emailDomain) {
5879
+ this.client.store.dispatch(removeEmailDomain(emailDomain));
5880
+ return this.enqueueRequest({
5881
+ description: "Remove email domain from organization",
5882
+ method: HttpMethod.DELETE,
5883
+ url: `/organizations/${emailDomain.organization}/email-domains/${emailDomain.offline_id}/`,
5884
+ blockers: [emailDomain.domain],
5885
+ blocks: []
5886
+ }).catch((e) => {
5887
+ this.client.store.dispatch(addEmailDomain(emailDomain));
5888
+ throw e;
5889
+ });
5890
+ }
5891
+ async refreshStore() {
5892
+ const organizationId = this.client.store.getState().organizationReducer.activeOrganizationId;
5893
+ if (!organizationId) {
5894
+ throw new Error("No active organization");
5895
+ }
5896
+ const promise = this.fetchAll(organizationId);
5897
+ const result = await promise;
5898
+ this.client.store.dispatch(setEmailDomains(result));
5899
+ }
5900
+ }
5901
+ class OrganizationService extends BaseApiService {
5902
+ async create(name) {
5903
+ const result = await this.enqueueRequest({
5904
+ description: "Create organization",
5905
+ method: HttpMethod.POST,
5906
+ url: "/organizations/",
5907
+ payload: { name },
5908
+ blockers: [],
5909
+ blocks: [`add-org-${name}`, "create-org"]
5910
+ });
5911
+ await this.client.main.fetchInitialData(true);
5912
+ return result;
5913
+ }
5914
+ async update(organization) {
5915
+ const promise = this.enqueueRequest({
5916
+ description: "Edit organization",
5917
+ method: HttpMethod.PATCH,
5918
+ url: `/organizations/${organization.id}/`,
5919
+ payload: organization,
5920
+ blockers: [`add-org-${organization.name}`, organization.id.toString()],
5921
+ blocks: [organization.id.toString()]
5922
+ });
5923
+ return promise.then((result) => {
5924
+ this.client.store.dispatch(setActiveOrganization(organization));
5925
+ return result;
5926
+ });
5927
+ }
5928
+ async invite(organizationId, email) {
5929
+ return this.enqueueRequest({
5930
+ description: "Invite user to organization",
5931
+ method: HttpMethod.POST,
5932
+ url: `/organizations/${organizationId}/invite/${email}/`,
5933
+ blockers: [],
5934
+ blocks: []
5935
+ });
5936
+ }
5937
+ }
5734
5938
  class OvermapSDK {
5735
5939
  constructor(apiUrl, store) {
5736
5940
  __publicField(this, "API_URL");
@@ -5740,6 +5944,7 @@ class OvermapSDK {
5740
5944
  __publicField(this, "auth", new AuthService(this));
5741
5945
  __publicField(this, "categories", new CategoryService(this));
5742
5946
  __publicField(this, "projectAccesses", new ProjectAccessService(this));
5947
+ __publicField(this, "organizations", new OrganizationService(this));
5743
5948
  __publicField(this, "organizationAccess", new OrganizationAccessService(this));
5744
5949
  __publicField(this, "issues", new IssueService(this));
5745
5950
  __publicField(this, "issueComments", new IssueCommentService(this));
@@ -5754,6 +5959,7 @@ class OvermapSDK {
5754
5959
  __publicField(this, "projects", new ProjectService(this));
5755
5960
  __publicField(this, "projectFiles", new ProjectFileService(this));
5756
5961
  __publicField(this, "emailVerification", new EmailVerificationService(this));
5962
+ __publicField(this, "emailDomains", new EmailDomainsService(this));
5757
5963
  this.API_URL = apiUrl;
5758
5964
  this.store = store;
5759
5965
  }
@@ -5796,6 +6002,7 @@ export {
5796
6002
  ComponentTypeService,
5797
6003
  DEFAULT_ISSUE_PRIORITY,
5798
6004
  DEFAULT_ISSUE_STATUS,
6005
+ EmailDomainsService,
5799
6006
  EmailVerificationService,
5800
6007
  FileService,
5801
6008
  GREEN,
@@ -5809,6 +6016,7 @@ export {
5809
6016
  OUTBOX_RETRY_DELAY,
5810
6017
  OrganizationAccessLevel,
5811
6018
  OrganizationAccessService,
6019
+ OrganizationService,
5812
6020
  OutboxCoordinator,
5813
6021
  OvermapContext,
5814
6022
  OvermapProvider,
@@ -5832,6 +6040,7 @@ export {
5832
6040
  addComponent,
5833
6041
  addComponentType,
5834
6042
  addComponentsInBatches,
6043
+ addEmailDomain,
5835
6044
  addFavouriteProjectId,
5836
6045
  addIssue,
5837
6046
  addOrReplaceCategories,
@@ -5851,6 +6060,7 @@ export {
5851
6060
  addUserFormSubmissionAttachment,
5852
6061
  addUserFormSubmissions,
5853
6062
  addUserForms,
6063
+ addUsers,
5854
6064
  addWorkspace,
5855
6065
  areArraysEqual,
5856
6066
  authReducer,
@@ -5890,6 +6100,8 @@ export {
5890
6100
  dequeue,
5891
6101
  discard,
5892
6102
  downloadInMemoryFile,
6103
+ emailDomainsReducer,
6104
+ emailDomainsSlice,
5893
6105
  emailRegex,
5894
6106
  enqueue,
5895
6107
  enqueueRequest,
@@ -5958,6 +6170,7 @@ export {
5958
6170
  removeCategory,
5959
6171
  removeColor,
5960
6172
  removeComponent,
6173
+ removeEmailDomain,
5961
6174
  removeFavouriteProjectId,
5962
6175
  removeIssue,
5963
6176
  removeIssueComment,
@@ -6016,6 +6229,7 @@ export {
6016
6229
  selectCreateProjectType,
6017
6230
  selectCurrentUser,
6018
6231
  selectDeletedRequests,
6232
+ selectEmailDomainsAsMapping,
6019
6233
  selectEnableClustering,
6020
6234
  selectEnableDuplicateIssues,
6021
6235
  selectEnablePlacementMode,
@@ -6050,6 +6264,8 @@ export {
6050
6264
  selectOrganizationAccessForUser,
6051
6265
  selectOrganizationAccessUserMapping,
6052
6266
  selectOrganizationAccesses,
6267
+ selectOrganizationUsersAsMapping,
6268
+ selectOrganizationUsersIds,
6053
6269
  selectOrganizations,
6054
6270
  selectPermittedWorkspaceIds,
6055
6271
  selectPhotoAttachmentsOfIssue,
@@ -6059,6 +6275,8 @@ export {
6059
6275
  selectProjectAccesses,
6060
6276
  selectProjectFileVisibility,
6061
6277
  selectProjectFiles,
6278
+ selectProjectUsersAsMapping,
6279
+ selectProjectUsersIds,
6062
6280
  selectProjects,
6063
6281
  selectRecentIssueIds,
6064
6282
  selectRecentIssuesAsSearchResults,
@@ -6066,7 +6284,9 @@ export {
6066
6284
  selectRehydrated,
6067
6285
  selectRevisionsForForm,
6068
6286
  selectShowTooltips,
6069
- selectSortedUsers,
6287
+ selectSortedEmailDomains,
6288
+ selectSortedOrganizationUsers,
6289
+ selectSortedProjectUsers,
6070
6290
  selectStageMapping,
6071
6291
  selectStages,
6072
6292
  selectStagesFromComponentType,
@@ -6088,6 +6308,7 @@ export {
6088
6308
  selectWorkspaceMapping,
6089
6309
  selectWorkspaces,
6090
6310
  setActiveIssueId,
6311
+ setActiveOrganization,
6091
6312
  setActiveOrganizationAccessId,
6092
6313
  setActiveOrganizationId,
6093
6314
  setActiveProjectFileId,
@@ -6101,6 +6322,7 @@ export {
6101
6322
  setComponents,
6102
6323
  setCreateProjectType,
6103
6324
  setCurrentUser,
6325
+ setEmailDomains,
6104
6326
  setEnableClustering,
6105
6327
  setEnableDuplicateIssues,
6106
6328
  setEnablePlacementMode,