@overmap-ai/core 1.0.58-sign-up-hotfix.5 → 1.0.60-model-adapter.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.
Files changed (47) hide show
  1. package/dist/overmap-core.js +1074 -1590
  2. package/dist/overmap-core.js.map +1 -1
  3. package/dist/overmap-core.umd.cjs +1077 -1593
  4. package/dist/overmap-core.umd.cjs.map +1 -1
  5. package/dist/sdk/services/AssetAttachmentService.d.ts +9 -3
  6. package/dist/sdk/services/AssetTypeAttachmentService.d.ts +9 -3
  7. package/dist/sdk/services/BaseAttachmentService.d.ts +11 -15
  8. package/dist/sdk/services/CategoryService.d.ts +1 -20
  9. package/dist/sdk/services/DocumentAttachmentService.d.ts +9 -3
  10. package/dist/sdk/services/EmailDomainsService.d.ts +0 -1
  11. package/dist/sdk/services/IssueAttachmentService.d.ts +9 -3
  12. package/dist/sdk/services/IssueService.d.ts +1 -2
  13. package/dist/sdk/services/ProjectAttachmentService.d.ts +9 -3
  14. package/dist/store/adapter.d.ts +15 -0
  15. package/dist/store/slices/agentsSlice.d.ts +23 -12
  16. package/dist/store/slices/assetAttachmentSlice.d.ts +52 -0
  17. package/dist/store/slices/assetSlice.d.ts +10 -51
  18. package/dist/store/slices/assetStageSlice.d.ts +30 -22
  19. package/dist/store/slices/assetTypeAttachmentSlice.d.ts +52 -0
  20. package/dist/store/slices/assetTypeSlice.d.ts +11 -49
  21. package/dist/store/slices/categorySlice.d.ts +26 -25
  22. package/dist/store/slices/documentAttachmentSlice.d.ts +52 -0
  23. package/dist/store/slices/documentSlice.d.ts +11 -43
  24. package/dist/store/slices/emailDomainsSlice.d.ts +14 -11
  25. package/dist/store/slices/formRevisionAttachmentSlice.d.ts +46 -0
  26. package/dist/store/slices/formRevisionSlice.d.ts +39 -21
  27. package/dist/store/slices/formSlice.d.ts +27 -22
  28. package/dist/store/slices/formSubmissionAttachmentSlice.d.ts +46 -0
  29. package/dist/store/slices/formSubmissionSlice.d.ts +29 -29
  30. package/dist/store/slices/index.d.ts +9 -0
  31. package/dist/store/slices/issueAttachmentSlice.d.ts +52 -0
  32. package/dist/store/slices/issueCommentSlice.d.ts +34 -0
  33. package/dist/store/slices/issueSlice.d.ts +21 -127
  34. package/dist/store/slices/issueTypeSlice.d.ts +25 -11
  35. package/dist/store/slices/issueUpdateSlice.d.ts +34 -0
  36. package/dist/store/slices/licenseSlice.d.ts +9 -7
  37. package/dist/store/slices/organizationAccessSlice.d.ts +12 -10
  38. package/dist/store/slices/projectAccessSlice.d.ts +15 -11
  39. package/dist/store/slices/projectAttachmentSlice.d.ts +52 -0
  40. package/dist/store/slices/projectFileSlice.d.ts +9 -0
  41. package/dist/store/slices/projectSlice.d.ts +2 -43
  42. package/dist/store/slices/teamSlice.d.ts +24 -10
  43. package/dist/store/slices/workspaceSlice.d.ts +28 -16
  44. package/dist/store/store.d.ts +28 -1
  45. package/dist/store/typings.d.ts +3 -0
  46. package/package.json +1 -1
  47. package/dist/store/slices/utils.d.ts +0 -14
@@ -744,15 +744,15 @@ const wrapMigration = (migrator) => (state) => {
744
744
  };
745
745
  const migrations = [initialVersioning, signOut, signOut, createOutboxState];
746
746
  const manifest = Object.fromEntries(migrations.map((migration2, i) => [i, wrapMigration(migration2)]));
747
- const initialState$s = {
747
+ const initialState$B = {
748
748
  accessToken: "",
749
749
  refreshToken: "",
750
750
  isLoggedIn: false
751
751
  };
752
752
  const authSlice = createSlice({
753
753
  name: "auth",
754
- initialState: initialState$s,
755
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$s)),
754
+ initialState: initialState$B,
755
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$B)),
756
756
  reducers: {
757
757
  setTokens: (state, action) => {
758
758
  state.accessToken = action.payload.accessToken;
@@ -1396,77 +1396,92 @@ const getLocalRelativeDateString = memoize((date, min, max) => {
1396
1396
  return getLocalDateString(date);
1397
1397
  return relative.format(days, "days");
1398
1398
  });
1399
- const initialState$r = {
1400
- categories: {},
1401
- usedCategoryColors: [],
1399
+ function createModelAdapter(computeModelId) {
1400
+ const addOne = (state, action) => {
1401
+ const id = computeModelId(action.payload);
1402
+ state.instances[id] = action.payload;
1403
+ };
1404
+ const addMany = (state, action) => {
1405
+ for (const model of action.payload) {
1406
+ const id = computeModelId(model);
1407
+ state.instances[id] = model;
1408
+ }
1409
+ };
1410
+ const setOne = (state, action) => {
1411
+ const id = computeModelId(action.payload);
1412
+ state.instances[id] = action.payload;
1413
+ };
1414
+ const setMany = (state, action) => {
1415
+ for (const model of action.payload) {
1416
+ const id = computeModelId(model);
1417
+ state.instances[id] = model;
1418
+ }
1419
+ };
1420
+ const updateOne = (state, action) => {
1421
+ const id = computeModelId(action.payload);
1422
+ state.instances[id] = action.payload;
1423
+ };
1424
+ const updateMany = (state, action) => {
1425
+ for (const model of action.payload) {
1426
+ const id = computeModelId(model);
1427
+ state.instances[id] = model;
1428
+ }
1429
+ };
1430
+ const deleteOne = (state, action) => {
1431
+ delete state.instances[action.payload];
1432
+ };
1433
+ const deleteMany = (state, action) => {
1434
+ for (const id of action.payload) {
1435
+ delete state.instances[id];
1436
+ }
1437
+ };
1438
+ const initialize = (state, action) => {
1439
+ state.instances = {};
1440
+ for (const model of action.payload) {
1441
+ const id = computeModelId(model);
1442
+ state.instances[id] = model;
1443
+ }
1444
+ };
1445
+ const getInitialState = (state) => {
1446
+ return {
1447
+ ...state,
1448
+ instances: {}
1449
+ };
1450
+ };
1451
+ return {
1452
+ addOne,
1453
+ addMany,
1454
+ setOne,
1455
+ setMany,
1456
+ updateOne,
1457
+ updateMany,
1458
+ deleteOne,
1459
+ deleteMany,
1460
+ initialize,
1461
+ getInitialState
1462
+ };
1463
+ }
1464
+ const categoryAdapter = createModelAdapter((category) => category.offline_id);
1465
+ const initialState$A = categoryAdapter.getInitialState({
1402
1466
  categoryVisibility: {
1403
1467
  hiddenCategoryIds: [],
1404
1468
  isNullCategoryHidden: false
1405
1469
  }
1406
- };
1470
+ });
1407
1471
  const categorySlice = createSlice({
1408
1472
  name: "categories",
1409
- initialState: initialState$r,
1410
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$r)),
1473
+ initialState: initialState$A,
1474
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$A)),
1411
1475
  reducers: {
1412
- setCategories: (state, action) => {
1413
- if (!Array.isArray(action.payload))
1414
- throw new Error("Expected an array of Categories");
1415
- if (action.payload.filter(onlyUniqueOfflineIds).length !== action.payload.length) {
1416
- throw new Error("Tried to use setCategories reducer with duplicate ID's");
1417
- }
1418
- action.payload.forEach((category) => {
1419
- state.categories[category.offline_id] = category;
1420
- });
1476
+ initializeCategories: (state, action) => {
1477
+ categoryAdapter.initialize(state, action);
1421
1478
  state.categoryVisibility.hiddenCategoryIds = state.categoryVisibility.hiddenCategoryIds.filter(
1422
1479
  (categoryId) => action.payload.some((category) => category.offline_id === categoryId)
1423
1480
  );
1424
1481
  },
1425
- addOrReplaceCategories: (state, action) => {
1426
- action.payload.forEach((category) => {
1427
- state.categories[category.offline_id] = category;
1428
- });
1429
- },
1430
- addCategory: (state, action) => {
1431
- if (action.payload.offline_id in state.categories) {
1432
- throw new Error(`Tried to add duplicate category with ID: ${action.payload.offline_id}`);
1433
- }
1434
- state.categories[action.payload.offline_id] = action.payload;
1435
- state.usedCategoryColors.push(action.payload.color);
1436
- },
1437
- patchCategory: (state, action) => {
1438
- const existingData = state.categories[action.payload.offline_id];
1439
- if (existingData) {
1440
- state.categories[action.payload.offline_id] = { ...existingData, ...action.payload };
1441
- } else {
1442
- console.error(`Tried to patch category with ID that doesn't exist: ${action.payload.offline_id}`);
1443
- }
1444
- if (action.payload.color && !(action.payload.color in state.usedCategoryColors)) {
1445
- state.usedCategoryColors.push(action.payload.color);
1446
- }
1447
- },
1448
- replaceCategory: (state, action) => {
1449
- if (action.payload.offline_id in state.categories) {
1450
- state.categories[action.payload.offline_id] = action.payload;
1451
- } else {
1452
- console.error(`Tried to replace category with ID that doesn't exist: ${action.payload.offline_id}`);
1453
- }
1454
- if (!(action.payload.color in state.usedCategoryColors)) {
1455
- state.usedCategoryColors.push(action.payload.color);
1456
- }
1457
- },
1458
- removeCategory: (state, action) => {
1459
- if (!action.payload) {
1460
- throw new Error("Category is undefined");
1461
- }
1462
- const category = state.categories[action.payload];
1463
- if (category) {
1464
- categorySlice.caseReducers.removeColor(state, { payload: category.color });
1465
- delete state.categories[action.payload];
1466
- } else {
1467
- throw new Error(`Tried to remove category with ID that doesn't exist: ${action.payload}`);
1468
- }
1469
- },
1482
+ addCategory: categoryAdapter.addOne,
1483
+ updateCategory: categoryAdapter.updateOne,
1484
+ deleteCategory: categoryAdapter.deleteOne,
1470
1485
  // Pass in a null value to hide the "No category" category
1471
1486
  hideCategory: (state, action) => {
1472
1487
  const categoryId = action.payload;
@@ -1477,7 +1492,7 @@ const categorySlice = createSlice({
1477
1492
  }
1478
1493
  },
1479
1494
  hideAllCategories: (state) => {
1480
- state.categoryVisibility.hiddenCategoryIds = Object.keys(state.categories);
1495
+ state.categoryVisibility.hiddenCategoryIds = Object.keys(state.instances);
1481
1496
  state.categoryVisibility.isNullCategoryHidden = true;
1482
1497
  },
1483
1498
  // Pass in a null value to unhide the "No category" category
@@ -1494,26 +1509,20 @@ const categorySlice = createSlice({
1494
1509
  unhideAllCategories: (state) => {
1495
1510
  state.categoryVisibility.hiddenCategoryIds = [];
1496
1511
  state.categoryVisibility.isNullCategoryHidden = false;
1497
- },
1498
- removeColor: (state, action) => {
1499
- state.usedCategoryColors = state.usedCategoryColors.filter((color) => color !== action.payload);
1500
1512
  }
1501
1513
  }
1502
1514
  });
1503
1515
  const {
1504
- setCategories,
1516
+ initializeCategories,
1505
1517
  addCategory,
1506
- replaceCategory,
1507
- patchCategory,
1508
- removeCategory,
1518
+ updateCategory,
1519
+ deleteCategory,
1509
1520
  hideCategory,
1510
1521
  hideAllCategories,
1511
1522
  unhideCategory,
1512
- unhideAllCategories,
1513
- removeColor,
1514
- addOrReplaceCategories
1523
+ unhideAllCategories
1515
1524
  } = categorySlice.actions;
1516
- const selectCategoryMapping = (state) => state.categoryReducer.categories;
1525
+ const selectCategoryMapping = (state) => state.categoryReducer.instances;
1517
1526
  const _selectActiveWorkspaceId = (state) => state.workspaceReducer.activeWorkspaceId;
1518
1527
  const selectCategories = createSelector(
1519
1528
  [selectCategoryMapping, _selectActiveWorkspaceId],
@@ -1525,12 +1534,12 @@ const selectCategoriesOfWorkspace = restructureCreateSelectorWithArgs(
1525
1534
  (categories, workspaceId) => categories.filter((category) => category.workspace === workspaceId)
1526
1535
  )
1527
1536
  );
1528
- const selectCategory = (offline_id) => (state) => {
1529
- if (!offline_id)
1530
- return void 0;
1531
- return state.categoryReducer.categories[offline_id];
1532
- };
1533
- const selectUsedColors = (state) => state.categoryReducer.usedCategoryColors;
1537
+ const selectCategoryById = restructureCreateSelectorWithArgs(
1538
+ createSelector(
1539
+ [selectCategoryMapping, (_state, categoryId) => categoryId],
1540
+ (mapping, categoryId) => mapping[categoryId]
1541
+ )
1542
+ );
1534
1543
  const selectCategoryVisibility = (state) => state.categoryReducer.categoryVisibility;
1535
1544
  const selectHiddenCategoryCount = (state) => {
1536
1545
  const { hiddenCategoryIds, isNullCategoryHidden } = state.categoryReducer.categoryVisibility;
@@ -1540,106 +1549,28 @@ const selectHiddenCategoryCount = (state) => {
1540
1549
  return hiddenCategoryCount;
1541
1550
  };
1542
1551
  const selectIssueCountOfCategory = (categoryId) => (state) => {
1543
- return Object.values(state.issueReducer.issues).filter((issue) => issue.category === categoryId).length;
1552
+ return Object.values(state.issueReducer.instances).filter((issue) => issue.category === categoryId).length;
1544
1553
  };
1545
1554
  const categoryReducer = categorySlice.reducer;
1546
- function setAttachment(state, action) {
1547
- state.attachments[action.payload.offline_id] = action.payload;
1548
- }
1549
- function setAttachments(state, action) {
1550
- state.attachments = {};
1551
- for (const attachment of action.payload) {
1552
- state.attachments[attachment.offline_id] = attachment;
1553
- }
1554
- }
1555
- function addAttachment(state, action) {
1556
- if (action.payload.offline_id in state.attachments) {
1557
- throw new Error(`Attachment ${action.payload.offline_id} already exists.`);
1558
- }
1559
- state.attachments[action.payload.offline_id] = action.payload;
1560
- }
1561
- function addAttachments(state, action) {
1562
- for (const attachment of action.payload) {
1563
- state.attachments[attachment.offline_id] = attachment;
1564
- }
1565
- }
1566
- function updateAttachment(state, action) {
1567
- if (action.payload.offline_id in state.attachments) {
1568
- state.attachments[action.payload.offline_id] = action.payload;
1569
- } else {
1570
- throw new Error(`Attachment ${action.payload.offline_id} does not exist.`);
1571
- }
1572
- }
1573
- function updateAttachments(state, action) {
1574
- for (const attachment of action.payload) {
1575
- if (attachment.offline_id in state.attachments) {
1576
- state.attachments[attachment.offline_id] = attachment;
1577
- } else {
1578
- throw new Error(`Attachment ${attachment.offline_id} does not exist.`);
1579
- }
1580
- }
1581
- }
1582
- function removeAttachment(state, action) {
1583
- if (action.payload in state.attachments) {
1584
- delete state.attachments[action.payload];
1585
- } else {
1586
- throw new Error(`Attachment ${action.payload} does not exist.`);
1587
- }
1588
- }
1589
- function removeAttachments(state, action) {
1590
- for (const attachmentId of action.payload) {
1591
- delete state.attachments[attachmentId];
1592
- }
1593
- }
1594
- const initialState$q = {
1595
- assetTypes: {},
1596
- hiddenAssetTypeIds: {},
1597
- attachments: {}
1598
- };
1555
+ const assetTypeAdapter = createModelAdapter((assetType) => assetType.offline_id);
1556
+ const initialState$z = assetTypeAdapter.getInitialState({
1557
+ hiddenAssetTypeIds: {}
1558
+ });
1599
1559
  const assetTypeSlice = createSlice({
1600
1560
  name: "assetTypes",
1601
- initialState: initialState$q,
1602
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$q)),
1561
+ initialState: initialState$z,
1562
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$z)),
1603
1563
  reducers: {
1604
- addAssetType: (state, action) => {
1605
- state.assetTypes[action.payload.offline_id] = action.payload;
1606
- },
1607
- setAssetTypes: (state, action) => {
1608
- state.assetTypes = toOfflineIdRecord(action.payload);
1609
- },
1564
+ initializeAssetTypes: assetTypeAdapter.initialize,
1565
+ addAssetType: assetTypeAdapter.addOne,
1566
+ deleteAssetType: assetTypeAdapter.deleteOne,
1610
1567
  toggleAssetTypeVisibility: (state, action) => {
1611
1568
  state.hiddenAssetTypeIds[action.payload] = !state.hiddenAssetTypeIds[action.payload];
1612
- },
1613
- deleteAssetType: (state, action) => {
1614
- delete state.assetTypes[action.payload];
1615
- },
1616
- // Attachments
1617
- setAssetTypeAttachment: setAttachment,
1618
- setAssetTypeAttachments: setAttachments,
1619
- addAssetTypeAttachment: addAttachment,
1620
- addAssetTypeAttachments: addAttachments,
1621
- updateAssetTypeAttachment: updateAttachment,
1622
- updateAssetTypeAttachments: updateAttachments,
1623
- removeAssetTypeAttachment: removeAttachment,
1624
- removeAssetTypeAttachments: removeAttachments
1569
+ }
1625
1570
  }
1626
1571
  });
1627
- const {
1628
- addAssetType,
1629
- setAssetTypes,
1630
- toggleAssetTypeVisibility,
1631
- deleteAssetType,
1632
- // Attachmet
1633
- setAssetTypeAttachment,
1634
- setAssetTypeAttachments,
1635
- addAssetTypeAttachment,
1636
- addAssetTypeAttachments,
1637
- updateAssetTypeAttachment,
1638
- updateAssetTypeAttachments,
1639
- removeAssetTypeAttachment,
1640
- removeAssetTypeAttachments
1641
- } = assetTypeSlice.actions;
1642
- const selectAssetTypesMapping = (state) => state.assetTypeReducer.assetTypes;
1572
+ const { addAssetType, initializeAssetTypes, deleteAssetType, toggleAssetTypeVisibility } = assetTypeSlice.actions;
1573
+ const selectAssetTypesMapping = (state) => state.assetTypeReducer.instances;
1643
1574
  const selectAssetTypes = createSelector(
1644
1575
  [selectAssetTypesMapping],
1645
1576
  (mapping) => Object.values(mapping)
@@ -1675,151 +1606,78 @@ const selectAssetTypesByName = restructureCreateSelectorWithArgs(
1675
1606
  })
1676
1607
  );
1677
1608
  const selectHiddenAssetTypeIds = (state) => state.assetTypeReducer.hiddenAssetTypeIds;
1678
- const selectAssetTypeAttachmentMapping = (state) => state.assetTypeReducer.attachments;
1679
- const selectAssetTypeAttachments = createSelector(
1680
- [selectAssetTypeAttachmentMapping],
1681
- (mapping) => Object.values(mapping)
1682
- );
1683
- const selectAssetTypeAttachment = (attachmentId) => (state) => {
1684
- return state.assetTypeReducer.attachments[attachmentId];
1685
- };
1686
- const selectAttachmentsOfAssetType = restructureCreateSelectorWithArgs(
1687
- createSelector(
1688
- [selectAssetTypeAttachments, (_state, assetTypeId) => assetTypeId],
1689
- (attachments, assetTypeId) => {
1690
- return attachments.filter(({ asset_type }) => assetTypeId === asset_type);
1691
- }
1692
- )
1693
- );
1694
- const selectAttachmentsOfAssetTypeByType = restructureCreateSelectorWithArgs(
1695
- createSelector(
1696
- [selectAssetTypeAttachments, (_state, assetTypeId) => assetTypeId],
1697
- (attachments, assetTypeId) => {
1698
- const attachmentsOfAssetType = attachments.filter(({ asset_type }) => asset_type === assetTypeId);
1699
- const fileAttachments = attachmentsOfAssetType.filter(
1700
- // this null check here is necessary, there are cases where file_type is null or undefined
1701
- ({ file_type }) => !file_type || !file_type.startsWith("image/")
1702
- );
1703
- const imageAttachments = attachmentsOfAssetType.filter(
1704
- // this null check here is necessary, there are cases where file_type is null or undefined
1705
- ({ file_type }) => file_type && file_type.startsWith("image/")
1706
- );
1707
- return { fileAttachments, imageAttachments };
1708
- }
1709
- )
1710
- );
1711
1609
  const assetTypeReducer = assetTypeSlice.reducer;
1712
- const initialState$p = {
1713
- assets: {},
1714
- attachments: {}
1715
- };
1610
+ const assetAdapter = createModelAdapter((asset) => asset.offline_id);
1611
+ const initialState$y = assetAdapter.getInitialState({});
1716
1612
  const assetSlice = createSlice({
1717
1613
  name: "assets",
1718
- initialState: initialState$p,
1719
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$p)),
1614
+ initialState: initialState$y,
1615
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$y)),
1720
1616
  reducers: {
1617
+ initializeAssets: (state, action) => {
1618
+ assetAdapter.initialize(state, action);
1619
+ prevAssets = null;
1620
+ },
1721
1621
  addAsset: (state, action) => {
1722
- state.assets[action.payload.offline_id] = action.payload;
1622
+ assetAdapter.addOne(state, action);
1623
+ prevAssets = null;
1624
+ },
1625
+ addAssets: (state, action) => {
1626
+ assetAdapter.addMany(state, action);
1723
1627
  prevAssets = null;
1724
1628
  },
1725
- addAssetsInBatches: (state, action) => {
1726
- Object.assign(state.assets, toOfflineIdRecord(action.payload));
1629
+ setAsset: (state, action) => {
1630
+ assetAdapter.setOne(state, action);
1727
1631
  prevAssets = null;
1728
1632
  },
1729
1633
  setAssets: (state, action) => {
1730
- state.assets = toOfflineIdRecord(action.payload);
1634
+ assetAdapter.setMany(state, action);
1731
1635
  prevAssets = null;
1732
1636
  },
1733
1637
  updateAsset: (state, action) => {
1734
- if (action.payload.offline_id in state.assets) {
1735
- state.assets[action.payload.offline_id] = action.payload;
1736
- } else {
1737
- throw new Error(`Tried to update asset with ID that doesn't exist: ${action.payload.offline_id}`);
1738
- }
1638
+ assetAdapter.updateOne(state, action);
1739
1639
  prevAssets = null;
1740
1640
  },
1741
1641
  updateAssets: (state, action) => {
1742
- for (const asset of action.payload) {
1743
- if (asset.offline_id in state.assets) {
1744
- state.assets[asset.offline_id] = asset;
1745
- } else {
1746
- throw new Error(`Tried to update asset with ID that doesn't exist: ${asset.offline_id}`);
1747
- }
1748
- }
1749
- prevAssets = null;
1750
- },
1751
- removeAsset: (state, action) => {
1752
- if (action.payload in state.assets) {
1753
- delete state.assets[action.payload];
1754
- } else {
1755
- throw new Error(`Failed to remove asset because ID doesn't exist: ${action.payload}`);
1756
- }
1642
+ assetAdapter.updateMany(state, action);
1757
1643
  prevAssets = null;
1758
1644
  },
1759
- removeAssets: (state, action) => {
1760
- for (const assetId of action.payload) {
1761
- if (assetId in state.assets) {
1762
- delete state.assets[assetId];
1763
- } else {
1764
- throw new Error(`Failed to remove asset because ID doesn't exist: ${assetId}`);
1765
- }
1766
- }
1645
+ deleteAsset: (state, action) => {
1646
+ assetAdapter.deleteOne(state, action);
1767
1647
  prevAssets = null;
1768
1648
  },
1769
- removeAllAssetsOfType: (state, action) => {
1770
- var _a2;
1771
- for (const componentId in state.assets) {
1772
- if (((_a2 = state.assets[componentId]) == null ? void 0 : _a2.asset_type) === action.payload) {
1773
- delete state.assets[componentId];
1774
- }
1775
- }
1649
+ deleteAssets: (state, action) => {
1650
+ assetAdapter.deleteMany(state, action);
1776
1651
  prevAssets = null;
1777
- },
1778
- // Attachments
1779
- setAssetAttachment: setAttachment,
1780
- setAssetAttachments: setAttachments,
1781
- addAssetAttachment: addAttachment,
1782
- addAssetAttachments: addAttachments,
1783
- updateAssetAttachment: updateAttachment,
1784
- updateAssetAttachments: updateAttachments,
1785
- removeAssetAttachment: removeAttachment,
1786
- removeAssetAttachments: removeAttachments
1652
+ }
1787
1653
  }
1788
1654
  });
