@overmap-ai/core 1.0.71-mapbox.3 → 1.0.71-mapbox.5

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.
@@ -1531,13 +1531,6 @@ const selectProjectAccesses = createSelector(
1531
1531
  const selectProjectAccessById = (id) => (state) => {
1532
1532
  return state.projectAccessReducer.instances[id];
1533
1533
  };
1534
- const selectActiveProjectAccess = (state) => {
1535
- const currentUser = state.userReducer.currentUser;
1536
- const activeProjectId = state.projectReducer.activeProjectId;
1537
- return Object.values(state.projectAccessReducer.instances).find((projectAccess) => {
1538
- return projectAccess.user === (currentUser == null ? void 0 : currentUser.id) && projectAccess.project === activeProjectId;
1539
- }) ?? null;
1540
- };
1541
1534
  const selectProjectAccessForUser = (user) => (state) => {
1542
1535
  return Object.values(state.projectAccessReducer.instances).find(
1543
1536
  (projectAccess) => projectAccess.user === user.id
@@ -1552,8 +1545,7 @@ const selectProjectAccessUserMapping = (state) => {
1552
1545
  };
1553
1546
  const projectAccessReducer = projectAccessSlice.reducer;
1554
1547
  const initialState$m = {
1555
- projects: {},
1556
- activeProjectId: null
1548
+ projects: {}
1557
1549
  };
1558
1550
  const projectSlice = createSlice({
1559
1551
  name: "projects",
@@ -1567,19 +1559,9 @@ const projectSlice = createSlice({
1567
1559
  });
1568
1560
  state.projects = projectsMap;
1569
1561
  },
1570
- setActiveProjectId: (state, action) => {
1571
- state.activeProjectId = action.payload;
1572
- },
1573
- updateOrCreateProject: (state, action) => {
1562
+ updateProject: (state, action) => {
1574
1563
  state.projects[action.payload.id] = action.payload;
1575
1564
  },
1576
- // Takes a list of Projects and updates existing ones to match the payload, or adds them
1577
- // to the store if they are not already present
1578
- updateOrCreateProjects: (state, action) => {
1579
- action.payload.forEach((project) => {
1580
- state.projects[project.id] = project;
1581
- });
1582
- },
1583
1565
  deleteProject: (state, action) => {
1584
1566
  delete state.projects[action.payload.id];
1585
1567
  },
@@ -1589,52 +1571,12 @@ const projectSlice = createSlice({
1589
1571
  } else {
1590
1572
  throw new Error("Accept project invite: user is not in this project");
1591
1573
  }
1592
- },
1593
- addActiveProjectIssuesCount: (state, action) => {
1594
- if (!state.activeProjectId || !(state.activeProjectId in state.projects)) {
1595
- throw new Error("Update issues count: no active project");
1596
- }
1597
- if (!state.projects[state.activeProjectId].issues_count) {
1598
- state.projects[state.activeProjectId].issues_count = action.payload;
1599
- } else {
1600
- state.projects[state.activeProjectId].issues_count += action.payload;
1601
- }
1602
- },
1603
- addActiveProjectFormSubmissionsCount: (state, action) => {
1604
- if (state.activeProjectId && state.activeProjectId in state.projects) {
1605
- if (!state.projects[state.activeProjectId].form_submissions_count) {
1606
- state.projects[state.activeProjectId].form_submissions_count = action.payload;
1607
- } else {
1608
- state.projects[state.activeProjectId].form_submissions_count += action.payload;
1609
- }
1610
- } else {
1611
- throw new Error("Update form submissions count: no active project");
1612
- }
1613
1574
  }
1614
1575
  }
1615
1576
  });
1616
- const {
1617
- setProjects,
1618
- updateOrCreateProject,
1619
- updateOrCreateProjects: addOrReplaceProjects,
1620
- setActiveProjectId,
1621
- deleteProject,
1622
- acceptProjectInvite,
1623
- addActiveProjectIssuesCount,
1624
- addActiveProjectFormSubmissionsCount
1625
- } = projectSlice.actions;
1577
+ const { setProjects, updateProject, deleteProject, acceptProjectInvite } = projectSlice.actions;
1626
1578
  const projectReducer = projectSlice.reducer;
1627
1579
  const selectProjectMapping = (state) => state.projectReducer.projects;
1628
- const selectActiveProjectId = (state) => state.projectReducer.activeProjectId;
1629
- const selectActiveProject = createSelector(
1630
- [selectProjectMapping, selectActiveProjectId],
1631
- (projectsMapping, activeprojectId) => {
1632
- if (activeprojectId === null) {
1633
- return null;
1634
- }
1635
- return projectsMapping[activeprojectId] ?? null;
1636
- }
1637
- );
1638
1580
  const selectProjectById = (id) => (state) => {
1639
1581
  return state.projectReducer.projects[id];
1640
1582
  };
@@ -1809,39 +1751,26 @@ const selectDeletedRequests = (state) => state.outboxReducer.deletedRequests;
1809
1751
  const selectLatestRetryTime = (state) => state.outboxReducer.latestRetryTime;
1810
1752
  const { enqueueRequest, markForDeletion, markAsDeleted, _setLatestRetryTime } = outboxSlice.actions;
1811
1753
  const outboxReducer = outboxSlice.reducer;
1812
- const initialState$j = {
1813
- projectFiles: {},
1754
+ const projectFileModelAdapter = createModelAdapter((projectFile) => projectFile.offline_id);
1755
+ const initialState$j = projectFileModelAdapter.getInitialState({
1814
1756
  activeProjectFileId: null,
1815
1757
  isImportingProjectFile: false
1816
- };
1758
+ });
1817
1759
  const projectFileSlice = createSlice({
1818
1760
  name: "projectFiles",
1819
1761
  initialState: initialState$j,
1820
1762
  extraReducers: (builder) => builder.addCase("RESET", (state) => Object.assign(state, initialState$j)),
1821
1763
  reducers: {
1822
- addOrReplaceProjectFiles: (state, action) => {
1823
- for (let fileObj of action.payload) {
1824
- let file = fileObj.file;
1825
- if (file.includes("+")) {
1826
- console.warn("Attempting to apply fix for image URL with '+' character:", file);
1827
- const parts = file.split("/");
1828
- if (parts.length < 2) {
1829
- throw new Error("Invalid URL: " + file);
1830
- }
1831
- const lastPart = encodeURIComponent(parts[parts.length - 1]);
1832
- file = parts.slice(0, -1).join("/") + "/" + lastPart;
1833
- console.warn("Fixed URL:", file);
1834
- fileObj = { ...fileObj, file };
1835
- }
1836
- state.projectFiles[fileObj.offline_id] = fileObj;
1837
- }
1838
- },
1839
- addOrReplaceProjectFile: (state, action) => {
1840
- if (!action.payload.project) {
1841
- throw new Error("ProjectFile has no project. A project must be set before storing.");
1842
- }
1843
- state.projectFiles[action.payload.offline_id] = action.payload;
1844
- },
1764
+ initializeProjectFiles: projectFileModelAdapter.initialize,
1765
+ setProjectFile: projectFileModelAdapter.setOne,
1766
+ setProjectFiles: projectFileModelAdapter.setMany,
1767
+ addProjectFile: projectFileModelAdapter.addOne,
1768
+ addProjectFiles: projectFileModelAdapter.addMany,
1769
+ updateProjectFile: projectFileModelAdapter.updateOne,
1770
+ updateProjectFiles: projectFileModelAdapter.updateMany,
1771
+ deleteProjectFile: projectFileModelAdapter.deleteOne,
1772
+ deleteProjectFiles: projectFileModelAdapter.deleteMany,
1773
+ // TODO: move following to /web
1845
1774
  setIsImportingProjectFile: (state, action) => {
1846
1775
  state.isImportingProjectFile = action.payload;
1847
1776
  },
@@ -1850,55 +1779,46 @@ const projectFileSlice = createSlice({
1850
1779
  if (!activeProjectFileId) {
1851
1780
  throw new Error("Tried to save bounds for active project file, but no active project file was set.");
1852
1781
  }
1853
- if (!state.projectFiles[activeProjectFileId]) {
1782
+ if (!state.instances[activeProjectFileId]) {
1854
1783
  throw new Error(
1855
1784
  `Tried to save bounds for active project file, but project file with ID ${activeProjectFileId}
1856
1785
  doesn't exist.`
1857
1786
  );
1858
1787
  }
1859
- state.projectFiles[activeProjectFileId].bounds = action.payload;
1788
+ state.instances[activeProjectFileId].bounds = action.payload;
1860
1789
  },
1861
- // TODO: Move to MapContext. Should not be persisted.
1862
1790
  setActiveProjectFileId: (state, action) => {
1863
1791
  state.activeProjectFileId = action.payload;
1864
1792
  },
1865
- removeProjectFile: (state, action) => {
1866
- delete state.projectFiles[action.payload];
1867
- },
1868
- removeProjectFilesOfProject: (state, action) => {
1869
- const filesToDelete = Object.values(state.projectFiles).filter((file) => file.project === action.payload);
1870
- for (const file of filesToDelete) {
1871
- delete state.projectFiles[file.offline_id];
1872
- }
1873
- },
1874
1793
  resetProjectFileObjectUrls: (state, ..._args) => {
1875
- for (const key in state.projectFiles) {
1876
- delete state.projectFiles[key].objectURL;
1794
+ for (const key in state.instances) {
1795
+ delete state.instances[key].objectURL;
1877
1796
  }
1878
1797
  }
1879
1798
  }
1880
1799
  });
1881
1800
  const {
1882
- addOrReplaceProjectFiles,
1883
- addOrReplaceProjectFile,
1801
+ initializeProjectFiles,
1802
+ setProjectFile,
1803
+ setProjectFiles,
1804
+ addProjectFile,
1805
+ addProjectFiles,
1806
+ updateProjectFile,
1807
+ updateProjectFiles,
1808
+ deleteProjectFile,
1809
+ deleteProjectFiles,
1810
+ // TODO: move following to /web
1884
1811
  setIsImportingProjectFile,
1885
1812
  setActiveProjectFileId,
1886
1813
  saveActiveProjectFileBounds,
1887
- removeProjectFile,
1888
- removeProjectFilesOfProject,
1889
1814
  resetProjectFileObjectUrls
1890
1815
  } = projectFileSlice.actions;
1891
- const selectProjectFileMapping = (state) => state.projectFileReducer.projectFiles;
1892
- const selectProjectFiles = createSelector(
1893
- [selectProjectFileMapping, selectActiveProjectId],
1894
- (mapping, activeProjectId) => {
1895
- return fallbackToEmptyArray(
1896
- Object.values(mapping).filter((file) => file.project === activeProjectId).sort((a, b) => a.z_index - b.z_index)
1897
- );
1898
- }
1899
- );
1816
+ const selectProjectFileMapping = (state) => state.projectFileReducer.instances;
1817
+ const selectProjectFiles = createSelector([selectProjectFileMapping], (mapping) => {
1818
+ return fallbackToEmptyArray(Object.values(mapping).sort((a, b) => a.z_index - b.z_index));
1819
+ });
1900
1820
  const selectProjectFileById = (id) => (state) => {
1901
- return state.projectFileReducer.projectFiles[id];
1821
+ return state.projectFileReducer.instances[id];
1902
1822
  };
1903
1823
  const selectActiveProjectFileId = (state) => state.projectFileReducer.activeProjectFileId;
1904
1824
  const selectIsImportingProjectFile = (state) => state.projectFileReducer.isImportingProjectFile;
@@ -4768,7 +4688,6 @@ class IssueService extends BaseApiService {
4768
4688
  created_by: createdBy
4769
4689
  });
4770
4690
  this.dispatch(addIssue(offlineIssue));
4771
- this.dispatch(addActiveProjectIssuesCount(1));
4772
4691
  const promise = this.enqueueRequest({
4773
4692
  description: "Create issue",
4774
4693
  method: HttpMethod.POST,
@@ -4785,7 +4704,6 @@ class IssueService extends BaseApiService {
4785
4704
  this.dispatch(updateIssue(result));
4786
4705
  }).catch((error) => {
4787
4706
  this.dispatch(deleteIssue(offlineIssue.offline_id));
4788
- this.dispatch(addActiveProjectIssuesCount(-1));
4789
4707
  throw error;
4790
4708
  });
4791
4709
  return [offlineIssue, promise];
@@ -4901,7 +4819,6 @@ class IssueService extends BaseApiService {
4901
4819
  issueAssociationsRecord[issueAssociation.offline_id] = issueAssociation;
4902
4820
  const issueAssociations = Object.values(issueAssociationsRecord);
4903
4821
  this.dispatch(deleteIssue(id));
4904
- this.dispatch(addActiveProjectIssuesCount(-1));
4905
4822
  if (attachmentsOfIssue.length > 0)
4906
4823
  this.dispatch(deleteIssueAttachments(attachmentsOfIssue.map(({ offline_id }) => offline_id)));
4907
4824
  if (updatesOfIssue.length > 0)
@@ -4922,7 +4839,6 @@ class IssueService extends BaseApiService {
4922
4839
  this.dispatch(addIssue(backup));
4923
4840
  this.dispatch(addIssueAttachments(attachmentsOfIssue));
4924
4841
  this.dispatch(addIssueUpdates(updatesOfIssue));
4925
- this.dispatch(addActiveProjectIssuesCount(1));
4926
4842
  this.dispatch(addFormSubmissions(formSubmissionsOfIssue));
4927
4843
  this.dispatch(addIssueAssociations(issueAssociations));
4928
4844
  throw e;
@@ -5081,7 +4997,7 @@ class ProjectFileService extends BaseApiService {
5081
4997
  blocks: [file.offline_id]
5082
4998
  });
5083
4999
  void promise.then((result) => {
5084
- this.dispatch(addOrReplaceProjectFile(result));
5000
+ this.dispatch(updateProjectFile(result));
5085
5001
  });
5086
5002
  return promise;
5087
5003
  }
@@ -5093,7 +5009,7 @@ class ProjectFileService extends BaseApiService {
5093
5009
  if (!activeProjectFileId) {
5094
5010
  throw new Error("No active project file");
5095
5011
  }
5096
- const activeProjectFile = state.projectFileReducer.projectFiles[activeProjectFileId];
5012
+ const activeProjectFile = state.projectFileReducer.instances[activeProjectFileId];
5097
5013
  if (!activeProjectFile) {
5098
5014
  throw new Error("No active project file");
5099
5015
  }
@@ -5132,7 +5048,7 @@ class ProjectFileService extends BaseApiService {
5132
5048
  return this.enqueueRequest(requestDetails2);
5133
5049
  });
5134
5050
  void promise.then((result) => {
5135
- this.dispatch(addOrReplaceProjectFile(result));
5051
+ this.dispatch(updateProjectFile(result));
5136
5052
  });
5137
5053
  this.dispatch(saveActiveProjectFileBounds);
5138
5054
  this.dispatch(setActiveProjectFileId(null));
@@ -5140,7 +5056,7 @@ class ProjectFileService extends BaseApiService {
5140
5056
  return [activeProjectFile, promise];
5141
5057
  }
5142
5058
  delete(projectFileId) {
5143
- this.dispatch(removeProjectFile(projectFileId));
5059
+ this.dispatch(deleteProjectFile(projectFileId));
5144
5060
  return this.enqueueRequest({
5145
5061
  method: HttpMethod.DELETE,
5146
5062
  url: `/projects/files/${projectFileId}`,
@@ -5156,8 +5072,7 @@ class ProjectFileService extends BaseApiService {
5156
5072
  blockers: [],
5157
5073
  blocks: []
5158
5074
  });
5159
- this.dispatch(addOrReplaceProjectFiles([]));
5160
- this.dispatch(addOrReplaceProjectFiles(result));
5075
+ this.dispatch(initializeProjectFiles(result));
5161
5076
  }
5162
5077
  }
5163
5078
  class ProjectAttachmentService extends BaseAttachmentService {
@@ -5213,7 +5128,7 @@ class ProjectService extends BaseApiService {
5213
5128
  if (!project.bounds && !project.canvas_bounds) {
5214
5129
  throw new Error("Project must either have bounds or canvas_bounds set");
5215
5130
  }
5216
- this.dispatch(updateOrCreateProject(project));
5131
+ this.dispatch(updateProject(project));
5217
5132
  return await this.enqueueRequest({
5218
5133
  description: "Update project",
5219
5134
  method: HttpMethod.PATCH,
@@ -5235,7 +5150,7 @@ class ProjectService extends BaseApiService {
5235
5150
  throw new Error("Expected project to exist");
5236
5151
  }
5237
5152
  const filesToDelete = selectProjectFiles(state).filter((file) => file.project === projectId);
5238
- this.dispatch(removeProjectFilesOfProject(project.id));
5153
+ this.dispatch(deleteProjectFiles(filesToDelete.map(({ offline_id }) => offline_id)));
5239
5154
  const attachmentsOfProject = selectAttachmentsOfProject(project.id)(state);
5240
5155
  this.dispatch(deleteProjectAttachments(attachmentsOfProject.map(({ offline_id }) => offline_id)));
5241
5156
  const projectAccesses = selectProjectAccesses(state);
@@ -5258,7 +5173,7 @@ class ProjectService extends BaseApiService {
5258
5173
  } catch (e) {
5259
5174
  this.dispatch(setProjects(Object.values(projects)));
5260
5175
  this.dispatch(initializeProjectAccesses(Object.values(projectAccesses)));
5261
- this.dispatch(addOrReplaceProjectFiles(filesToDelete));
5176
+ this.dispatch(addProjectFiles(filesToDelete));
5262
5177
  this.dispatch(setProjectAttachments(attachmentsOfProject));
5263
5178
  this.dispatch({ type: "rehydrated/setRehydrated", payload: true });
5264
5179
  if (license) {
@@ -5753,12 +5668,10 @@ class FormSubmissionService extends BaseUploadService {
5753
5668
  files
5754
5669
  );
5755
5670
  promise.then((result) => {
5756
- this.dispatch(addActiveProjectFormSubmissionsCount(1));
5757
5671
  this.dispatch(setFormSubmission(result));
5758
5672
  return result;
5759
5673
  }).catch(() => {
5760
5674
  this.dispatch(deleteFormSubmission(offlineSubmission.offline_id));
5761
- this.dispatch(addActiveProjectFormSubmissionsCount(-1));
5762
5675
  });
5763
5676
  return [offlineSubmission, offlineFormSubmissionAttachments, promise, attachmentsPromise];
5764
5677
  }
@@ -5925,7 +5838,6 @@ class FormSubmissionService extends BaseUploadService {
5925
5838
  }
5926
5839
  const submissionAttachments = selectAttachmentsOfFormSubmission(id)(state);
5927
5840
  this.dispatch(deleteFormSubmission(id));
5928
- this.dispatch(addActiveProjectFormSubmissionsCount(-1));
5929
5841
  this.dispatch(deleteFormSubmissionAttachments(submissionAttachments.map((x) => x.offline_id)));
5930
5842
  try {
5931
5843
  return await this.enqueueRequest({
@@ -5936,7 +5848,6 @@ class FormSubmissionService extends BaseUploadService {
5936
5848
  blocks: []
5937
5849
  });
5938
5850
  } catch (e) {
5939
- this.dispatch(addActiveProjectFormSubmissionsCount(1));
5940
5851
  this.dispatch(addFormSubmission(submissionToBeDeleted));
5941
5852
  this.dispatch(addFormSubmissionAttachments(submissionAttachments));
5942
5853
  throw e;
@@ -6813,15 +6724,14 @@ class DocumentAttachmentService extends BaseAttachmentService {
6813
6724
  }
6814
6725
  }
6815
6726
  class AgentService extends BaseApiService {
6816
- async startConversation(prompt) {
6817
- const activeProjectId = this.client.store.getState().projectReducer.activeProjectId;
6727
+ async startConversation(prompt, projectId) {
6818
6728
  return this.enqueueRequest({
6819
6729
  description: "Start agent conversation",
6820
6730
  method: HttpMethod.POST,
6821
6731
  url: "/agents/prompt/",
6822
6732
  payload: {
6823
6733
  prompt,
6824
- active_project: activeProjectId
6734
+ active_project: projectId
6825
6735
  },
6826
6736
  blockers: ["prompt"],
6827
6737
  blocks: ["prompt"]
@@ -6830,21 +6740,14 @@ class AgentService extends BaseApiService {
6830
6740
  return response;
6831
6741
  });
6832
6742
  }
6833
- /**
6834
- * Prompt the agent with a message.
6835
- * @param prompt The message to prompt the agent with.
6836
- * @param conversationId If continuing an existing message, the UUID of that conversation.
6837
- */
6838
- async continueConversation(prompt, conversationId) {
6839
- const { store } = this.client;
6840
- const activeProjectId = store.getState().projectReducer.activeProjectId;
6743
+ async continueConversation(prompt, conversationId, projectId) {
6841
6744
  return this.enqueueRequest({
6842
6745
  description: "Prompt agent",
6843
6746
  method: HttpMethod.POST,
6844
6747
  url: "/agents/prompt/",
6845
6748
  payload: {
6846
6749
  prompt,
6847
- active_project: activeProjectId
6750
+ active_project: projectId
6848
6751
  },
6849
6752
  blockers: ["prompt"],
6850
6753
  blocks: ["prompt"],
@@ -7348,8 +7251,6 @@ export {
7348
7251
  _selectLatestFormRevision,
7349
7252
  _setLatestRetryTime,
7350
7253
  acceptProjectInvite,
7351
- addActiveProjectFormSubmissionsCount,
7352
- addActiveProjectIssuesCount,
7353
7254
  addAsset,
7354
7255
  addAssetAttachment,
7355
7256
  addAssetAttachments,
@@ -7392,11 +7293,10 @@ export {
7392
7293
  addIssueUpdates,
7393
7294
  addIssues,
7394
7295
  addLicenses,
7395
- addOrReplaceProjectFile,
7396
- addOrReplaceProjectFiles,
7397
- addOrReplaceProjects,
7398
7296
  addProjectAttachment,
7399
7297
  addProjectAttachments,
7298
+ addProjectFile,
7299
+ addProjectFiles,
7400
7300
  addTeam,
7401
7301
  addUsers,
7402
7302
  addWorkspace,
@@ -7470,6 +7370,8 @@ export {
7470
7370
  deleteProjectAccesses,
7471
7371
  deleteProjectAttachment,
7472
7372
  deleteProjectAttachments,
7373
+ deleteProjectFile,
7374
+ deleteProjectFiles,
7473
7375
  deleteTeam,
7474
7376
  deleteWorkspace,
7475
7377
  dequeue,
@@ -7537,6 +7439,7 @@ export {
7537
7439
  initializeOrganizationAccesses,
7538
7440
  initializeProjectAccesses,
7539
7441
  initializeProjectAttachments,
7442
+ initializeProjectFiles,
7540
7443
  initializeTeams,
7541
7444
  initializeWorkspaces,
7542
7445
  isToday,
@@ -7585,8 +7488,6 @@ export {
7585
7488
  rehydratedSlice,
7586
7489
  removeDocuments,
7587
7490
  removeIssueType,
7588
- removeProjectFile,
7589
- removeProjectFilesOfProject,
7590
7491
  removeUser,
7591
7492
  resetProjectFileObjectUrls,
7592
7493
  resetStore,
@@ -7594,10 +7495,7 @@ export {
7594
7495
  saveActiveProjectFileBounds,
7595
7496
  selectAccessToken,
7596
7497
  selectActiveOrganizationAccess,
7597
- selectActiveProject,
7598
- selectActiveProjectAccess,
7599
7498
  selectActiveProjectFileId,
7600
- selectActiveProjectId,
7601
7499
  selectActiveStatusLicenses,
7602
7500
  selectAllDocumentAttachments,
7603
7501
  selectAllProjectAttachments,
@@ -7770,7 +7668,6 @@ export {
7770
7668
  selectWorkspaceMapping,
7771
7669
  selectWorkspaces,
7772
7670
  setActiveProjectFileId,
7773
- setActiveProjectId,
7774
7671
  setAsset,
7775
7672
  setAssetAttachment,
7776
7673
  setAssetAttachments,
@@ -7810,6 +7707,8 @@ export {
7810
7707
  setProfilePicture,
7811
7708
  setProjectAttachment,
7812
7709
  setProjectAttachments,
7710
+ setProjectFile,
7711
+ setProjectFiles,
7813
7712
  setProjects,
7814
7713
  setRehydrated,
7815
7714
  setTeam,
@@ -7859,11 +7758,13 @@ export {
7859
7758
  updateIssueAttachments,
7860
7759
  updateIssueType,
7861
7760
  updateLicense,
7862
- updateOrCreateProject,
7863
7761
  updateOrganizationAccess,
7762
+ updateProject,
7864
7763
  updateProjectAccess,
7865
7764
  updateProjectAttachment,
7866
7765
  updateProjectAttachments,
7766
+ updateProjectFile,
7767
+ updateProjectFiles,
7867
7768
  updateTeam,
7868
7769
  updateWorkspace,
7869
7770
  userReducer,