@overmap-ai/core 1.0.48-fix-agent-errors.4 → 1.0.48-form-submission-view.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,7 +8,7 @@ var _a;
8
8
  import * as React from "react";
9
9
  import React__default, { useState, useEffect, useRef, memo, useMemo, useCallback, createContext, createElement, useContext, forwardRef, Children, isValidElement, cloneElement, Fragment as Fragment$1, useLayoutEffect, useReducer, lazy, Suspense } from "react";
10
10
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
11
- import { unsafeShowToast, AlertDialogProvider, ToastProvider, DefaultTheme, Flex as Flex$1, IconButton, RiIcon, Text as Text$1, useSeverityColor, Checkbox, TextArea, Select, useToast, Badge, MultiSelect, useViewportSize, Overlay, ButtonGroup, Spinner, IconColorUtility, Tooltip, Popover, useSize, ToggleButton, Separator, OvermapItem, Button, ButtonList, divButtonProps, DropdownItemMenu, Input, useAlertDialog } from "@overmap-ai/blocks";
11
+ import { unsafeShowToast, AlertDialogProvider, ToastProvider, DefaultTheme, Flex as Flex$1, IconButton, RiIcon, Text as Text$1, useSeverityColor, Checkbox, TextArea, Select, useToast, Badge, MultiSelect, useViewportSize, Overlay, ButtonGroup, Spinner, IconColorUtility, Tooltip, Popover, useSize, ToggleButton, Separator, OvermapItem, Button, ButtonList, divButtonProps, OvermapDropdownMenu, Input, useAlertDialog } from "@overmap-ai/blocks";
12
12
  import { DepGraph } from "dependency-graph";
13
13
  import { offline as offline$1 } from "@redux-offline/redux-offline";
14
14
  import offlineConfig from "@redux-offline/redux-offline/lib/defaults";
@@ -1610,6 +1610,7 @@ const selectComponents = (state) => {
1610
1610
  }
1611
1611
  return prevComponents;
1612
1612
  };
1613
+ const selectComponentsMapping = (state) => state.componentReducer.components;
1613
1614
  const selectComponentsFromComponentType = (componentTypeId) => (state) => {
1614
1615
  if (!componentTypeId)
1615
1616
  return [];
@@ -1640,16 +1641,14 @@ const selectComponentTypeFromComponents = (state) => {
1640
1641
  }
1641
1642
  return ret;
1642
1643
  };