1789
1655
  const {
1656
+ initializeAssets,
1790
1657
  addAsset,
1658
+ addAssets,
1791
1659
  updateAsset,
1792
1660
  updateAssets,
1793
- removeAsset,
1794
- removeAssets,
1795
- addAssetsInBatches,
1796
- setAssets,
1797
- removeAllAssetsOfType,
1798
- // Attachments
1799
- setAssetAttachment,
1800
- setAssetAttachments,
1801
- addAssetAttachment,
1802
- addAssetAttachments,
1803
- updateAssetAttachment,
1804
- updateAssetAttachments,
1805
- removeAssetAttachment,
1806
- removeAssetAttachments
1661
+ deleteAsset,
1662
+ deleteAssets,
1663
+ setAsset,
1664
+ setAssets
1807
1665
  } = assetSlice.actions;
1808
1666
  let prevAssets = null;
1809
1667
  const selectAssets = (state) => {
1810
1668
  if (!prevAssets) {
1811
- prevAssets = Object.values(state.assetReducer.assets);
1669
+ prevAssets = Object.values(state.assetReducer.instances);
1812
1670
  }
1813
1671
  return prevAssets;
1814
1672
  };
1815
- const selectAssetsMapping = (state) => state.assetReducer.assets;
1673
+ const selectAssetsMapping = (state) => state.assetReducer.instances;
1816
1674
  const selectAssetsOfAssetType = restructureCreateSelectorWithArgs(
1817
1675
  createSelector([selectAssets, (_state, assetTypeId) => assetTypeId], (components, assetTypeId) => {
1818
1676
  return components.filter((asset) => asset.asset_type === assetTypeId);
1819
1677
  })
1820
1678
  );
1821
1679
  const selectAsset = (assetId) => (state) => {
1822
- return state.assetReducer.assets[assetId];
1680
+ return state.assetReducer.instances[assetId];
1823
1681
  };
1824
1682
  const selectAssetToAssetTypeMapping = createSelector(
1825
1683
  [selectAssets, selectAssetTypesMapping],
@@ -1848,20 +1706,50 @@ const selectNumberOfAssetsOfAssetType = (assetTypeId) => (state) => {
1848
1706
  };
1849
1707
  const selectAssetTypesFromIds = (assetTypeIds) => (state) => {
1850
1708
  return assetTypeIds.reduce((acc, assetTypeId) => {
1851
- const assetType = state.assetTypeReducer.assetTypes[assetTypeId];
1709
+ const assetType = state.assetTypeReducer.instances[assetTypeId];
1852
1710
  if (assetType) {
1853
1711
  acc.push(assetType);
1854
1712
  }
1855
1713
  return acc;
1856
1714
  }, []);
1857
1715
  };
1858
- const selectAssetAttachmentMapping = (state) => state.assetReducer.attachments;
1716
+ const assetReducer = assetSlice.reducer;
1717
+ const assetAttachmentAdapter = createModelAdapter((attachment) => attachment.offline_id);
1718
+ const initialState$x = assetAttachmentAdapter.getInitialState({});
1719
+ const assetAttachmentSlice = createSlice({
1720
+ name: "assetAttachments",
1721
+ initialState: initialState$x,
1722
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$x)),
1723
+ reducers: {
1724
+ initializeAssetAttachments: assetAttachmentAdapter.initialize,
1725
+ addAssetAttachment: assetAttachmentAdapter.addOne,
1726
+ addAssetAttachments: assetAttachmentAdapter.addMany,
1727
+ setAssetAttachment: assetAttachmentAdapter.setOne,
1728
+ setAssetAttachments: assetAttachmentAdapter.setMany,
1729
+ updateAssetAttachment: assetAttachmentAdapter.updateOne,
1730
+ updateAssetAttachments: assetAttachmentAdapter.updateMany,
1731
+ deleteAssetAttachment: assetAttachmentAdapter.deleteOne,
1732
+ deleteAssetAttachments: assetAttachmentAdapter.deleteMany
1733
+ }
1734
+ });
1735
+ const {
1736
+ initializeAssetAttachments,
1737
+ addAssetAttachment,
1738
+ addAssetAttachments,
1739
+ setAssetAttachment,
1740
+ setAssetAttachments,
1741
+ updateAssetAttachment,
1742
+ updateAssetAttachments,
1743
+ deleteAssetAttachment,
1744
+ deleteAssetAttachments
1745
+ } = assetAttachmentSlice.actions;
1746
+ const selectAssetAttachmentMapping = (state) => state.assetAttachmentReducer.instances;
1859
1747
  const selectAssetAttachments = createSelector(
1860
1748
  [selectAssetAttachmentMapping],
1861
1749
  (mapping) => Object.values(mapping)
1862
1750
  );
1863
1751
  const selectAssetAttachment = (attachmentId) => (state) => {
1864
- return state.assetReducer.attachments[attachmentId];
1752
+ return state.assetAttachmentReducer.instances[attachmentId];
1865
1753
  };
1866
1754
  const selectAttachmentsOfAsset = restructureCreateSelectorWithArgs(
1867
1755
  createSelector(
@@ -1888,14 +1776,14 @@ const selectAttachmentsOfAssetByType = restructureCreateSelectorWithArgs(
1888
1776
  }
1889
1777
  )
1890
1778
  );
1891
- const assetReducer = assetSlice.reducer;
1892
- const initialState$o = {
1779
+ const assetAttachmentReducer = assetAttachmentSlice.reducer;
1780
+ const initialState$w = {
1893
1781
  completionsByAssetId: {}
1894
1782
  };
1895
1783
  const assetStageCompletionSlice = createSlice({
1896
1784
  name: "assetStageCompletions",
1897
- initialState: initialState$o,
1898
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$o)),
1785
+ initialState: initialState$w,
1786
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$w)),
1899
1787
  reducers: {
1900
1788
  addStageCompletion: (state, action) => {
1901
1789
  let stageToCompletionDateMapping = state.completionsByAssetId[action.payload.asset];
@@ -1944,46 +1832,22 @@ const selectCompletedStageIdsForAsset = (asset) => (state) => {
1944
1832
  return Object.keys(state.assetStageCompletionReducer.completionsByAssetId[asset.offline_id] ?? {});
1945
1833
  };
1946
1834
  const assetStageCompletionReducer = assetStageCompletionSlice.reducer;
1947
- const initialState$n = {
1948
- stages: {}
1949
- };
1835
+ const assetStageAdapter = createModelAdapter((assetStage) => assetStage.offline_id);
1836
+ const initialState$v = assetStageAdapter.getInitialState({});
1950
1837
  const assetStageSlice = createSlice({
1951
1838
  name: "assetStages",
1952
- initialState: initialState$n,
1953
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$n)),
1839
+ initialState: initialState$v,
1840
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$v)),
1954
1841
  reducers: {
1955
- addStages: (state, action) => {
1956
- Object.assign(state.stages, toOfflineIdRecord(action.payload));
1957
- },
1958
- updateStages: (state, action) => {
1959
- for (const stage of action.payload) {
1960
- state.stages[stage.offline_id] = stage;
1961
- }
1962
- },
1963
- removeStages: (state, action) => {
1964
- action.payload.forEach((id) => {
1965
- delete state.stages[id];
1966
- });
1967
- },
1968
- linkStageToForm: (state, action) => {
1969
- const { stageId, formId: formId2 } = action.payload;
1970
- const stage = state.stages[stageId];
1971
- if (!stage) {
1972
- throw new Error("No stage exists with the id " + stageId);
1973
- }
1974
- stage.user_form = formId2;
1975
- },
1976
- unlinkStageToForm: (state, action) => {
1977
- const { stageId } = action.payload;
1978
- const stage = state.stages[stageId];
1979
- if (!stage) {
1980
- throw new Error("No stage exists with the id " + stageId);
1981
- }
1982
- delete stage.user_form;
1983
- }
1842
+ initializeStages: assetStageAdapter.initialize,
1843
+ setStage: assetStageAdapter.setOne,
1844
+ addStages: assetStageAdapter.addMany,
1845
+ updateStage: assetStageAdapter.updateOne,
1846
+ updateStages: assetStageAdapter.updateMany,
1847
+ removeStages: assetStageAdapter.deleteMany
1984
1848
  }
1985
1849
  });
1986
- const selectStageMapping = (state) => state.assetStageReducer.stages;
1850
+ const selectStageMapping = (state) => state.assetStageReducer.instances;
1987
1851
  const selectStage = restructureCreateSelectorWithArgs(
1988
1852
  createSelector([selectStageMapping, (_state, stageId) => stageId], (stageMapping, stageId) => {
1989
1853
  return stageMapping[stageId];
@@ -2046,43 +1910,100 @@ const selectStageFormIdsFromStageIds = restructureCreateSelectorWithArgs(
2046
1910
  return ret;
2047
1911
  })
2048
1912
  );
2049
- const { addStages, updateStages, removeStages, linkStageToForm, unlinkStageToForm } = assetStageSlice.actions;
1913
+ const { initializeStages, setStage, addStages, updateStages, removeStages, updateStage } = assetStageSlice.actions;
2050
1914
  const assetStageReducer = assetStageSlice.reducer;
2051
- const initialState$m = {
2052
- workspaces: {},
2053
- activeWorkspaceId: null
1915
+ const assetTypeAttachmentAdapter = createModelAdapter(
1916
+ (attachment) => attachment.offline_id
1917
+ );
1918
+ const initialState$u = assetTypeAttachmentAdapter.getInitialState({});
1919
+ const assetTypeAttachmentSlice = createSlice({
1920
+ name: "assetTypeAttachments",
1921
+ initialState: initialState$u,
1922
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$u)),
1923
+ reducers: {
1924
+ initializeAssetTypeAttachments: assetTypeAttachmentAdapter.initialize,
1925
+ addAssetTypeAttachment: assetTypeAttachmentAdapter.addOne,
1926
+ addAssetTypeAttachments: assetTypeAttachmentAdapter.addMany,
1927
+ setAssetTypeAttachment: assetTypeAttachmentAdapter.setOne,
1928
+ setAssetTypeAttachments: assetTypeAttachmentAdapter.setMany,
1929
+ updateAssetTypeAttachment: assetTypeAttachmentAdapter.updateOne,
1930
+ updateAssetTypeAttachments: assetTypeAttachmentAdapter.updateMany,
1931
+ deleteAssetTypeAttachment: assetTypeAttachmentAdapter.deleteOne,
1932
+ deleteAssetTypeAttachments: assetTypeAttachmentAdapter.deleteMany
1933
+ }
1934
+ });
1935
+ const {
1936
+ initializeAssetTypeAttachments,
1937
+ addAssetTypeAttachment,
1938
+ addAssetTypeAttachments,
1939
+ setAssetTypeAttachment,
1940
+ setAssetTypeAttachments,
1941
+ updateAssetTypeAttachment,
1942
+ updateAssetTypeAttachments,
1943
+ deleteAssetTypeAttachment,
1944
+ deleteAssetTypeAttachments
1945
+ } = assetTypeAttachmentSlice.actions;
1946
+ const selectAssetTypeAttachmentMapping = (state) => state.assetTypeAttachmentReducer.instances;
1947
+ const selectAssetTypeAttachments = createSelector(
1948
+ [selectAssetTypeAttachmentMapping],
1949
+ (mapping) => Object.values(mapping)
1950
+ );
1951
+ const selectAssetTypeAttachment = (attachmentId) => (state) => {
1952
+ return state.assetTypeAttachmentReducer.instances[attachmentId];
2054
1953
  };
1954
+ const selectAttachmentsOfAssetType = restructureCreateSelectorWithArgs(
1955
+ createSelector(
1956
+ [selectAssetTypeAttachments, (_state, assetTypeId) => assetTypeId],
1957
+ (attachments, assetTypeId) => {
1958
+ return attachments.filter(({ asset_type }) => assetTypeId === asset_type);
1959
+ }
1960
+ )
1961
+ );
1962
+ const selectAttachmentsOfAssetTypeByType = restructureCreateSelectorWithArgs(
1963
+ createSelector(
1964
+ [selectAssetTypeAttachments, (_state, assetTypeId) => assetTypeId],
1965
+ (attachments, assetTypeId) => {
1966
+ const attachmentsOfAssetType = attachments.filter(({ asset_type }) => asset_type === assetTypeId);
1967
+ const fileAttachments = attachmentsOfAssetType.filter(
1968
+ // this null check here is necessary, there are cases where file_type is null or undefined
1969
+ ({ file_type }) => !file_type || !file_type.startsWith("image/")
1970
+ );
1971
+ const imageAttachments = attachmentsOfAssetType.filter(
1972
+ // this null check here is necessary, there are cases where file_type is null or undefined
1973
+ ({ file_type }) => file_type && file_type.startsWith("image/")
1974
+ );
1975
+ return { fileAttachments, imageAttachments };
1976
+ }
1977
+ )
1978
+ );
1979
+ const assetTypeAttachmentReducer = assetTypeAttachmentSlice.reducer;
1980
+ const workspaceAdapter = createModelAdapter((workspace) => workspace.offline_id);
1981
+ const initialState$t = workspaceAdapter.getInitialState({
1982
+ activeWorkspaceId: null
1983
+ });
2055
1984
  const workspaceSlice = createSlice({
2056
1985
  name: "workspace",
2057
- initialState: initialState$m,
2058
- // The `reducers` field lets us define reducers and generate associated actions
1986
+ initialState: initialState$t,
2059
1987
  reducers: {
2060
- setWorkspaces: (state, action) => {
2061
- state.workspaces = action.payload;
2062
- },
2063
- // Takes a list of Workspaces and updates existing ones to match the payload, or adds them
2064
- // to the store if they are not already present
2065
- addOrReplaceWorkspaces: (state, action) => {
2066
- Object.values(action.payload).forEach((workspace) => {
2067
- state.workspaces[workspace.offline_id] = workspace;
2068
- });
2069
- },
2070
- addWorkspace: (state, action) => {
2071
- if (action.payload.offline_id in state.workspaces) {
2072
- throw new Error(`Tried to add duplicate workspace with name: ${action.payload.offline_id}`);
2073
- }
2074
- state.workspaces[action.payload.offline_id] = action.payload;
2075
- },
2076
- removeWorkspace: (state, action) => {
2077
- delete state.workspaces[action.payload];
2078
- },
1988
+ initializeWorkspaces: workspaceAdapter.initialize,
1989
+ setWorkspaces: workspaceAdapter.setMany,
1990
+ addWorkspace: workspaceAdapter.addOne,
1991
+ updateWorkspace: workspaceAdapter.updateOne,
1992
+ deleteWorkspace: workspaceAdapter.deleteOne,
2079
1993
  setActiveWorkspaceId: (state, action) => {
2080
1994
  state.activeWorkspaceId = action.payload;
2081
1995
  }
2082
1996
  }
2083
1997
  });
2084
- const { setWorkspaces, addOrReplaceWorkspaces, addWorkspace, setActiveWorkspaceId, removeWorkspace } = workspaceSlice.actions;
2085
- const selectWorkspaceMapping = (state) => state.workspaceReducer.workspaces;
1998
+ const {
1999
+ initializeWorkspaces,
2000
+ setWorkspaces,
2001
+ addWorkspace,
2002
+ updateWorkspace,
2003
+ setActiveWorkspaceId,
2004
+ deleteWorkspace
2005
+ } = workspaceSlice.actions;
2006
+ const selectWorkspaceMapping = (state) => state.workspaceReducer.instances;
2086
2007
  const selectWorkspaces = createSelector([selectWorkspaceMapping], (mapping) => Object.values(mapping));
2087
2008
  const selectMainWorkspace = createSelector([selectWorkspaces], (workspaces) => {
2088
2009
  return workspaces.find((workspace) => workspace.name.toLowerCase() === "main");
@@ -2111,169 +2032,33 @@ const selectPermittedWorkspaceIds = createSelector(
2111
2032
  );
2112
2033
  const workspaceReducer = workspaceSlice.reducer;
2113
2034
  const maxRecentIssues = 10;
2114
- const initialState$l = {
2115
- issues: {},
2116
- attachments: {},
2117
- comments: {},
2118
- updates: {},
2035
+ const issueAdapter = createModelAdapter((issue) => issue.offline_id);
2036
+ const initialState$s = issueAdapter.getInitialState({
2119
2037
  visibleStatuses: [IssueStatus.BACKLOG, IssueStatus.SELECTED],
2120
2038
  visibleUserIds: null,
2121
- recentIssueIds: [],
2122
- activeIssueId: null
2123
- };
2039
+ recentIssueIds: []
2040
+ });
2124
2041
  const issueSlice = createSlice({
2125
2042
  name: "issues",
2126
- initialState: initialState$l,
2043
+ initialState: initialState$s,
2127
2044
  extraReducers: (builder) => builder.addCase("RESET", (state) => {
2128
- Object.assign(state, initialState$l);
2045
+ Object.assign(state, initialState$s);
2129
2046
  }),
2130
2047
  reducers: {
2131
- setIssues: (state, action) => {
2132
- if (action.payload.filter(onlyUniqueOfflineIds).length !== action.payload.length) {
2133
- throw new Error("Tried to use setIssues reducer with duplicate ID's");
2134
- }
2135
- action.payload.forEach((issue) => {
2136
- state.issues[issue.offline_id] = issue;
2137
- });
2138
- },
2139
- setIssueUpdates: (state, action) => {
2140
- if (action.payload.filter(onlyUniqueOfflineIds).length !== action.payload.length) {
2141
- throw new Error("Tried to use setIssues reducer with duplicate ID's");
2142
- }
2143
- const newUpdates = {};
2144
- for (const update of action.payload) {
2145
- newUpdates[update.offline_id] = update;
2146
- }
2147
- state.updates = newUpdates;
2148
- },
2149
- setActiveIssueId: (state, action) => {
2150
- state.activeIssueId = action.payload;
2151
- },
2152
- addIssue: (state, action) => {
2153
- if (action.payload.offline_id in state.issues) {
2154
- throw new Error(`Tried to add duplicate issue with ID: ${action.payload.offline_id}`);
2155
- }
2156
- state.issues[action.payload.offline_id] = action.payload;
2157
- },
2158
- addIssues: (state, action) => {
2159
- for (const issue of action.payload) {
2160
- if (issue.offline_id in state.issues) {
2161
- throw new Error(`Tried to add duplicate issue with ID: ${issue.offline_id}`);
2162
- }
2163
- }
2164
- for (const issue of action.payload) {
2165
- state.issues[issue.offline_id] = issue;
2166
- }
2167
- },
2168
- addIssueUpdate: (state, action) => {
2169
- if (action.payload.offline_id in state.updates) {
2170
- throw new Error(`Tried to add duplicate issue update with offline_id: ${action.payload.offline_id}`);
2171
- }
2172
- state.updates[action.payload.offline_id] = action.payload;
2173
- },
2174
- addIssueUpdates: (state, action) => {
2175
- for (const update of action.payload) {
2176
- state.updates[update.offline_id] = update;
2177
- }
2178
- },
2179
- updateIssue: (state, action) => {
2180
- if (action.payload.offline_id in state.issues) {
2181
- state.issues[action.payload.offline_id] = {
2182
- ...state.issues[action.payload.offline_id],
2183
- ...action.payload
2184
- };
2185
- } else {
2186
- throw new Error(`Tried to update issue with ID that doesn't exist: ${action.payload.offline_id}`);
2187
- }
2188
- },
2189
- removeIssue: (state, action) => {
2190
- if (action.payload in state.issues) {
2191
- delete state.issues[action.payload];
2192
- } else {
2193
- throw new Error(`Failed to remove issue because ID doesn't exist: ${action.payload}`);
2194
- }
2195
- },
2196
- removeIssues: (state, action) => {
2197
- for (const issueId of action.payload) {
2198
- delete state.issues[issueId];
2199
- }
2200
- },
2201
- removeIssueUpdate: (state, action) => {
2202
- if (action.payload in state.updates) {
2203
- delete state.updates[action.payload];
2204
- } else {
2205
- throw new Error(`Failed to remove issue update because offline_id doesn't exist: ${action.payload}`);
2206
- }
2207
- },
2208
- removeIssueUpdates: (state, action) => {
2209
- for (const updateId of action.payload) {
2210
- delete state.updates[updateId];
2211
- }
2212
- },
2213
- removeAttachmentsOfIssue: (state, action) => {
2214
- const attachments = Object.values(state.attachments).filter((a) => a.issue === action.payload);
2215
- for (const attachment of attachments) {
2216
- delete state.attachments[attachment.offline_id];
2217
- }
2218
- },
2219
- setVisibleStatuses: (state, action) => {
2220
- state.visibleStatuses = action.payload;
2048
+ initializeIssues: issueAdapter.initialize,
2049
+ addIssue: issueAdapter.addOne,
2050
+ addIssues: issueAdapter.addMany,
2051
+ updateIssue: issueAdapter.updateOne,
2052
+ deleteIssue: issueAdapter.deleteOne,
2053
+ deleteIssues: issueAdapter.deleteMany,
2054
+ setVisibleStatuses: (state, action) => {
2055
+ state.visibleStatuses = action.payload;
2221
2056
  },
2222
2057
  setVisibleUserIds: (state, action) => {
2223
2058
  state.visibleUserIds = [...new Set(action.payload)];
2224
2059
  },
2225
- // Comments
2226
- addIssueComment: (state, action) => {
2227
- if (action.payload.offline_id in state.comments) {
2228
- throw new Error(
2229
- `Tried to add issue comment with offline_id: ${action.payload.offline_id} that already exists`
2230
- );
2231
- }
2232
- state.comments[action.payload.offline_id] = action.payload;
2233
- },
2234
- addIssueComments: (state, action) => {
2235
- for (const comment of action.payload) {
2236
- if (comment.offline_id in state.comments) {
2237
- throw new Error(
2238
- `Tried to add issue comment with offline_id: ${comment.offline_id} that already exists`
2239
- );
2240
- }
2241
- }
2242
- for (const comment of action.payload) {
2243
- state.comments[comment.offline_id] = comment;
2244
- }
2245
- },
2246
- setIssueComment: (state, action) => {
2247
- state.comments[action.payload.offline_id] = action.payload;
2248
- },
2249
- setIssueComments: (state, action) => {
2250
- const newComments = {};
2251
- for (const comment of action.payload) {
2252
- newComments[comment.offline_id] = comment;
2253
- }
2254
- state.comments = newComments;
2255
- },
2256
- addOrReplaceIssueComment: (state, action) => {
2257
- state.comments[action.payload.offline_id] = action.payload;
2258
- },
2259
- removeIssueComment: (state, action) => {
2260
- if (!(action.payload in state.comments)) {
2261
- throw new Error(`Failed to remove issue comment because ID doesn't exist: ${action.payload}`);
2262
- }
2263
- delete state.comments[action.payload];
2264
- },
2265
- removeIssueComments: (state, action) => {
2266
- for (const commentId of action.payload) {
2267
- if (!(commentId in state.comments)) {
2268
- throw new Error(`Failed to remove issue comment because ID doesn't exist: ${commentId}`);
2269
- }
2270
- }
2271
- for (const commentId of action.payload) {
2272
- delete state.comments[commentId];
2273
- }
2274
- },
2275
2060
  cleanRecentIssues: (state) => {
2276
- state.recentIssueIds = state.recentIssueIds.filter((recentIssue) => state.issues[recentIssue.offlineId]);
2061
+ state.recentIssueIds = state.recentIssueIds.filter((recentIssue) => state.instances[recentIssue.offlineId]);
2277
2062
  },
2278
2063
  addToRecentIssues: (state, action) => {
2279
2064
  state.recentIssueIds = state.recentIssueIds.filter(
@@ -2294,57 +2079,24 @@ const issueSlice = createSlice({
2294
2079
  if (indexToRemove !== -1) {
2295
2080
  state.recentIssueIds.splice(indexToRemove, 1);
2296
2081
  }
2297
- },
2298
- // Attachments
2299
- setIssueAttachment: setAttachment,
2300
- setIssueAttachments: setAttachments,
2301
- addIssueAttachment: addAttachment,
2302
- addIssueAttachments: addAttachments,
2303
- updateIssueAttachment: updateAttachment,
2304
- updateIssueAttachments: updateAttachments,
2305
- removeIssueAttachment: removeAttachment,
2306
- removeIssueAttachments: removeAttachments
2082
+ }
2307
2083
  }
2308
2084
  });
2309
2085
  const {
2086
+ initializeIssues,
2310
2087
  addIssue,
2311
2088
  addIssues,
2312
- addIssueUpdate,
2313
- addIssueUpdates,
2314
- addOrReplaceIssueComment,
2089
+ updateIssue,
2090
+ deleteIssue,
2091
+ deleteIssues,
2092
+ setVisibleStatuses,
2093
+ setVisibleUserIds,
2315
2094
  addToRecentIssues,
2316
2095
  cleanRecentIssues,
2317
- removeAttachmentsOfIssue,
2318
- removeIssue,
2319
- removeIssues,
2320
- removeIssueUpdate,
2321
- removeIssueUpdates,
2322
2096
  removeRecentIssue,
2323
- resetRecentIssues,
2324
- setActiveIssueId,
2325
- setIssueUpdates,
2326
- setIssues,
2327
- setVisibleStatuses,
2328
- setVisibleUserIds,
2329
- updateIssue,
2330
- // Attachments
2331
- setIssueAttachment,
2332
- setIssueAttachments,
2333
- addIssueAttachment,
2334
- addIssueAttachments,
2335
- updateIssueAttachment,
2336
- updateIssueAttachments,
2337
- removeIssueAttachment,
2338
- removeIssueAttachments,
2339
- // Commments
2340
- addIssueComment,
2341
- addIssueComments,
2342
- setIssueComment,
2343
- setIssueComments,
2344
- removeIssueComment,
2345
- removeIssueComments
2097
+ resetRecentIssues
2346
2098
  } = issueSlice.actions;
2347
- const selectIssueMapping = (state) => state.issueReducer.issues;
2099
+ const selectIssueMapping = (state) => state.issueReducer.instances;
2348
2100
  const selectRecentIssueIds = (state) => state.issueReducer.recentIssueIds;
2349
2101
  const selectVisibleUserIds = (state) => state.issueReducer.visibleUserIds;
2350
2102
  const selectVisibleStatuses = (state) => state.issueReducer.visibleStatuses;
@@ -2391,83 +2143,11 @@ const selectIssues = restructureCreateSelectorWithArgs(
2391
2143
  }
2392
2144
  )
2393
2145
  );
2394
- const selectActiveIssueId = (state) => state.issueReducer.activeIssueId;
2395
- const selectIssueAttachmentMapping = (state) => state.issueReducer.attachments;
2396
- const selectIssueAttachments = createSelector(
2397
- [selectIssueAttachmentMapping],
2398
- (mapping) => Object.values(mapping)
2399
- );
2400
- const selectPhotoAttachmentsOfIssue = restructureCreateSelectorWithArgs(
2401
- createSelector(
2402
- [selectIssueAttachmentMapping, (_state, issueId) => issueId],
2403
- (attachmentMapping, issueId) => {
2404
- return Object.values(attachmentMapping).filter(
2405
- (attachment) => attachment.issue === issueId && attachment.file_type && attachment.file_type.startsWith("image/")
2406
- );
2407
- }
2408
- )
2409
- );
2410
- const selectCommentMapping = (state) => state.issueReducer.comments;
2411
- const selectCommentsOfIssue = restructureCreateSelectorWithArgs(
2412
- createSelector([selectCommentMapping, (_state, issueId) => issueId], (commentMapping, issueId) => {
2413
- return Object.values(commentMapping).filter((comment) => comment.issue === issueId);
2414
- })
2415
- );
2416
- const selectIssueUpdateMapping = (state) => state.issueReducer.updates;
2417
- const selectIssueUpdatesOfIssue = restructureCreateSelectorWithArgs(
2418
- createSelector([selectIssueUpdateMapping, (_state, issueId) => issueId], (updates, issueId) => {
2419
- return Object.values(updates).filter((update) => update.issue === issueId);
2420
- })
2421
- );
2422
- const selectAttachmentsOfIssue = restructureCreateSelectorWithArgs(
2423
- createSelector(
2424
- [selectIssueAttachments, (_state, issueId) => issueId],
2425
- (attachments, issueId) => {
2426
- return attachments.filter(({ issue }) => issueId === issue);
2427
- }
2428
- )
2429
- );
2430
- const selectIssueAttachment = (attachmentId) => (root) => {
2431
- return root.issueReducer.attachments[attachmentId];
2432
- };
2433
- const selectAttachmentsOfIssueByType = restructureCreateSelectorWithArgs(
2434
- createSelector(
2435
- [selectIssueAttachments, (_state, issueId) => issueId],
2436
- (attachments, issueId) => {
2437
- const attachmentsOfIssue = attachments.filter(({ issue }) => issue === issueId);
2438
- const fileAttachments = attachmentsOfIssue.filter(
2439
- // this null check here is necessary, there are cases where file_type is null or undefined
2440
- ({ file_type }) => !file_type || !file_type.startsWith("image/")
2441
- );
2442
- const imageAttachments = attachmentsOfIssue.filter(
2443
- // this null check here is necessary, there are cases where file_type is null or undefined
2444
- ({ file_type }) => file_type && file_type.startsWith("image/")
2445
- );
2446
- return { fileAttachments, imageAttachments };
2447
- }
2448
- )
2449
- );
2450
- const selectFileAttachmentsOfIssue = restructureCreateSelectorWithArgs(
2451
- createSelector(
2452
- [selectIssueAttachmentMapping, (_state, issueId) => issueId],
2453
- (attachmentMapping, issueId) => {
2454
- if (!issueId)
2455
- return void 0;
2456
- return Object.values(attachmentMapping).filter(
2457
- (attachment) => (
2458
- // Files with file_type that is null or not an image file
2459
- attachment.issue === issueId && (!attachment.file_type || !attachment.file_type.startsWith("image/"))
2460
- )
2461
- );
2462
- }
2463
- )
2464
- );
2465
2146
  const selectIssue = restructureCreateSelectorWithArgs(
2466
2147
  createSelector([selectIssueMapping, (_state, id) => id], (mapping, id) => {
2467
2148
  return mapping[id];
2468
2149
  })
2469
2150
  );
2470
- const selectAllAttachments = createSelector([selectIssueAttachmentMapping], (mapping) => Object.values(mapping));
2471
2151
  const searchIssues = restructureCreateSelectorWithArgs(
2472
2152
  createSelector(
2473
2153
  [selectIssueMapping, selectWorkspaceMapping, (_state, searchArgs) => searchArgs],
@@ -2558,47 +2238,25 @@ const selectRecentIssuesAsSearchResults = createSelector(
2558
2238
  }
2559
2239
  );
2560
2240
  const issueReducer = issueSlice.reducer;
2561
- const initialState$k = {
2562
- issueTypes: {}
2563
- };
2241
+ const issueTypeAdapter = createModelAdapter((issueType) => issueType.offline_id);
2242
+ const initialState$r = issueTypeAdapter.getInitialState({});
2564
2243
  const issueTypeSlice = createSlice({
2565
2244
  name: "issueTypes",
2566
- initialState: initialState$k,
2245
+ initialState: initialState$r,
2567
2246
  extraReducers: (builder) => builder.addCase("RESET", (state) => {
2568
- Object.assign(state, initialState$k);
2247
+ Object.assign(state, initialState$r);
2569
2248
  }),
2570
2249
  reducers: {
2571
- setIssueTypes: (state, action) => {
2572
- for (const issueType of action.payload) {
2573
- state.issueTypes[issueType.offline_id] = issueType;
2574
- }
2575
- },
2576
- setIssueType: (state, action) => {
2577
- state.issueTypes[action.payload.offline_id] = action.payload;
2578
- },
2579
- addIssueType: (state, action) => {
2580
- if (action.payload.offline_id in state.issueTypes) {
2581
- throw new Error(`IssueType with offline_id ${action.payload.offline_id} already exists in the store.`);
2582
- }
2583
- state.issueTypes[action.payload.offline_id] = action.payload;
2584
- },
2585
- updateIssueType: (state, action) => {
2586
- if (!(action.payload.offline_id in state.issueTypes)) {
2587
- throw new Error(`IssueType with offline_id ${action.payload.offline_id} does not exist in the store.`);
2588
- }
2589
- state.issueTypes[action.payload.offline_id] = action.payload;
2590
- },
2591
- removeIssueType: (state, action) => {
2592
- if (!(action.payload in state.issueTypes)) {
2593
- throw new Error(`IssueType with offline_id ${action.payload} does not exist in the store.`);
2594
- }
2595
- delete state.issueTypes[action.payload];
2596
- }
2250
+ initializeIssueTypes: issueTypeAdapter.initialize,
2251
+ setIssueType: issueTypeAdapter.setOne,
2252
+ addIssueType: issueTypeAdapter.addOne,
2253
+ updateIssueType: issueTypeAdapter.updateOne,
2254
+ removeIssueType: issueTypeAdapter.deleteOne
2597
2255
  }
2598
2256
  });
2599
- const { setIssueTypes, setIssueType, addIssueType, updateIssueType, removeIssueType } = issueTypeSlice.actions;
2257
+ const { initializeIssueTypes, setIssueType, addIssueType, updateIssueType, removeIssueType } = issueTypeSlice.actions;
2600
2258
  const selectIssueTypeMapping = (state) => {
2601
- return state.issueTypeReducer.issueTypes;
2259
+ return state.issueTypeReducer.instances;
2602
2260
  };
2603
2261
  const selectIssueTypes = createSelector(selectIssueTypeMapping, (issueTypes) => {
2604
2262
  return Object.values(issueTypes);
@@ -2621,7 +2279,7 @@ const selectIssueTypesOfOrganization = restructureCreateSelectorWithArgs(
2621
2279
  );
2622
2280
  const selectIssuesOfIssueType = restructureCreateSelectorWithArgs(
2623
2281
  createSelector(
2624
- [(state) => state.issueReducer.issues, (_, issueTypeId) => issueTypeId],
2282
+ [(state) => state.issueReducer.instances, (_, issueTypeId) => issueTypeId],
2625
2283
  (issuesMapping, issueTypeId) => {
2626
2284
  return Object.values(issuesMapping).filter((issue) => issue.issue_type === issueTypeId);
2627
2285
  }
@@ -2632,15 +2290,15 @@ const selectIssuesOfIssueTypeCount = (issueTypeId) => (state) => {
2632
2290
  return ((_a2 = selectIssuesOfIssueType(issueTypeId)(state)) == null ? void 0 : _a2.length) ?? 0;
2633
2291
  };
2634
2292
  const issueTypeReducer = issueTypeSlice.reducer;
2635
- const initialState$j = {
2293
+ const initialState$q = {
2636
2294
  s3Urls: {}
2637
2295
  };
2638
2296
  const msPerHour = 1e3 * 60 * 60;
2639
2297
  const msPerWeek = msPerHour * 24 * 7;
2640
2298
  const fileSlice = createSlice({
2641
2299
  name: "file",
2642
- initialState: initialState$j,
2643
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$j)),
2300
+ initialState: initialState$q,
2301
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$q)),
2644
2302
  reducers: {
2645
2303
  setUploadUrl: (state, action) => {
2646
2304
  const { url, fields, sha1 } = action.payload;
@@ -2667,7 +2325,7 @@ const selectUploadUrl = (sha1) => (state) => {
2667
2325
  return url;
2668
2326
  };
2669
2327
  const fileReducer = fileSlice.reducer;
2670
- const initialState$i = {
2328
+ const initialState$p = {
2671
2329
  // TODO: Change first MapStyle.SATELLITE to MaptStyle.None when project creation map is fixed
2672
2330
  mapStyle: MapStyle.SATELLITE,
2673
2331
  showTooltips: false,
@@ -2675,8 +2333,8 @@ const initialState$i = {
2675
2333
  };
2676
2334
  const mapSlice = createSlice({
2677
2335
  name: "map",
2678
- initialState: initialState$i,
2679
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$i)),
2336
+ initialState: initialState$p,
2337
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$p)),
2680
2338
  reducers: {
2681
2339
  setMapStyle: (state, action) => {
2682
2340
  state.mapStyle = action.payload;
@@ -2748,7 +2406,7 @@ var LicenseStatus = /* @__PURE__ */ ((LicenseStatus2) => {
2748
2406
  LicenseStatus2[LicenseStatus2["PAST_DUE"] = 8] = "PAST_DUE";
2749
2407
  return LicenseStatus2;
2750
2408
  })(LicenseStatus || {});
2751
- const initialState$h = {
2409
+ const initialState$o = {
2752
2410
  users: {},
2753
2411
  currentUser: {
2754
2412
  id: 0,
@@ -2759,8 +2417,8 @@ const initialState$h = {
2759
2417
  };
2760
2418
  const userSlice = createSlice({
2761
2419
  name: "users",
2762
- initialState: initialState$h,
2763
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$h)),
2420
+ initialState: initialState$o,
2421
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$o)),
2764
2422
  reducers: {
2765
2423
  setUsers: (state, action) => {
2766
2424
  const usersMapping = {};
@@ -2822,52 +2480,26 @@ const selectUser = (userId) => (state) => {
2822
2480
  const selectUsersAsMapping = (state) => state.userReducer.users;
2823
2481
  const selectFavouriteProjects = (state) => state.userReducer.currentUser.profile.favourite_project_ids;
2824
2482
  const userReducer = userSlice.reducer;
2825
- const initialState$g = {
2826
- organizationAccesses: {}
2827
- };
2483
+ const organizationAccessAdapter = createModelAdapter(
2484
+ (organizationAccess) => organizationAccess.offline_id
2485
+ );
2486
+ const initialState$n = organizationAccessAdapter.getInitialState({});
2828
2487
  const organizationAccessSlice = createSlice({
2829
2488
  name: "organizationAccess",
2830
- initialState: initialState$g,
2831
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$g)),
2489
+ initialState: initialState$n,
2490
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$n)),
2832
2491
  reducers: {
2833
- setOrganizationAccesses: (state, action) => {
2834
- if (!Array.isArray(action.payload))
2835
- throw new Error("Expected an array of OrganizationAccess");
2836
- if (action.payload.filter(onlyUniqueOfflineIds).length !== action.payload.length) {
2837
- throw new Error("Tried to use setOrganizationAccesses reducer with duplicate ID's");
2838
- }
2839
- const organizationAccesses = {};
2840
- for (const organizationAccess of action.payload) {
2841
- organizationAccesses[organizationAccess.offline_id] = organizationAccess;
2842
- }
2843
- state.organizationAccesses = organizationAccesses;
2844
- },
2845
- updateOrganizationAccess: (state, action) => {
2846
- if (action.payload.offline_id in state.organizationAccesses) {
2847
- state.organizationAccesses[action.payload.offline_id] = action.payload;
2848
- } else {
2849
- throw new Error(
2850
- `Tried to update organization access with ID that doesn't exist: ${action.payload.offline_id}`
2851
- );
2852
- }
2853
- },
2854
- removeOrganizationAccess: (state, action) => {
2855
- if (action.payload.offline_id in state.organizationAccesses) {
2856
- delete state.organizationAccesses[action.payload.offline_id];
2857
- } else {
2858
- throw new Error(
2859
- `Tried to remove organization access with ID that doesn't exist: ${action.payload.offline_id}`
2860
- );
2861
- }
2862
- }
2492
+ initializeOrganizationAccesses: organizationAccessAdapter.initialize,
2493
+ updateOrganizationAccess: organizationAccessAdapter.updateOne,
2494
+ deleteOrganizationAccess: organizationAccessAdapter.deleteOne
2863
2495
  }
2864
2496
  });
2865
- const { setOrganizationAccesses, updateOrganizationAccess, removeOrganizationAccess } = organizationAccessSlice.actions;
2497
+ const { initializeOrganizationAccesses, updateOrganizationAccess, deleteOrganizationAccess } = organizationAccessSlice.actions;
2866
2498
  const selectOrganizationAccesses = (state) => {
2867
- return state.organizationAccessReducer.organizationAccesses;
2499
+ return state.organizationAccessReducer.instances;
2868
2500
  };
2869
2501
  const selectOrganizationAccess = (organizationAccessId) => (state) => {
2870
- return state.organizationAccessReducer.organizationAccesses[organizationAccessId];
2502
+ return state.organizationAccessReducer.instances[organizationAccessId];
2871
2503
  };
2872
2504
  const selectActiveOrganizationAccess = createSelector(
2873
2505
  [selectCurrentUser, selectOrganizationAccesses],
@@ -2879,60 +2511,39 @@ const selectActiveOrganizationAccess = createSelector(
2879
2511
  }
2880
2512
  );
2881
2513
  const selectOrganizationAccessForUser = (user) => (state) => {
2882
- return Object.values(state.organizationAccessReducer.organizationAccesses).find(
2514
+ return Object.values(state.organizationAccessReducer.instances).find(
2883
2515
  (organizationAccess) => organizationAccess.user === user.id
2884
2516
  );
2885
2517
  };
2886
2518
  const selectOrganizationAccessUserMapping = (state) => {
2887
2519
  const organizationAccesses = {};
2888
- for (const organizationAccess of Object.values(state.organizationAccessReducer.organizationAccesses)) {
2520
+ for (const organizationAccess of Object.values(state.organizationAccessReducer.instances)) {
2889
2521
  organizationAccesses[organizationAccess.user] = organizationAccess;
2890
2522
  }
2891
2523
  return organizationAccesses;
2892
2524
  };
2893
2525
  const organizationAccessReducer = organizationAccessSlice.reducer;
2894
- const initialState$f = {
2895
- licenses: {}
2896
- };
2526
+ const licenseAdapter = createModelAdapter((license) => license.offline_id);
2527
+ const initialState$m = licenseAdapter.getInitialState({});
2897
2528
  const licenseSlice = createSlice({
2898
2529
  name: "license",
2899
- initialState: initialState$f,
2900
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$f)),
2530
+ initialState: initialState$m,
2531
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$m)),
2901
2532
  reducers: {
2902
- setLicenses: (state, action) => {
2903
- if (!Array.isArray(action.payload))
2904
- throw new Error("Expected an array of Licenses");
2905
- if (action.payload.filter(onlyUniqueOfflineIds).length !== action.payload.length) {
2906
- throw new Error("Tried to use setLicenses reducer with duplicate ID's");
2907
- }
2908
- const licenses = {};
2909
- for (const license of action.payload) {
2910
- licenses[license.offline_id] = license;
2911
- }
2912
- state.licenses = licenses;
2913
- },
2914
- addLicenses: (state, action) => {
2915
- for (const license of action.payload) {
2916
- state.licenses[license.offline_id] = license;
2917
- }
2918
- },
2919
- updateLicense: (state, action) => {
2920
- if (!(action.payload.offline_id in state.licenses)) {
2921
- throw new Error("Tried to update license that does not exist.");
2922
- }
2923
- state.licenses[action.payload.offline_id] = action.payload;
2924
- }
2533
+ setLicenses: licenseAdapter.initialize,
2534
+ addLicenses: licenseAdapter.addMany,
2535
+ updateLicense: licenseAdapter.updateOne
2925
2536
  }
2926
2537
  });
2927
2538
  const { setLicenses, addLicenses, updateLicense } = licenseSlice.actions;
2928
2539
  const selectLicenses = (state) => {
2929
- return state.licenseReducer.licenses;
2540
+ return state.licenseReducer.instances;
2930
2541
  };
2931
- const selectLicense = (licenseId) => (state) => state.licenseReducer.licenses[licenseId];
2932
- const selectActiveLicense = (state) => Object.values(state.licenseReducer.licenses).find(
2542
+ const selectLicense = (licenseId) => (state) => state.licenseReducer.instances[licenseId];
2543
+ const selectActiveLicense = (state) => Object.values(state.licenseReducer.instances).find(
2933
2544
  (license) => license.project === state.projectReducer.activeProjectId
2934
2545
  ) ?? null;
2935
- const selectLicenseForProject = (projectId) => (state) => Object.values(state.licenseReducer.licenses).find((license) => license.project === projectId);
2546
+ const selectLicenseForProject = (projectId) => (state) => Object.values(state.licenseReducer.instances).find((license) => license.project === projectId);
2936
2547
  const selectActiveStatusLicenses = createSelector(
2937
2548
  [selectLicenses],
2938
2549
  (licenses) => Object.values(licenses).filter((license) => license.is_active)
@@ -2942,90 +2553,58 @@ const selectLicensesForProjectsMapping = createSelector(
2942
2553
  (licenses) => Object.values(licenses).filter((license) => license.project).reduce((accum, license) => ({ ...accum, [license.project]: license }), {})
2943
2554
  );
2944
2555
  const licenseReducer = licenseSlice.reducer;
2945
- const initialState$e = {
2946
- projectAccesses: {}
2947
- };
2556
+ const projectAccessAdapter = createModelAdapter((projectAccess) => projectAccess.offline_id);
2557
+ const initialState$l = projectAccessAdapter.getInitialState({});
2948
2558
  const projectAccessSlice = createSlice({
2949
2559
  name: "projectAccess",
2950
- initialState: initialState$e,
2951
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$e)),
2560
+ initialState: initialState$l,
2561
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$l)),
2952
2562
  reducers: {
2953
- setProjectAccesses: (state, action) => {
2954
- if (!Array.isArray(action.payload))
2955
- throw new Error("Expected an array of ProjectAccess");
2956
- if (action.payload.filter(onlyUniqueOfflineIds).length !== action.payload.length) {
2957
- throw new Error("Tried to use setProjectAccesses reducer with duplicate ID's");
2958
- }
2959
- const projectAccesses = {};
2960
- for (const projectAccess of action.payload) {
2961
- projectAccesses[projectAccess.offline_id] = projectAccess;
2962
- }
2963
- state.projectAccesses = projectAccesses;
2964
- },
2965
- updateProjectAccess: (state, action) => {
2966
- if (action.payload.offline_id in state.projectAccesses) {
2967
- state.projectAccesses[action.payload.offline_id] = action.payload;
2968
- } else {
2969
- throw new Error(
2970
- `Tried to update project access with ID that doesn't exist: ${action.payload.offline_id}`
2971
- );
2972
- }
2973
- },
2974
- removeProjectAccess: (state, action) => {
2975
- if (action.payload.offline_id in state.projectAccesses) {
2976
- delete state.projectAccesses[action.payload.offline_id];
2977
- } else {
2978
- throw new Error(
2979
- `Tried to remove project access with ID that doesn't exist: ${action.payload.offline_id}`
2980
- );
2981
- }
2982
- },
2983
- removeProjectAccessesOfProject: (state, action) => {
2984
- for (const projectAccess of Object.values(state.projectAccesses)) {
2985
- if (projectAccess.project === action.payload) {
2986
- delete state.projectAccesses[projectAccess.offline_id];
2987
- }
2988
- }
2989
- }
2563
+ setProjectAccesses: projectAccessAdapter.initialize,
2564
+ updateProjectAccess: projectAccessAdapter.updateOne,
2565
+ deleteProjectAccess: projectAccessAdapter.deleteOne,
2566
+ deleteProjectAccesses: projectAccessAdapter.deleteMany
2990
2567
  }
2991
2568
  });
2992
- const { setProjectAccesses, updateProjectAccess, removeProjectAccess, removeProjectAccessesOfProject } = projectAccessSlice.actions;
2569
+ const { setProjectAccesses, updateProjectAccess, deleteProjectAccess, deleteProjectAccesses } = projectAccessSlice.actions;
2570
+ const selectProjectAccessMapping = (state) => {
2571
+ return state.projectAccessReducer.instances;
2572
+ };
2993
2573
  const selectProjectAccesses = (state) => {
2994
- return state.projectAccessReducer.projectAccesses;
2574
+ return Object.values(state.projectAccessReducer.instances);
2995
2575
  };
2996
2576
  const selectProjectAccess = (projectAccessId) => (state) => {
2997
- return state.projectAccessReducer.projectAccesses[projectAccessId];
2577
+ return state.projectAccessReducer.instances[projectAccessId];
2998
2578
  };
2999
2579
  const selectActiveProjectAccess = (state) => {
3000
2580
  const currentUser = state.userReducer.currentUser;
3001
2581
  const activeProjectId = state.projectReducer.activeProjectId;
3002
- return Object.values(state.projectAccessReducer.projectAccesses).find((projectAccess) => {
2582
+ return Object.values(state.projectAccessReducer.instances).find((projectAccess) => {
3003
2583
  return projectAccess.user === currentUser.id && projectAccess.project === activeProjectId;
3004
2584
  }) ?? null;
3005
2585
  };
3006
2586
  const selectProjectAccessForUser = (user) => (state) => {
3007
- return Object.values(state.projectAccessReducer.projectAccesses).find(
2587
+ return Object.values(state.projectAccessReducer.instances).find(
3008
2588
  (projectAccess) => projectAccess.user === user.id
3009
2589
  );
3010
2590
  };
3011
2591
  const selectProjectAccessUserMapping = (state) => {
3012
2592
  const projectAccesses = {};
3013
- for (const projectAccess of Object.values(state.projectAccessReducer.projectAccesses)) {
2593
+ for (const projectAccess of Object.values(state.projectAccessReducer.instances)) {
3014
2594
  projectAccesses[projectAccess.user] = projectAccess;
3015
2595
  }
3016
2596
  return projectAccesses;
3017
2597
  };
3018
2598
  const projectAccessReducer = projectAccessSlice.reducer;
3019
- const initialState$d = {
2599
+ const initialState$k = {
3020
2600
  projects: {},
3021
2601
  activeProjectId: null,
3022
2602
  recentProjectIds: [],
3023
- recentSearchableQueries: [],
3024
- attachments: {}
2603
+ recentSearchableQueries: []
3025
2604
  };
3026
2605
  const projectSlice = createSlice({
3027
2606
  name: "projects",
3028
- initialState: initialState$d,
2607
+ initialState: initialState$k,
3029
2608
  reducers: {
3030
2609
  setProjects: (state, action) => {
3031
2610
  const projectsMap = {};
@@ -3089,16 +2668,7 @@ const projectSlice = createSlice({
3089
2668
  } else {
3090
2669
  throw new Error("Update form submissions count: no active project");
3091
2670
  }
3092
- },
3093
- // Attachments
3094
- setProjectAttachment: setAttachment,
3095
- setProjectAttachments: setAttachments,
3096
- addProjectAttachment: addAttachment,
3097
- addProjectAttachments: addAttachments,
3098
- updateProjectAttachment: updateAttachment,
3099
- updateProjectAttachments: updateAttachments,
3100
- removeProjectAttachment: removeAttachment,
3101
- removeProjectAttachments: removeAttachments
2671
+ }
3102
2672
  }
3103
2673
  });
3104
2674
  const {
@@ -3109,16 +2679,7 @@ const {
3109
2679
  deleteProject,
3110
2680
  acceptProjectInvite,
3111
2681
  addActiveProjectIssuesCount,
3112
- addActiveProjectFormSubmissionsCount,
3113
- // Attachments
3114
- setProjectAttachment,
3115
- setProjectAttachments,
3116
- addProjectAttachment,
3117
- addProjectAttachments,
3118
- updateProjectAttachment,
3119
- updateProjectAttachments,
3120
- removeProjectAttachment,
3121
- removeProjectAttachments
2682
+ addActiveProjectFormSubmissionsCount
3122
2683
  } = projectSlice.actions;
3123
2684
  const selectProjects = (state) => state.projectReducer.projects;
3124
2685
  const selectActiveProjectId = (state) => state.projectReducer.activeProjectId;
@@ -3149,7 +2710,7 @@ const selectSortedProjects = createSelector(
3149
2710
  );
3150
2711
  const projectReducer = projectSlice.reducer;
3151
2712
  const selectProjectUsersIds = createSelector(
3152
- [selectProjectAccesses],
2713
+ [selectProjectAccessMapping],
3153
2714
  (projectAccesses) => Object.values(projectAccesses).map((projectAccess) => projectAccess.user)
3154
2715
  );
3155
2716
  const selectProjectUsersAsMapping = createSelector(
@@ -3181,47 +2742,14 @@ const selectSortedProjectUsers = createSelector(
3181
2742
  });
3182
2743
  }
3183
2744
  );
3184
- const selectProjectAttachmentMapping = (state) => state.projectReducer.attachments;
3185
- const selectAllProjectAttachments = createSelector(
3186
- [selectProjectAttachmentMapping],
3187
- (mapping) => Object.values(mapping)
3188
- );
3189
- const selectProjectAttachment = (attachmentId) => (state) => {
3190
- return state.projectReducer.attachments[attachmentId];
3191
- };
3192
- const selectAttachmentsOfProject = restructureCreateSelectorWithArgs(
3193
- createSelector(
3194
- [selectAllProjectAttachments, (_state, projectId) => projectId],
3195
- (attachments, projectId) => {
3196
- return attachments.filter(({ project }) => projectId === project);
3197
- }
3198
- )
3199
- );
3200
- const selectAttachmentsOfProjectByType = restructureCreateSelectorWithArgs(
3201
- createSelector(
3202
- [selectAllProjectAttachments, (_state, projectId) => projectId],
3203
- (attachments, projectId) => {
3204
- const attachmentsOfProject = attachments.filter(({ project }) => projectId === project);
3205
- const fileAttachments = attachmentsOfProject.filter(
3206
- // this null check here is necessary, there are cases where file_type is null or undefined
3207
- ({ file_type }) => !file_type || !file_type.startsWith("image/")
3208
- );
3209
- const imageAttachments = attachmentsOfProject.filter(
3210
- // this null check here is necessary, there are cases where file_type is null or undefined
3211
- ({ file_type }) => file_type && file_type.startsWith("image/")
3212
- );
3213
- return { fileAttachments, imageAttachments };
3214
- }
3215
- )
3216
- );
3217
- const initialState$c = {
2745
+ const initialState$j = {
3218
2746
  organizations: {},
3219
2747
  activeOrganizationId: null
3220
2748
  };
3221
2749
  const organizationSlice = createSlice({
3222
2750
  name: "organizations",
3223
- initialState: initialState$c,
3224
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$c)),
2751
+ initialState: initialState$j,
2752
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$j)),
3225
2753
  reducers: {
3226
2754
  setOrganizations: (state, action) => {
3227
2755
  for (const org of action.payload) {
@@ -3340,14 +2868,14 @@ const createOfflineAction = (request2, baseUrl) => {
3340
2868
  }
3341
2869
  };
3342
2870
  };
3343
- const initialState$b = {
2871
+ const initialState$i = {
3344
2872
  deletedRequests: [],
3345
2873
  latestRetryTime: 0
3346
2874
  };
3347
2875
  const outboxSlice = createSlice({
3348
2876
  name: "outbox",
3349
- initialState: initialState$b,
3350
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$b)),
2877
+ initialState: initialState$i,
2878
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$i)),
3351
2879
  reducers: {
3352
2880
  // enqueueActions is a reducer that does nothing but enqueue API request to the Redux Offline outbox
3353
2881
  // Whenever an issue is being created, a reducer addIssue() is responsible for adding it to the offline store
@@ -3379,7 +2907,7 @@ const selectDeletedRequests = (state) => state.outboxReducer.deletedRequests;
3379
2907
  const selectLatestRetryTime = (state) => state.outboxReducer.latestRetryTime;
3380
2908
  const { enqueueRequest, markForDeletion, markAsDeleted, _setLatestRetryTime } = outboxSlice.actions;
3381
2909
  const outboxReducer = outboxSlice.reducer;
3382
- const initialState$a = {
2910
+ const initialState$h = {
3383
2911
  projectFiles: {},
3384
2912
  activeProjectFileId: null,
3385
2913
  isImportingProjectFile: false,
@@ -3387,8 +2915,8 @@ const initialState$a = {
3387
2915
  };
3388
2916
  const projectFileSlice = createSlice({
3389
2917
  name: "projectFiles",
3390
- initialState: initialState$a,
3391
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$a)),
2918
+ initialState: initialState$h,
2919
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$h)),
3392
2920
  reducers: {
3393
2921
  addOrReplaceProjectFiles: (state, action) => {
3394
2922
  for (let fileObj of action.payload) {
@@ -3489,12 +3017,75 @@ const selectProjectFiles = createSelector(
3489
3017
  const selectActiveProjectFileId = (state) => state.projectFileReducer.activeProjectFileId;
3490
3018
  const selectIsImportingProjectFile = (state) => state.projectFileReducer.isImportingProjectFile;
3491
3019
  const projectFileReducer = projectFileSlice.reducer;
3492
- const initialState$9 = {
3020
+ const projectAttachmentAdapter = createModelAdapter((attachment) => attachment.offline_id);
3021
+ const initialState$g = projectAttachmentAdapter.getInitialState({});
3022
+ const projectAttachmentSlice = createSlice({
3023
+ name: "projectAttachments",
3024
+ initialState: initialState$g,
3025
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$g)),
3026
+ reducers: {
3027
+ initializeProjectAttachments: projectAttachmentAdapter.initialize,
3028
+ addProjectAttachment: projectAttachmentAdapter.addOne,
3029
+ addProjectAttachments: projectAttachmentAdapter.addMany,
3030
+ setProjectAttachment: projectAttachmentAdapter.setOne,
3031
+ setProjectAttachments: projectAttachmentAdapter.setMany,
3032
+ updateProjectAttachment: projectAttachmentAdapter.updateOne,
3033
+ updateProjectAttachments: projectAttachmentAdapter.updateMany,
3034
+ deleteProjectAttachment: projectAttachmentAdapter.deleteOne,
3035
+ deleteProjectAttachments: projectAttachmentAdapter.deleteMany
3036
+ }
3037
+ });
3038
+ const {
3039
+ initializeProjectAttachments,
3040
+ addProjectAttachment,
3041
+ addProjectAttachments,
3042
+ setProjectAttachment,
3043
+ setProjectAttachments,
3044
+ updateProjectAttachment,
3045
+ updateProjectAttachments,
3046
+ deleteProjectAttachment,
3047
+ deleteProjectAttachments
3048
+ } = projectAttachmentSlice.actions;
3049
+ const selectProjectAttachmentMapping = (state) => state.projectAttachmentReducer.instances;
3050
+ const selectAllProjectAttachments = createSelector(
3051
+ [selectProjectAttachmentMapping],
3052
+ (mapping) => Object.values(mapping)
3053
+ );
3054
+ const selectProjectAttachment = (attachmentId) => (state) => {
3055
+ return state.projectAttachmentReducer.instances[attachmentId];
3056
+ };
3057
+ const selectAttachmentsOfProject = restructureCreateSelectorWithArgs(
3058
+ createSelector(
3059
+ [selectAllProjectAttachments, (_state, projectId) => projectId],
3060
+ (attachments, projectId) => {
3061
+ return attachments.filter(({ project }) => projectId === project);
3062
+ }
3063
+ )
3064
+ );
3065
+ const selectAttachmentsOfProjectByType = restructureCreateSelectorWithArgs(
3066
+ createSelector(
3067
+ [selectAllProjectAttachments, (_state, projectId) => projectId],
3068
+ (attachments, projectId) => {
3069
+ const attachmentsOfProject = attachments.filter(({ project }) => projectId === project);
3070
+ const fileAttachments = attachmentsOfProject.filter(
3071
+ // this null check here is necessary, there are cases where file_type is null or undefined
3072
+ ({ file_type }) => !file_type || !file_type.startsWith("image/")
3073
+ );
3074
+ const imageAttachments = attachmentsOfProject.filter(
3075
+ // this null check here is necessary, there are cases where file_type is null or undefined
3076
+ ({ file_type }) => file_type && file_type.startsWith("image/")
3077
+ );
3078
+ return { fileAttachments, imageAttachments };
3079
+ }
3080
+ )
3081
+ );
3082
+ const projectAttachmentReducer = projectAttachmentSlice.reducer;
3083
+ const initialState$f = {
3493
3084
  isRehydrated: false
3494
3085
  };
3495
3086
  const rehydratedSlice = createSlice({
3496
3087
  name: "rehydrated",
3497
- initialState: initialState$9,
3088
+ initialState: initialState$f,
3498
3089
  // The `reducers` field lets us define reducers and generate associated actions
3499
3090
  reducers: {
3500
3091
  setRehydrated: (state, action) => {
@@ -3504,7 +3095,7 @@ const rehydratedSlice = createSlice({
3504
3095
  });
3505
3096
  const selectRehydrated = (state) => state.rehydratedReducer.isRehydrated;
3506
3097
  const rehydratedReducer = rehydratedSlice.reducer;
3507
- const initialState$8 = {
3098
+ const initialState$e = {
3508
3099
  useIssueTemplate: false,
3509
3100
  placementMode: false,
3510
3101
  enableClustering: false,
@@ -3522,8 +3113,8 @@ const initialState$8 = {
3522
3113
  };
3523
3114
  const settingSlice = createSlice({
3524
3115
  name: "settings",
3525
- initialState: initialState$8,
3526
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$8)),
3116
+ initialState: initialState$e,
3117
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$e)),
3527
3118
  reducers: {
3528
3119
  setEnableDuplicateIssues: (state, action) => {
3529
3120
  state.useIssueTemplate = action.payload;
@@ -3582,119 +3173,36 @@ const formRevisionSortFn = (formRevisionA, formRevisionB) => {
3582
3173
  return revisionA < revisionB ? -1 : 1;
3583
3174
  }
3584
3175
  };
3585
- const initialState$7 = {
3586
- formRevisions: {},
3587
- attachments: {}
3588
- };
3176
+ const formRevisionAdapter = createModelAdapter((revision) => revision.offline_id);
3177
+ const initialState$d = formRevisionAdapter.getInitialState({});
3589
3178
  const formRevisionsSlice = createSlice({
3590
3179
  name: "formRevisions",
3591
- initialState: initialState$7,
3592
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$7)),
3180
+ initialState: initialState$d,
3181
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$d)),
3593
3182
  reducers: {
3594
- // revision related actions
3595
- setFormRevision: (state, action) => {
3596
- state.formRevisions[action.payload.offline_id] = action.payload;
3597
- },
3598
- setFormRevisions: (state, action) => {
3599
- state.formRevisions = {};
3600
- for (const revision of action.payload) {
3601
- state.formRevisions[revision.offline_id] = revision;
3602
- }
3603
- },
3604
- addFormRevision: (state, action) => {
3605
- if (state.formRevisions[action.payload.offline_id] !== void 0) {
3606
- throw new Error(`Revision with offline_id ${action.payload.offline_id} already exists`);
3607
- }
3608
- state.formRevisions[action.payload.offline_id] = action.payload;
3609
- },
3610
- addFormRevisions: (state, action) => {
3611
- for (const userFormRevision of action.payload) {
3612
- if (state.formRevisions[userFormRevision.offline_id] !== void 0) {
3613
- throw new Error(`Revision with offline_id ${userFormRevision.offline_id} already exists`);
3614
- }
3615
- }
3616
- for (const userFormRevision of action.payload) {
3617
- state.formRevisions[userFormRevision.offline_id] = userFormRevision;
3618
- }
3619
- },
3620
- // UserFormRevisions do not get updated
3621
- deleteFormRevision: (state, action) => {
3622
- if (state.formRevisions[action.payload] === void 0) {
3623
- throw new Error(`Revision with offline_id ${action.payload} does not exist`);
3624
- }
3625
- delete state.formRevisions[action.payload];
3626
- },
3627
- deleteFormRevisions: (state, action) => {
3628
- for (const offlineId of action.payload) {
3629
- if (state.formRevisions[offlineId] === void 0) {
3630
- throw new Error(`Revision with offline_id ${offlineId} does not exist`);
3631
- }
3632
- }
3633
- for (const offlineId of action.payload) {
3634
- delete state.formRevisions[offlineId];
3635
- }
3636
- },
3637
- // attachment related actions
3638
- setFormRevisionAttachments: (state, action) => {
3639
- state.attachments = {};
3640
- for (const attachment of action.payload) {
3641
- state.attachments[attachment.offline_id] = attachment;
3642
- }
3643
- },
3644
- addFormRevisionAttachment: (state, action) => {
3645
- if (state.attachments[action.payload.offline_id] !== void 0) {
3646
- throw new Error(`Attachment with offline_id ${action.payload.offline_id} already exists`);
3647
- }
3648
- state.attachments[action.payload.offline_id] = action.payload;
3649
- },
3650
- addFormRevisionAttachments: (state, action) => {
3651
- for (const attachment of action.payload) {
3652
- if (state.attachments[attachment.offline_id] !== void 0) {
3653
- throw new Error(`Attachment with offline_id ${attachment.offline_id} already exists`);
3654
- }
3655
- }
3656
- for (const attachment of action.payload) {
3657
- state.attachments[attachment.offline_id] = attachment;
3658
- }
3659
- },
3660
- deleteFormRevisionAttachment: (state, action) => {
3661
- if (state.attachments[action.payload] === void 0) {
3662
- throw new Error(`Attachment with offline_id ${action.payload} does not exist`);
3663
- }
3664
- delete state.attachments[action.payload];
3665
- },
3666
- deleteFormRevisionAttachments: (state, action) => {
3667
- for (const offlineId of action.payload) {
3668
- if (state.attachments[offlineId] === void 0) {
3669
- throw new Error(`Attachment with offline_id ${offlineId} does not exist`);
3670
- }
3671
- }
3672
- for (const offlineId of action.payload) {
3673
- delete state.attachments[offlineId];
3674
- }
3675
- }
3183
+ initializeFormRevisions: formRevisionAdapter.initialize,
3184
+ setFormRevision: formRevisionAdapter.setOne,
3185
+ addFormRevision: formRevisionAdapter.addOne,
3186
+ addFormRevisions: formRevisionAdapter.addMany,
3187
+ deleteFormRevision: formRevisionAdapter.deleteOne,
3188
+ deleteFormRevisions: formRevisionAdapter.deleteMany
3676
3189
  }
3677
3190
  });
3678
3191
  const {
3679
3192
  setFormRevision,
3680
- setFormRevisions,
3193
+ initializeFormRevisions,
3681
3194
  addFormRevision,
3682
3195
  addFormRevisions,
3683
3196
  deleteFormRevision,
3684
- deleteFormRevisions,
3685
- setFormRevisionAttachments,
3686
- addFormRevisionAttachment,
3687
- addFormRevisionAttachments,
3688
- deleteFormRevisionAttachment,
3689
- deleteFormRevisionAttachments
3197
+ deleteFormRevisions
3690
3198
  } = formRevisionsSlice.actions;
3691
- const selectFormRevisionMapping = (state) => state.formRevisionReducer.formRevisions;
3199
+ const selectFormRevisionMapping = (state) => state.formRevisionReducer.instances;
3692
3200
  const selectFormRevisions = createSelector(
3693
3201
  [selectFormRevisionMapping],
3694
3202
  (formRevisions) => Object.values(formRevisions)
3695
3203
  );
3696
3204
  const selectFormRevision = (formRevisionId) => (state) => {
3697
- return state.formRevisionReducer.formRevisions[formRevisionId];
3205
+ return state.formRevisionReducer.instances[formRevisionId];
3698
3206
  };
3699
3207
  const _selectLatestFormRevision = (formRevisions, formId2) => {
3700
3208
  let ret = null;
@@ -3723,7 +3231,7 @@ const selectFormRevisionsOfForm = restructureCreateSelectorWithArgs(
3723
3231
  const selectLatestFormRevisionsOfAssetTypes = restructureCreateSelectorWithArgs(
3724
3232
  createSelector(
3725
3233
  [
3726
- (state) => state.formReducer.forms,
3234
+ (state) => state.formReducer.instances,
3727
3235
  selectFormRevisionMapping,
3728
3236
  (_state, assetTypeIds) => assetTypeIds
3729
3237
  ],
@@ -3757,67 +3265,28 @@ const selectLatestFormRevisionByForm = createSelector([selectFormRevisionMapping
3757
3265
  }
3758
3266
  return latestRevisions;
3759
3267
  });
3760
- const selectUserFormRevisionAttachmentsMapping = (state) => {
3761
- return state.formRevisionReducer.attachments;
3762
- };
3763
- const selectAttachmentsOfFormRevision = restructureCreateSelectorWithArgs(
3764
- createSelector(
3765
- [selectUserFormRevisionAttachmentsMapping, (_state, revisionId) => revisionId],
3766
- (attachments, revisionId) => {
3767
- return Object.values(attachments).filter((attachment) => attachment.revision === revisionId);
3768
- }
3769
- )
3770
- );
3771
3268
  const formRevisionReducer = formRevisionsSlice.reducer;
3772
- const initialState$6 = {
3773
- forms: {}
3774
- };
3269
+ const formAdapter = createModelAdapter((form) => form.offline_id);
3270
+ const initialState$c = formAdapter.getInitialState({});
3775
3271
  const formSlice = createSlice({
3776
3272
  name: "forms",
3777
- initialState: initialState$6,
3778
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$6)),
3273
+ initialState: initialState$c,
3274
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$c)),
3779
3275
  reducers: {
3780
- setForms: (state, action) => {
3781
- state.forms = {};
3782
- action.payload.forEach((userForm) => {
3783
- state.forms[userForm.offline_id] = userForm;
3784
- });
3785
- },
3786
- addForm: (state, action) => {
3787
- state.forms[action.payload.offline_id] = action.payload;
3788
- },
3789
- addForms: (state, action) => {
3790
- for (const userForm of action.payload) {
3791
- state.forms[userForm.offline_id] = userForm;
3792
- }
3793
- },
3794
- favoriteForm: (state, action) => {
3795
- const { formId: formId2 } = action.payload;
3796
- const form = state.forms[formId2];
3797
- if (!form) {
3798
- throw new Error("No form exists with the id " + formId2);
3799
- }
3800
- form.favorite = true;
3801
- },
3802
- unfavoriteForm: (state, action) => {
3803
- const { formId: formId2 } = action.payload;
3804
- const form = state.forms[formId2];
3805
- if (!form) {
3806
- throw new Error("No form exists with the id " + formId2);
3807
- }
3808
- form.favorite = false;
3809
- },
3810
- deleteForm: (state, action) => {
3811
- delete state.forms[action.payload];
3812
- }
3276
+ setForms: formAdapter.initialize,
3277
+ setForm: formAdapter.setOne,
3278
+ addForm: formAdapter.addOne,
3279
+ addForms: formAdapter.addMany,
3280
+ updateForm: formAdapter.updateOne,
3281
+ deleteForm: formAdapter.deleteOne
3813
3282
  }
3814
3283
  });
3815
- const { setForms, addForm, addForms, favoriteForm, unfavoriteForm, deleteForm } = formSlice.actions;
3284
+ const { setForms, setForm, addForm, addForms, updateForm, deleteForm } = formSlice.actions;
3816
3285
  const selectFilteredForms = restructureCreateSelectorWithArgs(
3817
3286
  createSelector(
3818
3287
  [
3819
- (state) => state.formReducer.forms,
3820
- (state) => state.formRevisionReducer.formRevisions,
3288
+ (state) => state.formReducer.instances,
3289
+ (state) => state.formRevisionReducer.instances,
3821
3290
  (_state, search) => search
3822
3291
  ],
3823
3292
  (userForms, revisions, search) => {
@@ -3850,10 +3319,10 @@ const selectFilteredForms = restructureCreateSelectorWithArgs(
3850
3319
  )
3851
3320
  );
3852
3321
  const selectForm = (formId2) => (state) => {
3853
- return state.formReducer.forms[formId2];
3322
+ return state.formReducer.instances[formId2];
3854
3323
  };
3855
3324
  const selectFormMapping = (state) => {
3856
- return state.formReducer.forms;
3325
+ return state.formReducer.instances;
3857
3326
  };
3858
3327
  const selectFormOfAssetType = restructureCreateSelectorWithArgs(
3859
3328
  createSelector(
@@ -3878,123 +3347,21 @@ const selectGeneralFormCount = createSelector([selectFormMapping], (userForms) =
3878
3347
  return Object.values(userForms).filter((form) => !form.asset_type).length;
3879
3348
  });
3880
3349
  const formReducer = formSlice.reducer;
3881
- const initialState$5 = {
3882
- formSubmissions: {},
3883
- attachments: {}
3884
- };
3350
+ const submissionAdapter = createModelAdapter((submission) => submission.offline_id);
3351
+ const initialState$b = submissionAdapter.getInitialState({});
3885
3352
  const formSubmissionSlice = createSlice({
3886
3353
  name: "formSubmissions",
3887
- initialState: initialState$5,
3888
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$5)),
3354
+ initialState: initialState$b,
3355
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$b)),
3889
3356
  reducers: {
3890
- setFormSubmission: (state, action) => {
3891
- state.formSubmissions[action.payload.offline_id] = action.payload;
3892
- },
3893
- setFormSubmissions: (state, action) => {
3894
- state.formSubmissions = {};
3895
- for (const submission of action.payload) {
3896
- state.formSubmissions[submission.offline_id] = submission;
3897
- }
3898
- },
3899
- addFormSubmission: (state, action) => {
3900
- if (action.payload.offline_id in state.formSubmissions) {
3901
- throw new Error(`Submission with offline_id ${action.payload.offline_id} already exists`);
3902
- }
3903
- state.formSubmissions[action.payload.offline_id] = action.payload;
3904
- },
3905
- addFormSubmissions: (state, action) => {
3906
- for (const submission of action.payload) {
3907
- if (state.formSubmissions[submission.offline_id] !== void 0) {
3908
- throw new Error(`Submission with offline_id ${submission.offline_id} already exists`);
3909
- }
3910
- }
3911
- for (const submission of action.payload) {
3912
- state.formSubmissions[submission.offline_id] = submission;
3913
- }
3914
- },
3915
- updateFormSubmission: (state, action) => {
3916
- if (state.formSubmissions[action.payload.offline_id] === void 0) {
3917
- throw new Error(`Submission with offline_id ${action.payload.offline_id} does not exist`);
3918
- }
3919
- state.formSubmissions[action.payload.offline_id] = action.payload;
3920
- },
3921
- updateFormSubmissions: (state, action) => {
3922
- for (const submission of action.payload) {
3923
- if (state.formSubmissions[submission.offline_id] === void 0) {
3924
- throw new Error(`Submission with offline_id ${submission.offline_id} does not exist`);
3925
- }
3926
- }
3927
- for (const submission of action.payload) {
3928
- state.formSubmissions[submission.offline_id] = submission;
3929
- }
3930
- },
3931
- deleteFormSubmission: (state, action) => {
3932
- if (state.formSubmissions[action.payload] === void 0) {
3933
- throw new Error(`Submission with offline_id ${action.payload} does not exist`);
3934
- }
3935
- delete state.formSubmissions[action.payload];
3936
- },
3937
- deleteFormSubmissions: (state, action) => {
3938
- for (const offlineId of action.payload) {
3939
- if (state.formSubmissions[offlineId] === void 0) {
3940
- throw new Error(`Submission with offline_id ${offlineId} does not exist`);
3941
- }
3942
- delete state.formSubmissions[offlineId];
3943
- }
3944
- for (const offlineId of action.payload) {
3945
- delete state.formSubmissions[offlineId];
3946
- }
3947
- },
3948
- // Attachments
3949
- addFormSubmissionAttachment: (state, action) => {
3950
- if (state.attachments[action.payload.offline_id] !== void 0) {
3951
- throw new Error(`Attachment with offline_id ${action.payload.offline_id} already exists`);
3952
- }
3953
- state.attachments[action.payload.offline_id] = action.payload;
3954
- },
3955
- addFormSubmissionAttachments: (state, action) => {
3956
- for (const attachment of action.payload) {
3957
- if (state.attachments[attachment.offline_id] !== void 0) {
3958
- throw new Error(`Attachment with offline_id ${attachment.offline_id} already exists`);
3959
- }
3960
- }
3961
- for (const attachment of action.payload) {
3962
- state.attachments[attachment.offline_id] = attachment;
3963
- }
3964
- },
3965
- // We only need a multi set for attachments because they are not updated, only added and deleted
3966
- setFormSubmissionAttachments: (state, action) => {
3967
- state.attachments = {};
3968
- for (const attachment of action.payload) {
3969
- state.attachments[attachment.offline_id] = attachment;
3970
- }
3971
- },
3972
- updateFormSubmissionAttachments: (state, action) => {
3973
- for (const attachment of action.payload) {
3974
- if (state.attachments[attachment.offline_id] === void 0) {
3975
- throw new Error(`Attachment with offline_id ${attachment.offline_id} does not exist`);
3976
- }
3977
- }
3978
- for (const attachment of action.payload) {
3979
- state.attachments[attachment.offline_id] = attachment;
3980
- }
3981
- },
3982
- // The delete actions for UserFormSubmissionAttachments are not used in the app, but are included for completeness
3983
- // Could be used if editing a submission is ever supported, will be applicable for supporting tip tap content in submissions
3984
- deleteFormSubmissionAttachment: (state, action) => {
3985
- if (state.attachments[action.payload] === void 0) {
3986
- throw new Error(`Attachment with offline_id ${action.payload} does not exist`);
3987
- }
3988
- delete state.attachments[action.payload];
3989
- },
3990
- deleteFormSubmissionAttachments: (state, action) => {
3991
- for (const offlineId of action.payload) {
3992
- if (state.attachments[offlineId] === void 0) {
3993
- throw new Error(`Attachment with offline_id ${offlineId} does not exist`);
3994
- }
3995
- delete state.attachments[offlineId];
3996
- }
3997
- }
3357
+ setFormSubmission: submissionAdapter.setOne,
3358
+ setFormSubmissions: submissionAdapter.setMany,
3359
+ addFormSubmission: submissionAdapter.addOne,
3360
+ addFormSubmissions: submissionAdapter.addMany,
3361
+ updateFormSubmission: submissionAdapter.updateOne,
3362
+ updateFormSubmissions: submissionAdapter.updateMany,
3363
+ deleteFormSubmission: submissionAdapter.deleteOne,
3364
+ deleteFormSubmissions: submissionAdapter.deleteMany
3998
3365
  }
3999
3366
  });
4000
3367
  const {
@@ -4005,16 +3372,10 @@ const {
4005
3372
  updateFormSubmission,
4006
3373
  updateFormSubmissions,
4007
3374
  deleteFormSubmission,
4008
- deleteFormSubmissions,
4009
- addFormSubmissionAttachment,
4010
- addFormSubmissionAttachments,
4011
- setFormSubmissionAttachments,
4012
- updateFormSubmissionAttachments,
4013
- deleteFormSubmissionAttachment,
4014
- deleteFormSubmissionAttachments
3375
+ deleteFormSubmissions
4015
3376
  } = formSubmissionSlice.actions;
4016
3377
  const selectFormSubmissionsMapping = (state) => {
4017
- return state.formSubmissionReducer.formSubmissions;
3378
+ return state.formSubmissionReducer.instances;
4018
3379
  };
4019
3380
  const selectFormSubmissions = createSelector(
4020
3381
  [selectFormSubmissionsMapping],
@@ -4023,7 +3384,7 @@ const selectFormSubmissions = createSelector(
4023
3384
  }
4024
3385
  );
4025
3386
  const selectFormSubmission = (submissionId) => (state) => {
4026
- return state.formSubmissionReducer.formSubmissions[submissionId];
3387
+ return state.formSubmissionReducer.instances[submissionId];
4027
3388
  };
4028
3389
  const selectFormSubmissionsOfForm = restructureCreateSelectorWithArgs(
4029
3390
  createSelector(
@@ -4128,8 +3489,40 @@ const selectFormSubmissionsByAssets = createSelector(
4128
3489
  return assetSubmissionMapping;
4129
3490
  }
4130
3491
  );
3492
+ const formSubmissionReducer = formSubmissionSlice.reducer;
3493
+ const formSubmissionAttachmentAdapter = createModelAdapter(
3494
+ (attachment) => attachment.offline_id
3495
+ );
3496
+ const initialState$a = formSubmissionAttachmentAdapter.getInitialState({});
3497
+ const formSubmissionAttachmentSlice = createSlice({
3498
+ name: "formSubmissionAttachments",
3499
+ initialState: initialState$a,
3500
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$a)),
3501
+ reducers: {
3502
+ initializeFormSubmissionAttachments: formSubmissionAttachmentAdapter.initialize,
3503
+ addFormSubmissionAttachment: formSubmissionAttachmentAdapter.addOne,
3504
+ addFormSubmissionAttachments: formSubmissionAttachmentAdapter.addMany,
3505
+ setFormSubmissionAttachment: formSubmissionAttachmentAdapter.setOne,
3506
+ setFormSubmissionAttachments: formSubmissionAttachmentAdapter.setMany,
3507
+ updateFormSubmissionAttachment: formSubmissionAttachmentAdapter.updateOne,
3508
+ updateFormSubmissionAttachments: formSubmissionAttachmentAdapter.updateMany,
3509
+ deleteFormSubmissionAttachment: formSubmissionAttachmentAdapter.deleteOne,
3510
+ deleteFormSubmissionAttachments: formSubmissionAttachmentAdapter.deleteMany
3511
+ }
3512
+ });
3513
+ const {
3514
+ initializeFormSubmissionAttachments,
3515
+ addFormSubmissionAttachment,
3516
+ addFormSubmissionAttachments,
3517
+ setFormSubmissionAttachment,
3518
+ setFormSubmissionAttachments,
3519
+ updateFormSubmissionAttachment,
3520
+ updateFormSubmissionAttachments,
3521
+ deleteFormSubmissionAttachment,
3522
+ deleteFormSubmissionAttachments
3523
+ } = formSubmissionAttachmentSlice.actions;
4131
3524
  const selectFormSubmissionAttachmentsMapping = (state) => {
4132
- return state.formSubmissionReducer.attachments;
3525
+ return state.formSubmissionAttachmentReducer.instances;
4133
3526
  };
4134
3527
  const selectAttachmentsOfFormSubmission = restructureCreateSelectorWithArgs(
4135
3528
  createSelector(
@@ -4139,48 +3532,81 @@ const selectAttachmentsOfFormSubmission = restructureCreateSelectorWithArgs(
4139
3532
  }
4140
3533
  )
4141
3534
  );
4142
- const formSubmissionReducer = formSubmissionSlice.reducer;
4143
- const initialState$4 = {
4144
- emailDomains: {}
3535
+ const formSubmissionAttachmentReducer = formSubmissionAttachmentSlice.reducer;
3536
+ const formRevisionAttachmentAdapter = createModelAdapter(
3537
+ (attachment) => attachment.offline_id
3538
+ );
3539
+ const initialState$9 = formRevisionAttachmentAdapter.getInitialState({});
3540
+ const formRevisionAttachmentSlice = createSlice({
3541
+ name: "formRevisionAttachments",
3542
+ initialState: initialState$9,
3543
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$9)),
3544
+ reducers: {
3545
+ initializeFormRevisionAttachments: formRevisionAttachmentAdapter.initialize,
3546
+ addFormRevisionAttachment: formRevisionAttachmentAdapter.addOne,
3547
+ addFormRevisionAttachments: formRevisionAttachmentAdapter.addMany,
3548
+ setFormRevisionAttachment: formRevisionAttachmentAdapter.setOne,
3549
+ setFormRevisionAttachments: formRevisionAttachmentAdapter.setMany,
3550
+ updateFormRevisionAttachment: formRevisionAttachmentAdapter.updateOne,
3551
+ updateFormRevisionAttachments: formRevisionAttachmentAdapter.updateMany,
3552
+ deleteFormRevisionAttachment: formRevisionAttachmentAdapter.deleteOne,
3553
+ deleteFormRevisionAttachments: formRevisionAttachmentAdapter.deleteMany
3554
+ }
3555
+ });
3556
+ const {
3557
+ initializeFormRevisionAttachments,
3558
+ addFormRevisionAttachment,
3559
+ addFormRevisionAttachments,
3560
+ setFormRevisionAttachment,
3561
+ setFormRevisionAttachments,
3562
+ updateFormRevisionAttachment,
3563
+ updateFormRevisionAttachments,
3564
+ deleteFormRevisionAttachment,
3565
+ deleteFormRevisionAttachments
3566
+ } = formRevisionAttachmentSlice.actions;
3567
+ const selectUserFormRevisionAttachmentsMapping = (state) => {
3568
+ return state.formRevisionAttachmentReducer.instances;
4145
3569
  };
3570
+ const selectAttachmentsOfFormRevision = restructureCreateSelectorWithArgs(
3571
+ createSelector(
3572
+ [selectUserFormRevisionAttachmentsMapping, (_state, revisionId) => revisionId],
3573
+ (attachments, revisionId) => {
3574
+ return Object.values(attachments).filter((attachment) => attachment.revision === revisionId);
3575
+ }
3576
+ )
3577
+ );
3578
+ const formRevisionAttachmentReducer = formRevisionAttachmentSlice.reducer;
3579
+ const emailDomainAdapter = createModelAdapter((emailDomain) => emailDomain.offline_id);
3580
+ const initialState$8 = emailDomainAdapter.getInitialState({});
4146
3581
  const emailDomainsSlice = createSlice({
4147
3582
  name: "emailDomains",
4148
- initialState: initialState$4,
3583
+ initialState: initialState$8,
4149
3584
  reducers: {
4150
- setEmailDomains: (state, action) => {
4151
- const emailDomains = {};
4152
- action.payload.forEach((emailDomain) => {
4153
- emailDomains[emailDomain.offline_id] = emailDomain;
4154
- });
4155
- state.emailDomains = emailDomains;
4156
- },
4157
- addEmailDomain: (state, action) => {
4158
- state.emailDomains[action.payload.offline_id] = action.payload;
4159
- },
4160
- removeEmailDomain: (state, action) => {
4161
- if (action.payload.offline_id in state.emailDomains) {
4162
- delete state.emailDomains[action.payload.offline_id];
4163
- } else {
4164
- throw new Error(`Tried to remove email domain with ID that doesn't exist: ${action.payload.offline_id}`);
4165
- }
4166
- }
3585
+ initializeEmailDomains: emailDomainAdapter.initialize,
3586
+ addEmailDomain: emailDomainAdapter.addOne,
3587
+ deleteEmailDomain: emailDomainAdapter.deleteOne
4167
3588
  }
4168
3589
  });
4169
- const { setEmailDomains, addEmailDomain, removeEmailDomain } = emailDomainsSlice.actions;
4170
- const selectEmailDomainsAsMapping = (state) => state.emailDomainsReducer.emailDomains;
4171
- const selectSortedEmailDomains = (state) => Object.values(state.emailDomainsReducer.emailDomains).sort(
4172
- (ed1, ed2) => ed1.domain.localeCompare(ed2.domain)
3590
+ const { initializeEmailDomains, addEmailDomain, deleteEmailDomain } = emailDomainsSlice.actions;
3591
+ const selectEmailDomainsAsMapping = (state) => state.emailDomainsReducer.instances;
3592
+ const selectEmailDomains = (state) => Object.values(state.emailDomainsReducer.instances);
3593
+ const selectEmailDomainsOfOrganization = restructureCreateSelectorWithArgs(
3594
+ createSelector(
3595
+ [selectEmailDomains, (_, organizationId) => organizationId],
3596
+ (emailDomains, organizationId) => {
3597
+ return emailDomains.filter((emailDomain) => emailDomain.organization === organizationId);
3598
+ }
3599
+ )
4173
3600
  );
4174
3601
  const emailDomainsReducer = emailDomainsSlice.reducer;
4175
- const initialState$3 = {
4176
- documents: {},
4177
- attachments: {}
3602
+ const initialState$7 = {
3603
+ documents: {}
4178
3604
  };
4179
3605
  const documentSlice = createSlice({
4180
3606
  name: "documents",
4181
- initialState: initialState$3,
3607
+ initialState: initialState$7,
4182
3608
  extraReducers: (builder) => builder.addCase("RESET", (state) => {
4183
- Object.assign(state, initialState$3);
3609
+ Object.assign(state, initialState$7);
4184
3610
  }),
4185
3611
  reducers: {
4186
3612
  setDocuments: (state, action) => {
@@ -4320,34 +3746,10 @@ const documentSlice = createSlice({
4320
3746
  }
4321
3747
  delete state.documents[documentId];
4322
3748
  }
4323
- },
4324
- // Attachments
4325
- setDocumentAttachment: setAttachment,
4326
- setDocumentAttachments: setAttachments,
4327
- addDocumentAttachment: addAttachment,
4328
- addDocumentAttachments: addAttachments,
4329
- updateDocumentAttachment: updateAttachment,
4330
- updateDocumentAttachments: updateAttachments,
4331
- removeDocumentAttachment: removeAttachment,
4332
- removeDocumentAttachments: removeAttachments
3749
+ }
4333
3750
  }
4334
3751
  });
4335
- const {
4336
- setDocuments,
4337
- addDocuments,
4338
- updateDocuments,
4339
- moveDocument,
4340
- removeDocuments,
4341
- // Attachments
4342
- setDocumentAttachment,
4343
- setDocumentAttachments,
4344
- addDocumentAttachment,
4345
- addDocumentAttachments,
4346
- updateDocumentAttachment,
4347
- updateDocumentAttachments,
4348
- removeDocumentAttachment,
4349
- removeDocumentAttachments
4350
- } = documentSlice.actions;
3752
+ const { setDocuments, addDocuments, updateDocuments, moveDocument, removeDocuments } = documentSlice.actions;
4351
3753
  const selectDocumentsMapping = (state) => state.documentsReducer.documents;
4352
3754
  const selectDocuments = createSelector(
4353
3755
  [selectDocumentsMapping],
@@ -4377,13 +3779,43 @@ const selectRootDocuments = createSelector(
4377
3779
  [selectDocuments],
4378
3780
  (documents) => documents.filter((document2) => !document2.parent_document)
4379
3781
  );
4380
- const selectDocumentAttachmentMapping = (state) => state.documentsReducer.attachments;
3782
+ const documentsReducer = documentSlice.reducer;
3783
+ const documentAttachmentAdapter = createModelAdapter((attachment) => attachment.offline_id);
3784
+ const initialState$6 = documentAttachmentAdapter.getInitialState({});
3785
+ const documentAttachmentSlice = createSlice({
3786
+ name: "documentAttachments",
3787
+ initialState: initialState$6,
3788
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$6)),
3789
+ reducers: {
3790
+ initializeDocumentAttachments: documentAttachmentAdapter.initialize,
3791
+ addDocumentAttachment: documentAttachmentAdapter.addOne,
3792
+ addDocumentAttachments: documentAttachmentAdapter.addMany,
3793
+ setDocumentAttachment: documentAttachmentAdapter.setOne,
3794
+ setDocumentAttachments: documentAttachmentAdapter.setMany,
3795
+ updateDocumentAttachment: documentAttachmentAdapter.updateOne,
3796
+ updateDocumentAttachments: documentAttachmentAdapter.updateMany,
3797
+ deleteDocumentAttachment: documentAttachmentAdapter.deleteOne,
3798
+ deleteDocumentAttachments: documentAttachmentAdapter.deleteMany
3799
+ }
3800
+ });
3801
+ const {
3802
+ initializeDocumentAttachments,
3803
+ addDocumentAttachment,
3804
+ addDocumentAttachments,
3805
+ setDocumentAttachment,
3806
+ setDocumentAttachments,
3807
+ updateDocumentAttachment,
3808
+ updateDocumentAttachments,
3809
+ deleteDocumentAttachment,
3810
+ deleteDocumentAttachments
3811
+ } = documentAttachmentSlice.actions;
3812
+ const selectDocumentAttachmentMapping = (state) => state.documentAttachmentReducer.instances;
4381
3813
  const selectAllDocumentAttachments = createSelector(
4382
3814
  [selectDocumentAttachmentMapping],
4383
3815
  (mapping) => Object.values(mapping)
4384
3816
  );
4385
3817
  const selectDocumentAttachment = (attachmentId) => (state) => {
4386
- return state.documentsReducer.attachments[attachmentId];
3818
+ return state.documentAttachmentReducer.instances[attachmentId];
4387
3819
  };
4388
3820
  const selectAttachmentsOfDocument = restructureCreateSelectorWithArgs(
4389
3821
  createSelector(
@@ -4410,48 +3842,28 @@ const selectAttachmentsOfDocumentByType = restructureCreateSelectorWithArgs(
4410
3842
  }
4411
3843
  )
4412
3844
  );
4413
- const documentsReducer = documentSlice.reducer;
4414
- const initialState$2 = {
4415
- teams: {}
4416
- };
3845
+ const documentAttachmentReducer = documentAttachmentSlice.reducer;
3846
+ const teamAdapter = createModelAdapter((team) => team.offline_id);
3847
+ const initialState$5 = teamAdapter.getInitialState({});
4417
3848
  const teamSlice = createSlice({
4418
3849
  name: "teams",
4419
- initialState: initialState$2,
4420
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$2)),
3850
+ initialState: initialState$5,
3851
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$5)),
4421
3852
  reducers: {
4422
- setTeam: (state, action) => {
4423
- state.teams[action.payload.offline_id] = action.payload;
4424
- },
4425
- setTeams: (state, action) => {
4426
- state.teams = {};
4427
- for (const team of action.payload) {
4428
- state.teams[team.offline_id] = team;
4429
- }
4430
- },
4431
- addTeam: (state, action) => {
4432
- if (state.teams[action.payload.offline_id]) {
4433
- throw new Error(`Team with offline_id ${action.payload.offline_id} already exists`);
4434
- }
4435
- state.teams[action.payload.offline_id] = action.payload;
4436
- },
4437
- updateTeam: (state, action) => {
4438
- if (!state.teams[action.payload.offline_id]) {
4439
- throw new Error(`Team with offline_id ${action.payload.offline_id} does not exist`);
4440
- }
4441
- state.teams[action.payload.offline_id] = action.payload;
4442
- },
4443
- deleteTeam: (state, action) => {
4444
- delete state.teams[action.payload];
4445
- }
3853
+ setTeam: teamAdapter.setOne,
3854
+ setTeams: teamAdapter.initialize,
3855
+ addTeam: teamAdapter.addOne,
3856
+ updateTeam: teamAdapter.updateOne,
3857
+ deleteTeam: teamAdapter.deleteOne
4446
3858
  }
4447
3859
  });
4448
3860
  const { setTeam, setTeams, addTeam, updateTeam, deleteTeam } = teamSlice.actions;
4449
- const selectTeamsMapping = (state) => state.teamReducer.teams;
3861
+ const selectTeamsMapping = (state) => state.teamReducer.instances;
4450
3862
  const selectTeams = createSelector([selectTeamsMapping], (teams) => {
4451
3863
  return Object.values(teams);
4452
3864
  });
4453
3865
  const selectTeam = (teamId) => (state) => {
4454
- return state.teamReducer.teams[teamId];
3866
+ return state.teamReducer.instances[teamId];
4455
3867
  };
4456
3868
  const selectTeamsOfOrganization = restructureCreateSelectorWithArgs(
4457
3869
  createSelector(
@@ -4467,43 +3879,23 @@ const selectTeamsOfUser = restructureCreateSelectorWithArgs(
4467
3879
  })
4468
3880
  );
4469
3881
  const teamReducer = teamSlice.reducer;
4470
- const initialState$1 = {
4471
- conversations: {}
4472
- };
3882
+ const agentUserConversationAdapter = createModelAdapter(
3883
+ (conversation) => conversation.offline_id
3884
+ );
3885
+ const initialState$4 = agentUserConversationAdapter.getInitialState({});
4473
3886
  const agentsSlice = createSlice({
4474
3887
  name: "agents",
4475
- initialState: initialState$1,
4476
- extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$1)),
3888
+ initialState: initialState$4,
3889
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$4)),
4477
3890
  reducers: {
4478
- setConversations: (state, action) => {
4479
- state.conversations = {};
4480
- for (const conversation of action.payload) {
4481
- state.conversations[conversation.offline_id] = conversation;
4482
- }
4483
- },
4484
- addConversation: (state, action) => {
4485
- if (action.payload.offline_id in state.conversations) {
4486
- throw new Error("Conversation already exists in history");
4487
- }
4488
- state.conversations[action.payload.offline_id] = action.payload;
4489
- },
4490
- setConversation: (state, action) => {
4491
- if (!(action.payload.offline_id in state.conversations)) {
4492
- throw new Error("Conversation does not exist in history");
4493
- }
4494
- state.conversations[action.payload.offline_id] = action.payload;
4495
- },
4496
- updateConversation: (state, action) => {
4497
- const existing = state.conversations[action.payload.offline_id];
4498
- if (!existing) {
4499
- throw new Error("Conversation does not exist in history");
4500
- }
4501
- state.conversations[action.payload.offline_id] = { ...existing, ...action.payload };
4502
- }
3891
+ initializeConversations: agentUserConversationAdapter.initialize,
3892
+ addConversation: agentUserConversationAdapter.addOne,
3893
+ setConversation: agentUserConversationAdapter.setOne,
3894
+ updateConversation: agentUserConversationAdapter.updateOne
4503
3895
  }
4504
3896
  });
4505
- const { setConversations, addConversation, setConversation, updateConversation } = agentsSlice.actions;
4506
- const selectConversationMapping = (state) => state.agentsReducer.conversations;
3897
+ const { initializeConversations, addConversation, setConversation, updateConversation } = agentsSlice.actions;
3898
+ const selectConversationMapping = (state) => state.agentsReducer.instances;
4507
3899
  const selectConversations = createSelector(
4508
3900
  [selectConversationMapping],
4509
3901
  (conversationMapping) => Object.values(conversationMapping)
@@ -4515,6 +3907,132 @@ const selectConversation = restructureCreateSelectorWithArgs(
4515
3907
  )
4516
3908
  );
4517
3909
  const agentsReducer = agentsSlice.reducer;
3910
+ const issueCommentAdapter = createModelAdapter((comment) => comment.offline_id);
3911
+ const initialState$3 = issueCommentAdapter.getInitialState({});
3912
+ const issueCommentSlice = createSlice({
3913
+ name: "issueComments",
3914
+ initialState: initialState$3,
3915
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$3)),
3916
+ reducers: {
3917
+ addIssueComment: issueCommentAdapter.addOne,
3918
+ addIssueComments: issueCommentAdapter.addMany,
3919
+ setIssueComment: issueCommentAdapter.setOne,
3920
+ setIssueComments: issueCommentAdapter.setMany,
3921
+ deleteIssueComment: issueCommentAdapter.deleteOne,
3922
+ deleteIssueComments: issueCommentAdapter.deleteMany
3923
+ }
3924
+ });
3925
+ const {
3926
+ setIssueComments,
3927
+ setIssueComment,
3928
+ addIssueComment,
3929
+ addIssueComments,
3930
+ deleteIssueComment,
3931
+ deleteIssueComments
3932
+ } = issueCommentSlice.actions;
3933
+ const selectIssueCommentMapping = (state) => state.issueCommentReducer.instances;
3934
+ const selectCommentsOfIssue = restructureCreateSelectorWithArgs(
3935
+ createSelector(
3936
+ [selectIssueCommentMapping, (_state, issueId) => issueId],
3937
+ (commentMapping, issueId) => {
3938
+ return Object.values(commentMapping).filter((comment) => comment.issue === issueId);
3939
+ }
3940
+ )
3941
+ );
3942
+ const issueCommentReducer = issueCommentSlice.reducer;
3943
+ const issueUpdateAdapter = createModelAdapter((issueUpdate) => issueUpdate.offline_id);
3944
+ const initialState$2 = issueUpdateAdapter.getInitialState({});
3945
+ const issueUpdateSlice = createSlice({
3946
+ name: "issueUpdates",
3947
+ initialState: initialState$2,
3948
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$2)),
3949
+ reducers: {
3950
+ initializeIssueUpdates: issueUpdateAdapter.setMany,
3951
+ setIssueUpdate: issueUpdateAdapter.setOne,
3952
+ addIssueUpdate: issueUpdateAdapter.addOne,
3953
+ addIssueUpdates: issueUpdateAdapter.addMany,
3954
+ deleteIssueUpdate: issueUpdateAdapter.deleteOne,
3955
+ deleteIssueUpdates: issueUpdateAdapter.deleteMany
3956
+ }
3957
+ });
3958
+ const {
3959
+ initializeIssueUpdates,
3960
+ setIssueUpdate,
3961
+ addIssueUpdate,
3962
+ addIssueUpdates,
3963
+ deleteIssueUpdate,
3964
+ deleteIssueUpdates
3965
+ } = issueUpdateSlice.actions;
3966
+ const selectIssueUpdateMapping = (state) => state.issueUpdateReducer.instances;
3967
+ const selectIssueUpdatesOfIssue = restructureCreateSelectorWithArgs(
3968
+ createSelector([selectIssueUpdateMapping, (_state, issueId) => issueId], (updates, issueId) => {
3969
+ return Object.values(updates).filter((update) => update.issue === issueId);
3970
+ })
3971
+ );
3972
+ const issueUpdateReducer = issueUpdateSlice.reducer;
3973
+ const issueAttachmentAdapter = createModelAdapter((attachment) => attachment.offline_id);
3974
+ const initialState$1 = issueAttachmentAdapter.getInitialState({});
3975
+ const issueAttachmentSlice = createSlice({
3976
+ name: "issueAttachments",
3977
+ initialState: initialState$1,
3978
+ extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$1)),
3979
+ reducers: {
3980
+ initializeIssueAttachments: issueAttachmentAdapter.initialize,
3981
+ addIssueAttachment: issueAttachmentAdapter.addOne,
3982
+ addIssueAttachments: issueAttachmentAdapter.addMany,
3983
+ setIssueAttachment: issueAttachmentAdapter.setOne,
3984
+ setIssueAttachments: issueAttachmentAdapter.setMany,
3985
+ updateIssueAttachment: issueAttachmentAdapter.updateOne,
3986
+ updateIssueAttachments: issueAttachmentAdapter.updateMany,
3987
+ deleteIssueAttachment: issueAttachmentAdapter.deleteOne,
3988
+ deleteIssueAttachments: issueAttachmentAdapter.deleteMany
3989
+ }
3990
+ });
3991
+ const {
3992
+ initializeIssueAttachments,
3993
+ addIssueAttachment,
3994
+ addIssueAttachments,
3995
+ setIssueAttachment,
3996
+ setIssueAttachments,
3997
+ updateIssueAttachment,
3998
+ updateIssueAttachments,
3999
+ deleteIssueAttachment,
4000
+ deleteIssueAttachments
4001
+ } = issueAttachmentSlice.actions;
4002
+ const selectIssueAttachmentMapping = (state) => state.issueAttachmentReducer.instances;
4003
+ const selectIssueAttachments = createSelector(
4004
+ [selectIssueAttachmentMapping],
4005
+ (mapping) => Object.values(mapping)
4006
+ );
4007
+ const selectAttachmentsOfIssue = restructureCreateSelectorWithArgs(
4008
+ createSelector(
4009
+ [selectIssueAttachments, (_state, issueId) => issueId],
4010
+ (attachments, issueId) => {
4011
+ return attachments.filter(({ issue }) => issueId === issue);
4012
+ }
4013
+ )
4014
+ );
4015
+ const selectIssueAttachment = (attachmentId) => (root) => {
4016
+ return root.issueAttachmentReducer.instances[attachmentId];
4017
+ };
4018
+ const selectAttachmentsOfIssueByType = restructureCreateSelectorWithArgs(
4019
+ createSelector(
4020
+ [selectIssueAttachments, (_state, issueId) => issueId],
4021
+ (attachments, issueId) => {
4022
+ const attachmentsOfIssue = attachments.filter(({ issue }) => issue === issueId);
4023
+ const fileAttachments = attachmentsOfIssue.filter(
4024
+ // this null check here is necessary, there are cases where file_type is null or undefined
4025
+ ({ file_type }) => !file_type || !file_type.startsWith("image/")
4026
+ );
4027
+ const imageAttachments = attachmentsOfIssue.filter(
4028
+ // this null check here is necessary, there are cases where file_type is null or undefined
4029
+ ({ file_type }) => file_type && file_type.startsWith("image/")
4030
+ );
4031
+ return { fileAttachments, imageAttachments };
4032
+ }
4033
+ )
4034
+ );
4035
+ const issueAttachmentReducer = issueAttachmentSlice.reducer;
4518
4036
  const initialState = {
4519
4037
  version: 0
4520
4038
  };