1643
- const selectComponentsByType = (componentTypeId) => (state) => {
1644
- const components = state.componentReducer.components;
1645
- const componentsOfType = [];
1646
- for (const component of Object.values(components)) {
1647
- if (component.component_type === componentTypeId) {
1648
- componentsOfType.push(component);
1644
+ const selectComponentsByType = restructureCreateSelectorWithArgs(
1645
+ createSelector(
1646
+ [selectComponents, (_state, componentTypeId) => componentTypeId],
1647
+ (components, componentTypeId) => {
1648
+ return components.filter((component) => component.component_type === componentTypeId);
1649
1649
  }
1650
- }
1651
- return componentsOfType;
1652
- };
1650
+ )
1651
+ );
1653
1652
  const selectNumberOfComponentsOfComponentType = (componentTypeId) => (state) => {
1654
1653
  var _a2;
1655
1654
  if (!componentTypeId)
@@ -1807,6 +1806,11 @@ const componentStageSlice = createSlice({
1807
1806
  }
1808
1807
  });
1809
1808
  const selectStageMapping = (state) => state.componentStageReducer.stages;
1809
+ const selectStage = restructureCreateSelectorWithArgs(
1810
+ createSelector([selectStageMapping, (_state, stageId) => stageId], (stageMapping, stageId) => {
1811
+ return stageMapping[stageId];
1812
+ })
1813
+ );
1810
1814
  const selectStages = createSelector(
1811
1815
  [selectStageMapping],
1812
1816
  (stageMapping) => {
@@ -1834,6 +1838,20 @@ const selectStagesFromComponentTypeIds = restructureCreateSelectorWithArgs(
1834
1838
  }
1835
1839
  )
1836
1840
  );
1841
+ const selectComponentTypeStagesMapping = restructureCreateSelectorWithArgs(
1842
+ createSelector(
1843
+ [selectStageMapping, (_state, componentTypeId) => componentTypeId],
1844
+ (stagesMapping, componentTypeId) => {
1845
+ const stagesMappingCopy = { ...stagesMapping };
1846
+ for (const stage in stagesMappingCopy) {
1847
+ if (stagesMappingCopy[stage].component_type !== componentTypeId) {
1848
+ delete stagesMappingCopy[stage];
1849
+ }
1850
+ }
1851
+ return stagesMappingCopy;
1852
+ }
1853
+ )
1854
+ );
1837
1855
  const selectStagesFromComponentType = restructureCreateSelectorWithArgs(
1838
1856
  createSelector(
1839
1857
  [selectStages, (_state, componentTypeId) => componentTypeId],
@@ -2047,6 +2065,7 @@ const initialState$g = {
2047
2065
  issues: {},
2048
2066
  attachments: {},
2049
2067
  comments: {},
2068
+ updates: {},
2050
2069
  visibleStatuses: [IssueStatus.BACKLOG, IssueStatus.SELECTED],
2051
2070
  visibleUserIds: null,
2052
2071
  recentIssueIds: [],
@@ -2068,6 +2087,16 @@ const issueSlice = createSlice({
2068
2087
  });
2069
2088
  },
2070
2089
  setIssueAttachments: setAttachments,
2090
+ setIssueUpdates: (state, action) => {
2091
+ if (action.payload.filter(onlyUniqueOfflineIds).length !== action.payload.length) {
2092
+ throw new Error("Tried to use setIssues reducer with duplicate ID's");
2093
+ }
2094
+ const newUpdates = {};
2095
+ for (const update of action.payload) {
2096
+ newUpdates[update.offline_id] = update;
2097
+ }
2098
+ state.updates = newUpdates;
2099
+ },
2071
2100
  setActiveIssueId: (state, action) => {
2072
2101
  state.activeIssueId = action.payload;
2073
2102
  },
@@ -2079,6 +2108,17 @@ const issueSlice = createSlice({
2079
2108
  },
2080
2109
  addIssueAttachment: addAttachment,
2081
2110
  addIssueAttachments: addAttachments,
2111
+ addIssueUpdate: (state, action) => {
2112
+ if (action.payload.offline_id in state.updates) {
2113
+ throw new Error(`Tried to add duplicate issue update with offline_id: ${action.payload.offline_id}`);
2114
+ }
2115
+ state.updates[action.payload.offline_id] = action.payload;
2116
+ },
2117
+ addIssueUpdates: (state, action) => {
2118
+ for (const update of action.payload) {
2119
+ state.updates[update.offline_id] = update;
2120
+ }
2121
+ },
2082
2122
  updateIssue: (state, action) => {
2083
2123
  if (action.payload.offline_id in state.issues) {
2084
2124
  state.issues[action.payload.offline_id] = {
@@ -2098,6 +2138,18 @@ const issueSlice = createSlice({
2098
2138
  }
2099
2139
  },
2100
2140
  removeIssueAttachment: removeAttachment,
2141
+ removeIssueUpdate: (state, action) => {
2142
+ if (action.payload in state.updates) {
2143
+ delete state.updates[action.payload];
2144
+ } else {
2145
+ throw new Error(`Failed to remove issue update because offline_id doesn't exist: ${action.payload}`);
2146
+ }
2147
+ },
2148
+ removeIssueUpdates: (state, action) => {
2149
+ for (const updateId of action.payload) {
2150
+ delete state.updates[updateId];
2151
+ }
2152
+ },
2101
2153
  removeAttachmentsOfIssue: (state, action) => {
2102
2154
  const attachments = Object.values(state.attachments).filter((a) => a.issue === action.payload);
2103
2155
  for (const attachment of attachments) {
@@ -2110,20 +2162,55 @@ const issueSlice = createSlice({
2110
2162
  setVisibleUserIds: (state, action) => {
2111
2163
  state.visibleUserIds = [...new Set(action.payload)];
2112
2164
  },
2113
- setIssueComments: (state, action) => {
2165
+ // Comments
2166
+ addIssueComment: (state, action) => {
2167
+ if (action.payload.offline_id in state.comments) {
2168
+ throw new Error(
2169
+ `Tried to add issue comment with offline_id: ${action.payload.offline_id} that already exists`
2170
+ );
2171
+ }
2172
+ state.comments[action.payload.offline_id] = action.payload;
2173
+ },
2174
+ addIssueComments: (state, action) => {
2175
+ for (const comment of action.payload) {
2176
+ if (comment.offline_id in state.comments) {
2177
+ throw new Error(
2178
+ `Tried to add issue comment with offline_id: ${comment.offline_id} that already exists`
2179
+ );
2180
+ }
2181
+ }
2114
2182
  for (const comment of action.payload) {
2115
2183
  state.comments[comment.offline_id] = comment;
2116
2184
  }
2117
2185
  },
2186
+ setIssueComment: (state, action) => {
2187
+ state.comments[action.payload.offline_id] = action.payload;
2188
+ },
2189
+ setIssueComments: (state, action) => {
2190
+ const newComments = {};
2191
+ for (const comment of action.payload) {
2192
+ newComments[comment.offline_id] = comment;
2193
+ }
2194
+ state.comments = newComments;
2195
+ },
2118
2196
  addOrReplaceIssueComment: (state, action) => {
2119
2197
  state.comments[action.payload.offline_id] = action.payload;
2120
2198
  },
2121
2199
  removeIssueComment: (state, action) => {
2122
- if (action.payload in state.comments) {
2123
- delete state.comments[action.payload];
2124
- } else {
2200
+ if (!(action.payload in state.comments)) {
2125
2201
  throw new Error(`Failed to remove issue comment because ID doesn't exist: ${action.payload}`);
2126
2202
  }
2203
+ delete state.comments[action.payload];
2204
+ },
2205
+ removeIssueComments: (state, action) => {
2206
+ for (const commentId of action.payload) {
2207
+ if (!(commentId in state.comments)) {
2208
+ throw new Error(`Failed to remove issue comment because ID doesn't exist: ${commentId}`);
2209
+ }
2210
+ }
2211
+ for (const commentId of action.payload) {
2212
+ delete state.comments[commentId];
2213
+ }
2127
2214
  },
2128
2215
  cleanRecentIssues: (state) => {
2129
2216
  state.recentIssueIds = state.recentIssueIds.filter((recentIssue) => state.issues[recentIssue.offlineId]);
@@ -2154,23 +2241,33 @@ const {
2154
2241
  addIssueAttachment,
2155
2242
  addIssueAttachments,
2156
2243
  addIssue,
2244
+ addIssueUpdate,
2245
+ addIssueUpdates,
2157
2246
  addOrReplaceIssueComment,
2158
2247
  addToRecentIssues,
2159
2248
  cleanRecentIssues,
2160
2249
  removeIssueAttachment,
2161
2250
  removeAttachmentsOfIssue,
2162
2251
  removeIssue,
2163
- removeIssueComment,
2252
+ removeIssueUpdate,
2253
+ removeIssueUpdates,
2164
2254
  removeRecentIssue,
2165
2255
  resetRecentIssues,
2166
2256
  setActiveIssueId,
2167
2257
  setIssueAttachments,
2168
- setIssueComments,
2258
+ setIssueUpdates,
2169
2259
  setIssues,
2170
2260
  setVisibleStatuses,
2171
2261
  setVisibleUserIds,
2172
2262
  updateIssueAttachment,
2173
- updateIssue
2263
+ updateIssue,
2264
+ // Commments
2265
+ addIssueComment,
2266
+ addIssueComments,
2267
+ setIssueComment,
2268
+ setIssueComments,
2269
+ removeIssueComment,
2270
+ removeIssueComments
2174
2271
  } = issueSlice.actions;
2175
2272
  const selectIssueMapping = (state) => state.issueReducer.issues;
2176
2273
  const selectRecentIssueIds = (state) => state.issueReducer.recentIssueIds;
@@ -2241,6 +2338,12 @@ const selectCommentsOfIssue = restructureCreateSelectorWithArgs(
2241
2338
  return Object.values(commentMapping).filter((comment) => comment.issue === issueId);
2242
2339
  })
2243
2340
  );
2341
+ const selectIssueUpdateMapping = (state) => state.issueReducer.updates;
2342
+ const selectIssueUpdatesOfIssue = restructureCreateSelectorWithArgs(
2343
+ createSelector([selectIssueUpdateMapping, (_state, issueId) => issueId], (updates, issueId) => {
2344
+ return Object.values(updates).filter((update) => update.issue === issueId);
2345
+ })
2346
+ );
2244
2347
  const selectAttachmentsOfIssue = restructureCreateSelectorWithArgs(
2245
2348
  createSelector(
2246
2349
  [selectIssueAttachments, (_state, issueId) => issueId],
@@ -2449,6 +2552,16 @@ var OrganizationAccessLevel = /* @__PURE__ */ ((OrganizationAccessLevel2) => {
2449
2552
  OrganizationAccessLevel2[OrganizationAccessLevel2["ADMIN"] = 2] = "ADMIN";
2450
2553
  return OrganizationAccessLevel2;
2451
2554
  })(OrganizationAccessLevel || {});
2555
+ var IssueUpdateChange = /* @__PURE__ */ ((IssueUpdateChange2) => {
2556
+ IssueUpdateChange2["STATUS"] = "status";
2557
+ IssueUpdateChange2["PRIORITY"] = "priority";
2558
+ IssueUpdateChange2["CATEGORY"] = "category";
2559
+ IssueUpdateChange2["DESCRIPTION"] = "description";
2560
+ IssueUpdateChange2["TITLE"] = "title";
2561
+ IssueUpdateChange2["ASSIGNED_TO"] = "assigned_to";
2562
+ IssueUpdateChange2["DUE_DATE"] = "due_date";
2563
+ return IssueUpdateChange2;
2564
+ })(IssueUpdateChange || {});
2452
2565
  var ProjectType = /* @__PURE__ */ ((ProjectType2) => {
2453
2566
  ProjectType2[ProjectType2["PERSONAL"] = 0] = "PERSONAL";
2454
2567
  ProjectType2[ProjectType2["ORGANIZATION"] = 2] = "ORGANIZATION";
@@ -3551,6 +3664,14 @@ const selectUserForm = (formId2) => (state) => {
3551
3664
  return state.userFormReducer.userForms[formId2];
3552
3665
  };
3553
3666
  const selectSubmissionMapping = (state) => state.userFormReducer.submissions;
3667
+ const selectUserFormSubmission = restructureCreateSelectorWithArgs(
3668
+ createSelector(
3669
+ [selectSubmissionMapping, (_state, submissionId) => submissionId],
3670
+ (submissions, submissionId) => {
3671
+ return submissions[submissionId];
3672
+ }
3673
+ )
3674
+ );
3554
3675
  const selectSubmissions = createSelector([selectSubmissionMapping], (submissions) => Object.values(submissions));
3555
3676
  const selectRevisionMapping = (state) => state.userFormReducer.revisions;
3556
3677
  const selectRevisions = createSelector([selectRevisionMapping], (revisions) => Object.values(revisions));
@@ -3592,6 +3713,23 @@ const selectSubmissionsForComponent = restructureCreateSelectorWithArgs(
3592
3713
  }
3593
3714
  )
3594
3715
  );
3716
+ const selectComponentSubmissionMapping = createSelector(
3717
+ [selectSubmissionMapping, selectComponentsMapping],
3718
+ (submissions, components) => {
3719
+ var _a2;
3720
+ const componentSubmissionMapping = {};
3721
+ for (const componentId in components) {
3722
+ componentSubmissionMapping[componentId] = [];
3723
+ }
3724
+ for (const submissionId in submissions) {
3725
+ const submission = submissions[submissionId];
3726
+ if (submission.component) {
3727
+ (_a2 = componentSubmissionMapping[submission.component]) == null ? void 0 : _a2.push(submission);
3728
+ }
3729
+ }
3730
+ return componentSubmissionMapping;
3731
+ }
3732
+ );
3595
3733
  const selectUserFormMapping = (state) => {
3596
3734
  return state.userFormReducer.userForms;
3597
3735
  };
@@ -4251,10 +4389,20 @@ function runMiddleware(action) {
4251
4389
  var _a2;
4252
4390
  return (_a2 = allMiddleware[0]) == null ? void 0 : _a2.run(action);
4253
4391
  }
4254
- const discardStatuses = [400, 409, 403, 404];
4392
+ const discardStatuses = [400, 409, 403, 404, 405, 500];
4255
4393
  const statusMessages = {
4256
4394
  403: { title: "Forbidden", description: "You are not authorized to perform this action.", severity: "danger" },
4257
- 404: { title: "Not found", description: "The requested resource was not found.", severity: "danger" }
4395
+ 404: { title: "Not found", description: "The requested resource was not found.", severity: "danger" },
4396
+ 405: {
4397
+ title: "Not supported",
4398
+ description: "It's not you. It's us. Sorry for the inconvenience.",
4399
+ severity: "danger"
4400
+ },
4401
+ 500: {
4402
+ title: "Server error",
4403
+ description: "Our server seems to be experiencing problems at the moment. We have been alerted and will fix the problem as soon as possible.",
4404
+ severity: "danger"
4405
+ }
4258
4406
  };
4259
4407
  function discard(reason, action, retries = 0) {
4260
4408
  var _a2;
@@ -4427,7 +4575,7 @@ class AttachmentService extends BaseApiService {
4427
4575
  }
4428
4576
  // Attachments aren't models, so we use the OptimisticGenericResult type instead
4429
4577
  async addIssueAttachment(attachmentPayload) {
4430
- const { description: description2, issue, file_sha1, offline_id } = attachmentPayload;
4578
+ const { issue, file_sha1, offline_id } = attachmentPayload;
4431
4579
  if (!attachmentPayload.file.objectURL) {
4432
4580
  throw new Error("Expected attachmentPayload.file.objectURL to be defined.");
4433
4581
  }
@@ -4435,7 +4583,9 @@ class AttachmentService extends BaseApiService {
4435
4583
  ...attachmentPayload,
4436
4584
  file: attachmentPayload.file.objectURL,
4437
4585
  file_name: attachmentPayload.file.name,
4438
- file_type: attachmentPayload.file.type
4586
+ file_type: attachmentPayload.file.type,
4587
+ submitted_at: (/* @__PURE__ */ new Date()).toISOString(),
4588
+ created_by: this.client.store.getState().userReducer.currentUser.id
4439
4589
  };
4440
4590
  await this.client.files.addCache(attachmentPayload.file, file_sha1);
4441
4591
  this.client.store.dispatch(addIssueAttachment(offlineAttachment));
@@ -4447,10 +4597,7 @@ class AttachmentService extends BaseApiService {
4447
4597
  blocks: [offline_id, issue],
4448
4598
  blockers: [file_sha1],
4449
4599
  payload: {
4450
- offline_id,
4451
- issue,
4452
- description: description2 ?? "",
4453
- submitted_at: (/* @__PURE__ */ new Date()).getTime() / 1e3,
4600
+ ...offlineAttachment,
4454
4601
  ...fileProps
4455
4602
  }
4456
4603
  });
@@ -4461,7 +4608,7 @@ class AttachmentService extends BaseApiService {
4461
4608
  return [offlineAttachment, promise];
4462
4609
  }
4463
4610
  async addComponentAttachment(attachmentPayload) {
4464
- const { description: description2, component, file_sha1, offline_id } = attachmentPayload;
4611
+ const { component, file_sha1, offline_id } = attachmentPayload;
4465
4612
  if (!attachmentPayload.file.objectURL) {
4466
4613
  throw new Error("Expected attachmentPayload.file.objectURL to be defined.");
4467
4614
  }
@@ -4469,7 +4616,9 @@ class AttachmentService extends BaseApiService {
4469
4616
  ...attachmentPayload,
4470
4617
  file: attachmentPayload.file.objectURL,
4471
4618
  file_name: attachmentPayload.file.name,
4472
- file_type: attachmentPayload.file.type
4619
+ file_type: attachmentPayload.file.type,
4620
+ submitted_at: (/* @__PURE__ */ new Date()).toISOString(),
4621
+ created_by: this.client.store.getState().userReducer.currentUser.id
4473
4622
  };
4474
4623
  await this.client.files.addCache(attachmentPayload.file, file_sha1);
4475
4624
  this.client.store.dispatch(addComponentAttachment(offlineAttachment));
@@ -4481,10 +4630,7 @@ class AttachmentService extends BaseApiService {
4481
4630
  blocks: [offline_id, component],
4482
4631
  blockers: [file_sha1],
4483
4632
  payload: {
4484
- offline_id,
4485
- component,
4486
- description: description2 ?? "",
4487
- submitted_at: (/* @__PURE__ */ new Date()).getTime() / 1e3,
4633
+ ...offlineAttachment,
4488
4634
  ...fileProps
4489
4635
  }
4490
4636
  });
@@ -4495,7 +4641,7 @@ class AttachmentService extends BaseApiService {
4495
4641
  return [offlineAttachment, promise];
4496
4642
  }
4497
4643
  async addComponentTypeAttachment(attachmentPayload) {
4498
- const { description: description2, component_type, file_sha1, offline_id } = attachmentPayload;
4644
+ const { component_type, file_sha1, offline_id } = attachmentPayload;
4499
4645
  if (!attachmentPayload.file.objectURL) {
4500
4646
  throw new Error("Expected attachmentPayload.file.objectURL to be defined.");
4501
4647
  }
@@ -4503,7 +4649,9 @@ class AttachmentService extends BaseApiService {
4503
4649
  ...attachmentPayload,
4504
4650
  file: attachmentPayload.file.objectURL,
4505
4651
  file_name: attachmentPayload.file.name,
4506
- file_type: attachmentPayload.file.type
4652
+ file_type: attachmentPayload.file.type,
4653
+ submitted_at: (/* @__PURE__ */ new Date()).toISOString(),
4654
+ created_by: this.client.store.getState().userReducer.currentUser.id
4507
4655
  };
4508
4656
  await this.client.files.addCache(attachmentPayload.file, file_sha1);
4509
4657
  this.client.store.dispatch(addComponentTypeAttachment(offlineAttachment));
@@ -4515,10 +4663,7 @@ class AttachmentService extends BaseApiService {
4515
4663
  blocks: [offline_id, component_type],
4516
4664
  blockers: [file_sha1],
4517
4665
  payload: {
4518
- offline_id,
4519
- component_type,
4520
- description: description2 ?? "",
4521
- submitted_at: (/* @__PURE__ */ new Date()).getTime() / 1e3,
4666
+ ...offlineAttachment,
4522
4667
  ...fileProps
4523
4668
  }
4524
4669
  });
@@ -4537,7 +4682,9 @@ class AttachmentService extends BaseApiService {
4537
4682
  ...attachmentPayload,
4538
4683
  file: attachmentPayload.file.objectURL,
4539
4684
  file_name: attachmentPayload.file.name,
4540
- file_type: attachmentPayload.file.type
4685
+ file_type: attachmentPayload.file.type,
4686
+ submitted_at: (/* @__PURE__ */ new Date()).toISOString(),
4687
+ created_by: this.client.store.getState().userReducer.currentUser.id
4541
4688
  };
4542
4689
  await this.client.files.addCache(attachmentPayload.file, file_sha1);
4543
4690
  this.client.store.dispatch(addProjectAttachment(offlineAttachment));
@@ -4577,7 +4724,9 @@ class AttachmentService extends BaseApiService {
4577
4724
  file_name: file2.name,
4578
4725
  file_type: file2.type,
4579
4726
  issue: issueId,
4580
- file_sha1: hash
4727
+ file_sha1: hash,
4728
+ submitted_at: (/* @__PURE__ */ new Date()).toISOString(),
4729
+ created_by: this.client.store.getState().userReducer.currentUser.id
4581
4730
  });
4582
4731
  return this.addIssueAttachment(attachment);
4583
4732
  };
@@ -4596,7 +4745,9 @@ class AttachmentService extends BaseApiService {
4596
4745
  file_name: file2.name,
4597
4746
  file_type: file2.type,
4598
4747
  component: componentId,
4599
- file_sha1: hash
4748
+ file_sha1: hash,
4749
+ submitted_at: (/* @__PURE__ */ new Date()).toISOString(),
4750
+ created_by: this.client.store.getState().userReducer.currentUser.id
4600
4751
  });
4601
4752
  return this.addComponentAttachment(attachment);
4602
4753
  };
@@ -4615,7 +4766,9 @@ class AttachmentService extends BaseApiService {
4615
4766
  file_name: file2.name,
4616
4767
  file_type: file2.type,
4617
4768
  component_type: componentTypeId,
4618
- file_sha1: hash
4769
+ file_sha1: hash,
4770
+ submitted_at: (/* @__PURE__ */ new Date()).toISOString(),
4771
+ created_by: this.client.store.getState().userReducer.currentUser.id
4619
4772
  });
4620
4773
  return this.addComponentTypeAttachment(attachment);
4621
4774
  };
@@ -4634,7 +4787,9 @@ class AttachmentService extends BaseApiService {
4634
4787
  file_name: file2.name,
4635
4788
  file_type: file2.type,
4636
4789
  project: projectId,
4637
- file_sha1: hash
4790
+ file_sha1: hash,
4791
+ submitted_at: (/* @__PURE__ */ new Date()).toISOString(),
4792
+ created_by: this.client.store.getState().userReducer.currentUser.id
4638
4793
  });
4639
4794
  return this.addProjectAttachment(attachment);
4640
4795
  };
@@ -5711,49 +5866,35 @@ class ComponentTypeService extends BaseApiService {
5711
5866
  }
5712
5867
  }
5713
5868
  class IssueCommentService extends BaseApiService {
5869
+ // Omit author and submitted_at since these will always be set internally
5714
5870
  add(comment) {
5715
- const offlinePayload = offline(comment);
5716
- const submittedAt = (/* @__PURE__ */ new Date()).toISOString();
5717
5871
  const { store } = this.client;
5718
- const offlineComment = {
5719
- ...offlinePayload,
5872
+ const offlineComment = offline({
5873
+ ...comment,
5720
5874
  author: store.getState().userReducer.currentUser.id,
5721
- created_at: submittedAt
5722
- };
5723
- store.dispatch(addOrReplaceIssueComment(offlineComment));
5875
+ submitted_at: (/* @__PURE__ */ new Date()).toISOString()
5876
+ });
5877
+ store.dispatch(addIssueComment(offlineComment));
5724
5878
  const promise = this.enqueueRequest({
5725
5879
  description: `${truncate(comment.content, 80)}`,
5726
5880
  method: HttpMethod.POST,
5727
5881
  url: `/issues/${comment.issue}/comment/`,
5728
- payload: { ...offlinePayload, submitted_at: submittedAt },
5882
+ payload: offlineComment,
5729
5883
  blockers: [comment.issue],
5730
- blocks: [offlinePayload.offline_id]
5884
+ blocks: [offlineComment.offline_id]
5885
+ });
5886
+ promise.catch(() => {
5887
+ store.dispatch(removeIssueComment(offlineComment.offline_id));
5731
5888
  });
5732
5889
  return [offlineComment, promise];
5733
5890
  }
5734
- async refreshStore() {
5891
+ update(comment) {
5735
5892
  const { store } = this.client;
5736
- const result = await this.enqueueRequest({
5737
- description: "Get comments",
5738
- method: HttpMethod.GET,
5739
- // TODO: Choose between /issues/comments/in-project/${projectId}/ and /projects/${projectId}/issue-comments/
5740
- url: `/projects/${store.getState().projectReducer.activeProjectId}/comments/`,
5741
- blockers: [],
5742
- blocks: []
5743
- });
5744
- let filteredResult = result.filter(onlyUniqueOfflineIds);
5745
- filteredResult = filteredResult.map((comment) => {
5746
- return { ...comment };
5747
- });
5748
- if (result.length !== filteredResult.length) {
5749
- console.error(
5750
- `Received duplicate comments from the API (new length ${filteredResult.length}); filtered in browser.`
5751
- );
5893
+ const commentToUpdate = store.getState().issueReducer.comments[comment.offline_id];
5894
+ if (!commentToUpdate) {
5895
+ throw new Error(`Comment with offline_id ${comment.offline_id} not found in store`);
5752
5896
  }
5753
- store.dispatch(setIssueComments(filteredResult));
5754
- }
5755
- update(comment) {
5756
- this.client.store.dispatch(addOrReplaceIssueComment(comment));
5897
+ store.dispatch(setIssueComment(comment));
5757
5898
  const promise = this.enqueueRequest({
5758
5899
  description: `Edit comment: ${truncate(comment.content, 80)}`,
5759
5900
  method: HttpMethod.PATCH,
@@ -5762,17 +5903,62 @@ class IssueCommentService extends BaseApiService {
5762
5903
  blockers: [comment.issue],
5763
5904
  blocks: [comment.offline_id]
5764
5905
  });
5906
+ promise.catch(() => {
5907
+ store.dispatch(setIssueComment(commentToUpdate));
5908
+ });
5765
5909
  return [comment, promise];
5766
5910
  }
5767
5911
  remove(offline_id) {
5912
+ const commentToRemove = this.client.store.getState().issueReducer.comments[offline_id];
5913
+ if (!commentToRemove) {
5914
+ throw new Error(`Comment with offline_id ${offline_id} not found in store`);
5915
+ }
5768
5916
  this.client.store.dispatch(removeIssueComment(offline_id));
5769
- return this.enqueueRequest({
5917
+ const promise = this.enqueueRequest({
5770
5918
  description: "Delete comment",
5771
5919
  method: HttpMethod.DELETE,
5772
5920
  url: `/issues/comments/${offline_id}/`,
5773
5921
  blockers: [offline_id],
5774
5922
  blocks: []
5775
5923
  });
5924
+ promise.catch(() => {
5925
+ this.client.store.dispatch(addIssueComment(commentToRemove));
5926
+ });
5927
+ return promise;
5928
+ }
5929
+ async refreshStore() {
5930
+ const { store } = this.client;
5931
+ const result = await this.enqueueRequest({
5932
+ description: "Get comments",
5933
+ method: HttpMethod.GET,
5934
+ // TODO: Choose between /issues/comments/in-project/${projectId}/ and /projects/${projectId}/issue-comments/
5935
+ url: `/projects/${store.getState().projectReducer.activeProjectId}/comments/`,
5936
+ blockers: [],
5937
+ blocks: []
5938
+ });
5939
+ store.dispatch(setIssueComments(result));
5940
+ }
5941
+ }
5942
+ class IssueUpdateService extends BaseApiService {
5943
+ async refreshStore() {
5944
+ const { store } = this.client;
5945
+ const result = await this.enqueueRequest({
5946
+ description: "Get issue updates",
5947
+ method: HttpMethod.GET,
5948
+ url: `/projects/${store.getState().projectReducer.activeProjectId}/issues/updates/`,
5949
+ blockers: [],
5950
+ blocks: []
5951
+ });
5952
+ let filteredResult = result.filter(onlyUniqueOfflineIds);
5953
+ filteredResult = filteredResult.map((comment) => {
5954
+ return { ...comment };
5955
+ });
5956
+ if (result.length !== filteredResult.length) {
5957
+ console.error(
5958
+ `Received duplicate comments from the API (new length ${filteredResult.length}); filtered in browser.`
5959
+ );
5960
+ }
5961
+ store.dispatch(setIssueUpdates(filteredResult));
5776
5962
  }
5777
5963
  }
5778
5964
  class IssueService extends BaseApiService {
@@ -5853,7 +6039,83 @@ class IssueService extends BaseApiService {
5853
6039
  return [offlineIssues, promise];
5854
6040
  }
5855
6041
  update(issue) {
6042
+ const state = this.client.store.getState();
6043
+ const issueToBeUpdated = state.issueReducer.issues[issue.offline_id];
6044
+ if (!issueToBeUpdated) {
6045
+ throw new Error(
6046
+ `Attempting to update an issue with offline_id ${issue.offline_id} that doesn't exist in the store`
6047
+ );
6048
+ }
5856
6049
  this.client.store.dispatch(updateIssue(issue));
6050
+ const changes = {};
6051
+ for (const issueUpdateChange of [
6052
+ IssueUpdateChange.TITLE,
6053
+ IssueUpdateChange.DESCRIPTION,
6054
+ IssueUpdateChange.STATUS,
6055
+ IssueUpdateChange.CATEGORY,
6056
+ IssueUpdateChange.PRIORITY,
6057
+ IssueUpdateChange.ASSIGNED_TO,
6058
+ IssueUpdateChange.DUE_DATE
6059
+ ]) {
6060
+ if (issueUpdateChange in issue && issue[issueUpdateChange] !== issueToBeUpdated[issueUpdateChange]) {
6061
+ switch (issueUpdateChange) {
6062
+ case "category": {
6063
+ let categoryOrNull = null;
6064
+ const categoryIdOrNull = issue[issueUpdateChange];
6065
+ if (categoryIdOrNull) {
6066
+ categoryOrNull = state.categoryReducer.categories[categoryIdOrNull] ?? null;
6067
+ if (!categoryOrNull)
6068
+ throw new Error(
6069
+ `Trying to update issue category to ${categoryIdOrNull} which does not exist in store`
6070
+ );
6071
+ }
6072
+ changes[issueUpdateChange] = categoryOrNull ? {
6073
+ name: categoryOrNull.name,
6074
+ color: categoryOrNull.color,
6075
+ offline_id: categoryOrNull.offline_id
6076
+ } : null;
6077
+ break;
6078
+ }
6079
+ case "assigned_to": {
6080
+ let userOrNull = null;
6081
+ const userIdOrNull = issue[issueUpdateChange];
6082
+ if (userIdOrNull) {
6083
+ userOrNull = state.userReducer.users[userIdOrNull] ?? null;
6084
+ if (!userOrNull)
6085
+ throw new Error(
6086
+ `Trying to update issue assigned_to to ${userIdOrNull} which does not exist in store`
6087
+ );
6088
+ }
6089
+ changes[issueUpdateChange] = userOrNull ? {
6090
+ full_name: userOrNull.username,
6091
+ id: userOrNull.id
6092
+ } : null;
6093
+ break;
6094
+ }
6095
+ case "description":
6096
+ changes[issueUpdateChange] = issue[issueUpdateChange] ?? null;
6097
+ break;
6098
+ case "title":
6099
+ changes[issueUpdateChange] = issue[issueUpdateChange] ?? null;
6100
+ break;
6101
+ case "priority":
6102
+ changes[issueUpdateChange] = issue[issueUpdateChange];
6103
+ break;
6104
+ case "status":
6105
+ changes[issueUpdateChange] = issue[issueUpdateChange];
6106
+ break;
6107
+ case "due_date":
6108
+ changes[issueUpdateChange] = issue[issueUpdateChange] ? issue[issueUpdateChange] : null;
6109
+ }
6110
+ }
6111
+ }
6112
+ const offlineIssueUpdate = offline({
6113
+ created_by: state.userReducer.currentUser.id,
6114
+ submitted_at: (/* @__PURE__ */ new Date()).toISOString(),
6115
+ issue: issueToBeUpdated.offline_id,
6116
+ changes
6117
+ });
6118
+ this.client.store.dispatch(addIssueUpdate(offlineIssueUpdate));
5857
6119
  const promise = this.enqueueRequest({
5858
6120
  description: "Edit issue",
5859
6121
  method: HttpMethod.PATCH,
@@ -5862,23 +6124,30 @@ class IssueService extends BaseApiService {
5862
6124
  blockers: [issue.offline_id],
5863
6125
  blocks: [issue.offline_id]
5864
6126
  });
6127
+ promise.catch(() => {
6128
+ this.client.store.dispatch(updateIssue(issueToBeUpdated));
6129
+ this.client.store.dispatch(removeIssueUpdate(offlineIssueUpdate.offline_id));
6130
+ });
5865
6131
  const fullIssue = this.client.store.getState().issueReducer.issues[issue.offline_id];
5866
6132
  return [fullIssue, promise];
5867
6133
  }
5868
6134
  async remove(id) {
5869
6135
  const { store } = this.client;
5870
6136
  const state = store.getState();
6137
+ const dispatch = store.dispatch;
5871
6138
  const backup = state.issueReducer.issues[id];
5872
6139
  if (!backup) {
5873
6140
  throw new Error(`No issue with id ${id} found in the store`);
5874
6141
  }
5875
6142
  const attachments = Object.values(state.issueReducer.attachments).filter((a) => a.issue === id);
5876
6143
  const attachmentsOfIssue = selectAttachmentsOfIssue(id)(state);
5877
- this.client.store.dispatch(removeIssue(id));
5878
- store.dispatch(addActiveProjectIssuesCount(-1));
5879
- if (attachmentsOfIssue.length > 0) {
5880
- this.client.store.dispatch(removeAttachmentsOfIssue(id));
5881
- }
6144
+ const updatesOfIssue = selectIssueUpdatesOfIssue(id)(state);
6145
+ dispatch(removeIssue(id));
6146
+ dispatch(addActiveProjectIssuesCount(-1));
6147
+ if (attachmentsOfIssue.length > 0)
6148
+ dispatch(removeAttachmentsOfIssue(id));
6149
+ if (updatesOfIssue.length > 0)
6150
+ dispatch(removeIssueUpdates(updatesOfIssue.map(({ offline_id }) => offline_id)));
5882
6151
  try {
5883
6152
  return await this.enqueueRequest({
5884
6153
  description: "Delete issue",
@@ -5888,9 +6157,10 @@ class IssueService extends BaseApiService {
5888
6157
  blocks: []
5889
6158
  });
5890
6159
  } catch (e) {
5891
- this.client.store.dispatch(addIssue(backup));
5892
- this.client.store.dispatch(addIssueAttachments(attachments));
5893
- store.dispatch(addActiveProjectIssuesCount(1));
6160
+ dispatch(addIssue(backup));
6161
+ dispatch(addIssueAttachments(attachments));
6162
+ dispatch(addIssueUpdates(updatesOfIssue));
6163
+ dispatch(addActiveProjectIssuesCount(1));
5894
6164
  throw e;
5895
6165
  }
5896
6166
  }
@@ -6072,6 +6342,7 @@ class MainService extends BaseApiService {
6072
6342
  store.dispatch(setProjectAttachments(project_attachments));
6073
6343
  });
6074
6344
  void this.client.documents.refreshStore();
6345
+ void this.client.issueUpdates.refreshStore();
6075
6346
  }
6076
6347
  store.dispatch(setIsFetchingInitialData(false));
6077
6348
  if (overwrite) {
@@ -7499,7 +7770,7 @@ class AgentService extends BaseApiService {
7499
7770
  * @param request The message to prompt the agent with.
7500
7771
  * @param conversationId If continuing an existing message, the UUID of that conversation.
7501
7772
  */
7502
- prompt(request2, conversationId) {
7773
+ async prompt(request2, conversationId) {
7503
7774
  const activeProjectId = this.client.store.getState().projectReducer.activeProjectId;
7504
7775
  return this.enqueueRequest({
7505
7776
  description: "Prompt agent",
@@ -7514,6 +7785,16 @@ class AgentService extends BaseApiService {
7514
7785
  queryParams: conversationId ? { conversation_id: conversationId } : {}
7515
7786
  });
7516
7787
  }
7788
+ async rate(responseId, rating) {
7789
+ return this.enqueueRequest({
7790
+ description: "Rate agent response",
7791
+ method: HttpMethod.PUT,
7792
+ url: `/agents/responses/${responseId}/rate/`,
7793
+ payload: { rating },
7794
+ blockers: ["rate"],
7795
+ blocks: ["rate"]
7796
+ });
7797
+ }
7517
7798
  }
7518
7799
  class OvermapSDK {
7519
7800
  constructor(apiUrl, store) {
@@ -7529,6 +7810,7 @@ class OvermapSDK {
7529
7810
  __publicField(this, "organizationAccess", new OrganizationAccessService(this));
7530
7811
  __publicField(this, "issues", new IssueService(this));
7531
7812
  __publicField(this, "issueComments", new IssueCommentService(this));
7813
+ __publicField(this, "issueUpdates", new IssueUpdateService(this));
7532
7814
  __publicField(this, "workspaces", new WorkspaceService(this));
7533
7815
  __publicField(this, "main", new MainService(this));
7534
7816
  __publicField(this, "components", new ComponentService(this));
@@ -13002,52 +13284,54 @@ const styles$4 = {
13002
13284
  Footer,
13003
13285
  Loading
13004
13286
  };
13005
- const ImageCard = memo((props) => {
13006
- const { file, alt, error: error2, size, rightSlot, className, truncateLength, ...rest } = props;
13007
- const fileCardRef = useRef(null);
13008
- const imageInsetRef = useRef(null);
13009
- const fileCardSize = useSize(fileCardRef);
13010
- useLayoutEffect(() => {
13011
- if (!imageInsetRef.current || !fileCardSize)
13012
- return;
13013
- imageInsetRef.current.style.height = `${fileCardSize.height * 4}px`;
13014
- }, [fileCardSize]);
13015
- const fileName2 = useMemo(() => {
13016
- if (!file)
13017
- return;
13018
- return truncateLength !== void 0 ? truncate(file.name, truncateLength) : file.name;
13019
- }, [file, truncateLength]);
13020
- return /* @__PURE__ */ jsxs(
13021
- Flex,
13022
- {
13023
- className: classNames$1(className, styles$4.ImageCard),
13024
- width: "100%",
13025
- direction: "column",
13026
- position: "relative",
13027
- height: "max-content",
13028
- gap: "0",
13029
- ...rest,
13030
- children: [
13031
- !file && !error2 && /* @__PURE__ */ jsx(Flex, { width: "100%", height: "100%", align: "center", justify: "center", position: "absolute", children: /* @__PURE__ */ jsx(Spinner, {}) }),
13032
- /* @__PURE__ */ jsx(Inset, { className: styles$4.ImageInset, ref: imageInsetRef, clip: "padding-box", side: "y", pb: "0", children: file && !error2 && /* @__PURE__ */ jsx("img", { className: styles$4.Image, src: URL.createObjectURL(file), alt: alt ?? file.name }) }),
13033
- /* @__PURE__ */ jsx(
13034
- OvermapItem,
13035
- {
13036
- className: classNames$1(styles$4.Footer, {
13037
- [styles$4.Loading]: !file
13038
- }),
13039
- size,
13040
- ref: fileCardRef,
13041
- leftSlot: error2 ? /* @__PURE__ */ jsx(RiIcon, { icon: "RiFileWarningLine" }) : file && /* @__PURE__ */ jsx(FileIcon, { fileType: file.type }),
13042
- rightSlot,
13043
- children: error2 ?? fileName2
13044
- }
13045
- )
13046
- ]
13047
- }
13048
- );
13049
- });
13050
- ImageCard.displayName = "ImageCard";
13287
+ const ImageCard = memo(
13288
+ forwardRef((props, forwardedRef) => {
13289
+ const { file, alt, error: error2, size, rightSlot, className, truncateLength, ...rest } = props;
13290
+ const fileCardRef = useRef(null);
13291
+ const imageInsetRef = useRef(null);
13292
+ const fileCardSize = useSize(fileCardRef);
13293
+ useLayoutEffect(() => {
13294
+ if (!imageInsetRef.current || !fileCardSize)
13295
+ return;
13296
+ imageInsetRef.current.style.height = `${fileCardSize.height * 4}px`;
13297
+ }, [fileCardSize]);
13298
+ const fileName2 = useMemo(() => {
13299
+ if (!file)
13300
+ return;
13301
+ return truncateLength !== void 0 ? truncate(file.name, truncateLength) : file.name;
13302
+ }, [file, truncateLength]);
13303
+ return /* @__PURE__ */ jsxs(
13304
+ Flex,
13305
+ {
13306
+ className: classNames$1(className, styles$4.ImageCard),
13307
+ width: "100%",
13308
+ direction: "column",
13309
+ position: "relative",
13310
+ height: "max-content",
13311
+ gap: "0",
13312
+ ref: forwardedRef,
13313
+ ...rest,
13314
+ children: [
13315
+ !file && !error2 && /* @__PURE__ */ jsx(Flex, { width: "100%", height: "100%", align: "center", justify: "center", position: "absolute", children: /* @__PURE__ */ jsx(Spinner, {}) }),
13316
+ /* @__PURE__ */ jsx(Inset, { className: styles$4.ImageInset, ref: imageInsetRef, clip: "padding-box", side: "y", pb: "0", children: file && !error2 && /* @__PURE__ */ jsx("img", { className: styles$4.Image, src: URL.createObjectURL(file), alt: alt ?? file.name }) }),
13317
+ /* @__PURE__ */ jsx(
13318
+ OvermapItem,
13319
+ {
13320
+ className: classNames$1(styles$4.Footer, {
13321
+ [styles$4.Loading]: !file
13322
+ }),
13323
+ size,
13324
+ ref: fileCardRef,
13325
+ leftSlot: error2 ? /* @__PURE__ */ jsx(RiIcon, { icon: "RiFileWarningLine" }) : file && /* @__PURE__ */ jsx(FileIcon, { fileType: file.type }),
13326
+ rightSlot,
13327
+ children: error2 ?? fileName2
13328
+ }
13329
+ )
13330
+ ]
13331
+ }
13332
+ );
13333
+ })
13334
+ );
13051
13335
  const UploadInput = memo((props) => {
13052
13336
  var _a2;
13053
13337
  const [{ inputId, labelId, size, severity, helpText, showInputOnly, field, fieldProps }, rest] = useFormikInput(props);
@@ -14184,17 +14468,15 @@ const FieldActions = memo((props) => {
14184
14468
  Action.key
14185
14469
  )) }),
14186
14470
  /* @__PURE__ */ jsx(Box, { display: forMobile(true, "block"), children: /* @__PURE__ */ jsx(
14187
- DropdownItemMenu,
14471
+ OvermapDropdownMenu,
14188
14472
  {
14189
14473
  trigger: /* @__PURE__ */ jsx(IconButton, { variant: "ghost", "aria-label": "Actions menu", children: /* @__PURE__ */ jsx(RiIcon, { icon: "RiMore2Line" }) }),
14190
14474
  items: actions.map((Action) => {
14191
14475
  var _a2;
14192
14476
  return {
14193
- content: /* @__PURE__ */ jsxs(Flex$1, { gap: "2", align: "center", children: [
14194
- /* @__PURE__ */ jsx(Action.Icon, {}),
14195
- Action.text
14196
- ] }, Action.key),
14197
- onSelect: (_a2 = Action.buttonProps) == null ? void 0 : _a2.onClick
14477
+ leftSlot: /* @__PURE__ */ jsx(Action.Icon, {}),
14478
+ children: Action.text,
14479
+ onClick: (_a2 = Action.buttonProps) == null ? void 0 : _a2.onClick
14198
14480
  };
14199
14481
  })
14200
14482
  }
@@ -14252,10 +14534,8 @@ const useFieldTypeItems = (onSelect = () => null) => {
14252
14534
  const field = FieldTypeToClsMapping[identifier];
14253
14535
  const Icon = field.Icon;
14254
14536
  return {
14255
- content: /* @__PURE__ */ jsxs(Flex$1, { align: "center", gap: "2", children: [
14256
- /* @__PURE__ */ jsx(Icon, {}),
14257
- /* @__PURE__ */ jsx(Text$1, { children: field.fieldTypeName })
14258
- ] }, identifier),
14537
+ children: field.fieldTypeName,
14538
+ leftSlot: /* @__PURE__ */ jsx(Icon, {}),
14259
14539
  value: identifier,
14260
14540
  onSelect: () => {
14261
14541
  onSelect(identifier);
@@ -14459,7 +14739,7 @@ const FieldBuilder = memo((props) => {
14459
14739
  }
14460
14740
  ),
14461
14741
  /* @__PURE__ */ jsxs(Flex$1, { align: "center", gap: "3", children: [
14462
- /* @__PURE__ */ jsx(Badge, { className: styles.typeBadge, children: (_f = fieldTypeItems.flat().find((item) => item.value === type)) == null ? void 0 : _f.content }),
14742
+ /* @__PURE__ */ jsx(Badge, { className: styles.typeBadge, children: (_f = fieldTypeItems.flat().find((item) => item.value === type)) == null ? void 0 : _f.children }),
14463
14743
  showPopoverInputs && /* @__PURE__ */ jsx(FieldSettingsPopover, { popoverInputs, hasError: popoverHasErrors })
14464
14744
  ] }),
14465
14745
  resolvedImage && /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -14820,7 +15100,7 @@ const FieldSectionWithActions = memo((props) => {
14820
15100
  )),
14821
15101
  droppableProvided.placeholder,
14822
15102
  /* @__PURE__ */ jsx(
14823
- DropdownItemMenu,
15103
+ OvermapDropdownMenu,
14824
15104
  {
14825
15105
  trigger: /* @__PURE__ */ jsxs(Button, { type: "button", variant: "soft", children: [
14826
15106
  /* @__PURE__ */ jsx(RiIcon, { icon: "RiAddLine" }),
@@ -15256,6 +15536,8 @@ export {
15256
15536
  IssuePriority,
15257
15537
  IssueService,
15258
15538
  IssueStatus,
15539
+ IssueUpdateChange,
15540
+ IssueUpdateService,
15259
15541
  LicenseLevel,
15260
15542
  LicenseService,
15261
15543
  LicenseStatus,
@@ -15319,6 +15601,10 @@ export {
15319
15601
  addIssue,
15320
15602
  addIssueAttachment,
15321
15603
  addIssueAttachments,
15604
+ addIssueComment,
15605
+ addIssueComments,
15606
+ addIssueUpdate,
15607
+ addIssueUpdates,
15322
15608
  addLicenses,
15323
15609
  addOrReplaceCategories,
15324
15610
  addOrReplaceIssueComment,
@@ -15478,6 +15764,9 @@ export {
15478
15764
  removeIssue,
15479
15765
  removeIssueAttachment,
15480
15766
  removeIssueComment,
15767
+ removeIssueComments,
15768
+ removeIssueUpdate,
15769
+ removeIssueUpdates,
15481
15770
  removeOrganizationAccess,
15482
15771
  removeProjectAccess,
15483
15772
  removeProjectAccessesOfProject,
@@ -15539,11 +15828,13 @@ export {
15539
15828
  selectCompletedStages,
15540
15829
  selectComponent,
15541
15830
  selectComponentAttachmentMapping,
15831
+ selectComponentSubmissionMapping,
15542
15832
  selectComponentType,
15543
15833
  selectComponentTypeAttachmentMapping,
15544
15834
  selectComponentTypeForm,
15545
15835
  selectComponentTypeFromComponent,
15546
15836
  selectComponentTypeFromComponents,
15837
+ selectComponentTypeStagesMapping,
15547
15838
  selectComponentTypes,
15548
15839
  selectComponentTypesByName,
15549
15840
  selectComponentTypesFromIds,
@@ -15551,6 +15842,7 @@ export {
15551
15842
  selectComponents,
15552
15843
  selectComponentsByType,
15553
15844
  selectComponentsFromComponentType,
15845
+ selectComponentsMapping,
15554
15846
  selectCreateProjectType,
15555
15847
  selectCurrentUser,
15556
15848
  selectDeletedRequests,
@@ -15579,6 +15871,8 @@ export {
15579
15871
  selectIssueAttachmentMapping,
15580
15872
  selectIssueAttachments,
15581
15873
  selectIssueMapping,
15874
+ selectIssueUpdateMapping,
15875
+ selectIssueUpdatesOfIssue,
15582
15876
  selectIssues,
15583
15877
  selectLatestFormRevision,
15584
15878
  selectLatestRetryTime,
@@ -15630,6 +15924,7 @@ export {
15630
15924
  selectSortedOrganizationUsers,
15631
15925
  selectSortedProjectUsers,
15632
15926
  selectSortedProjects,
15927
+ selectStage,
15633
15928
  selectStageFormIdsFromStageIds,
15634
15929
  selectStageMapping,
15635
15930
  selectStages,
@@ -15645,6 +15940,7 @@ export {
15645
15940
  selectUser,
15646
15941
  selectUserForm,
15647
15942
  selectUserFormMapping,
15943
+ selectUserFormSubmission,
15648
15944
  selectUsersAsMapping,
15649
15945
  selectVisibleStatuses,
15650
15946
  selectVisibleUserIds,
@@ -15674,7 +15970,9 @@ export {
15674
15970
  setIsImportingProjectFile,
15675
15971
  setIsLoading,
15676
15972
  setIssueAttachments,
15973
+ setIssueComment,
15677
15974
  setIssueComments,
15975
+ setIssueUpdates,
15678
15976
  setIssues,
15679
15977
  setLicenses,
15680
15978
  setLoggedIn,