@@ -4543,15 +4061,19 @@ const overmapReducers = {
4543
4061
  authReducer,
4544
4062
  categoryReducer,
4545
4063
  assetReducer,
4064
+ assetAttachmentReducer,
4546
4065
  assetStageCompletionReducer,
4547
4066
  assetStageReducer,
4548
4067
  assetTypeReducer,
4068
+ assetTypeAttachmentReducer,
4549
4069
  issueReducer,
4070
+ issueAttachmentReducer,
4550
4071
  issueTypeReducer,
4551
4072
  mapReducer,
4552
4073
  organizationReducer,
4553
4074
  outboxReducer,
4554
4075
  projectReducer,
4076
+ projectAttachmentReducer,
4555
4077
  projectAccessReducer,
4556
4078
  organizationAccessReducer,
4557
4079
  projectFileReducer,
@@ -4559,20 +4081,25 @@ const overmapReducers = {
4559
4081
  settingReducer,
4560
4082
  formReducer,
4561
4083
  formRevisionReducer,
4084
+ formRevisionAttachmentReducer,
4085
+ formSubmissionAttachmentReducer,
4562
4086
  formSubmissionReducer,
4563
4087
  userReducer,
4564
4088
  workspaceReducer,
4565
4089
  emailDomainsReducer,
4566
4090
  licenseReducer,
4567
4091
  documentsReducer,
4092
+ documentAttachmentReducer,
4568
4093
  teamReducer,
4569
- agentsReducer
4094
+ agentsReducer,
4095
+ issueCommentReducer,
4096
+ issueUpdateReducer
4570
4097
  };
4571
4098
  const overmapReducer = combineReducers(overmapReducers);
4572
4099
  const resetStore = "RESET";
4573
4100
  function handleWorkspaceRemoval(draft, action) {
4574
4101
  const workspaceId = action.payload;
4575
- const issuesVisibleInWorkspace = Object.values(draft.issueReducer.issues).filter(
4102
+ const issuesVisibleInWorkspace = Object.values(draft.issueReducer.instances).filter(
4576
4103
  (issue) => issue.visible_in_workspaces.includes(workspaceId)
4577
4104
  );
4578
4105
  const mainWorkspace = selectMainWorkspace(draft);
@@ -5298,24 +4825,14 @@ class CategoryService extends BaseApiService {
5298
4825
  });
5299
4826
  return [categoryWithWorkspace, promise];
5300
4827
  }
5301
- fetchAll(projectId) {
5302
- const promise = this.client.enqueueRequest({
5303
- description: "Get categories",
5304
- method: HttpMethod.GET,
5305
- url: `/projects/${projectId}/categories/`,
5306
- blocks: [],
5307
- blockers: []
5308
- });
5309
- const offlineCategories = Object.values(this.client.store.getState().categoryReducer.categories);
5310
- return [offlineCategories, promise];
5311
- }
5312
4828
  update(category, workspaceId) {
5313
- const existingCategory = this.client.store.getState().categoryReducer.categories[category.offline_id];
4829
+ const state = this.client.store.getState();
4830
+ const existingCategory = selectCategoryById(category.offline_id)(state);
5314
4831
  if (!existingCategory) {
5315
4832
  throw new Error(`Expected an existing category with offline_id ${category.offline_id}`);
5316
4833
  }
5317
- this.client.store.dispatch(patchCategory(category));
5318
4834
  const optimisticCategory = { ...existingCategory, ...category };
4835
+ this.client.store.dispatch(updateCategory(optimisticCategory));
5319
4836
  const promise = this.client.enqueueRequest({
5320
4837
  description: "Edit Category",
5321
4838
  method: HttpMethod.PATCH,
@@ -5330,7 +4847,7 @@ class CategoryService extends BaseApiService {
5330
4847
  return [optimisticCategory, promise];
5331
4848
  }
5332
4849
  remove(category, workspaceId) {
5333
- this.client.store.dispatch(removeCategory(category.offline_id));
4850
+ this.client.store.dispatch(deleteCategory(category.offline_id));
5334
4851
  return this.client.enqueueRequest({
5335
4852
  description: "Delete Category",
5336
4853
  method: HttpMethod.DELETE,
@@ -5343,33 +4860,20 @@ class CategoryService extends BaseApiService {
5343
4860
  blocks: []
5344
4861
  });
5345
4862
  }
5346
- /**
5347
- * Overwrites the store with whatever categories are on the server.
5348
- * @returns A promise that resolves to an empty result.
5349
- * @throws An APIError if the request fails.
5350
- * @throws An Error if there is no active project, or for any other unexpected error.
5351
- * @example
5352
- * ```typescript
5353
- * try {
5354
- * await sdk.category.refreshStore()
5355
- * } catch (e) {
5356
- * if (e instanceof APIError) {
5357
- * // handle error
5358
- * return
5359
- * }
5360
- * throw e
5361
- * }
5362
- * ```
5363
- */
5364
4863
  async refreshStore() {
5365
4864
  const { store } = this.client;
5366
4865
  const projectId = store.getState().projectReducer.activeProjectId;
5367
4866
  if (!projectId) {
5368
4867
  throw new Error("No active project");
5369
4868
  }
5370
- const [_offlineCategories, promise] = this.fetchAll(projectId);
5371
- const result = await promise;
5372
- store.dispatch(setCategories(result));
4869
+ const result = await this.client.enqueueRequest({
4870
+ description: "Get categories",
4871
+ method: HttpMethod.GET,
4872
+ url: `/projects/${projectId}/categories/`,
4873
+ blocks: [],
4874
+ blockers: []
4875
+ });
4876
+ store.dispatch(initializeCategories(result));
5373
4877
  }
5374
4878
  }
5375
4879
  function chunkArray(arr, chunkSize) {
@@ -5420,10 +4924,10 @@ class AssetService extends BaseApiService {
5420
4924
  if (!assetToBeDeleted)
5421
4925
  throw new Error(`No asset with id ${assetId} found in the store`);
5422
4926
  const attachmentsOfAssets = selectAttachmentsOfAsset(assetId)(store.getState());
5423
- store.dispatch(removeAsset(assetId));
4927
+ store.dispatch(deleteAsset(assetId));
5424
4928
  if (attachmentsOfAssets.length > 0) {
5425
4929
  const attachmentsOfAssetIds = attachmentsOfAssets.map(({ offline_id }) => offline_id);
5426
- store.dispatch(removeAssetAttachments(attachmentsOfAssetIds));
4930
+ store.dispatch(deleteAssetAttachments(attachmentsOfAssetIds));
5427
4931
  }
5428
4932
  return this.client.enqueueRequest({
5429
4933
  description: "Delete asset",
@@ -5440,10 +4944,10 @@ class AssetService extends BaseApiService {
5440
4944
  async deleteAllAssetsOfAssetType(assetTypeId) {
5441
4945
  const { store } = this.client;
5442
4946
  const state = store.getState();
5443
- const allAssetsOfAssetType = selectAssetsOfAssetType(assetTypeId)(state);
5444
- const allAssetsOfAssetTypeIds = (allAssetsOfAssetType || []).map((c) => c.offline_id);
4947
+ const allAssetsOfAssetType = selectAssetsOfAssetType(assetTypeId)(state) ?? [];
4948
+ const allAssetsOfAssetTypeIds = allAssetsOfAssetType.map((c) => c.offline_id);
5445
4949
  const affectedOfflineIds = [assetTypeId, ...allAssetsOfAssetTypeIds];
5446
- store.dispatch(removeAllAssetsOfType(assetTypeId));
4950
+ store.dispatch(deleteAssets(allAssetsOfAssetTypeIds));
5447
4951
  return this.client.enqueueRequest({
5448
4952
  description: "Delete all assets of asset type",
5449
4953
  method: HttpMethod.DELETE,
@@ -5451,9 +4955,7 @@ class AssetService extends BaseApiService {
5451
4955
  blockers: affectedOfflineIds,
5452
4956
  blocks: affectedOfflineIds
5453
4957
  }).catch((err) => {
5454
- if (allAssetsOfAssetType) {
5455
- store.dispatch(addAssetsInBatches(allAssetsOfAssetType));
5456
- }
4958
+ store.dispatch(addAssets(allAssetsOfAssetType));
5457
4959
  throw err;
5458
4960
  });
5459
4961
  }
@@ -5503,7 +5005,7 @@ class AssetService extends BaseApiService {
5503
5005
  }
5504
5006
  void Promise.all(batchPromises).then((result) => {
5505
5007
  const allCreatedAssets = result.flat();
5506
- store.dispatch(addAssetsInBatches(allCreatedAssets));
5008
+ store.dispatch(addAssets(allCreatedAssets));
5507
5009
  });
5508
5010
  return batchPromises;
5509
5011
  }
@@ -5516,14 +5018,14 @@ class AssetService extends BaseApiService {
5516
5018
  blockers: [],
5517
5019
  blocks: []
5518
5020
  });
5519
- store.dispatch(setAssets(result));
5021
+ store.dispatch(initializeAssets(result));
5520
5022
  }
5521
5023
  }
5522
5024
  class AssetStageCompletionService extends BaseApiService {
5523
5025
  add(assetId, stageId) {
5524
5026
  var _a2;
5525
5027
  const { store } = this.client;
5526
- const assetTypeId = (_a2 = store.getState().assetReducer.assets[assetId]) == null ? void 0 : _a2.asset_type;
5028
+ const assetTypeId = (_a2 = selectAsset(assetId)(store.getState())) == null ? void 0 : _a2.asset_type;
5527
5029
  if (!assetTypeId) {
5528
5030
  throw new Error(`Asset with offline_id ${assetId} not found`);
5529
5031
  }
@@ -5677,7 +5179,11 @@ class AssetStageService extends BaseApiService {
5677
5179
  }
5678
5180
  async linkForm(stageId, formId2) {
5679
5181
  const { store } = this.client;
5680
- store.dispatch(linkStageToForm({ stageId, formId: formId2 }));
5182
+ const stage = store.getState().assetStageReducer.instances[stageId];
5183
+ if (!stage) {
5184
+ throw new Error(`No asset stage with id ${stageId} found in the store`);
5185
+ }
5186
+ store.dispatch(updateStage({ ...stage, user_form: formId2 }));
5681
5187
  try {
5682
5188
  await this.client.enqueueRequest({
5683
5189
  description: "Link asset stage to form",
@@ -5688,13 +5194,17 @@ class AssetStageService extends BaseApiService {
5688
5194
  blocks: [stageId]
5689
5195
  });
5690
5196
  } catch (e) {
5691
- store.dispatch(unlinkStageToForm({ stageId }));
5197
+ store.dispatch(setStage(stage));
5692
5198
  throw e;
5693
5199
  }
5694
5200
  }
5695
5201
  async unlinkForm(stageId, formId2) {
5696
5202
  const { store } = this.client;
5697
- store.dispatch(unlinkStageToForm({ stageId }));
5203
+ const stage = store.getState().assetStageReducer.instances[stageId];
5204
+ if (!stage) {
5205
+ throw new Error(`No asset stage with id ${stageId} found in the store`);
5206
+ }
5207
+ store.dispatch(updateStage({ ...stage, user_form: void 0 }));
5698
5208
  try {
5699
5209
  await this.client.enqueueRequest({
5700
5210
  description: "Unlink asset stage from form",
@@ -5704,7 +5214,7 @@ class AssetStageService extends BaseApiService {
5704
5214
  blocks: [stageId]
5705
5215
  });
5706
5216
  } catch (e) {
5707
- store.dispatch(linkStageToForm({ stageId, formId: formId2 }));
5217
+ store.dispatch(setStage(stage));
5708
5218
  throw e;
5709
5219
  }
5710
5220
  }
@@ -5717,7 +5227,7 @@ class AssetStageService extends BaseApiService {
5717
5227
  blockers: [],
5718
5228
  blocks: []
5719
5229
  });
5720
- store.dispatch(addStages(result));
5230
+ store.dispatch(initializeStages(result));
5721
5231
  }
5722
5232
  }
5723
5233
  const AttachmentModelMeta = {
@@ -5755,22 +5265,22 @@ const AttachmentModelMeta = {
5755
5265
  class BaseAttachmentService extends BaseApiService {
5756
5266
  getNumberOfAttachmentsWithSha1(sha1) {
5757
5267
  const {
5758
- issueReducer: issueReducer2,
5759
- assetReducer: assetReducer2,
5760
- assetTypeReducer: assetTypeReducer2,
5761
- documentsReducer: documentsReducer2,
5762
- projectReducer: projectReducer2,
5763
- formSubmissionReducer: formSubmissionReducer2,
5764
- formRevisionReducer: formRevisionReducer2
5268
+ issueAttachmentReducer: issueAttachmentReducer2,
5269
+ assetAttachmentReducer: assetAttachmentReducer2,
5270
+ assetTypeAttachmentReducer: assetTypeAttachmentReducer2,
5271
+ documentAttachmentReducer: documentAttachmentReducer2,
5272
+ projectAttachmentReducer: projectAttachmentReducer2,
5273
+ formSubmissionAttachmentReducer: formSubmissionAttachmentReducer2,
5274
+ formRevisionAttachmentReducer: formRevisionAttachmentReducer2
5765
5275
  } = this.client.store.getState();
5766
5276
  const objectsWithSha1 = [].concat(
5767
- Object.values(issueReducer2.attachments),
5768
- Object.values(assetReducer2.attachments),
5769
- Object.values(assetTypeReducer2.attachments),
5770
- Object.values(documentsReducer2.attachments),
5771
- Object.values(projectReducer2.attachments),
5772
- Object.values(formRevisionReducer2.attachments),
5773
- Object.values(formSubmissionReducer2.attachments)
5277
+ Object.values(issueAttachmentReducer2.instances),
5278
+ Object.values(assetAttachmentReducer2.instances),
5279
+ Object.values(assetTypeAttachmentReducer2.instances),
5280
+ Object.values(documentAttachmentReducer2.instances),
5281
+ Object.values(projectAttachmentReducer2.instances),
5282
+ Object.values(formRevisionAttachmentReducer2.instances),
5283
+ Object.values(formSubmissionAttachmentReducer2.instances)
5774
5284
  );
5775
5285
  return objectsWithSha1.filter((object) => object.file_sha1 === sha1).length;
5776
5286
  }
@@ -5790,22 +5300,7 @@ class BaseAttachmentService extends BaseApiService {
5790
5300
  });
5791
5301
  }
5792
5302
  }
5793
- // Note that currently the fetching of attachments for all models dependds on the active projectId. This may change in the future. And
5794
- // so for some attachment model services, this method will have to be overridden.
5795
- async getAttachments(actions) {
5796
- const { store } = this.client;
5797
- const activeProjectId = store.getState().projectReducer.activeProjectId;
5798
- const meta = AttachmentModelMeta[this.attachmentModel];
5799
- const result = await this.client.enqueueRequest({
5800
- description: `Get ${meta.name} attachments`,
5801
- method: HttpMethod.GET,
5802
- url: `/projects/${activeProjectId}${meta.fetchUrlPostfix}/`,
5803
- blocks: [],
5804
- blockers: []
5805
- });
5806
- store.dispatch(actions.setAttachments(result));
5807
- }
5808
- async attachFiles(files, modelId, buildOfflineAttachment, actions) {
5303
+ async attachFiles(files, modelId, buildOfflineAttachment) {
5809
5304
  const { store } = this.client;
5810
5305
  const currentUser = store.getState().userReducer.currentUser;
5811
5306
  const submittedAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -5839,7 +5334,7 @@ class BaseAttachmentService extends BaseApiService {
5839
5334
  description: offlineAttachment.description
5840
5335
  });
5841
5336
  }
5842
- store.dispatch(actions.addAttachments(offlineAttachments));
5337
+ store.dispatch(this.addAttachments(offlineAttachments));
5843
5338
  const meta = AttachmentModelMeta[this.attachmentModel];
5844
5339
  const promise = this.client.enqueueRequest({
5845
5340
  description: `Attach files to ${meta.name}`,
@@ -5854,22 +5349,22 @@ class BaseAttachmentService extends BaseApiService {
5854
5349
  blockers: offlineAttachments.map((attachment) => attachment.file_sha1)
5855
5350
  });
5856
5351
  promise.then(({ attachments, presigned_urls }) => {
5857
- store.dispatch(actions.updateAttachments(attachments));
5352
+ store.dispatch(this.updateAttachments(attachments));
5858
5353
  this.processPresignedUrls(presigned_urls);
5859
5354
  }).catch(() => {
5860
- store.dispatch(actions.removeAttachments(offlineAttachments.map((attachment) => attachment.offline_id)));
5355
+ store.dispatch(this.removeAttachments(offlineAttachments.map((attachment) => attachment.offline_id)));
5861
5356
  });
5862
5357
  return [offlineAttachments, promise.then(({ attachments }) => attachments)];
5863
5358
  }
5864
- async deleteAttachment(attachmendId, actions, selectors) {
5359
+ async deleteAttachment(attachmendId) {
5865
5360
  const { store } = this.client;
5866
- const attachment = selectors.selectAttachment(attachmendId)(store.getState());
5361
+ const attachment = this.selectAttachment(attachmendId)(store.getState());
5867
5362
  if (!attachment) {
5868
5363
  throw new Error(
5869
5364
  `Attempting to delete attachment with offline_id ${attachmendId} that does not exist in the store`
5870
5365
  );
5871
5366
  }
5872
- store.dispatch(actions.removeAttachment(attachment.offline_id));
5367
+ store.dispatch(this.removeAttachment(attachment.offline_id));
5873
5368
  const meta = AttachmentModelMeta[this.attachmentModel];
5874
5369
  const promise = this.client.enqueueRequest({
5875
5370
  description: "Delete attachment",
@@ -5883,15 +5378,37 @@ class BaseAttachmentService extends BaseApiService {
5883
5378
  void this.client.files.removeCache(attachment.file_sha1);
5884
5379
  }
5885
5380
  }).catch(() => {
5886
- store.dispatch(actions.setAttachment(attachment));
5381
+ store.dispatch(this.setAttachment(attachment));
5887
5382
  });
5888
5383
  return promise;
5889
5384
  }
5385
+ // Note that currently the fetching of attachments for all models dependds on the active projectId. This may change in the future. And
5386
+ // so for some attachment model services, this method will have to be overridden.
5387
+ async refreshStore() {
5388
+ const { store } = this.client;
5389
+ const activeProjectId = store.getState().projectReducer.activeProjectId;
5390
+ const meta = AttachmentModelMeta[this.attachmentModel];
5391
+ const result = await this.client.enqueueRequest({
5392
+ description: `Get ${meta.name} attachments`,
5393
+ method: HttpMethod.GET,
5394
+ url: `/projects/${activeProjectId}${meta.fetchUrlPostfix}/`,
5395
+ blocks: [],
5396
+ blockers: []
5397
+ });
5398
+ store.dispatch(this.initializeAttachments(result));
5399
+ }
5890
5400
  }
5891
5401
  class AssetAttachmentService extends BaseAttachmentService {
5892
5402
  constructor() {
5893
5403
  super(...arguments);
5894
5404
  __publicField(this, "attachmentModel", AttachmentModel.Asset);
5405
+ __publicField(this, "initializeAttachments", initializeAssetAttachments);
5406
+ __publicField(this, "addAttachments", addAssetAttachments);
5407
+ __publicField(this, "updateAttachments", updateAssetAttachments);
5408
+ __publicField(this, "removeAttachments", deleteAssetAttachments);
5409
+ __publicField(this, "removeAttachment", deleteAssetAttachment);
5410
+ __publicField(this, "setAttachment", setAssetAttachment);
5411
+ __publicField(this, "selectAttachment", selectAssetAttachment);
5895
5412
  }
5896
5413
  buildOfflineAttachment(data) {
5897
5414
  return offline({
@@ -5906,28 +5423,10 @@ class AssetAttachmentService extends BaseAttachmentService {
5906
5423
  });
5907
5424
  }
5908
5425
  async attachFilesToAsset(files, assetId) {
5909
- return this.attachFiles(files, assetId, this.buildOfflineAttachment.bind(this), {
5910
- addAttachments: addAssetAttachments,
5911
- updateAttachments: updateAssetAttachments,
5912
- removeAttachments: removeAssetAttachments
5913
- });
5914
- }
5915
- deleteAssetAttachment(attachmentId) {
5916
- return this.deleteAttachment(
5917
- attachmentId,
5918
- {
5919
- setAttachment: setAssetAttachment,
5920
- removeAttachment: removeAssetAttachment
5921
- },
5922
- {
5923
- selectAttachment: selectAssetAttachment
5924
- }
5925
- );
5426
+ return this.attachFiles(files, assetId, this.buildOfflineAttachment.bind(this));
5926
5427
  }
5927
- async refreshStore() {
5928
- return this.getAttachments({
5929
- setAttachments: setAssetAttachments
5930
- });
5428
+ async deleteAssetAttachment(attachmentId) {
5429
+ return this.deleteAttachment(attachmentId);
5931
5430
  }
5932
5431
  }
5933
5432
  class AssetTypeService extends BaseApiService {
@@ -5973,7 +5472,7 @@ class AssetTypeService extends BaseApiService {
5973
5472
  }
5974
5473
  if (attachmentsOfAssetType.length > 0) {
5975
5474
  const attachmentsOfAssetTypeIds = attachmentsOfAssetType.map(({ offline_id }) => offline_id);
5976
- store.dispatch(removeAssetTypeAttachments(attachmentsOfAssetTypeIds));
5475
+ store.dispatch(deleteAssetTypeAttachments(attachmentsOfAssetTypeIds));
5977
5476
  }
5978
5477
  return this.client.enqueueRequest({
5979
5478
  description: "Delete asset type",
@@ -5997,13 +5496,20 @@ class AssetTypeService extends BaseApiService {
5997
5496
  blockers: [],
5998
5497
  blocks: []
5999
5498
  });
6000
- store.dispatch(setAssetTypes(result));
5499
+ store.dispatch(initializeAssetTypes(result));
6001
5500
  }
6002
5501
  }
6003
5502
  class AssetTypeAttachmentService extends BaseAttachmentService {
6004
5503
  constructor() {
6005
5504
  super(...arguments);
6006
5505
  __publicField(this, "attachmentModel", AttachmentModel.AssetType);
5506
+ __publicField(this, "initializeAttachments", initializeAssetTypeAttachments);
5507
+ __publicField(this, "addAttachments", addAssetTypeAttachments);
5508
+ __publicField(this, "updateAttachments", updateAssetTypeAttachments);
5509
+ __publicField(this, "removeAttachments", deleteAssetTypeAttachments);
5510
+ __publicField(this, "removeAttachment", deleteAssetTypeAttachment);
5511
+ __publicField(this, "setAttachment", setAssetTypeAttachment);
5512
+ __publicField(this, "selectAttachment", selectAssetTypeAttachment);
6007
5513
  }
6008
5514
  buildOfflineAttachment(data) {
6009
5515
  return offline({
@@ -6018,33 +5524,10 @@ class AssetTypeAttachmentService extends BaseAttachmentService {
6018
5524
  });
6019
5525
  }
6020
5526
  async attachFilesToAssetType(files, assetTypeId) {
6021
- return this.attachFiles(
6022
- files,
6023
- assetTypeId,
6024
- this.buildOfflineAttachment.bind(this),
6025
- {
6026
- addAttachments: addAssetTypeAttachments,
6027
- updateAttachments: updateAssetTypeAttachments,
6028
- removeAttachments: removeAssetTypeAttachments
6029
- }
6030
- );
6031
- }
6032
- deleteAssetTypeAttachment(attachmentId) {
6033
- return this.deleteAttachment(
6034
- attachmentId,
6035
- {
6036
- setAttachment: setAssetTypeAttachment,
6037
- removeAttachment: removeAssetTypeAttachment
6038
- },
6039
- {
6040
- selectAttachment: selectAssetTypeAttachment
6041
- }
6042
- );
5527
+ return this.attachFiles(files, assetTypeId, this.buildOfflineAttachment.bind(this));
6043
5528
  }
6044
- async refreshStore() {
6045
- return this.getAttachments({
6046
- setAttachments: setAssetTypeAttachments
6047
- });
5529
+ async deleteAssetTypeAttachment(attachmentId) {
5530
+ return this.deleteAttachment(attachmentId);
6048
5531
  }
6049
5532
  }
6050
5533
  class IssueCommentService extends BaseApiService {
@@ -6066,13 +5549,13 @@ class IssueCommentService extends BaseApiService {
6066
5549
  blocks: [offlineComment.offline_id]
6067
5550
  });
6068
5551
  promise.catch(() => {
6069
- store.dispatch(removeIssueComment(offlineComment.offline_id));
5552
+ store.dispatch(deleteIssueComment(offlineComment.offline_id));
6070
5553
  });
6071
5554
  return [offlineComment, promise];
6072
5555
  }
6073
5556
  update(comment) {
6074
5557
  const { store } = this.client;
6075
- const commentToUpdate = store.getState().issueReducer.comments[comment.offline_id];
5558
+ const commentToUpdate = store.getState().issueCommentReducer.instances[comment.offline_id];
6076
5559
  if (!commentToUpdate) {
6077
5560
  throw new Error(`Comment with offline_id ${comment.offline_id} not found in store`);
6078
5561
  }
@@ -6091,11 +5574,11 @@ class IssueCommentService extends BaseApiService {
6091
5574
  return [comment, promise];
6092
5575
  }
6093
5576
  remove(offline_id) {
6094
- const commentToRemove = this.client.store.getState().issueReducer.comments[offline_id];
5577
+ const commentToRemove = this.client.store.getState().issueCommentReducer.instances[offline_id];
6095
5578
  if (!commentToRemove) {
6096
5579
  throw new Error(`Comment with offline_id ${offline_id} not found in store`);
6097
5580
  }
6098
- this.client.store.dispatch(removeIssueComment(offline_id));
5581
+ this.client.store.dispatch(deleteIssueComment(offline_id));
6099
5582
  const promise = this.client.enqueueRequest({
6100
5583
  description: "Delete comment",
6101
5584
  method: HttpMethod.DELETE,
@@ -6140,13 +5623,20 @@ class IssueUpdateService extends BaseApiService {
6140
5623
  `Received duplicate comments from the API (new length ${filteredResult.length}); filtered in browser.`
6141
5624
  );
6142
5625
  }
6143
- store.dispatch(setIssueUpdates(filteredResult));
5626
+ store.dispatch(initializeIssueUpdates(filteredResult));
6144
5627
  }
6145
5628
  }
6146
5629
  class IssueAttachmentService extends BaseAttachmentService {
6147
5630
  constructor() {
6148
5631
  super(...arguments);
6149
5632
  __publicField(this, "attachmentModel", AttachmentModel.Issue);
5633
+ __publicField(this, "initializeAttachments", initializeIssueAttachments);
5634
+ __publicField(this, "addAttachments", addIssueAttachments);
5635
+ __publicField(this, "updateAttachments", updateIssueAttachments);
5636
+ __publicField(this, "removeAttachments", deleteIssueAttachments);
5637
+ __publicField(this, "removeAttachment", deleteIssueAttachment);
5638
+ __publicField(this, "setAttachment", setIssueAttachment);
5639
+ __publicField(this, "selectAttachment", selectIssueAttachment);
6150
5640
  }
6151
5641
  buildOfflineAttachment(data) {
6152
5642
  return offline({
@@ -6161,28 +5651,10 @@ class IssueAttachmentService extends BaseAttachmentService {
6161
5651
  });
6162
5652
  }
6163
5653
  async attachFilesToIssue(files, issueId) {
6164
- return this.attachFiles(files, issueId, this.buildOfflineAttachment.bind(this), {
6165
- addAttachments: addIssueAttachments,
6166
- updateAttachments: updateIssueAttachments,
6167
- removeAttachments: removeIssueAttachments
6168
- });
6169
- }
6170
- deleteIssueAttachment(attachmentId) {
6171
- return this.deleteAttachment(
6172
- attachmentId,
6173
- {
6174
- setAttachment: setIssueAttachment,
6175
- removeAttachment: removeIssueAttachment
6176
- },
6177
- {
6178
- selectAttachment: selectIssueAttachment
6179
- }
6180
- );
5654
+ return this.attachFiles(files, issueId, this.buildOfflineAttachment.bind(this));
6181
5655
  }
6182
- async refreshStore() {
6183
- return this.getAttachments({
6184
- setAttachments: setIssueAttachments
6185
- });
5656
+ async deleteIssueAttachment(attachmentId) {
5657
+ return this.deleteAttachment(attachmentId);
6186
5658
  }
6187
5659
  }
6188
5660
  class IssueService extends BaseApiService {
@@ -6238,41 +5710,22 @@ class IssueService extends BaseApiService {
6238
5710
  severity: "danger"
6239
5711
  });
6240
5712
  }
6241
- store.dispatch(removeIssue(issuePayload.offline_id));
5713
+ store.dispatch(deleteIssue(issuePayload.offline_id));
6242
5714
  store.dispatch(addActiveProjectIssuesCount(-1));
6243
5715
  throw error2;
6244
5716
  });
6245
5717
  return [issuePayload, promise];
6246
5718
  }
6247
- fetchAll(projectId) {
6248
- const promise = this.client.enqueueRequest({
6249
- description: "Get issues",
6250
- method: HttpMethod.GET,
6251
- url: `/projects/${projectId}/issues/`,
6252
- blockers: [],
6253
- blocks: []
6254
- }).then((result) => {
6255
- const filteredResult = result.filter(onlyUniqueOfflineIds);
6256
- if (result.length !== filteredResult.length) {
6257
- console.error(
6258
- `Received duplicate issues from the API (new length ${filteredResult.length});
6259
- filtered in browser.`
6260
- );
6261
- }
6262
- return filteredResult;
6263
- });
6264
- const offlineIssues = Object.values(this.client.store.getState().issueReducer.issues);
6265
- return [offlineIssues, promise];
6266
- }
6267
5719
  update(issue) {
6268
5720
  const state = this.client.store.getState();
6269
- const issueToBeUpdated = state.issueReducer.issues[issue.offline_id];
5721
+ const issueToBeUpdated = selectIssue(issue.offline_id)(state);
6270
5722
  if (!issueToBeUpdated) {
6271
5723
  throw new Error(
6272
5724
  `Attempting to update an issue with offline_id ${issue.offline_id} that doesn't exist in the store`
6273
5725
  );
6274
5726
  }
6275
- this.client.store.dispatch(updateIssue(issue));
5727
+ const updatedIssue = { ...issueToBeUpdated, ...issue };
5728
+ this.client.store.dispatch(updateIssue(updatedIssue));
6276
5729
  const changes = {};
6277
5730
  for (const issueUpdateChange of [
6278
5731
  IssueUpdateChange.TITLE,
@@ -6289,7 +5742,7 @@ class IssueService extends BaseApiService {
6289
5742
  let categoryOrNull = null;
6290
5743
  const categoryIdOrNull = issue[issueUpdateChange];
6291
5744
  if (categoryIdOrNull) {
6292
- categoryOrNull = state.categoryReducer.categories[categoryIdOrNull] ?? null;
5745
+ categoryOrNull = state.categoryReducer.instances[categoryIdOrNull] ?? null;
6293
5746
  if (!categoryOrNull)
6294
5747
  throw new Error(
6295
5748
  `Trying to update issue category to ${categoryIdOrNull} which does not exist in store`
@@ -6352,28 +5805,26 @@ class IssueService extends BaseApiService {
6352
5805
  });
6353
5806
  promise.catch(() => {
6354
5807
  this.client.store.dispatch(updateIssue(issueToBeUpdated));
6355
- this.client.store.dispatch(removeIssueUpdate(offlineIssueUpdate.offline_id));
5808
+ this.client.store.dispatch(deleteIssueUpdate(offlineIssueUpdate.offline_id));
6356
5809
  });
6357
- const fullIssue = state.issueReducer.issues[issue.offline_id];
6358
- return [fullIssue, promise];
5810
+ return [updatedIssue, promise];
6359
5811
  }
6360
5812
  async remove(id) {
6361
5813
  const { store } = this.client;
6362
5814
  const state = store.getState();
6363
5815
  const dispatch = store.dispatch;
6364
- const backup = state.issueReducer.issues[id];
5816
+ const backup = selectIssue(id)(state);
6365
5817
  if (!backup) {
6366
5818
  throw new Error(`No issue with id ${id} found in the store`);
6367
5819
  }
6368
- const attachments = Object.values(state.issueReducer.attachments).filter((a) => a.issue === id);
6369
5820
  const attachmentsOfIssue = selectAttachmentsOfIssue(id)(state);
6370
5821
  const updatesOfIssue = selectIssueUpdatesOfIssue(id)(state);
6371
- dispatch(removeIssue(id));
5822
+ dispatch(deleteIssue(id));
6372
5823
  dispatch(addActiveProjectIssuesCount(-1));
6373
5824
  if (attachmentsOfIssue.length > 0)
6374
- dispatch(removeAttachmentsOfIssue(id));
5825
+ dispatch(deleteIssueAttachments(attachmentsOfIssue.map(({ offline_id }) => offline_id)));
6375
5826
  if (updatesOfIssue.length > 0)
6376
- dispatch(removeIssueUpdates(updatesOfIssue.map(({ offline_id }) => offline_id)));
5827
+ dispatch(deleteIssueUpdates(updatesOfIssue.map(({ offline_id }) => offline_id)));
6377
5828
  try {
6378
5829
  return await this.client.enqueueRequest({
6379
5830
  description: "Delete issue",
@@ -6384,7 +5835,7 @@ class IssueService extends BaseApiService {
6384
5835
  });
6385
5836
  } catch (e) {
6386
5837
  dispatch(addIssue(backup));
6387
- dispatch(addIssueAttachments(attachments));
5838
+ dispatch(addIssueAttachments(attachmentsOfIssue));
6388
5839
  dispatch(addIssueUpdates(updatesOfIssue));
6389
5840
  dispatch(addActiveProjectIssuesCount(1));
6390
5841
  throw e;
@@ -6397,9 +5848,23 @@ class IssueService extends BaseApiService {
6397
5848
  if (!projectId) {
6398
5849
  throw new Error("No active project");
6399
5850
  }
6400
- const [_offlineIssues, promise] = this.fetchAll(projectId);
6401
- const result = await promise;
6402
- store.dispatch(setIssues(result));
5851
+ const result = await this.client.enqueueRequest({
5852
+ description: "Get issues",
5853
+ method: HttpMethod.GET,
5854
+ url: `/projects/${projectId}/issues/`,
5855
+ blockers: [],
5856
+ blocks: []
5857
+ }).then((result2) => {
5858
+ const filteredResult = result2.filter(onlyUniqueOfflineIds);
5859
+ if (result2.length !== filteredResult.length) {
5860
+ console.error(
5861
+ `Received duplicate issues from the API (new length ${filteredResult.length});
5862
+ filtered in browser.`
5863
+ );
5864
+ }
5865
+ return filteredResult;
5866
+ });
5867
+ store.dispatch(initializeIssues(result));
6403
5868
  }
6404
5869
  }
6405
5870
  class IssueTypeService extends BaseApiService {
@@ -6441,7 +5906,8 @@ class IssueTypeService extends BaseApiService {
6441
5906
  }
6442
5907
  update(issueTypeFields) {
6443
5908
  const { store } = this.client;
6444
- const issueTypeToBeUpdated = store.getState().issueTypeReducer.issueTypes[issueTypeFields.offline_id];
5909
+ const state = store.getState();
5910
+ const issueTypeToBeUpdated = selectIssueType(issueTypeFields.offline_id)(state);
6445
5911
  if (!issueTypeToBeUpdated) {
6446
5912
  throw new Error(`IssueType with offline_id ${issueTypeFields.offline_id} does not exist in the store.`);
6447
5913
  }
@@ -6467,13 +5933,13 @@ class IssueTypeService extends BaseApiService {
6467
5933
  delete(issueTypeId) {
6468
5934
  const { store } = this.client;
6469
5935
  const state = store.getState();
6470
- const issueTypeToDelete = state.issueTypeReducer.issueTypes[issueTypeId];
5936
+ const issueTypeToDelete = selectIssueType(issueTypeId)(state);
6471
5937
  if (!issueTypeToDelete) {
6472
5938
  throw new Error(`IssueType with offline_id ${issueTypeId} does not exist in the store.`);
6473
5939
  }
6474
5940
  const issuesOfIssueType = selectIssuesOfIssueType(issueTypeId)(state) ?? [];
6475
5941
  store.dispatch(removeIssueType(issueTypeId));
6476
- store.dispatch(removeIssues(issuesOfIssueType.map((issue) => issue.offline_id)));
5942
+ store.dispatch(deleteIssues(issuesOfIssueType.map((issue) => issue.offline_id)));
6477
5943
  const promise = this.client.enqueueRequest({
6478
5944
  method: HttpMethod.DELETE,
6479
5945
  url: `/issues/types/${issueTypeId}/`,
@@ -6498,7 +5964,7 @@ class IssueTypeService extends BaseApiService {
6498
5964
  blockers: [],
6499
5965
  blocks: []
6500
5966
  });
6501
- store.dispatch(setIssueTypes(result));
5967
+ store.dispatch(initializeIssueTypes(result));
6502
5968
  }
6503
5969
  }
6504
5970
  class MainService extends BaseApiService {
@@ -6632,12 +6098,12 @@ class MainService extends BaseApiService {
6632
6098
  if (overwrite) {
6633
6099
  console.log("Overwriting data");
6634
6100
  store.dispatch(setProjects(projects));
6635
- store.dispatch(setWorkspaces(workspaces));
6101
+ store.dispatch(initializeWorkspaces(Object.values(workspaces)));
6636
6102
  store.dispatch(resetRecentIssues());
6637
6103
  } else {
6638
6104
  console.log("Updating data (collisions will be replaced)");
6639
6105
  store.dispatch(addOrReplaceProjects(projects));
6640
- store.dispatch(addOrReplaceWorkspaces(workspaces));
6106
+ store.dispatch(setWorkspaces(Object.values(workspaces)));
6641
6107
  }
6642
6108
  if (!currentProjectId) {
6643
6109
  store.dispatch(setIsFetchingInitialData(false));
@@ -6695,7 +6161,7 @@ class ProjectAccessService extends BaseApiService {
6695
6161
  // TODO: Re-add user to project if removal fails
6696
6162
  async remove(projectAccess) {
6697
6163
  const { store } = this.client;
6698
- store.dispatch(removeProjectAccess(projectAccess));
6164
+ store.dispatch(deleteProjectAccess(projectAccess.offline_id));
6699
6165
  return this.client.enqueueRequest({
6700
6166
  description: "Delete project access",
6701
6167
  method: HttpMethod.DELETE,
@@ -6818,6 +6284,13 @@ class ProjectAttachmentService extends BaseAttachmentService {
6818
6284
  constructor() {
6819
6285
  super(...arguments);
6820
6286
  __publicField(this, "attachmentModel", AttachmentModel.Project);
6287
+ __publicField(this, "initializeAttachments", initializeProjectAttachments);
6288
+ __publicField(this, "addAttachments", addProjectAttachments);
6289
+ __publicField(this, "updateAttachments", updateProjectAttachments);
6290
+ __publicField(this, "removeAttachments", deleteProjectAttachments);
6291
+ __publicField(this, "removeAttachment", deleteProjectAttachment);
6292
+ __publicField(this, "setAttachment", setProjectAttachment);
6293
+ __publicField(this, "selectAttachment", selectProjectAttachment);
6821
6294
  }
6822
6295
  buildOfflineAttachment(data) {
6823
6296
  return offline({
@@ -6832,28 +6305,10 @@ class ProjectAttachmentService extends BaseAttachmentService {
6832
6305
  });
6833
6306
  }
6834
6307
  async attachFilesToProject(files, projectId) {
6835
- return this.attachFiles(files, projectId, this.buildOfflineAttachment.bind(this), {
6836
- addAttachments: addProjectAttachments,
6837
- updateAttachments: updateProjectAttachments,
6838
- removeAttachments: removeProjectAttachments
6839
- });
6840
- }
6841
- deleteProjectAttachment(attachmentId) {
6842
- return this.deleteAttachment(
6843
- attachmentId,
6844
- {
6845
- setAttachment: setProjectAttachment,
6846
- removeAttachment: removeProjectAttachment
6847
- },
6848
- {
6849
- selectAttachment: selectProjectAttachment
6850
- }
6851
- );
6308
+ return this.attachFiles(files, projectId, this.buildOfflineAttachment.bind(this));
6852
6309
  }
6853
- async refreshStore() {
6854
- return this.getAttachments({
6855
- setAttachments: setProjectAttachments
6856
- });
6310
+ async deleteProjectAttachment(attachmentId) {
6311
+ return this.deleteAttachment(attachmentId);
6857
6312
  }
6858
6313
  }
6859
6314
  class ProjectService extends BaseApiService {
@@ -6931,9 +6386,9 @@ class ProjectService extends BaseApiService {
6931
6386
  const filesToDelete = selectProjectFiles(state).filter((file) => file.project === projectId);
6932
6387
  store.dispatch(removeProjectFilesOfProject(project.id));
6933
6388
  const attachmentsOfProject = selectAttachmentsOfProject(project.id)(state);
6934
- store.dispatch(removeProjectAttachments(attachmentsOfProject.map(({ offline_id }) => offline_id)));
6389
+ store.dispatch(deleteProjectAttachments(attachmentsOfProject.map(({ offline_id }) => offline_id)));
6935
6390
  const projectAccesses = selectProjectAccesses(state);
6936
- store.dispatch(removeProjectAccessesOfProject(project.id));
6391
+ store.dispatch(deleteProjectAccesses(projectAccesses.map(({ offline_id }) => offline_id)));
6937
6392
  store.dispatch({ type: "rehydrated/setRehydrated", payload: false });
6938
6393
  store.dispatch(deleteProject(project));
6939
6394
  const license = selectLicenseForProject(project.id)(state);
@@ -7188,8 +6643,13 @@ class UserFormService extends BaseApiService {
7188
6643
  }
7189
6644
  async favorite(formId2) {
7190
6645
  const { store } = this.client;
7191
- const activeProjectId = store.getState().projectReducer.activeProjectId;
7192
- store.dispatch(favoriteForm({ formId: formId2 }));
6646
+ const state = store.getState();
6647
+ const activeProjectId = state.projectReducer.activeProjectId;
6648
+ const form = state.formReducer.instances[formId2];
6649
+ if (!form) {
6650
+ throw new Error(`Expected form to exist, got ${form}`);
6651
+ }
6652
+ store.dispatch(updateForm({ ...form, favorite: true }));
7193
6653
  try {
7194
6654
  await this.client.enqueueRequest({
7195
6655
  description: "Favorite form",
@@ -7199,14 +6659,19 @@ class UserFormService extends BaseApiService {
7199
6659
  blocks: [`favorite-${formId2}`]
7200
6660
  });
7201
6661
  } catch (e) {
7202
- store.dispatch(unfavoriteForm({ formId: formId2 }));
6662
+ store.dispatch(updateForm(form));
7203
6663
  throw e;
7204
6664
  }
7205
6665
  }
7206
6666
  async unfavorite(formId2) {
7207
6667
  const { store } = this.client;
7208
- const activeProjectId = store.getState().projectReducer.activeProjectId;
7209
- store.dispatch(unfavoriteForm({ formId: formId2 }));
6668
+ const state = store.getState();
6669
+ const activeProjectId = state.projectReducer.activeProjectId;
6670
+ const form = state.formReducer.instances[formId2];
6671
+ if (!form) {
6672
+ throw new Error(`Expected form to exist, got ${form}`);
6673
+ }
6674
+ store.dispatch(updateForm({ ...form, favorite: false }));
7210
6675
  try {
7211
6676
  return await this.client.enqueueRequest({
7212
6677
  description: "Unfavorite form",
@@ -7216,7 +6681,7 @@ class UserFormService extends BaseApiService {
7216
6681
  blocks: [`favorite-${formId2}`]
7217
6682
  });
7218
6683
  } catch (e) {
7219
- store.dispatch(favoriteForm({ formId: formId2 }));
6684
+ store.dispatch(updateForm(form));
7220
6685
  throw e;
7221
6686
  }
7222
6687
  }
@@ -7317,7 +6782,7 @@ class UserFormService extends BaseApiService {
7317
6782
  for (const attachment of issueTypeFormsResult.attachments)
7318
6783
  attachments.push(attachment);
7319
6784
  store.dispatch(setForms(forms));
7320
- store.dispatch(setFormRevisions(revisions));
6785
+ store.dispatch(initializeFormRevisions(revisions));
7321
6786
  store.dispatch(setFormRevisionAttachments(attachments));
7322
6787
  }
7323
6788
  }
@@ -7544,7 +7009,10 @@ class UserFormSubmissionService extends BaseApiService {
7544
7009
  ...submission,
7545
7010
  values
7546
7011
  };
7547
- const submissionToBeUpdated = store.getState().formSubmissionReducer.formSubmissions[submission.offline_id];
7012
+ const submissionToBeUpdated = selectFormSubmission(submission.offline_id)(store.getState());
7013
+ if (!submissionToBeUpdated) {
7014
+ throw new Error(`Expected submission with offline_id ${submission.offline_id} to exist`);
7015
+ }
7548
7016
  store.dispatch(updateFormSubmission(offlineSubmission));
7549
7017
  const promise = this.client.enqueueRequest({
7550
7018
  description: "Patch form submission",
@@ -7566,7 +7034,10 @@ class UserFormSubmissionService extends BaseApiService {
7566
7034
  async delete(submissionId) {
7567
7035
  const { store } = this.client;
7568
7036
  const state = store.getState();
7569
- const submission = state.formSubmissionReducer.formSubmissions[submissionId];
7037
+ const submissionToBeDeleted = selectFormSubmission(submissionId)(store.getState());
7038
+ if (!submissionToBeDeleted) {
7039
+ throw new Error(`Expected submission with offline_id ${submissionId} to exist`);
7040
+ }
7570
7041
  const submissionAttachments = selectAttachmentsOfFormSubmission(submissionId)(state);
7571
7042
  store.dispatch(deleteFormSubmission(submissionId));
7572
7043
  store.dispatch(addActiveProjectFormSubmissionsCount(-1));
@@ -7581,7 +7052,7 @@ class UserFormSubmissionService extends BaseApiService {
7581
7052
  });
7582
7053
  } catch (e) {
7583
7054
  store.dispatch(addActiveProjectFormSubmissionsCount(1));
7584
- store.dispatch(addFormSubmission(submission));
7055
+ store.dispatch(addFormSubmission(submissionToBeDeleted));
7585
7056
  store.dispatch(addFormSubmissionAttachments(submissionAttachments));
7586
7057
  throw e;
7587
7058
  }
@@ -7621,15 +7092,15 @@ class WorkspaceService extends BaseApiService {
7621
7092
  blocks: [offlineWorkspace.offline_id]
7622
7093
  });
7623
7094
  void promise.then((result) => {
7624
- store.dispatch(addOrReplaceWorkspaces({ [offlineWorkspace.offline_id]: result }));
7095
+ store.dispatch(updateWorkspace(result));
7625
7096
  }).catch(() => {
7626
- store.dispatch(removeWorkspace(offlineWorkspace.offline_id));
7097
+ store.dispatch(deleteWorkspace(offlineWorkspace.offline_id));
7627
7098
  });
7628
7099
  return [offlineWorkspace, promise];
7629
7100
  }
7630
7101
  update(workspace) {
7631
7102
  const { store } = this.client;
7632
- store.dispatch(addOrReplaceWorkspaces({ [workspace.offline_id]: workspace }));
7103
+ store.dispatch(addWorkspace(workspace));
7633
7104
  const promise = this.client.enqueueRequest({
7634
7105
  description: "Update Workspace",
7635
7106
  method: HttpMethod.PATCH,
@@ -7649,8 +7120,8 @@ class WorkspaceService extends BaseApiService {
7649
7120
  blockers: [workspaceId],
7650
7121
  blocks: []
7651
7122
  });
7652
- const originalWorkspace = store.getState().workspaceReducer.workspaces[workspaceId];
7653
- store.dispatch(removeWorkspace(workspaceId));
7123
+ const originalWorkspace = store.getState().workspaceReducer.instances[workspaceId];
7124
+ store.dispatch(deleteWorkspace(workspaceId));
7654
7125
  void promise.then(() => {
7655
7126
  void this.client.main.fetchInitialData(true).then();
7656
7127
  }).catch((reason) => {
@@ -7678,7 +7149,7 @@ class OrganizationAccessService extends BaseApiService {
7678
7149
  return promise;
7679
7150
  }
7680
7151
  async remove(organizationAccess) {
7681
- this.client.store.dispatch(removeOrganizationAccess(organizationAccess));
7152
+ this.client.store.dispatch(deleteOrganizationAccess(organizationAccess.offline_id));
7682
7153
  this.client.store.dispatch(removeUser(organizationAccess.user));
7683
7154
  return this.client.enqueueRequest({
7684
7155
  description: "Remove organization access",
@@ -7702,7 +7173,7 @@ class OrganizationAccessService extends BaseApiService {
7702
7173
  blockers: [],
7703
7174
  blocks: []
7704
7175
  });
7705
- store.dispatch(setOrganizationAccesses(result));
7176
+ store.dispatch(initializeOrganizationAccesses(result));
7706
7177
  }
7707
7178
  }
7708
7179
  const cachedRequestPromises = {};
@@ -7937,15 +7408,6 @@ class EmailVerificationService extends BaseApiService {
7937
7408
  }
7938
7409
  }
7939
7410
  class EmailDomainsService extends BaseApiService {
7940
- async fetchAll(orgId) {
7941
- return this.client.enqueueRequest({
7942
- description: "Fetch email domains for organization",
7943
- method: HttpMethod.GET,
7944
- url: `/organizations/${orgId}/email-domains/`,
7945
- blockers: [orgId.toString()],
7946
- blocks: []
7947
- });
7948
- }
7949
7411
  async add(orgId, email) {
7950
7412
  return this.client.enqueueRequest({
7951
7413
  description: "Add email domain to organization",
@@ -7957,7 +7419,7 @@ class EmailDomainsService extends BaseApiService {
7957
7419
  });
7958
7420
  }
7959
7421
  async remove(emailDomain) {
7960
- this.client.store.dispatch(removeEmailDomain(emailDomain));
7422
+ this.client.store.dispatch(deleteEmailDomain(emailDomain.offline_id));
7961
7423
  return this.client.enqueueRequest({
7962
7424
  description: "Remove email domain from organization",
7963
7425
  method: HttpMethod.DELETE,
@@ -7974,9 +7436,14 @@ class EmailDomainsService extends BaseApiService {
7974
7436
  if (!organizationId) {
7975
7437
  throw new Error("No active organization");
7976
7438
  }
7977
- const promise = this.fetchAll(organizationId);
7978
- const result = await promise;
7979
- this.client.store.dispatch(setEmailDomains(result));
7439
+ const result = await this.client.enqueueRequest({
7440
+ description: "Fetch email domains for organization",
7441
+ method: HttpMethod.GET,
7442
+ url: `/organizations/${organizationId}/email-domains/`,
7443
+ blockers: [organizationId.toString()],
7444
+ blocks: []
7445
+ });
7446
+ this.client.store.dispatch(initializeEmailDomains(result));
7980
7447
  }
7981
7448
  }
7982
7449
  class OrganizationService extends BaseApiService {
@@ -8005,8 +7472,8 @@ class OrganizationService extends BaseApiService {
8005
7472
  const users = data.users;
8006
7473
  store.dispatch(addUsers(users));
8007
7474
  store.dispatch(setActiveOrganizationId(activeOrganization.id));
8008
- store.dispatch(setOrganizationAccesses(organizationAccesses));
8009
- store.dispatch(setEmailDomains(emailDomains));
7475
+ store.dispatch(initializeOrganizationAccesses(organizationAccesses));
7476
+ store.dispatch(initializeEmailDomains(emailDomains));
8010
7477
  if (showLoading) {
8011
7478
  store.dispatch(setIsFetchingInitialData(false));
8012
7479
  }
@@ -8319,6 +7786,13 @@ class DocumentAttachmentService extends BaseAttachmentService {
8319
7786
  constructor() {
8320
7787
  super(...arguments);
8321
7788
  __publicField(this, "attachmentModel", AttachmentModel.Document);
7789
+ __publicField(this, "initializeAttachments", initializeDocumentAttachments);
7790
+ __publicField(this, "addAttachments", addDocumentAttachments);
7791
+ __publicField(this, "updateAttachments", updateDocumentAttachments);
7792
+ __publicField(this, "removeAttachments", deleteDocumentAttachments);
7793
+ __publicField(this, "removeAttachment", deleteDocumentAttachment);
7794
+ __publicField(this, "setAttachment", setDocumentAttachment);
7795
+ __publicField(this, "selectAttachment", selectDocumentAttachment);
8322
7796
  }
8323
7797
  buildOfflineAttachment(data) {
8324
7798
  return offline({
@@ -8333,28 +7807,10 @@ class DocumentAttachmentService extends BaseAttachmentService {
8333
7807
  });
8334
7808
  }
8335
7809
  async attachFilesToDocument(files, documentId) {
8336
- return this.attachFiles(files, documentId, this.buildOfflineAttachment.bind(this), {
8337
- addAttachments: addDocumentAttachments,
8338
- updateAttachments: updateDocumentAttachments,
8339
- removeAttachments: removeDocumentAttachments
8340
- });
8341
- }
8342
- deleteDocumentAttachment(attachmentId) {
8343
- return this.deleteAttachment(
8344
- attachmentId,
8345
- {
8346
- setAttachment: setDocumentAttachment,
8347
- removeAttachment: removeDocumentAttachment
8348
- },
8349
- {
8350
- selectAttachment: selectDocumentAttachment
8351
- }
8352
- );
7810
+ return this.attachFiles(files, documentId, this.buildOfflineAttachment.bind(this));
8353
7811
  }
8354
- async refreshStore() {
8355
- return this.getAttachments({
8356
- setAttachments: setDocumentAttachments
8357
- });
7812
+ async deleteDocumentAttachment(attachmentId) {
7813
+ return this.deleteAttachment(attachmentId);
8358
7814
  }
8359
7815
  }
8360
7816
  class AgentService extends BaseApiService {
@@ -8395,7 +7851,7 @@ class AgentService extends BaseApiService {
8395
7851
  blocks: ["prompt"],
8396
7852
  queryParams: { conversation_id: conversationId }
8397
7853
  }).then((response) => {
8398
- const conversation = store.getState().agentsReducer.conversations[conversationId];
7854
+ const conversation = store.getState().agentsReducer.instances[conversationId];
8399
7855
  if (!(conversation == null ? void 0 : conversation.offline_id)) {
8400
7856
  throw new Error("Conversation not found");
8401
7857
  }
@@ -8441,7 +7897,7 @@ class AgentService extends BaseApiService {
8441
7897
  blockers: ["agent-conversations"],
8442
7898
  blocks: ["agent-conversations"]
8443
7899
  });
8444
- store.dispatch(setConversations(result));
7900
+ store.dispatch(initializeConversations(result));
8445
7901
  }
8446
7902
  }
8447
7903
  class TeamService extends BaseApiService {
@@ -8479,7 +7935,10 @@ class TeamService extends BaseApiService {
8479
7935
  // TODO: @Audiopolis / Magnus - should we pass a offline_id as one arg and a UpdatedTeamProps as a second arg instead of this set up?
8480
7936
  update(team) {
8481
7937
  const { store } = this.client;
8482
- const teamToBeUpdated = store.getState().teamReducer.teams[team.offline_id];
7938
+ const teamToBeUpdated = selectTeam(team.offline_id)(store.getState());
7939
+ if (!teamToBeUpdated) {
7940
+ throw new Error(`Expected team with offline_id ${team.offline_id} to exist`);
7941
+ }
8483
7942
  const offlineUpdatedTeam = {
8484
7943
  ...teamToBeUpdated,
8485
7944
  ...team
@@ -8503,7 +7962,7 @@ class TeamService extends BaseApiService {
8503
7962
  async delete(teamId) {
8504
7963
  const { store } = this.client;
8505
7964
  const state = store.getState();
8506
- const team = state.teamReducer.teams[teamId];
7965
+ const team = selectTeam(teamId)(state);
8507
7966
  if (!team) {
8508
7967
  throw new Error(`Expected team with id ${teamId} to exist`);
8509
7968
  }
@@ -8523,7 +7982,7 @@ class TeamService extends BaseApiService {
8523
7982
  }
8524
7983
  async setMembers(teamId, members) {
8525
7984
  const { store } = this.client;
8526
- const team = store.getState().teamReducer.teams[teamId];
7985
+ const team = selectTeam(teamId)(store.getState());
8527
7986
  if (!team) {
8528
7987
  throw new Error(`Expected team with id ${teamId} to exist`);
8529
7988
  }
@@ -8548,7 +8007,7 @@ class TeamService extends BaseApiService {
8548
8007
  }
8549
8008
  async addMembers(teamId, members) {
8550
8009
  const { store } = this.client;
8551
- const team = store.getState().teamReducer.teams[teamId];
8010
+ const team = selectTeam(teamId)(store.getState());
8552
8011
  if (!team) {
8553
8012
  throw new Error(`Expected team with id ${teamId} to exist`);
8554
8013
  }
@@ -8557,7 +8016,7 @@ class TeamService extends BaseApiService {
8557
8016
  }
8558
8017
  async removeMembers(teamId, members) {
8559
8018
  const { store } = this.client;
8560
- const team = store.getState().teamReducer.teams[teamId];
8019
+ const team = selectTeam(teamId)(store.getState());
8561
8020
  if (!team) {
8562
8021
  throw new Error(`Expected team with id ${teamId} to exist`);
8563
8022
  }
@@ -16914,7 +16373,7 @@ export {
16914
16373
  addAssetType,
16915
16374
  addAssetTypeAttachment,
16916
16375
  addAssetTypeAttachments,
16917
- addAssetsInBatches,
16376
+ addAssets,
16918
16377
  addCategory,
16919
16378
  addConversation,
16920
16379
  addDocumentAttachment,
@@ -16942,12 +16401,9 @@ export {
16942
16401
  addIssueUpdates,
16943
16402
  addIssues,
16944
16403
  addLicenses,
16945
- addOrReplaceCategories,
16946
- addOrReplaceIssueComment,
16947
16404
  addOrReplaceProjectFile,
16948
16405
  addOrReplaceProjectFiles,
16949
16406
  addOrReplaceProjects,
16950
- addOrReplaceWorkspaces,
16951
16407
  addProjectAttachment,
16952
16408
  addProjectAttachments,
16953
16409
  addStageCompletion,
@@ -16960,12 +16416,16 @@ export {
16960
16416
  agentsReducer,
16961
16417
  agentsSlice,
16962
16418
  areArraysEqual,
16419
+ assetAttachmentReducer,
16420
+ assetAttachmentSlice,
16963
16421
  assetReducer,
16964
16422
  assetSlice,
16965
16423
  assetStageCompletionReducer,
16966
16424
  assetStageCompletionSlice,
16967
16425
  assetStageReducer,
16968
16426
  assetStageSlice,
16427
+ assetTypeAttachmentReducer,
16428
+ assetTypeAttachmentSlice,
16969
16429
  assetTypeReducer,
16970
16430
  assetTypeSlice,
16971
16431
  authReducer,
@@ -16988,7 +16448,17 @@ export {
16988
16448
  decodeFormValues,
16989
16449
  defaultBadgeColor,
16990
16450
  defaultStore,
16451
+ deleteAsset,
16452
+ deleteAssetAttachment,
16453
+ deleteAssetAttachments,
16991
16454
  deleteAssetType,
16455
+ deleteAssetTypeAttachment,
16456
+ deleteAssetTypeAttachments,
16457
+ deleteAssets,
16458
+ deleteCategory,
16459
+ deleteDocumentAttachment,
16460
+ deleteDocumentAttachments,
16461
+ deleteEmailDomain,
16992
16462
  deleteForm,
16993
16463
  deleteFormRevision,
16994
16464
  deleteFormRevisionAttachment,
@@ -16998,12 +16468,28 @@ export {
16998
16468
  deleteFormSubmissionAttachment,
16999
16469
  deleteFormSubmissionAttachments,
17000
16470
  deleteFormSubmissions,
16471
+ deleteIssue,
16472
+ deleteIssueAttachment,
16473
+ deleteIssueAttachments,
16474
+ deleteIssueComment,
16475
+ deleteIssueComments,
16476
+ deleteIssueUpdate,
16477
+ deleteIssueUpdates,
16478
+ deleteIssues,
16479
+ deleteOrganizationAccess,
17001
16480
  deleteProject,
16481
+ deleteProjectAccess,
16482
+ deleteProjectAccesses,
16483
+ deleteProjectAttachment,
16484
+ deleteProjectAttachments,
17002
16485
  deleteTeam,
16486
+ deleteWorkspace,
17003
16487
  dequeue,
17004
16488
  deserialize,
17005
16489
  deserializeField,
17006
16490
  discard,
16491
+ documentAttachmentReducer,
16492
+ documentAttachmentSlice,
17007
16493
  documentSlice,
17008
16494
  documentsReducer,
17009
16495
  downloadFile,
@@ -17025,17 +16511,20 @@ export {
17025
16511
  enqueue,
17026
16512
  enqueueRequest,
17027
16513
  errorColor,
17028
- favoriteForm,
17029
16514
  fileReducer,
17030
16515
  fileSlice,
17031
16516
  fileToBlob,
17032
16517
  flattenFields,
17033
16518
  flipCoordinates,
17034
16519
  formReducer,
16520
+ formRevisionAttachmentReducer,
16521
+ formRevisionAttachmentSlice,
17035
16522
  formRevisionReducer,
17036
16523
  formRevisionToSchema,
17037
16524
  formRevisionsSlice,
17038
16525
  formSlice,
16526
+ formSubmissionAttachmentReducer,
16527
+ formSubmissionAttachmentSlice,
17039
16528
  formSubmissionReducer,
17040
16529
  formSubmissionSlice,
17041
16530
  index as forms,
@@ -17054,16 +16543,40 @@ export {
17054
16543
  hideAllCategories,
17055
16544
  hideCategory,
17056
16545
  initialFormValues,
16546
+ initializeAssetAttachments,
16547
+ initializeAssetTypeAttachments,
16548
+ initializeAssetTypes,
16549
+ initializeAssets,
16550
+ initializeCategories,
16551
+ initializeConversations,
16552
+ initializeDocumentAttachments,
16553
+ initializeEmailDomains,
16554
+ initializeFormRevisionAttachments,
16555
+ initializeFormRevisions,
16556
+ initializeFormSubmissionAttachments,
16557
+ initializeIssueAttachments,
16558
+ initializeIssueTypes,
16559
+ initializeIssueUpdates,
16560
+ initializeIssues,
16561
+ initializeOrganizationAccesses,
16562
+ initializeProjectAttachments,
16563
+ initializeStages,
16564
+ initializeWorkspaces,
17057
16565
  isConditionMet,
17058
16566
  isToday,
16567
+ issueAttachmentReducer,
16568
+ issueAttachmentSlice,
16569
+ issueCommentReducer,
16570
+ issueCommentSlice,
17059
16571
  issueReducer,
17060
16572
  issueSlice,
17061
16573
  issueToSearchResult,
17062
16574
  issueTypeReducer,
17063
16575
  issueTypeSlice,
16576
+ issueUpdateReducer,
16577
+ issueUpdateSlice,
17064
16578
  licenseReducer,
17065
16579
  licenseSlice,
17066
- linkStageToForm,
17067
16580
  literalToCoordinates,
17068
16581
  logOnlyOnce,
17069
16582
  makeClient,
@@ -17090,54 +16603,27 @@ export {
17090
16603
  overmapEnhancer,
17091
16604
  overmapReducer,
17092
16605
  overmapReducers,
17093
- patchCategory,
17094
16606
  performRequest,
17095
16607
  primaryColor,
17096
16608
  projectAccessReducer,
17097
16609
  projectAccessSlice,
16610
+ projectAttachmentReducer,
16611
+ projectAttachmentSlice,
17098
16612
  projectFileReducer,
17099
16613
  projectFileSlice,
17100
16614
  projectReducer,
17101
16615
  projectSlice,
17102
16616
  rehydratedReducer,
17103
16617
  rehydratedSlice,
17104
- removeAllAssetsOfType,
17105
- removeAsset,
17106
- removeAssetAttachment,
17107
- removeAssetAttachments,
17108
- removeAssetTypeAttachment,
17109
- removeAssetTypeAttachments,
17110
- removeAssets,
17111
- removeAttachmentsOfIssue,
17112
- removeCategory,
17113
- removeColor,
17114
- removeDocumentAttachment,
17115
- removeDocumentAttachments,
17116
16618
  removeDocuments,
17117
- removeEmailDomain,
17118
16619
  removeFavouriteProjectId,
17119
- removeIssue,
17120
- removeIssueAttachment,
17121
- removeIssueAttachments,
17122
- removeIssueComment,
17123
- removeIssueComments,
17124
16620
  removeIssueType,
17125
- removeIssueUpdate,
17126
- removeIssueUpdates,
17127
- removeIssues,
17128
- removeOrganizationAccess,
17129
- removeProjectAccess,
17130
- removeProjectAccessesOfProject,
17131
- removeProjectAttachment,
17132
- removeProjectAttachments,
17133
16621
  removeProjectFile,
17134
16622
  removeProjectFilesOfProject,
17135
16623
  removeRecentIssue,
17136
16624
  removeStageCompletions,
17137
16625
  removeStages,
17138
16626
  removeUser,
17139
- removeWorkspace,
17140
- replaceCategory,
17141
16627
  resetProjectFileObjectUrls,
17142
16628
  resetRecentIssues,
17143
16629
  resetStore,
@@ -17146,7 +16632,6 @@ export {
17146
16632
  saveActiveProjectFileBounds,
17147
16633
  searchIssues,
17148
16634
  selectAccessToken,
17149
- selectActiveIssueId,
17150
16635
  selectActiveLicense,
17151
16636
  selectActiveOrganization,
17152
16637
  selectActiveOrganizationAccess,
@@ -17160,7 +16645,6 @@ export {
17160
16645
  selectActiveStatusLicenses,
17161
16646
  selectActiveWorkspace,
17162
16647
  selectActiveWorkspaceId,
17163
- selectAllAttachments,
17164
16648
  selectAllDocumentAttachments,
17165
16649
  selectAllProjectAttachments,
17166
16650
  selectAncestorIdsOfDocument,
@@ -17196,11 +16680,10 @@ export {
17196
16680
  selectAttachmentsOfProjectByType,
17197
16681
  selectCategories,
17198
16682
  selectCategoriesOfWorkspace,
17199
- selectCategory,
16683
+ selectCategoryById,
17200
16684
  selectCategoryMapping,
17201
16685
  selectCategoryVisibility,
17202
16686
  selectCenterMapToProject,
17203
- selectCommentMapping,
17204
16687
  selectCommentsOfIssue,
17205
16688
  selectCompletedStageIdsForAsset,
17206
16689
  selectCompletedStages,
@@ -17214,7 +16697,9 @@ export {
17214
16697
  selectDocumentAttachmentMapping,
17215
16698
  selectDocuments,
17216
16699
  selectDocumentsMapping,
16700
+ selectEmailDomains,
17217
16701
  selectEmailDomainsAsMapping,
16702
+ selectEmailDomainsOfOrganization,
17218
16703
  selectEnableClustering,
17219
16704
  selectEnableDuplicateIssues,
17220
16705
  selectEnablePlacementMode,
@@ -17223,7 +16708,6 @@ export {
17223
16708
  selectEnabledProjectFiles,
17224
16709
  selectExpandedSections,
17225
16710
  selectFavouriteProjects,
17226
- selectFileAttachmentsOfIssue,
17227
16711
  selectFilteredForms,
17228
16712
  selectForm,
17229
16713
  selectFormMapping,
@@ -17255,6 +16739,7 @@ export {
17255
16739
  selectIssueAttachment,
17256
16740
  selectIssueAttachmentMapping,
17257
16741
  selectIssueAttachments,
16742
+ selectIssueCommentMapping,
17258
16743
  selectIssueCountOfCategory,
17259
16744
  selectIssueMapping,
17260
16745
  selectIssueType,
@@ -17289,9 +16774,9 @@ export {
17289
16774
  selectOrganizationsMapping,
17290
16775
  selectOrganizationsWithAccess,
17291
16776
  selectPermittedWorkspaceIds,
17292
- selectPhotoAttachmentsOfIssue,
17293
16777
  selectProjectAccess,
17294
16778
  selectProjectAccessForUser,
16779
+ selectProjectAccessMapping,
17295
16780
  selectProjectAccessUserMapping,
17296
16781
  selectProjectAccesses,
17297
16782
  selectProjectAttachment,
@@ -17308,7 +16793,6 @@ export {
17308
16793
  selectRehydrated,
17309
16794
  selectRootDocuments,
17310
16795
  selectShowTooltips,
17311
- selectSortedEmailDomains,
17312
16796
  selectSortedFormSubmissionsOfForm,
17313
16797
  selectSortedOrganizationLicenses,
17314
16798
  selectSortedOrganizationUsers,
@@ -17327,7 +16811,6 @@ export {
17327
16811
  selectTeamsOfOrganization,
17328
16812
  selectTeamsOfUser,
17329
16813
  selectUploadUrl,
17330
- selectUsedColors,
17331
16814
  selectUser,
17332
16815
  selectUserFormRevisionAttachmentsMapping,
17333
16816
  selectUsersAsMapping,
@@ -17336,34 +16819,32 @@ export {
17336
16819
  selectWorkspace,
17337
16820
  selectWorkspaceMapping,
17338
16821
  selectWorkspaces,
17339
- setActiveIssueId,
17340
16822
  setActiveOrganizationId,
17341
16823
  setActiveProjectFileId,
17342
16824
  setActiveProjectId,
17343
16825
  setActiveWorkspaceId,
17344
16826
  setAppearance,
16827
+ setAsset,
17345
16828
  setAssetAttachment,
17346
16829
  setAssetAttachments,
17347
16830
  setAssetTypeAttachment,
17348
16831
  setAssetTypeAttachments,
17349
- setAssetTypes,
17350
16832
  setAssets,
17351
- setCategories,
17352
16833
  setCenterMapToProject,
17353
16834
  setConversation,
17354
- setConversations,
17355
16835
  setCurrentUser,
17356
16836
  setDocumentAttachment,
17357
16837
  setDocumentAttachments,
17358
16838
  setDocuments,
17359
- setEmailDomains,
17360
16839
  setEnableClustering,
17361
16840
  setEnableDuplicateIssues,
17362
16841
  setEnablePlacementMode,
16842
+ setForm,
17363
16843
  setFormRevision,
16844
+ setFormRevisionAttachment,
17364
16845
  setFormRevisionAttachments,
17365
- setFormRevisions,
17366
16846
  setFormSubmission,
16847
+ setFormSubmissionAttachment,
17367
16848
  setFormSubmissionAttachments,
17368
16849
  setFormSubmissions,
17369
16850
  setForms,
@@ -17375,13 +16856,10 @@ export {
17375
16856
  setIssueComment,
17376
16857
  setIssueComments,
17377
16858
  setIssueType,
17378
- setIssueTypes,
17379
- setIssueUpdates,
17380
- setIssues,
16859
+ setIssueUpdate,
17381
16860
  setLicenses,
17382
16861
  setLoggedIn,
17383
16862
  setMapStyle,
17384
- setOrganizationAccesses,
17385
16863
  setOrganizations,
17386
16864
  setProfilePicture,
17387
16865
  setProjectAccesses,
@@ -17391,6 +16869,7 @@ export {
17391
16869
  setProjects,
17392
16870
  setSectionExpanded,
17393
16871
  setShowTooltips,
16872
+ setStage,
17394
16873
  setStageCompletions,
17395
16874
  setTeam,
17396
16875
  setTeams,
@@ -17413,10 +16892,8 @@ export {
17413
16892
  toOfflineIdRecord,
17414
16893
  toggleAssetTypeVisibility,
17415
16894
  truncate,
17416
- unfavoriteForm,
17417
16895
  unhideAllCategories,
17418
16896
  unhideCategory,
17419
- unlinkStageToForm,
17420
16897
  updateActiveOrganization,
17421
16898
  updateAsset,
17422
16899
  updateAssetAttachment,
@@ -17424,11 +16901,16 @@ export {
17424
16901
  updateAssetTypeAttachment,
17425
16902
  updateAssetTypeAttachments,
17426
16903
  updateAssets,
16904
+ updateCategory,
17427
16905
  updateConversation,
17428
16906
  updateDocumentAttachment,
17429
16907
  updateDocumentAttachments,
17430
16908
  updateDocuments,
16909
+ updateForm,
16910
+ updateFormRevisionAttachment,
16911
+ updateFormRevisionAttachments,
17431
16912
  updateFormSubmission,
16913
+ updateFormSubmissionAttachment,
17432
16914
  updateFormSubmissionAttachments,
17433
16915
  updateFormSubmissions,
17434
16916
  updateIssue,
@@ -17441,8 +16923,10 @@ export {
17441
16923
  updateProjectAccess,
17442
16924
  updateProjectAttachment,
17443
16925
  updateProjectAttachments,
16926
+ updateStage,
17444
16927
  updateStages,
17445
16928
  updateTeam,
16929
+ updateWorkspace,
17446
16930
  useAppDispatch,
17447
16931
  useAppSelector,
17448
16932
  useFieldInput,