@overmap-ai/core 1.0.63-selector-standardization.1 → 1.0.63-selector-standardization.4

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 (37) hide show
  1. package/dist/overmap-core.js +143 -160
  2. package/dist/overmap-core.js.map +1 -1
  3. package/dist/overmap-core.umd.cjs +143 -160
  4. package/dist/overmap-core.umd.cjs.map +1 -1
  5. package/dist/sdk/services/AssetAttachmentService.d.ts +1 -1
  6. package/dist/sdk/services/AssetTypeAttachmentService.d.ts +1 -1
  7. package/dist/sdk/services/BaseAttachmentService.d.ts +1 -1
  8. package/dist/sdk/services/DocumentAttachmentService.d.ts +1 -1
  9. package/dist/sdk/services/IssueAttachmentService.d.ts +1 -1
  10. package/dist/sdk/services/ProjectAttachmentService.d.ts +1 -1
  11. package/dist/store/slices/assetAttachmentSlice.d.ts +1 -1
  12. package/dist/store/slices/assetSlice.d.ts +2 -3
  13. package/dist/store/slices/assetTypeAttachmentSlice.d.ts +1 -1
  14. package/dist/store/slices/assetTypeSlice.d.ts +3 -3
  15. package/dist/store/slices/categorySlice.d.ts +1 -1
  16. package/dist/store/slices/documentAttachmentSlice.d.ts +1 -1
  17. package/dist/store/slices/documentSlice.d.ts +1 -1
  18. package/dist/store/slices/fileSlice.d.ts +1 -1
  19. package/dist/store/slices/formRevisionSlice.d.ts +2 -2
  20. package/dist/store/slices/formSlice.d.ts +3 -3
  21. package/dist/store/slices/formSubmissionSlice.d.ts +1 -1
  22. package/dist/store/slices/issueAssociationSlice.d.ts +1 -1
  23. package/dist/store/slices/issueAttachmentSlice.d.ts +1 -1
  24. package/dist/store/slices/issueSlice.d.ts +1 -1
  25. package/dist/store/slices/issueTypeSlice.d.ts +1 -1
  26. package/dist/store/slices/licenseSlice.d.ts +1 -1
  27. package/dist/store/slices/organizationAccessSlice.d.ts +1 -1
  28. package/dist/store/slices/organizationSlice.d.ts +1 -1
  29. package/dist/store/slices/projectAccessSlice.d.ts +1 -1
  30. package/dist/store/slices/projectAttachmentSlice.d.ts +2 -2
  31. package/dist/store/slices/projectFileSlice.d.ts +1 -1
  32. package/dist/store/slices/projectSlice.d.ts +1 -1
  33. package/dist/store/slices/teamSlice.d.ts +1 -1
  34. package/dist/store/slices/userSlice.d.ts +2 -2
  35. package/dist/store/slices/workspaceSlice.d.ts +1 -1
  36. package/dist/typings/store.d.ts +1 -1
  37. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"overmap-core.umd.cjs","sources":["../src/enums/api.ts","../src/enums/issue.ts","../src/sdk/classes/OutboxCoordinator.ts","../src/sdk/errors.ts","../src/utils/async/DeferredPromise.ts","../node_modules/redux/es/redux.js","../src/store/migrations.ts","../src/store/slices/authSlice.ts","../src/utils/coordinates.ts","../src/utils/css.ts","../src/utils/file.ts","../src/utils/logging.ts","../src/utils/offline.ts","../src/utils/search.ts","../src/utils/string.ts","../src/utils/utils.ts","../src/utils/optimization.ts","../src/utils/colors.ts","../src/utils/date.ts","../src/store/adapter.ts","../src/store/slices/categorySlice.ts","../src/store/slices/assetStageSlice.ts","../src/store/slices/assetTypeSlice.ts","../src/store/slices/assetSlice.ts","../src/store/slices/assetAttachmentSlice.ts","../src/store/slices/assetStageCompletionSlice.ts","../src/store/slices/assetTypeAttachmentSlice.ts","../src/store/slices/workspaceSlice.ts","../src/store/slices/issueSlice.ts","../src/store/slices/issueTypeSlice.ts","../src/store/slices/fileSlice.ts","../src/typings/models/access.ts","../src/typings/models/attachments.ts","../src/typings/models/issues.ts","../src/typings/models/emailVerification.ts","../src/typings/models/license.ts","../src/store/slices/userSlice.ts","../src/store/slices/organizationAccessSlice.ts","../src/store/slices/licenseSlice.ts","../src/store/slices/projectAccessSlice.ts","../src/store/slices/projectSlice.ts","../src/store/slices/organizationSlice.ts","../src/store/slices/outboxSlice.ts","../src/store/slices/projectFileSlice.ts","../src/store/slices/projectAttachmentSlice.ts","../src/store/slices/rehydratedSlice.ts","../src/utils/forms.ts","../src/store/slices/formRevisionSlice.ts","../src/store/slices/formSlice.ts","../src/store/slices/formSubmissionSlice.ts","../src/store/slices/formSubmissionAttachmentSlice.ts","../src/store/slices/formRevisionAttachmentSlice.ts","../src/store/slices/emailDomainsSlice.ts","../src/store/slices/documentSlice.ts","../src/store/slices/documentAttachmentSlice.ts","../src/store/slices/teamSlice.ts","../src/store/slices/agentsSlice.ts","../src/store/slices/issueCommentSlice.ts","../src/store/slices/issueUpdateSlice.ts","../src/store/slices/issueAttachmentSlice.ts","../src/store/slices/versioningSlice.ts","../src/store/slices/geoImageSlice.ts","../src/store/slices/issueAssociationSlice.ts","../src/constants/ui.ts","../src/constants/defaults.ts","../src/constants/offline.ts","../src/sdk/globals.ts","../src/sdk/services/BaseService.ts","../src/store/store.ts","../src/sdk/base.ts","../src/sdk/sdk.ts","../src/sdk/services/BaseAuthService.ts","../src/sdk/services/JWTAuthService.ts","../src/sdk/services/BaseApiService.ts","../src/sdk/services/CategoryService.ts","../src/utils/array.ts","../src/sdk/services/AssetService.ts","../src/sdk/services/AssetStageCompletionService.ts","../src/sdk/services/AssetStageService.ts","../src/sdk/services/BaseUploadService.ts","../src/sdk/services/BaseAttachmentService.ts","../src/sdk/services/AssetAttachmentService.ts","../src/sdk/services/AssetTypeService.ts","../src/sdk/services/AssetTypeAttachmentService.ts","../src/sdk/services/IssueCommentService.ts","../src/sdk/services/IssueUpdateService.ts","../src/sdk/services/IssueAttachmentService.ts","../src/sdk/services/IssueService.ts","../src/sdk/services/IssueTypeService.ts","../src/sdk/services/ProjectAccessService.ts","../src/sdk/services/ProjectFileService.ts","../src/sdk/services/ProjectAttachmentService.ts","../src/sdk/services/ProjectService.ts","../src/sdk/services/FormService.ts","../src/sdk/services/FormSubmissionService.ts","../src/sdk/services/WorkspaceService.ts","../src/sdk/services/OrganizationAccessService.ts","../src/sdk/services/FileService.ts","../src/sdk/services/EmailVerificationService.ts","../src/sdk/services/EmailDomainsService.ts","../src/sdk/services/OrganizationService.ts","../src/sdk/services/LicenseService.ts","../src/sdk/services/DocumentService.ts","../src/sdk/services/DocumentAttachmentService.ts","../src/sdk/services/AgentService.ts","../src/sdk/services/TeamService.ts","../src/sdk/services/UserService.ts","../src/sdk/services/GeoImageService.ts","../src/sdk/services/IssueAssociationService.ts"],"sourcesContent":["export const enum HttpMethod {\n\tGET = \"GET\",\n\tPOST = \"POST\",\n\tPATCH = \"PATCH\",\n\tPUT = \"PUT\",\n\tDELETE = \"DELETE\",\n\t// TODO: Add support\n\t// OPTIONS = \"OPTIONS\",\n}\n","export enum IssuePriority {\n\tLOWEST = 0,\n\tLOW = 2,\n\tMEDIUM = 4,\n\tHIGH = 6,\n\tHIGHEST = 8,\n}\n\nexport enum IssueStatus {\n\tBACKLOG = 0,\n\tSELECTED = 2,\n\tDONE = 4,\n}\n","import { DepGraph } from \"dependency-graph\"\nimport type { FullOfflineAction } from \"../../store\"\nimport { Outbox } from \"@redux-offline/redux-offline/lib/types\"\n\n// TODO: Tests:\n// - Bulk-create components, then delete one of those components. Ensure the dependency to the bulk-create is found.\n\nexport class OutboxCoordinator {\n\tgraph: DepGraph<FullOfflineAction>\n\trequestAttemptCounter: Record<string, number>\n\n\tconstructor() {\n\t\tthis.graph = new DepGraph()\n\t\tthis.requestAttemptCounter = {}\n\t}\n\n\t/**\n\t * Used when the app is loaded. Reconstructs the dependency graph based on an outbox from the redux-offline store.\n\t */\n\tstatic _fromOutbox(outbox: Outbox): OutboxCoordinator {\n\t\tconst ret = new OutboxCoordinator()\n\n\t\tfor (let i = 0; i < outbox.length; i++) {\n\t\t\tconst outboxItem = outbox[i] as FullOfflineAction | undefined\n\t\t\tif (!outboxItem) {\n\t\t\t\tconsole.error(\"Outbox item was undefined\")\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tret.sneakRequest(outboxItem)\n\t\t\t// Add any dependencies to requests that were added before this one\n\t\t\tfor (let j = 0; j < i; j++) {\n\t\t\t\tconst previousOutboxItem = outbox[j] as FullOfflineAction | undefined\n\t\t\t\tif (!previousOutboxItem) {\n\t\t\t\t\tconsole.error(\"Previous outbox item was undefined\")\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (previousOutboxItem.payload.uuid === outboxItem.payload.uuid) {\n\t\t\t\t\tcontinue // Skip self\n\t\t\t\t}\n\t\t\t\tif (previousOutboxItem.payload.blocks.some((block) => outboxItem.payload.blockers.includes(block))) {\n\t\t\t\t\tOutboxCoordinator._addDependency(\n\t\t\t\t\t\toutboxItem.payload.uuid,\n\t\t\t\t\t\tpreviousOutboxItem.payload.uuid,\n\t\t\t\t\t\tret.graph,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn ret\n\t}\n\n\t_addDependency(from: string, to: string) {\n\t\tOutboxCoordinator._addDependency(from, to, this.graph)\n\t}\n\n\tstatic _addDependency(from: string, to: string, graph: DepGraph<FullOfflineAction>) {\n\t\tif (from === to) {\n\t\t\tthrow new Error(`Tried to add dependency from node to itself: ${from}`)\n\t\t}\n\t\tconst fromExists = graph.hasNode(from)\n\t\tif (!fromExists) {\n\t\t\tthrow new Error(`Tried to add dependency from non-existent node: ${from} (to node: ${to})`)\n\t\t}\n\t\tconst toExists = graph.hasNode(to)\n\t\tif (!toExists) {\n\t\t\tthrow new Error(`Tried to add dependency to non-existent node: ${to} (from node: ${from})`)\n\t\t}\n\t\tgraph.addDependency(from, to)\n\t}\n\n\t/**\n\t * If there are one or more nodes in the graph, we find all nodes that match a dependency of the request and add a\n\t * dependency from the new request node to that node.\n\t */\n\taddRequest(request: FullOfflineAction) {\n\t\tthis.graph.addNode(request.payload.uuid, request)\n\n\t\tif (request.payload.blockers.length === 0 || this.graph.size() === 1) {\n\t\t\t// The request has no dependencies, or there are no other nodes in the graph, so there are no dependencies\n\t\t\t// to create.\n\t\t\treturn\n\t\t}\n\n\t\t// Create dependencies according to the request's blockers\n\t\tfor (const node of this.graph.overallOrder()) {\n\t\t\tif (node === request.payload.uuid) continue // Skip the node we just added\n\t\t\tconst details = this.graph.getNodeData(node)\n\t\t\t// 1. Any node matching this request's offline_id\n\t\t\tif (request.payload.blockers.some((blocker) => details.payload.blocks.includes(blocker))) {\n\t\t\t\tthis._addDependency(request.payload.uuid, node)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Inserts a request at the beginning of the queue. This could be used for requests that were popped, then failed,\n\t * and need to be re-enqueued at the front of the queue. Any requests that were previously blocked by this request\n\t * will be blocked by this request again. No blockers will be added to this request because it is assumed that the\n\t * request was already unblocked when it was popped.\n\t * @param request The request to insert at the beginning of the queue.\n\t */\n\tinsertRequest(request: FullOfflineAction) {\n\t\tthis.graph.addNode(request.payload.uuid, request)\n\n\t\t// Create dependencies according to the request's blockers\n\t\tfor (const node of this.graph.overallOrder()) {\n\t\t\tif (node === request.payload.uuid) continue // Skip the request we just inserted\n\t\t\tconst details = this.graph.getNodeData(node)\n\t\t\t// 1. Any node matching this request's offline_id\n\t\t\tif (details.payload.blockers.some((blocker) => request.payload.blocks.includes(blocker))) {\n\t\t\t\tthis._addDependency(node, request.payload.uuid)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sneaks a request into the dependency graph without creating any blockers. Useful for reconstructing the graph\n\t * (from the offline store's outbox state) when the app is loaded.\n\t */\n\tsneakRequest(request: FullOfflineAction) {\n\t\tthis.graph.addNode(request.payload.uuid, request)\n\t}\n\n\t/**\n\t * Returns the next node in line to be sent. This is the unblocked node with the fewest number of attempts. If there\n\t * are multiple nodes with the same number of attempts, the first one (by insertion order) will be returned.\n\t */\n\t_getNextNode(): string | undefined {\n\t\tconst leafNodes = this.graph.overallOrder(true)\n\t\tlet minAttempts = Infinity\n\t\tlet minAttemptsNode: string | undefined\n\t\tfor (const node of leafNodes) {\n\t\t\tconst attempts = this.requestAttemptCounter[node] || 0\n\t\t\tif (attempts < minAttempts) {\n\t\t\t\tminAttempts = attempts\n\t\t\t\tminAttemptsNode = node\n\t\t\t}\n\t\t}\n\t\treturn minAttemptsNode\n\t}\n\n\t/**\n\t * Returns the next request in line to be sent without removing it.\n\t */\n\tpeek(): FullOfflineAction | undefined {\n\t\tconst nextNode = this._getNextNode()\n\t\tif (!nextNode) return undefined\n\t\treturn this.graph.getNodeData(nextNode)\n\t}\n\n\t/**\n\t * Removes a request from the graph. This should be called when a request is successfully sent.\n\t * @param uuid The UUID of the request to remove.\n\t */\n\tremove(uuid: string): void {\n\t\tthis.graph.removeNode(uuid)\n\t\tdelete this.requestAttemptCounter[uuid]\n\t}\n\n\t/**\n\t * Returns the next request in line to be sent and removes it from the graph.\n\t */\n\tpop(): FullOfflineAction | undefined {\n\t\tconst nextRequestDetails = this.peek()\n\t\tif (nextRequestDetails) {\n\t\t\tthis.graph.removeNode(nextRequestDetails.payload.uuid)\n\t\t}\n\t\treturn nextRequestDetails\n\t}\n\n\t/**\n\t * Gets the current queue for the outbox. Should be called to get a new value for the outbox slice every time a\n\t * request is enqueued. It will be used to render the outbox items in a single lane.\n\t */\n\tgetQueue(): FullOfflineAction[] {\n\t\tconst ret = this.graph.overallOrder().map((nodeName) => this.graph.getNodeData(nodeName))\n\n\t\t// We will return the normal overall order, except we put the request with the fewest number of attempts at the\n\t\t// front of the queue, assuming it is not blocked.\n\t\tconst nextNode = this._getNextNode()\n\t\tif (nextNode) {\n\t\t\tconst nextRequestDetails = this.graph.getNodeData(nextNode)\n\t\t\tconst nextRequestIndex = ret.findIndex(\n\t\t\t\t(request) => request.payload.uuid === nextRequestDetails.payload.uuid,\n\t\t\t)\n\t\t\tif (nextRequestIndex !== -1) {\n\t\t\t\tret.splice(nextRequestIndex, 1)\n\t\t\t\tret.unshift(nextRequestDetails)\n\t\t\t}\n\t\t}\n\n\t\treturn ret\n\t}\n\n\t/**\n\t * Gets a list of requests that can currently be sent (requests with no unresolved dependencies). Used to process\n\t * the next ready request in case the request at the front of the queue is failing.\n\t */\n\tgetReady(): FullOfflineAction[] {\n\t\tlet ret = this.graph.overallOrder(true).map((nodeName) => this.graph.getNodeData(nodeName))\n\t\t// First, order by insertion order\n\t\tret = ret.sort((a, b) => {\n\t\t\treturn a.meta.offline.effect.timestamp.localeCompare(b.meta.offline.effect.timestamp)\n\t\t})\n\t\t// Then, order by number of attempts\n\t\tret = ret.sort((a, b) => {\n\t\t\tconst aAttempts = this.requestAttemptCounter[a.payload.uuid] || 0\n\t\t\tconst bAttempts = this.requestAttemptCounter[b.payload.uuid] || 0\n\t\t\t// If these are equal, we want to keep the insertion order, which should be maintained from the previous\n\t\t\t// sort if we return 0.\n\t\t\treturn aAttempts - bAttempts\n\t\t})\n\t\treturn ret\n\t}\n\n\tregisterRetry(uuid: string): void {\n\t\tthis.requestAttemptCounter[uuid] = (this.requestAttemptCounter[uuid] || 0) + 1\n\t}\n}\n\n// TODO: Consider auto-discovering UUIDs instead of (or in addition to) explicitly passing them to `enqueueRequest`\n/**\n * Given a request, returns an array of discovered UUIDs referenced in the request.\n * Discovers UUIDs in the URL, body, and query string.\n * @param request\n */\n/*\nfunction _discoverUuids(request: RequestDetails): Set<string> {\n\t// We need to consider:\n\t// 1. Any UUID in the URL\n\t// 2. Any UUID in the body\n\t// 3. Any UUID in the query parameters\n\n\tconst ret = new Set<string>()\n\n\tfunction discoverUuidsInArray(values: unknown[]): void {\n\t\tfor (const value of values) {\n\t\t\tif (typeof value === \"string\" && value.length === 36 && UUID_REGEX.test(value)) {\n\t\t\t\tret.add(value)\n\t\t\t}\n\t\t}\n\t}\n\n\tconst urlParts = request.url.split(\"/\")\n\n\tdiscoverUuidsInArray(urlParts)\n\n\tif (request.payload) {\n\t\tdiscoverUuidsInArray(Object.values(request.payload))\n\t}\n\n\tif (request.queryParams) {\n\t\tdiscoverUuidsInArray(Object.values(request.queryParams))\n\t}\n\n\treturn ret\n}\n */\n","// Contains custom error classes used by the SDK\n\nimport request from \"superagent\"\n\nexport interface APIErrorOptions {\n\tresponse?: request.Response\n\tinnerError?: unknown // Most likely an Error\n\tmessage?: string\n\tdiscard?: boolean\n}\n\nconst UNKNOWN_ERROR_MESSAGE = \"An unknown error occurred\"\nconst MAX_ERROR_MESSAGE_LENGTH = 500\nconst _SPECIAL_KEYS = [\"non_field_errors\", \"detail\"]\n\n/**\n * Makes a best-effort attempt to extract an error message from a request.Response or an error object.\n * @param errorRes The response object from a request, if available\n * @param err The error object, if available\n */\nfunction extractErrorMessage(errorRes: request.Response | undefined, err: unknown): string | undefined {\n\tlet ret: string | undefined\n\tif (errorRes?.body) {\n\t\tif (typeof errorRes.body === \"object\") {\n\t\t\tconst responseBody = errorRes.body as {\n\t\t\t\terror?: string\n\t\t\t\tmessage?: string\n\t\t\t\tbody?: Record<string, string | string[]>\n\t\t\t}\n\t\t\tif (typeof responseBody.error === \"string\") {\n\t\t\t\tret = responseBody.error\n\t\t\t} else if (typeof responseBody.message === \"string\") {\n\t\t\t\tret = responseBody.message\n\t\t\t} else if (responseBody.body) {\n\t\t\t\t// The error message may be something like this:\n\t\t\t\t// \t\t{\n\t\t\t\t// \t\t\tname: [\"This name is already taken.\", \"This name is too short.\"],\n\t\t\t\t// \t\t\temail: \"This email is already taken\",\n\t\t\t\t//\t\t\tnon_field_errors: [\"This username is already taken.\"]\n\t\t\t\t// \t\t}\n\t\t\t\t// We want to convert this into:\n\t\t\t\t// \t\tName: This name is already taken.\n\t\t\t\t// \t\tName: This name is too short.\n\t\t\t\t// \t\tEmail: This email is already taken\n\t\t\t\t//\t\tThis username is already taken.\n\t\t\t\t// TODO: Support bold field names without using unsafe HTML\n\t\t\t\ttry {\n\t\t\t\t\tret = Object.entries(responseBody.body)\n\t\t\t\t\t\t.map(([key, value]) => {\n\t\t\t\t\t\t\tif (typeof value === \"string\") {\n\t\t\t\t\t\t\t\tif (_SPECIAL_KEYS.includes(key)) return value\n\t\t\t\t\t\t\t\treturn `${key}: ${value}`\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (Array.isArray(value)) {\n\t\t\t\t\t\t\t\tif (_SPECIAL_KEYS.includes(key)) return value.join(\"\\n\")\n\t\t\t\t\t\t\t\treturn value.map((v) => `${key}: ${v}`).join(\"\\n\")\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn `${key}: ${JSON.stringify(value)}`\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.join(\"\\n\")\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconsole.error(\"Failed to extract error message from response body\", e)\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (typeof errorRes.body === \"string\") {\n\t\t\tret = errorRes.body\n\t\t}\n\t} else if (errorRes?.text) {\n\t\tret = errorRes.text\n\t} else if (err instanceof Error) {\n\t\tret = err.message\n\t}\n\n\t// Check the length of the message. If it's too long, show a generic message instead.\n\t// This can happen if the backend returns a document instead of a JSON object.\n\tif (!ret || ret.length > MAX_ERROR_MESSAGE_LENGTH) {\n\t\treturn UNKNOWN_ERROR_MESSAGE\n\t}\n\treturn ret\n}\n\nexport class APIError extends Error {\n\t// NOTE: Needs to conform to NetworkError in @redux-offline/redux-offline, which has `status` and `response`.\n\tstatus: number\n\tresponse: request.Response | undefined\n\tmessage: string\n\toptions: APIErrorOptions\n\n\tconstructor(options: APIErrorOptions) {\n\t\tsuper(UNKNOWN_ERROR_MESSAGE)\n\t\tconst { response, innerError } = options\n\t\tthis.message = options.message ?? extractErrorMessage(response, innerError) ?? UNKNOWN_ERROR_MESSAGE\n\t\tthis.status = response?.status ?? 0\n\t\tthis.response = response\n\t\toptions.discard = options.discard ?? false\n\t\tthis.options = options\n\t}\n}\n","// https://gist.github.com/GFoley83/5877f6c09fbcfd62569c51dc91444cf0\n\n/**\n * A new instance of deferred is constructed by calling `new DeferredPromise<T>()`.\n * The purpose of the deferred object is to expose the associated Promise\n * instance APIs that can be used for signaling the successful\n * or unsuccessful completion, as well as the state of the task.\n * @export\n * @class DeferredPromise\n * @implements {Promise<T>}\n * @template T\n * @example\n * const deferred = new DeferredPromise<string>()\n * console.log(deferred.state) // \"pending\"\n *\n * deferred\n * .then(str => console.log(str))\n * .catch(err => console.error(err))\n *\n * deferred.resolve(\"Foo\")\n * console.log(deferred.state) // \"fulfilled\"\n * // deferred.reject(\"Bar\")\n */\nexport class DeferredPromise<T> implements Promise<T> {\n\t[Symbol.toStringTag] = \"Promise\"\n\n\tprivate _promise: Promise<T>\n\tprivate _resolve: null | ((value?: T | PromiseLike<T>) => void)\n\tprivate _reject: null | ((reason?: unknown) => void)\n\tprivate _state: \"pending\" | \"fulfilled\" | \"rejected\" = \"pending\"\n\n\tpublic get state(): \"pending\" | \"fulfilled\" | \"rejected\" {\n\t\treturn this._state\n\t}\n\n\tconstructor() {\n\t\tthis._resolve = null\n\t\tthis._reject = null\n\n\t\tthis._promise = new Promise<T>((resolve, reject) => {\n\t\t\tthis._resolve = resolve as (value?: T | PromiseLike<T>) => void\n\t\t\tthis._reject = reject\n\t\t})\n\t}\n\n\tpublic then<TResult1, TResult2>(\n\t\tonFulfilled?: (value: T) => TResult1 | PromiseLike<TResult1>,\n\t\tonRejected?: (reason: unknown) => TResult2 | PromiseLike<TResult2>,\n\t): Promise<TResult1 | TResult2> {\n\t\treturn this._promise.then(onFulfilled, onRejected)\n\t}\n\n\tpublic catch<TResult>(onRejected?: (reason: unknown) => TResult | PromiseLike<TResult>): Promise<T | TResult> {\n\t\treturn this._promise.catch(onRejected)\n\t}\n\n\tpublic resolve(value?: T | PromiseLike<T>): void {\n\t\tif (!this._resolve) throw new Error(\"No resolve callback\")\n\t\tthis._resolve(value)\n\t\tthis._state = \"fulfilled\"\n\t}\n\n\tpublic reject(reason?: unknown): void {\n\t\tif (!this._reject) throw reason\n\t\tthis._reject(reason)\n\t\tthis._state = \"rejected\"\n\t}\n\n\tpublic finally(_onFinally?: (() => void) | undefined | null): Promise<T> {\n\t\tthrow new Error(\"`finally` not implemented\")\n\t}\n}\n","import _objectSpread from '@babel/runtime/helpers/esm/objectSpread2';\n\n/**\n * Adapted from React: https://github.com/facebook/react/blob/master/packages/shared/formatProdErrorMessage.js\n *\n * Do not require this module directly! Use normal throw error calls. These messages will be replaced with error codes\n * during build.\n * @param {number} code\n */\nfunction formatProdErrorMessage(code) {\n return \"Minified Redux error #\" + code + \"; visit https://redux.js.org/Errors?code=\" + code + \" for the full message or \" + 'use the non-minified dev environment for full errors. ';\n}\n\n// Inlined version of the `symbol-observable` polyfill\nvar $$observable = (function () {\n return typeof Symbol === 'function' && Symbol.observable || '@@observable';\n})();\n\n/**\n * These are private action types reserved by Redux.\n * For any unknown actions, you must return the current state.\n * If the current state is undefined, you must return the initial state.\n * Do not reference these action types directly in your code.\n */\nvar randomString = function randomString() {\n return Math.random().toString(36).substring(7).split('').join('.');\n};\n\nvar ActionTypes = {\n INIT: \"@@redux/INIT\" + randomString(),\n REPLACE: \"@@redux/REPLACE\" + randomString(),\n PROBE_UNKNOWN_ACTION: function PROBE_UNKNOWN_ACTION() {\n return \"@@redux/PROBE_UNKNOWN_ACTION\" + randomString();\n }\n};\n\n/**\n * @param {any} obj The object to inspect.\n * @returns {boolean} True if the argument appears to be a plain object.\n */\nfunction isPlainObject(obj) {\n if (typeof obj !== 'object' || obj === null) return false;\n var proto = obj;\n\n while (Object.getPrototypeOf(proto) !== null) {\n proto = Object.getPrototypeOf(proto);\n }\n\n return Object.getPrototypeOf(obj) === proto;\n}\n\n// Inlined / shortened version of `kindOf` from https://github.com/jonschlinkert/kind-of\nfunction miniKindOf(val) {\n if (val === void 0) return 'undefined';\n if (val === null) return 'null';\n var type = typeof val;\n\n switch (type) {\n case 'boolean':\n case 'string':\n case 'number':\n case 'symbol':\n case 'function':\n {\n return type;\n }\n }\n\n if (Array.isArray(val)) return 'array';\n if (isDate(val)) return 'date';\n if (isError(val)) return 'error';\n var constructorName = ctorName(val);\n\n switch (constructorName) {\n case 'Symbol':\n case 'Promise':\n case 'WeakMap':\n case 'WeakSet':\n case 'Map':\n case 'Set':\n return constructorName;\n } // other\n\n\n return type.slice(8, -1).toLowerCase().replace(/\\s/g, '');\n}\n\nfunction ctorName(val) {\n return typeof val.constructor === 'function' ? val.constructor.name : null;\n}\n\nfunction isError(val) {\n return val instanceof Error || typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number';\n}\n\nfunction isDate(val) {\n if (val instanceof Date) return true;\n return typeof val.toDateString === 'function' && typeof val.getDate === 'function' && typeof val.setDate === 'function';\n}\n\nfunction kindOf(val) {\n var typeOfVal = typeof val;\n\n if (process.env.NODE_ENV !== 'production') {\n typeOfVal = miniKindOf(val);\n }\n\n return typeOfVal;\n}\n\n/**\n * @deprecated\n *\n * **We recommend using the `configureStore` method\n * of the `@reduxjs/toolkit` package**, which replaces `createStore`.\n *\n * Redux Toolkit is our recommended approach for writing Redux logic today,\n * including store setup, reducers, data fetching, and more.\n *\n * **For more details, please read this Redux docs page:**\n * **https://redux.js.org/introduction/why-rtk-is-redux-today**\n *\n * `configureStore` from Redux Toolkit is an improved version of `createStore` that\n * simplifies setup and helps avoid common bugs.\n *\n * You should not be using the `redux` core package by itself today, except for learning purposes.\n * The `createStore` method from the core `redux` package will not be removed, but we encourage\n * all users to migrate to using Redux Toolkit for all Redux code.\n *\n * If you want to use `createStore` without this visual deprecation warning, use\n * the `legacy_createStore` import instead:\n *\n * `import { legacy_createStore as createStore} from 'redux'`\n *\n */\n\nfunction createStore(reducer, preloadedState, enhancer) {\n var _ref2;\n\n if (typeof preloadedState === 'function' && typeof enhancer === 'function' || typeof enhancer === 'function' && typeof arguments[3] === 'function') {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(0) : 'It looks like you are passing several store enhancers to ' + 'createStore(). This is not supported. Instead, compose them ' + 'together to a single function. See https://redux.js.org/tutorials/fundamentals/part-4-store#creating-a-store-with-enhancers for an example.');\n }\n\n if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {\n enhancer = preloadedState;\n preloadedState = undefined;\n }\n\n if (typeof enhancer !== 'undefined') {\n if (typeof enhancer !== 'function') {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(1) : \"Expected the enhancer to be a function. Instead, received: '\" + kindOf(enhancer) + \"'\");\n }\n\n return enhancer(createStore)(reducer, preloadedState);\n }\n\n if (typeof reducer !== 'function') {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(2) : \"Expected the root reducer to be a function. Instead, received: '\" + kindOf(reducer) + \"'\");\n }\n\n var currentReducer = reducer;\n var currentState = preloadedState;\n var currentListeners = [];\n var nextListeners = currentListeners;\n var isDispatching = false;\n /**\n * This makes a shallow copy of currentListeners so we can use\n * nextListeners as a temporary list while dispatching.\n *\n * This prevents any bugs around consumers calling\n * subscribe/unsubscribe in the middle of a dispatch.\n */\n\n function ensureCanMutateNextListeners() {\n if (nextListeners === currentListeners) {\n nextListeners = currentListeners.slice();\n }\n }\n /**\n * Reads the state tree managed by the store.\n *\n * @returns {any} The current state tree of your application.\n */\n\n\n function getState() {\n if (isDispatching) {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(3) : 'You may not call store.getState() while the reducer is executing. ' + 'The reducer has already received the state as an argument. ' + 'Pass it down from the top reducer instead of reading it from the store.');\n }\n\n return currentState;\n }\n /**\n * Adds a change listener. It will be called any time an action is dispatched,\n * and some part of the state tree may potentially have changed. You may then\n * call `getState()` to read the current state tree inside the callback.\n *\n * You may call `dispatch()` from a change listener, with the following\n * caveats:\n *\n * 1. The subscriptions are snapshotted just before every `dispatch()` call.\n * If you subscribe or unsubscribe while the listeners are being invoked, this\n * will not have any effect on the `dispatch()` that is currently in progress.\n * However, the next `dispatch()` call, whether nested or not, will use a more\n * recent snapshot of the subscription list.\n *\n * 2. The listener should not expect to see all state changes, as the state\n * might have been updated multiple times during a nested `dispatch()` before\n * the listener is called. It is, however, guaranteed that all subscribers\n * registered before the `dispatch()` started will be called with the latest\n * state by the time it exits.\n *\n * @param {Function} listener A callback to be invoked on every dispatch.\n * @returns {Function} A function to remove this change listener.\n */\n\n\n function subscribe(listener) {\n if (typeof listener !== 'function') {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(4) : \"Expected the listener to be a function. Instead, received: '\" + kindOf(listener) + \"'\");\n }\n\n if (isDispatching) {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(5) : 'You may not call store.subscribe() while the reducer is executing. ' + 'If you would like to be notified after the store has been updated, subscribe from a ' + 'component and invoke store.getState() in the callback to access the latest state. ' + 'See https://redux.js.org/api/store#subscribelistener for more details.');\n }\n\n var isSubscribed = true;\n ensureCanMutateNextListeners();\n nextListeners.push(listener);\n return function unsubscribe() {\n if (!isSubscribed) {\n return;\n }\n\n if (isDispatching) {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(6) : 'You may not unsubscribe from a store listener while the reducer is executing. ' + 'See https://redux.js.org/api/store#subscribelistener for more details.');\n }\n\n isSubscribed = false;\n ensureCanMutateNextListeners();\n var index = nextListeners.indexOf(listener);\n nextListeners.splice(index, 1);\n currentListeners = null;\n };\n }\n /**\n * Dispatches an action. It is the only way to trigger a state change.\n *\n * The `reducer` function, used to create the store, will be called with the\n * current state tree and the given `action`. Its return value will\n * be considered the **next** state of the tree, and the change listeners\n * will be notified.\n *\n * The base implementation only supports plain object actions. If you want to\n * dispatch a Promise, an Observable, a thunk, or something else, you need to\n * wrap your store creating function into the corresponding middleware. For\n * example, see the documentation for the `redux-thunk` package. Even the\n * middleware will eventually dispatch plain object actions using this method.\n *\n * @param {Object} action A plain object representing “what changed”. It is\n * a good idea to keep actions serializable so you can record and replay user\n * sessions, or use the time travelling `redux-devtools`. An action must have\n * a `type` property which may not be `undefined`. It is a good idea to use\n * string constants for action types.\n *\n * @returns {Object} For convenience, the same action object you dispatched.\n *\n * Note that, if you use a custom middleware, it may wrap `dispatch()` to\n * return something else (for example, a Promise you can await).\n */\n\n\n function dispatch(action) {\n if (!isPlainObject(action)) {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(7) : \"Actions must be plain objects. Instead, the actual type was: '\" + kindOf(action) + \"'. You may need to add middleware to your store setup to handle dispatching other values, such as 'redux-thunk' to handle dispatching functions. See https://redux.js.org/tutorials/fundamentals/part-4-store#middleware and https://redux.js.org/tutorials/fundamentals/part-6-async-logic#using-the-redux-thunk-middleware for examples.\");\n }\n\n if (typeof action.type === 'undefined') {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(8) : 'Actions may not have an undefined \"type\" property. You may have misspelled an action type string constant.');\n }\n\n if (isDispatching) {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(9) : 'Reducers may not dispatch actions.');\n }\n\n try {\n isDispatching = true;\n currentState = currentReducer(currentState, action);\n } finally {\n isDispatching = false;\n }\n\n var listeners = currentListeners = nextListeners;\n\n for (var i = 0; i < listeners.length; i++) {\n var listener = listeners[i];\n listener();\n }\n\n return action;\n }\n /**\n * Replaces the reducer currently used by the store to calculate the state.\n *\n * You might need this if your app implements code splitting and you want to\n * load some of the reducers dynamically. You might also need this if you\n * implement a hot reloading mechanism for Redux.\n *\n * @param {Function} nextReducer The reducer for the store to use instead.\n * @returns {void}\n */\n\n\n function replaceReducer(nextReducer) {\n if (typeof nextReducer !== 'function') {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(10) : \"Expected the nextReducer to be a function. Instead, received: '\" + kindOf(nextReducer));\n }\n\n currentReducer = nextReducer; // This action has a similiar effect to ActionTypes.INIT.\n // Any reducers that existed in both the new and old rootReducer\n // will receive the previous state. This effectively populates\n // the new state tree with any relevant data from the old one.\n\n dispatch({\n type: ActionTypes.REPLACE\n });\n }\n /**\n * Interoperability point for observable/reactive libraries.\n * @returns {observable} A minimal observable of state changes.\n * For more information, see the observable proposal:\n * https://github.com/tc39/proposal-observable\n */\n\n\n function observable() {\n var _ref;\n\n var outerSubscribe = subscribe;\n return _ref = {\n /**\n * The minimal observable subscription method.\n * @param {Object} observer Any object that can be used as an observer.\n * The observer object should have a `next` method.\n * @returns {subscription} An object with an `unsubscribe` method that can\n * be used to unsubscribe the observable from the store, and prevent further\n * emission of values from the observable.\n */\n subscribe: function subscribe(observer) {\n if (typeof observer !== 'object' || observer === null) {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(11) : \"Expected the observer to be an object. Instead, received: '\" + kindOf(observer) + \"'\");\n }\n\n function observeState() {\n if (observer.next) {\n observer.next(getState());\n }\n }\n\n observeState();\n var unsubscribe = outerSubscribe(observeState);\n return {\n unsubscribe: unsubscribe\n };\n }\n }, _ref[$$observable] = function () {\n return this;\n }, _ref;\n } // When a store is created, an \"INIT\" action is dispatched so that every\n // reducer returns their initial state. This effectively populates\n // the initial state tree.\n\n\n dispatch({\n type: ActionTypes.INIT\n });\n return _ref2 = {\n dispatch: dispatch,\n subscribe: subscribe,\n getState: getState,\n replaceReducer: replaceReducer\n }, _ref2[$$observable] = observable, _ref2;\n}\n/**\n * Creates a Redux store that holds the state tree.\n *\n * **We recommend using `configureStore` from the\n * `@reduxjs/toolkit` package**, which replaces `createStore`:\n * **https://redux.js.org/introduction/why-rtk-is-redux-today**\n *\n * The only way to change the data in the store is to call `dispatch()` on it.\n *\n * There should only be a single store in your app. To specify how different\n * parts of the state tree respond to actions, you may combine several reducers\n * into a single reducer function by using `combineReducers`.\n *\n * @param {Function} reducer A function that returns the next state tree, given\n * the current state tree and the action to handle.\n *\n * @param {any} [preloadedState] The initial state. You may optionally specify it\n * to hydrate the state from the server in universal apps, or to restore a\n * previously serialized user session.\n * If you use `combineReducers` to produce the root reducer function, this must be\n * an object with the same shape as `combineReducers` keys.\n *\n * @param {Function} [enhancer] The store enhancer. You may optionally specify it\n * to enhance the store with third-party capabilities such as middleware,\n * time travel, persistence, etc. The only store enhancer that ships with Redux\n * is `applyMiddleware()`.\n *\n * @returns {Store} A Redux store that lets you read the state, dispatch actions\n * and subscribe to changes.\n */\n\nvar legacy_createStore = createStore;\n\n/**\n * Prints a warning in the console if it exists.\n *\n * @param {String} message The warning message.\n * @returns {void}\n */\nfunction warning(message) {\n /* eslint-disable no-console */\n if (typeof console !== 'undefined' && typeof console.error === 'function') {\n console.error(message);\n }\n /* eslint-enable no-console */\n\n\n try {\n // This error was thrown as a convenience so that if you enable\n // \"break on all exceptions\" in your console,\n // it would pause the execution at this line.\n throw new Error(message);\n } catch (e) {} // eslint-disable-line no-empty\n\n}\n\nfunction getUnexpectedStateShapeWarningMessage(inputState, reducers, action, unexpectedKeyCache) {\n var reducerKeys = Object.keys(reducers);\n var argumentName = action && action.type === ActionTypes.INIT ? 'preloadedState argument passed to createStore' : 'previous state received by the reducer';\n\n if (reducerKeys.length === 0) {\n return 'Store does not have a valid reducer. Make sure the argument passed ' + 'to combineReducers is an object whose values are reducers.';\n }\n\n if (!isPlainObject(inputState)) {\n return \"The \" + argumentName + \" has unexpected type of \\\"\" + kindOf(inputState) + \"\\\". Expected argument to be an object with the following \" + (\"keys: \\\"\" + reducerKeys.join('\", \"') + \"\\\"\");\n }\n\n var unexpectedKeys = Object.keys(inputState).filter(function (key) {\n return !reducers.hasOwnProperty(key) && !unexpectedKeyCache[key];\n });\n unexpectedKeys.forEach(function (key) {\n unexpectedKeyCache[key] = true;\n });\n if (action && action.type === ActionTypes.REPLACE) return;\n\n if (unexpectedKeys.length > 0) {\n return \"Unexpected \" + (unexpectedKeys.length > 1 ? 'keys' : 'key') + \" \" + (\"\\\"\" + unexpectedKeys.join('\", \"') + \"\\\" found in \" + argumentName + \". \") + \"Expected to find one of the known reducer keys instead: \" + (\"\\\"\" + reducerKeys.join('\", \"') + \"\\\". Unexpected keys will be ignored.\");\n }\n}\n\nfunction assertReducerShape(reducers) {\n Object.keys(reducers).forEach(function (key) {\n var reducer = reducers[key];\n var initialState = reducer(undefined, {\n type: ActionTypes.INIT\n });\n\n if (typeof initialState === 'undefined') {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(12) : \"The slice reducer for key \\\"\" + key + \"\\\" returned undefined during initialization. \" + \"If the state passed to the reducer is undefined, you must \" + \"explicitly return the initial state. The initial state may \" + \"not be undefined. If you don't want to set a value for this reducer, \" + \"you can use null instead of undefined.\");\n }\n\n if (typeof reducer(undefined, {\n type: ActionTypes.PROBE_UNKNOWN_ACTION()\n }) === 'undefined') {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(13) : \"The slice reducer for key \\\"\" + key + \"\\\" returned undefined when probed with a random type. \" + (\"Don't try to handle '\" + ActionTypes.INIT + \"' or other actions in \\\"redux/*\\\" \") + \"namespace. They are considered private. Instead, you must return the \" + \"current state for any unknown actions, unless it is undefined, \" + \"in which case you must return the initial state, regardless of the \" + \"action type. The initial state may not be undefined, but can be null.\");\n }\n });\n}\n/**\n * Turns an object whose values are different reducer functions, into a single\n * reducer function. It will call every child reducer, and gather their results\n * into a single state object, whose keys correspond to the keys of the passed\n * reducer functions.\n *\n * @param {Object} reducers An object whose values correspond to different\n * reducer functions that need to be combined into one. One handy way to obtain\n * it is to use ES6 `import * as reducers` syntax. The reducers may never return\n * undefined for any action. Instead, they should return their initial state\n * if the state passed to them was undefined, and the current state for any\n * unrecognized action.\n *\n * @returns {Function} A reducer function that invokes every reducer inside the\n * passed object, and builds a state object with the same shape.\n */\n\n\nfunction combineReducers(reducers) {\n var reducerKeys = Object.keys(reducers);\n var finalReducers = {};\n\n for (var i = 0; i < reducerKeys.length; i++) {\n var key = reducerKeys[i];\n\n if (process.env.NODE_ENV !== 'production') {\n if (typeof reducers[key] === 'undefined') {\n warning(\"No reducer provided for key \\\"\" + key + \"\\\"\");\n }\n }\n\n if (typeof reducers[key] === 'function') {\n finalReducers[key] = reducers[key];\n }\n }\n\n var finalReducerKeys = Object.keys(finalReducers); // This is used to make sure we don't warn about the same\n // keys multiple times.\n\n var unexpectedKeyCache;\n\n if (process.env.NODE_ENV !== 'production') {\n unexpectedKeyCache = {};\n }\n\n var shapeAssertionError;\n\n try {\n assertReducerShape(finalReducers);\n } catch (e) {\n shapeAssertionError = e;\n }\n\n return function combination(state, action) {\n if (state === void 0) {\n state = {};\n }\n\n if (shapeAssertionError) {\n throw shapeAssertionError;\n }\n\n if (process.env.NODE_ENV !== 'production') {\n var warningMessage = getUnexpectedStateShapeWarningMessage(state, finalReducers, action, unexpectedKeyCache);\n\n if (warningMessage) {\n warning(warningMessage);\n }\n }\n\n var hasChanged = false;\n var nextState = {};\n\n for (var _i = 0; _i < finalReducerKeys.length; _i++) {\n var _key = finalReducerKeys[_i];\n var reducer = finalReducers[_key];\n var previousStateForKey = state[_key];\n var nextStateForKey = reducer(previousStateForKey, action);\n\n if (typeof nextStateForKey === 'undefined') {\n var actionType = action && action.type;\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(14) : \"When called with an action of type \" + (actionType ? \"\\\"\" + String(actionType) + \"\\\"\" : '(unknown type)') + \", the slice reducer for key \\\"\" + _key + \"\\\" returned undefined. \" + \"To ignore an action, you must explicitly return the previous state. \" + \"If you want this reducer to hold no value, you can return null instead of undefined.\");\n }\n\n nextState[_key] = nextStateForKey;\n hasChanged = hasChanged || nextStateForKey !== previousStateForKey;\n }\n\n hasChanged = hasChanged || finalReducerKeys.length !== Object.keys(state).length;\n return hasChanged ? nextState : state;\n };\n}\n\nfunction bindActionCreator(actionCreator, dispatch) {\n return function () {\n return dispatch(actionCreator.apply(this, arguments));\n };\n}\n/**\n * Turns an object whose values are action creators, into an object with the\n * same keys, but with every function wrapped into a `dispatch` call so they\n * may be invoked directly. This is just a convenience method, as you can call\n * `store.dispatch(MyActionCreators.doSomething())` yourself just fine.\n *\n * For convenience, you can also pass an action creator as the first argument,\n * and get a dispatch wrapped function in return.\n *\n * @param {Function|Object} actionCreators An object whose values are action\n * creator functions. One handy way to obtain it is to use ES6 `import * as`\n * syntax. You may also pass a single function.\n *\n * @param {Function} dispatch The `dispatch` function available on your Redux\n * store.\n *\n * @returns {Function|Object} The object mimicking the original object, but with\n * every action creator wrapped into the `dispatch` call. If you passed a\n * function as `actionCreators`, the return value will also be a single\n * function.\n */\n\n\nfunction bindActionCreators(actionCreators, dispatch) {\n if (typeof actionCreators === 'function') {\n return bindActionCreator(actionCreators, dispatch);\n }\n\n if (typeof actionCreators !== 'object' || actionCreators === null) {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(16) : \"bindActionCreators expected an object or a function, but instead received: '\" + kindOf(actionCreators) + \"'. \" + \"Did you write \\\"import ActionCreators from\\\" instead of \\\"import * as ActionCreators from\\\"?\");\n }\n\n var boundActionCreators = {};\n\n for (var key in actionCreators) {\n var actionCreator = actionCreators[key];\n\n if (typeof actionCreator === 'function') {\n boundActionCreators[key] = bindActionCreator(actionCreator, dispatch);\n }\n }\n\n return boundActionCreators;\n}\n\n/**\n * Composes single-argument functions from right to left. The rightmost\n * function can take multiple arguments as it provides the signature for\n * the resulting composite function.\n *\n * @param {...Function} funcs The functions to compose.\n * @returns {Function} A function obtained by composing the argument functions\n * from right to left. For example, compose(f, g, h) is identical to doing\n * (...args) => f(g(h(...args))).\n */\nfunction compose() {\n for (var _len = arguments.length, funcs = new Array(_len), _key = 0; _key < _len; _key++) {\n funcs[_key] = arguments[_key];\n }\n\n if (funcs.length === 0) {\n return function (arg) {\n return arg;\n };\n }\n\n if (funcs.length === 1) {\n return funcs[0];\n }\n\n return funcs.reduce(function (a, b) {\n return function () {\n return a(b.apply(void 0, arguments));\n };\n });\n}\n\n/**\n * Creates a store enhancer that applies middleware to the dispatch method\n * of the Redux store. This is handy for a variety of tasks, such as expressing\n * asynchronous actions in a concise manner, or logging every action payload.\n *\n * See `redux-thunk` package as an example of the Redux middleware.\n *\n * Because middleware is potentially asynchronous, this should be the first\n * store enhancer in the composition chain.\n *\n * Note that each middleware will be given the `dispatch` and `getState` functions\n * as named arguments.\n *\n * @param {...Function} middlewares The middleware chain to be applied.\n * @returns {Function} A store enhancer applying the middleware.\n */\n\nfunction applyMiddleware() {\n for (var _len = arguments.length, middlewares = new Array(_len), _key = 0; _key < _len; _key++) {\n middlewares[_key] = arguments[_key];\n }\n\n return function (createStore) {\n return function () {\n var store = createStore.apply(void 0, arguments);\n\n var _dispatch = function dispatch() {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(15) : 'Dispatching while constructing your middleware is not allowed. ' + 'Other middleware would not be applied to this dispatch.');\n };\n\n var middlewareAPI = {\n getState: store.getState,\n dispatch: function dispatch() {\n return _dispatch.apply(void 0, arguments);\n }\n };\n var chain = middlewares.map(function (middleware) {\n return middleware(middlewareAPI);\n });\n _dispatch = compose.apply(void 0, chain)(store.dispatch);\n return _objectSpread(_objectSpread({}, store), {}, {\n dispatch: _dispatch\n });\n };\n };\n}\n\nexport { ActionTypes as __DO_NOT_USE__ActionTypes, applyMiddleware, bindActionCreators, combineReducers, compose, createStore, legacy_createStore };\n","// TODO: This is deprecated and moved into redux-persist. See: https://github.com/wildlifela/redux-persist-migrate\n// It also doesn't seem to be doing much.\n\nimport type { Manifest, Migrator } from \"../typings\"\n\n// NOTE: If changing, also change it in store.ts (avoid circular imports)\nconst VERSION_REDUCER_KEY = \"versioning\"\n\ntype WrapMigrator = (migrator: Migrator) => Migrator\n\n// gets the most recent (largest) version number\nconst latestVersion = () => migrations.length - 1\n\n// if unset, set the app version to the latest\n// this is the case when someone opens the app for the first time\nconst initialVersioning: Migrator = (state) => {\n\tstate[VERSION_REDUCER_KEY] = { version: latestVersion() }\n\treturn state\n}\n\n// migration that signs the user out due to the redux store being changed in a breaking way\nconst signOut: Migrator = () => {\n\t// set the app version to the latest so that this migration is not run again\n\treturn initialVersioning({})\n}\n\n// Added a new state to the outbox slice\nconst createOutboxState: Migrator = (state) => {\n\tif (state.outboxReducer) {\n\t\tstate.outboxReducer.deletedRequests = []\n\t}\n\treturn state\n}\n\n// wraps migrations with the skipAfterInitialVersioning check for convenience\nconst wrapMigration: WrapMigrator = (migrator) => (state) => {\n\t// REASON: This happened to GCS\n\t// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n\tif (state === undefined) {\n\t\tstate = {}\n\t}\n\n\tif (state[VERSION_REDUCER_KEY]?.version === latestVersion()) return state\n\n\treturn migrator(state)\n}\n\n// migrations take in a RootState, modify it, and then return the updated root state\n// add new migrations to the **end** of this array\n// ensure initialVersioning() is always the first migration\nconst migrations: Migrator[] = [initialVersioning, signOut, signOut, createOutboxState]\n\n// used by redux-persist-migrate to run the migrations when rehydrating the app\nexport const manifest: Manifest = Object.fromEntries(migrations.map((migration, i) => [i, wrapMigration(migration)]))\n","import { createSlice, PayloadAction, Reducer } from \"@reduxjs/toolkit\"\nimport { TokenPair } from \"sdk/typings\"\nimport { BaseState } from \"../../typings\"\n\nexport interface AuthState {\n\taccessToken: string\n\trefreshToken: string\n\tisLoggedIn: boolean\n}\n\nconst initialState: AuthState = {\n\taccessToken: \"\",\n\trefreshToken: \"\",\n\tisLoggedIn: false,\n}\n\n/**\n * Stores the auth state of the app (tokens, and whether user is logged in or not)\n */\nexport const authSlice = createSlice({\n\tname: \"auth\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tsetTokens: (state, action: PayloadAction<TokenPair>) => {\n\t\t\tstate.accessToken = action.payload.accessToken\n\t\t\tstate.refreshToken = action.payload.refreshToken\n\t\t},\n\t\tclearTokens: (state) => {\n\t\t\tstate.accessToken = \"\"\n\t\t\tstate.refreshToken = \"\"\n\t\t},\n\t\tsetLoggedIn: (state, action: PayloadAction<boolean>) => {\n\t\t\tif (!action.payload) {\n\t\t\t\tauthSlice.caseReducers.clearTokens(state)\n\t\t\t}\n\t\t\tstate.isLoggedIn = action.payload\n\t\t},\n\t},\n})\n\nexport const { setTokens, clearTokens, setLoggedIn } = authSlice.actions\nexport const selectAccessToken = (state: BaseState) => state.authReducer.accessToken\nexport const selectIsLoggedIn = (state: BaseState) => state.authReducer.isLoggedIn\n\nexport const authReducer: Reducer<AuthState> = authSlice.reducer\n","import L from \"leaflet\"\nimport { Bounds, Coordinates, MultiPointGeometry, PointGeometry } from \"../typings\"\n\n// Convert our Coordinates type into a Leaflet LatLngLiteral\nexport const coordinatesToLiteral = (coordinates: Coordinates): L.LatLngLiteral => {\n\treturn { lng: coordinates[0], lat: coordinates[1] }\n}\n\n// Convert a Leaflet LatLngLiteral into our Coordinates type\nexport const literalToCoordinates = (literal: L.LatLngLiteral): Coordinates => {\n\treturn [literal.lng, literal.lat]\n}\n\n/**\n * Flip coordinates from [lng, lat] to [lat, lng]\n */\nexport const flipCoordinates = (coordinates: L.LatLngTuple): Coordinates => {\n\treturn [coordinates[1], coordinates[0]]\n}\n\nexport const flipBounds = (bounds: Bounds): Bounds => {\n\treturn [flipCoordinates(bounds[0]), flipCoordinates(bounds[1])]\n}\n\nexport function offsetPositionByMeters(\n\toriginalPosition: L.LatLng,\n\tlatMeters: number,\n\tlngMeters: number,\n): L.LatLngLiteral {\n\tconst { lat, lng } = originalPosition\n\tconst earthRadius = 6378137 // Earth's radius in meters.\n\tconst metersPerDegree = (2 * Math.PI * earthRadius) / 360\n\t// The significance of one degree decreases the closer you get to a pole. This accounts for that.\n\tconst newLng = lng + lngMeters / metersPerDegree / Math.cos((lat * Math.PI) / 180)\n\tconst newLat = lat - latMeters / metersPerDegree\n\treturn { lat: newLat, lng: newLng }\n}\n\nexport const createPointGeometry = (coordinates: Coordinates): PointGeometry => {\n\treturn {\n\t\ttype: \"Point\",\n\t\tcoordinates,\n\t}\n}\n\nexport const coordinatesAreEqual = (a: Coordinates, b: Coordinates): boolean => {\n\treturn a[0] === b[0] && a[1] === b[1]\n}\n\n// export const coordinatesAreNearlyEqual = (a: Coordinates, b: Coordinates, thresholdMeters: number): boolean => {\n// return a === b\n// TODO: Fix\n// const diffLat = Math.abs(a[1] - b[1])\n// Length in km of 1° of latitude = always 111.32 km\n// const diffLatMeters = diffLat * 111320\n// if (diffLatMeters < thresholdMeters) return true\n// Length in km of 1° of longitude = 40075 km * cos(latitude) / 360'\n// const aVal = a[0] // Optimization\n// const diffLong = Math.abs(aVal - b[0])\n// const diffLongMeters = diffLong * ((40075000 * Math.cos(aVal)) / 360)\n// return diffLongMeters < thresholdMeters\n// }\n\n// This converts a Coordinate [lng, lat] to \"lat, lng\" string format with an option to round the numbers\nexport const coordinatesToText = (coordinates: Coordinates | null | undefined, decimalPlaces?: number) => {\n\tif (!coordinates) return \"(No Location)\"\n\tconst { lat, lng } = coordinatesToLiteral(coordinates)\n\tif (decimalPlaces) return `${lat.toFixed(decimalPlaces)}, ${lng.toFixed(decimalPlaces)}`\n\treturn `${lat}, ${lng}`\n}\n\nexport const coordinatesToUrlText = (coordinates: Coordinates) => {\n\tconst { lat, lng } = coordinatesToLiteral(coordinates)\n\treturn `${lat}%2C${lng}`\n}\n\n// Opens coordinates in Google maps\nexport const openCoordsInGoogleMaps = (coordinates: Coordinates) => {\n\tconst url = `https://www.google.com/maps/search/?api=1&query=${coordinatesToUrlText(coordinates)}`\n\twindow.open(url)\n}\n\nexport const openDirectionsInGoogleMaps = (startingPoint: Coordinates, destination: Coordinates) => {\n\tconst startingPointUrl = coordinatesToUrlText(startingPoint)\n\tconst destinationUrl = coordinatesToUrlText(destination)\n\tconst url = `https://www.google.com/maps/dir/?api=1&origin=${startingPointUrl}&destination=${destinationUrl}`\n\twindow.open(url)\n}\n\nexport const worldBounds: MultiPointGeometry = {\n\ttype: \"MultiPoint\",\n\tcoordinates: [\n\t\t[90, -180],\n\t\t[-90, 180],\n\t],\n}\n\nexport const createMultiPointGeometry = (coordinates: [Coordinates, Coordinates]): MultiPointGeometry => {\n\treturn {\n\t\ttype: \"MultiPoint\",\n\t\tcoordinates,\n\t}\n}\n","/**\n * Combines multiple class names into a single string. Keys are class names and values are booleans.\n * If the value is true, the key is added to the string.\n */\nexport function classNames(...args: (object | string | undefined | null | number)[]): string {\n\tconst classes: string[] = []\n\tfor (const arg of args) {\n\t\tif (!arg) {\n\t\t\tcontinue\n\t\t}\n\t\tif (typeof arg === \"string\") {\n\t\t\tclasses.push(arg)\n\t\t} else if (typeof arg === \"object\") {\n\t\t\tfor (const [key, value] of Object.entries(arg)) {\n\t\t\t\tif (value) {\n\t\t\t\t\tclasses.push(key)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn classes.join(\" \")\n}\n","import { saveAs } from \"file-saver\"\nimport { FileUploadPayload } from \"../typings\"\n\n// See: https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#converting_a_digest_to_a_hex_string\nfunction hex(buffer: ArrayBufferLike): string {\n\tconst hashArray = new Uint8Array(buffer)\n\n\treturn hashArray.reduce((data, byte) => data + byte.toString(16).padStart(2, \"0\"), \"\")\n}\n\nexport const getFileS3Key = async (file: File, hash?: string) => {\n\tif (!hash) {\n\t\thash = await hashFile(file)\n\t}\n\tlet fileType = file.type\n\tif (fileType.includes(\"/\")) {\n\t\tfileType = fileType.split(\"/\")[1]!\n\t}\n\tif (!fileType) {\n\t\tthrow new Error(`Could not extract file type from ${file.type}`)\n\t}\n\treturn `${hash}.${fileType}`\n}\n\nexport function hashFile(file: Blob): Promise<string> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst reader = new FileReader()\n\t\t// Provide an onload callback for this instance of FileReader\n\t\t// This is called once reader.readAsArrayBuffer() is done\n\t\treader.onload = () => {\n\t\t\tconst fileResult = reader.result as ArrayBuffer | null\n\t\t\tif (!fileResult) {\n\t\t\t\treject()\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tvoid crypto.subtle.digest(\"SHA-1\", fileResult).then((hash) => {\n\t\t\t\tconst sha1result = hex(hash)\n\t\t\t\tresolve(sha1result)\n\t\t\t})\n\t\t}\n\n\t\t// calling reader.readAsArrayBuffer and providing a file should trigger the callback above\n\t\t// as soon as readAsArrayBuffer is complete\n\t\treader.readAsArrayBuffer(file)\n\t})\n}\n\nexport function getFileIdentifier(file: File): string {\n\tif (!file.name || !file.type || !file.size) {\n\t\tconst message = \"File has no name, type, and/or size\"\n\t\tconsole.error(`${message}`, file)\n\t\tthrow new Error(`${message}.`)\n\t}\n\treturn `${file.name}&${file.type}${file.size}`\n}\n\nexport function getRenamedFile(file: File, newName: string): File & { name: string } {\n\treturn new File([file], newName, { type: file.type })\n}\n\nexport function downloadInMemoryFile(filename: string, text: string) {\n\tconst element = document.createElement(\"a\")\n\telement.setAttribute(\"href\", \"data:text/plain;charset=utf-8,\" + encodeURIComponent(text))\n\telement.setAttribute(\"download\", filename)\n\n\telement.style.display = \"none\"\n\tdocument.body.appendChild(element)\n\n\telement.click()\n\n\tdocument.body.removeChild(element)\n}\n\n// TODO: implement to not block ui when hashing https://developer.chrome.com/blog/introducing-scheduler-yield-origin-trial\nexport const constructUploadedFilePayloads = async (files: File[]): Promise<FileUploadPayload[]> => {\n\tconst filePayloads: Record<string, FileUploadPayload> = {}\n\tfor (const file of files) {\n\t\tconst sha1 = await hashFile(file)\n\t\tfilePayloads[sha1] = {\n\t\t\tsha1,\n\t\t\textension: file.name.split(\".\").pop() || \"\",\n\t\t\tfile_type: file.type,\n\t\t\tsize: file.size,\n\t\t}\n\t}\n\treturn Object.values(filePayloads)\n}\n\nexport const fileToBlob = async (dataUrl: string): Promise<Blob> => {\n\t// TODO: Is this as reliable and supported as this?\n\t// https://www.nixtu.info/2013/06/how-to-upload-canvas-data-to-server.html\n\treturn (await fetch(dataUrl)).blob()\n}\n\nexport const blobToBase64 = (blob: Blob): Promise<string> => {\n\treturn new Promise((resolve, _) => {\n\t\tconst reader = new FileReader()\n\t\treader.onloadend = () => {\n\t\t\tresolve(reader.result?.toString() || \"\")\n\t\t}\n\t\treader.readAsDataURL(blob)\n\t})\n}\n\n// TODO:\n/** Converts a profile `file` and `fileSha1` into an img src that can be rendered. This relies on an API request. */\n\nexport function downloadFile(file: File) {\n\tconst blob = new Blob([file])\n\tsaveAs(blob, file.name)\n}\n","const logCache: Record<string, Record<string, boolean> | undefined> = {}\n\n/**\n * Logging the same message over and over again in a loop takes a lot of resources and makes the app laggy. This utility\n * function accepts a log ID (e.g. \"issue-has-no-index-workspace\") and an object ID (e.g. the offline_id of an issue),\n * and only logs the message on the first call with the same combination of logId and objId.\n * @param logId An arbitrary but unique identifier for this \"type of message\".\n * @param objId A unique identifier for the object the message regards. Can be an arbitrary string, e.g. \"current-user\"\n * or an actual object ID, e.g. the offline_id of an issue.\n * @param level The log level to use. For example, \"debug\" means `console.debug` will be called.\n * @param args The arguments to pass to the console log method.\n */\nexport function logOnlyOnce(\n\tlogId: string,\n\tobjId: string,\n\tlevel: \"debug\" | \"info\" | \"warn\" | \"error\",\n\t...args: unknown[]\n) {\n\tconst thisLogIdCache = logCache[logId]\n\tlet shouldLog = false\n\tif (!thisLogIdCache) {\n\t\tlogCache[logId] = { [objId]: true }\n\t\tshouldLog = true\n\t} else {\n\t\tconst hasLoggedForThisObject = thisLogIdCache[objId]\n\t\tif (!hasLoggedForThisObject) {\n\t\t\tthisLogIdCache[objId] = true\n\t\t\tshouldLog = true\n\t\t}\n\t}\n\tif (shouldLog) {\n\t\tconsole[level](...args)\n\t}\n}\n","import { Offline, OfflineModel } from \"../typings\"\nimport { v4 as uuidv4 } from \"uuid\"\n\n/**\n * Adds a generated UUID to the \"offline_id\" key of the object.\n * @param draft The model data to add the offline_id to\n */\nexport function offline<T>(draft: T): Offline<T> {\n\treturn { ...draft, offline_id: uuidv4() } as Offline<T>\n}\n\n/**\n * Converts an array of OfflineModel objects to a Record<string, TModel>, mapping an offline ID to the object with that\n * offline ID.\n * @param array An array of offline model instances\n */\nexport function toOfflineIdRecord<TModel extends OfflineModel>(array: TModel[]): Record<string, TModel> {\n\tconst asMapping: Record<string, TModel> = {}\n\tfor (const item of array) {\n\t\tasMapping[item.offline_id] = item\n\t}\n\treturn asMapping\n}\n","import { SearchResult, Stored } from \"../typings\"\nimport { Issue } from \"../typings\"\n\nexport const issueToSearchResult = (issue: Stored<Issue>, tag: string | null): SearchResult<Stored<Issue>> => {\n\treturn {\n\t\tlabel: issue.title || \"\",\n\t\ttypeLabel: \"issue\",\n\t\ttag: tag,\n\t\titem: issue,\n\t}\n}\n","/**\n * Returns a file-safe string from arbitrary text. Will return maximum 255 characters, which is the longest safe\n * Long File Name (LFN).\n * WARNING! May give poor performance in big loops.\n * @param str The string to make safe for file names.\n * @param extension An extension (not including a period) to be added after a period at the end of the string. The\n * character limit of the returned string includes the extension, meaning characters from str will be removed to\n * accommodate it if necessary.\n * @param maxLength The maximum length of the resulting file name. Defaults to 255.\n */\nexport function toFileNameSafeString(str: string, extension: string | undefined = undefined, maxLength = 255): string {\n\tlet ret = str.replace(/[^a-z0-9_\\-.]/gi, \"_\").replace(/_{2,}/g, \"_\")\n\tif (!extension) {\n\t\tconst parts = str.split(\".\")\n\t\tif (parts.length > 1) {\n\t\t\textension = parts[parts.length - 1]\n\t\t}\n\t}\n\tif (extension && !extension.startsWith(\".\")) {\n\t\textension = \".\" + extension\n\t}\n\tconst extensionLengthWithPeriod = extension ? extension.length : 0\n\n\tif (ret.length + extensionLengthWithPeriod > maxLength) {\n\t\tret = ret.slice(0, maxLength - extensionLengthWithPeriod) + (extension || \"\")\n\t}\n\treturn ret\n}\n\nexport function spacesToDashesLower(value: string): string {\n\treturn value.toLowerCase().replace(\" \", \"-\")\n}\n\nexport function slugify(str: string, underscore = false) {\n\treturn str\n\t\t.normalize(\"NFKD\")\n\t\t.toLowerCase()\n\t\t.replace(/[^\\w\\s-]/g, \"\")\n\t\t.trim()\n\t\t.replace(/[-\\s]+/g, underscore ? \"_\" : \"-\")\n}\n\n/**\n * Given a string, returns a truncated version of it with an ellipsis character at the end if it is longer than\n * maxLength. The resulting string will be no longer than maxLength. Note that the ellipsis is only one character long.\n * @param str The string to truncate.\n * @param maxLength The maximum length of the resulting string, including the ellipsis.\n */\nexport function truncate(str: string, maxLength: number) {\n\tif (str.length <= maxLength) {\n\t\treturn str\n\t}\n\t// -1 to account for the ellipsis character\n\tconst subString = str.slice(0, maxLength - 1)\n\treturn subString.slice(0, subString.lastIndexOf(\" \")) + \"…\"\n}\n","import { Coordinates, IssueAttachment, OfflineModel, OvermapRootState } from \"../typings\"\n\ntype MemoizedSelectorWithArgs<TArgs, TRet> = (state: OvermapRootState, args: TArgs) => TRet\n\n// makes the createSelector function fit the current pattern for selectors with arguments\nexport const restructureCreateSelectorWithArgs =\n\t<TArgs, TRet>(selector: MemoizedSelectorWithArgs<TArgs, TRet>) =>\n\t(args: TArgs) =>\n\t(state: OvermapRootState) =>\n\t\tselector(state, args)\n\nexport function onlyUniqueOfflineIds(value: OfflineModel, index: number, self: OfflineModel[]) {\n\treturn self.findIndex((v) => v.offline_id === value.offline_id) === index\n}\n\nexport function onlyUniqueHashes(value: IssueAttachment, index: number, self: IssueAttachment[]) {\n\treturn (\n\t\tself.findIndex((v: IssueAttachment) => {\n\t\t\treturn v.file_sha1 === value.file_sha1\n\t\t}) === index\n\t)\n}\n\n/**\n *\n * @param bounds order: [northEast, southWest]\n * @param coordinates\n */\nexport function boundsContainPoint(bounds: [Coordinates, Coordinates], coordinates: Coordinates): boolean {\n\t// TODO: this is flipped for Marker (Geometry)\n\treturn (\n\t\tbounds[0][0] > coordinates[0] &&\n\t\tbounds[1][0] < coordinates[0] &&\n\t\tbounds[0][1] > coordinates[1] &&\n\t\tbounds[1][1] < coordinates[1]\n\t)\n}\n\nexport const emailRegex = /^.+@.+\\..+$/\n","import React, { useEffect, useRef } from \"react\"\n\nlet debug = false\n\nconst REACT_APP_DEBUG_MEMOIZATION = (import.meta.env.REACT_APP_DEBUG_MEMOIZATION as string | undefined) || \"\"\n\nif ([\"true\", \"1\"].includes(REACT_APP_DEBUG_MEMOIZATION.toLowerCase())) {\n\tdebug = true\n}\n\nexport function shallowEqual(objA: Record<string, unknown>, objB: Record<string, unknown>) {\n\t// Check if they're the same object (objA is objB) -- just a quick reference check\n\tif (objA === objB) return true\n\n\tif (typeof objA !== typeof objB) {\n\t\treturn false\n\t}\n\n\tconst keysA = Object.keys(objA)\n\tconst keysB = Object.keys(objB)\n\n\t// Only calculate this once\n\tconst keysALength = keysA.length\n\tif (keysALength !== keysB.length) return false\n\n\tfor (let i = 0; i < keysALength; i++) {\n\t\tconst key = keysA[i]!\n\t\tif (!Object.prototype.hasOwnProperty.call(objB, key) || objA[key] !== objB[key]) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\nexport function memoize<T extends (...args: never[]) => unknown>(func: T): T {\n\t// Taken from https://www.sitepoint.com/implementing-memoization-in-javascript/\n\tconst memo = {}\n\n\treturn function () {\n\t\t// eslint-disable-next-line prefer-rest-params\n\t\tconst args = Array.prototype.slice.call(arguments) as never[]\n\n\t\t// SEE: https://stackoverflow.com/questions/10173956/how-to-use-array-as-key-in-javascript\n\n\t\t// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n\t\t// @ts-expect-error\n\t\tif (args in memo) {\n\t\t\tif (debug) {\n\t\t\t\tconsole.debug(`Memoization debug: Using memorized return value for ${func.toString()}(`, args, \")\")\n\t\t\t}\n\t\t\t// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n\t\t\t// @ts-expect-error\n\t\t\treturn memo[args] as T\n\t\t} else {\n\t\t\tif (debug) {\n\t\t\t\tconsole.debug(`Memoization debug: Cache miss! Memoizing ${func.toString()}(`, args, \")\")\n\t\t\t}\n\t\t\t// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n\t\t\t// @ts-expect-error\n\t\t\treturn (memo[args] = func.apply(this, args))\n\t\t}\n\t} as T\n}\n\nexport type EqualityChecker<TArgs> = (current: TArgs, previous: TArgs) => boolean\n\nexport function useMemoCompare<TValue>(\n\tnext: TValue | undefined,\n\tcompare: (prev: TValue | undefined, next: TValue | undefined) => boolean,\n): TValue | undefined {\n\t// Ref for storing previous value\n\tconst previousRef = useRef<TValue>(undefined)\n\tconst previous: TValue | undefined = previousRef.current\n\n\t// Pass previous and next value to compare function\n\t// to determine whether to consider them equal.\n\tconst isEqual = compare(previous, next)\n\n\t// If not equal update previousRef to next value.\n\t// We only update if not equal so that this hook continues to return\n\t// the same old value if compare keeps returning true.\n\tuseEffect(() => {\n\t\tif (!isEqual) {\n\t\t\tpreviousRef.current = next\n\t\t}\n\t})\n\n\t// Finally, if equal then return the previous value\n\treturn isEqual ? previous : next\n}\n\n/**\n * Performs an equality check by contents in order.\n * Reference types like objects and arrays are compared by reference.\n */\nexport function areArraysEqual(first: unknown[], second: unknown[]) {\n\tif (first.length !== second.length) return false\n\tfor (let i = 0; i < first.length; i++) {\n\t\tif (first[i] !== second[i]) return false\n\t}\n\treturn true\n}\n\nexport const genericMemo: <T>(component: T) => T = React.memo\n","import { default as ColorCls } from \"color\"\nimport {\n\tgray,\n\tgold,\n\tbrown,\n\tyellow,\n\tamber,\n\torange,\n\tred,\n\tcrimson,\n\tpink,\n\tplum,\n\tpurple,\n\tviolet,\n\tiris,\n\tindigo,\n\tblue,\n\tcyan,\n\tjade,\n\tgrass,\n\tlime,\n\tmint,\n\tsky,\n} from \"@radix-ui/colors\"\nimport { CSSColor } from \"../typings\"\n\n// TODO: Move most of these constants into src/theme/variables.ts\nexport const primaryColor: CSSColor = \"#2D55E2\"\nexport const successColor: CSSColor = \"#349C55\"\nexport const warningColor: CSSColor = \"#FFA620\"\nexport const errorColor: CSSColor = \"#E24C4C\"\nexport const GREEN: CSSColor = \"#1fd155\"\nexport const YELLOW: CSSColor = \"#f5de14\"\nexport interface BadgeColors {\n\tbackgroundColor: CSSColor\n\ttextColor: CSSColor\n}\n\n// Colors used for color selection purposes\nexport const Colors: Record<string, CSSColor> = {\n\tgray: (gray as Record<string, CSSColor>).gray9!,\n\tgold: (gold as Record<string, CSSColor>).gold9!,\n\tbrown: (brown as Record<string, CSSColor>).brown9!,\n\tyellow: (yellow as Record<string, CSSColor>).yellow9!,\n\tamber: (amber as Record<string, CSSColor>).amber9!,\n\torange: (orange as Record<string, CSSColor>).orange9!,\n\tred: (red as Record<string, CSSColor>).red9!,\n\tcrimson: (crimson as Record<string, CSSColor>).crimson9!,\n\tpink: (pink as Record<string, CSSColor>).pink9!,\n\tplum: (plum as Record<string, CSSColor>).plum9!,\n\tpurple: (purple as Record<string, CSSColor>).purple9!,\n\tviolet: (violet as Record<string, CSSColor>).violet9!,\n\tiris: (iris as Record<string, CSSColor>).iris9!,\n\tindigo: (indigo as Record<string, CSSColor>).indigo9!,\n\tblue: (blue as Record<string, CSSColor>).blue9!,\n\tcyan: (cyan as Record<string, CSSColor>).cyan9!,\n\tjade: (jade as Record<string, CSSColor>).jade9!,\n\tgrass: (grass as Record<string, CSSColor>).grass9!,\n\tlime: (lime as Record<string, CSSColor>).lime9!,\n\tmint: (mint as Record<string, CSSColor>).mint9!,\n\tsky: (sky as Record<string, CSSColor>).sky9!,\n}\n\n// Colors used for asset stages\nexport const AssetStageColors: Record<string, CSSColor> = {\n\tindigo: (indigo as Record<string, CSSColor>).indigo9!,\n\tred: (red as Record<string, CSSColor>).red9!,\n\tviolet: (violet as Record<string, CSSColor>).violet9!,\n\tyellow: (yellow as Record<string, CSSColor>).yellow9!,\n\tjade: (jade as Record<string, CSSColor>).jade9!,\n\tcyan: (cyan as Record<string, CSSColor>).cyan9!,\n\tgold: (gold as Record<string, CSSColor>).gold9!,\n\torange: (orange as Record<string, CSSColor>).orange9!,\n\tlime: (lime as Record<string, CSSColor>).lime9!,\n\tsky: (sky as Record<string, CSSColor>).sky9!,\n\tpink: (pink as Record<string, CSSColor>).pink9!,\n}\n\nexport const defaultBadgeColor: CSSColor = \"#868686\"\n\n// This function adjusts a given colour into two variations for use as badge colours\nexport const generateBadgeColors = (rawColor: CSSColor): BadgeColors => {\n\tconst color = ColorCls(rawColor)\n\tconst safety = ColorCls(YELLOW)\n\tconst backgroundColor: CSSColor = color.darken(0.09).hex() as CSSColor\n\t// If the color matches the special yellow safety color, make the text black\n\tconst textColor = color.hex() === safety.hex() ? \"#000000\" : \"#FFFFFF\"\n\t// Alternate style:\n\t// const backgroundColor = color.lighten(0.4).hex()\n\t// const textColor = color.darken(0.6).hex()\n\n\treturn { backgroundColor, textColor }\n}\n\nexport function getStageColor(index: number): CSSColor {\n\treturn Object.values(AssetStageColors)[index % Object.keys(AssetStageColors).length]!\n}\n","import { memoize } from \"./optimization\"\n\n/** Only shows year if a past year */\nexport const getLocalDateString = memoize((date?: string | null | Date | number) => {\n\tif (!date) return \"\"\n\tconst asDate = new Date(date)\n\tconst isThisYear = asDate.getFullYear() === today.getFullYear()\n\tconst options: Intl.DateTimeFormatOptions = { day: \"numeric\", month: \"short\" }\n\tif (!isThisYear) options.year = \"numeric\"\n\treturn asDate.toLocaleDateString([], options)\n})\n\nconst relative = new Intl.RelativeTimeFormat([], { style: \"long\", numeric: \"auto\" })\nconst msInDay = 1000 * 86400\nconst today = new Date()\n\n/** Returns true if the given date is today */\nexport const isToday = (date: string | Date | number) => {\n\treturn new Date(date).toDateString() === today.toDateString()\n}\n\n/*\nDisplays a relative message \"in 2 days\" or \"today\" if within the given period (min, max)\nOtherwise, falls back to getLocalDateString()\n*/\nexport const getLocalRelativeDateString = memoize((date: string | Date | number, min: number, max: number) => {\n\tconst days = Math.round((new Date(date).getTime() - today.getTime()) / msInDay)\n\tif (days < min || days > max) return getLocalDateString(date)\n\treturn relative.format(days, \"days\")\n})\n","import { PayloadAction } from \"@reduxjs/toolkit\"\nimport { ModelState } from \"./typings\"\n\nexport interface OvermapModelAdapter<TModel> {\n\taddOne: <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel>) => void\n\taddMany: <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel[]>) => void\n\tsetOne: <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel>) => void\n\tsetMany: <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel[]>) => void\n\tupdateOne: <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel>) => void\n\tupdateMany: <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel[]>) => void\n\tdeleteOne: <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<string>) => void\n\tdeleteMany: <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<string[]>) => void\n\tinitialize: <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel[]>) => void\n\tgetInitialState: <TState extends object>(state: TState) => TState & ModelState<TModel>\n}\n\nexport function createModelAdapter<TModel>(computeModelId: (model: TModel) => string): OvermapModelAdapter<TModel> {\n\tconst addOne = <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel>) => {\n\t\t// TODO: error check here if the model already exists?\n\t\tconst id = computeModelId(action.payload)\n\t\tstate.instances[id] = action.payload\n\t}\n\n\tconst addMany = <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel[]>) => {\n\t\tfor (const model of action.payload) {\n\t\t\t// TODO: error check here if the model already exists?\n\t\t\tconst id = computeModelId(model)\n\t\t\tstate.instances[id] = model\n\t\t}\n\t}\n\n\tconst setOne = <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel>) => {\n\t\tconst id = computeModelId(action.payload)\n\t\tstate.instances[id] = action.payload\n\t}\n\n\tconst setMany = <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel[]>) => {\n\t\tfor (const model of action.payload) {\n\t\t\tconst id = computeModelId(model)\n\t\t\tstate.instances[id] = model\n\t\t}\n\t}\n\n\tconst updateOne = <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel>) => {\n\t\tconst id = computeModelId(action.payload)\n\t\tstate.instances[id] = action.payload\n\t}\n\n\tconst updateMany = <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel[]>) => {\n\t\tfor (const model of action.payload) {\n\t\t\tconst id = computeModelId(model)\n\t\t\tstate.instances[id] = model\n\t\t}\n\t}\n\n\tconst deleteOne = <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<string>) => {\n\t\tdelete state.instances[action.payload]\n\t}\n\n\tconst deleteMany = <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<string[]>) => {\n\t\tfor (const id of action.payload) {\n\t\t\tdelete state.instances[id]\n\t\t}\n\t}\n\n\tconst initialize = <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel[]>) => {\n\t\tstate.instances = {}\n\t\tfor (const model of action.payload) {\n\t\t\t// TODO: error check here if the model already exists?\n\t\t\tconst id = computeModelId(model)\n\t\t\tstate.instances[id] = model\n\t\t}\n\t}\n\n\tconst getInitialState = <TState extends object>(state: TState) => {\n\t\treturn {\n\t\t\t...state,\n\t\t\tinstances: {} as Record<string, TModel>,\n\t\t}\n\t}\n\n\treturn {\n\t\taddOne,\n\t\taddMany,\n\t\tsetOne,\n\t\tsetMany,\n\t\tupdateOne,\n\t\tupdateMany,\n\t\tdeleteOne,\n\t\tdeleteMany,\n\t\tinitialize,\n\t\tgetInitialState,\n\t}\n}\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport { Category, OvermapRootState, OvermapSelectorWithArgs, Stored } from \"../../typings\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\n\nexport type CategoryState = ModelState<Stored<Category>>\n\nconst categoryAdapter = createModelAdapter<Stored<Category>>((category) => category.offline_id)\n\nconst initialState: CategoryState = categoryAdapter.getInitialState({})\n\nexport const categorySlice = createSlice({\n\tname: \"categories\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeCategories: categoryAdapter.initialize,\n\t\taddCategory: categoryAdapter.addOne,\n\t\tupdateCategory: categoryAdapter.updateOne,\n\t\tdeleteCategory: categoryAdapter.deleteOne,\n\t},\n})\n\nexport const { initializeCategories, addCategory, updateCategory, deleteCategory } = categorySlice.actions\n\nexport const selectCategoryMapping = (state: OvermapRootState) => state.categoryReducer.instances\n\nexport const selectCategories = createSelector([selectCategoryMapping], (categoryMapping) => {\n\treturn Object.values(categoryMapping)\n})\n\nexport const selectCategoryById: OvermapSelectorWithArgs<string, Stored<Category>> =\n\t(id: Category[\"offline_id\"]) => (state) => {\n\t\treturn state.categoryReducer.instances[id]\n\t}\n\nexport const selectCategoriesByIds = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectCategoryMapping, (_state, categoryIds: Category[\"offline_id\"][]) => categoryIds],\n\t\t(categoryMapping, categoryIds) => {\n\t\t\tconst categories: Stored<Category>[] = []\n\n\t\t\tfor (const categoryId of categoryIds) {\n\t\t\t\tconst category = categoryMapping[categoryId]\n\n\t\t\t\tif (category) {\n\t\t\t\t\tcategories.push(category)\n\t\t\t\t} else {\n\t\t\t\t\tconsole.warn(\"selectCategoryByIds: No category exists with the id\", categoryId)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn categories\n\t\t},\n\t),\n)\n\nexport const selectCategoriesOfWorkspace: OvermapSelectorWithArgs<string, Category[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector([selectCategories, (_state, workspaceId: string) => workspaceId], (categories, workspaceId) =>\n\t\t\tcategories.filter((category) => category.workspace === workspaceId),\n\t\t),\n\t)\n\nexport const selectIssueCountOfCategory: OvermapSelectorWithArgs<string | null, number> =\n\t(categoryId) => (state: OvermapRootState) => {\n\t\treturn Object.values(state.issueReducer.instances).filter((issue) => issue.category === categoryId).length\n\t}\n\nexport const categoryReducer: Reducer<CategoryState> = categorySlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport { AssetStage, OvermapSelector, OvermapSelectorWithArgs, Stored } from \"../../typings\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\n\nexport type AssetStageState = ModelState<Stored<AssetStage>>\n\nconst assetStageAdapter = createModelAdapter<Stored<AssetStage>>((assetStage) => assetStage.offline_id)\n\nconst initialState = assetStageAdapter.getInitialState({})\n\nexport const assetStageSlice = createSlice({\n\tname: \"assetStages\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeStages: assetStageAdapter.initialize,\n\t\tsetStage: assetStageAdapter.setOne,\n\t\taddStages: assetStageAdapter.addMany,\n\t\tupdateStage: assetStageAdapter.updateOne,\n\t\tupdateStages: assetStageAdapter.updateMany,\n\t\tremoveStages: assetStageAdapter.deleteMany,\n\t},\n})\n\nexport const selectStageMapping: OvermapSelector<Record<AssetStage[\"offline_id\"], AssetStage>> = (state) =>\n\tstate.assetStageReducer.instances\n\nexport const selectAssetStageById: OvermapSelectorWithArgs<string, AssetStage | undefined> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector([selectStageMapping, (_state, stageId: string) => stageId], (stageMapping, stageId) => {\n\t\t\treturn stageMapping[stageId]\n\t\t}),\n\t)\n\nexport const selectAssetStages = createSelector([selectStageMapping], (stageMapping) => {\n\treturn Object.values(stageMapping)\n})\n\nexport const selectStagesFromAssetTypeIds: OvermapSelectorWithArgs<\n\tstring[],\n\tRecord<string, AssetStage[]>\n> = restructureCreateSelectorWithArgs(\n\tcreateSelector([selectAssetStages, (_state, assetTypeIds: string[]) => assetTypeIds], (stages, assetTypeIds) => {\n\t\tconst assetTypeIdsSet = new Set(assetTypeIds)\n\t\tconst ret: Record<string, AssetStage[]> = {}\n\t\tfor (const stage of stages) {\n\t\t\tif (assetTypeIdsSet.has(stage.asset_type)) {\n\t\t\t\tif (!ret[stage.asset_type]) {\n\t\t\t\t\tret[stage.asset_type] = []\n\t\t\t\t}\n\t\t\t\tret[stage.asset_type]!.push(stage)\n\t\t\t}\n\t\t}\n\t\tfor (const key in ret) {\n\t\t\tret[key] = ret[key]!.sort((a, b) => a.priority - b.priority)\n\t\t}\n\t\treturn ret\n\t}),\n)\n\nexport const selectAssetTypeStagesMapping: OvermapSelectorWithArgs<\n\tstring,\n\tRecord<string, AssetStage>\n> = restructureCreateSelectorWithArgs(\n\tcreateSelector([selectStageMapping, (_state, assetTypeId: string) => assetTypeId], (stagesMapping, assetTypeId) => {\n\t\tconst assetTypeStagesMapping: Record<string, AssetStage> = {}\n\t\tfor (const [stageId, stage] of Object.entries(stagesMapping)) {\n\t\t\tif (stage.asset_type === assetTypeId) {\n\t\t\t\tassetTypeStagesMapping[stageId] = stage\n\t\t\t}\n\t\t}\n\t\treturn assetTypeStagesMapping\n\t}),\n)\n\nexport const selectStagesOfAssetType: OvermapSelectorWithArgs<string, AssetStage[]> = restructureCreateSelectorWithArgs(\n\tcreateSelector([selectAssetStages, (_state, assetTypeId: string) => assetTypeId], (stages, assetTypeId) => {\n\t\treturn stages.filter((stage) => stage.asset_type === assetTypeId).sort((a, b) => a.priority - b.priority)\n\t}),\n)\n\nexport const selectAssetStagesByIds = restructureCreateSelectorWithArgs(\n\tcreateSelector([selectStageMapping, (_state, stageIds: string[]) => stageIds], (stageMapping, stageIds) => {\n\t\tconst assetStages: Stored<AssetStage>[] = []\n\n\t\tfor (const stageId of stageIds) {\n\t\t\tconst stage = stageMapping[stageId]\n\n\t\t\tif (stage) {\n\t\t\t\tassetStages.push(stage)\n\t\t\t} else {\n\t\t\t\tconsole.warn(\"selectStagesFromStageIds: No stage exists with the id\", stageId)\n\t\t\t}\n\t\t}\n\n\t\treturn assetStages\n\t}),\n)\n\n// Takes an array of stage ids and returns a record of stage ids to form ids, if the stage has a form\nexport const selectStageFormIdsFromStageIds: OvermapSelectorWithArgs<\n\tstring[],\n\tRecord<string, string>\n> = restructureCreateSelectorWithArgs(\n\tcreateSelector([selectStageMapping, (_state, stageIds: string[]) => stageIds], (stageMapping, stageIds) => {\n\t\tconst ret: Record<string, string> = {}\n\t\tfor (const stageId of stageIds) {\n\t\t\tconst stage = stageMapping[stageId]\n\t\t\tif (!stage) {\n\t\t\t\tthrow new Error(\"No stage exists with the id \" + stageId)\n\t\t\t}\n\t\t\tif (stage.form) {\n\t\t\t\tret[stageId] = stage.form\n\t\t\t}\n\t\t}\n\t\treturn ret\n\t}),\n)\n\nexport const { initializeStages, setStage, addStages, updateStages, removeStages, updateStage } =\n\tassetStageSlice.actions\n\nexport const assetStageReducer: Reducer<AssetStageState> = assetStageSlice.reducer\n","import type { Reducer } from \"@reduxjs/toolkit\"\nimport { createSelector, createSlice } from \"@reduxjs/toolkit\"\nimport {\n\tAssetStage,\n\tAssetType,\n\tOvermapRootState,\n\tOvermapSelector,\n\tOvermapSelectorWithArgs,\n\tStored,\n} from \"../../typings\"\nimport type { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\nimport { selectStageMapping } from \"./assetStageSlice\"\n\nexport type AssetTypeState = ModelState<Stored<AssetType>>\n\nconst assetTypeAdapter = createModelAdapter<Stored<AssetType>>((assetType) => assetType.offline_id)\n\nconst initialState: AssetTypeState = assetTypeAdapter.getInitialState({})\n\nexport const assetTypeSlice = createSlice({\n\tname: \"assetTypes\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeAssetTypes: assetTypeAdapter.initialize,\n\t\taddAssetType: assetTypeAdapter.addOne,\n\t\tdeleteAssetType: assetTypeAdapter.deleteOne,\n\t},\n})\n\nexport const { addAssetType, initializeAssetTypes, deleteAssetType } = assetTypeSlice.actions\n\nexport const selectAssetTypesMapping: OvermapSelector<Record<string, AssetType>> = (state: OvermapRootState) =>\n\tstate.assetTypeReducer.instances\n\nexport const selectAssetTypes: OvermapSelector<AssetType[]> = createSelector([selectAssetTypesMapping], (mapping) =>\n\tObject.values(mapping),\n)\n\nexport const selectAssetTypeById: OvermapSelectorWithArgs<AssetType[\"offline_id\"], Stored<AssetType>> =\n\t(id: AssetType[\"offline_id\"]) => (state) => {\n\t\treturn state.assetTypeReducer.instances[id]\n\t}\n\nexport const selectAssetTypesByIds = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectStageMapping, (_state, assetTypeIds: AssetType[\"offline_id\"][]) => assetTypeIds],\n\t\t(assetTypeMapping, assetTypeIds) => {\n\t\t\tconst assetTypes: Stored<AssetStage>[] = []\n\n\t\t\tfor (const stageId of assetTypeIds) {\n\t\t\t\tconst stage = assetTypeMapping[stageId]\n\n\t\t\t\tif (stage) {\n\t\t\t\t\tassetTypes.push(stage)\n\t\t\t\t} else {\n\t\t\t\t\tconsole.warn(\"selectAssetTypesByIds: No stage exists with the id\", stageId)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn assetTypes\n\t\t},\n\t),\n)\n\nexport const assetTypeReducer: Reducer<AssetTypeState> = assetTypeSlice.reducer\n","import { createSelector, createSlice, PayloadAction, Reducer } from \"@reduxjs/toolkit\"\nimport {\n\tAsset,\n\tAssetType,\n\tOvermapRootState,\n\tOvermapSelector,\n\tOvermapSelectorWithArgs,\n\tStored,\n\tSubmitted,\n} from \"../../typings\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\nimport { selectAssetTypesMapping } from \"./assetTypeSlice\"\nimport { createModelAdapter } from \"../adapter\"\nimport { ModelState } from \"../typings\"\n\nexport type AssetState = ModelState<Stored<Asset>>\n\nconst assetAdapter = createModelAdapter<Stored<Asset>>((asset) => asset.offline_id)\n\nconst initialState: AssetState = assetAdapter.getInitialState({})\n\nexport const assetSlice = createSlice({\n\tname: \"assets\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeAssets: (state, action: PayloadAction<Asset[]>) => {\n\t\t\tassetAdapter.initialize(state, action)\n\t\t\tprevAssets = null\n\t\t},\n\t\taddAsset: (state, action: PayloadAction<Asset>) => {\n\t\t\tassetAdapter.addOne(state, action)\n\t\t\tprevAssets = null\n\t\t},\n\t\taddAssets: (state, action: PayloadAction<(Asset | Submitted<Asset>)[]>) => {\n\t\t\tassetAdapter.addMany(state, action)\n\t\t\tprevAssets = null\n\t\t},\n\t\tsetAsset: (state, action: PayloadAction<Asset>) => {\n\t\t\tassetAdapter.setOne(state, action)\n\t\t\tprevAssets = null\n\t\t},\n\t\tsetAssets: (state, action: PayloadAction<Asset[]>) => {\n\t\t\tassetAdapter.setMany(state, action)\n\t\t\tprevAssets = null\n\t\t},\n\n\t\tupdateAsset: (state, action: PayloadAction<Asset>) => {\n\t\t\tassetAdapter.updateOne(state, action)\n\t\t\tprevAssets = null\n\t\t},\n\t\tupdateAssets: (state, action: PayloadAction<Asset[]>) => {\n\t\t\tassetAdapter.updateMany(state, action)\n\t\t\tprevAssets = null\n\t\t},\n\t\tdeleteAsset: (state, action: PayloadAction<string>) => {\n\t\t\tassetAdapter.deleteOne(state, action)\n\t\t\tprevAssets = null\n\t\t},\n\t\tdeleteAssets: (state, action: PayloadAction<string[]>) => {\n\t\t\tassetAdapter.deleteMany(state, action)\n\t\t\tprevAssets = null\n\t\t},\n\t},\n})\n\nexport const {\n\tinitializeAssets,\n\taddAsset,\n\taddAssets,\n\tupdateAsset,\n\tupdateAssets,\n\tdeleteAsset,\n\tdeleteAssets,\n\tsetAsset,\n\tsetAssets,\n} = assetSlice.actions\n\n// TODO: Reusable helper for this\n// When calling a selector, it returns a new object/array on each call. This causes hooks and assets that depend on\n// assets to rerender, even if the assets themselves haven't changed. We know when assets change (only when\n// one of the reducers above are called), so we can improve the performance of the app significantly by returning an old\n// reference until the cache has been invalidated.\nlet prevAssets: Asset[] | null = null\nexport const selectAssets = (state: OvermapRootState) => {\n\tif (!prevAssets) {\n\t\tprevAssets = Object.values(state.assetReducer.instances)\n\t}\n\treturn prevAssets\n}\n\nexport const selectAssetsMapping = (state: OvermapRootState) => state.assetReducer.instances\n\nexport const selectAssetsOfAssetType: OvermapSelectorWithArgs<string, Asset[]> = restructureCreateSelectorWithArgs(\n\tcreateSelector([selectAssets, (_state, assetTypeId: string) => assetTypeId], (components, assetTypeId) => {\n\t\treturn components.filter((asset) => asset.asset_type === assetTypeId)\n\t}),\n)\n\nexport const selectAssetById: OvermapSelectorWithArgs<string, Asset> = (assetId) => (state: OvermapRootState) => {\n\treturn state.assetReducer.instances[assetId]\n}\n\nexport const selectAssetsByIds = restructureCreateSelectorWithArgs(\n\tcreateSelector([selectAssetsMapping, (_, assetIds: string[]) => assetIds], (assetsMapping, assetIds) => {\n\t\tconst assets: Stored<Asset>[] = []\n\n\t\tfor (const assetId of assetIds) {\n\t\t\tconst asset = assetsMapping[assetId]\n\n\t\t\tif (asset) assets.push(asset)\n\t\t}\n\n\t\treturn assets\n\t}),\n)\n\nexport const selectAssetToAssetTypeMapping: OvermapSelector<Record<string, AssetType>> = createSelector(\n\t[selectAssets, selectAssetTypesMapping],\n\t(assets, assetTypeMapping) => {\n\t\tconst ret: Record<string, AssetType> = {}\n\n\t\tfor (const asset of assets) {\n\t\t\tconst assetType = assetTypeMapping[asset.asset_type]\n\t\t\t// TODO: need to make sure that all asset types are populated for loaded assets, otherwise this error will be produced\n\t\t\tif (!assetType) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t`Asset type with ID ${asset.asset_type} not found.\n\t\t\t\tExpected all referenced asset types to be populated.\n\t\t\t\tReturning empty object to avoid fatal errors.`,\n\t\t\t\t)\n\t\t\t\treturn {}\n\t\t\t}\n\t\t\tret[asset.offline_id] = assetType\n\t\t}\n\n\t\treturn ret\n\t},\n)\n\nexport const selectNumberOfAssetsOfAssetType: OvermapSelectorWithArgs<string | undefined, number> =\n\t(assetTypeId) => (state) => {\n\t\tif (!assetTypeId) return 0\n\t\treturn selectAssetsOfAssetType(assetTypeId)(state)?.length\n\t}\n\nexport const selectAssetTypesFromIds: OvermapSelectorWithArgs<string[], AssetType[]> =\n\t(assetTypeIds: string[]) => (state: OvermapRootState) => {\n\t\treturn assetTypeIds.reduce<AssetType[]>((acc, assetTypeId) => {\n\t\t\tconst assetType = state.assetTypeReducer.instances[assetTypeId]\n\t\t\tif (assetType) {\n\t\t\t\tacc.push(assetType)\n\t\t\t}\n\t\t\treturn acc\n\t\t}, [])\n\t}\n\nexport const assetReducer: Reducer<AssetState> = assetSlice.reducer\n","import { createSlice, Reducer, createSelector } from \"@reduxjs/toolkit\"\nimport { ModelState } from \"../typings\"\nimport { AssetAttachment, OvermapRootState, OvermapSelector, OvermapSelectorWithArgs, Stored } from \"../../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport type AssetAttachmentState = ModelState<Stored<AssetAttachment>>\n\nconst assetAttachmentAdapter = createModelAdapter<Stored<AssetAttachment>>((attachment) => attachment.offline_id)\n\nconst initialState = assetAttachmentAdapter.getInitialState({})\n\nexport const assetAttachmentSlice = createSlice({\n\tname: \"assetAttachments\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeAssetAttachments: assetAttachmentAdapter.initialize,\n\t\taddAssetAttachment: assetAttachmentAdapter.addOne,\n\t\taddAssetAttachments: assetAttachmentAdapter.addMany,\n\t\tsetAssetAttachment: assetAttachmentAdapter.setOne,\n\t\tsetAssetAttachments: assetAttachmentAdapter.setMany,\n\t\tupdateAssetAttachment: assetAttachmentAdapter.updateOne,\n\t\tupdateAssetAttachments: assetAttachmentAdapter.updateMany,\n\t\tdeleteAssetAttachment: assetAttachmentAdapter.deleteOne,\n\t\tdeleteAssetAttachments: assetAttachmentAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tinitializeAssetAttachments,\n\taddAssetAttachment,\n\taddAssetAttachments,\n\tsetAssetAttachment,\n\tsetAssetAttachments,\n\tupdateAssetAttachment,\n\tupdateAssetAttachments,\n\tdeleteAssetAttachment,\n\tdeleteAssetAttachments,\n} = assetAttachmentSlice.actions\n\nexport const selectAssetAttachmentMapping = (state: OvermapRootState) => state.assetAttachmentReducer.instances\n\nexport const selectAssetAttachments: OvermapSelector<Stored<AssetAttachment>[]> = createSelector(\n\t[selectAssetAttachmentMapping],\n\t(mapping) => Object.values(mapping),\n)\n\nexport const selectAssetAttachment: OvermapSelectorWithArgs<string, Stored<AssetAttachment>> =\n\t(attachmentId: string) => (state) => {\n\t\treturn state.assetAttachmentReducer.instances[attachmentId]\n\t}\n\nexport const selectAttachmentsOfAsset = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectAssetAttachments, (_state: OvermapRootState, assetId: string) => assetId],\n\t\t(attachments, assetId) => {\n\t\t\treturn attachments.filter(({ asset }) => assetId === asset)\n\t\t},\n\t),\n)\n\nexport const selectAttachmentsOfAssetByType = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectAssetAttachments, (_state: OvermapRootState, assetId: string) => assetId],\n\t\t(attachments, assetId) => {\n\t\t\tconst attachmentsOfAsset = attachments.filter(({ asset }) => assetId === asset)\n\t\t\tconst fileAttachments = attachmentsOfAsset.filter(\n\t\t\t\t// this null check here is necessary, there are cases where file_type is null or undefined\n\t\t\t\t({ file_type }) => !file_type || !file_type.startsWith(\"image/\"),\n\t\t\t)\n\t\t\tconst imageAttachments = attachmentsOfAsset.filter(\n\t\t\t\t// this null check here is necessary, there are cases where file_type is null or undefined\n\t\t\t\t({ file_type }) => file_type && file_type.startsWith(\"image/\"),\n\t\t\t)\n\t\t\treturn { fileAttachments, imageAttachments }\n\t\t},\n\t),\n)\n\nexport const assetAttachmentReducer: Reducer<AssetAttachmentState> = assetAttachmentSlice.reducer\n","import { createSlice, Reducer, PayloadAction, createSelector } from \"@reduxjs/toolkit\"\nimport {\n\tCompletedStagesMapping,\n\tAsset,\n\tOvermapRootState,\n\tOvermapSelectorWithArgs,\n\tAssetStageCompletion,\n} from \"../../typings\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport interface AssetStageCompletionState {\n\tcompletionsByAssetId: CompletedStagesMapping\n}\n\nconst initialState: AssetStageCompletionState = {\n\tcompletionsByAssetId: {},\n}\n\n// TODO: It would be much more performant if completions are stored with assetId keys and stageId[] values\nexport const assetStageCompletionSlice = createSlice({\n\tname: \"assetStageCompletions\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\taddStageCompletion: (state, action: PayloadAction<AssetStageCompletion>) => {\n\t\t\tlet stageToCompletionDateMapping = state.completionsByAssetId[action.payload.asset]\n\t\t\tif (!stageToCompletionDateMapping) {\n\t\t\t\tstageToCompletionDateMapping = {}\n\t\t\t\tstate.completionsByAssetId[action.payload.asset] = stageToCompletionDateMapping\n\t\t\t}\n\t\t\tstageToCompletionDateMapping[action.payload.stage] = new Date().toISOString()\n\t\t},\n\t\taddStageCompletions: (state, action: PayloadAction<CompletedStagesMapping>) => {\n\t\t\tfor (const [assetId, stageIdToCompletionDateMapping] of Object.entries(action.payload)) {\n\t\t\t\tif (Object.keys(stageIdToCompletionDateMapping).length === 0)\n\t\t\t\t\tthrow new Error(`Encountered empty stageIdToCompletionDateMapping argument for asset ${assetId}`)\n\t\t\t\tlet thisAssetCompletions = state.completionsByAssetId[assetId]\n\t\t\t\tif (thisAssetCompletions === undefined) {\n\t\t\t\t\tthisAssetCompletions = {}\n\t\t\t\t}\n\n\t\t\t\tfor (const [stageId, completionDate] of Object.entries(stageIdToCompletionDateMapping)) {\n\t\t\t\t\tthisAssetCompletions[stageId] = completionDate\n\t\t\t\t}\n\n\t\t\t\tstate.completionsByAssetId[assetId] = thisAssetCompletions\n\t\t\t}\n\t\t},\n\t\tremoveStageCompletions: (state, action: PayloadAction<AssetStageCompletion[]>) => {\n\t\t\tfor (const completion of action.payload) {\n\t\t\t\tconst thisAssetCompletions = state.completionsByAssetId[completion.asset]\n\n\t\t\t\tif (!thisAssetCompletions || !(completion.stage in thisAssetCompletions)) {\n\t\t\t\t\t// TODO: This should be an error. We should not construct completions to remove if the stage is not\n\t\t\t\t\t// completed for the asset.\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\"Skipping removal of uncompleted stage. This message indicates completion objects \" +\n\t\t\t\t\t\t\t\"are created unnecessarily.\",\n\t\t\t\t\t)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tdelete thisAssetCompletions[completion.stage]\n\t\t\t}\n\t\t},\n\t\tsetStageCompletions: (state, action: PayloadAction<CompletedStagesMapping>) => {\n\t\t\tstate.completionsByAssetId = action.payload\n\t\t},\n\t},\n})\nexport const { addStageCompletion, addStageCompletions, removeStageCompletions, setStageCompletions } =\n\tassetStageCompletionSlice.actions\n\nexport const selectCompletedStages = (state: OvermapRootState) => {\n\treturn state.assetStageCompletionReducer.completionsByAssetId\n}\n\nexport const selectCompletedStageIdsForAsset: OvermapSelectorWithArgs<Asset, string[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector([selectCompletedStages, (_state, asset: Asset) => asset], (completedStages, asset) => {\n\t\t\treturn Object.keys(completedStages[asset.offline_id] ?? {})\n\t\t}),\n\t)\n\nexport const assetStageCompletionReducer: Reducer<AssetStageCompletionState> = assetStageCompletionSlice.reducer\n","import { createSlice, createSelector, Reducer } from \"@reduxjs/toolkit\"\nimport {\n\tAssetTypeAttachment,\n\ttype OvermapRootState,\n\ttype OvermapSelector,\n\ttype OvermapSelectorWithArgs,\n\tStored,\n} from \"../../typings\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport type AssetTypeAttachmentState = ModelState<Stored<AssetTypeAttachment>>\n\nconst assetTypeAttachmentAdapter = createModelAdapter<Stored<AssetTypeAttachment>>(\n\t(attachment) => attachment.offline_id,\n)\n\nconst initialState = assetTypeAttachmentAdapter.getInitialState({})\n\nexport const assetTypeAttachmentSlice = createSlice({\n\tname: \"assetTypeAttachments\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeAssetTypeAttachments: assetTypeAttachmentAdapter.initialize,\n\t\taddAssetTypeAttachment: assetTypeAttachmentAdapter.addOne,\n\t\taddAssetTypeAttachments: assetTypeAttachmentAdapter.addMany,\n\t\tsetAssetTypeAttachment: assetTypeAttachmentAdapter.setOne,\n\t\tsetAssetTypeAttachments: assetTypeAttachmentAdapter.setMany,\n\t\tupdateAssetTypeAttachment: assetTypeAttachmentAdapter.updateOne,\n\t\tupdateAssetTypeAttachments: assetTypeAttachmentAdapter.updateMany,\n\t\tdeleteAssetTypeAttachment: assetTypeAttachmentAdapter.deleteOne,\n\t\tdeleteAssetTypeAttachments: assetTypeAttachmentAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tinitializeAssetTypeAttachments,\n\taddAssetTypeAttachment,\n\taddAssetTypeAttachments,\n\tsetAssetTypeAttachment,\n\tsetAssetTypeAttachments,\n\tupdateAssetTypeAttachment,\n\tupdateAssetTypeAttachments,\n\tdeleteAssetTypeAttachment,\n\tdeleteAssetTypeAttachments,\n} = assetTypeAttachmentSlice.actions\n\nexport const selectAssetTypeAttachmentMapping = (state: OvermapRootState) => state.assetTypeAttachmentReducer.instances\n\nexport const selectAssetTypeAttachments: OvermapSelector<Stored<AssetTypeAttachment>[]> = createSelector(\n\t[selectAssetTypeAttachmentMapping],\n\t(mapping) => Object.values(mapping),\n)\n\nexport const selectAssetTypeAttachment: OvermapSelectorWithArgs<string, Stored<AssetTypeAttachment>> =\n\t(attachmentId: string) => (state) => {\n\t\treturn state.assetTypeAttachmentReducer.instances[attachmentId]\n\t}\n\nexport const selectAttachmentsOfAssetType = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectAssetTypeAttachments, (_state: OvermapRootState, assetTypeId: string) => assetTypeId],\n\t\t(attachments, assetTypeId) => {\n\t\t\treturn attachments.filter(({ asset_type }) => assetTypeId === asset_type)\n\t\t},\n\t),\n)\n\nexport const selectAttachmentsOfAssetTypeByType = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectAssetTypeAttachments, (_state: OvermapRootState, assetTypeId: string) => assetTypeId],\n\t\t(attachments, assetTypeId) => {\n\t\t\tconst attachmentsOfAssetType = attachments.filter(({ asset_type }) => asset_type === assetTypeId)\n\t\t\tconst fileAttachments = attachmentsOfAssetType.filter(\n\t\t\t\t// this null check here is necessary, there are cases where file_type is null or undefined\n\t\t\t\t({ file_type }) => !file_type || !file_type.startsWith(\"image/\"),\n\t\t\t)\n\t\t\tconst imageAttachments = attachmentsOfAssetType.filter(\n\t\t\t\t// this null check here is necessary, there are cases where file_type is null or undefined\n\t\t\t\t({ file_type }) => file_type && file_type.startsWith(\"image/\"),\n\t\t\t)\n\t\t\treturn { fileAttachments, imageAttachments }\n\t\t},\n\t),\n)\n\nexport const assetTypeAttachmentReducer: Reducer<AssetTypeAttachmentState> = assetTypeAttachmentSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport { OvermapRootState, OvermapSelector, OvermapSelectorWithArgs, Stored, Workspace } from \"../../typings\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\n\nexport type WorkspaceState = ModelState<Workspace>\n\nconst workspaceAdapter = createModelAdapter<Workspace>((workspace) => workspace.offline_id)\n\nconst initialState: WorkspaceState = workspaceAdapter.getInitialState({})\n\nexport const workspaceSlice = createSlice({\n\tname: \"workspace\",\n\tinitialState,\n\treducers: {\n\t\tinitializeWorkspaces: workspaceAdapter.initialize,\n\t\tsetWorkspaces: workspaceAdapter.setMany,\n\t\taddWorkspace: workspaceAdapter.addOne,\n\t\tupdateWorkspace: workspaceAdapter.updateOne,\n\t\tdeleteWorkspace: workspaceAdapter.deleteOne,\n\t},\n})\n\nexport const { initializeWorkspaces, setWorkspaces, addWorkspace, updateWorkspace, deleteWorkspace } =\n\tworkspaceSlice.actions\n\nexport const selectWorkspaceMapping: OvermapSelector<Record<string, Workspace>> = (state: OvermapRootState) =>\n\tstate.workspaceReducer.instances\n\nexport const selectWorkspaces = createSelector([selectWorkspaceMapping], (mapping) => Object.values(mapping))\n\nexport const selectMainWorkspace: OvermapSelector<Workspace | undefined> = createSelector(\n\t[selectWorkspaces],\n\t(workspaces) => {\n\t\treturn workspaces.find((workspace) => workspace.name.toLowerCase() === \"main\")\n\t},\n)\n\nexport const selectWorkspaceById: OvermapSelectorWithArgs<string, Stored<Workspace>> = (workspaceId) => (state) => {\n\treturn state.workspaceReducer.instances[workspaceId]\n}\n\nexport const selectPermittedWorkspaceIds: OvermapSelector<Set<string>> = createSelector(\n\t[selectWorkspaceMapping],\n\t(mapping) => {\n\t\treturn new Set(\n\t\t\tObject.values(mapping)\n\t\t\t\t.filter((workspace: Workspace) => workspace.permitted)\n\t\t\t\t.map((workspace: Workspace) => workspace.offline_id),\n\t\t)\n\t},\n)\n\nexport const workspaceReducer: Reducer<WorkspaceState> = workspaceSlice.reducer\n","import { createSelector, createSlice, PayloadAction, Reducer } from \"@reduxjs/toolkit\"\nimport {\n\tIssue,\n\tOvermapRootState,\n\tOvermapSelector,\n\tOvermapSelectorWithArgs,\n\tSearchableRecentResult,\n\tSearchArgs,\n\tSearchResult,\n\tStored,\n} from \"../../typings\"\nimport { issueToSearchResult, logOnlyOnce, restructureCreateSelectorWithArgs } from \"../../utils\"\nimport { selectWorkspaceMapping } from \"./workspaceSlice\"\nimport { createModelAdapter } from \"../adapter\"\nimport { ModelState } from \"../typings\"\n\nconst maxRecentIssues = 10\ninterface RecentIssueId {\n\tofflineId: string\n\tlastOpenedEpochTime: number\n}\n\nexport interface IssueState extends ModelState<Stored<Issue>> {\n\trecentIssueIds: RecentIssueId[]\n}\n\nconst issueAdapter = createModelAdapter<Stored<Issue>>((issue) => issue.offline_id)\n\nconst initialState: IssueState = issueAdapter.getInitialState({\n\trecentIssueIds: [],\n})\n\nexport const issueSlice = createSlice({\n\tname: \"issues\",\n\tinitialState,\n\textraReducers: (builder) =>\n\t\tbuilder.addCase(\"RESET\", (state) => {\n\t\t\tObject.assign(state, initialState)\n\t\t}),\n\treducers: {\n\t\tinitializeIssues: issueAdapter.initialize,\n\t\taddIssue: issueAdapter.addOne,\n\t\taddIssues: issueAdapter.addMany,\n\t\tupdateIssue: issueAdapter.updateOne,\n\t\tdeleteIssue: issueAdapter.deleteOne,\n\t\tdeleteIssues: issueAdapter.deleteMany,\n\n\t\tcleanRecentIssues: (state) => {\n\t\t\tstate.recentIssueIds = state.recentIssueIds.filter((recentIssue) => state.instances[recentIssue.offlineId])\n\t\t},\n\t\taddToRecentIssues: (state, action: { payload: string }) => {\n\t\t\tstate.recentIssueIds = state.recentIssueIds.filter(\n\t\t\t\t(recentIssue) => recentIssue.offlineId !== action.payload,\n\t\t\t)\n\t\t\tstate.recentIssueIds.push({ offlineId: action.payload.toLowerCase(), lastOpenedEpochTime: Date.now() })\n\n\t\t\tif (state.recentIssueIds.length > maxRecentIssues) {\n\t\t\t\tstate.recentIssueIds.shift()\n\t\t\t}\n\t\t},\n\t\tresetRecentIssues: (state) => {\n\t\t\tstate.recentIssueIds = []\n\t\t},\n\t\tremoveRecentIssue: (state, action: PayloadAction<string>) => {\n\t\t\tconst indexToRemove = state.recentIssueIds.findIndex((item) => {\n\t\t\t\treturn item.offlineId == action.payload\n\t\t\t})\n\t\t\tif (indexToRemove !== -1) {\n\t\t\t\tstate.recentIssueIds.splice(indexToRemove, 1)\n\t\t\t}\n\t\t},\n\t},\n})\n\nexport const {\n\tinitializeIssues,\n\taddIssue,\n\taddIssues,\n\tupdateIssue,\n\tdeleteIssue,\n\tdeleteIssues,\n\n\taddToRecentIssues,\n\tcleanRecentIssues,\n\tremoveRecentIssue,\n\tresetRecentIssues,\n} = issueSlice.actions\n\nexport interface IssueFilterArgs {\n\tfilterByAssignedTo: boolean\n\tfilterByStatus: boolean\n\tfilterByCategory: boolean\n\tfilterByWorkspace: boolean\n}\n\nexport const selectIssueMapping = (state: OvermapRootState) => state.issueReducer.instances\nexport const selectRecentIssueIds = (state: OvermapRootState) => state.issueReducer.recentIssueIds\n\nexport const selectIssueById: OvermapSelectorWithArgs<string, Stored<Issue>> =\n\t(id: string) => (state: OvermapRootState) => {\n\t\treturn state.issueReducer.instances[id]\n\t}\n\n// TODO: Cache?\nexport const searchIssues: OvermapSelectorWithArgs<SearchArgs, SearchResult<Stored<Issue>>[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector(\n\t\t\t[selectIssueMapping, selectWorkspaceMapping, (_state, searchArgs: SearchArgs) => searchArgs],\n\t\t\t(mapping, workspaceMapping, searchArgs) => {\n\t\t\t\tlet searchTerm = searchArgs.searchTerm\n\t\t\t\tconst maxResults = searchArgs.maxResults\n\t\t\t\tsearchTerm = searchTerm.toLowerCase()\n\t\t\t\tconst ret: SearchResult<Stored<Issue>>[] = []\n\t\t\t\tconst issues = Object.values(mapping)\n\t\t\t\t// This is more performant than repeatedly calling .length\n\t\t\t\tlet nbResults = 0\n\t\t\t\tfor (const issue of issues) {\n\t\t\t\t\t// First, get rid of any issues with no index_workspace. This can happen if the index workspace was deleted,\n\t\t\t\t\t// but the server hasn't responded with a new index in the main workspace. If no index_workspace is\n\t\t\t\t\t// available, we can't calculate the \"tag\" of the search result.\n\t\t\t\t\t// TODO: It's still possible to support search by showing a blank tag.\n\t\t\t\t\tif (!issue.index_workspace) {\n\t\t\t\t\t\tlogOnlyOnce(\n\t\t\t\t\t\t\t\"issue-has-no-index-workspace\",\n\t\t\t\t\t\t\tissue.offline_id,\n\t\t\t\t\t\t\t\"warn\",\n\t\t\t\t\t\t\t`Issue ${issue.offline_id} has no index_workspace and cannot be searched.`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tconst workspace = workspaceMapping[issue.index_workspace]\n\n\t\t\t\t\tif (!workspace) {\n\t\t\t\t\t\tlogOnlyOnce(\n\t\t\t\t\t\t\t\"issue-has-non-existent-index-workspace\",\n\t\t\t\t\t\t\tissue.offline_id,\n\t\t\t\t\t\t\t\"warn\",\n\t\t\t\t\t\t\t`Encountered issue with an index_workspace that doesn't exist. Issue ${issue.offline_id} has \n\t\t\t\t\tindex_workspace = ${issue.index_workspace}, which does not exist in:`,\n\t\t\t\t\t\t\tObject.keys(workspaceMapping),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\n\t\t\t\t\tconst workspaceAbbreviation = workspace.abbreviation\n\t\t\t\t\tif (!workspaceAbbreviation) {\n\t\t\t\t\t\tlogOnlyOnce(\n\t\t\t\t\t\t\t\"workspace-has-no-abbreviation\",\n\t\t\t\t\t\t\tworkspace.offline_id,\n\t\t\t\t\t\t\t\"error\",\n\t\t\t\t\t\t\t`Workspace ${workspace.name} has no abbreviation. Not including any issues in search.`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tconst tag = \"index\" in issue ? `${workspaceAbbreviation.toUpperCase()}-${issue.index}` : null\n\t\t\t\t\tif (\n\t\t\t\t\t\t(issue.title || \"\").toLowerCase().includes(searchTerm) ||\n\t\t\t\t\t\t(tag && tag.toLowerCase().includes(searchTerm))\n\t\t\t\t\t) {\n\t\t\t\t\t\tret.push(issueToSearchResult(issue, tag))\n\t\t\t\t\t\tnbResults++\n\t\t\t\t\t\tif (maxResults && nbResults >= maxResults) {\n\t\t\t\t\t\t\treturn ret\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn ret\n\t\t\t},\n\t\t),\n\t)\n\nexport const selectIssuesByIds = restructureCreateSelectorWithArgs(\n\tcreateSelector([selectIssueMapping, (_, issueIds: string[]) => issueIds], (issuesMapping, issueIds) => {\n\t\tconst issues: Stored<Issue>[] = []\n\n\t\tfor (const issueId of issueIds) {\n\t\t\tconst issue = issuesMapping[issueId]\n\t\t\tif (issue) {\n\t\t\t\tissues.push(issue)\n\t\t\t} else {\n\t\t\t\tconsole.warn(\"selectIssuesByIds: No issue exists with the id\", issueId)\n\t\t\t}\n\t\t}\n\n\t\treturn issues\n\t}),\n)\n\nexport const selectRecentIssuesAsSearchResults: OvermapSelector<SearchableRecentResult<Stored<Issue>>[]> =\n\tcreateSelector(\n\t\t[selectIssueMapping, selectRecentIssueIds, selectWorkspaceMapping],\n\t\t(issueMapping, recentIssueIds, workspaceMapping) => {\n\t\t\tconst ret: SearchableRecentResult<Stored<Issue>>[] = []\n\t\t\tfor (const recentIssueResult of recentIssueIds) {\n\t\t\t\tconst issue = issueMapping[recentIssueResult.offlineId]\n\t\t\t\tif (!issue) {\n\t\t\t\t\t// Recent issue has been deleted. Remove it from the list.\n\t\t\t\t\tconsole.info(\"Recent issue no longer exists\")\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (\"index\" in issue && issue.index_workspace) {\n\t\t\t\t\tconst indexWorkspace = workspaceMapping[issue.index_workspace]\n\t\t\t\t\tif (!indexWorkspace) {\n\t\t\t\t\t\t// Prevent repeated logging, which hurts performance.\n\t\t\t\t\t\tlogOnlyOnce(\n\t\t\t\t\t\t\t\"issue-has-index-but-not-index-workspace\",\n\t\t\t\t\t\t\tissue.offline_id,\n\t\t\t\t\t\t\t\"warn\",\n\t\t\t\t\t\t\t`Issue ${issue.offline_id} has an index but no index_workspace. This may be because the \n\t\t\t\t\tworkspace has been deleted, but the new index has not been returned by the server yet. It will not\n\t\t\t\t\tbe included in search results.`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tconst workspaceTag = `${indexWorkspace.abbreviation}-${issue.index}`\n\t\t\t\t\tconst searchResult = {\n\t\t\t\t\t\t...issueToSearchResult(issue, workspaceTag),\n\t\t\t\t\t\tlastOpenedEpochTime: recentIssueResult.lastOpenedEpochTime,\n\t\t\t\t\t} satisfies SearchableRecentResult<Stored<Issue>>\n\t\t\t\t\tret.push(searchResult)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn ret\n\t\t},\n\t)\n\nexport const issueReducer: Reducer<IssueState> = issueSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport {\n\tIssue,\n\tIssueType,\n\tOrganization,\n\tOvermapRootState,\n\tOvermapSelector,\n\tOvermapSelectorWithArgs,\n\tStored,\n} from \"../../typings\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\nimport { createModelAdapter } from \"../adapter\"\nimport { ModelState } from \"../typings\"\n\n// TODO: add attachment support for issue type descriptions\n\nexport type IssueTypeState = ModelState<Stored<IssueType>>\n\nconst issueTypeAdapter = createModelAdapter<Stored<IssueType>>((issueType) => issueType.offline_id)\n\nconst initialState: IssueTypeState = issueTypeAdapter.getInitialState({})\n\nexport const issueTypeSlice = createSlice({\n\tname: \"issueTypes\",\n\tinitialState,\n\textraReducers: (builder) =>\n\t\tbuilder.addCase(\"RESET\", (state) => {\n\t\t\tObject.assign(state, initialState)\n\t\t}),\n\treducers: {\n\t\tinitializeIssueTypes: issueTypeAdapter.initialize,\n\t\tsetIssueType: issueTypeAdapter.setOne,\n\t\taddIssueType: issueTypeAdapter.addOne,\n\t\tupdateIssueType: issueTypeAdapter.updateOne,\n\t\tremoveIssueType: issueTypeAdapter.deleteOne,\n\t},\n})\n\nexport const { initializeIssueTypes, setIssueType, addIssueType, updateIssueType, removeIssueType } =\n\tissueTypeSlice.actions\n\nexport const selectIssueTypeMapping: OvermapSelector<IssueTypeState[\"instances\"]> = (state) => {\n\treturn state.issueTypeReducer.instances\n}\n\nexport const selectIssueTypes: OvermapSelector<Stored<IssueType>[]> = createSelector(\n\tselectIssueTypeMapping,\n\t(issueTypes) => {\n\t\treturn Object.values(issueTypes)\n\t},\n)\n\nexport const selectIssueTypeById: OvermapSelectorWithArgs<string, Stored<IssueType>> =\n\t(issueTypeId: string) => (state: OvermapRootState) => {\n\t\treturn state.issueTypeReducer.instances[issueTypeId]\n\t}\n\nexport const selectIssueTypesByIds: OvermapSelectorWithArgs<string[], Stored<IssueType>[]> =\n\t(issueTypeIds: string[]) => (state: OvermapRootState) => {\n\t\tconst issueTypes: Stored<IssueType>[] = []\n\n\t\tfor (const issueTypeId of issueTypeIds) {\n\t\t\tconst issueType = state.issueTypeReducer.instances[issueTypeId]\n\t\t\tif (issueType) {\n\t\t\t\tissueTypes.push(issueType)\n\t\t\t} else {\n\t\t\t\tconsole.warn(\"selectIssueTypesByIds: No issue type exists with the id\", issueTypeId)\n\t\t\t}\n\t\t}\n\n\t\treturn issueTypes\n\t}\n\nexport const selectIssueTypesOfOrganization: OvermapSelectorWithArgs<Organization[\"id\"], Stored<IssueType>[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector(\n\t\t\t[selectIssueTypes, (_, organizationId: number) => organizationId],\n\t\t\t(issueTypes, organizationId) => {\n\t\t\t\treturn issueTypes.filter((issueType) => issueType.organization === organizationId)\n\t\t\t},\n\t\t),\n\t)\n\nexport const selectIssuesOfIssueType: OvermapSelectorWithArgs<IssueType[\"offline_id\"], Stored<Issue>[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector(\n\t\t\t[(state: OvermapRootState) => state.issueReducer.instances, (_, issueTypeId: string) => issueTypeId],\n\t\t\t(issuesMapping, issueTypeId) => {\n\t\t\t\treturn Object.values(issuesMapping).filter((issue) => issue.issue_type === issueTypeId)\n\t\t\t},\n\t\t),\n\t)\n\nexport const selectIssuesOfIssueTypeCount: OvermapSelectorWithArgs<IssueType[\"offline_id\"], number> =\n\t(issueTypeId: string) => (state) => {\n\t\treturn selectIssuesOfIssueType(issueTypeId)(state)?.length ?? 0\n\t}\n\nexport const issueTypeReducer: Reducer<IssueTypeState> = issueTypeSlice.reducer\n","import { createSlice, PayloadAction, Reducer } from \"@reduxjs/toolkit\"\nimport { BaseState, SelectorWithArgs } from \"typings\"\n\ninterface S3UploadUrl {\n\turl: string\n\tfields: Record<string, string>\n\t/** the time the upload url expires */\n\texp?: number\n}\n\nexport interface FileState {\n\t// maps sha1 hash to upload URL\n\ts3Urls: Record<string, S3UploadUrl>\n}\n\ninterface S3UrlPayload {\n\tsha1: string\n\turl: string\n\tfields: Record<string, string>\n}\n\nconst initialState: FileState = {\n\ts3Urls: {},\n}\n\nconst msPerHour = 1000 * 60 * 60\nconst msPerWeek = msPerHour * 24 * 7\n\n/**\n * Stores the auth state of the app (tokens, and whether user is logged in or not)\n */\nexport const fileSlice = createSlice({\n\tname: \"file\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tsetUploadUrl: (state, action: PayloadAction<S3UrlPayload>) => {\n\t\t\tconst { url, fields, sha1 } = action.payload\n\t\t\tconst today = new Date()\n\t\t\tconst weekFromToday = new Date(today.getTime() + msPerWeek)\n\n\t\t\tstate.s3Urls[sha1] = {\n\t\t\t\turl,\n\t\t\t\tfields,\n\t\t\t\texp: weekFromToday.getTime(),\n\t\t\t}\n\t\t},\n\t},\n})\n\nexport const { setUploadUrl } = fileSlice.actions\n\nexport const selectUploadUrl: SelectorWithArgs<BaseState, string, S3UploadUrl> = (sha1: string) => (state) => {\n\tconst url = state.fileReducer.s3Urls[sha1]\n\tif (!url) {\n\t\treturn undefined\n\t}\n\n\tconst today = new Date().getTime()\n\tconst expiringWithinAnHour = (url.exp ?? today) - today < msPerHour\n\tif (expiringWithinAnHour) return undefined\n\n\treturn url\n}\n\nexport const fileReducer: Reducer<FileState> = fileSlice.reducer\n","import { OfflineModel } from \"./base\"\n\nexport interface ProjectAccess extends OfflineModel {\n\tuser: number\n\tproject: number\n\taccess_level: ProjectAccessLevel\n\tview_only: boolean\n}\n\nexport enum ProjectAccessLevel {\n\tBASIC = 0,\n\tADMIN = 2,\n}\n\nexport interface OrganizationAccess extends OfflineModel {\n\tuser: number\n\torganization: number\n\taccess_level: OrganizationAccessLevel\n}\n\n// TODO: Move\nexport enum OrganizationAccessLevel {\n\tBASIC = 0,\n\tADMIN = 2,\n}\n","import { CreatedByModel, OfflineModel, SubmittedAtModel } from \"./base\"\nimport { FileModel, FileWithNameModel, MaybeObjectURL } from \"../files\"\n\nexport interface Attachment extends OfflineModel, SubmittedAtModel, FileWithNameModel, CreatedByModel {\n\tdescription?: string\n\tfile_type: string\n}\n\nexport interface IssueAttachment extends Attachment {\n\tissue: string\n}\n\nexport interface AssetAttachment extends Attachment {\n\tasset: string\n}\n\nexport interface AssetTypeAttachment extends Attachment {\n\tasset_type: string\n}\n\nexport interface ProjectAttachment extends Attachment {\n\tproject: number\n}\n\nexport interface DocumentAttachment extends Attachment {\n\tdocument: string\n}\n\nexport enum AttachmentModel {\n\tIssue = \"issue\",\n\tAsset = \"asset\",\n\tAssetType = \"asset_type\",\n\tProject = \"project\",\n\tDocument = \"document\",\n}\n\n/** to get an AttachmentPayload for a specific type, pass in the given AttachmentType\n * ex. AttachmentPayload<IssueAttachment> */\nexport type AttachmentPayload<TAttachment> = Omit<TAttachment, \"file\" | \"submitted_at\" | \"created_by\"> & {\n\tfile: MaybeObjectURL<File>\n}\n\nexport type ProfilePic = FileModel\n","// This is not a model, but a set of fields that can also be used for issue forms where there are no attachments yet\nimport type { CreatedByModel, Offline, OfflineModel, SubmittedAtModel } from \"./base\"\nimport { IssuePriority, IssueStatus } from \"../../enums\"\nimport type { WorkspaceIndexedModel } from \"./workspace\"\nimport type { CanvasMarkableModel, MarkableModel } from \"./geo\"\nimport type { CreatedForm, Form, SubmittedForm } from \"./forms\"\nimport type { User } from \"./users\"\nimport type { CSSColor } from \"../colors\"\n\n// TODO: Add more ternary operations for other models. I think this will be a good pattern. Move elsewhere.\n// TODO: Remove \"id\" from Omit when it's no longer used (only use offline_id)\n/**\n * Represents a model instance that has been submitted to the backend. Some properties (depending on which model, but in\n * all cases, the `offline_id`) are guaranteed to be set.\n */\nexport type Submitted<TModel> = Offline<TModel> &\n\t(TModel extends Issue\n\t\t? SubmittedIssue\n\t\t: TModel extends Form\n\t\t? SubmittedForm\n\t\t: Omit<TModel, \"created_at\" | \"created_by\" | \"id\">)\n/**\n * Represents a model instance that has been submitted to the backend, accepted, then downloaded. Created models\n * typically have additional properties that are only known once it has been processed and accepted by the API, such as\n * the `created_at` timestamp, which is the time at which the data was written to the database.\n */\nexport type Created<TModel> = Submitted<TModel> &\n\t(TModel extends Issue\n\t\t? CreatedIssue\n\t\t: TModel extends IssueComment\n\t\t? CreatedIssueComment\n\t\t: TModel extends Form\n\t\t? CreatedForm\n\t\t: TModel)\n/**\n * Model instances that are stored in the Redux store can be already-created (and will likely be gotten with the initial\n * data load), or to-be-created. In the former case, you will get a `Created<TModel>`. In the latter case, you will get\n * a `Submitted<TModel>`.\n */\nexport type Stored<TModel> = Created<TModel> | Submitted<TModel>\n\n/**\n * Represents the properties you can always expect on any object representing an issue. These are the minimal details\n * required when creating an issue.\n */\nexport interface Issue extends Pick<WorkspaceIndexedModel, \"index_workspace\">, MarkableModel, CanvasMarkableModel {\n\ttitle?: string | null\n\tdescription?: string | null\n\tpriority?: IssuePriority\n\tstatus?: IssueStatus\n\tassigned_to?: number | null\n\tdue_date?: string | Date | null\n\tcategory?: string | null\n\tvisible_in_workspaces: string[]\n\t// TODO: add issue_type here\n\tissue_type?: string | null\n}\n\n/**\n * These details need to be provided by the frontend code before submitting to the backend.\n */\nexport interface SubmittedIssue extends OfflineModel, CreatedByModel {\n\tsubmitted_at: string\n\tstatus: Exclude<Issue[\"status\"], undefined>\n\tpriority: Exclude<Issue[\"priority\"], undefined>\n}\n\n/**\n * These details exist on issues that have been successfully submitted, accepted, created, and serialized by the\n * backend, then downloaded by the frontend.\n */\nexport interface CreatedIssue extends SubmittedIssue, Pick<WorkspaceIndexedModel, \"index\"> {\n\t// Some of these have defaults in the backend, so they will have some defined value once created. Others can be\n\t// null, but not undefined.\n\ttitle: Exclude<Issue[\"title\"], undefined>\n\tdescription: Exclude<Issue[\"description\"], undefined>\n\tassigned_to: Exclude<Issue[\"assigned_to\"], undefined>\n\tdue_date: Exclude<Issue[\"due_date\"], undefined>\n\tcategory: Exclude<Issue[\"category\"], undefined>\n\tgeo_marker: Exclude<Issue[\"geo_marker\"], undefined>\n\n\t// These are generated by the backend upon receipt of the Issue payload. (`created_by` is also included in this, but\n\t// we can safely assume the current user will be the creator, so we set it when submitting, so it's available in the\n\t// store\n\tcreated_at: string\n}\n\nexport interface IssueComment extends OfflineModel {\n\tissue: string\n\tcontent: string\n\tauthor?: number\n\tcreated_at?: string\n\tsubmitted_at: string\n}\n\nexport interface SubmittedIssueComment {\n\tcreated_at: Exclude<IssueComment[\"created_at\"], undefined>\n}\n\nexport interface CreatedIssueComment {\n\tauthor: Exclude<IssueComment[\"author\"], undefined>\n\tcreated_at: Exclude<IssueComment[\"created_at\"], undefined>\n}\n\nexport type IssueCommentPayload = Omit<IssueComment, \"author\" | \"created_at\" | \"offline_id\">\n\nexport enum IssueUpdateChange {\n\tSTATUS = \"status\",\n\tPRIORITY = \"priority\",\n\tCATEGORY = \"category\",\n\tDESCRIPTION = \"description\",\n\tTITLE = \"title\",\n\tASSIGNED_TO = \"assigned_to\",\n\tDUE_DATE = \"due_date\",\n}\n\nexport interface IssueUpdateChangeTypes {\n\tstatus: IssueStatus\n\tpriority: IssuePriority\n\tcategory: {\n\t\tname: string\n\t\tcolor: CSSColor\n\t\toffline_id: OfflineModel[\"offline_id\"]\n\t} | null\n\tdescription: string\n\ttitle: string\n\tassigned_to: {\n\t\tfull_name: string\n\t\tid: User[\"id\"]\n\t} | null\n\tdue_date: string\n}\n\nexport interface IssueUpdate extends OfflineModel, CreatedByModel {\n\tsubmitted_at: string\n\tissue: OfflineModel[\"offline_id\"]\n\tchanges: Partial<Record<IssueUpdateChange, IssueUpdateChangeTypes[IssueUpdateChange]>>\n}\n\nexport interface IssueAssociation extends OfflineModel, SubmittedAtModel, CreatedByModel {\n\tassociated_issue: string\n\tissue?: string\n\tasset?: string\n}\n","import { RegistrationPayload } from \"./users\"\nimport { OfflineModel } from \"./base\"\n\nexport type EmailVerificationPayload = undefined | RegistrationPayload | Omit<RegistrationPayload, \"username\" | \"email\">\n\nexport interface EmailVerificationReturn {\n\tusername?: string\n\tproject?: number\n}\n\nexport enum VerificationCodeType {\n\tUSER_REGISTRATION = 0,\n\tAPPLICATION_INVITE = 2,\n\tPROJECT_INVITE = 4,\n\tORGANIZATION_INVITE = 6,\n\tADD_EMAIL_DOMAIN = 8,\n\tRESET_PASSWORD = 10,\n}\n\nexport interface VerificationCode extends OfflineModel {\n\tverification_code: string\n\tverification_type: VerificationCodeType\n\torganization?: number\n\tproject?: number\n\tuser?: number\n}\n","import { OfflineModel, OwnedByUserOrOrganization } from \"./base\"\n\nexport enum PaddleCheckoutEvent {\n\tCOMPLETED = \"checkout.completed\",\n\tCLOSED = \"checkout.closed\",\n}\nexport enum LicenseLevel {\n\tPRO = 0,\n}\n\nexport enum LicenseStatus {\n\tACTIVE = 0,\n\tPAUSED = 2,\n\tCANCELLED = 4,\n\tINACTIVE = 6,\n\tPAST_DUE = 8,\n}\n\nexport interface Transaction {\n\tid: string\n}\n\nexport interface License extends OfflineModel, OwnedByUserOrOrganization {\n\tproject: number | null\n\tlevel: LicenseLevel\n\tstatus: LicenseStatus\n\tis_special: boolean\n\tis_active: boolean\n\tnext_billing_date: Date\n}\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport { OvermapRootState, OvermapSelectorWithArgs, User } from \"../../typings\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport interface UserState {\n\tcurrentUser: User\n\tusers: Record<number, User>\n}\n\nconst initialState: UserState = {\n\tusers: {},\n\tcurrentUser: {\n\t\tid: 0,\n\t\tusername: \"\",\n\t\temail: \"\",\n\t\tprofile: { file: null, file_sha1: null, favourite_project_ids: [], tour_step: -1 },\n\t},\n}\n\nexport const userSlice = createSlice({\n\tname: \"users\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tsetUsers: (state, action: { payload: User[] }) => {\n\t\t\tconst usersMapping: Record<string, User> = {}\n\t\t\taction.payload.forEach((user) => {\n\t\t\t\tusersMapping[user.id] = user\n\t\t\t})\n\t\t\tstate.users = usersMapping\n\t\t},\n\t\taddUsers: (state, action: { payload: User[] }) => {\n\t\t\tfor (const user of action.payload) {\n\t\t\t\tstate.users[user.id] = user\n\t\t\t}\n\t\t},\n\t\tsetCurrentUser: (state, action: { payload: User }) => {\n\t\t\tstate.currentUser = action.payload\n\t\t},\n\t\tsetProfilePicture: (state, action: { payload: { file?: string; file_sha1?: string } }) => {\n\t\t\tstate.currentUser.profile.file = action.payload.file ?? null\n\t\t\tstate.currentUser.profile.file_sha1 = action.payload.file_sha1 ?? null\n\n\t\t\tconst currentUser = state.users[state.currentUser.id]\n\n\t\t\tif (!currentUser) {\n\t\t\t\tthrow new Error(\"Unable to find current user in users slice\")\n\t\t\t}\n\n\t\t\tcurrentUser.profile.file = action.payload.file ?? null\n\t\t\tcurrentUser.profile.file_sha1 = action.payload.file_sha1 ?? null\n\t\t},\n\t\taddFavouriteProjectId: (state, action: { payload: number }) => {\n\t\t\tstate.currentUser.profile.favourite_project_ids.push(action.payload)\n\t\t},\n\t\tremoveFavouriteProjectId: (state, action: { payload: number }) => {\n\t\t\tstate.currentUser.profile.favourite_project_ids = state.currentUser.profile.favourite_project_ids.filter(\n\t\t\t\t(id) => id !== action.payload,\n\t\t\t)\n\t\t},\n\t\tsetTourStep: (state, action: { payload: number }) => {\n\t\t\tstate.currentUser.profile.tour_step = action.payload\n\t\t},\n\t\tremoveUser: (state, action: { payload: number }) => {\n\t\t\tdelete state.users[action.payload]\n\t\t},\n\t},\n})\n\nexport const {\n\tsetCurrentUser,\n\tsetProfilePicture,\n\tsetUsers,\n\taddUsers,\n\taddFavouriteProjectId,\n\tremoveFavouriteProjectId,\n\tsetTourStep,\n\tremoveUser,\n} = userSlice.actions\n\nexport const userReducer: Reducer<UserState> = userSlice.reducer\n\nexport const selectCurrentUser = (state: OvermapRootState) => state.userReducer.currentUser\n\nexport const selectUsersMapping = (state: OvermapRootState) => state.userReducer.users\n\nexport const selectUser: OvermapSelectorWithArgs<number | null, User | undefined> = (userId) => (state) => {\n\tif (userId === null) return undefined\n\treturn state.userReducer.users[userId]\n}\n\nexport const selectUserById: OvermapSelectorWithArgs<number, User> = (userId) => (state) => {\n\treturn state.userReducer.users[userId]\n}\n\nexport const selectUsersByIds: OvermapSelectorWithArgs<number[], User[]> = restructureCreateSelectorWithArgs(\n\tcreateSelector([selectUsersMapping, (_state, userIds: number[]) => userIds], (usersMapping, userIds) => {\n\t\tconst users: User[] = []\n\n\t\tfor (const userId of userIds) {\n\t\t\tconst user = usersMapping[userId]\n\t\t\tif (user) {\n\t\t\t\tusers.push(user)\n\t\t\t} else {\n\t\t\t\tconsole.warn(\"selectUsersByIds: No user exists with the id\", userId)\n\t\t\t}\n\t\t}\n\n\t\treturn users\n\t}),\n)\n\nexport const selectFavouriteProjects = (state: OvermapRootState): number[] =>\n\tstate.userReducer.currentUser.profile.favourite_project_ids\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport { OvermapRootState, OvermapSelector, OvermapSelectorWithArgs } from \"typings\"\nimport { OfflineIdMapping, OrganizationAccess, User } from \"typings/models\"\nimport { selectCurrentUser } from \"./userSlice\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\n\nexport type OrganizationAccessState = ModelState<OrganizationAccess>\n\nconst organizationAccessAdapter = createModelAdapter<OrganizationAccess>(\n\t(organizationAccess) => organizationAccess.offline_id,\n)\n\nconst initialState: OrganizationAccessState = organizationAccessAdapter.getInitialState({})\n\nexport const organizationAccessSlice = createSlice({\n\tname: \"organizationAccess\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeOrganizationAccesses: organizationAccessAdapter.initialize,\n\t\tupdateOrganizationAccess: organizationAccessAdapter.updateOne,\n\t\tdeleteOrganizationAccess: organizationAccessAdapter.deleteOne,\n\t},\n})\n\nexport const { initializeOrganizationAccesses, updateOrganizationAccess, deleteOrganizationAccess } =\n\torganizationAccessSlice.actions\n\nexport const selectOrganizationAccesses = (state: OvermapRootState) => {\n\treturn state.organizationAccessReducer.instances\n}\n\nexport const selectOrganizationAccessById: OvermapSelectorWithArgs<string, OrganizationAccess> =\n\t(organizationAccessId: string) => (state: OvermapRootState) => {\n\t\treturn state.organizationAccessReducer.instances[organizationAccessId]\n\t}\n\nexport const selectActiveOrganizationAccess: OvermapSelector<OrganizationAccess | null> = createSelector(\n\t[selectCurrentUser, selectOrganizationAccesses],\n\t(currentUser: User, organizationAccesses: OfflineIdMapping<OrganizationAccess>) => {\n\t\tconst activeOrganizationAccess = Object.values(organizationAccesses).find(\n\t\t\t(organizationAccess: OrganizationAccess) => organizationAccess.user === currentUser.id,\n\t\t)\n\t\treturn activeOrganizationAccess ?? null\n\t},\n)\n\nexport const selectOrganizationAccessForUser: OvermapSelectorWithArgs<User, OrganizationAccess | undefined> =\n\t(user: User) => (state: OvermapRootState) => {\n\t\treturn Object.values(state.organizationAccessReducer.instances).find(\n\t\t\t(organizationAccess: OrganizationAccess) => organizationAccess.user === user.id,\n\t\t)\n\t}\n\nexport const selectOrganizationAccessUserMapping = (state: OvermapRootState): Record<number, OrganizationAccess> => {\n\tconst organizationAccesses: Record<number, OrganizationAccess> = {}\n\tfor (const organizationAccess of Object.values(state.organizationAccessReducer.instances)) {\n\t\torganizationAccesses[organizationAccess.user] = organizationAccess\n\t}\n\treturn organizationAccesses\n}\n\nexport const organizationAccessReducer: Reducer<OrganizationAccessState> = organizationAccessSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport { License, OvermapRootState, OvermapSelector, OvermapSelectorWithArgs } from \"../../typings\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\n\nexport type LicenseState = ModelState<License>\n\nconst licenseAdapter = createModelAdapter<License>((license) => license.offline_id)\n\nconst initialState: LicenseState = licenseAdapter.getInitialState({})\n\nexport const licenseSlice = createSlice({\n\tname: \"license\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeLicences: licenseAdapter.initialize,\n\t\taddLicenses: licenseAdapter.addMany,\n\t\tupdateLicense: licenseAdapter.updateOne,\n\t},\n})\n\nexport const { initializeLicences, addLicenses, updateLicense } = licenseSlice.actions\n\nexport const selectLicenses: OvermapSelector<Record<string, License>> = (state: OvermapRootState) => {\n\treturn state.licenseReducer.instances\n}\n\nexport const selectLicense: OvermapSelectorWithArgs<string, License> =\n\t(licenseId: string) => (state: OvermapRootState) =>\n\t\tstate.licenseReducer.instances[licenseId]\n\nexport const selectActiveLicense: OvermapSelector<License | null> = (state: OvermapRootState) =>\n\tObject.values(state.licenseReducer.instances).find(\n\t\t(license) => license.project === state.projectReducer.activeProjectId,\n\t) ?? null\n\nexport const selectLicenseForProject: OvermapSelectorWithArgs<number, License | undefined> =\n\t(projectId: number) => (state: OvermapRootState) =>\n\t\tObject.values(state.licenseReducer.instances).find((license) => license.project === projectId)\n\nexport const selectActiveStatusLicenses: OvermapSelector<License[]> = createSelector(\n\t[selectLicenses],\n\t(licenses: Record<string, License>) => Object.values(licenses).filter((license) => license.is_active),\n)\n\nexport const selectLicensesForProjectsMapping: OvermapSelector<Record<number, License>> = createSelector(\n\t[selectLicenses],\n\t(licenses: Record<string, License>) =>\n\t\tObject.values(licenses)\n\t\t\t.filter((license) => license.project)\n\t\t\t.reduce((accum, license) => ({ ...accum, [license.project!]: license }), {}),\n)\n\nexport const licenseReducer: Reducer<LicenseState> = licenseSlice.reducer\n","import { Reducer, createSelector, createSlice } from \"@reduxjs/toolkit\"\nimport { OvermapRootState, OvermapSelector, OvermapSelectorWithArgs, ProjectAccess, Stored, User } from \"../../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { ModelState } from \"../typings\"\n\nexport type ProjectAccessState = ModelState<ProjectAccess>\n\nconst projectAccessAdapter = createModelAdapter<ProjectAccess>((projectAccess) => projectAccess.offline_id)\n\nconst initialState: ProjectAccessState = projectAccessAdapter.getInitialState({})\n\nexport const projectAccessSlice = createSlice({\n\tname: \"projectAccess\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeProjectAccesses: projectAccessAdapter.initialize,\n\t\tupdateProjectAccess: projectAccessAdapter.updateOne,\n\t\tdeleteProjectAccess: projectAccessAdapter.deleteOne,\n\t\tdeleteProjectAccesses: projectAccessAdapter.deleteMany,\n\t},\n})\n\nexport const { initializeProjectAccesses, updateProjectAccess, deleteProjectAccess, deleteProjectAccesses } =\n\tprojectAccessSlice.actions\n\nexport const selectProjectAccessMapping = (state: OvermapRootState) => {\n\treturn state.projectAccessReducer.instances\n}\n\nexport const selectProjectAccesses: OvermapSelector<Stored<ProjectAccess>[]> = createSelector(\n\tselectProjectAccessMapping,\n\t(projectAccesses) => {\n\t\treturn Object.values(projectAccesses)\n\t},\n)\n\nexport const selectProjectAccessById: OvermapSelectorWithArgs<string, ProjectAccess> =\n\t(projectAccessId: string) => (state: OvermapRootState) => {\n\t\treturn state.projectAccessReducer.instances[projectAccessId]\n\t}\n\nexport const selectActiveProjectAccess: OvermapSelector<ProjectAccess | null> = (state: OvermapRootState) => {\n\tconst currentUser = state.userReducer.currentUser\n\tconst activeProjectId = state.projectReducer.activeProjectId\n\treturn (\n\t\tObject.values(state.projectAccessReducer.instances).find((projectAccess: ProjectAccess) => {\n\t\t\treturn projectAccess.user === currentUser.id && projectAccess.project === activeProjectId\n\t\t}) ?? null\n\t)\n}\n\nexport const selectProjectAccessForUser: OvermapSelectorWithArgs<User, ProjectAccess | undefined> =\n\t(user: User) => (state: OvermapRootState) => {\n\t\treturn Object.values(state.projectAccessReducer.instances).find(\n\t\t\t(projectAccess: ProjectAccess) => projectAccess.user === user.id,\n\t\t)\n\t}\n\nexport const selectProjectAccessUserMapping: OvermapSelector<Record<string, ProjectAccess>> = (\n\tstate: OvermapRootState,\n) => {\n\tconst projectAccesses: Record<string, ProjectAccess> = {}\n\tfor (const projectAccess of Object.values(state.projectAccessReducer.instances)) {\n\t\tprojectAccesses[projectAccess.user] = projectAccess\n\t}\n\treturn projectAccesses\n}\n\nexport const projectAccessReducer: Reducer<ProjectAccessState> = projectAccessSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport {\n\tOfflineIdMapping,\n\tOvermapRootState,\n\tOvermapSelector,\n\tOvermapSelectorWithArgs,\n\tProject,\n\tProjectAccess,\n\tProjectAccessLevel,\n\tUser,\n} from \"../../typings\"\nimport { selectProjectAccessMapping, selectProjectAccessUserMapping } from \"./projectAccessSlice\"\nimport { selectCurrentUser, selectUsersMapping } from \"./userSlice\"\n\nexport interface ProjectState {\n\tprojects: Record<number, Project>\n\tactiveProjectId: number | null\n}\n\nconst initialState: ProjectState = {\n\tprojects: {},\n\tactiveProjectId: null,\n}\n\nexport const projectSlice = createSlice({\n\tname: \"projects\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tsetProjects: (state, action: { payload: Project[] }) => {\n\t\t\tconst projectsMap: Record<number, Project> = {}\n\t\t\taction.payload.forEach((project) => {\n\t\t\t\tprojectsMap[project.id] = project\n\t\t\t})\n\t\t\tstate.projects = projectsMap\n\t\t},\n\t\tsetActiveProjectId: (state, action: { payload: number | null }) => {\n\t\t\tstate.activeProjectId = action.payload\n\t\t},\n\t\tupdateOrCreateProject: (state, action: { payload: Project }) => {\n\t\t\tstate.projects[action.payload.id] = action.payload\n\t\t},\n\t\t// Takes a list of Projects and updates existing ones to match the payload, or adds them\n\t\t// to the store if they are not already present\n\t\tupdateOrCreateProjects: (state, action: { payload: Project[] }) => {\n\t\t\taction.payload.forEach((project) => {\n\t\t\t\tstate.projects[project.id] = project\n\t\t\t})\n\t\t},\n\t\tdeleteProject: (state, action: { payload: Project }) => {\n\t\t\tdelete state.projects[action.payload.id]\n\t\t},\n\t\tacceptProjectInvite: (state, action: { payload: number }) => {\n\t\t\tif (action.payload in state.projects) {\n\t\t\t\tstate.projects[action.payload]!.invited = false\n\t\t\t} else {\n\t\t\t\tthrow new Error(\"Accept project invite: user is not in this project\")\n\t\t\t}\n\t\t},\n\t\taddActiveProjectIssuesCount: (state, action: { payload: number }) => {\n\t\t\tif (!state.activeProjectId || !(state.activeProjectId in state.projects)) {\n\t\t\t\tthrow new Error(\"Update issues count: no active project\")\n\t\t\t}\n\n\t\t\tif (!state.projects[state.activeProjectId]!.issues_count) {\n\t\t\t\tstate.projects[state.activeProjectId]!.issues_count = action.payload\n\t\t\t} else {\n\t\t\t\tstate.projects[state.activeProjectId]!.issues_count! += action.payload\n\t\t\t}\n\t\t},\n\t\taddActiveProjectFormSubmissionsCount: (state, action: { payload: number }) => {\n\t\t\tif (state.activeProjectId && state.activeProjectId in state.projects) {\n\t\t\t\tif (!state.projects[state.activeProjectId]!.form_submissions_count) {\n\t\t\t\t\tstate.projects[state.activeProjectId]!.form_submissions_count = action.payload\n\t\t\t\t} else {\n\t\t\t\t\tstate.projects[state.activeProjectId]!.form_submissions_count! += action.payload\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new Error(\"Update form submissions count: no active project\")\n\t\t\t}\n\t\t},\n\t},\n})\n\nexport const {\n\tsetProjects,\n\tupdateOrCreateProject,\n\tupdateOrCreateProjects: addOrReplaceProjects,\n\tsetActiveProjectId,\n\tdeleteProject,\n\tacceptProjectInvite,\n\taddActiveProjectIssuesCount,\n\taddActiveProjectFormSubmissionsCount,\n} = projectSlice.actions\n\nexport const projectReducer: Reducer<ProjectState> = projectSlice.reducer\n\nexport const selectProjectMapping: OvermapSelector<Record<number, Project>> = (state: OvermapRootState) =>\n\tstate.projectReducer.projects\n\nexport const selectActiveProjectId = (state: OvermapRootState): number | null => state.projectReducer.activeProjectId\n\nexport const selectActiveProject = (state: OvermapRootState): Project | null => {\n\tconst activeProjectId = selectActiveProjectId(state)\n\tif (!activeProjectId) {\n\t\treturn null\n\t}\n\treturn state.projectReducer.projects[activeProjectId] ?? null\n}\n\nexport const selectProjectById: OvermapSelectorWithArgs<number, Project> =\n\t(projectId: number) => (state: OvermapRootState) => {\n\t\treturn state.projectReducer.projects[projectId]\n\t}\n\nexport const selectProjectUsersIds: OvermapSelector<number[]> = createSelector(\n\t[selectProjectAccessMapping],\n\t(projectAccesses: OfflineIdMapping<ProjectAccess>) =>\n\t\tObject.values(projectAccesses).map((projectAccess: ProjectAccess) => projectAccess.user),\n)\n\nexport const selectProjectUsersAsMapping: OvermapSelector<Record<number, User>> = createSelector(\n\t[selectProjectUsersIds, selectUsersMapping],\n\t(projectUserIds, users) => projectUserIds.reduce((accum, userId) => ({ ...accum, [userId]: users[userId] }), {}),\n)\n\nexport const selectProjectsWithAccess: OvermapSelector<Project[]> = createSelector(\n\t[selectProjectMapping],\n\t(projects: Record<number, Project>) => Object.values(projects).filter((project) => !project.invited),\n)\n\nexport const selectSortedProjectUsers: OvermapSelector<User[]> = createSelector(\n\t[selectCurrentUser, selectProjectUsersAsMapping, selectProjectAccessUserMapping],\n\t(currentUser: User, userMapping: Record<number, User>, projectAccessMapping: Record<number, ProjectAccess>) => {\n\t\treturn Object.values(userMapping).sort((userA, userB) => {\n\t\t\tif (userA.id === currentUser.id) {\n\t\t\t\treturn -1\n\t\t\t} else if (userB.id === currentUser.id) {\n\t\t\t\treturn 1\n\t\t\t}\n\t\t\tconst projectAccessesA = projectAccessMapping[userA.id]\n\t\t\tconst projectAccessesB = projectAccessMapping[userB.id]\n\t\t\tif (projectAccessesA?.access_level === projectAccessesB?.access_level) {\n\t\t\t\treturn userA.username.localeCompare(userB.username)\n\t\t\t}\n\t\t\tif (projectAccessesA?.access_level === ProjectAccessLevel.ADMIN) {\n\t\t\t\treturn -1\n\t\t\t}\n\t\t\treturn 1\n\t\t})\n\t},\n)\n","import { createSelector, createSlice, PayloadAction, Reducer } from \"@reduxjs/toolkit\"\nimport { OvermapSelector, OvermapSelectorWithArgs } from \"typings/store\"\nimport {\n\tLicense,\n\tOfflineIdMapping,\n\tOrganization,\n\tOrganizationAccess,\n\tOrganizationAccessLevel,\n\tOvermapRootState,\n\tProject,\n\tUser,\n} from \"../../typings\"\nimport { selectCurrentUser, selectUsersMapping } from \"./userSlice\"\nimport { selectOrganizationAccesses, selectOrganizationAccessUserMapping } from \"./organizationAccessSlice\"\nimport { selectLicenses } from \"./licenseSlice\"\nimport { selectProjectMapping } from \"./projectSlice\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport interface OrganizationState {\n\torganizations: Record<number, Organization>\n}\n\nconst initialState: OrganizationState = {\n\torganizations: {},\n}\n\nexport const organizationSlice = createSlice({\n\tname: \"organizations\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tsetOrganizations: (state, action: PayloadAction<Organization[]>) => {\n\t\t\tfor (const org of action.payload) {\n\t\t\t\tstate.organizations[org.id] = org\n\t\t\t}\n\t\t},\n\t},\n})\n\nexport const { setOrganizations } = organizationSlice.actions\n\nexport const selectOrganizations: OvermapSelector<Organization[]> = (state: OvermapRootState) => {\n\treturn Object.values(state.organizationReducer.organizations)\n}\n\nexport const selectOrganizationsMapping: OvermapSelector<Record<number, Organization>> = (state: OvermapRootState) => {\n\treturn state.organizationReducer.organizations\n}\n\nexport const selectOrganizationsWithAccess: OvermapSelector<Organization[]> = createSelector(\n\t[selectOrganizations],\n\t(organizations: Record<number, Organization>) =>\n\t\tObject.values(organizations).filter((organization: Organization) => organization.has_access),\n)\n\nexport const selectOrganizationById: OvermapSelectorWithArgs<number, Organization> = (organizationId) => (state) => {\n\treturn state.organizationReducer.organizations[organizationId]\n}\n\nexport const selectOrganizationUsersIds: OvermapSelector<number[]> = createSelector(\n\t[selectOrganizationAccesses],\n\t(organizationAccesses: OfflineIdMapping<OrganizationAccess>) =>\n\t\tObject.values(organizationAccesses).map((organizationAccess: OrganizationAccess) => organizationAccess.user),\n)\n\nexport const selectProjectsOfOrganization: OvermapSelectorWithArgs<number, Project[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector(\n\t\t\t[selectProjectMapping, (_, organizationId: number) => organizationId],\n\t\t\t(projects, organizationId) => {\n\t\t\t\treturn Object.values(projects).filter((project) => project.organization_owner === organizationId)\n\t\t\t},\n\t\t),\n\t)\n\nexport const selectLicensesOfOrganization: OvermapSelectorWithArgs<number, License[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector([selectLicenses, (_, organizationId: number) => organizationId], (licenses, organizationId) => {\n\t\t\treturn Object.values(licenses).filter((license) => license.organization_owner === organizationId)\n\t\t}),\n\t)\n\nexport const selectOrganizationUsersAsMapping: OvermapSelector<Record<number, User>> = createSelector(\n\t[selectOrganizationUsersIds, selectUsersMapping],\n\t(organizationUserIds: number[], users: Record<number, User>) =>\n\t\torganizationUserIds.reduce((accum, userId) => ({ ...accum, [userId]: users[userId] }), {}),\n)\n\nexport const selectSortedOrganizationUsers: OvermapSelector<User[]> = createSelector(\n\t[selectCurrentUser, selectOrganizationUsersAsMapping, selectOrganizationAccessUserMapping],\n\t(\n\t\tcurrentUser: User,\n\t\tuserMapping: Record<number, User>,\n\t\torganizationAccessMapping: Record<number, OrganizationAccess>,\n\t) => {\n\t\treturn Object.values(userMapping).sort((userA: User, userB: User) => {\n\t\t\tif (userA.id === currentUser.id) {\n\t\t\t\treturn -1\n\t\t\t} else if (userB.id === currentUser.id) {\n\t\t\t\treturn 1\n\t\t\t}\n\t\t\tconst organizationAccessesA: OrganizationAccess | undefined = organizationAccessMapping[userA.id]\n\t\t\tconst organizationAccessesB: OrganizationAccess | undefined = organizationAccessMapping[userB.id]\n\t\t\tif (organizationAccessesA?.access_level === organizationAccessesB?.access_level) {\n\t\t\t\treturn userA.username.localeCompare(userB.username)\n\t\t\t}\n\t\t\tif (organizationAccessesA?.access_level === OrganizationAccessLevel.ADMIN) {\n\t\t\t\treturn -1\n\t\t\t}\n\t\t\treturn 1\n\t\t})\n\t},\n)\n\nexport const selectOrganization: OvermapSelectorWithArgs<number, Organization | undefined> =\n\t(id: number) => (state: OvermapRootState) => {\n\t\treturn state.organizationReducer.organizations[id]\n\t}\n\nexport const organizationReducer: Reducer<OrganizationState> = organizationSlice.reducer\n","import { createSlice, PayloadAction, Reducer } from \"@reduxjs/toolkit\"\nimport type { FullOfflineAction } from \"../store\"\nimport type { RequestDetails } from \"../../sdk\"\nimport { v4 as uuidv4 } from \"uuid\"\nimport { SDKRequest } from \"../../sdk\"\nimport { OvermapRootState } from \"../../typings\"\n\nexport const createOfflineAction = (request: SDKRequest, baseUrl: string, serviceName: string): FullOfflineAction => {\n\tconst requestWithUuid = request.uuid ? (request as RequestDetails) : { ...request, uuid: uuidv4() }\n\treturn {\n\t\tpayload: requestWithUuid,\n\t\ttype: \"\",\n\t\tmeta: {\n\t\t\toffline: {\n\t\t\t\teffect: {\n\t\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t\t\trequest: requestWithUuid,\n\t\t\t\t\tBASE_URL: baseUrl,\n\t\t\t\t\tserviceName: serviceName,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n}\n\nexport interface OutboxState {\n\t/** A list of requests marked for deletion. Once the offline slice encounters one of these, */\n\tdeletedRequests: string[]\n\t/** The timestamp of the last retry of an outgoing request. (Number of milliseconds since the epoch.) */\n\tlatestRetryTime: number\n}\n\nconst initialState: OutboxState = {\n\tdeletedRequests: [],\n\tlatestRetryTime: 0,\n}\n\n/**\n * This slice primarily exists as an interface to enqueue API requests to the redux-offline slice. Any dispatched action\n * with an `offline` field in its metadata will be handled by redux-offline. This slice is just a sensible place to\n * \"dump\" no-op actions for enqueueing requests to the outbox. At the same time, we can use this slice to keep track of\n * requests that have been marked for deletion, so that we can skip them instead of sending the request.\n */\nexport const outboxSlice = createSlice({\n\tname: \"outbox\",\n\tinitialState: initialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\t// enqueueActions is a reducer that does nothing but enqueue API request to the Redux Offline outbox\n\t\t// Whenever an issue is being created, a reducer addIssue() is responsible for adding it to the offline store\n\t\t// Then this reducer enqueueRequest() is responsible for adding the actual request data to the outbox\n\t\tenqueueRequest: {\n\t\t\treducer: (state, _action: PayloadAction<RequestDetails>) => {\n\t\t\t\treturn state\n\t\t\t},\n\t\t\tprepare: (payload: SDKRequest & { BASE_URL: string; serviceName: string }): FullOfflineAction => {\n\t\t\t\tconsole.debug(\"Preparing to enqueue request\", payload)\n\t\t\t\tconst { BASE_URL, serviceName, ...rest } = payload\n\t\t\t\treturn createOfflineAction(rest, BASE_URL, serviceName)\n\t\t\t},\n\t\t},\n\t\tmarkForDeletion(state, action: PayloadAction<string>) {\n\t\t\tstate.deletedRequests.push(action.payload)\n\t\t},\n\t\tmarkAsDeleted(state, action: PayloadAction<string>) {\n\t\t\tconst index = state.deletedRequests.indexOf(action.payload)\n\t\t\tif (index !== -1) state.deletedRequests.splice(index, 1)\n\t\t},\n\t\t_setLatestRetryTime: (state, action: PayloadAction<number>) => {\n\t\t\tstate.latestRetryTime = action.payload\n\t\t},\n\t},\n})\n\nexport const selectDeletedRequests = (state: OvermapRootState) => state.outboxReducer.deletedRequests\nexport const selectLatestRetryTime = (state: OvermapRootState) => state.outboxReducer.latestRetryTime\n\nexport const { enqueueRequest, markForDeletion, markAsDeleted, _setLatestRetryTime } = outboxSlice.actions\nexport const outboxReducer: Reducer<OutboxState> = outboxSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport {\n\tMultiPointGeometry,\n\tOvermapRootState,\n\tOvermapSelector,\n\tOvermapSelectorWithArgs,\n\tProjectFile,\n} from \"../../typings\"\nimport { selectActiveProjectId } from \"./projectSlice\"\n\nexport interface ProjectFileState {\n\tprojectFiles: Record<string, ProjectFile>\n\tactiveProjectFileId: string | null\n\t/**\n\t * State variable which is set true by web client to mark that the activeProjectFile is a new one that was just\n\t * imported and not a pre-existing one which is being edited\n\t */\n\tisImportingProjectFile: boolean\n}\n\nconst initialState: ProjectFileState = {\n\tprojectFiles: {},\n\tactiveProjectFileId: null,\n\tisImportingProjectFile: false,\n}\n\nexport const projectFileSlice = createSlice({\n\tname: \"projectFiles\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\taddOrReplaceProjectFiles: (state, action: { payload: ProjectFile[] }) => {\n\t\t\tfor (let fileObj of action.payload) {\n\t\t\t\tlet file = fileObj.file\n\t\t\t\tif (file.includes(\"+\")) {\n\t\t\t\t\tconsole.warn(\"Attempting to apply fix for image URL with '+' character:\", file)\n\t\t\t\t\t// We have a src such as this:\n\t\t\t\t\t// https://example.com/my-svg.svg+xml\n\t\t\t\t\t// Or:\n\t\t\t\t\t// blob://.../my-svg.svg+xml\n\t\t\t\t\t// We want just the `my-svg.svg+xml` part.\n\t\t\t\t\tconst parts = file.split(\"/\")\n\t\t\t\t\tif (parts.length < 2) {\n\t\t\t\t\t\tthrow new Error(\"Invalid URL: \" + file)\n\t\t\t\t\t}\n\t\t\t\t\tconst lastPart = encodeURIComponent(parts[parts.length - 1]!)\n\t\t\t\t\t// Reconstruct the URL with the fixed last part.\n\t\t\t\t\tfile = parts.slice(0, -1).join(\"/\") + \"/\" + lastPart\n\t\t\t\t\tconsole.warn(\"Fixed URL:\", file)\n\t\t\t\t\tfileObj = { ...fileObj, file }\n\t\t\t\t}\n\t\t\t\tstate.projectFiles[fileObj.offline_id] = fileObj\n\t\t\t}\n\t\t},\n\t\taddOrReplaceProjectFile: (state, action: { payload: ProjectFile }) => {\n\t\t\tif (!action.payload.project) {\n\t\t\t\tthrow new Error(\"ProjectFile has no project. A project must be set before storing.\")\n\t\t\t}\n\t\t\tstate.projectFiles[action.payload.offline_id] = action.payload\n\t\t},\n\t\tsetIsImportingProjectFile: (state, action: { payload: boolean }) => {\n\t\t\tstate.isImportingProjectFile = action.payload\n\t\t},\n\t\tsaveActiveProjectFileBounds: (state, action: { payload: MultiPointGeometry }) => {\n\t\t\tconst activeProjectFileId = state.activeProjectFileId\n\t\t\tif (!activeProjectFileId) {\n\t\t\t\tthrow new Error(\"Tried to save bounds for active project file, but no active project file was set.\")\n\t\t\t}\n\t\t\tif (!state.projectFiles[activeProjectFileId]) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Tried to save bounds for active project file, but project file with ID ${activeProjectFileId} \n\t\t\t\t\tdoesn't exist.`,\n\t\t\t\t)\n\t\t\t}\n\t\t\tstate.projectFiles[activeProjectFileId]!.bounds = action.payload\n\t\t},\n\t\t// TODO: Move to MapContext. Should not be persisted.\n\t\tsetActiveProjectFileId: (state, action: { payload: string | null }) => {\n\t\t\tstate.activeProjectFileId = action.payload\n\t\t},\n\t\tremoveProjectFile: (state, action: { payload: string }) => {\n\t\t\tdelete state.projectFiles[action.payload]\n\t\t},\n\t\tremoveProjectFilesOfProject: (state, action: { payload: number }) => {\n\t\t\tconst filesToDelete = Object.values(state.projectFiles).filter((file) => file.project === action.payload)\n\t\t\tfor (const file of filesToDelete) {\n\t\t\t\tdelete state.projectFiles[file.offline_id]\n\t\t\t}\n\t\t},\n\t\tresetProjectFileObjectUrls: (state, ..._args: []) => {\n\t\t\tfor (const key in state.projectFiles) {\n\t\t\t\tdelete state.projectFiles[key]!.objectURL\n\t\t\t}\n\t\t},\n\t},\n})\n\nexport const {\n\taddOrReplaceProjectFiles,\n\taddOrReplaceProjectFile,\n\tsetIsImportingProjectFile,\n\tsetActiveProjectFileId,\n\tsaveActiveProjectFileBounds,\n\tremoveProjectFile,\n\tremoveProjectFilesOfProject,\n\tresetProjectFileObjectUrls,\n} = projectFileSlice.actions\n\nexport const selectProjectFileMapping = (state: OvermapRootState) => state.projectFileReducer.projectFiles\n\nexport const selectProjectFiles = createSelector(\n\t[selectProjectFileMapping, selectActiveProjectId],\n\t(mapping, activeProjectId) => {\n\t\treturn Object.values(mapping)\n\t\t\t.filter((file) => file.project === activeProjectId)\n\t\t\t.sort((a, b) => a.z_index - b.z_index)\n\t},\n)\n\nexport const selectActiveProjectFileId: OvermapSelector<string | null> = (state: OvermapRootState) =>\n\tstate.projectFileReducer.activeProjectFileId\n\nexport const selectIsImportingProjectFile: OvermapSelector<boolean> = (state: OvermapRootState) =>\n\tstate.projectFileReducer.isImportingProjectFile\n\nexport const selectProjectFileById: OvermapSelectorWithArgs<string, ProjectFile> =\n\t(id: string) => (state: OvermapRootState) => {\n\t\treturn state.projectFileReducer.projectFiles[id]\n\t}\n\nexport const projectFileReducer: Reducer<ProjectFileState> = projectFileSlice.reducer\n","import { createSlice, Reducer, createSelector } from \"@reduxjs/toolkit\"\nimport { ModelState } from \"../typings\"\nimport { ProjectAttachment, OvermapRootState, OvermapSelector, OvermapSelectorWithArgs, Stored } from \"../../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport type ProjectAttachmentState = ModelState<Stored<ProjectAttachment>>\n\nconst projectAttachmentAdapter = createModelAdapter<Stored<ProjectAttachment>>((attachment) => attachment.offline_id)\n\nconst initialState: ProjectAttachmentState = projectAttachmentAdapter.getInitialState({})\n\nexport const projectAttachmentSlice = createSlice({\n\tname: \"projectAttachments\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeProjectAttachments: projectAttachmentAdapter.initialize,\n\t\taddProjectAttachment: projectAttachmentAdapter.addOne,\n\t\taddProjectAttachments: projectAttachmentAdapter.addMany,\n\t\tsetProjectAttachment: projectAttachmentAdapter.setOne,\n\t\tsetProjectAttachments: projectAttachmentAdapter.setMany,\n\t\tupdateProjectAttachment: projectAttachmentAdapter.updateOne,\n\t\tupdateProjectAttachments: projectAttachmentAdapter.updateMany,\n\t\tdeleteProjectAttachment: projectAttachmentAdapter.deleteOne,\n\t\tdeleteProjectAttachments: projectAttachmentAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tinitializeProjectAttachments,\n\taddProjectAttachment,\n\taddProjectAttachments,\n\tsetProjectAttachment,\n\tsetProjectAttachments,\n\tupdateProjectAttachment,\n\tupdateProjectAttachments,\n\tdeleteProjectAttachment,\n\tdeleteProjectAttachments,\n} = projectAttachmentSlice.actions\n\nexport const selectProjectAttachmentMapping = (state: OvermapRootState) => state.projectAttachmentReducer.instances\n\nexport const selectAllProjectAttachments: OvermapSelector<Stored<ProjectAttachment>[]> = createSelector(\n\t[selectProjectAttachmentMapping],\n\t(mapping) => Object.values(mapping),\n)\n\nexport const selectProjectAttachment: OvermapSelectorWithArgs<string, ProjectAttachment> =\n\t(attachmentId: string) => (state: OvermapRootState) => {\n\t\treturn state.projectAttachmentReducer.instances[attachmentId]\n\t}\n\nexport const selectAttachmentsOfProject = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectAllProjectAttachments, (_state: OvermapRootState, projectId: number) => projectId],\n\t\t(attachments, projectId) => {\n\t\t\treturn attachments.filter(({ project }) => projectId === project)\n\t\t},\n\t),\n)\nexport const selectAttachmentsOfProjectByType = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectAllProjectAttachments, (_state: OvermapRootState, projectId: number) => projectId],\n\t\t(attachments, projectId) => {\n\t\t\tconst attachmentsOfProject = attachments.filter(({ project }) => projectId === project)\n\t\t\tconst fileAttachments = attachmentsOfProject.filter(\n\t\t\t\t// this null check here is necessary, there are cases where file_type is null or undefined\n\t\t\t\t({ file_type }) => !file_type || !file_type.startsWith(\"image/\"),\n\t\t\t)\n\t\t\tconst imageAttachments = attachmentsOfProject.filter(\n\t\t\t\t// this null check here is necessary, there are cases where file_type is null or undefined\n\t\t\t\t({ file_type }) => file_type && file_type.startsWith(\"image/\"),\n\t\t\t)\n\t\t\treturn { fileAttachments, imageAttachments }\n\t\t},\n\t),\n)\n\nexport const projectAttachmentReducer: Reducer<ProjectAttachmentState> = projectAttachmentSlice.reducer\n","import { createSlice, PayloadAction, Reducer } from \"@reduxjs/toolkit\"\nimport { OvermapRootState } from \"../../typings\"\n\n// TODO: this slice can be moved to /web ?\n\nexport interface RehydratedState {\n\tisRehydrated: boolean\n}\n\nconst initialState: RehydratedState = {\n\tisRehydrated: false,\n}\n\n// rehydratedSlice is used to indicate when the Redux store has finished rehydrating its state from localForage\n// Once finished, the app renders, which prevents the annoying login screen flickering issue\nexport const rehydratedSlice = createSlice({\n\tname: \"rehydrated\",\n\tinitialState,\n\t// The `reducers` field lets us define reducers and generate associated actions\n\treducers: {\n\t\tsetRehydrated: (state, action: PayloadAction<boolean>) => {\n\t\t\tstate.isRehydrated = action.payload\n\t\t},\n\t},\n})\n\nexport const { setRehydrated } = rehydratedSlice.actions\n\n// The function below is called a selector and allows us to select a value from\n// the state. Selectors can also be defined inline where they're used instead of\n// in the slice file. For example: `useSelector((state: RootState) => state.counter.value)`\nexport const selectRehydrated = (state: OvermapRootState) => state.rehydratedReducer.isRehydrated\n\nexport const rehydratedReducer: Reducer<RehydratedState> = rehydratedSlice.reducer\n","import { Stored, FormRevision } from \"../typings\"\n\nexport const formRevisionSortFn = (formRevisionA: Stored<FormRevision>, formRevisionB: Stored<FormRevision>) => {\n\tconst revisionA = formRevisionA.revision\n\tconst revisionB = formRevisionB.revision\n\n\tif (revisionA === \"Pending\" && revisionB === \"Pending\") {\n\t\treturn formRevisionA.submitted_at < formRevisionB.submitted_at ? -1 : 1\n\t} else if (revisionA === \"Pending\") {\n\t\treturn 1\n\t} else if (revisionB === \"Pending\") {\n\t\treturn -1\n\t} else {\n\t\treturn revisionA < revisionB ? -1 : 1\n\t}\n}\n","import { createSlice, Reducer, createSelector } from \"@reduxjs/toolkit\"\nimport { OvermapRootState, OvermapSelector, OvermapSelectorWithArgs, Stored, Form, FormRevision } from \"../../typings\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\nimport { formRevisionSortFn } from \"../../utils/forms\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\n\nexport type FormRevisionState = ModelState<Stored<FormRevision>>\n\nconst formRevisionAdapter = createModelAdapter<Stored<FormRevision>>((revision) => revision.offline_id)\n\nconst initialState: FormRevisionState = formRevisionAdapter.getInitialState({})\n\nexport const formRevisionsSlice = createSlice({\n\tname: \"formRevisions\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeFormRevisions: formRevisionAdapter.initialize,\n\t\tsetFormRevision: formRevisionAdapter.setOne,\n\t\taddFormRevision: formRevisionAdapter.addOne,\n\t\taddFormRevisions: formRevisionAdapter.addMany,\n\t\tdeleteFormRevision: formRevisionAdapter.deleteOne,\n\t\tdeleteFormRevisions: formRevisionAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tsetFormRevision,\n\tinitializeFormRevisions,\n\taddFormRevision,\n\taddFormRevisions,\n\tdeleteFormRevision,\n\tdeleteFormRevisions,\n} = formRevisionsSlice.actions\n\nexport const selectFormRevisionMapping = (state: OvermapRootState) => state.formRevisionReducer.instances\n\nexport const selectFormRevisions = createSelector([selectFormRevisionMapping], (formRevisions) =>\n\tObject.values(formRevisions),\n)\n\nexport const selectFormRevisionById: OvermapSelectorWithArgs<string, Stored<FormRevision>> =\n\t(formRevisionId: string) => (state: OvermapRootState) => {\n\t\treturn state.formRevisionReducer.instances[formRevisionId]\n\t}\n\n// takes user form state revisions instead of the whole state as an argument\nexport const _selectLatestFormRevision = (\n\tformRevisions: FormRevisionState[\"instances\"],\n\tformId: string,\n): Stored<FormRevision> => {\n\tlet ret: Stored<FormRevision> | null = null\n\n\tfor (const candidate of Object.values(formRevisions)) {\n\t\tif (candidate.form === formId && (!ret || ret.revision < candidate.revision)) {\n\t\t\tret = candidate\n\t\t}\n\t}\n\n\tif (!ret) {\n\t\tthrow new Error(\"No form revision found for form \" + formId)\n\t}\n\n\treturn ret\n}\n\nexport const selectLatestFormRevisionOfForm: OvermapSelectorWithArgs<\n\tstring,\n\tStored<FormRevision>\n> = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectFormRevisionMapping, (_state: OvermapRootState, formId: string) => formId],\n\t\t(revisions, formId) => {\n\t\t\tconst revisionsOfForm = Object.values(revisions).filter((revision) => revision.form === formId)\n\n\t\t\tif (revisionsOfForm.length === 0) return undefined\n\n\t\t\tconst sortedRevisions = revisionsOfForm.sort(formRevisionSortFn)\n\n\t\t\tconst latestRevision = sortedRevisions[revisionsOfForm.length - 1]!\n\n\t\t\treturn revisions[latestRevision.offline_id]\n\t\t},\n\t),\n)\n\nexport const selectFormRevisionsOfForm: OvermapSelectorWithArgs<string, Stored<FormRevision>[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector(\n\t\t\t[selectFormRevisions, (_state: OvermapRootState, formId: string) => formId],\n\t\t\t(revisions, formId) => {\n\t\t\t\treturn revisions.filter((revision) => {\n\t\t\t\t\treturn revision.form === formId\n\t\t\t\t})\n\t\t\t},\n\t\t),\n\t)\n\nexport const selectLatestFormRevisionsOfAssetTypes: OvermapSelectorWithArgs<\n\tstring[],\n\tRecord<string, Stored<FormRevision>>\n> = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[\n\t\t\t(state: OvermapRootState) => state.formReducer.instances,\n\t\t\tselectFormRevisionMapping,\n\t\t\t(_state: OvermapRootState, assetTypeIds: string[]) => assetTypeIds,\n\t\t],\n\t\t(formsMapping, revisions, assetTypeIds) => {\n\t\t\tconst assetTypeIdsSet = new Set(assetTypeIds)\n\t\t\tconst formsOfAssetTypes: Record<string, Stored<Form>> = {}\n\t\t\tconst ret: Record<string, Stored<FormRevision>> = {}\n\n\t\t\tfor (const form of Object.values(formsMapping)) {\n\t\t\t\tif (form.asset_type && assetTypeIdsSet.has(form.asset_type)) {\n\t\t\t\t\tformsOfAssetTypes[form.offline_id] = form\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const revision of Object.values(revisions)) {\n\t\t\t\t// look up if a asset type form exists for the current revision\n\t\t\t\tconst form = formsOfAssetTypes[revision.form]\n\n\t\t\t\tif (\n\t\t\t\t\t!form ||\n\t\t\t\t\t!form.asset_type ||\n\t\t\t\t\t(ret[form.asset_type] && formRevisionSortFn(ret[form.asset_type]!, revision) > 0)\n\t\t\t\t)\n\t\t\t\t\tcontinue\n\n\t\t\t\tret[form.asset_type] = revision\n\t\t\t}\n\n\t\t\treturn ret\n\t\t},\n\t),\n)\n\nexport const selectLatestFormRevisionByForm: OvermapSelector<Record<Stored<Form>[\"offline_id\"], Stored<FormRevision>>> =\n\tcreateSelector([selectFormRevisionMapping], (revisions) => {\n\t\tconst latestRevisions: Record<string, FormRevision> = {}\n\t\tfor (const revision of Object.values(revisions)) {\n\t\t\tconst formId = revision.form\n\t\t\tconst currentLatestRevision = latestRevisions[formId]\n\t\t\tif (!currentLatestRevision || currentLatestRevision.revision < revision.revision) {\n\t\t\t\tlatestRevisions[formId] = revision\n\t\t\t}\n\t\t}\n\t\treturn latestRevisions\n\t})\n\nexport const formRevisionReducer: Reducer<FormRevisionState> = formRevisionsSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport { CachedForm, Form } from \"typings/models/forms\"\nimport { SearchArgs } from \"typings/search\"\nimport { OvermapSelector, OvermapSelectorWithArgs } from \"typings/store\"\nimport { restructureCreateSelectorWithArgs } from \"utils/utils\"\nimport { OvermapRootState, Stored } from \"../../typings\"\nimport { _selectLatestFormRevision } from \"./formRevisionSlice\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { shallowEqual } from \"../../utils\"\n\nexport type FormState = ModelState<Stored<Form>>\n\nconst formAdapter = createModelAdapter<Stored<Form>>((form) => form.offline_id)\n\nconst initialState: FormState = formAdapter.getInitialState({})\n\nexport const formSlice = createSlice({\n\tname: \"forms\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeForms: formAdapter.initialize,\n\t\tsetForm: formAdapter.setOne,\n\t\taddForm: formAdapter.addOne,\n\t\taddForms: formAdapter.addMany,\n\t\tupdateForm: formAdapter.updateOne,\n\t\tdeleteForm: formAdapter.deleteOne,\n\t},\n})\n\nexport const { initializeForms, setForm, addForm, addForms, updateForm, deleteForm } = formSlice.actions\n\nexport type FormSearchArgs = SearchArgs<{\n\t/** `undefined` means don't filter by favorite. `boolean` filters forms. */\n\tfavorites?: boolean\n\t/** organization owner */\n\torganization?: number\n}>\n\nexport const selectFormsMapping: OvermapSelector<Record<Stored<Form>[\"offline_id\"], Stored<Form>>> = (state) => {\n\treturn state.formReducer.instances\n}\n\nexport const selectFilteredForms: OvermapSelectorWithArgs<FormSearchArgs, CachedForm[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector(\n\t\t\t[\n\t\t\t\t(state: OvermapRootState) => state.formReducer.instances,\n\t\t\t\t(state: OvermapRootState) => state.formRevisionReducer.instances,\n\t\t\t\t(_state: OvermapRootState, search: FormSearchArgs) => search,\n\t\t\t],\n\t\t\t(formsMapping, revisions, search) => {\n\t\t\t\tconst { searchTerm, maxResults, favorites, organization } = search\n\n\t\t\t\tconst favoriteMatches: CachedForm[] = []\n\t\t\t\tconst regularMatches: CachedForm[] = []\n\n\t\t\t\tfor (const [formId, form] of Object.entries(formsMapping)) {\n\t\t\t\t\t// if filtering by favorites, skip forms with the wrong favorite status\n\t\t\t\t\tif (favorites !== undefined && form.favorite != favorites) continue\n\n\t\t\t\t\t// if filtering by organizations, skip forms with the wrong organization\n\t\t\t\t\tif (Number.isInteger(organization) && organization !== form.organization) {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\n\t\t\t\t\t// find the latest revision for this form (note: expensive)\n\t\t\t\t\tconst latestRevision = _selectLatestFormRevision(revisions, formId)\n\n\t\t\t\t\tif (latestRevision.title.toLowerCase().includes(searchTerm.toLowerCase())) {\n\t\t\t\t\t\tif (form.favorite) {\n\t\t\t\t\t\t\tfavoriteMatches.push({ ...form, latestRevision: latestRevision })\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tregularMatches.push({ ...form, latestRevision: latestRevision })\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// if we've found enough matches, stop searching\n\t\t\t\t\t// only count favorites as favorites are displayed first\n\t\t\t\t\tif (favoriteMatches.length >= maxResults) {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst maxRegularMatches = maxResults - favoriteMatches.length\n\n\t\t\t\treturn [...favoriteMatches, ...regularMatches.slice(0, maxRegularMatches)]\n\t\t\t},\n\t\t\t// as the argument is an object, we check the first level of properties for equality\n\t\t\t{ memoizeOptions: { equalityCheck: shallowEqual } },\n\t\t),\n\t)\n\nexport const selectFormMapping: OvermapSelector<Record<Stored<Form>[\"offline_id\"], Stored<Form>>> = (\n\tstate: OvermapRootState,\n) => {\n\treturn state.formReducer.instances\n}\n\nexport const selectFormById: OvermapSelectorWithArgs<string, Stored<Form>> =\n\t(formId: string) => (state: OvermapRootState) => {\n\t\treturn state.formReducer.instances[formId]\n\t}\n\nexport const selectFormOfAssetType: OvermapSelectorWithArgs<string, Stored<Form>> = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectFormMapping, (_state: OvermapRootState, assetTypeId: string) => assetTypeId],\n\t\t(formsMapping, assetTypeId) => {\n\t\t\treturn Object.values(formsMapping).find((form) => form.asset_type === assetTypeId)\n\t\t},\n\t),\n)\n\nexport const selectFormOfIssueType: OvermapSelectorWithArgs<string, Stored<Form>> = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectFormMapping, (_state: OvermapRootState, issueTypeId: string) => issueTypeId],\n\t\t(formsMapping, issueTypeId) => {\n\t\t\treturn Object.values(formsMapping).find((form) => form.issue_type === issueTypeId)\n\t\t},\n\t),\n)\n\n// Total number of user forms\nexport const selectFormsCount: OvermapSelector<number> = createSelector([selectFormMapping], (formsMapping) => {\n\treturn Object.keys(formsMapping).length\n})\n\n// Number of user forms not related to a asset type\nexport const selectGeneralFormCount: OvermapSelector<number> = createSelector([selectFormMapping], (formsMapping) => {\n\treturn Object.values(formsMapping).filter((form) => !form.asset_type).length\n})\n\nexport const formReducer: Reducer<FormState> = formSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport { OvermapRootState, OvermapSelector, OvermapSelectorWithArgs, Stored, FormSubmission } from \"../../typings\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\nimport { selectFormRevisionMapping } from \"./formRevisionSlice\"\nimport { selectAssetsMapping } from \"./assetSlice\"\nimport { formRevisionSortFn } from \"../../utils/forms\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\n\nexport type FormSubmissionState = ModelState<Stored<FormSubmission>>\n\nconst submissionAdapter = createModelAdapter<Stored<FormSubmission>>((submission) => submission.offline_id)\n\nconst initialState: FormSubmissionState = submissionAdapter.getInitialState({})\n\nexport const formSubmissionSlice = createSlice({\n\tname: \"formSubmissions\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeFormSubmissions: submissionAdapter.initialize,\n\t\tsetFormSubmission: submissionAdapter.setOne,\n\t\tsetFormSubmissions: submissionAdapter.setMany,\n\t\taddFormSubmission: submissionAdapter.addOne,\n\t\taddFormSubmissions: submissionAdapter.addMany,\n\t\tupdateFormSubmission: submissionAdapter.updateOne,\n\t\tupdateFormSubmissions: submissionAdapter.updateMany,\n\t\tdeleteFormSubmission: submissionAdapter.deleteOne,\n\t\tdeleteFormSubmissions: submissionAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tinitializeFormSubmissions,\n\tsetFormSubmission,\n\tsetFormSubmissions,\n\taddFormSubmission,\n\taddFormSubmissions,\n\tupdateFormSubmission,\n\tupdateFormSubmissions,\n\tdeleteFormSubmission,\n\tdeleteFormSubmissions,\n} = formSubmissionSlice.actions\n\nexport const selectFormSubmissionsMapping: OvermapSelector<FormSubmissionState[\"instances\"]> = (state) => {\n\treturn state.formSubmissionReducer.instances\n}\n\nexport const selectFormSubmissions: OvermapSelector<Stored<FormSubmission>[]> = createSelector(\n\t[selectFormSubmissionsMapping],\n\t(submissions) => {\n\t\treturn Object.values(submissions)\n\t},\n)\n\nexport const selectFormSubmissionById: OvermapSelectorWithArgs<string, Stored<FormSubmission>> =\n\t(submissionId) => (state: OvermapRootState) => {\n\t\treturn state.formSubmissionReducer.instances[submissionId]\n\t}\n\nexport const selectFormSubmissionsOfForm: OvermapSelectorWithArgs<string, Stored<FormSubmission>[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector(\n\t\t\t[\n\t\t\t\tselectFormSubmissionsMapping,\n\t\t\t\tselectFormRevisionMapping,\n\t\t\t\t(_state: OvermapRootState, formId: string) => formId,\n\t\t\t],\n\t\t\t(submissions, revisionMapping, formId) => {\n\t\t\t\tconst revisionsOfForm = Object.values(revisionMapping).filter((revision) => revision.form === formId)\n\t\t\t\tconst revisionIds = new Set(revisionsOfForm.map((revision) => revision.offline_id))\n\n\t\t\t\treturn Object.values(submissions).filter((submission) => {\n\t\t\t\t\treturn revisionIds.has(submission.form_revision)\n\t\t\t\t})\n\t\t\t},\n\t\t),\n\t)\n\nexport const selectFormSubmissionsByFormRevisions: OvermapSelector<Record<string, Stored<FormSubmission>[]>> =\n\tcreateSelector([selectFormRevisionMapping, selectFormSubmissions], (revisions, submissions) => {\n\t\tconst submissionMapping: Record<string, Stored<FormSubmission>[]> = {}\n\t\tfor (const revisionId in revisions) {\n\t\t\tsubmissionMapping[revisionId] = []\n\t\t}\n\t\tfor (const submission of submissions) {\n\t\t\tsubmissionMapping[submission.form_revision]?.push(submission)\n\t\t}\n\t\treturn submissionMapping\n\t})\n\nexport const selectSortedFormSubmissionsOfForm: OvermapSelectorWithArgs<string, Stored<FormSubmission>[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector(\n\t\t\t[\n\t\t\t\tselectFormRevisionMapping,\n\t\t\t\tselectFormSubmissionsByFormRevisions,\n\t\t\t\t(_state: OvermapRootState, formId: string) => formId,\n\t\t\t],\n\t\t\t(revisionsMapping, submissionsByRevision, formId) => {\n\t\t\t\tconst submissionsByFormRevisions: Record<string, Stored<FormSubmission>[]> = {}\n\n\t\t\t\tfor (const revisionId in revisionsMapping) {\n\t\t\t\t\tconst revision = revisionsMapping[revisionId]\n\t\t\t\t\tconst submissionsOfRevision = submissionsByRevision[revisionId]\n\t\t\t\t\tif (revision && submissionsOfRevision && revision.form === formId) {\n\t\t\t\t\t\tsubmissionsByFormRevisions[revisionId] = submissionsOfRevision.sort((a, b) =>\n\t\t\t\t\t\t\ta.submitted_at < b.submitted_at ? -1 : 1,\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn Object.entries(submissionsByFormRevisions)\n\t\t\t\t\t.sort((a, b) => {\n\t\t\t\t\t\tconst aRevision = revisionsMapping[a[0]]!\n\t\t\t\t\t\tconst bRevision = revisionsMapping[b[0]]!\n\t\t\t\t\t\treturn formRevisionSortFn(aRevision, bRevision)\n\t\t\t\t\t})\n\t\t\t\t\t.map(([_revisionId, submissions]) => submissions)\n\t\t\t\t\t.flat()\n\t\t\t},\n\t\t),\n\t)\n\nexport const selectFormSubmissionsOfIssue = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectFormSubmissions, (_state: OvermapRootState, issueId: string) => issueId],\n\t\t(submissions, issueId) => {\n\t\t\treturn Object.values(submissions).filter((submission) => {\n\t\t\t\treturn submission.issue === issueId\n\t\t\t})\n\t\t},\n\t),\n)\n\nexport const selectAttachedFormSubmissionsOfIssue = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[\n\t\t\t(state: OvermapRootState) => state.issueReducer.instances,\n\t\t\t(state: OvermapRootState) => state.formReducer.instances,\n\t\t\t(state: OvermapRootState) => state.formRevisionReducer.instances,\n\t\t\t(state: OvermapRootState) => state.formSubmissionReducer.instances,\n\t\t\t(_state: OvermapRootState, issueId: string) => issueId,\n\t\t],\n\t\t(issues, forms, formRevisions, submissions, issueId) => {\n\t\t\t// step 1: check if issue has an issue type\n\t\t\tconst issue = issues[issueId]\n\n\t\t\tif (!issue) return []\n\n\t\t\tif (!issue.issue_type) {\n\t\t\t\treturn Object.values(submissions).filter((submission) => submission.issue === issueId)\n\t\t\t}\n\n\t\t\t// step 2: find the ids for forms of the issue type\n\t\t\tconst issueTypeForms = new Set(\n\t\t\t\tObject.keys(forms).filter((formId) => forms[formId]!.issue_type === issue.issue_type),\n\t\t\t)\n\n\t\t\t// step 3: find the ids for form revisions of the forms\n\t\t\tconst issueTypeFormRevisions = new Set(\n\t\t\t\tObject.keys(formRevisions).filter((formRevisionId) =>\n\t\t\t\t\tissueTypeForms.has(formRevisions[formRevisionId]!.form),\n\t\t\t\t),\n\t\t\t)\n\n\t\t\t// step 4: filter out any submissions whos revision is in the set\n\t\t\treturn Object.values(submissions).filter(\n\t\t\t\t(submission) => submission.issue === issueId && !issueTypeFormRevisions.has(submission.form_revision),\n\t\t\t)\n\t\t},\n\t),\n)\n\nexport const selectFormSubmissionsByIssues: OvermapSelectorWithArgs<\n\tstring[],\n\tRecord<string, Stored<FormSubmission>[]>\n> = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectFormSubmissions, (_state: OvermapRootState, issueIds: string[]) => issueIds],\n\t\t(submissions, issueIds) => {\n\t\t\tconst issueSubmissions: Record<string, Stored<FormSubmission>[]> = {}\n\t\t\tfor (const issueId of issueIds) {\n\t\t\t\tissueSubmissions[issueId] = []\n\t\t\t}\n\t\t\tfor (const submission of submissions) {\n\t\t\t\tif (submission.issue && issueIds.includes(submission.issue)) {\n\t\t\t\t\tissueSubmissions[submission.issue]?.push(submission)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn issueSubmissions\n\t\t},\n\t),\n)\n\nexport const selectFormSubmissionsOfAsset = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectFormSubmissions, (_state: OvermapRootState, assetId: string) => assetId],\n\t\t(submissions, assetId) => {\n\t\t\treturn submissions.filter((submission) => {\n\t\t\t\treturn submission.asset === assetId\n\t\t\t})\n\t\t},\n\t),\n)\n\nexport const selectAttachedFormSubmissionsOfAsset = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[\n\t\t\t(state: OvermapRootState) => state.assetReducer.instances,\n\t\t\t(state: OvermapRootState) => state.formReducer.instances,\n\t\t\t(state: OvermapRootState) => state.formRevisionReducer.instances,\n\t\t\t(state: OvermapRootState) => state.formSubmissionReducer.instances,\n\t\t\t(_state: OvermapRootState, assetId: string) => assetId,\n\t\t],\n\t\t(assets, forms, formRevisions, submissions, assetId) => {\n\t\t\t// step 1: check if asset has an asset type\n\t\t\tconst asset = assets[assetId]\n\n\t\t\tif (!asset) return []\n\n\t\t\tif (!asset.asset_type) {\n\t\t\t\treturn Object.values(submissions).filter((submission) => submission.asset === assetId)\n\t\t\t}\n\n\t\t\t// step 2: find the ids for forms of the asset type\n\t\t\tconst issueTypeForms = new Set(\n\t\t\t\tObject.keys(forms).filter((formId) => forms[formId]!.asset_type === asset.asset_type),\n\t\t\t)\n\n\t\t\t// step 3: find the ids for form revisions of the forms\n\t\t\tconst issueTypeFormRevisions = new Set(\n\t\t\t\tObject.keys(formRevisions).filter((formRevisionId) =>\n\t\t\t\t\tissueTypeForms.has(formRevisions[formRevisionId]!.form),\n\t\t\t\t),\n\t\t\t)\n\n\t\t\t// step 4: filter out any submissions whos revision is in the set\n\t\t\treturn Object.values(submissions).filter(\n\t\t\t\t(submission) => submission.asset === assetId && !issueTypeFormRevisions.has(submission.form_revision),\n\t\t\t)\n\t\t},\n\t),\n)\n\nexport const selectFormSubmissionsByAssets: OvermapSelector<Record<string, Stored<FormSubmission>[]>> = createSelector(\n\t[selectFormSubmissionsMapping, selectAssetsMapping],\n\t(submissions, assets) => {\n\t\tconst assetSubmissionMapping: Record<string, FormSubmission[]> = {}\n\t\tfor (const assetId in assets) {\n\t\t\tassetSubmissionMapping[assetId] = []\n\t\t}\n\t\tfor (const submissionId in submissions) {\n\t\t\tconst submission = submissions[submissionId]!\n\t\t\tif (submission.asset) {\n\t\t\t\tassetSubmissionMapping[submission.asset]?.push(submission)\n\t\t\t}\n\t\t}\n\t\treturn assetSubmissionMapping\n\t},\n)\n\nexport const formSubmissionReducer: Reducer<FormSubmissionState> = formSubmissionSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport { ModelState } from \"../typings\"\nimport {\n\tFormSubmissionAttachment,\n\tOvermapRootState,\n\tOvermapSelector,\n\tOvermapSelectorWithArgs,\n\tStored,\n} from \"../../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport type FormSubmissionAttachmentState = ModelState<Stored<FormSubmissionAttachment>>\n\nconst formSubmissionAttachmentAdapter = createModelAdapter<Stored<FormSubmissionAttachment>>(\n\t(attachment) => attachment.offline_id,\n)\n\nconst initialState: FormSubmissionAttachmentState = formSubmissionAttachmentAdapter.getInitialState({})\n\nexport const formSubmissionAttachmentSlice = createSlice({\n\tname: \"formSubmissionAttachments\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeFormSubmissionAttachments: formSubmissionAttachmentAdapter.initialize,\n\t\taddFormSubmissionAttachment: formSubmissionAttachmentAdapter.addOne,\n\t\taddFormSubmissionAttachments: formSubmissionAttachmentAdapter.addMany,\n\t\tsetFormSubmissionAttachment: formSubmissionAttachmentAdapter.setOne,\n\t\tsetFormSubmissionAttachments: formSubmissionAttachmentAdapter.setMany,\n\t\tupdateFormSubmissionAttachment: formSubmissionAttachmentAdapter.updateOne,\n\t\tupdateFormSubmissionAttachments: formSubmissionAttachmentAdapter.updateMany,\n\t\tdeleteFormSubmissionAttachment: formSubmissionAttachmentAdapter.deleteOne,\n\t\tdeleteFormSubmissionAttachments: formSubmissionAttachmentAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tinitializeFormSubmissionAttachments,\n\taddFormSubmissionAttachment,\n\taddFormSubmissionAttachments,\n\tsetFormSubmissionAttachment,\n\tsetFormSubmissionAttachments,\n\tupdateFormSubmissionAttachment,\n\tupdateFormSubmissionAttachments,\n\tdeleteFormSubmissionAttachment,\n\tdeleteFormSubmissionAttachments,\n} = formSubmissionAttachmentSlice.actions\n\nexport const selectFormSubmissionAttachmentsMapping: OvermapSelector<FormSubmissionAttachmentState[\"instances\"]> = (\n\tstate,\n) => {\n\treturn state.formSubmissionAttachmentReducer.instances\n}\n\nexport const selectFormSubmissionAttachemntsByIds = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectFormSubmissionAttachmentsMapping, (_, attachmentIds: string[]) => attachmentIds],\n\t\t(mapping, attachmentIds) => {\n\t\t\tconst attachmentIdsSet = new Set(attachmentIds)\n\n\t\t\treturn Object.values(mapping).filter((attachment) => attachmentIdsSet.has(attachment.offline_id))\n\t\t},\n\t),\n)\n\nexport const selectAttachmentsOfFormSubmission: OvermapSelectorWithArgs<string, Stored<FormSubmissionAttachment>[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector(\n\t\t\t[selectFormSubmissionAttachmentsMapping, (_state: OvermapRootState, submissionId: string) => submissionId],\n\t\t\t(attachmentsMapping, submissionId) => {\n\t\t\t\treturn Object.values(attachmentsMapping).filter((attachment) => attachment.submission === submissionId)\n\t\t\t},\n\t\t),\n\t)\n\nexport const formSubmissionAttachmentReducer: Reducer<FormSubmissionAttachmentState> =\n\tformSubmissionAttachmentSlice.reducer\n","import { createSlice, Reducer, createSelector } from \"@reduxjs/toolkit\"\nimport { ModelState } from \"../typings\"\nimport { OvermapSelector, OvermapSelectorWithArgs, Stored, FormRevisionAttachment } from \"../../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport type FormRevisionAttachmentState = ModelState<Stored<FormRevisionAttachment>>\n\nconst formRevisionAttachmentAdapter = createModelAdapter<Stored<FormRevisionAttachment>>(\n\t(attachment) => attachment.offline_id,\n)\n\nconst initialState: FormRevisionAttachmentState = formRevisionAttachmentAdapter.getInitialState({})\n\nexport const formRevisionAttachmentSlice = createSlice({\n\tname: \"formRevisionAttachments\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeFormRevisionAttachments: formRevisionAttachmentAdapter.initialize,\n\t\taddFormRevisionAttachment: formRevisionAttachmentAdapter.addOne,\n\t\taddFormRevisionAttachments: formRevisionAttachmentAdapter.addMany,\n\t\tsetFormRevisionAttachment: formRevisionAttachmentAdapter.setOne,\n\t\tsetFormRevisionAttachments: formRevisionAttachmentAdapter.setMany,\n\t\tupdateFormRevisionAttachment: formRevisionAttachmentAdapter.updateOne,\n\t\tupdateFormRevisionAttachments: formRevisionAttachmentAdapter.updateMany,\n\t\tdeleteFormRevisionAttachment: formRevisionAttachmentAdapter.deleteOne,\n\t\tdeleteFormRevisionAttachments: formRevisionAttachmentAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tinitializeFormRevisionAttachments,\n\taddFormRevisionAttachment,\n\taddFormRevisionAttachments,\n\tsetFormRevisionAttachment,\n\tsetFormRevisionAttachments,\n\tupdateFormRevisionAttachment,\n\tupdateFormRevisionAttachments,\n\tdeleteFormRevisionAttachment,\n\tdeleteFormRevisionAttachments,\n} = formRevisionAttachmentSlice.actions\n\nexport const selectFormRevisionAttachmentsMapping: OvermapSelector<FormRevisionAttachmentState[\"instances\"]> = (\n\tstate,\n) => {\n\treturn state.formRevisionAttachmentReducer.instances\n}\n\nexport const selectAttachmentsOfFormRevision: OvermapSelectorWithArgs<string, Stored<FormRevisionAttachment>[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector(\n\t\t\t[selectFormRevisionAttachmentsMapping, (_state, revisionId: string) => revisionId],\n\t\t\t(attachments, revisionId) => {\n\t\t\t\treturn Object.values(attachments).filter((attachment) => attachment.revision === revisionId)\n\t\t\t},\n\t\t),\n\t)\n\nexport const formRevisionAttachmentReducer: Reducer<FormRevisionAttachmentState> = formRevisionAttachmentSlice.reducer\n","import { EmailDomain, OvermapSelector, OvermapRootState } from \"../../typings\"\nimport { createSlice, Reducer, createSelector } from \"@reduxjs/toolkit\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport type EmailDomainState = ModelState<EmailDomain>\n\nconst emailDomainAdapter = createModelAdapter<EmailDomain>((emailDomain) => emailDomain.offline_id)\n\nconst initialState = emailDomainAdapter.getInitialState({})\n\nexport const emailDomainsSlice = createSlice({\n\tname: \"emailDomains\",\n\tinitialState,\n\treducers: {\n\t\tinitializeEmailDomains: emailDomainAdapter.initialize,\n\t\taddEmailDomain: emailDomainAdapter.addOne,\n\t\tdeleteEmailDomain: emailDomainAdapter.deleteOne,\n\t},\n})\n\nexport const { initializeEmailDomains, addEmailDomain, deleteEmailDomain } = emailDomainsSlice.actions\n\nexport const selectEmailDomainsAsMapping: OvermapSelector<Record<number, EmailDomain>> = (state: OvermapRootState) =>\n\tstate.emailDomainsReducer.instances\n\nexport const selectEmailDomains = (state: OvermapRootState): EmailDomain[] =>\n\tObject.values(state.emailDomainsReducer.instances)\n\nexport const selectEmailDomainsOfOrganization = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectEmailDomains, (_, organizationId: number) => organizationId],\n\t\t(emailDomains, organizationId) => {\n\t\t\treturn emailDomains.filter((emailDomain) => emailDomain.organization === organizationId)\n\t\t},\n\t),\n)\n\nexport const emailDomainsReducer: Reducer<EmailDomainState> = emailDomainsSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport {\n\tDocument,\n\tMovePosition,\n\tOvermapRootState,\n\tOvermapSelector,\n\tOvermapSelectorWithArgs,\n\tStored,\n\tSubmitted,\n} from \"../../typings\"\nimport { onlyUniqueOfflineIds, restructureCreateSelectorWithArgs, toOfflineIdRecord } from \"../../utils\"\n\nexport interface DocumentState {\n\tdocuments: Record<string, Stored<Document>>\n}\n\nexport interface MoveDocumentPayload {\n\tdocumentId: Document[\"offline_id\"]\n\ttargetDocumentId: Document[\"offline_id\"] | null\n\tposition: MovePosition\n}\n\nconst initialState: DocumentState = {\n\tdocuments: {},\n}\n\nexport const documentSlice = createSlice({\n\tname: \"documents\",\n\tinitialState: initialState,\n\textraReducers: (builder) =>\n\t\tbuilder.addCase(\"RESET\", (state) => {\n\t\t\tObject.assign(state, initialState)\n\t\t}),\n\treducers: {\n\t\tsetDocuments: (state, action: { payload: Stored<Document>[] }) => {\n\t\t\tif (action.payload.filter(onlyUniqueOfflineIds).length !== action.payload.length) {\n\t\t\t\tthrow new Error(\"Tried to use setIssues reducer with duplicate ID's\")\n\t\t\t}\n\t\t\tstate.documents = toOfflineIdRecord(action.payload)\n\t\t},\n\t\taddDocuments: (state, action: { payload: Stored<Document>[] }) => {\n\t\t\tfor (const document of action.payload) {\n\t\t\t\tif (document.offline_id in state.documents) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`attempting to add a document with offline_id ${document.offline_id} which already exists in state.documents.`,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (const document of action.payload) {\n\t\t\t\tif (document.parent_document && !!state.documents[document.parent_document]) {\n\t\t\t\t\tconst parentDocument = state.documents[document.parent_document]!\n\t\t\t\t\tstate.documents[document.parent_document] = {\n\t\t\t\t\t\t...parentDocument,\n\t\t\t\t\t\tchildren_documents: [...parentDocument.children_documents, document.offline_id],\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tstate.documents[document.offline_id] = document\n\t\t\t}\n\t\t},\n\t\tupdateDocuments: (state, action: { payload: Submitted<Partial<Stored<Document>>>[] }) => {\n\t\t\tfor (const document of action.payload) {\n\t\t\t\tif (!(document.offline_id in state.documents)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`attempting to update a document with offline_id ${document.offline_id} which doesn't exists in state.documents.`,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (const document of action.payload) {\n\t\t\t\tconst existingDocument = state.documents[document.offline_id]!\n\t\t\t\tif (document.organization !== undefined && document.organization !== existingDocument.organization) {\n\t\t\t\t\tthrow new Error(\"organization cannot be updated\")\n\t\t\t\t}\n\t\t\t\tif (document.project !== undefined && document.project !== existingDocument.project) {\n\t\t\t\t\tthrow new Error(\"project cannot be updated\")\n\t\t\t\t}\n\t\t\t\tstate.documents[document.offline_id] = {\n\t\t\t\t\t...existingDocument,\n\t\t\t\t\t...document,\n\t\t\t\t\t// Without the cast, TypeScript doesn't realize that we have guaranteed that the document doesn't\n\t\t\t\t\t// have both a project and an organization.\n\t\t\t\t} as Stored<Document>\n\t\t\t}\n\t\t},\n\t\tmoveDocument: (state, action: { payload: MoveDocumentPayload }) => {\n\t\t\tconst { documentId, targetDocumentId, position } = action.payload\n\t\t\tif (!(documentId in state.documents)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`attempting to move a document with offline_id ${documentId} which doesn't exist in state.documents`,\n\t\t\t\t)\n\t\t\t}\n\n\t\t\t// even if a document is being moved to the same parent, it needs to be removed since its position in its parent would be changing\n\t\t\tconst document = state.documents[documentId]!\n\t\t\tif (document.parent_document && state.documents[document.parent_document]) {\n\t\t\t\tconst { children_documents } = state.documents[document.parent_document]!\n\t\t\t\tstate.documents[document.parent_document]!.children_documents.splice(\n\t\t\t\t\tchildren_documents.indexOf(document.offline_id),\n\t\t\t\t\t1,\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tif (targetDocumentId) {\n\t\t\t\tconst targetDocument = state.documents[targetDocumentId]\n\t\t\t\tconst newParentDocument = targetDocument?.parent_document\n\t\t\t\t\t? state.documents[targetDocument.parent_document]\n\t\t\t\t\t: null\n\n\t\t\t\tswitch (position) {\n\t\t\t\t\tcase \"left\":\n\t\t\t\t\t\tif (!newParentDocument) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t\"attempting to move a document to the left of a document with no parent_document\",\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// if newParentDocument exists, then targetDocument must exist\n\t\t\t\t\t\tstate.documents[targetDocument!.parent_document!]!.children_documents.splice(\n\t\t\t\t\t\t\tnewParentDocument.children_documents.indexOf(targetDocument!.offline_id),\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\tdocument.offline_id,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tstate.documents[documentId]!.parent_document = newParentDocument.offline_id\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase \"right\":\n\t\t\t\t\t\tif (!newParentDocument) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t\"attempting to move a document to the left of a document with no parent_document\",\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// if newParentDocument exists, then targetDocument must exist\n\t\t\t\t\t\tstate.documents[targetDocument!.parent_document!]!.children_documents.splice(\n\t\t\t\t\t\t\tnewParentDocument.children_documents.indexOf(targetDocument!.offline_id) + 1,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\tdocument.offline_id,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tstate.documents[documentId]!.parent_document = newParentDocument.offline_id\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase \"left-child\":\n\t\t\t\t\t\tif (!targetDocument) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t\"attempting to move a document to the left-child of a document that doesn't exist\",\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstate.documents[targetDocumentId]!.children_documents.unshift(document.offline_id)\n\t\t\t\t\t\tstate.documents[documentId]!.parent_document = targetDocument.offline_id\n\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase \"right-child\":\n\t\t\t\t\t\tif (!targetDocument) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t\"attempting to move a document to the left-child of a document that doesn't exist\",\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstate.documents[targetDocumentId]!.children_documents.push(document.offline_id)\n\t\t\t\t\t\tstate.documents[documentId]!.parent_document = targetDocument.offline_id\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tstate.documents[documentId]!.parent_document = null\n\t\t\t}\n\t\t},\n\t\tremoveDocuments: (state, action: { payload: string[] }) => {\n\t\t\tfor (const documentId of action.payload) {\n\t\t\t\tif (!(documentId in state.documents)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`attempting to delete a document with offline_id ${documentId} which doesn't exists in state.documents.`,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (const documentId of action.payload) {\n\t\t\t\tconst document = state.documents[documentId]!\n\t\t\t\tif (document.parent_document && !!state.documents[document.parent_document]) {\n\t\t\t\t\tconst parentDocument = state.documents[document.parent_document]!\n\t\t\t\t\tstate.documents[document.parent_document] = {\n\t\t\t\t\t\t...parentDocument,\n\t\t\t\t\t\tchildren_documents: parentDocument.children_documents.filter(\n\t\t\t\t\t\t\t(offline_id) => offline_id !== document.offline_id,\n\t\t\t\t\t\t),\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdelete state.documents[documentId]\n\t\t\t}\n\t\t},\n\t},\n})\n\nexport const { setDocuments, addDocuments, updateDocuments, moveDocument, removeDocuments } = documentSlice.actions\n\nexport const selectDocumentsMapping: OvermapSelector<Record<string, Stored<Document>>> = (state: OvermapRootState) =>\n\tstate.documentsReducer.documents\n\nexport const selectDocuments: OvermapSelector<Stored<Document>[]> = createSelector(\n\t[selectDocumentsMapping],\n\t(mapping) => Object.values(mapping),\n)\n\nexport const selectDocumentById: OvermapSelectorWithArgs<string, Stored<Document>> =\n\t(documentId: Document[\"offline_id\"]) => (state) => {\n\t\treturn state.documentsReducer.documents[documentId]\n\t}\n\nexport const selectDocumentsByIds = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectDocumentsMapping, (_state, documentIds: Document[\"offline_id\"][]) => documentIds],\n\t\t(mapping, documentIds) => {\n\t\t\tconst documents: Stored<Document>[] = []\n\n\t\t\tfor (const documentId of documentIds) {\n\t\t\t\tconst document = mapping[documentId]\n\t\t\t\tif (document) {\n\t\t\t\t\tdocuments.push(document)\n\t\t\t\t} else {\n\t\t\t\t\tconsole.warn(\"selectDocumentByIds: No document exists with the id\", documentId)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn documents\n\t\t},\n\t),\n)\n\nexport const selectAncestorIdsOfDocument = restructureCreateSelectorWithArgs(\n\tcreateSelector([selectDocumentsMapping, (_state, documentId: string) => documentId], (mapping, documentId) => {\n\t\tconst listOfAncestors: string[] = []\n\t\tconst document = mapping[documentId]\n\t\tif (!document || !document.parent_document) return listOfAncestors\n\n\t\tlet currentAncestor = mapping[document.parent_document]\n\n\t\twhile (currentAncestor) {\n\t\t\tlistOfAncestors.push(currentAncestor.offline_id)\n\t\t\tcurrentAncestor = mapping[currentAncestor.parent_document ?? \"\"]\n\t\t}\n\t\treturn listOfAncestors\n\t}),\n)\n\nexport const selectRootDocuments = createSelector([selectDocuments], (documents) =>\n\tdocuments.filter((document) => !document.parent_document),\n)\n\nexport const documentsReducer: Reducer<DocumentState> = documentSlice.reducer\n","import { createSlice, createSelector, Reducer } from \"@reduxjs/toolkit\"\nimport { ModelState } from \"../typings\"\nimport { DocumentAttachment, OvermapRootState, OvermapSelector, OvermapSelectorWithArgs, Stored } from \"../../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport type DocumentAttachmentState = ModelState<Stored<DocumentAttachment>>\n\nconst documentAttachmentAdapter = createModelAdapter<Stored<DocumentAttachment>>((attachment) => attachment.offline_id)\n\nconst initialState = documentAttachmentAdapter.getInitialState({})\n\nexport const documentAttachmentSlice = createSlice({\n\tname: \"documentAttachments\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeDocumentAttachments: documentAttachmentAdapter.initialize,\n\t\taddDocumentAttachment: documentAttachmentAdapter.addOne,\n\t\taddDocumentAttachments: documentAttachmentAdapter.addMany,\n\t\tsetDocumentAttachment: documentAttachmentAdapter.setOne,\n\t\tsetDocumentAttachments: documentAttachmentAdapter.setMany,\n\t\tupdateDocumentAttachment: documentAttachmentAdapter.updateOne,\n\t\tupdateDocumentAttachments: documentAttachmentAdapter.updateMany,\n\t\tdeleteDocumentAttachment: documentAttachmentAdapter.deleteOne,\n\t\tdeleteDocumentAttachments: documentAttachmentAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tinitializeDocumentAttachments,\n\taddDocumentAttachment,\n\taddDocumentAttachments,\n\tsetDocumentAttachment,\n\tsetDocumentAttachments,\n\tupdateDocumentAttachment,\n\tupdateDocumentAttachments,\n\tdeleteDocumentAttachment,\n\tdeleteDocumentAttachments,\n} = documentAttachmentSlice.actions\n\nexport const selectDocumentAttachmentMapping = (state: OvermapRootState) => state.documentAttachmentReducer.instances\n\nexport const selectAllDocumentAttachments: OvermapSelector<Stored<DocumentAttachment>[]> = createSelector(\n\t[selectDocumentAttachmentMapping],\n\t(mapping) => Object.values(mapping),\n)\n\nexport const selectDocumentAttachment: OvermapSelectorWithArgs<string, Stored<DocumentAttachment>> =\n\t(attachmentId: string) => (state: OvermapRootState) => {\n\t\treturn state.documentAttachmentReducer.instances[attachmentId]\n\t}\n\nexport const selectAttachmentsOfDocument = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectAllDocumentAttachments, (_state: OvermapRootState, documentId: string) => documentId],\n\t\t(attachments, documentId) => {\n\t\t\treturn attachments.filter(({ document }) => documentId === document)\n\t\t},\n\t),\n)\n\nexport const selectAttachmentsOfDocumentByType = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectAllDocumentAttachments, (_state: OvermapRootState, documentId: string) => documentId],\n\t\t(attachments, documentId) => {\n\t\t\tconst attachmentsOfProject = attachments.filter(({ document }) => documentId === document)\n\t\t\tconst fileAttachments = attachmentsOfProject.filter(\n\t\t\t\t// this null check here is necessary, there are cases where file_type is null or undefined\n\t\t\t\t({ file_type }) => !file_type || !file_type.startsWith(\"image/\"),\n\t\t\t)\n\t\t\tconst imageAttachments = attachmentsOfProject.filter(\n\t\t\t\t// this null check here is necessary, there are cases where file_type is null or undefined\n\t\t\t\t({ file_type }) => file_type && file_type.startsWith(\"image/\"),\n\t\t\t)\n\t\t\treturn { fileAttachments, imageAttachments }\n\t\t},\n\t),\n)\n\nexport const documentAttachmentReducer: Reducer<DocumentAttachmentState> = documentAttachmentSlice.reducer\n","import { createSlice, Reducer, createSelector } from \"@reduxjs/toolkit\"\nimport {\n\tTeam,\n\tOvermapRootState,\n\tStored,\n\tOvermapSelector,\n\tOvermapSelectorWithArgs,\n\tOrganization,\n\tUser,\n} from \"../../typings\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\n\nexport type TeamState = ModelState<Stored<Team>>\n\nconst teamAdapter = createModelAdapter<Stored<Team>>((team) => team.offline_id)\n\nconst initialState: TeamState = teamAdapter.getInitialState({})\n\nexport const teamSlice = createSlice({\n\tname: \"teams\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tsetTeam: teamAdapter.setOne,\n\t\tinitializeTeams: teamAdapter.initialize,\n\t\taddTeam: teamAdapter.addOne,\n\t\tupdateTeam: teamAdapter.updateOne,\n\t\tdeleteTeam: teamAdapter.deleteOne,\n\t},\n})\n\nexport const { setTeam, initializeTeams, addTeam, updateTeam, deleteTeam } = teamSlice.actions\n\nexport const selectTeamsMapping: OvermapSelector<TeamState[\"instances\"]> = (state: OvermapRootState) =>\n\tstate.teamReducer.instances\n\nexport const selectTeams: OvermapSelector<Stored<Team>[]> = createSelector([selectTeamsMapping], (teams) => {\n\treturn Object.values(teams)\n})\n\nexport const selectTeamById: OvermapSelectorWithArgs<string, Stored<Team>> =\n\t(teamId: string) => (state: OvermapRootState) => {\n\t\treturn state.teamReducer.instances[teamId]\n\t}\n\nexport const selectTeamsOfOrganization: OvermapSelectorWithArgs<Organization[\"id\"], Stored<Team>[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector(\n\t\t\t[selectTeams, (_state: OvermapRootState, organizationId: Organization[\"id\"]) => organizationId],\n\t\t\t(teams, organizationId) => {\n\t\t\t\treturn teams.filter((team) => team.organization === organizationId)\n\t\t\t},\n\t\t),\n\t)\n\nexport const selectTeamsOfUser: OvermapSelectorWithArgs<User[\"id\"], Stored<Team>[]> = restructureCreateSelectorWithArgs(\n\tcreateSelector([selectTeams, (_state: OvermapRootState, userId: User[\"id\"]) => userId], (teams, userId) => {\n\t\treturn teams.filter((team) => team.members.includes(userId))\n\t}),\n)\n\nexport const teamReducer: Reducer<TeamState> = teamSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport { AgentUserConversation, OvermapRootState, OvermapSelector } from \"../../typings\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\n\nexport type AgentsState = ModelState<AgentUserConversation>\n\nconst agentUserConversationAdapter = createModelAdapter<AgentUserConversation>(\n\t(conversation) => conversation.offline_id,\n)\n\nconst initialState = agentUserConversationAdapter.getInitialState({})\n\nexport const agentsSlice = createSlice({\n\tname: \"agents\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeConversations: agentUserConversationAdapter.initialize,\n\t\taddConversation: agentUserConversationAdapter.addOne,\n\t\tsetConversation: agentUserConversationAdapter.setOne,\n\t\tupdateConversation: agentUserConversationAdapter.updateOne,\n\t},\n})\n\nexport const { initializeConversations, addConversation, setConversation, updateConversation } = agentsSlice.actions\nexport const selectConversationMapping = (state: OvermapRootState) => state.agentsReducer.instances\n\nexport const selectConversations: OvermapSelector<AgentUserConversation[]> = createSelector(\n\t[selectConversationMapping],\n\t(conversationMapping) => Object.values(conversationMapping),\n)\n\nexport const selectConversation = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectConversationMapping, (_state, conversationId: string) => conversationId],\n\t\t(conversationMapping, conversationId) => conversationMapping[conversationId],\n\t),\n)\n\nexport const agentsReducer: Reducer<AgentsState> = agentsSlice.reducer\n","import { createSlice, Reducer, createSelector } from \"@reduxjs/toolkit\"\nimport { ModelState } from \"../typings\"\nimport { IssueComment, OvermapRootState, Stored } from \"../../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport type IssueCommentState = ModelState<Stored<IssueComment>>\n\nconst issueCommentAdapter = createModelAdapter<Stored<IssueComment>>((comment) => comment.offline_id)\n\nconst initialState: IssueCommentState = issueCommentAdapter.getInitialState({})\n\nexport const issueCommentSlice = createSlice({\n\tname: \"issueComments\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\taddIssueComment: issueCommentAdapter.addOne,\n\t\taddIssueComments: issueCommentAdapter.addMany,\n\t\tsetIssueComment: issueCommentAdapter.setOne,\n\t\tsetIssueComments: issueCommentAdapter.setMany,\n\t\tdeleteIssueComment: issueCommentAdapter.deleteOne,\n\t\tdeleteIssueComments: issueCommentAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tsetIssueComments,\n\tsetIssueComment,\n\taddIssueComment,\n\taddIssueComments,\n\tdeleteIssueComment,\n\tdeleteIssueComments,\n} = issueCommentSlice.actions\n\nexport const selectIssueCommentMapping = (state: OvermapRootState) => state.issueCommentReducer.instances\n\nexport const selectCommentsOfIssue = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectIssueCommentMapping, (_state, issueId: string) => issueId],\n\t\t(commentMapping, issueId: string) => {\n\t\t\treturn Object.values(commentMapping).filter((comment) => comment.issue === issueId)\n\t\t},\n\t),\n)\n\nexport const issueCommentReducer: Reducer<IssueCommentState> = issueCommentSlice.reducer\n","import { createSlice, Reducer, createSelector } from \"@reduxjs/toolkit\"\nimport { IssueUpdate, OvermapRootState, Stored } from \"../../typings\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport type IssueUpdateState = ModelState<Stored<IssueUpdate>>\n\nconst issueUpdateAdapter = createModelAdapter<Stored<IssueUpdate>>((issueUpdate) => issueUpdate.offline_id)\n\nconst initialState: IssueUpdateState = issueUpdateAdapter.getInitialState({})\n\nexport const issueUpdateSlice = createSlice({\n\tname: \"issueUpdates\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeIssueUpdates: issueUpdateAdapter.setMany,\n\t\tsetIssueUpdate: issueUpdateAdapter.setOne,\n\t\taddIssueUpdate: issueUpdateAdapter.addOne,\n\t\taddIssueUpdates: issueUpdateAdapter.addMany,\n\t\tdeleteIssueUpdate: issueUpdateAdapter.deleteOne,\n\t\tdeleteIssueUpdates: issueUpdateAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tinitializeIssueUpdates,\n\tsetIssueUpdate,\n\taddIssueUpdate,\n\taddIssueUpdates,\n\tdeleteIssueUpdate,\n\tdeleteIssueUpdates,\n} = issueUpdateSlice.actions\n\nexport const selectIssueUpdateMapping = (state: OvermapRootState) => state.issueUpdateReducer.instances\n\nexport const selectIssueUpdatesOfIssue = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectIssueUpdateMapping, (_state: OvermapRootState, issueId: string) => issueId],\n\t\t(updates, issueId) => {\n\t\t\treturn Object.values(updates).filter((update) => update.issue === issueId)\n\t\t},\n\t),\n)\n\nexport const issueUpdateReducer: Reducer<IssueUpdateState> = issueUpdateSlice.reducer\n","import { createSlice, Reducer, createSelector } from \"@reduxjs/toolkit\"\nimport { IssueAttachment, OvermapRootState, OvermapSelector, OvermapSelectorWithArgs, Stored } from \"../../typings\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport type IssueAttachmentState = ModelState<Stored<IssueAttachment>>\n\nconst issueAttachmentAdapter = createModelAdapter<Stored<IssueAttachment>>((attachment) => attachment.offline_id)\n\nconst initialState: IssueAttachmentState = issueAttachmentAdapter.getInitialState({})\n\nexport const issueAttachmentSlice = createSlice({\n\tname: \"issueAttachments\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeIssueAttachments: issueAttachmentAdapter.initialize,\n\t\taddIssueAttachment: issueAttachmentAdapter.addOne,\n\t\taddIssueAttachments: issueAttachmentAdapter.addMany,\n\t\tsetIssueAttachment: issueAttachmentAdapter.setOne,\n\t\tsetIssueAttachments: issueAttachmentAdapter.setMany,\n\t\tupdateIssueAttachment: issueAttachmentAdapter.updateOne,\n\t\tupdateIssueAttachments: issueAttachmentAdapter.updateMany,\n\t\tdeleteIssueAttachment: issueAttachmentAdapter.deleteOne,\n\t\tdeleteIssueAttachments: issueAttachmentAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tinitializeIssueAttachments,\n\taddIssueAttachment,\n\taddIssueAttachments,\n\tsetIssueAttachment,\n\tsetIssueAttachments,\n\tupdateIssueAttachment,\n\tupdateIssueAttachments,\n\tdeleteIssueAttachment,\n\tdeleteIssueAttachments,\n} = issueAttachmentSlice.actions\n\nexport const selectIssueAttachmentMapping = (state: OvermapRootState) => state.issueAttachmentReducer.instances\nexport const selectIssueAttachments: OvermapSelector<Stored<IssueAttachment>[]> = createSelector(\n\t[selectIssueAttachmentMapping],\n\t(mapping) => Object.values(mapping),\n)\n\nexport const selectAttachmentsOfIssue = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectIssueAttachments, (_state: OvermapRootState, issueId: string) => issueId],\n\t\t(attachments, issueId) => {\n\t\t\treturn attachments.filter(({ issue }) => issueId === issue)\n\t\t},\n\t),\n)\n\nexport const selectIssueAttachment: OvermapSelectorWithArgs<string, Stored<IssueAttachment>> =\n\t(attachmentId: string) => (root: OvermapRootState) => {\n\t\treturn root.issueAttachmentReducer.instances[attachmentId]\n\t}\n\nexport const selectAttachmentsOfIssueByType = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectIssueAttachments, (_state: OvermapRootState, issueId: string) => issueId],\n\t\t(attachments, issueId) => {\n\t\t\tconst attachmentsOfIssue = attachments.filter(({ issue }) => issue === issueId)\n\t\t\tconst fileAttachments = attachmentsOfIssue.filter(\n\t\t\t\t// this null check here is necessary, there are cases where file_type is null or undefined\n\t\t\t\t({ file_type }) => !file_type || !file_type.startsWith(\"image/\"),\n\t\t\t)\n\t\t\tconst imageAttachments = attachmentsOfIssue.filter(\n\t\t\t\t// this null check here is necessary, there are cases where file_type is null or undefined\n\t\t\t\t({ file_type }) => file_type && file_type.startsWith(\"image/\"),\n\t\t\t)\n\t\t\treturn { fileAttachments, imageAttachments }\n\t\t},\n\t),\n)\n\nexport const issueAttachmentReducer: Reducer<IssueAttachmentState> = issueAttachmentSlice.reducer\n","import { createSlice, Reducer } from \"@reduxjs/toolkit\"\n\nexport interface VersioningState {\n\tversion: number\n}\n\nconst initialState: VersioningState = {\n\tversion: 0,\n}\n\n/**\n * Version of the offline redux store\n */\nexport const versioningSlice = createSlice({\n\tname: \"versioning\",\n\tinitialState,\n\treducers: {},\n})\n\nexport const versioningReducer: Reducer<VersioningState> = versioningSlice.reducer\n","import { createSlice, Reducer, createSelector } from \"@reduxjs/toolkit\"\nimport { GeoImage, OvermapRootState, Stored } from \"../../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { ModelState } from \"../typings\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport type GeoImageSliceState = ModelState<Stored<GeoImage>>\n\nconst geoImageAdapter = createModelAdapter<GeoImage>((model) => model.offline_id)\n\nconst initialState: GeoImageSliceState = geoImageAdapter.getInitialState({})\n\nexport const geoImageSlice = createSlice({\n\tname: \"geoImages\",\n\tinitialState,\n\textraReducers: (builder) => {\n\t\tbuilder.addCase(\"RESET\", (state) => {\n\t\t\tObject.assign(state, initialState)\n\t\t})\n\t},\n\treducers: {\n\t\tinitializeGeoImages: geoImageAdapter.initialize,\n\t\tsetGeoImage: geoImageAdapter.setOne,\n\t\tsetGeoImages: geoImageAdapter.setMany,\n\t\taddGeoImage: geoImageAdapter.addOne,\n\t\taddGeoImages: geoImageAdapter.addMany,\n\t\tupdateGeoImage: geoImageAdapter.updateOne,\n\t\tupdateGeoImages: geoImageAdapter.updateMany,\n\t\tdeleteGeoImage: geoImageAdapter.deleteOne,\n\t\tdeleteGeoImages: geoImageAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tinitializeGeoImages,\n\tsetGeoImage,\n\tsetGeoImages,\n\taddGeoImage,\n\taddGeoImages,\n\tupdateGeoImage,\n\tupdateGeoImages,\n\tdeleteGeoImage,\n\tdeleteGeoImages,\n} = geoImageSlice.actions\n\nexport const selectGeoImageMapping = (state: OvermapRootState) => state.geoImageReducer.instances\n\nexport const selectGeoImages = (state: OvermapRootState) => Object.values(state.geoImageReducer.instances)\n\nexport const selectGeoImageById = (id: string) => (state: OvermapRootState) => {\n\treturn state.geoImageReducer.instances[id]\n}\n\nexport const selectGeoImagesOfProject = restructureCreateSelectorWithArgs(\n\tcreateSelector([selectGeoImages, (_, projectId: number) => projectId], (mapImages, projectId) => {\n\t\treturn mapImages.filter((mapImage) => mapImage.project === projectId)\n\t}),\n)\n\nexport const geoImageReducer: Reducer<GeoImageSliceState> = geoImageSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport type { IssueAssociation, OvermapRootState, OvermapSelectorWithArgs, Stored } from \"../../typings\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\nimport { createModelAdapter } from \"../adapter\"\nimport type { ModelState } from \"../typings\"\n\nexport type IssueAssociationSliceState = ModelState<Stored<IssueAssociation>>\n\nconst issueAssociationAdapter = createModelAdapter<Stored<IssueAssociation>>((assoc) => assoc.offline_id)\n\nconst initialState: IssueAssociationSliceState = issueAssociationAdapter.getInitialState({})\n\nexport const issueAssociationSlice = createSlice({\n\tname: \"issueAssociations\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeIssueAssociations: issueAssociationAdapter.initialize,\n\t\taddIssueAssociation: issueAssociationAdapter.addOne,\n\t\taddIssueAssociations: issueAssociationAdapter.addMany,\n\t\tsetIssueAssociation: issueAssociationAdapter.setOne,\n\t\tsetIssueAssociations: issueAssociationAdapter.setMany,\n\t\tupdateIssueAssociation: issueAssociationAdapter.updateOne,\n\t\tupdateIssueAssociations: issueAssociationAdapter.updateMany,\n\t\tdeleteIssueAssociation: issueAssociationAdapter.deleteOne,\n\t\tdeleteIssueAssociations: issueAssociationAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tinitializeIssueAssociations,\n\tsetIssueAssociations,\n\tsetIssueAssociation,\n\tupdateIssueAssociation,\n\tupdateIssueAssociations,\n\taddIssueAssociation,\n\taddIssueAssociations,\n\tdeleteIssueAssociation,\n\tdeleteIssueAssociations,\n} = issueAssociationSlice.actions\n\nexport const selectIssueAssociationMapping = (state: OvermapRootState): Record<string, Stored<IssueAssociation>> =>\n\tstate.issueAssociationReducer.instances\n\nexport const selectIssueAssociations = createSelector([selectIssueAssociationMapping], (associations) => {\n\treturn Object.values(associations)\n})\n\nexport const selectIssueAssociationById: OvermapSelectorWithArgs<string, Stored<IssueAssociation>> =\n\t(id) => (state) => {\n\t\treturn state.issueAssociationReducer.instances[id]\n\t}\n\nexport const selectIssueAssociationsToIssue = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectIssueAssociationMapping, (_state, issueId: string) => issueId],\n\t\t(associationMapping, issueId) => {\n\t\t\treturn Object.values(associationMapping).filter((assoc) => assoc.associated_issue === issueId)\n\t\t},\n\t),\n)\n\nexport const selectIssueAssociationsOfIssue = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectIssueAssociationMapping, (_state, issueId: string) => issueId],\n\t\t(associationMapping, issueId) => {\n\t\t\treturn Object.values(associationMapping).filter((assoc) => assoc.issue === issueId)\n\t\t},\n\t),\n)\n\nexport const selectIssueAssociationsOfAsset = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectIssueAssociationMapping, (_state, assetId: string) => assetId],\n\t\t(associationMapping, assetId) => {\n\t\t\treturn Object.values(associationMapping).filter((assoc) => assoc.asset === assetId)\n\t\t},\n\t),\n)\n\nexport const issueAssociationReducer: Reducer<IssueAssociationSliceState> = issueAssociationSlice.reducer\n","// NOTE: Also update $full-asset-marker-size in src/theme/_variables.sass\nexport const fullAssetMarkerSize = 45 // px\n","import { IssuePriority, IssueStatus } from \"../enums\"\n\nexport const DEFAULT_ISSUE_STATUS = IssueStatus.BACKLOG\nexport const DEFAULT_ISSUE_PRIORITY = IssuePriority.MEDIUM\n","export const OUTBOX_RETRY_DELAY = 5000 // milliseconds\n","import { ToolkitStore } from \"@reduxjs/toolkit/dist/configureStore\"\nimport { BaseState } from \"../typings\"\nimport { BaseSDK } from \"./base\"\n\n/** The client store is the store passed to the SDKProvider\n * and is used where the SDKProvider is not available.\n */\nlet clientStore: ToolkitStore<BaseState> | undefined\n\nexport function setClientStore<TState extends BaseState>(store: ToolkitStore<TState>) {\n\tclientStore = store\n}\n\nexport function getClientStore(): ToolkitStore<BaseState> | undefined {\n\treturn clientStore\n}\n\nlet clientSDK: BaseSDK<BaseState> | undefined\n\nexport function setClientSDK<TState extends BaseState>(sdkCtor: BaseSDK<TState>) {\n\tclientSDK = sdkCtor\n}\n\nexport function getClientSDK(): BaseSDK<BaseState> | undefined {\n\treturn clientSDK\n}\n","import { AnyAction } from \"@reduxjs/toolkit\"\nimport type { BaseSDK } from \"../base\"\nimport { BaseState } from \"../../typings\"\nimport { SDKRequest } from \"../typings\"\n\nexport const CLASS_NAME_TO_SERVICE: Record<string, BaseService<BaseState, BaseSDK<BaseState>>> = {}\n\n/**\n * Abstract base class for building a service that can enqueue API requests\n */\nexport abstract class BaseService<TStore extends BaseState, TSDK extends BaseSDK<TStore>> {\n\tprotected readonly client: TSDK\n\tabstract readonly host: string\n\n\tprotected constructor(sdk: TSDK) {\n\t\tCLASS_NAME_TO_SERVICE[this.constructor.name] = this\n\t\tthis.client = sdk\n\t}\n\n\tprotected async enqueueRequest<TResult>(requestDetails: SDKRequest): Promise<TResult> {\n\t\t// enqueueRequest is a wrapper for _enqueueRequest that ensures the result is not an APIError unless\n\t\t// `.catch()` is triggered.\n\t\treturn this.client.enqueueRequest(requestDetails, this.host, this.constructor.name)\n\t}\n\n\tprotected dispatch(action: AnyAction) {\n\t\tthis.client.store.dispatch(action)\n\t}\n}\n","import { AnyAction, compose, Reducer } from \"redux\"\nimport { offline } from \"@redux-offline/redux-offline\"\nimport offlineConfig from \"@redux-offline/redux-offline/lib/defaults\"\nimport localforage from \"localforage\"\n\n// TODO: Fix\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-expect-error\nimport createMigration from \"redux-persist-migrate\"\n\nimport { combineReducers, createNextState } from \"@reduxjs/toolkit\"\nimport {\n\tConfig,\n\tOfflineAction,\n\tOfflineMetadata,\n\tOfflineState,\n\tResultAction,\n} from \"@redux-offline/redux-offline/lib/types\"\nimport request from \"superagent\"\nimport { HttpMethod } from \"../enums\"\nimport { manifest } from \"./migrations\"\n\n// There are two \"blobs\": The Blob type from the \"buffer\" package (part of node),\n// and the Blob type from the browser. For some reason, superagent uses the \"buffer\"\n// version after moving code from hemora-web to overmap-core. This overwrites the name\n// \"Blob\". There are minor differences between the two interfaces (remove the type casting\n// of the `file` argument to `req.field()` in performRequest() to see the error), but it's\n// unlikely that we'll run into any problems.\nimport { Blob } from \"buffer\"\nimport {\n\tAPIError,\n\tBaseApiService,\n\ttype BaseSDK,\n\ttype OfflineMetaEffect,\n\tOutboxCoordinator,\n\tRequestDetails,\n} from \"../sdk\"\nimport { ToastProps, unsafeShowToast } from \"@overmap-ai/blocks\"\nimport {\n\t_setLatestRetryTime,\n\tagentsReducer,\n\tAgentsState,\n\tassetAttachmentReducer,\n\tAssetAttachmentState,\n\tassetReducer,\n\tassetStageCompletionReducer,\n\tAssetStageCompletionState,\n\tassetStageReducer,\n\tAssetStageState,\n\tAssetState,\n\tassetTypeAttachmentReducer,\n\tAssetTypeAttachmentState,\n\tassetTypeReducer,\n\tAssetTypeState,\n\tauthReducer,\n\tAuthState,\n\tcategoryReducer,\n\tCategoryState,\n\tdocumentAttachmentReducer,\n\tDocumentAttachmentState,\n\tdocumentsReducer,\n\tDocumentState,\n\temailDomainsReducer,\n\tEmailDomainState,\n\tfileReducer,\n\tFileState,\n\tformReducer,\n\tformRevisionAttachmentReducer,\n\tFormRevisionAttachmentState,\n\tformRevisionReducer,\n\tFormRevisionState,\n\tFormState,\n\tformSubmissionAttachmentReducer,\n\tFormSubmissionAttachmentState,\n\tformSubmissionReducer,\n\tFormSubmissionState,\n\tgeoImageReducer,\n\tGeoImageSliceState,\n\tissueAssociationReducer,\n\tIssueAssociationSliceState,\n\tissueAttachmentReducer,\n\tIssueAttachmentState,\n\tissueCommentReducer,\n\tIssueCommentState,\n\tissueReducer,\n\tIssueState,\n\tissueTypeReducer,\n\tIssueTypeState,\n\tissueUpdateReducer,\n\tIssueUpdateState,\n\tlicenseReducer,\n\tLicenseState,\n\tmarkAsDeleted,\n\torganizationAccessReducer,\n\tOrganizationAccessState,\n\torganizationReducer,\n\tOrganizationState,\n\toutboxReducer,\n\tOutboxState,\n\tprojectAccessReducer,\n\tProjectAccessState,\n\tprojectAttachmentReducer,\n\tProjectAttachmentState,\n\tprojectFileReducer,\n\tProjectFileState,\n\tprojectReducer,\n\tProjectState,\n\trehydratedReducer,\n\tRehydratedState,\n\tselectCategoriesOfWorkspace,\n\tselectMainWorkspace,\n\tteamReducer,\n\tTeamState,\n\tuserReducer,\n\tUserState,\n\tversioningReducer,\n\tVersioningState,\n\tworkspaceReducer,\n\tWorkspaceState,\n} from \"./slices\"\nimport { OUTBOX_RETRY_DELAY } from \"../constants\"\nimport type { BaseState, OvermapRootState } from \"../typings\"\nimport { getClientSDK, getClientStore } from \"../sdk/globals\"\nimport { CLASS_NAME_TO_SERVICE } from \"../sdk/services/BaseService\"\n\n// NOTE: If changing, also change it in migrations.ts (avoid circular imports)\nexport const VERSION_REDUCER_KEY = \"versioning\"\n\nexport const overmapReducers = {\n\t// TODO: attachmentReducer,\n\t[VERSION_REDUCER_KEY]: versioningReducer,\n\tfileReducer,\n\tauthReducer,\n\tcategoryReducer,\n\tassetReducer,\n\tassetAttachmentReducer,\n\tassetStageCompletionReducer,\n\tassetStageReducer,\n\tassetTypeReducer,\n\tassetTypeAttachmentReducer,\n\tissueReducer,\n\tissueAttachmentReducer,\n\tissueTypeReducer,\n\torganizationReducer,\n\toutboxReducer,\n\tprojectReducer,\n\tprojectAttachmentReducer,\n\tprojectAccessReducer,\n\torganizationAccessReducer,\n\tprojectFileReducer,\n\trehydratedReducer,\n\tformReducer,\n\tformRevisionReducer,\n\tformRevisionAttachmentReducer,\n\tformSubmissionAttachmentReducer,\n\tformSubmissionReducer,\n\tuserReducer,\n\tworkspaceReducer,\n\temailDomainsReducer,\n\tlicenseReducer,\n\tdocumentsReducer,\n\tdocumentAttachmentReducer,\n\tteamReducer,\n\tagentsReducer,\n\tissueCommentReducer,\n\tissueUpdateReducer,\n\tgeoImageReducer,\n\tissueAssociationReducer,\n} as {\n\tversioning: Reducer<VersioningState>\n\tfileReducer: Reducer<FileState>\n\tauthReducer: Reducer<AuthState>\n\tcategoryReducer: Reducer<CategoryState>\n\tassetReducer: Reducer<AssetState>\n\tassetAttachmentReducer: Reducer<AssetAttachmentState>\n\tassetStageCompletionReducer: Reducer<AssetStageCompletionState>\n\tassetStageReducer: Reducer<AssetStageState>\n\tassetTypeReducer: Reducer<AssetTypeState>\n\tassetTypeAttachmentReducer: Reducer<AssetTypeAttachmentState>\n\tissueReducer: Reducer<IssueState>\n\tissueTypeReducer: Reducer<IssueTypeState>\n\torganizationReducer: Reducer<OrganizationState>\n\toutboxReducer: Reducer<OutboxState>\n\tprojectReducer: Reducer<ProjectState>\n\tprojectAttachmentReducer: Reducer<ProjectAttachmentState>\n\tprojectAccessReducer: Reducer<ProjectAccessState>\n\torganizationAccessReducer: Reducer<OrganizationAccessState>\n\tprojectFileReducer: Reducer<ProjectFileState>\n\trehydratedReducer: Reducer<RehydratedState>\n\tformReducer: Reducer<FormState>\n\tuserReducer: Reducer<UserState>\n\tformRevisionReducer: Reducer<FormRevisionState>\n\tformRevisionAttachmentReducer: Reducer<FormRevisionAttachmentState>\n\tformSubmissionAttachmentReducer: Reducer<FormSubmissionAttachmentState>\n\tformSubmissionReducer: Reducer<FormSubmissionState>\n\tworkspaceReducer: Reducer<WorkspaceState>\n\temailDomainsReducer: Reducer<EmailDomainState>\n\tlicenseReducer: Reducer<LicenseState>\n\tdocumentsReducer: Reducer<DocumentState>\n\tdocumentAttachmentReducer: Reducer<DocumentAttachmentState>\n\tteamReducer: Reducer<TeamState>\n\tagentsReducer: Reducer<AgentsState>\n\tissueCommentReducer: Reducer<IssueCommentState>\n\tissueUpdateReducer: Reducer<IssueUpdateState>\n\tissueAttachmentReducer: Reducer<IssueAttachmentState>\n\tgeoImageReducer: Reducer<GeoImageSliceState>\n\tissueAssociationReducer: Reducer<IssueAssociationSliceState>\n}\n\nconst overmapReducer = combineReducers(overmapReducers)\n\n// Special action to revert all slices to their initial state. A reducer for this is added to each slice using\n// `extraReducers` in the slice definition.\nexport const resetStore = \"RESET\"\n\nfunction handleWorkspaceRemoval(draft: OvermapRootState, action: AnyAction): void {\n\tconst workspaceId = (action as AnyAction & { payload: string }).payload\n\tconst issuesVisibleInWorkspace = Object.values(draft.issueReducer.instances).filter((issue) =>\n\t\tissue.visible_in_workspaces.includes(workspaceId),\n\t)\n\n\tconst mainWorkspace = selectMainWorkspace(draft)\n\tif (!mainWorkspace) {\n\t\tthrow new Error(\"Main workspace not found\")\n\t}\n\tif (action.payload === mainWorkspace.offline_id) {\n\t\tthrow new Error(\"Tried to delete main workspace\")\n\t}\n\n\t// Find categories about to be deleted. If the issue has this category, we will have to remove it.\n\tconst categoriesInThisWorkspace = new Set<string>(\n\t\t(selectCategoriesOfWorkspace(workspaceId)(draft) ?? []).map((category) => category.offline_id),\n\t)\n\tfor (const issue of issuesVisibleInWorkspace) {\n\t\tif (issue.category && categoriesInThisWorkspace.has(issue.category)) {\n\t\t\tissue.category = null\n\t\t}\n\t}\n\n\t// If the deleted workspace was the index_workspace, we need to update the index_workspace to be the\n\t// main workspace.\n\t// NOTE: Issues are always visible in the index_workspace, so we can expect to find the index_workspace\n\t// in visible_in_workspaces.\n\tconst issuesWithThisWorkspaceIndex = issuesVisibleInWorkspace.filter(\n\t\t(issue) => issue.index_workspace === action.payload,\n\t)\n\n\tfor (const issue of issuesWithThisWorkspaceIndex) {\n\t\t// NOTE: Indexes of WorkspaceIndexedModels are updated after a reload in the workspace service. For now,\n\t\t// we'll just update the index_workspace of indexed models (currently issues and forms).\n\t\tissue.index_workspace = mainWorkspace.offline_id\n\t\tif (!issue.visible_in_workspaces.includes(mainWorkspace.offline_id)) {\n\t\t\tissue.visible_in_workspaces.push(mainWorkspace.offline_id)\n\t\t}\n\t}\n\n\t// Remove the workspace from the visible_in_workspaces of all issues\n\tfor (const issue of issuesVisibleInWorkspace) {\n\t\tconst indexOfWorkspace = issue.visible_in_workspaces.indexOf(workspaceId)\n\t\tif (indexOfWorkspace === -1) {\n\t\t\t// This is unexpected because we already filtered by visible_in_workspaces.\n\t\t\tthrow new Error(\"Workspace not found in issue's visible_in_workspaces\")\n\t\t}\n\t\tissue.visible_in_workspaces.splice(indexOfWorkspace, 1)\n\t}\n\n\t// Lastly, some sanity checks to make sure we didn't miss anything.\n\tfor (const issue of issuesVisibleInWorkspace) {\n\t\tif (issue.visible_in_workspaces.length === 0) {\n\t\t\tthrow new Error(`Unexpected error: Issue ${issue.offline_id} has no visible_in_workspaces`)\n\t\t}\n\t\tif (issue.index_workspace === action.payload || !issue.index_workspace) {\n\t\t\tthrow new Error(`Failed to update index_workspace of issue ${issue.offline_id} to main workspace`)\n\t\t}\n\t}\n}\n\n// NOTE: Leaving this here for now until stories are removed from /core which requires a store to be set up.\n// not being used in /web\nexport const overmapRootReducer: Reducer<OvermapRootState> = (state, action): OvermapRootState => {\n\t// TODO: dont know if this is needed?\n\tif (action.type === \"auth/setLoggedIn\" && !action.payload) {\n\t\treturn overmapReducer(undefined, action) as OvermapRootState\n\t}\n\n\tlet mutatedState = state\n\n\tif (state && action.type === \"workspace/removeWorkspace\") {\n\t\tmutatedState = createNextState(state, (draft) => {\n\t\t\thandleWorkspaceRemoval(draft, action)\n\t\t})\n\t}\n\n\treturn overmapReducer(mutatedState, action) as OvermapRootState\n}\n\nexport interface FullOfflineMetadata extends OfflineMetadata {\n\teffect: OfflineMetaEffect\n}\n\nexport interface FullOfflineAction extends OfflineAction {\n\tmeta: { offline: FullOfflineMetadata }\n\t// Redundantly store request details in the unused `payload` property to make TypeScript happy\n\tpayload: RequestDetails\n}\n\nlet __OUTBOX_COORDINATOR: OutboxCoordinator | null = null\n\nexport function getOutboxCoordinator(): OutboxCoordinator | null {\n\tconst clientStore = getClientStore()\n\tif (!clientStore) {\n\t\tconsole.warn(\"Client store not set; cannot get outbox coordinator yet.\")\n\t\treturn null\n\t}\n\tif (__OUTBOX_COORDINATOR) {\n\t\treturn __OUTBOX_COORDINATOR\n\t}\n\tconst outbox = clientStore.getState().offline.outbox\n\tconst coordinator = OutboxCoordinator._fromOutbox(outbox)\n\t__OUTBOX_COORDINATOR = coordinator\n\treturn coordinator\n}\n\n// This callback is run when the Redux store has finished rehydrating itself from localForage\n// We signal to the rest of the app that hydration has finished\nconst persistCallback = (err: null | Error) => {\n\tif (err) throw err\n\tconst clientStore = getClientStore()\n\tif (clientStore) {\n\t\tclientStore.dispatch({ type: \"rehydrated/setRehydrated\", payload: true })\n\t} else {\n\t\tconsole.error(\"Client store not set\")\n\t}\n}\n\nexport const enqueue: Config[\"queue\"][\"enqueue\"] = (_array, item, _context) => {\n\tconst coordinator = getOutboxCoordinator()\n\tif (!coordinator) {\n\t\tconsole.warn(\"Outbox coordinator not set; cannot enqueue request yet.\")\n\t\treturn []\n\t}\n\tcoordinator.addRequest(item as FullOfflineAction)\n\treturn coordinator.getQueue()\n}\n\nexport const dequeue: Config[\"queue\"][\"dequeue\"] = (_array, item, _context) => {\n\tconst coordinator = getOutboxCoordinator()\n\tif (!coordinator) {\n\t\tconsole.warn(\"Outbox coordinator not set; cannot dequeue request yet.\")\n\t\treturn []\n\t}\n\t// The redux-offline type leaves out the \"offlineAction\" property\n\ttype BadMetaType = ResultAction[\"meta\"]\n\ttype CorrectedMetaType = BadMetaType & { offlineAction: FullOfflineAction }\n\tconst meta = item.meta as CorrectedMetaType\n\tconst uuid = meta.offlineAction.payload.uuid\n\tcoordinator.remove(uuid)\n\treturn coordinator.getQueue()\n}\n\n// This is called an \"effect reconciler\", and it turns an offline action into a real API request\nasync function effect(_effect: OfflineMetaEffect, action: FullOfflineAction) {\n\t// REASON: Handling of unexpected case\n\t// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n\tif (!action.payload) {\n\t\tthrow new Error(\"Received empty payload\")\n\t}\n\n\t// We pass the action through a chain of middleware, which can do some useful things and then perform the action.\n\t// `runMiddleware` returns a Promise<Response> if everything goes well.\n\treturn runMiddleware(action)\n}\n\nconst customConfig: Partial<Config> = {\n\t...offlineConfig,\n\teffect: effect as Config[\"effect\"],\n\t// Casting needed because we are saving FullOfflineAction objects, not just OfflineAction objects,\n\t// but redux-offline does not know this.\n\tdiscard: discard as Config[\"discard\"],\n\treturnPromises: true,\n\tpersistCallback,\n\tretry: retry as Config[\"retry\"],\n\t// Modify the configuration of the offline store to use localforage\n\t// which uses IndexedDB by default (persists even on mobile when installed as a PWA, unlike localStorage)\n\tpersistOptions: { storage: localforage },\n\t// TODO: custom enqueue implementation to take care of intelligently cancelling \"create/delete same issue\",\n\t// and custom dequeue for e.g. if user insists on removing a failed a \"create issue\", then remove the \"edit\n\t// that same issue\"\n\tqueue: {\n\t\t...offlineConfig.queue,\n\t\tenqueue,\n\t\tdequeue,\n\t\t// Bad typing, undefined is actually fine, and the action is a FullOfflineAction, not just an OfflineAction.\n\t\tpeek: (...args) => peek(...(args as Parameters<typeof peek>))!,\n\t} satisfies Config[\"queue\"],\n}\n\n// migration to compose into store\nconst migration = createMigration(manifest, VERSION_REDUCER_KEY) as (_: unknown) => unknown\n\n/**\n * Enhancer for the Redux store that adds offline support and needed middleware for overmap.\n * Add to your store's `enhancers` array.\n */\nexport const overmapEnhancer = compose(offline(customConfig), migration)\n\n/**\n * Makes a best-effort attempt to extract a request.Response from an error object.\n * @param error The error object\n */\nfunction extractResponseFromError(error: unknown): request.Response | undefined {\n\tfunction isResponse(response: unknown): response is request.Response {\n\t\t// Just some keys we know are on a request.Response\n\t\tconst knownKeys = [\"ok\", \"redirect\", \"clientError\", \"serverError\", \"error\"]\n\t\treturn typeof response === \"object\" && response !== null && knownKeys.every((key) => key in response)\n\t}\n\n\tif (isResponse(error)) return error\n\tif (typeof error === \"object\" && error !== null) {\n\t\tconst typedError = error as { response?: { response?: request.Response } }\n\t\tif (isResponse(typedError.response)) return typedError.response\n\t\tif (typedError.response && isResponse(typedError.response.response)) return typedError.response.response\n\t}\n\treturn undefined\n}\n\n// Executes an offline action by making the API request specified in the action's offline metadata\nexport async function performRequest(action: FullOfflineAction, client: BaseSDK<BaseState>): Promise<request.Response> {\n\tconst serviceOfRequest = CLASS_NAME_TO_SERVICE[action.meta.offline.effect.serviceName]\n\n\tif (!serviceOfRequest) {\n\t\tthrow new Error(`Service ${action.meta.offline.effect.serviceName} not found`)\n\t}\n\n\tconst isApiService = serviceOfRequest instanceof BaseApiService\n\n\tconst state = client.store.getState()\n\tif (state.outboxReducer.deletedRequests.includes(action.payload.uuid)) {\n\t\t// The request has been marked for deletion, so we don't want to perform it.\n\t\t// Instead, throw an error, so it will be retried and discarded in the `discard` function.\n\t\tthrow new Error(\"Request was marked for deletion\")\n\t}\n\n\tif (isApiService && action.payload.checkAuth !== false) {\n\t\tawait serviceOfRequest.auth.prepareAuth()\n\t}\n\n\tconst defaultSettings = {\n\t\tqueryParams: \"\",\n\t\tisAuthNeeded: true,\n\t}\n\n\tconst offlineEffect = action.meta.offline.effect\n\tconst { payload, headers, method, queryParams, attachmentHash, isExternalUrl, isAuthNeeded, isResponseBlob } = {\n\t\t...defaultSettings,\n\t\t...offlineEffect.request,\n\t}\n\tconst requestDetails = offlineEffect.request\n\tlet url = requestDetails.url\n\tconst file = attachmentHash ? await client.files.fetchCache(attachmentHash) : undefined\n\n\tif (attachmentHash && !file) {\n\t\tthrow new Error(`Cannot upload file ${attachmentHash} because it's not cached.`)\n\t}\n\n\tif ((!isExternalUrl || import.meta.env.DEV) && !url.startsWith(\"http\")) {\n\t\tif (!url.startsWith(\"/\") && !url.startsWith(\"blob:\")) {\n\t\t\turl = \"/\" + url\n\t\t\tif (import.meta.env.DEV) {\n\t\t\t\tconsole.trace(`You have passed a host-relative URL: ${url}`)\n\t\t\t}\n\t\t}\n\t\turl = action.meta.offline.effect.BASE_URL + url\n\t}\n\n\tconst addPayload = (req: request.SuperAgentRequest) => {\n\t\tif (attachmentHash) {\n\t\t\tconst s3url = requestDetails.s3url\n\t\t\tif (!s3url) throw new Error(`No S3 URL for file ${attachmentHash}`)\n\t\t\tif (\"warning\" in s3url) throw new Error(`S3 URL warning for file ${attachmentHash}`)\n\t\t\tif (!file) throw new Error(`No file for file ${attachmentHash}`)\n\t\t\tconst s3Sha1Checksum = s3url.fields[\"x-amz-checksum-sha1\"]\n\t\t\tif (!s3Sha1Checksum) throw new Error(`No checksum for file ${attachmentHash}`)\n\t\t\treturn req\n\t\t\t\t.set(\"x-amz-checksum-sha1\", s3Sha1Checksum)\n\t\t\t\t.field({ ...payload, ...s3url.fields })\n\t\t\t\t.attach(\"file\", file as unknown as Blob)\n\t\t}\n\t\treturn req.send(payload)\n\t}\n\n\tconst methodRequestMapping: Record<HttpMethod, () => request.SuperAgentRequest> = {\n\t\t[HttpMethod.GET]: () => {\n\t\t\tif (isResponseBlob) {\n\t\t\t\treturn request.get(url.toString()).responseType(\"blob\")\n\t\t\t}\n\t\t\treturn request.get(url.toString())\n\t\t},\n\t\t[HttpMethod.POST]: () => {\n\t\t\tconst ret = request.post(url.toString())\n\t\t\treturn addPayload(ret)\n\t\t},\n\t\t[HttpMethod.PATCH]: () => {\n\t\t\tconst ret = request.patch(url.toString())\n\t\t\treturn addPayload(ret)\n\t\t},\n\t\t[HttpMethod.PUT]: () => {\n\t\t\tconst ret = request.put(url.toString())\n\t\t\treturn addPayload(ret)\n\t\t},\n\t\t[HttpMethod.DELETE]: () => {\n\t\t\tconst ret = request.delete(url.toString())\n\t\t\treturn addPayload(ret)\n\t\t},\n\t}\n\n\tconst selectedRequest = methodRequestMapping[method]\n\n\tlet requestToSend = selectedRequest()\n\tif (isAuthNeeded && isApiService) {\n\t\tconst authHeader = serviceOfRequest.auth.getAuthHeader()\n\t\trequestToSend = requestToSend.set(\"Authorization\", authHeader)\n\t}\n\tif (headers) {\n\t\trequestToSend = requestToSend.set(headers)\n\t}\n\n\ttry {\n\t\treturn await requestToSend.query(queryParams)\n\t} catch (error) {\n\t\t// Observed error types: Error, request.Response\n\t\t// If it's an Error, it has a `response.response` property that is a request.Response.\n\t\tconst errorResponse = extractResponseFromError(error)\n\t\tconst status: number | undefined = errorResponse?.status\n\n\t\tif (isApiService && status === 401) {\n\t\t\tawait serviceOfRequest.auth.handleUnauthorized(requestToSend, errorResponse!)\n\t\t\treturn requestToSend.query(queryParams)\n\t\t}\n\n\t\t// TODO: Error codes for all APIErrors.\n\t\t// TODO: Constant for all messages.\n\t\tthrow new APIError({ response: errorResponse, innerError: error, discard: discardStatuses.includes(status!) })\n\t}\n}\n\ninterface MiddlewareChainer {\n\tthen: (next: OfflineMiddleware) => MiddlewareChainer\n\tcompile: () => OfflineMiddleware[]\n}\n\nclass MiddlewareChainerPrivate {\n\t_all: OfflineMiddleware[]\n\t_previous?: OfflineMiddleware\n\n\tconstructor(current: OfflineMiddleware) {\n\t\tthis._all = [current]\n\t\tthis._previous = current\n\t\tthis.then = this.then.bind(this)\n\t\tthis.compile = this.compile.bind(this)\n\t}\n\n\tthen(next: OfflineMiddleware): MiddlewareChainer {\n\t\tif (this._previous) this._previous.next = next // \"next\" is now \"current\"\n\t\tthis._all.push(next)\n\t\tthis._previous = next // \"next\" is now \"previous\"\n\n\t\treturn {\n\t\t\t// eslint-disable-next-line @typescript-eslint/unbound-method\n\t\t\tthen: this.then,\n\t\t\t// eslint-disable-next-line @typescript-eslint/unbound-method\n\t\t\tcompile: this.compile,\n\t\t}\n\t}\n\n\tcompile() {\n\t\treturn this._all\n\t}\n}\n\nabstract class OfflineMiddleware {\n\tnext: OfflineMiddleware | null\n\n\tconstructor() {\n\t\tthis.next = null\n\t}\n\n\tthen(next: OfflineMiddleware): MiddlewareChainer {\n\t\treturn new MiddlewareChainerPrivate(this).then(next)\n\t}\n\n\tasync run(action: FullOfflineAction): Promise<request.Response | null> {\n\t\tif (this.next) {\n\t\t\treturn this.next.run(action)\n\t\t} else {\n\t\t\tconsole.debug(\"Middleware finished. Performing request:\", action)\n\n\t\t\tconst clientStore = getClientStore()\n\t\t\tif (!clientStore) throw new Error(\"Client store not set\")\n\n\t\t\tconst clientSDK = getClientSDK()\n\t\t\tif (!clientSDK) throw new Error(\"Client SDK not set\")\n\n\t\t\t// At the end of the middleware chain, we want to perform the action\n\t\t\treturn performRequest(action, clientSDK)\n\t\t}\n\t}\n}\n\nclass OfflineAnalyticsMiddleware extends OfflineMiddleware {\n\tasync run(action: FullOfflineAction): Promise<request.Response | null> {\n\t\t// TODO: Store some statistics on which actions are called and enqueue reports periodically\n\t\treturn super.run(action)\n\t}\n}\n\nclass RateLimitingMiddleware extends OfflineMiddleware {\n\tasync run(action: FullOfflineAction): Promise<request.Response | null> {\n\t\t// TODO: Consider rate limits (enable offline mode programmatically to reduce rate)\n\t\treturn super.run(action)\n\t}\n}\n\nconst allMiddleware = new OfflineAnalyticsMiddleware().then(new RateLimitingMiddleware()).compile()\n\nfunction runMiddleware(action: FullOfflineAction) {\n\treturn allMiddleware[0]?.run(action)\n}\n\n// These status codes are due to a fundamental problem that can never be corrected except by manual intervention.\n// TODO: 400 (Bad Request) should result in the user being given a chance to amend their request to be valid.\nconst discardStatuses = [400, 409, 403, 404, 405, 500]\nconst statusMessages: Record<number, ToastProps | undefined> = {\n\t403: { title: \"Forbidden\", description: \"You are not authorized to perform this action.\", accentColor: \"red\" },\n\t404: { title: \"Not found\", description: \"The requested resource was not found.\", accentColor: \"red\" },\n\t405: {\n\t\ttitle: \"Not supported\",\n\t\tdescription: \"It's not you. It's us. Sorry for the inconvenience.\",\n\t\taccentColor: \"red\",\n\t},\n\t500: {\n\t\ttitle: \"Server error\",\n\t\tdescription:\n\t\t\t\"Our server seems to be experiencing problems at the moment. We have been alerted and will fix the \" +\n\t\t\t\"problem as soon as possible.\",\n\t\taccentColor: \"red\",\n\t},\n}\n\n// Discard function is used by Redux Offline to decide whether to discard an action or not, based on the error\n// that the effect reconciler threw and/or the action\nexport function discard(reason: unknown, action: FullOfflineAction, retries = 0): boolean {\n\t// TODO: If 401, renew auth and return false\n\t// TODO: If 400, set state to rescue mode, allowing the user to fix the request and retry (or discard)\n\n\tconsole.debug(\n\t\t\"Considering discarding request due to error:\",\n\t\treason,\n\t\t`(${typeof reason})`,\n\t\t\"\\nAction:\",\n\t\taction,\n\t\t\"\\nRetries:\",\n\t\tretries,\n\t)\n\n\tif (!(reason instanceof Error)) {\n\t\tconsole.error(\n\t\t\t\"ENCOUNTERED NON-ERROR ERROR:\",\n\t\t\treason,\n\t\t\t\"(throwing immediately, which may lead to unexpected behavior)\",\n\t\t)\n\t\tthrow reason\n\t}\n\n\tconst clientStore = getClientStore()\n\tconst state = clientStore!.getState()\n\tconst deletedRequests = state.outboxReducer.deletedRequests\n\tconst uuid = action.payload.uuid\n\n\t// NOTE: Doesn't really return true, but TypeScript doesn't need to know that.\n\t// Adding a `return true` would be meaningless since we are throwing the passed error.\n\tfunction rollbackAndThrow(): true {\n\t\tclientStore!.dispatch(markAsDeleted(uuid))\n\t\tconst coordinator = getOutboxCoordinator()\n\t\tif (!coordinator) {\n\t\t\tthrow new Error(\"Outbox coordinator not set\")\n\t\t}\n\t\tcoordinator.remove(action.payload.uuid)\n\t\tconst rollbackAction = action.meta.offline.rollback\n\t\tif (rollbackAction) {\n\t\t\tconsole.warn(\"Rolling back request due to SDK error:\", action)\n\t\t\tclientStore!.dispatch(rollbackAction)\n\t\t}\n\t\tthrow reason\n\t}\n\n\tif (reason instanceof APIError && reason.options.discard) {\n\t\tconsole.debug(\"Discarding request due to explicit discard:\", action)\n\t\treturn rollbackAndThrow()\n\t}\n\n\tif (deletedRequests.includes(uuid)) {\n\t\tconsole.debug(\"Discarding request due to deletion:\", action)\n\t\treturn rollbackAndThrow()\n\t}\n\n\tif (reason instanceof APIError) {\n\t\tconst status: number | undefined = reason.status || reason.response?.status\n\t\tif (!status) {\n\t\t\tconsole.warn(\"Error has no status code:\", reason)\n\t\t}\n\t\tif (status !== undefined && discardStatuses.includes(status)) {\n\t\t\tconsole.warn(\"Discarding request due to error:\", reason, \"\\nAction:\", action)\n\t\t\tconst message = statusMessages[status]\n\t\t\tif (message) {\n\t\t\t\tif (unsafeShowToast) {\n\t\t\t\t\tunsafeShowToast(message)\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error(`Could not display toast for status ${status} because there is no toast handle.`)\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst coordinator = getOutboxCoordinator()\n\t\t\tif (!coordinator) {\n\t\t\t\tthrow new Error(\"Outbox coordinator not set\")\n\t\t\t}\n\t\t\tcoordinator.remove(action.payload.uuid)\n\t\t\treason.options.discard = true\n\t\t\trollbackAndThrow()\n\t\t}\n\t}\n\n\tconsole.debug(\"Registering a retry for request:\", action.payload.uuid)\n\t// All failures due to any other reason should be retried indefinitely. It will not block the outbox thanks to\n\t// OutboxCoordinator.\n\tconst coordinator = getOutboxCoordinator()\n\tif (!coordinator) {\n\t\tthrow new Error(\"Outbox coordinator not set\")\n\t}\n\tcoordinator.registerRetry(action.payload.uuid)\n\treturn false\n}\n\n// Peek function is used by Redux Offline to determine the next action of the outbox to execute.\n// We are overriding the default implementation (return array[0]) with our own to support our graph-based outbox.\nfunction peek(\n\t_array: FullOfflineAction[],\n\t_item: unknown,\n\t_context: { offline: OfflineState },\n): OfflineAction | undefined {\n\treturn getOutboxCoordinator()?.peek()\n}\n\n// Retry function is used by Redux Offline to determine how long to retry an action, given number of retries\nfunction retry(_action: FullOfflineAction, _retries: number): number | undefined {\n\t// Always retry, but wait a few seconds after a failed request. We have our own custom discard/retry logic.\n\tgetClientStore()!.dispatch(_setLatestRetryTime(new Date().getTime()))\n\treturn OUTBOX_RETRY_DELAY\n}\n\n// export type AppThunk<ReturnType = void> = ThunkAction<ReturnType, RootState, unknown, Action<string>>\n","// The shape of an object that describes the details of an API request\nimport { FileService } from \"./services\"\nimport { ToolkitStore } from \"@reduxjs/toolkit/dist/configureStore\"\nimport request from \"superagent\"\nimport { v4 as uuidv4 } from \"uuid\"\nimport { OfflineMetaEffect, SDKRequest } from \"./typings\"\nimport { APIError } from \"./errors\"\nimport { DeferredPromise } from \"../utils/async/DeferredPromise\"\nimport { discard, enqueueRequest, FullOfflineAction, performRequest } from \"../store\"\nimport { BaseState } from \"../typings\"\n\n// This is a bundle of the services that our app uses. These can be used in tandem with the types\n// declared above in order to execute requests to the backend (queued or otherwise). To use it,\n// you can declare a \"PlaceholderName-Service.ts\" and have CRUD methods to send to the backend,\n// and call it by using `sdk.PlaceHolderName.CRUD_METHOD`\nexport abstract class BaseSDK<TState extends BaseState> {\n\treadonly store: ToolkitStore<TState>\n\tabstract readonly files: FileService<TState, BaseSDK<TState>>\n\n\tprotected constructor(store: ToolkitStore<TState>) {\n\t\tthis.store = store\n\t}\n\n\tpublic async enqueueRequest<TResult>(\n\t\trequestDetails: SDKRequest,\n\t\thost: string,\n\t\tserviceName: string,\n\t): Promise<TResult> {\n\t\t// enqueueRequest is a wrapper for _enqueueRequest that ensures the result is not an APIError unless\n\t\t// `.catch()` is triggered.\n\t\treturn this._enqueueRequest<TResult>(requestDetails, host, serviceName).then((result) => {\n\t\t\tif (result instanceof APIError) {\n\t\t\t\tthrow result\n\t\t\t}\n\t\t\treturn result\n\t\t})\n\t}\n\n\tprivate _enqueueRequest<TResult>(\n\t\trequestDetails: SDKRequest,\n\t\thost: string,\n\t\tserviceName: string,\n\t): DeferredPromise<TResult | APIError> {\n\t\t// We'll receive a Response object, but we want to return just the body of the response. This means\n\t\t// that we must inject a callback in the middle. We will use two promises:\n\t\tconst promise = new DeferredPromise<TResult | APIError>()\n\n\t\t// We dispatch an action that will eventually result in a request.\n\t\tconst requestDetailsWithBaseUrl = { ...requestDetails, BASE_URL: host, serviceName: serviceName }\n\n\t\tif (requestDetails.immediate) {\n\t\t\tconst requestWithUuid = {\n\t\t\t\t...requestDetailsWithBaseUrl,\n\t\t\t\tuuid: requestDetails.uuid ?? uuidv4(),\n\t\t\t}\n\t\t\t// TODO: Does this result in sending the request multiple times?\n\t\t\t// Should performRequest accept pure requestDetails?\n\t\t\t// (It shouldn't result in dupes because we're not dispatching an action.)\n\t\t\tconst fullOfflineAction: FullOfflineAction = {\n\t\t\t\tpayload: requestWithUuid,\n\t\t\t\ttype: \"\",\n\t\t\t\tmeta: {\n\t\t\t\t\toffline: {\n\t\t\t\t\t\teffect: {\n\t\t\t\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t\t\t\t\trequest: requestWithUuid,\n\t\t\t\t\t\t\tBASE_URL: host,\n\t\t\t\t\t\t\tserviceName: serviceName,\n\t\t\t\t\t\t} satisfies OfflineMetaEffect,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t\tperformRequest(fullOfflineAction, this)\n\t\t\t\t.then((result) => {\n\t\t\t\t\tpromise.resolve(result.body as TResult)\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tdiscard(error, fullOfflineAction)\n\t\t\t\t\tpromise.reject(error)\n\t\t\t\t})\n\t\t} else {\n\t\t\tconst innerPromise: Promise<request.Response> = this.store.dispatch(\n\t\t\t\tenqueueRequest(requestDetailsWithBaseUrl),\n\t\t\t) as unknown as Promise<request.Response>\n\n\t\t\tconst successOrUndefinedHandler = (response: request.Response | undefined) => {\n\t\t\t\tif (response) {\n\t\t\t\t\tpromise.resolve(response.body as TResult)\n\t\t\t\t} else {\n\t\t\t\t\tconst error = new APIError({\n\t\t\t\t\t\tmessage: \"Could not get a response from the server.\",\n\t\t\t\t\t\tresponse: response satisfies undefined,\n\t\t\t\t\t\tdiscard: true,\n\t\t\t\t\t})\n\t\t\t\t\tpromise.reject(error)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Handles errors from the inner promise (which performs the request) and rejects the outer promise, which has\n\t\t\t * been returned to the caller by the time this is triggered. This handler is only expected to be triggered if\n\t\t\t * the request has been discarded from the outbox.\n\t\t\t * @param error The error that caused the request to be discarded. Expected to be an APIError instance.\n\t\t\t */\n\t\t\tconst errorHandler = (error: unknown) => {\n\t\t\t\tif (error instanceof APIError) {\n\t\t\t\t\terror.options.discard = true\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\"Received an unexpected error while processing a request:\",\n\t\t\t\t\t\terror,\n\t\t\t\t\t\t\"\\nConverting error to APIError and discarding.\",\n\t\t\t\t\t)\n\t\t\t\t\terror = new APIError({\n\t\t\t\t\t\tmessage: \"An error occurred while processing the request.\",\n\t\t\t\t\t\tinnerError: error,\n\t\t\t\t\t\tdiscard: true,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tpromise.reject(error)\n\t\t\t}\n\n\t\t\tinnerPromise.then(successOrUndefinedHandler, errorHandler)\n\t\t}\n\n\t\treturn promise\n\t}\n\n\t// NOTE: these are currently expected to be present in the base SDK, not sure if that is desired\n}\n","import { BaseSDK } from \"./base\"\nimport { ToolkitStore } from \"@reduxjs/toolkit/dist/configureStore\"\nimport { BaseState } from \"../typings\"\nimport { setClientSDK, setClientStore } from \"./globals\"\nimport { OvermapSDKConstructor } from \"./typings\"\n\nexport const initSDK = <TState extends BaseState, TSDK extends BaseSDK<TState>>(\n\tstore: ToolkitStore<TState>,\n\tsdk: OvermapSDKConstructor<TState, TSDK>,\n) => {\n\tconst sdkInstance = new sdk(store)\n\tsetClientSDK(sdkInstance)\n\tsetClientStore(store)\n\n\treturn sdkInstance\n}\n","import { Response, SuperAgentRequest } from \"superagent\"\nimport { BaseState } from \"../../typings\"\nimport type { BaseSDK } from \"../base\"\nimport { BaseService } from \"./BaseService\"\n\nexport abstract class BaseAuthService<TStore extends BaseState, TSDK extends BaseSDK<TStore>> extends BaseService<\n\tTStore,\n\tTSDK\n> {\n\tprotected constructor(sdk: TSDK) {\n\t\tsuper(sdk)\n\t}\n\n\tabstract initAuth(payload: object): Promise<void>\n\n\tabstract clearAuth(): void\n\n\tabstract prepareAuth(): Promise<void>\n\n\tabstract getAuthHeader(): string\n\n\tabstract handleUnauthorized(request: SuperAgentRequest, response: Response): Promise<void>\n}\n","import { markForDeletion, resetStore, setLoggedIn } from \"../../store\"\nimport { RESET_STATE } from \"@redux-offline/redux-offline/lib/constants\"\nimport request from \"superagent\"\nimport jwtDecode, { JwtPayload } from \"jwt-decode\"\nimport { BaseState } from \"../../typings\"\nimport { HttpMethod } from \"../../enums\"\nimport { v4 as uuidv4 } from \"uuid\"\nimport { APIError } from \"../errors\"\nimport type { BaseSDK } from \"../base\"\nimport { TokenPair } from \"../typings\"\nimport { BaseAuthService } from \"./BaseAuthService\"\n\n// Number of seconds until expiry that we consider as \"expiring soon\"\nconst EXPIRING_SOON_THRESHOLD = 1800\n\n// TODO: Rename `accessToken` and `refreshToken` to `access` and `refresh` respectively, then remove this function and\n// just return the response directly.\nfunction parseTokens(response: { access: string; refresh: string }): TokenPair {\n\tif (!response.access) throw new Error(\"Missing access token\")\n\tif (!response.refresh) throw new Error(\"Missing refresh token\")\n\treturn { accessToken: response.access, refreshToken: response.refresh }\n}\n\n/**\n * Handles login, logout and renewing tokens\n */\nexport abstract class JWTService<TState extends BaseState, TSDK extends BaseSDK<TState>> extends BaseAuthService<\n\tTState,\n\tTSDK\n> {\n\t// AUTH below\n\tprotected abstract initTokensUrl: string\n\tprotected abstract refreshTokensUrl: string\n\tprotected abstract setTokens: (tokens: TokenPair) => void\n\tprotected abstract clearTokens: () => void\n\tprotected abstract getAccessToken: () => string\n\tprotected abstract getRefreshToken: () => string\n\n\t// _getTokenPair and _getRenewedTokens don't need to use enqueueRequest from the BaseApiService because\n\t// they are very simple. However, if we need robust error handling or want these operations to queue in the Outbox,\n\t// we will use enqueueRequest.\n\n\t/**\n\t * Takes refresh token and gets a new token pair\n\t * @async\n\t * @param {string} refreshToken The refresh token used to get new tokens\n\t * @returns {Promise<TokenPair>} The new access and refresh tokens\n\t */\n\tprivate _getRenewedTokens = async (refreshToken: string): Promise<TokenPair | undefined> => {\n\t\tinterface MaybeTokenPair {\n\t\t\taccess?: string\n\t\t\trefresh?: string\n\t\t}\n\n\t\tconst promise = this.enqueueRequest<MaybeTokenPair>({\n\t\t\tdescription: \"Get renewed tokens\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: this.refreshTokensUrl,\n\t\t\tpayload: { refresh: refreshToken },\n\t\t\tisAuthNeeded: false,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t\t// Don't wait for an auth check since this is a refresh token request.\n\t\t\tcheckAuth: false,\n\t\t\t// Don't wait for other requests to finish, or we might end up in a deadlock.\n\t\t\timmediate: true,\n\t\t})\n\n\t\tlet response: MaybeTokenPair | undefined = undefined\n\t\ttry {\n\t\t\tresponse = await promise\n\t\t} catch (e) {\n\t\t\t// TODO: See TODOs in `renewTokens`\n\t\t\t// Log out if the request fails\n\t\t\tconsole.error(\"Could not renew tokens; clearing auth\", e)\n\t\t\tthis.clearAuth()\n\t\t\treturn undefined\n\t\t}\n\n\t\tif (!response.access) throw new Error(\"Missing access token\")\n\n\t\treturn { accessToken: response.access, refreshToken: response.refresh ?? this.getRefreshToken() }\n\t}\n\n\t/**\n\t * Logs the user out\n\t */\n\tclearAuth() {\n\t\t// This also sends an action to the store.ts rootReducer function, allowing\n\t\t// the store to be reset upon sending an undefined state to the other\n\t\t// reducers.\n\t\tconsole.debug(this.constructor.name, \"clearing auth;\")\n\n\t\tthis.dispatch(setLoggedIn(false))\n\t\tthis.clearTokens()\n\t\t// Clear the outbox\n\t\tthis.dispatch({ type: RESET_STATE })\n\t\t// TODO: Consider using only one of the two approaches\n\t\t// For good measure:\n\t\tthis.dispatch({ type: resetStore })\n\t}\n\n\t/**\n\t * Attempts to renew tokens\n\t */\n\tasync renewTokens() {\n\t\tconst dyingRefreshToken = this.getRefreshToken()\n\t\tif (!dyingRefreshToken) {\n\t\t\tthrow new Error(\"No refresh token found\")\n\t\t}\n\n\t\tconsole.debug(this.constructor.name, \"renewing tokens\")\n\n\t\ttry {\n\t\t\tconst tokens = await this._getRenewedTokens(dyingRefreshToken)\n\t\t\tif (!tokens) {\n\t\t\t\treturn undefined\n\t\t\t}\n\t\t\tconsole.log(\"Got renewed tokens\")\n\t\t\tthis.setTokens(tokens)\n\t\t} catch (e) {\n\t\t\t// TODO: Why is this not being triggered when the request fails inside _getRenewedTokens?\n\t\t\t// TODO: This is temporary behaviour, replace it with login button on outbox failed requests\n\t\t\t// that failed because of a 401 Unauthorized\n\t\t\tconsole.error(\"Could not renew tokens; clearing auth\", e)\n\t\t\tthis.clearAuth()\n\t\t\tthrow e\n\t\t}\n\t}\n\n\ttokenIsExpiringSoon(): boolean {\n\t\tconst accessToken = this.getAccessToken()\n\t\tif (!accessToken) {\n\t\t\t// If the access token doesn't exist, it's not expiring.\n\t\t\treturn false\n\t\t}\n\t\t// Convert the current date from milliseconds to seconds (divide by 1000)\n\t\tconst currentDate = Date.now() / 1000\n\t\t// Find the expiration date of access token (in seconds)\n\t\tlet expiryDate: number\n\t\t// jwtDecode may throw an error if the access token is an empty string (logged out)\n\t\ttry {\n\t\t\t// REASON: Bad types\n\t\t\t// eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error,@typescript-eslint/ban-ts-comment\n\t\t\t// @ts-ignore\n\n\t\t\texpiryDate = jwtDecode<JwtPayload>(accessToken).exp ?? currentDate\n\t\t} catch {\n\t\t\t// Enforce expiration if unable to decode token\n\t\t\texpiryDate = currentDate\n\t\t}\n\t\tconst secondsUntilExpiry = expiryDate - currentDate\n\t\treturn secondsUntilExpiry < EXPIRING_SOON_THRESHOLD\n\t}\n\n\tpublic getAuthHeader() {\n\t\tconst accessToken = this.getAccessToken()\n\t\treturn `Bearer ${accessToken}`\n\t}\n\n\tpublic async prepareAuth() {\n\t\tif (!this.tokenIsExpiringSoon()) return\n\n\t\tconsole.debug(this.constructor.name, \"preparing auth\")\n\t\ttry {\n\t\t\tawait this.renewTokens()\n\t\t} catch (e) {\n\t\t\tif (e instanceof APIError) {\n\t\t\t\t// Renewing tokens has failed; we should sign out the user.\n\t\t\t\tthis.clearAuth()\n\t\t\t}\n\t\t\treturn Promise.reject(e)\n\t\t}\n\t}\n\n\t/* if not successfull in gracefully handling an unauthorized response, throw and APIError */\n\tpublic async handleUnauthorized(request: request.SuperAgentRequest, response: request.Response) {\n\t\tconst state = this.client.store.getState()\n\t\t// Without this check, we end up in a loop:\n\t\t// client.auth.renewTokens() -> enqueue -> performRequest -> status === 401 -> client.auth.renewTokens()\n\t\t// See [1] below\n\t\tif (request.url.endsWith(\"/token/refresh/\")) {\n\t\t\t// If the refresh token has expired, we can't do anything.\n\t\t\tif (state.authReducer.isLoggedIn) {\n\t\t\t\t// This is only expected when signing in for the first time with invalid credentials.\n\t\t\t\tconsole.warn(\"No signed-in user to sign out.\")\n\t\t\t}\n\t\t\tthis.clearAuth()\n\t\t\tthrow new APIError({\n\t\t\t\tmessage: \"You have been signed out due to inactivity.\",\n\t\t\t\tresponse: response,\n\t\t\t\tdiscard: true,\n\t\t\t})\n\t\t}\n\t\tif (state.authReducer.isLoggedIn) {\n\t\t\tawait this.renewTokens()\n\t\t} else {\n\t\t\t// If the user is not logged in, we can't renew tokens.\n\t\t\t// Assume this is a login attempt with invalid credentials.\n\t\t\tconsole.debug(\"Forbidden; user is not logged in.\")\n\t\t\tthrow new APIError({\n\t\t\t\tmessage: \"Incorrect username or password.\",\n\t\t\t\tresponse: response,\n\t\t\t\tdiscard: true,\n\t\t\t})\n\t\t}\n\t}\n\n\tasync initAuth(payload: object): Promise<undefined> {\n\t\t// false: Don't log out on failure because we're not currently logged in. Instead, throw and show an error.\n\t\tconst uuid = uuidv4()\n\n\t\tconsole.debug(this.constructor.name, \"Initiating auth\")\n\t\tconst promise = this.enqueueRequest<{ access: string; refresh: string }>({\n\t\t\tuuid,\n\t\t\tdescription: \"Get token pair\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: this.initTokensUrl,\n\t\t\tpayload: payload,\n\t\t\tisAuthNeeded: false,\n\t\t\tcheckAuth: false,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t}).then(parseTokens)\n\n\t\t// The goal: Cancel the request if it takes too long\n\t\tconst timeout = 5 // seconds\n\t\tlet timedOut = false\n\n\t\tconst timeoutPromise = new Promise<undefined>((_, reject) => {\n\t\t\tsetTimeout(() => {\n\t\t\t\ttimedOut = true\n\t\t\t\tthis.dispatch(markForDeletion(uuid))\n\t\t\t\treject(new APIError({ message: `Request timed out after ${timeout} seconds` }))\n\t\t\t}, timeout * 1000)\n\t\t})\n\n\t\tconst successPromise: Promise<undefined> = promise.then((tokens) => {\n\t\t\tif (timedOut) {\n\t\t\t\treturn undefined\n\t\t\t}\n\t\t\tthis.setTokens(tokens)\n\t\t})\n\n\t\treturn Promise.race([timeoutPromise, successPromise])\n\t}\n}\n","import type { BaseSDK } from \"../base\"\nimport { BaseState } from \"../../typings\"\nimport { BaseAuthService } from \"./BaseAuthService\"\nimport { BaseService } from \"./BaseService\"\n\n/**\n * Abstract base class for building a service that can enqueue API requests\n */\nexport abstract class BaseApiService<TStore extends BaseState, TSDK extends BaseSDK<TStore>> extends BaseService<\n\tTStore,\n\tTSDK\n> {\n\treadonly auth: BaseAuthService<TStore, TSDK>\n\n\tconstructor(sdk: TSDK, auth: BaseAuthService<TStore, TSDK>) {\n\t\tsuper(sdk)\n\t\tthis.auth = auth\n\t}\n}\n","import { Category, Created, Offline, OvermapRootState, Payload, Stored } from \"../../typings\"\nimport { OptimisticModelResult } from \"../typings\"\nimport { offline } from \"../../utils\"\nimport { HttpMethod } from \"../../enums\"\nimport { addCategory, updateCategory, deleteCategory, initializeCategories, selectCategoryById } from \"../../store\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\n/**\n * Handles the creation of Category Service\n * TODO: Support editing and deleting categories\n */\nexport abstract class CategoryService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tadd(category: Omit<Payload<Category>, \"workspace\">, workspaceId: string): OptimisticModelResult<Category> {\n\t\tconst offlineCategory = offline(category)\n\t\tconst categoryWithWorkspace = { ...offlineCategory, workspace: workspaceId }\n\t\tthis.dispatch(addCategory(categoryWithWorkspace))\n\n\t\tconst promise = this.enqueueRequest<Category>({\n\t\t\tdescription: \"Create Category\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: \"/categories/\",\n\t\t\tqueryParams: {\n\t\t\t\tworkspace_id: workspaceId.toString(),\n\t\t\t},\n\t\t\tpayload: offlineCategory,\n\t\t\tblockers: [],\n\t\t\tblocks: [offlineCategory.offline_id],\n\t\t})\n\t\treturn [categoryWithWorkspace, promise]\n\t}\n\n\tupdate(category: Offline<Partial<Category>>, workspaceId: string): OptimisticModelResult<Category> {\n\t\tconst state = this.client.store.getState()\n\t\tconst existingCategory = selectCategoryById(category.offline_id)(state)\n\n\t\tif (!existingCategory) {\n\t\t\tthrow new Error(`Expected an existing category with offline_id ${category.offline_id}`)\n\t\t}\n\n\t\tconst optimisticCategory: Stored<Category> = { ...existingCategory, ...category }\n\t\tthis.dispatch(updateCategory(optimisticCategory))\n\n\t\tconst promise = this.enqueueRequest<Created<Category>>({\n\t\t\tdescription: \"Edit Category\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/categories/${category.offline_id}/`,\n\t\t\tqueryParams: {\n\t\t\t\tworkspace_id: workspaceId.toString(),\n\t\t\t},\n\t\t\tpayload: category,\n\t\t\tblockers: [category.offline_id],\n\t\t\tblocks: [category.offline_id],\n\t\t})\n\n\t\treturn [optimisticCategory, promise]\n\t}\n\n\tremove(category: Category, workspaceId: string): Promise<undefined> {\n\t\tthis.dispatch(deleteCategory(category.offline_id))\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Delete Category\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/categories/${category.offline_id}/`,\n\t\t\t// TODO: Shouldn't be necessary to specify workspace_id here\n\t\t\tqueryParams: {\n\t\t\t\tworkspace_id: workspaceId.toString(),\n\t\t\t},\n\t\t\tblockers: [category.offline_id],\n\t\t\tblocks: [],\n\t\t})\n\t}\n\n\tasync refreshStore(projectId: number): Promise<undefined> {\n\t\tconst result = await this.enqueueRequest<Category[]>({\n\t\t\tdescription: \"Get categories\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/categories/`,\n\t\t\tblocks: [],\n\t\t\tblockers: [],\n\t\t})\n\t\tthis.dispatch(initializeCategories(result))\n\t}\n}\n","export function chunkArray<T>(arr: T[], chunkSize: number) {\n\tconst chunks: T[][] = []\n\tlet index = 0\n\tconst arrLength = arr.length\n\n\twhile (index < arrLength) {\n\t\tchunks.push(arr.slice(index, (index += chunkSize)))\n\t}\n\n\treturn chunks\n}\n","import { v4 as uuidv4 } from \"uuid\"\nimport { Asset, Created, Payload, OvermapRootState, Submitted } from \"../../typings\"\nimport { OptimisticModelResult } from \"../typings\"\nimport { offline } from \"../../utils\"\nimport { HttpMethod } from \"../../enums\"\nimport {\n\taddAsset,\n\taddAssets,\n\taddAssetAttachments,\n\tdeleteAsset,\n\tselectAttachmentsOfAsset,\n\tselectAssetById,\n\tselectAssetsOfAssetType,\n\tupdateAsset,\n\tdeleteAssets,\n\tinitializeAssets,\n\tdeleteAssetAttachments,\n\tselectFormSubmissionsOfAsset,\n\tdeleteFormSubmissions,\n\taddFormSubmissions,\n\tselectIssueAssociationsOfAsset,\n\tdeleteIssueAssociations,\n\taddIssueAssociations,\n} from \"../../store\"\nimport { chunkArray } from \"../../utils/array\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class AssetService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\t// Basic CRUD functions\n\tadd(asset: Payload<Asset>, workspaceId: string): OptimisticModelResult<Asset> {\n\t\tif (!asset.canvas_marker && !asset.geo_marker) {\n\t\t\tthrow new Error(\"Asset must have either a canvas_marker or geo_marker\")\n\t\t}\n\n\t\tconst offlineAsset = offline(asset)\n\t\tthis.dispatch(addAsset(offlineAsset))\n\t\tconst promise = this.enqueueRequest<Asset>({\n\t\t\tdescription: \"Create asset\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/assets/types/${offlineAsset.asset_type}/add-assets/`,\n\t\t\tqueryParams: {\n\t\t\t\tworkspace_id: workspaceId.toString(),\n\t\t\t},\n\t\t\tpayload: { assets: [offlineAsset] },\n\t\t\tblockers: [],\n\t\t\tblocks: [offlineAsset.offline_id],\n\t\t})\n\t\treturn [offlineAsset, promise]\n\t}\n\n\tupdate(asset: Asset, workspaceId: string): OptimisticModelResult<Asset> {\n\t\tif (!asset.canvas_marker && !asset.geo_marker) {\n\t\t\tthrow new Error(\"Asset must have either a canvas_marker or geo_marker\")\n\t\t}\n\n\t\tthis.client.store.dispatch(updateAsset(asset))\n\t\tconst promise = this.enqueueRequest<Asset>({\n\t\t\tdescription: \"Edit asset\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/assets/${asset.offline_id}/`,\n\t\t\tqueryParams: {\n\t\t\t\tworkspace_id: workspaceId.toString(),\n\t\t\t},\n\t\t\tpayload: asset,\n\t\t\tblockers: [asset.offline_id],\n\t\t\tblocks: [asset.offline_id],\n\t\t})\n\t\treturn [asset, promise]\n\t}\n\tasync remove(assetId: string): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\t\tconst assetToBeDeleted = selectAssetById(assetId)(state)\n\n\t\tif (!assetToBeDeleted) throw new Error(`No asset with id ${assetId} found in the store`)\n\n\t\tconst attachmentsOfAssets = selectAttachmentsOfAsset(assetId)(state)\n\t\tconst formSubmissionsOfAssets = selectFormSubmissionsOfAsset(assetId)(state)\n\t\tconst issueAssociations = selectIssueAssociationsOfAsset(assetId)(state)\n\n\t\tthis.dispatch(deleteAsset(assetId))\n\n\t\t// remove any attachments of asset from the store\n\t\tif (attachmentsOfAssets.length > 0) {\n\t\t\tconst attachmentsOfAssetIds = attachmentsOfAssets.map(({ offline_id }) => offline_id)\n\t\t\tthis.dispatch(deleteAssetAttachments(attachmentsOfAssetIds))\n\t\t}\n\n\t\t// remove any form submissions of asset from the store\n\t\tif (formSubmissionsOfAssets.length > 0) {\n\t\t\tconst formSubmissionsOfAssetIds = formSubmissionsOfAssets.map(({ offline_id }) => offline_id)\n\t\t\tthis.dispatch(deleteFormSubmissions(formSubmissionsOfAssetIds))\n\t\t}\n\n\t\tif (issueAssociations.length > 0) {\n\t\t\tconst issueAssociationsIds = issueAssociations.map(({ offline_id }) => offline_id)\n\t\t\tthis.dispatch(deleteIssueAssociations(issueAssociationsIds))\n\t\t}\n\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Delete asset\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/assets/${assetId}/`,\n\t\t\tblockers: [assetId],\n\t\t\tblocks: [],\n\t\t}).catch((err) => {\n\t\t\tthis.dispatch(addAsset(assetToBeDeleted))\n\t\t\tthis.dispatch(addAssetAttachments(attachmentsOfAssets))\n\t\t\tthis.dispatch(addFormSubmissions(formSubmissionsOfAssets))\n\t\t\tthis.dispatch(addIssueAssociations(issueAssociations))\n\t\t\tthrow err\n\t\t})\n\t}\n\tasync deleteAllAssetsOfAssetType(assetTypeId: string): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst state: OvermapRootState = store.getState()\n\n\t\tconst allAssetsOfAssetType = selectAssetsOfAssetType(assetTypeId)(state) ?? []\n\t\tconst allAssetsOfAssetTypeIds = allAssetsOfAssetType.map((c) => c.offline_id)\n\t\tconst affectedOfflineIds = [assetTypeId, ...allAssetsOfAssetTypeIds]\n\n\t\tstore.dispatch(deleteAssets(allAssetsOfAssetTypeIds))\n\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Delete all assets of asset type\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/assets/types/${assetTypeId}/delete-all-of-type/`,\n\t\t\tblockers: affectedOfflineIds,\n\t\t\tblocks: affectedOfflineIds,\n\t\t}).catch((err) => {\n\t\t\t// If the request fails, we need to add the assets back to the store\n\t\t\tstore.dispatch(addAssets(allAssetsOfAssetType))\n\t\t\tthrow err\n\t\t})\n\t}\n\n\t// TODO: payload does not require asset_type\n\tbulkAdd(\n\t\tassetsToCreate: Payload<Asset>[],\n\t\tworkspaceId: string,\n\t\tassetTypeId: string,\n\t\t// TODO: should we validate this?\n\t\tbatchSize: number,\n\t): Promise<Created<Asset>[]>[] {\n\t\tconst { store } = this.client\n\n\t\tinterface BulkAddAssetPayload {\n\t\t\ttransaction_id: string\n\t\t\tassets: Submitted<Asset>[]\n\t\t\t// TODO: uncommnent when endpoint is refactored\n\t\t\t// submitted_at: string\n\t\t}\n\n\t\tinterface BulkAddAssetBatch {\n\t\t\tbatchId: string\n\t\t\tpayload: BulkAddAssetPayload\n\t\t}\n\n\t\tconst submittedAt = new Date().toISOString()\n\t\tconst transactionId = uuidv4()\n\n\t\tconst assetBatches: BulkAddAssetBatch[] = chunkArray(assetsToCreate, batchSize).map((assetBatch) => {\n\t\t\tconst assetPayloads: Submitted<Asset>[] = assetBatch.map((assetPayload) => {\n\t\t\t\treturn offline({\n\t\t\t\t\t...assetPayload,\n\t\t\t\t\tsubmitted_at: submittedAt,\n\t\t\t\t})\n\t\t\t})\n\n\t\t\treturn {\n\t\t\t\tbatchId: uuidv4(),\n\t\t\t\tpayload: {\n\t\t\t\t\ttransaction_id: transactionId,\n\t\t\t\t\tassets: assetPayloads,\n\t\t\t\t},\n\t\t\t}\n\t\t})\n\n\t\tconst batchPromises: Promise<Created<Asset>[]>[] = []\n\t\tlet prevBatchId: string | null = null\n\n\t\tfor (const assetBatch of assetBatches) {\n\t\t\tconst { batchId, payload } = assetBatch\n\n\t\t\tconst batchAssetOfflineIds = payload.assets.map((c) => c.offline_id)\n\n\t\t\tconst blockers = [assetTypeId]\n\t\t\tif (prevBatchId) blockers.push(prevBatchId)\n\n\t\t\tconst blocks = batchAssetOfflineIds\n\t\t\tblocks.push(batchId)\n\n\t\t\tconst promise = this.enqueueRequest<Created<Asset>[]>({\n\t\t\t\tdescription: \"Batch create assets\",\n\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\turl: `/assets/types/${assetTypeId}/add-assets/`,\n\t\t\t\tqueryParams: {\n\t\t\t\t\tworkspace_id: workspaceId.toString(),\n\t\t\t\t},\n\t\t\t\tpayload: payload,\n\t\t\t\tblockers: blockers,\n\t\t\t\tblocks: blocks,\n\t\t\t})\n\n\t\t\tprevBatchId = assetBatch.batchId\n\n\t\t\tbatchPromises.push(promise)\n\t\t}\n\n\t\tvoid Promise.all(batchPromises).then((result) => {\n\t\t\tconst allCreatedAssets = result.flat()\n\t\t\tstore.dispatch(addAssets(allCreatedAssets))\n\t\t})\n\n\t\treturn batchPromises\n\t}\n\n\tasync refreshStore(projectId: number): Promise<void> {\n\t\tconst result = await this.enqueueRequest<Asset[]>({\n\t\t\tdescription: \"Get assets\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/assets/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t\tthis.dispatch(initializeAssets(result))\n\t}\n}\n","import { addStageCompletion, addStageCompletions, removeStageCompletions, selectAssetById } from \"../../store\"\nimport { OptimisticModelResult } from \"../typings\"\nimport { offline } from \"../../utils\"\nimport { HttpMethod } from \"../../enums\"\nimport { AssetStageCompletion, CompletedStagesMapping, Created, OvermapRootState, Payload } from \"../../typings\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class AssetStageCompletionService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tadd(assetId: string, stageId: string): OptimisticModelResult<AssetStageCompletion> {\n\t\tconst { store } = this.client\n\t\tconst assetTypeId = selectAssetById(assetId)(store.getState())?.asset_type\n\n\t\tif (!assetTypeId) {\n\t\t\tthrow new Error(`Asset with offline_id ${assetId} not found`)\n\t\t}\n\n\t\tconst offlineStageCompletion = offline({\n\t\t\tasset: assetId,\n\t\t\tstage: stageId,\n\t\t})\n\n\t\tthis.dispatch(addStageCompletion(offlineStageCompletion))\n\n\t\tconst promise = this.enqueueRequest<Created<AssetStageCompletion>>({\n\t\t\tdescription: \"Complete stage\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/assets/types/${assetTypeId}/complete-stages/`,\n\t\t\t// TODO: Add submitted_at to model\n\t\t\tpayload: { completions: [{ ...offlineStageCompletion, submitted_at: new Date().getTime() / 1000 }] },\n\t\t\tblockers: [assetId, stageId],\n\t\t\tblocks: [offlineStageCompletion.offline_id],\n\t\t})\n\n\t\treturn [offlineStageCompletion, promise]\n\t}\n\tasync refreshStore(projectId: number): Promise<void> {\n\t\tconst result = await this.enqueueRequest<CompletedStagesMapping>({\n\t\t\tdescription: \"Get stage completions\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/asset-stage-completions/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t\tthis.dispatch(addStageCompletions(result))\n\t}\n\n\t/**\n\t * Creates a collection of AssetStageCompletions, marking the referenced stages as completed for the referenced\n\t * assets. It's REQUIRED that all assets referenced all have the SAME asset type.\n\t * @param assetTypeId The ID of the asset type for which we are completing stages (we can only complete\n\t * stages for one asset type at a time)\n\t * @param stageCompletions\n\t */\n\tasync bulkAdd(assetTypeId: string, stageCompletions: Payload<AssetStageCompletion>[]) {\n\t\tconst offlineStageCompletions = stageCompletions.map((completion) => {\n\t\t\treturn offline(completion)\n\t\t})\n\t\tconst asMapping: CompletedStagesMapping = {}\n\t\tfor (const completion of stageCompletions) {\n\t\t\tconst stageToCompletionDateMapping = asMapping[completion.asset] || {}\n\t\t\tstageToCompletionDateMapping[completion.stage] = new Date().toISOString()\n\t\t\tasMapping[completion.asset] = stageToCompletionDateMapping\n\t\t}\n\t\tthis.dispatch(addStageCompletions(asMapping))\n\t\tawait this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Bulk complete stages\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/assets/types/${assetTypeId}/complete-stages/`,\n\t\t\tpayload: {\n\t\t\t\tcompletions: offlineStageCompletions,\n\t\t\t},\n\t\t\tblockers: [assetTypeId, ...stageCompletions.map((c) => c.asset), ...stageCompletions.map((c) => c.stage)],\n\t\t\tblocks: offlineStageCompletions.map((c) => c.offline_id),\n\t\t})\n\t}\n\tbulkDelete(stageId: string, assetIds: string[]): Promise<undefined> {\n\t\tconst stageCompletionsToRemove: AssetStageCompletion[] = assetIds.map((assetId) => {\n\t\t\treturn {\n\t\t\t\tasset: assetId,\n\t\t\t\tstage: stageId,\n\t\t\t}\n\t\t})\n\t\tthis.dispatch(removeStageCompletions(stageCompletionsToRemove))\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: `Undo stage for ${assetIds.length} assets(s)`,\n\t\t\t// TODO: Rename to setCompletedStages\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/assets/stages/${stageId}/undo-stages/`,\n\t\t\tpayload: {\n\t\t\t\tassets: assetIds,\n\t\t\t},\n\t\t\tblockers: [stageId, ...assetIds],\n\t\t\tblocks: [],\n\t\t})\n\t}\n}\n","import { AssetStage, AssetStagePayload, OvermapRootState, Payload } from \"../../typings\"\nimport { offline } from \"../../utils\"\nimport { HttpMethod } from \"../../enums\"\nimport {\n\taddStages,\n\tremoveStages,\n\tselectAssetStagesByIds,\n\tupdateStages,\n\tupdateStage,\n\tsetStage,\n\tinitializeStages,\n} from \"../../store\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class AssetStageService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tasync bulkCreateStages(\n\t\tstagesToSubmit: Payload<AssetStagePayload>[],\n\t\tassetTypeId: string,\n\t\tworkspaceId: string,\n\t): Promise<AssetStage[]> {\n\t\tconst payload: AssetStagePayload[] = stagesToSubmit.map((stage) => {\n\t\t\treturn offline(stage)\n\t\t})\n\t\tconst fullStages: AssetStage[] = payload.map((stage) => {\n\t\t\treturn { ...stage, asset_type: assetTypeId }\n\t\t})\n\t\tthis.dispatch(addStages(fullStages))\n\t\treturn this.enqueueRequest<AssetStage[]>({\n\t\t\tdescription: \"Add asset stages\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/assets/types/${assetTypeId}/add-stages/`,\n\t\t\tpayload: {\n\t\t\t\tstages: payload,\n\t\t\t},\n\t\t\tqueryParams: {\n\t\t\t\tworkspace_id: workspaceId.toString(),\n\t\t\t},\n\t\t\tblockers: [assetTypeId, workspaceId],\n\t\t\tblocks: payload.map(({ offline_id }) => offline_id),\n\t\t})\n\t}\n\n\tasync bulkUpdateStages(stagesToUpdate: AssetStage[], assetTypeId: string): Promise<AssetStage[]> {\n\t\tconst store = this.client.store\n\t\tconst state = store.getState()\n\t\tconst prevStages = selectAssetStagesByIds(stagesToUpdate.map(({ offline_id }) => offline_id))(state)\n\n\t\tthis.dispatch(updateStages(stagesToUpdate))\n\n\t\treturn this.enqueueRequest<AssetStage[]>({\n\t\t\tdescription: \"Edit asset stages\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/assets/types/${assetTypeId}/bulk-update-stages/`,\n\t\t\tpayload: {\n\t\t\t\tstages: stagesToUpdate,\n\t\t\t},\n\t\t\tblockers: [assetTypeId],\n\t\t\tblocks: stagesToUpdate.map(({ offline_id }) => offline_id),\n\t\t}).catch((e) => {\n\t\t\t// restore stages in store if request fails\n\t\t\tstore.dispatch(updateStages(prevStages))\n\t\t\tthrow e\n\t\t})\n\t}\n\n\tasync bulkDelete(idsToDelete: string[]): Promise<undefined> {\n\t\tthis.dispatch(removeStages(idsToDelete))\n\t\treturn this.enqueueRequest({\n\t\t\tdescription: \"Delete asset stages\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: \"/assets/stages/bulk-delete/\",\n\t\t\tpayload: {\n\t\t\t\tstage_ids: idsToDelete,\n\t\t\t},\n\t\t\tblockers: idsToDelete,\n\t\t\tblocks: [],\n\t\t})\n\t}\n\n\tasync update(assetStage: AssetStage): Promise<undefined> {\n\t\tthis.dispatch(addStages([assetStage]))\n\t\treturn this.enqueueRequest({\n\t\t\tdescription: \"Update asset stage\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/assets/stages/${assetStage.offline_id}/`,\n\t\t\tpayload: assetStage,\n\t\t\tblockers: [assetStage.offline_id],\n\t\t\tblocks: [assetStage.offline_id],\n\t\t})\n\t}\n\n\tasync linkForm(stageId: string, formId: string): Promise<undefined> {\n\t\tconst { store } = this.client\n\n\t\tconst stage = store.getState().assetStageReducer.instances[stageId]\n\n\t\tif (!stage) {\n\t\t\tthrow new Error(`No asset stage with id ${stageId} found in the store`)\n\t\t}\n\n\t\tthis.dispatch(updateStage({ ...stage, form: formId }))\n\t\ttry {\n\t\t\tawait this.enqueueRequest({\n\t\t\t\tdescription: \"Link asset stage to form\",\n\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\turl: `/assets/stages/${stageId}/associate-with-form/`,\n\t\t\t\tpayload: { form: formId },\n\t\t\t\tblockers: [stageId, formId],\n\t\t\t\tblocks: [stageId],\n\t\t\t})\n\t\t} catch (e) {\n\t\t\tthis.dispatch(setStage(stage))\n\t\t\tthrow e\n\t\t}\n\t}\n\n\tasync unlinkForm(stageId: string, formId: string): Promise<undefined> {\n\t\tconst { store } = this.client\n\n\t\tconst stage = store.getState().assetStageReducer.instances[stageId]\n\n\t\tif (!stage) {\n\t\t\tthrow new Error(`No asset stage with id ${stageId} found in the store`)\n\t\t}\n\n\t\tthis.dispatch(updateStage({ ...stage, form: undefined }))\n\n\t\ttry {\n\t\t\tawait this.enqueueRequest({\n\t\t\t\tdescription: \"Unlink asset stage from form\",\n\t\t\t\tmethod: HttpMethod.DELETE,\n\t\t\t\turl: `/assets/stages/${stageId}/associate-with-form/`,\n\t\t\t\tblockers: [stageId, formId],\n\t\t\t\tblocks: [stageId],\n\t\t\t})\n\t\t} catch (e) {\n\t\t\tthis.dispatch(setStage(stage))\n\t\t\tthrow e\n\t\t}\n\t}\n\n\tasync refreshStore(projectId: number): Promise<undefined> {\n\t\tconst result = await this.enqueueRequest<AssetStage[]>({\n\t\t\tdescription: \"Get asset stages\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/asset-stages/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t\tthis.dispatch(initializeStages(result))\n\t}\n}\n","import { BaseApiService } from \"./BaseApiService\"\nimport { HttpMethod } from \"../../enums\"\nimport { PresignedUrlsResponse, SDKRequest } from \"../typings\"\nimport { OvermapRootState } from \"../../typings\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class BaseUploadService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tprotected getNumberOfAttachmentsWithSha1(sha1: string) {\n\t\tconst {\n\t\t\tissueAttachmentReducer,\n\t\t\tassetAttachmentReducer,\n\t\t\tassetTypeAttachmentReducer,\n\t\t\tdocumentAttachmentReducer,\n\t\t\tprojectAttachmentReducer,\n\t\t\tformRevisionAttachmentReducer,\n\t\t\tformSubmissionAttachmentReducer,\n\t\t\tgeoImageReducer,\n\t\t} = this.client.store.getState()\n\n\t\t// creating an array of objects with the file_sha1 property\n\t\t// TODO: @Audiopolis, probably makes sense to also include projectFiles in here?\n\t\tconst objectsWithSha1: { file_sha1: string }[] = ([] as { file_sha1: string }[]).concat(\n\t\t\tObject.values(issueAttachmentReducer.instances),\n\t\t\tObject.values(assetAttachmentReducer.instances),\n\t\t\tObject.values(assetTypeAttachmentReducer.instances),\n\t\t\tObject.values(documentAttachmentReducer.instances),\n\t\t\tObject.values(projectAttachmentReducer.instances),\n\t\t\tObject.values(formRevisionAttachmentReducer.instances),\n\t\t\tObject.values(formSubmissionAttachmentReducer.instances),\n\t\t\tObject.values(geoImageReducer.instances),\n\t\t)\n\n\t\treturn objectsWithSha1.filter((object) => object.file_sha1 === sha1).length\n\t}\n\n\tprotected processPresignedUrls(presignedUrls: PresignedUrlsResponse) {\n\t\tfor (const [sha1, presignedUrl] of Object.entries(presignedUrls)) {\n\t\t\tvoid this.enqueueRequest<undefined>({\n\t\t\t\turl: presignedUrl.url,\n\t\t\t\tdescription: \"Upload file to S3\",\n\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\tisExternalUrl: true,\n\t\t\t\tisAuthNeeded: false,\n\t\t\t\tattachmentHash: sha1,\n\t\t\t\t// TODO: can we use the sha1 as the blocker?\n\t\t\t\tblockers: [`s3-${presignedUrl.fields.key}`],\n\t\t\t\tblocks: [sha1],\n\t\t\t\ts3url: presignedUrl,\n\t\t\t} satisfies SDKRequest)\n\t\t}\n\t}\n}\n","import { ActionCreatorWithPayload } from \"@reduxjs/toolkit\"\nimport { OptimisticMultipleModelResult, PresignedUrlsResponse } from \"../typings\"\nimport { HttpMethod } from \"../../enums\"\nimport {\n\tAttachment,\n\tAttachmentModel,\n\tCreated,\n\tOfflineModel,\n\tOvermapRootState,\n\tOvermapSelectorWithArgs,\n\tStored,\n\tSubmitted,\n} from \"../../typings\"\nimport { hashFile } from \"../../utils\"\nimport type { BaseSDK } from \"../base\"\nimport { BaseUploadService } from \"./BaseUploadService\"\n\ninterface AttachmentPayload {\n\toffline_id: OfflineModel[\"offline_id\"]\n\tname: Attachment[\"file_name\"]\n\tsha1: Attachment[\"file_sha1\"]\n\tdescription: Attachment[\"description\"]\n}\n\nexport interface FilePayload {\n\tsha1: Attachment[\"file_sha1\"]\n\tfile_type: string\n\textension: string\n\tsize: number\n}\n\nexport interface BuildOfflineAttachmentData<TModelId> {\n\tfile: File\n\t// passing sha1 here so dont have to hash multiple times\n\tsha1: string\n\tsubmittedAt: string\n\tcreatedBy: number\n\tdescription?: string\n\t// this the offline_id passed in from the attachFiles method\n\tmodelId: TModelId\n}\n\nconst AttachmentModelMeta: Record<\n\tAttachmentModel,\n\t{ attachUrlPrefix: string; deleteUrlPrefix: string; name: string; fetchUrlPostfix: string }\n> = {\n\t[AttachmentModel.Issue]: {\n\t\tname: \"issue\",\n\t\tattachUrlPrefix: \"/issues\",\n\t\tdeleteUrlPrefix: \"/issues\",\n\t\tfetchUrlPostfix: \"/issue-attachments\",\n\t},\n\t[AttachmentModel.Asset]: {\n\t\tname: \"asset\",\n\t\tattachUrlPrefix: \"/assets\",\n\t\tdeleteUrlPrefix: \"/assets\",\n\t\tfetchUrlPostfix: \"/asset-attachments\",\n\t},\n\t[AttachmentModel.AssetType]: {\n\t\tname: \"asset type\",\n\t\tattachUrlPrefix: \"/assets/types\",\n\t\tdeleteUrlPrefix: \"/assets/types\",\n\t\tfetchUrlPostfix: \"/asset-type-attachments\",\n\t},\n\t[AttachmentModel.Project]: {\n\t\tname: \"project\",\n\t\tattachUrlPrefix: \"/projects\",\n\t\tdeleteUrlPrefix: \"/projects\",\n\t\tfetchUrlPostfix: \"/attachments\",\n\t},\n\t[AttachmentModel.Document]: {\n\t\tname: \"document\",\n\t\tattachUrlPrefix: \"/documents\",\n\t\tdeleteUrlPrefix: \"/documents\",\n\t\tfetchUrlPostfix: \"/document-attachments\",\n\t},\n}\n\nexport abstract class BaseAttachmentService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n\tTModelId extends string | number,\n\tTAttachment extends Attachment,\n> extends BaseUploadService<TState, TSDK> {\n\tabstract readonly attachmentModel: AttachmentModel\n\n\t// redux actions\n\tabstract readonly initializeAttachments: ActionCreatorWithPayload<Submitted<TAttachment>[]>\n\tabstract readonly addAttachments: ActionCreatorWithPayload<Submitted<TAttachment>[]>\n\tabstract readonly updateAttachments: ActionCreatorWithPayload<Submitted<TAttachment>[]>\n\tabstract readonly removeAttachments: ActionCreatorWithPayload<string[]>\n\tabstract readonly setAttachment: ActionCreatorWithPayload<Stored<TAttachment>>\n\tabstract readonly removeAttachment: ActionCreatorWithPayload<string>\n\n\t// redux selectors\n\tabstract readonly selectAttachment: OvermapSelectorWithArgs<string, Stored<TAttachment>>\n\n\tprotected async attachFiles(\n\t\tfiles: File[],\n\t\tmodelId: TModelId,\n\t\tbuildOfflineAttachment: (data: BuildOfflineAttachmentData<TModelId>) => Stored<TAttachment>,\n\t): Promise<OptimisticMultipleModelResult<TAttachment>> {\n\t\tconst { store } = this.client\n\n\t\tconst currentUser = store.getState().userReducer.currentUser\n\t\tconst submittedAt = new Date().toISOString()\n\n\t\tconst offlineAttachments: Stored<TAttachment>[] = []\n\t\tconst attachmentPayloads: AttachmentPayload[] = []\n\t\tconst filePayloads: Record<FilePayload[\"sha1\"], FilePayload> = {}\n\n\t\tfor (const file of files) {\n\t\t\t// has file once\n\t\t\tconst sha1 = await hashFile(file)\n\n\t\t\t// if the file is already being uploaded, skip it\n\t\t\tif (!(sha1 in filePayloads)) {\n\t\t\t\tfilePayloads[sha1] = {\n\t\t\t\t\tsha1,\n\t\t\t\t\tfile_type: file.type,\n\t\t\t\t\textension: file.name.split(\".\").pop()!,\n\t\t\t\t\tsize: file.size,\n\t\t\t\t}\n\t\t\t\tawait this.client.files.addCache(file, sha1)\n\t\t\t}\n\n\t\t\t// construct offline attachment\n\t\t\tconst offlineAttachment = buildOfflineAttachment({\n\t\t\t\tfile,\n\t\t\t\tsha1,\n\t\t\t\tsubmittedAt,\n\t\t\t\tcreatedBy: currentUser.id,\n\t\t\t\tdescription: \"\",\n\t\t\t\tmodelId: modelId,\n\t\t\t})\n\t\t\tofflineAttachments.push(offlineAttachment)\n\n\t\t\t// construct attachment payload\n\t\t\tattachmentPayloads.push({\n\t\t\t\toffline_id: offlineAttachment.offline_id,\n\t\t\t\tname: offlineAttachment.file_name,\n\t\t\t\tsha1: offlineAttachment.file_sha1,\n\t\t\t\tdescription: offlineAttachment.description,\n\t\t\t})\n\t\t}\n\n\t\tthis.dispatch(this.addAttachments(offlineAttachments))\n\n\t\tconst meta = AttachmentModelMeta[this.attachmentModel]\n\n\t\tconst promise = this.enqueueRequest<{\n\t\t\tattachments: Created<TAttachment>[]\n\t\t\tpresigned_urls: PresignedUrlsResponse\n\t\t}>({\n\t\t\tdescription: `Attach files to ${meta.name}`,\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `${meta.attachUrlPrefix}/${modelId}/attach/`,\n\t\t\tpayload: {\n\t\t\t\tsubmitted_at: submittedAt,\n\t\t\t\tattachments: attachmentPayloads,\n\t\t\t\tfiles: Object.values(filePayloads),\n\t\t\t},\n\t\t\tblocks: offlineAttachments.map((attachment) => attachment.offline_id),\n\t\t\tblockers: offlineAttachments.map((attachment) => attachment.file_sha1),\n\t\t})\n\n\t\tpromise\n\t\t\t.then(({ attachments, presigned_urls }) => {\n\t\t\t\tthis.dispatch(this.updateAttachments(attachments))\n\t\t\t\tthis.processPresignedUrls(presigned_urls)\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(this.removeAttachments(offlineAttachments.map((attachment) => attachment.offline_id)))\n\t\t\t})\n\n\t\treturn [offlineAttachments, promise.then(({ attachments }) => attachments)]\n\t}\n\n\tprotected async deleteAttachment(attachmendId: string): Promise<void> {\n\t\tconst { store } = this.client\n\t\tconst attachment = this.selectAttachment(attachmendId)(store.getState())\n\n\t\tif (!attachment) {\n\t\t\tthrow new Error(\n\t\t\t\t`Attempting to delete attachment with offline_id ${attachmendId} that does not exist in the store`,\n\t\t\t)\n\t\t}\n\n\t\tthis.dispatch(this.removeAttachment(attachment.offline_id))\n\n\t\tconst meta = AttachmentModelMeta[this.attachmentModel]\n\n\t\tconst promise = this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Delete attachment\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `${meta.deleteUrlPrefix}/attachments/${attachmendId}/`,\n\t\t\tblockers: [attachmendId],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tpromise\n\t\t\t.then(() => {\n\t\t\t\tif (this.getNumberOfAttachmentsWithSha1(attachment.file_sha1) === 0) {\n\t\t\t\t\tvoid this.client.files.removeCache(attachment.file_sha1)\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(this.setAttachment(attachment))\n\t\t\t})\n\n\t\treturn promise\n\t}\n\n\t// Note that currently the fetching of attachments for all models dependds on the active projectId. This may change in the future. And\n\t// so for some attachment model services, this method will have to be overridden.\n\tasync refreshStore(projectId: number, _organizationId?: number): Promise<void> {\n\t\tconst meta = AttachmentModelMeta[this.attachmentModel]\n\n\t\tconst result = await this.enqueueRequest<Created<TAttachment>[]>({\n\t\t\tdescription: `Get ${meta.name} attachments`,\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}${meta.fetchUrlPostfix}/`,\n\t\t\tblocks: [],\n\t\t\tblockers: [],\n\t\t})\n\n\t\tthis.dispatch(this.initializeAttachments(result))\n\t}\n}\n","import { BaseAttachmentService, BuildOfflineAttachmentData } from \"./BaseAttachmentService\"\nimport { AttachmentModel, AssetAttachment, Stored, OvermapRootState } from \"../../typings\"\nimport { offline } from \"../../utils\"\nimport { OptimisticMultipleModelResult } from \"../typings\"\nimport {\n\taddAssetAttachments,\n\tdeleteAssetAttachments,\n\tdeleteAssetAttachment,\n\tselectAssetAttachment,\n\tsetAssetAttachment,\n\tupdateAssetAttachments,\n\tinitializeAssetAttachments,\n} from \"../../store\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class AssetAttachmentService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseAttachmentService<TState, TSDK, string, AssetAttachment> {\n\tattachmentModel = AttachmentModel.Asset\n\n\tinitializeAttachments = initializeAssetAttachments\n\taddAttachments = addAssetAttachments\n\tupdateAttachments = updateAssetAttachments\n\tremoveAttachments = deleteAssetAttachments\n\tremoveAttachment = deleteAssetAttachment\n\tsetAttachment = setAssetAttachment\n\n\tselectAttachment = selectAssetAttachment\n\n\tprivate buildOfflineAttachment(data: BuildOfflineAttachmentData<string>) {\n\t\treturn offline({\n\t\t\tfile: URL.createObjectURL(data.file),\n\t\t\tfile_sha1: data.sha1,\n\t\t\tcreated_by: data.createdBy,\n\t\t\tfile_name: data.file.name,\n\t\t\tfile_type: data.file.type,\n\t\t\tsubmitted_at: data.submittedAt,\n\t\t\tdescription: data.description,\n\t\t\tasset: data.modelId,\n\t\t}) satisfies Stored<AssetAttachment>\n\t}\n\n\tasync attachFilesToAsset(files: File[], assetId: string): Promise<OptimisticMultipleModelResult<AssetAttachment>> {\n\t\treturn this.attachFiles(files, assetId, this.buildOfflineAttachment.bind(this))\n\t}\n\n\tasync deleteAssetAttachment(attachmentId: string): Promise<void> {\n\t\treturn this.deleteAttachment(attachmentId)\n\t}\n}\n","import { offline } from \"../../utils\"\nimport {\n\taddAssetType,\n\taddAssetTypeAttachments,\n\taddStages,\n\tdeleteAssetType,\n\tdeleteAssetTypeAttachments,\n\tinitializeAssetTypes,\n\tremoveStages,\n\tselectAssetTypeById,\n\tselectAttachmentsOfAssetType,\n\tselectStagesOfAssetType,\n} from \"../../store\"\nimport { AssetStage, AssetType, OvermapRootState, Payload } from \"../../typings\"\nimport { HttpMethod } from \"../../enums\"\nimport { OptimisticModelResult } from \"../typings\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class AssetTypeService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tadd(assetType: Payload<AssetType>): OptimisticModelResult<AssetType> {\n\t\tconst offlineAssetType = offline(assetType)\n\t\tconst { store } = this.client\n\t\tconst activeProjectId = store.getState().projectReducer.activeProjectId\n\n\t\tthis.dispatch(addAssetType(offlineAssetType))\n\t\tconst promise = this.enqueueRequest<AssetType>({\n\t\t\tdescription: \"Create asset type\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/projects/${activeProjectId}/asset-types/`,\n\t\t\tpayload: { ...offlineAssetType },\n\t\t\tblockers: [],\n\t\t\tblocks: [offlineAssetType.offline_id],\n\t\t})\n\t\treturn [offlineAssetType, promise]\n\t}\n\n\tupdate(assetType: AssetType): Promise<undefined> {\n\t\tthis.dispatch(addAssetType(assetType))\n\t\treturn this.enqueueRequest({\n\t\t\tdescription: \"Update asset type\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/assets/types/${assetType.offline_id}/`,\n\t\t\tpayload: assetType,\n\t\t\tblockers: [assetType.offline_id],\n\t\t\tblocks: [assetType.offline_id],\n\t\t})\n\t}\n\n\tasync delete(assetTypeId: string): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\t\t// Get asset Stages in state associated with asset type to be deleted\n\t\tconst assetType = selectAssetTypeById(assetTypeId)(state)\n\t\tif (!assetType) {\n\t\t\tthrow new Error(`Expected asset type with offline_id ${assetTypeId} to exist`)\n\t\t}\n\t\tconst stagesOfAssetType = selectStagesOfAssetType(assetTypeId)(state) ?? []\n\t\tconst attachmentsOfAssetType = selectAttachmentsOfAssetType(assetTypeId)(state)\n\n\t\tthis.dispatch(deleteAssetType(assetTypeId))\n\n\t\t// If any asset type stages, remove them from the store\n\t\tif (stagesOfAssetType.length > 0) {\n\t\t\tconst stagesOfAssetTypeIds = stagesOfAssetType.map((assetStage: AssetStage) => assetStage.offline_id)\n\t\t\tthis.dispatch(removeStages(stagesOfAssetTypeIds))\n\t\t}\n\n\t\t// If any attachments to the asset type, remove them from the store\n\t\tif (attachmentsOfAssetType.length > 0) {\n\t\t\t// TODO: Figure out when we actually delete these attachments from the database, not just removing them from the store\n\t\t\tconst attachmentsOfAssetTypeIds = attachmentsOfAssetType.map(({ offline_id }) => offline_id)\n\t\t\tthis.dispatch(deleteAssetTypeAttachments(attachmentsOfAssetTypeIds))\n\t\t}\n\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Delete asset type\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/assets/types/${assetTypeId}/`,\n\t\t\tblockers: [assetTypeId],\n\t\t\tblocks: [],\n\t\t}).catch((e) => {\n\t\t\tthis.dispatch(addAssetType(assetType))\n\t\t\tthis.dispatch(addStages(stagesOfAssetType))\n\t\t\tthis.dispatch(addAssetTypeAttachments(attachmentsOfAssetType))\n\t\t\tthrow e\n\t\t})\n\t}\n\n\tasync refreshStore(projectId: number): Promise<void> {\n\t\tconst result = await this.enqueueRequest<AssetType[]>({\n\t\t\tdescription: \"Get asset types\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/asset-types/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t\tthis.dispatch(initializeAssetTypes(result))\n\t}\n}\n","import { BaseAttachmentService, BuildOfflineAttachmentData } from \"./BaseAttachmentService\"\nimport {\n\taddAssetTypeAttachments,\n\tdeleteAssetTypeAttachments,\n\tdeleteAssetTypeAttachment,\n\tselectAssetTypeAttachment,\n\tsetAssetTypeAttachment,\n\tupdateAssetTypeAttachments,\n\tinitializeAssetTypeAttachments,\n} from \"../../store\"\nimport { AttachmentModel, AssetTypeAttachment, Stored, OvermapRootState } from \"../../typings\"\nimport { offline } from \"../../utils\"\nimport { OptimisticMultipleModelResult } from \"../typings\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class AssetTypeAttachmentService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseAttachmentService<TState, TSDK, string, AssetTypeAttachment> {\n\tattachmentModel = AttachmentModel.AssetType\n\n\tinitializeAttachments = initializeAssetTypeAttachments\n\taddAttachments = addAssetTypeAttachments\n\tupdateAttachments = updateAssetTypeAttachments\n\tremoveAttachments = deleteAssetTypeAttachments\n\tremoveAttachment = deleteAssetTypeAttachment\n\tsetAttachment = setAssetTypeAttachment\n\n\tselectAttachment = selectAssetTypeAttachment\n\n\tprivate buildOfflineAttachment(data: BuildOfflineAttachmentData<string>) {\n\t\treturn offline({\n\t\t\tfile: URL.createObjectURL(data.file),\n\t\t\tfile_sha1: data.sha1,\n\t\t\tcreated_by: data.createdBy,\n\t\t\tfile_name: data.file.name,\n\t\t\tfile_type: data.file.type,\n\t\t\tsubmitted_at: data.submittedAt,\n\t\t\tdescription: data.description,\n\t\t\tasset_type: data.modelId,\n\t\t}) satisfies Stored<AssetTypeAttachment>\n\t}\n\n\tasync attachFilesToAssetType(\n\t\tfiles: File[],\n\t\tassetTypeId: string,\n\t): Promise<OptimisticMultipleModelResult<AssetTypeAttachment>> {\n\t\treturn this.attachFiles(files, assetTypeId, this.buildOfflineAttachment.bind(this))\n\t}\n\n\tasync deleteAssetTypeAttachment(attachmentId: string): Promise<void> {\n\t\treturn this.deleteAttachment(attachmentId)\n\t}\n}\n","import { Created, IssueComment, OvermapRootState, Payload, Submitted } from \"../../typings\"\nimport { offline, truncate } from \"../../utils\"\nimport { HttpMethod } from \"../../enums\"\nimport { addIssueComment, deleteIssueComment, setIssueComment, setIssueComments } from \"../../store\"\nimport { OptimisticModelResult } from \"../typings\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class IssueCommentService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\t// Omit author and submitted_at since these will always be set internally\n\tadd(comment: Omit<Payload<IssueComment>, \"author\" | \"submitted_at\">): OptimisticModelResult<IssueComment> {\n\t\tconst { store } = this.client\n\n\t\tconst offlineComment: Submitted<IssueComment> = offline({\n\t\t\t...comment,\n\t\t\tauthor: store.getState().userReducer.currentUser.id,\n\t\t\tsubmitted_at: new Date().toISOString(),\n\t\t})\n\n\t\tthis.dispatch(addIssueComment(offlineComment))\n\n\t\tconst promise = this.enqueueRequest<Created<IssueComment>>({\n\t\t\tdescription: `${truncate(comment.content, 80)}`,\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/issues/${comment.issue}/comment/`,\n\t\t\tpayload: offlineComment,\n\t\t\tblockers: [comment.issue],\n\t\t\tblocks: [offlineComment.offline_id],\n\t\t})\n\n\t\tpromise.catch(() => {\n\t\t\tthis.dispatch(deleteIssueComment(offlineComment.offline_id))\n\t\t})\n\n\t\treturn [offlineComment, promise]\n\t}\n\n\tupdate(comment: Submitted<IssueComment>): OptimisticModelResult<IssueComment> {\n\t\tconst { store } = this.client\n\n\t\tconst commentToUpdate = store.getState().issueCommentReducer.instances[comment.offline_id]\n\t\tif (!commentToUpdate) {\n\t\t\tthrow new Error(`Comment with offline_id ${comment.offline_id} not found in store`)\n\t\t}\n\n\t\tthis.dispatch(setIssueComment(comment))\n\n\t\tconst promise = this.enqueueRequest<Created<IssueComment>>({\n\t\t\tdescription: `Edit comment: ${truncate(comment.content, 80)}`,\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/issues/comments/${comment.offline_id}/`,\n\t\t\tpayload: comment,\n\t\t\tblockers: [comment.issue],\n\t\t\tblocks: [comment.offline_id],\n\t\t})\n\n\t\tpromise.catch(() => {\n\t\t\tthis.dispatch(setIssueComment(commentToUpdate))\n\t\t})\n\n\t\treturn [comment, promise]\n\t}\n\n\tremove(offline_id: string): Promise<undefined> {\n\t\tconst commentToRemove = this.client.store.getState().issueCommentReducer.instances[offline_id]\n\t\tif (!commentToRemove) {\n\t\t\tthrow new Error(`Comment with offline_id ${offline_id} not found in store`)\n\t\t}\n\n\t\tthis.dispatch(deleteIssueComment(offline_id))\n\n\t\tconst promise = this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Delete comment\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/issues/comments/${offline_id}/`,\n\t\t\tblockers: [offline_id],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tpromise.catch(() => {\n\t\t\tthis.dispatch(addIssueComment(commentToRemove))\n\t\t})\n\n\t\treturn promise\n\t}\n\n\tasync refreshStore(projectId: number): Promise<void> {\n\t\tconst result = await this.enqueueRequest<Created<IssueComment>[]>({\n\t\t\tdescription: \"Get comments\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/comments/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t\tthis.dispatch(setIssueComments(result))\n\t}\n}\n","import { Created, IssueUpdate, OvermapRootState } from \"../../typings\"\nimport { onlyUniqueOfflineIds } from \"../../utils\"\nimport { HttpMethod } from \"../../enums\"\nimport { initializeIssueUpdates } from \"../../store\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class IssueUpdateService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tasync refreshStore(projectId: number): Promise<void> {\n\t\tconst result = await this.enqueueRequest<Created<IssueUpdate>[]>({\n\t\t\tdescription: \"Get issue updates\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/issues/updates/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tlet filteredResult = result.filter(onlyUniqueOfflineIds)\n\t\tfilteredResult = filteredResult.map((comment) => {\n\t\t\treturn { ...comment }\n\t\t})\n\t\tif (result.length !== filteredResult.length) {\n\t\t\tconsole.error(\n\t\t\t\t`Received duplicate comments from the API (new length ${filteredResult.length}); filtered in browser.`,\n\t\t\t)\n\t\t}\n\t\tthis.dispatch(initializeIssueUpdates(filteredResult))\n\t}\n}\n","import { BaseAttachmentService, BuildOfflineAttachmentData } from \"./BaseAttachmentService\"\nimport { OptimisticMultipleModelResult } from \"../typings\"\nimport { AttachmentModel, IssueAttachment, OvermapRootState, Stored } from \"../../typings\"\nimport {\n\taddIssueAttachments,\n\tdeleteIssueAttachments,\n\tdeleteIssueAttachment,\n\tselectIssueAttachment,\n\tsetIssueAttachment,\n\tupdateIssueAttachments,\n\tinitializeIssueAttachments,\n} from \"../../store\"\nimport { offline } from \"../../utils\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class IssueAttachmentService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseAttachmentService<TState, TSDK, string, IssueAttachment> {\n\tattachmentModel = AttachmentModel.Issue\n\n\tinitializeAttachments = initializeIssueAttachments\n\taddAttachments = addIssueAttachments\n\tupdateAttachments = updateIssueAttachments\n\tremoveAttachments = deleteIssueAttachments\n\tremoveAttachment = deleteIssueAttachment\n\tsetAttachment = setIssueAttachment\n\n\tselectAttachment = selectIssueAttachment\n\n\tprivate buildOfflineAttachment(data: BuildOfflineAttachmentData<string>) {\n\t\treturn offline({\n\t\t\tfile: URL.createObjectURL(data.file),\n\t\t\tfile_sha1: data.sha1,\n\t\t\tcreated_by: data.createdBy,\n\t\t\tfile_name: data.file.name,\n\t\t\tfile_type: data.file.type,\n\t\t\tsubmitted_at: data.submittedAt,\n\t\t\tdescription: data.description,\n\t\t\tissue: data.modelId,\n\t\t}) satisfies Stored<IssueAttachment>\n\t}\n\n\tasync attachFilesToIssue(files: File[], issueId: string): Promise<OptimisticMultipleModelResult<IssueAttachment>> {\n\t\treturn this.attachFiles(files, issueId, this.buildOfflineAttachment.bind(this))\n\t}\n\n\tasync deleteIssueAttachment(attachmentId: string): Promise<void> {\n\t\treturn this.deleteAttachment(attachmentId)\n\t}\n}\n","import { unsafeShowToast } from \"@overmap-ai/blocks\"\nimport { OptimisticModelResult } from \"../typings\"\nimport {\n\tCategory,\n\tCreated,\n\tIssue,\n\tIssueAssociation,\n\tIssueType,\n\tIssueUpdate,\n\tIssueUpdateChange,\n\tOvermapRootState,\n\tStored,\n\tSubmitted,\n\tUser,\n} from \"../../typings\"\nimport { offline, onlyUniqueOfflineIds } from \"../../utils\"\nimport {\n\taddActiveProjectIssuesCount,\n\taddFormSubmissions,\n\taddIssue,\n\taddIssueAssociations,\n\taddIssueAttachments,\n\taddIssueUpdate,\n\taddIssueUpdates,\n\taddToRecentIssues,\n\tdeleteFormSubmissions,\n\tdeleteIssue,\n\tdeleteIssueAssociations,\n\tdeleteIssueAttachments,\n\tdeleteIssueUpdate,\n\tdeleteIssueUpdates,\n\tinitializeIssues,\n\tselectAttachmentsOfIssue,\n\tselectFormSubmissionsOfIssue,\n\tselectIssueAssociationsOfIssue,\n\tselectIssueAssociationsToIssue,\n\tselectIssueById,\n\tselectIssueUpdatesOfIssue,\n\tupdateIssue,\n} from \"../../store\"\nimport { HttpMethod } from \"../../enums\"\nimport { DEFAULT_ISSUE_PRIORITY, DEFAULT_ISSUE_STATUS } from \"../../constants\"\nimport { APIError } from \"../errors\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\n/**\n * Handles CRUD operations on issues\n */\nexport abstract class IssueService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\t// Basic CRUD functions\n\t// TODO: Once all models are represented in `Created<TModel>`, use `Created` in `OptimisticModelResult`, so we don't\n\t// have to repeat it for all optimistic model results (all optimistic results are created).\n\tadd(\n\t\tissue: Issue,\n\t\tworkspaceId: string,\n\t\tissueType: IssueType[\"offline_id\"] | null = null,\n\t): OptimisticModelResult<Issue> {\n\t\tconst { store } = this.client\n\t\tconst dateWithoutMilliseconds = new Date()\n\t\tconst state = store.getState()\n\t\tconst currentUserId = state.userReducer.currentUser.id\n\t\tdateWithoutMilliseconds.setMilliseconds(0)\n\n\t\tif (!workspaceId) {\n\t\t\tthrow new Error(\"No active workspace ID while creating issue.\")\n\t\t}\n\n\t\tconst issuePayload: Submitted<Issue> = offline({\n\t\t\t...issue,\n\t\t\tsubmitted_at: dateWithoutMilliseconds.toISOString(),\n\t\t\tindex_workspace: workspaceId,\n\t\t\tcreated_by: currentUserId,\n\t\t\tstatus: issue.status ?? DEFAULT_ISSUE_STATUS,\n\t\t\tpriority: issue.priority ?? DEFAULT_ISSUE_PRIORITY,\n\t\t})\n\n\t\tthis.dispatch(addIssue(issuePayload))\n\t\tthis.dispatch(addToRecentIssues(issuePayload.offline_id))\n\t\tthis.dispatch(addActiveProjectIssuesCount(1))\n\n\t\tconst promise = this.enqueueRequest<Created<Issue>>({\n\t\t\tdescription: \"Create issue\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: \"/issues/\",\n\t\t\tqueryParams: {\n\t\t\t\tworkspace_id: workspaceId,\n\t\t\t\t...(issueType ? { issue_type: issueType } : {}),\n\t\t\t},\n\t\t\tpayload: issuePayload,\n\t\t\tblockers: [\n\t\t\t\t\"add-issue\",\n\t\t\t\t...(issuePayload.index_workspace ? [issuePayload.index_workspace] : []),\n\t\t\t\t...issuePayload.visible_in_workspaces,\n\t\t\t],\n\t\t\tblocks: [issuePayload.offline_id],\n\t\t})\n\t\tvoid promise\n\t\t\t.then((result: Created<Issue>) => {\n\t\t\t\tthis.dispatch(updateIssue(result)) // Updates the index in the store\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tconsole.error(error)\n\t\t\t\tif (error instanceof APIError) {\n\t\t\t\t\tunsafeShowToast?.({\n\t\t\t\t\t\ttitle: \"Could not create issue\",\n\t\t\t\t\t\tdescription: error.message,\n\t\t\t\t\t\taccentColor: \"red\",\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tthis.dispatch(deleteIssue(issuePayload.offline_id))\n\t\t\t\tthis.dispatch(addActiveProjectIssuesCount(-1))\n\t\t\t\tthrow error\n\t\t\t})\n\t\treturn [issuePayload, promise]\n\t}\n\n\tupdate(issue: Submitted<Partial<Issue>>): OptimisticModelResult<Issue> {\n\t\tconst state = this.client.store.getState()\n\t\tconst issueToBeUpdated = selectIssueById(issue.offline_id)(state)\n\n\t\tif (!issueToBeUpdated) {\n\t\t\tthrow new Error(\n\t\t\t\t`Attempting to update an issue with offline_id ${issue.offline_id} that doesn't exist in the store`,\n\t\t\t)\n\t\t}\n\n\t\tconst updatedIssue: Stored<Issue> = { ...issueToBeUpdated, ...issue }\n\n\t\tthis.dispatch(updateIssue(updatedIssue))\n\n\t\tconst changes: IssueUpdate[\"changes\"] = {}\n\t\t// NOTE: order here mirrors the backend order\n\t\tfor (const issueUpdateChange of [\n\t\t\tIssueUpdateChange.TITLE,\n\t\t\tIssueUpdateChange.DESCRIPTION,\n\t\t\tIssueUpdateChange.STATUS,\n\t\t\tIssueUpdateChange.CATEGORY,\n\t\t\tIssueUpdateChange.PRIORITY,\n\t\t\tIssueUpdateChange.ASSIGNED_TO,\n\t\t\tIssueUpdateChange.DUE_DATE,\n\t\t]) {\n\t\t\tif (issueUpdateChange in issue && issue[issueUpdateChange] !== issueToBeUpdated[issueUpdateChange]) {\n\t\t\t\tswitch (issueUpdateChange) {\n\t\t\t\t\tcase \"category\": {\n\t\t\t\t\t\tlet categoryOrNull: Category | null = null\n\t\t\t\t\t\tconst categoryIdOrNull = issue[issueUpdateChange]\n\t\t\t\t\t\tif (categoryIdOrNull) {\n\t\t\t\t\t\t\tcategoryOrNull = state.categoryReducer.instances[categoryIdOrNull] ?? null\n\n\t\t\t\t\t\t\tif (!categoryOrNull)\n\t\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t\t`Trying to update issue category to ${categoryIdOrNull} which does not exist in store`,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tchanges[issueUpdateChange] = categoryOrNull\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\tname: categoryOrNull.name,\n\t\t\t\t\t\t\t\t\tcolor: categoryOrNull.color,\n\t\t\t\t\t\t\t\t\toffline_id: categoryOrNull.offline_id,\n\t\t\t\t\t\t\t }\n\t\t\t\t\t\t\t: null\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcase \"assigned_to\": {\n\t\t\t\t\t\tlet userOrNull: User | null = null\n\t\t\t\t\t\tconst userIdOrNull = issue[issueUpdateChange]\n\t\t\t\t\t\tif (userIdOrNull) {\n\t\t\t\t\t\t\tuserOrNull = state.userReducer.users[userIdOrNull] ?? null\n\n\t\t\t\t\t\t\tif (!userOrNull)\n\t\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t\t`Trying to update issue assigned_to to ${userIdOrNull} which does not exist in store`,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tchanges[issueUpdateChange] = userOrNull\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\tfull_name: userOrNull.username,\n\t\t\t\t\t\t\t\t\tid: userOrNull.id,\n\t\t\t\t\t\t\t }\n\t\t\t\t\t\t\t: null\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcase \"description\":\n\t\t\t\t\t\tchanges[issueUpdateChange] = issue[issueUpdateChange] ?? null\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase \"title\":\n\t\t\t\t\t\tchanges[issueUpdateChange] = issue[issueUpdateChange] ?? null\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase \"priority\":\n\t\t\t\t\t\tchanges[issueUpdateChange] = issue[issueUpdateChange]!\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase \"status\":\n\t\t\t\t\t\tchanges[issueUpdateChange] = issue[issueUpdateChange]!\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase \"due_date\":\n\t\t\t\t\t\tchanges[issueUpdateChange] = issue[issueUpdateChange]\n\t\t\t\t\t\t\t? (issue[issueUpdateChange] as string)\n\t\t\t\t\t\t\t: null\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst offlineIssueUpdate: Submitted<IssueUpdate> = offline({\n\t\t\tcreated_by: state.userReducer.currentUser.id,\n\t\t\tsubmitted_at: new Date().toISOString(),\n\t\t\tissue: issueToBeUpdated.offline_id,\n\t\t\tchanges: changes,\n\t\t})\n\n\t\tthis.dispatch(addIssueUpdate(offlineIssueUpdate))\n\n\t\tconst promise = this.enqueueRequest<Created<Issue>>({\n\t\t\tdescription: \"Edit issue\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/issues/${issue.offline_id}/`,\n\t\t\tpayload: issue,\n\t\t\tblockers: [issue.offline_id],\n\t\t\tblocks: [issue.offline_id],\n\t\t})\n\n\t\tpromise.catch(() => {\n\t\t\t// the patch failed, revert issue back, remove offline issue update\n\t\t\tthis.dispatch(updateIssue(issueToBeUpdated))\n\t\t\tthis.dispatch(deleteIssueUpdate(offlineIssueUpdate.offline_id))\n\t\t})\n\n\t\treturn [updatedIssue, promise]\n\t}\n\n\tasync remove(id: string): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst backup = selectIssueById(id)(state)\n\n\t\tif (!backup) {\n\t\t\tthrow new Error(`No issue with id ${id} found in the store`)\n\t\t}\n\n\t\tconst attachmentsOfIssue = selectAttachmentsOfIssue(id)(state)\n\t\tconst updatesOfIssue = selectIssueUpdatesOfIssue(id)(state)\n\t\tconst formSubmissionsOfIssue = selectFormSubmissionsOfIssue(id)(state)\n\n\t\tconst issueAssociationsRecord: Record<string, Stored<IssueAssociation>> = {}\n\n\t\tfor (const issueAssociation of selectIssueAssociationsToIssue(id)(state))\n\t\t\tissueAssociationsRecord[issueAssociation.offline_id] = issueAssociation\n\t\tfor (const issueAssociation of selectIssueAssociationsOfIssue(id)(state))\n\t\t\tissueAssociationsRecord[issueAssociation.offline_id] = issueAssociation\n\n\t\tconst issueAssociations = Object.values(issueAssociationsRecord)\n\n\t\tthis.dispatch(deleteIssue(id))\n\t\tthis.dispatch(addActiveProjectIssuesCount(-1))\n\t\tif (attachmentsOfIssue.length > 0)\n\t\t\tthis.dispatch(deleteIssueAttachments(attachmentsOfIssue.map(({ offline_id }) => offline_id)))\n\t\tif (updatesOfIssue.length > 0)\n\t\t\tthis.dispatch(deleteIssueUpdates(updatesOfIssue.map(({ offline_id }) => offline_id)))\n\t\tif (formSubmissionsOfIssue.length > 0)\n\t\t\tthis.dispatch(deleteFormSubmissions(formSubmissionsOfIssue.map(({ offline_id }) => offline_id)))\n\t\tif (issueAssociations.length > 0)\n\t\t\tthis.dispatch(deleteIssueAssociations(issueAssociations.map(({ offline_id }) => offline_id)))\n\n\t\t// TODO: remove Issue comments in similar pattern above\n\n\t\ttry {\n\t\t\t// REASON: Need to await to trigger the catch block.\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-confusing-void-expression\n\t\t\treturn await this.enqueueRequest<undefined>({\n\t\t\t\tdescription: \"Delete issue\",\n\t\t\t\tmethod: HttpMethod.DELETE,\n\t\t\t\turl: `/issues/${id}/`,\n\t\t\t\tblockers: [id],\n\t\t\t\tblocks: [],\n\t\t\t})\n\t\t} catch (e) {\n\t\t\tthis.dispatch(addIssue(backup))\n\t\t\tthis.dispatch(addIssueAttachments(attachmentsOfIssue))\n\t\t\tthis.dispatch(addIssueUpdates(updatesOfIssue))\n\t\t\tthis.dispatch(addActiveProjectIssuesCount(1))\n\t\t\tthis.dispatch(addFormSubmissions(formSubmissionsOfIssue))\n\t\t\tthis.dispatch(addIssueAssociations(issueAssociations))\n\n\t\t\tthrow e\n\t\t}\n\t}\n\n\t// Special functions\n\tasync refreshStore(projectId: number): Promise<undefined> {\n\t\tconst result = await this.enqueueRequest<Created<Issue>[]>({\n\t\t\tdescription: \"Get issues\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/issues/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t}).then((result) => {\n\t\t\tconst filteredResult = result.filter(onlyUniqueOfflineIds)\n\t\t\tif (result.length !== filteredResult.length) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t`Received duplicate issues from the API (new length ${filteredResult.length});\n\t\t\t\t\t\t filtered in browser.`,\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn filteredResult\n\t\t})\n\n\t\tthis.dispatch(initializeIssues(result))\n\t}\n}\n","import { OptimisticModelResult } from \"../typings\"\nimport { Created, IssueType, IssueTypePayload, Offline, OvermapRootState, Stored } from \"../../typings\"\nimport { offline } from \"../../utils\"\nimport {\n\taddIssues,\n\taddIssueType,\n\tdeleteIssues,\n\tinitializeIssueTypes,\n\tremoveIssueType,\n\tselectIssuesOfIssueType,\n\tselectIssueTypeById,\n\tsetIssueType,\n\tupdateIssueType,\n} from \"../../store\"\nimport { HttpMethod } from \"../../enums\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class IssueTypeService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tadd(payload: IssueTypePayload, organizationId: number): OptimisticModelResult<IssueType> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst offlineIssueType: Stored<IssueType> = offline({\n\t\t\t...payload,\n\t\t\tsubmitted_at: new Date().toISOString(),\n\t\t\tcreated_by: state.userReducer.currentUser.id,\n\t\t\torganization: organizationId,\n\t\t})\n\n\t\tthis.dispatch(addIssueType(offlineIssueType))\n\n\t\tconst promise = this.enqueueRequest<Created<IssueType>>({\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/organizations/${organizationId}/issue-types/`,\n\t\t\t// Sending only whats needed here\n\t\t\tpayload: {\n\t\t\t\toffline_id: offlineIssueType.offline_id,\n\t\t\t\tsubmitted_at: offlineIssueType.submitted_at,\n\t\t\t\ticon: offlineIssueType.icon,\n\t\t\t\tcolor: offlineIssueType.color,\n\t\t\t\tname: offlineIssueType.name,\n\t\t\t\tdescription: offlineIssueType.description,\n\t\t\t},\n\t\t\tblockers: [],\n\t\t\tblocks: [offlineIssueType.offline_id],\n\t\t})\n\n\t\tpromise\n\t\t\t.then((createdIssueType) => {\n\t\t\t\tthis.dispatch(setIssueType(createdIssueType))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(removeIssueType(offlineIssueType.offline_id))\n\t\t\t})\n\n\t\treturn [offlineIssueType, promise]\n\t}\n\n\tupdate(payload: Offline<Partial<IssueType>>): OptimisticModelResult<IssueType> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst issueTypeToBeUpdated = selectIssueTypeById(payload.offline_id)(state)\n\n\t\tif (!issueTypeToBeUpdated) {\n\t\t\tthrow new Error(`IssueType with offline_id ${payload.offline_id} does not exist in the store.`)\n\t\t}\n\n\t\tconst offlineUpdatedIssueType: Stored<IssueType> = {\n\t\t\t...issueTypeToBeUpdated,\n\t\t\t...payload,\n\t\t}\n\n\t\tthis.dispatch(updateIssueType(offlineUpdatedIssueType))\n\n\t\tconst promise = this.enqueueRequest<Stored<IssueType>>({\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/issues/types/${payload.offline_id}/`,\n\t\t\tpayload: payload,\n\t\t\tblockers: [payload.offline_id],\n\t\t\tblocks: [payload.offline_id],\n\t\t})\n\n\t\tpromise\n\t\t\t.then((updatedIssueType) => {\n\t\t\t\tthis.dispatch(setIssueType(updatedIssueType))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(setIssueType(issueTypeToBeUpdated))\n\t\t\t})\n\n\t\treturn [offlineUpdatedIssueType, promise]\n\t}\n\n\tdelete(issueTypeId: string): Promise<void> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst issueTypeToDelete = selectIssueTypeById(issueTypeId)(state)\n\n\t\tif (!issueTypeToDelete) {\n\t\t\tthrow new Error(`IssueType with offline_id ${issueTypeId} does not exist in the store.`)\n\t\t}\n\n\t\tconst issuesOfIssueType = selectIssuesOfIssueType(issueTypeId)(state) ?? []\n\n\t\tthis.dispatch(removeIssueType(issueTypeId))\n\n\t\tthis.dispatch(deleteIssues(issuesOfIssueType.map((issue) => issue.offline_id)))\n\n\t\t// TODO: probably want to remove any forms, revisions and submissions associated with the issue type\n\n\t\tconst promise = this.enqueueRequest<undefined>({\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/issues/types/${issueTypeId}/`,\n\t\t\tblockers: [issueTypeId],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tpromise.catch(() => {\n\t\t\tthis.dispatch(setIssueType(issueTypeToDelete))\n\t\t\tthis.dispatch(addIssues(issuesOfIssueType))\n\t\t})\n\n\t\treturn promise\n\t}\n\n\tasync refreshStore(organizationId: number): Promise<void> {\n\t\t// TODO: fetch for projects too\n\n\t\tconst result = await this.enqueueRequest<Created<IssueType>[]>({\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/organizations/${organizationId}/issue-types/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tthis.dispatch(initializeIssueTypes(result))\n\t}\n}\n","import { HttpMethod } from \"../../enums\"\nimport { deleteProjectAccess, initializeProjectAccesses, updateProjectAccess } from \"../../store\"\nimport { OvermapRootState, ProjectAccess } from \"../../typings\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\n/**\n * Handles the creation of ProjectAccess Service\n */\nexport abstract class ProjectAccessService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tasync fetchAll(projectId: number): Promise<ProjectAccess[]> {\n\t\treturn this.enqueueRequest<ProjectAccess[]>({\n\t\t\tdescription: \"Get project accesses\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/access/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t}\n\n\tasync update(projectAccess: ProjectAccess): Promise<ProjectAccess> {\n\t\tthis.dispatch(updateProjectAccess(projectAccess))\n\t\treturn this.enqueueRequest<ProjectAccess>({\n\t\t\tdescription: \"Edit project access\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/access/${projectAccess.offline_id}/`,\n\t\t\tpayload: projectAccess,\n\t\t\tblockers: [projectAccess.offline_id, \"change-access-level\"],\n\t\t\tblocks: [projectAccess.offline_id],\n\t\t})\n\t}\n\t// TODO: Re-add user to project if removal fails\n\tasync remove(projectAccess: ProjectAccess): Promise<undefined> {\n\t\tthis.dispatch(deleteProjectAccess(projectAccess.offline_id))\n\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Delete project access\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/access/${projectAccess.offline_id}/`,\n\t\t\tblockers: [projectAccess.offline_id],\n\t\t\tblocks: [],\n\t\t})\n\t}\n\n\tasync refreshStore(projectId: number): Promise<undefined> {\n\t\tconst promise = this.fetchAll(projectId)\n\t\tconst result: ProjectAccess[] = await promise\n\t\tthis.dispatch(initializeProjectAccesses(result))\n\t}\n}\n","import { HttpMethod } from \"enums/api\"\nimport { ProjectFile } from \"typings/models/projects\"\nimport { OptimisticGenericResult, SDKRequest } from \"../typings\"\nimport {\n\taddOrReplaceProjectFile,\n\taddOrReplaceProjectFiles,\n\tremoveProjectFile,\n\tsaveActiveProjectFileBounds,\n\tsetActiveProjectFileId,\n\tsetIsImportingProjectFile,\n} from \"store/slices/projectFileSlice\"\nimport { OvermapRootState } from \"../../typings\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\n/**\n * Handles creation and caching of ProjectFiles\n */\nexport abstract class ProjectFileService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tasync refreshStore(projectId: number): Promise<void> {\n\t\tconst result = await this.enqueueRequest<ProjectFile[]>({\n\t\t\tdescription: \"Get project files\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/files/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t\tthis.dispatch(addOrReplaceProjectFiles([]))\n\t\tthis.dispatch(addOrReplaceProjectFiles(result))\n\t}\n\n\tasync saveExisting(file: ProjectFile): Promise<ProjectFile> {\n\t\tif (!file.offline_id) {\n\t\t\tthrow new Error(\n\t\t\t\t\"You can only use this method to save existing project files. The one provided has no offline_id.\",\n\t\t\t)\n\t\t}\n\t\tconst editableData: { file?: unknown } = { ...file }\n\t\tdelete editableData.file\n\t\tconst promise = this.enqueueRequest<ProjectFile>({\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/projects/files/${file.offline_id}/`,\n\t\t\tpayload: editableData,\n\t\t\tblockers: [file.offline_id],\n\t\t\tblocks: [file.offline_id],\n\t\t})\n\t\tvoid promise.then((result) => {\n\t\t\tthis.dispatch(addOrReplaceProjectFile(result))\n\t\t})\n\t\treturn promise\n\t}\n\n\t// TODO: This needs to be seperated into a update and create method\n\tsaveActive(): OptimisticGenericResult<ProjectFile> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\t\tconst activeProjectFileId = state.projectFileReducer.activeProjectFileId\n\t\tconst activeProjectId = state.projectReducer.activeProjectId\n\t\tif (!activeProjectFileId) {\n\t\t\tthrow new Error(\"No active project file\")\n\t\t}\n\t\tif (!activeProjectId) {\n\t\t\tthrow new Error(\"No active project\")\n\t\t}\n\t\tconst activeProjectFile = state.projectFileReducer.projectFiles[activeProjectFileId]\n\t\tif (!activeProjectFile) {\n\t\t\tthrow new Error(\"No active project file\")\n\t\t}\n\n\t\tif (!activeProjectFile.bounds && !activeProjectFile.canvas_bounds) {\n\t\t\tthrow new Error(\"Project file must either have bounds or canvas_bounds set\")\n\t\t}\n\n\t\tlet requestDetails: SDKRequest | Promise<SDKRequest>\n\t\tconst existing = typeof activeProjectFile.file === \"string\" && !activeProjectFile.file.startsWith(\"blob:\")\n\t\tif (existing) {\n\t\t\tconst editableData: { file?: unknown } = { ...activeProjectFile }\n\t\t\tdelete editableData.file\n\t\t\trequestDetails = {\n\t\t\t\tmethod: HttpMethod.PATCH,\n\t\t\t\turl: `/projects/files/${activeProjectFileId}/`,\n\t\t\t\tpayload: editableData,\n\t\t\t\tblockers: [activeProjectFileId],\n\t\t\t\tblocks: [activeProjectFileId],\n\t\t\t}\n\t\t} else {\n\t\t\trequestDetails = new Promise<SDKRequest>((resolve, reject) => {\n\t\t\t\tthis.client.files\n\t\t\t\t\t.uploadFileToS3(activeProjectFile.file_sha1)\n\t\t\t\t\t.then(([fileProps]) => {\n\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\t\t\t\turl: `/projects/${activeProjectId}/files/`,\n\t\t\t\t\t\t\tpayload: {\n\t\t\t\t\t\t\t\t...activeProjectFile,\n\t\t\t\t\t\t\t\t...fileProps,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tblockers: [activeProjectFileId],\n\t\t\t\t\t\t\tblocks: [activeProjectFileId],\n\t\t\t\t\t\t})\n\t\t\t\t\t})\n\t\t\t\t\t.catch(reject)\n\t\t\t})\n\t\t}\n\t\tconst promise = Promise.resolve(requestDetails).then((requestDetails) => {\n\t\t\treturn this.enqueueRequest<ProjectFile>(requestDetails)\n\t\t})\n\t\tvoid promise.then((result) => {\n\t\t\tthis.dispatch(addOrReplaceProjectFile(result))\n\t\t})\n\t\tthis.dispatch(saveActiveProjectFileBounds)\n\t\tthis.dispatch(setActiveProjectFileId(null))\n\t\tthis.dispatch(setIsImportingProjectFile(false))\n\t\treturn [activeProjectFile, promise]\n\t}\n\n\tdelete(projectFileId: string): Promise<undefined> {\n\t\tthis.dispatch(removeProjectFile(projectFileId))\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/projects/files/${projectFileId}`,\n\t\t\tblockers: [projectFileId],\n\t\t\tblocks: [],\n\t\t})\n\t}\n}\n","import { BaseAttachmentService, BuildOfflineAttachmentData } from \"./BaseAttachmentService\"\nimport { offline } from \"../../utils\"\nimport { AttachmentModel, OvermapRootState, ProjectAttachment, Stored } from \"../../typings\"\nimport { OptimisticMultipleModelResult } from \"../typings\"\nimport {\n\taddProjectAttachments,\n\tdeleteProjectAttachments,\n\tdeleteProjectAttachment,\n\tselectProjectAttachment,\n\tsetProjectAttachment,\n\tupdateProjectAttachments,\n\tinitializeProjectAttachments,\n} from \"../../store\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class ProjectAttachmentService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseAttachmentService<TState, TSDK, number, ProjectAttachment> {\n\tattachmentModel = AttachmentModel.Project\n\n\tinitializeAttachments = initializeProjectAttachments\n\taddAttachments = addProjectAttachments\n\tupdateAttachments = updateProjectAttachments\n\tremoveAttachments = deleteProjectAttachments\n\tremoveAttachment = deleteProjectAttachment\n\tsetAttachment = setProjectAttachment\n\n\tselectAttachment = selectProjectAttachment\n\n\tprivate buildOfflineAttachment(data: BuildOfflineAttachmentData<number>) {\n\t\treturn offline({\n\t\t\tfile: URL.createObjectURL(data.file),\n\t\t\tfile_sha1: data.sha1,\n\t\t\tcreated_by: data.createdBy,\n\t\t\tfile_name: data.file.name,\n\t\t\tfile_type: data.file.type,\n\t\t\tsubmitted_at: data.submittedAt,\n\t\t\tdescription: data.description,\n\t\t\tproject: data.modelId,\n\t\t}) satisfies Stored<ProjectAttachment>\n\t}\n\n\tasync attachFilesToProject(\n\t\tfiles: File[],\n\t\tprojectId: number,\n\t): Promise<OptimisticMultipleModelResult<ProjectAttachment>> {\n\t\treturn this.attachFiles(files, projectId, this.buildOfflineAttachment.bind(this))\n\t}\n\n\tasync deleteProjectAttachment(attachmentId: string): Promise<void> {\n\t\treturn this.deleteAttachment(attachmentId)\n\t}\n}\n","import { HttpMethod } from \"enums/api\"\nimport { Project } from \"typings/models/projects\"\nimport { v4 as uuidv4 } from \"uuid\"\nimport { Created, License, OvermapRootState, Payload } from \"../../typings\"\nimport {\n\tacceptProjectInvite,\n\taddOrReplaceProjectFiles,\n\tdeleteProject,\n\tdeleteProjectAccesses,\n\tdeleteProjectAttachments,\n\tinitializeProjectAccesses,\n\tremoveProjectFilesOfProject,\n\tselectAttachmentsOfProject,\n\tselectLicenseForProject,\n\tselectProjectAccesses,\n\tselectProjectFiles,\n\tselectProjectMapping,\n\tsetProjectAttachments,\n\tsetProjects,\n\tupdateLicense,\n\tupdateOrCreateProject,\n} from \"../../store\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\ninterface JoinProjectResponse {\n\tusername: string\n}\n\nexport abstract class ProjectService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\t/**\n\t * Creates a new project. Due to the nature of project creation,\n\t * @param project A Payload<Project> object containing project attributes.\n\t * @returns A promise that resolves to a Project.\n\t * @throws An APIError if the server returns an error, or any other error that may occur.\n\t */\n\tasync add(project: Payload<Project>): Promise<Project> {\n\t\tif (!project.organization_owner && !project.user_owner) {\n\t\t\tthrow new Error(\"Project type was not chosen when trying to create a project\")\n\t\t}\n\n\t\tif (!project.bounds && !project.canvas_bounds) {\n\t\t\tthrow new Error(\"Project must either have bounds or canvas_bounds set\")\n\t\t}\n\n\t\tconst isOrganizationProject = !!project.organization_owner\n\n\t\tconst url = isOrganizationProject ? `/organizations/${project.organization_owner}/projects/` : \"/projects/\"\n\t\tconst projectType = isOrganizationProject\n\t\t\t? { organization_owner: project.organization_owner }\n\t\t\t: { user_owner: project.user_owner }\n\n\t\treturn await this.enqueueRequest<Created<Project>>({\n\t\t\tdescription: \"Create project\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl,\n\t\t\tpayload: {\n\t\t\t\tname: project.name,\n\t\t\t\tbounds: project.bounds,\n\t\t\t\t...projectType,\n\t\t\t},\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t}\n\n\tasync update(project: Project): Promise<Project> {\n\t\tif (!project.bounds && !project.canvas_bounds) {\n\t\t\tthrow new Error(\"Project must either have bounds or canvas_bounds set\")\n\t\t}\n\n\t\tthis.dispatch(updateOrCreateProject(project))\n\t\treturn await this.enqueueRequest<Project>({\n\t\t\tdescription: \"Update project\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/projects/${project.id}/`,\n\t\t\tpayload: {\n\t\t\t\tname: project.name,\n\t\t\t\tbounds: project.bounds,\n\t\t\t},\n\t\t\tblockers: [project.id.toString()],\n\t\t\tblocks: [project.id.toString()],\n\t\t})\n\t}\n\n\tasync delete(projectId: number): Promise<void> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\t\tconst projects = selectProjectMapping(state)\n\t\tconst project = projects[projectId]\n\t\tif (!project) {\n\t\t\tthrow new Error(\"Expected project to exist\")\n\t\t}\n\n\t\t// TODO: this shouldnt be an optimistic result\n\t\t// Selector needed to restore if the request fails\n\t\tconst filesToDelete = selectProjectFiles(state).filter((file) => file.project === projectId)\n\t\tthis.dispatch(removeProjectFilesOfProject(project.id))\n\n\t\t// Selector needed to restore if the request fails\n\t\tconst attachmentsOfProject = selectAttachmentsOfProject(project.id)(state)\n\t\tthis.dispatch(deleteProjectAttachments(attachmentsOfProject.map(({ offline_id }) => offline_id)))\n\n\t\t// Selector needed to restore if the request fails\n\t\tconst projectAccesses = selectProjectAccesses(state)\n\t\tthis.dispatch(deleteProjectAccesses(projectAccesses.map(({ offline_id }) => offline_id)))\n\n\t\t// Necessary to prevent no projects view from showing when project is deleted\n\t\tthis.dispatch({ type: \"rehydrated/setRehydrated\", payload: false })\n\t\tthis.dispatch(deleteProject(project))\n\n\t\tconst license = selectLicenseForProject(project.id)(state)\n\t\t// Detach license from project\n\t\tif (license) {\n\t\t\tthis.dispatch(updateLicense({ ...license, project: null } as License))\n\t\t}\n\n\t\ttry {\n\t\t\tawait this.enqueueRequest<undefined>({\n\t\t\t\tdescription: \"Delete project\",\n\t\t\t\tmethod: HttpMethod.DELETE,\n\t\t\t\turl: `/projects/${projectId}/`,\n\t\t\t\tblockers: [projectId.toString()],\n\t\t\t\tblocks: [],\n\t\t\t})\n\t\t\tthis.dispatch({ type: \"rehydrated/setRehydrated\", payload: true })\n\t\t} catch (e) {\n\t\t\tthis.dispatch(setProjects(Object.values(projects)))\n\t\t\tthis.dispatch(initializeProjectAccesses(Object.values(projectAccesses)))\n\t\t\tthis.dispatch(addOrReplaceProjectFiles(filesToDelete))\n\t\t\tthis.dispatch(setProjectAttachments(attachmentsOfProject))\n\t\t\tthis.dispatch({ type: \"rehydrated/setRehydrated\", payload: true })\n\t\t\tif (license) {\n\t\t\t\tthis.dispatch(updateLicense({ ...license, project: project.id } as License))\n\t\t\t}\n\t\t\tthrow e\n\t\t}\n\t}\n\n\tinvite(projectId: number, email: string): Promise<undefined> {\n\t\tconst offline_id: string = uuidv4()\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Invite user to project\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/projects/${projectId}/invite/${email}/`,\n\t\t\tpayload: {\n\t\t\t\toffline_id,\n\t\t\t},\n\t\t\tblockers: [],\n\t\t\tblocks: [offline_id],\n\t\t})\n\t}\n\n\tjoinProject(projectId: number, userId: number, inviteCode: string): Promise<JoinProjectResponse> {\n\t\treturn this.enqueueRequest<JoinProjectResponse>({\n\t\t\tdescription: \"Join project\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/join-project/${userId}/${inviteCode}/`,\n\t\t\tisAuthNeeded: false,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t}\n\n\tasync acceptInvite(projectId: number): Promise<void> {\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Accept project invite\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/projects/${projectId}/accept-invite/`,\n\t\t\tblockers: [projectId.toString()],\n\t\t\tblocks: [projectId.toString()],\n\t\t}).then(() => {\n\t\t\tthis.dispatch(acceptProjectInvite(projectId))\n\t\t})\n\t}\n}\n","import { HttpMethod } from \"enums/api\"\nimport { addForm, deleteForm, initializeForms, selectFormById, updateForm } from \"store/slices/formSlice\"\nimport {\n\tForm,\n\tFormRevision,\n\tFormRevisionAttachment,\n\tFormRevisionPayload,\n\tISerializedField,\n\tISerializedOnlyField,\n} from \"typings/models/forms\"\nimport { OptimisticMultipleModelResult, PresignedUrlsResponse } from \"../typings\"\nimport { offline } from \"utils/offline\"\nimport { Created, OvermapRootState, Stored, Submitted } from \"../../typings\"\nimport { hashFile } from \"../../utils\"\nimport {\n\taddFormRevision,\n\taddFormRevisionAttachments,\n\taddFormRevisions,\n\taddFormSubmissions,\n\tdeleteFormRevision,\n\tdeleteFormRevisionAttachments,\n\tdeleteFormRevisions,\n\tdeleteFormSubmissions,\n\tinitializeFormRevisionAttachments,\n\tinitializeFormRevisions,\n\tselectFormRevisionsOfForm,\n\tselectFormSubmissionsOfForm,\n\tsetFormRevision,\n\tupdateFormRevisionAttachments,\n} from \"../../store\"\nimport type { BaseSDK } from \"../base\"\nimport { FilePayload } from \"./BaseAttachmentService\"\nimport { BaseUploadService } from \"./BaseUploadService\"\n\n/**\n * Finds and separates image files from form revision fields. The image attribute is deleted from the field objects and\n * is returned separately from the image files as they are stored in a different table.\n */\nconst separateImageFromFields = async (fields: ISerializedField[]) => {\n\tconst images: Record<string, File> = {} // key: field identifier, value: File\n\tconst newFields: ISerializedField[] = [] // fields without image attribute\n\tfor (const section of fields) {\n\t\tif (section.type !== \"section\") {\n\t\t\tthrow new Error(`Expected ISerializedField type to be a section. Got ${section.type} instead.`)\n\t\t}\n\n\t\tconst { fields: sectionFields } = section\n\t\tconst newSectionFields: ISerializedOnlyField[] = []\n\t\tfor (const field of sectionFields) {\n\t\t\tif (field.image) {\n\t\t\t\tif (field.image instanceof Promise) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\timages[field.identifier] = await field.image\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tconsole.error(\"Failed to get image from promise\", e)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\timages[field.identifier] = field.image\n\t\t\t\t}\n\t\t\t\tdelete field.image\n\t\t\t}\n\t\t\tnewSectionFields.push(field)\n\t\t}\n\t\tnewFields.push({ ...section, fields: newSectionFields })\n\t}\n\n\treturn { fields: newFields, images }\n}\n\nexport abstract class FormService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseUploadService<TState, TSDK> {\n\tprivate async bulkAddRevisionAttachments(\n\t\trevisionId: string,\n\t\tfiles: Record<string, File>,\n\t): Promise<OptimisticMultipleModelResult<FormRevisionAttachment>> {\n\t\tinterface AttachmentPayload {\n\t\t\toffline_id: string\n\t\t\tname: string\n\t\t\tsha1: string\n\t\t\tfield_identifier: string\n\t\t\tdesscription?: string\n\t\t}\n\n\t\tconst submittedAt = new Date().toISOString()\n\t\tconst createdBy = this.client.store.getState().userReducer.currentUser.id\n\n\t\tconst filePayloads: Record<FilePayload[\"sha1\"], FilePayload> = {}\n\t\tconst offlineFormRevisionAttachments: Stored<FormRevisionAttachment>[] = []\n\t\tconst attachmentPayloads: AttachmentPayload[] = []\n\n\t\tfor (const [fieldIdentifier, file] of Object.entries(files)) {\n\t\t\tconst sha1 = await hashFile(file)\n\n\t\t\tif (!(sha1 in filePayloads)) {\n\t\t\t\tfilePayloads[sha1] = {\n\t\t\t\t\tsha1,\n\t\t\t\t\tfile_type: file.type,\n\t\t\t\t\textension: file.name.split(\".\").pop()!,\n\t\t\t\t\tsize: file.size,\n\t\t\t\t}\n\t\t\t\tawait this.client.files.addCache(file, sha1)\n\t\t\t}\n\n\t\t\tconst offlineFormRevisionAttachment: Stored<FormRevisionAttachment> = offline({\n\t\t\t\tfile: URL.createObjectURL(file),\n\t\t\t\tfile_type: file.type,\n\t\t\t\tfile_name: file.name,\n\t\t\t\tfile_sha1: sha1,\n\t\t\t\tcreated_by: createdBy,\n\t\t\t\trevision: revisionId,\n\t\t\t\tsubmitted_at: submittedAt,\n\t\t\t\tfield_identifier: fieldIdentifier,\n\t\t\t})\n\t\t\tofflineFormRevisionAttachments.push(offlineFormRevisionAttachment)\n\n\t\t\tconst attachmentPayload: AttachmentPayload = {\n\t\t\t\toffline_id: offlineFormRevisionAttachment.offline_id,\n\t\t\t\tname: file.name,\n\t\t\t\tfield_identifier: fieldIdentifier,\n\t\t\t\tsha1,\n\t\t\t}\n\t\t\tattachmentPayloads.push(attachmentPayload)\n\t\t}\n\n\t\tthis.dispatch(addFormRevisionAttachments(offlineFormRevisionAttachments))\n\n\t\tconst promise = this.enqueueRequest<{\n\t\t\tattachments: Created<FormRevisionAttachment>[]\n\t\t\tpresigned_urls: PresignedUrlsResponse\n\t\t}>({\n\t\t\tdescription: \"Attach files to form revision\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/forms/revisions/${revisionId}/attachments/bulk/`,\n\t\t\tpayload: {\n\t\t\t\tsubmitted_at: submittedAt,\n\t\t\t\tattachments: attachmentPayloads,\n\t\t\t\tfiles: Object.values(filePayloads),\n\t\t\t},\n\t\t\tblockers: [revisionId],\n\t\t\tblocks: offlineFormRevisionAttachments.map((attachment) => attachment.offline_id),\n\t\t})\n\n\t\tpromise\n\t\t\t.then((result) => {\n\t\t\t\tthis.processPresignedUrls(result.presigned_urls)\n\t\t\t\tthis.dispatch(updateFormRevisionAttachments(result.attachments))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(\n\t\t\t\t\tdeleteFormRevisionAttachments(\n\t\t\t\t\t\tofflineFormRevisionAttachments.map((attachment) => attachment.offline_id),\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t})\n\n\t\treturn [offlineFormRevisionAttachments, promise.then(({ attachments }) => attachments)]\n\t}\n\n\tprivate async add(\n\t\townerId: string,\n\t\tform: Submitted<Form>,\n\t\tinitialRevision: FormRevisionPayload,\n\t\turlPrefix: string,\n\t): Promise<\n\t\t[\n\t\t\tStored<Form>,\n\t\t\tStored<FormRevision>,\n\t\t\tStored<FormRevisionAttachment>[],\n\t\t\tPromise<Created<FormRevision>>,\n\t\t\tPromise<Created<FormRevisionAttachment>[]>,\n\t\t]\n\t> {\n\t\tinterface CreateFormPayload {\n\t\t\toffline_id: string\n\t\t\tsubmitted_at: string\n\t\t\tinitial_revision: {\n\t\t\t\toffline_id: string\n\t\t\t\tsubmitted_at: string\n\t\t\t\ttitle: string\n\t\t\t\tdescription?: string\n\t\t\t\tfields: ISerializedField[]\n\t\t\t}\n\t\t}\n\n\t\tconst { fields, images } = await separateImageFromFields(initialRevision.fields)\n\n\t\tconst offlineFormRevision: Submitted<FormRevision> = offline({\n\t\t\t...initialRevision,\n\t\t\tfields: fields,\n\t\t\tcreated_by: form.created_by,\n\t\t\tform: form.offline_id,\n\t\t\tsubmitted_at: form.submitted_at,\n\t\t\trevision: \"Pending\",\n\t\t})\n\n\t\tthis.dispatch(addForm(form))\n\t\tthis.dispatch(addFormRevision(offlineFormRevision))\n\n\t\tconst formPromise = this.enqueueRequest<FormRevision>({\n\t\t\tdescription: \"Create form\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: urlPrefix,\n\t\t\tpayload: {\n\t\t\t\t// Sending exactly what is currently needed for the endpoint\n\t\t\t\toffline_id: form.offline_id,\n\t\t\t\tsubmitted_at: form.submitted_at,\n\t\t\t\tinitial_revision: {\n\t\t\t\t\toffline_id: offlineFormRevision.offline_id,\n\t\t\t\t\tsubmitted_at: offlineFormRevision.submitted_at,\n\t\t\t\t\ttitle: offlineFormRevision.title,\n\t\t\t\t\tdescription: offlineFormRevision.description,\n\t\t\t\t\tfields: offlineFormRevision.fields,\n\t\t\t\t},\n\t\t\t} satisfies CreateFormPayload,\n\t\t\tblockers: [ownerId],\n\t\t\tblocks: [form.offline_id, offlineFormRevision.offline_id],\n\t\t})\n\n\t\tconst [offlineFormRevisionAttachments, attachmentsPromise] = await this.bulkAddRevisionAttachments(\n\t\t\tofflineFormRevision.offline_id,\n\t\t\timages,\n\t\t)\n\n\t\tvoid formPromise.catch((e) => {\n\t\t\tthis.dispatch(deleteForm(form.offline_id))\n\t\t\tthis.dispatch(deleteFormRevision(offlineFormRevision.offline_id))\n\t\t\t// TODO: remove form revision attachments\n\t\t\tthrow e\n\t\t})\n\n\t\treturn [form, offlineFormRevision, offlineFormRevisionAttachments, formPromise, attachmentsPromise]\n\t}\n\n\taddForOrganization(organizationId: number, initialRevision: FormRevisionPayload) {\n\t\tconst state: OvermapRootState = this.client.store.getState()\n\n\t\tconst offlineForm: Submitted<Form> = offline({\n\t\t\tfavorite: false,\n\t\t\tcreated_by: state.userReducer.currentUser.id,\n\t\t\tsubmitted_at: new Date().toISOString(),\n\t\t\torganization: organizationId,\n\t\t})\n\n\t\treturn this.add(\n\t\t\torganizationId.toString(),\n\t\t\tofflineForm,\n\t\t\tinitialRevision,\n\t\t\t`/organizations/${organizationId}/create-form/`,\n\t\t)\n\t}\n\n\taddForProject(projectId: number, initialRevision: FormRevisionPayload) {\n\t\tconst state: OvermapRootState = this.client.store.getState()\n\n\t\tconst offlineForm: Submitted<Form> = offline({\n\t\t\tfavorite: false,\n\t\t\tcreated_by: state.userReducer.currentUser.id,\n\t\t\tsubmitted_at: new Date().toISOString(),\n\t\t\tproject: projectId,\n\t\t})\n\n\t\treturn this.add(projectId.toString(), offlineForm, initialRevision, `/projects/${projectId}/create-form/`)\n\t}\n\n\taddForIssueType(issueTypeId: string, initialRevision: FormRevisionPayload) {\n\t\tconst state: OvermapRootState = this.client.store.getState()\n\n\t\tconst offlineForm: Submitted<Form> = offline({\n\t\t\tfavorite: false,\n\t\t\tcreated_by: state.userReducer.currentUser.id,\n\t\t\tsubmitted_at: new Date().toISOString(),\n\t\t\tissue_type: issueTypeId,\n\t\t})\n\n\t\treturn this.add(issueTypeId, offlineForm, initialRevision, `/issues/types/${issueTypeId}/create-form/`)\n\t}\n\n\taddForAssetType(assetTypeId: string, initialRevision: FormRevisionPayload) {\n\t\tconst state: OvermapRootState = this.client.store.getState()\n\n\t\tconst offlineForm: Submitted<Form> = offline({\n\t\t\tfavorite: false,\n\t\t\tcreated_by: state.userReducer.currentUser.id,\n\t\t\tsubmitted_at: new Date().toISOString(),\n\t\t\tasset_type: assetTypeId,\n\t\t})\n\n\t\treturn this.add(assetTypeId, offlineForm, initialRevision, `/assets/types/${assetTypeId}/create-form/`)\n\t}\n\n\tasync createRevision(\n\t\tformId: string,\n\t\trevision: FormRevisionPayload,\n\t): Promise<\n\t\t[\n\t\t\tStored<FormRevision>,\n\t\t\tStored<FormRevisionAttachment>[],\n\t\t\tPromise<Created<FormRevision>>,\n\t\t\tPromise<Created<FormRevisionAttachment>[]>,\n\t\t]\n\t> {\n\t\tconst offlineRevision = offline(revision)\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst activeProjectId = state.projectReducer.activeProjectId\n\t\tif (!activeProjectId) {\n\t\t\tthrow new Error(\"Cannot create form revision when there is no active project.\")\n\t\t}\n\t\tconst currentUserId = state.userReducer.currentUser.id\n\n\t\tconst { fields, images } = await separateImageFromFields(offlineRevision.fields)\n\n\t\tconst fullRevision: Submitted<FormRevision> = {\n\t\t\t...offlineRevision,\n\t\t\tfields: fields,\n\t\t\tcreated_by: currentUserId,\n\t\t\trevision: \"Pending\",\n\t\t\tform: formId,\n\t\t\tsubmitted_at: new Date().toISOString(),\n\t\t}\n\n\t\tthis.dispatch(addFormRevision(fullRevision))\n\n\t\tconst promise = this.enqueueRequest<FormRevision>({\n\t\t\tdescription: \"Create form revision\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/forms/${formId}/`,\n\t\t\tpayload: {\n\t\t\t\tinitial_revision: {\n\t\t\t\t\toffline_id: fullRevision.offline_id,\n\t\t\t\t\tsubmitted_at: fullRevision.submitted_at,\n\t\t\t\t\ttitle: fullRevision.title,\n\t\t\t\t\tdescription: fullRevision.description,\n\t\t\t\t\tfields: fullRevision.fields,\n\t\t\t\t},\n\t\t\t},\n\t\t\tblockers: [formId],\n\t\t\tblocks: [offlineRevision.offline_id],\n\t\t})\n\n\t\tconst [offlineFormRevisionAttachments, attachmentsPromise] = await this.bulkAddRevisionAttachments(\n\t\t\tfullRevision.offline_id,\n\t\t\timages,\n\t\t)\n\n\t\tvoid promise\n\t\t\t.then((result) => {\n\t\t\t\tthis.dispatch(setFormRevision(result))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(deleteFormRevision(fullRevision.offline_id))\n\t\t\t})\n\n\t\treturn [fullRevision, offlineFormRevisionAttachments, promise, attachmentsPromise]\n\t}\n\n\tasync favorite(formId: string): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst activeProjectId = state.projectReducer.activeProjectId\n\t\tconst form = state.formReducer.instances[formId]\n\n\t\tif (!form) {\n\t\t\tthrow new Error(`Expected form to exist, got ${form}`)\n\t\t}\n\n\t\tthis.dispatch(updateForm({ ...form, favorite: true }))\n\n\t\ttry {\n\t\t\tawait this.enqueueRequest({\n\t\t\t\tdescription: \"Favorite form\",\n\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\turl: `/forms/${formId}/favorite/${activeProjectId}/`,\n\t\t\t\tblockers: [formId, `favorite-${formId}`],\n\t\t\t\tblocks: [`favorite-${formId}`],\n\t\t\t})\n\t\t} catch (e) {\n\t\t\tthis.dispatch(updateForm(form))\n\t\t\tthrow e\n\t\t}\n\t}\n\n\tasync unfavorite(formId: string): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst activeProjectId = state.projectReducer.activeProjectId\n\t\tconst form = state.formReducer.instances[formId]\n\n\t\tif (!form) {\n\t\t\tthrow new Error(`Expected form to exist, got ${form}`)\n\t\t}\n\n\t\tthis.dispatch(updateForm({ ...form, favorite: false }))\n\n\t\ttry {\n\t\t\t// REASON: Need to await to trigger the catch block.\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-confusing-void-expression\n\t\t\treturn await this.enqueueRequest<undefined>({\n\t\t\t\tdescription: \"Unfavorite form\",\n\t\t\t\tmethod: HttpMethod.DELETE,\n\t\t\t\turl: `/forms/${formId}/unfavorite/${activeProjectId}/`,\n\t\t\t\tblockers: [formId, `favorite-${formId}`],\n\t\t\t\tblocks: [`favorite-${formId}`],\n\t\t\t})\n\t\t} catch (e) {\n\t\t\tthis.dispatch(updateForm(form))\n\t\t\tthrow e\n\t\t}\n\t}\n\n\tasync delete(formId: string): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\t\tconst form = selectFormById(formId)(state)\n\t\tif (!form) {\n\t\t\tthrow new Error(\"Expected form to exist\")\n\t\t}\n\t\t// Delete all submissions for this form\n\t\tconst formSubmissions = selectFormSubmissionsOfForm(formId)(state)\n\t\tif (formSubmissions && formSubmissions.length > 0) {\n\t\t\tthis.dispatch(deleteFormSubmissions(formSubmissions.map(({ offline_id }) => offline_id)))\n\t\t}\n\n\t\t// Delete all revisions for this form\n\t\tconst formRevisions = selectFormRevisionsOfForm(formId)(state)\n\t\tif (formRevisions && formRevisions.length > 0) {\n\t\t\tthis.dispatch(deleteFormRevisions(formRevisions.map(({ offline_id }) => offline_id)))\n\t\t}\n\n\t\t// Delete the form itself\n\t\tthis.dispatch(deleteForm(formId))\n\n\t\ttry {\n\t\t\t// REASON: Need to await to trigger the catch block.\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-confusing-void-expression\n\t\t\treturn await this.enqueueRequest<undefined>({\n\t\t\t\tdescription: \"Delete form\",\n\t\t\t\tmethod: HttpMethod.DELETE,\n\t\t\t\turl: `/forms/${formId}/`,\n\t\t\t\tblockers: [formId],\n\t\t\t\tblocks: [],\n\t\t\t})\n\t\t} catch (e) {\n\t\t\tthis.dispatch(addForm(form))\n\t\t\tif (formRevisions && formRevisions.length > 0) {\n\t\t\t\tthis.dispatch(addFormRevisions(formRevisions))\n\t\t\t}\n\t\t\tif (formSubmissions && formSubmissions.length > 0) {\n\t\t\t\tthis.dispatch(addFormSubmissions(formSubmissions))\n\t\t\t}\n\t\t\tthrow e\n\t\t}\n\t}\n\n\tasync refreshStore(projectId: number): Promise<void> {\n\t\tinterface FormDataResponse {\n\t\t\tforms: Created<Form>[]\n\t\t\trevisions: Created<FormRevision>[]\n\t\t\tattachments: Created<FormRevisionAttachment>[]\n\t\t}\n\n\t\tconst forms: Created<Form>[] = []\n\t\tconst revisions: Created<FormRevision>[] = []\n\t\tconst attachments: Created<FormRevisionAttachment>[] = []\n\n\t\tconst projectFormsResult = await this.enqueueRequest<FormDataResponse>({\n\t\t\tdescription: \"Fetch project forms\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/forms/`,\n\t\t\tblockers: [projectId.toString()],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tfor (const form of projectFormsResult.forms) forms.push(form)\n\t\tfor (const revision of projectFormsResult.revisions) revisions.push(revision)\n\t\tfor (const attachment of projectFormsResult.attachments) attachments.push(attachment)\n\n\t\tconst organizationFormsResult = await this.enqueueRequest<FormDataResponse>({\n\t\t\tdescription: \"Fetch organization forms\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/organizations/forms/`,\n\t\t\tblockers: [projectId.toString()],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tfor (const form of organizationFormsResult.forms) forms.push(form)\n\t\tfor (const revision of organizationFormsResult.revisions) revisions.push(revision)\n\t\tfor (const attachment of organizationFormsResult.attachments) attachments.push(attachment)\n\n\t\tconst assetTypeFormsResult = await this.enqueueRequest<FormDataResponse>({\n\t\t\tdescription: \"Fetch asset type forms\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/asset-types/forms/`,\n\t\t\tblockers: [projectId.toString()],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tfor (const form of assetTypeFormsResult.forms) forms.push(form)\n\t\tfor (const revision of assetTypeFormsResult.revisions) revisions.push(revision)\n\t\tfor (const attachment of assetTypeFormsResult.attachments) attachments.push(attachment)\n\n\t\tconst issueTypeFormsResult = await this.enqueueRequest<FormDataResponse>({\n\t\t\tdescription: \"Fetch issue type forms\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/issue-types/forms/`,\n\t\t\tblockers: [projectId.toString()],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tfor (const form of issueTypeFormsResult.forms) forms.push(form)\n\t\tfor (const revision of issueTypeFormsResult.revisions) revisions.push(revision)\n\t\tfor (const attachment of issueTypeFormsResult.attachments) attachments.push(attachment)\n\n\t\tthis.dispatch(initializeForms(forms))\n\t\tthis.dispatch(initializeFormRevisions(revisions))\n\t\tthis.dispatch(initializeFormRevisionAttachments(attachments))\n\t}\n}\n","import { FieldValue, FormSubmission, FormSubmissionAttachment, FormSubmissionPayload } from \"typings/models/forms\"\nimport { OptimisticMultipleModelResult, PresignedUrlsResponse } from \"../typings\"\nimport { HttpMethod } from \"enums/api\"\nimport { hashFile, offline } from \"utils\"\nimport { v4 as uuidv4 } from \"uuid\"\nimport {\n\taddActiveProjectFormSubmissionsCount,\n\taddFormSubmission,\n\taddFormSubmissionAttachments,\n\taddFormSubmissions,\n\tdeleteFormSubmission,\n\tdeleteFormSubmissionAttachments,\n\tinitializeFormSubmissionAttachments,\n\tinitializeFormSubmissions,\n\tselectAttachmentsOfFormSubmission,\n\tselectFormSubmissionAttachemntsByIds,\n\tselectFormSubmissionById,\n\tsetFormSubmission,\n\tupdateFormSubmission,\n\tupdateFormSubmissionAttachments,\n} from \"../../store\"\nimport { Created, Offline, OvermapRootState, Payload, Stored, Submitted } from \"../../typings\"\nimport { chunkArray } from \"../../utils/array\"\nimport type { BaseSDK } from \"../base\"\nimport { BaseUploadService } from \"./BaseUploadService\"\nimport { FilePayload } from \"./BaseAttachmentService\"\n\nconst isArrayOfFiles = (value: unknown): value is File[] => {\n\treturn Array.isArray(value) && value[0] instanceof File\n}\n\n// returns a new object with the files separated from the values, files is a dictionary with the key being the\n// field identifier and the value being the list of files for that field\nconst separateFilesFromValues = (values: FormSubmissionPayload[\"values\"]) => {\n\tconst files: Record<string, File[]> = {}\n\tconst newValues: Record<string, FieldValue> = {}\n\tfor (const key in values) {\n\t\tconst value = values[key]\n\n\t\tif (value === undefined) throw new Error(\"Expected value to be defined\")\n\n\t\tif (value instanceof File) {\n\t\t\tfiles[key] = [value]\n\t\t} else if (isArrayOfFiles(value)) {\n\t\t\tfiles[key] = value\n\t\t} else {\n\t\t\tnewValues[key] = value\n\t\t}\n\t}\n\n\treturn { values: newValues, files }\n}\n\ninterface BulkAddRequestReturnValue {\n\tsubmissions: Created<FormSubmission>[]\n\tattachments: Created<FormSubmissionAttachment>[]\n\tpresigned_urls: PresignedUrlsResponse\n}\n\nexport abstract class FormSubmissionService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseUploadService<TState, TSDK> {\n\tprivate async bulkAddSubmissionAttachments(\n\t\tsubmissionId: string,\n\t\tfiles: Record<string, File[]>,\n\t): Promise<OptimisticMultipleModelResult<FormSubmissionAttachment>> {\n\t\tinterface AttachmentPayload {\n\t\t\toffline_id: string\n\t\t\tname: string\n\t\t\tsha1: string\n\t\t\tfield_identifier: string\n\t\t\tdesscription?: string\n\t\t}\n\n\t\tconst submittedAt = new Date().toISOString()\n\t\tconst createdBy = this.client.store.getState().userReducer.currentUser.id\n\n\t\tconst filePayloads: Record<FilePayload[\"sha1\"], FilePayload> = {}\n\t\tconst offlineFormSubmissionAttachments: Stored<FormSubmissionAttachment>[] = []\n\t\tconst attachmentPayloads: AttachmentPayload[] = []\n\n\t\tfor (const [fieldIdentifier, filesArray] of Object.entries(files)) {\n\t\t\tfor (const file of filesArray) {\n\t\t\t\tconst sha1 = await hashFile(file)\n\n\t\t\t\tif (!(sha1 in filePayloads)) {\n\t\t\t\t\tfilePayloads[sha1] = {\n\t\t\t\t\t\tsha1,\n\t\t\t\t\t\tfile_type: file.type,\n\t\t\t\t\t\textension: file.name.split(\".\").pop()!,\n\t\t\t\t\t\tsize: file.size,\n\t\t\t\t\t}\n\t\t\t\t\tawait this.client.files.addCache(file, sha1)\n\t\t\t\t}\n\n\t\t\t\tconst offlineFormSubmissionAttachment: Stored<FormSubmissionAttachment> = offline({\n\t\t\t\t\tfile: URL.createObjectURL(file),\n\t\t\t\t\tfile_type: file.type,\n\t\t\t\t\tfile_name: file.name,\n\t\t\t\t\tfile_sha1: sha1,\n\t\t\t\t\tcreated_by: createdBy,\n\t\t\t\t\tsubmission: submissionId,\n\t\t\t\t\tsubmitted_at: submittedAt,\n\t\t\t\t\tfield_identifier: fieldIdentifier,\n\t\t\t\t})\n\t\t\t\tofflineFormSubmissionAttachments.push(offlineFormSubmissionAttachment)\n\n\t\t\t\tconst attachmentPayload: AttachmentPayload = {\n\t\t\t\t\toffline_id: offlineFormSubmissionAttachment.offline_id,\n\t\t\t\t\tname: file.name,\n\t\t\t\t\tsha1,\n\t\t\t\t\tfield_identifier: fieldIdentifier,\n\t\t\t\t}\n\t\t\t\tattachmentPayloads.push(attachmentPayload)\n\t\t\t}\n\t\t}\n\n\t\tthis.dispatch(addFormSubmissionAttachments(offlineFormSubmissionAttachments))\n\n\t\tconst promise = this.enqueueRequest<{\n\t\t\tattachments: Created<FormSubmissionAttachment>[]\n\t\t\tpresigned_urls: PresignedUrlsResponse\n\t\t}>({\n\t\t\tdescription: \"Attach files to form submission\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/forms/submissions/${submissionId}/attachments/bulk/`,\n\t\t\tpayload: {\n\t\t\t\tsubmitted_at: submittedAt,\n\t\t\t\tattachments: attachmentPayloads,\n\t\t\t\tfiles: Object.values(filePayloads),\n\t\t\t},\n\t\t\tblockers: [submissionId],\n\t\t\tblocks: offlineFormSubmissionAttachments.map((attachment) => attachment.offline_id),\n\t\t})\n\n\t\tpromise\n\t\t\t.then((result) => {\n\t\t\t\tthis.processPresignedUrls(result.presigned_urls)\n\t\t\t\tthis.dispatch(updateFormSubmissionAttachments(result.attachments))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(\n\t\t\t\t\tdeleteFormSubmissionAttachments(\n\t\t\t\t\t\tofflineFormSubmissionAttachments.map((attachment) => attachment.offline_id),\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t})\n\n\t\treturn [offlineFormSubmissionAttachments, promise.then(({ attachments }) => attachments)]\n\t}\n\n\tprivate async bulkDeleteSubmissionAttachments(submissionId: string, attachmentsIds: string[]): Promise<void> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst formSubmissionAttachments = selectFormSubmissionAttachemntsByIds(attachmentsIds)(state)\n\n\t\tthis.dispatch(deleteFormSubmissionAttachments(attachmentsIds))\n\n\t\ttry {\n\t\t\tawait this.enqueueRequest<undefined>({\n\t\t\t\tdescription: \"Delete form submission attachments\",\n\t\t\t\tmethod: HttpMethod.DELETE,\n\t\t\t\turl: `/forms/submissions/${submissionId}/attachments/bulk/`,\n\t\t\t\tpayload: { attachments: attachmentsIds },\n\t\t\t\tblockers: [submissionId, ...attachmentsIds],\n\t\t\t\tblocks: [],\n\t\t\t})\n\t\t} catch (e) {\n\t\t\tthis.dispatch(addFormSubmissionAttachments(formSubmissionAttachments))\n\t\t\tthrow e\n\t\t}\n\t}\n\n\t// Outer promise is for hashing and caching files for submission attachments\n\tasync add(\n\t\tpayload: FormSubmissionPayload,\n\t): Promise<\n\t\t[\n\t\t\tStored<FormSubmission>,\n\t\t\tStored<FormSubmissionAttachment>[],\n\t\t\tPromise<Created<FormSubmission>>,\n\t\t\tPromise<Created<FormSubmissionAttachment>[]>,\n\t\t]\n\t> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\t\tconst activeProjectId = state.projectReducer.activeProjectId\n\n\t\tif (!activeProjectId) {\n\t\t\tthrow new Error(\"Expected an active project\")\n\t\t}\n\n\t\tconst { values, files } = separateFilesFromValues(payload.values)\n\n\t\tconst offlineSubmission: Submitted<FormSubmission> = offline({\n\t\t\t...payload,\n\t\t\tvalues: values,\n\t\t\tcreated_by: state.userReducer.currentUser.id,\n\t\t\tsubmitted_at: new Date().toISOString(),\n\t\t})\n\n\t\tconst promise = this.enqueueRequest<FormSubmission>({\n\t\t\tdescription: \"Respond to form\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/forms/revisions/${payload.form_revision}/respond/`,\n\t\t\tpayload: { ...offlineSubmission, project: activeProjectId },\n\t\t\tblockers: [payload.issue, payload.asset, payload.asset_stage, \"add-form-entry\"].filter(\n\t\t\t\t(x) => x !== undefined,\n\t\t\t) as string[],\n\t\t\tblocks: [offlineSubmission.offline_id],\n\t\t})\n\n\t\tthis.dispatch(addFormSubmission(offlineSubmission))\n\n\t\tconst [offlineFormSubmissionAttachments, attachmentsPromise] = await this.bulkAddSubmissionAttachments(\n\t\t\tofflineSubmission.offline_id,\n\t\t\tfiles,\n\t\t)\n\n\t\tpromise\n\t\t\t.then((result) => {\n\t\t\t\tthis.dispatch(addActiveProjectFormSubmissionsCount(1))\n\t\t\t\tthis.dispatch(setFormSubmission(result))\n\t\t\t\treturn result\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(deleteFormSubmission(offlineSubmission.offline_id))\n\t\t\t\tthis.dispatch(addActiveProjectFormSubmissionsCount(-1))\n\t\t\t})\n\n\t\treturn [offlineSubmission, offlineFormSubmissionAttachments, promise, attachmentsPromise]\n\t}\n\n\t// Note currently the bulkAdd method is specific to form submissions for assets\n\t// TODO: adapt the support bulk adding to any model type\n\tasync bulkAdd(\n\t\targs: {\n\t\t\tformRevision: string\n\t\t\tcommonFieldValues: Record<string, FieldValue>\n\t\t\tfieldValuesByAsset: Record<string, Record<string, FieldValue>>\n\t\t},\n\t\tbatchSize: number,\n\t): Promise<Promise<BulkAddRequestReturnValue>[]> {\n\t\tinterface SubmissionPayload {\n\t\t\toffline_id: string\n\t\t\tasset_id: string\n\t\t\tform_data: Record<string, FieldValue>\n\t\t}\n\n\t\tinterface AttachmenPayload {\n\t\t\toffline_id: string\n\t\t\tsubmission_id: string\n\t\t\tsha1: string\n\t\t\tname: string\n\t\t\tfield_identifier: string\n\t\t}\n\n\t\tinterface FilePayload {\n\t\t\tsha1: string\n\t\t\textension: string\n\t\t\tfile_type: string\n\t\t\tsize: number\n\t\t}\n\n\t\tinterface BulkAddPayload {\n\t\t\ttransaction_id: string\n\t\t\tform_data: Record<string, FieldValue>\n\t\t\tsubmitted_at: string\n\t\t\tsubmissions: SubmissionPayload[]\n\t\t\tattachments: AttachmenPayload[]\n\t\t\tfiles: FilePayload[]\n\t\t}\n\n\t\tinterface BulkAddBatch {\n\t\t\tbatchId: string\n\t\t\tpayload: BulkAddPayload\n\t\t}\n\t\t// Things we need to do:\n\t\t// 1. separate any files from the submitted form values\n\t\t// 2. create offline submissions\n\t\t// 3. create offline attachments\n\t\t// 4. deduplicate any files\n\t\tconst { formRevision, commonFieldValues, fieldValuesByAsset } = args\n\n\t\tconst allFilesRecord: Record<string, FilePayload> = {}\n\n\t\tconst { values: fileSeperatedCommonFieldValues, files: commonFiles } =\n\t\t\tseparateFilesFromValues(commonFieldValues)\n\n\t\tconst submittedAt = new Date().toISOString()\n\t\tconst transactionId = uuidv4()\n\n\t\tconst assetIdBatches = chunkArray(Object.keys(fieldValuesByAsset), batchSize)\n\n\t\tconst bulkAddBatches: BulkAddBatch[] = await Promise.all(\n\t\t\tassetIdBatches.map(async (assetIdBatch) => {\n\t\t\t\tconst batchId = uuidv4()\n\t\t\t\tconst submissionPayloads: SubmissionPayload[] = []\n\t\t\t\tconst attachmentPayloads: AttachmenPayload[] = []\n\t\t\t\tconst files: Record<string, File[]> = { ...commonFiles }\n\n\t\t\t\tfor (const assetId of assetIdBatch) {\n\t\t\t\t\tconst { values: fileSeperatedSubmissionSpecificValues, files: submissionSpecificFiles } =\n\t\t\t\t\t\tseparateFilesFromValues(fieldValuesByAsset[assetId] ?? {})\n\n\t\t\t\t\tObject.assign(files, submissionSpecificFiles)\n\n\t\t\t\t\tconst submissionPayload: SubmissionPayload = offline({\n\t\t\t\t\t\tasset_id: assetId,\n\t\t\t\t\t\tform_data: fileSeperatedSubmissionSpecificValues,\n\t\t\t\t\t})\n\n\t\t\t\t\tsubmissionPayloads.push(submissionPayload)\n\n\t\t\t\t\tfor (const [fieldIdentifier, fileArray] of Object.entries(files)) {\n\t\t\t\t\t\tfor (const file of fileArray) {\n\t\t\t\t\t\t\tconst sha1 = await hashFile(file)\n\t\t\t\t\t\t\tawait this.client.files.addCache(file, sha1)\n\n\t\t\t\t\t\t\tconst attachmentPayload: AttachmenPayload = offline({\n\t\t\t\t\t\t\t\tsubmission_id: submissionPayload.offline_id,\n\t\t\t\t\t\t\t\tsha1,\n\t\t\t\t\t\t\t\tname: file.name,\n\t\t\t\t\t\t\t\tfield_identifier: fieldIdentifier,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\tattachmentPayloads.push(attachmentPayload)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst filePaylods: FilePayload[] = []\n\n\t\t\t\tfor (const file of Object.values(files).flat()) {\n\t\t\t\t\tconst sha1 = await hashFile(file)\n\t\t\t\t\tconst filePayload: FilePayload = {\n\t\t\t\t\t\tsha1,\n\t\t\t\t\t\textension: file.name.split(\".\").pop() || \"\",\n\t\t\t\t\t\tfile_type: file.type,\n\t\t\t\t\t\tsize: file.size,\n\t\t\t\t\t}\n\t\t\t\t\tallFilesRecord[sha1] = filePayload\n\t\t\t\t\tfilePaylods.push(filePayload)\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tbatchId,\n\t\t\t\t\tpayload: {\n\t\t\t\t\t\ttransaction_id: transactionId,\n\t\t\t\t\t\tform_data: fileSeperatedCommonFieldValues,\n\t\t\t\t\t\tsubmitted_at: submittedAt,\n\t\t\t\t\t\tsubmissions: submissionPayloads,\n\t\t\t\t\t\tattachments: attachmentPayloads,\n\t\t\t\t\t\tfiles: filePaylods,\n\t\t\t\t\t},\n\t\t\t\t} satisfies BulkAddBatch\n\t\t\t}),\n\t\t)\n\n\t\tconst batchPromises: Promise<BulkAddRequestReturnValue>[] = []\n\t\tlet prevBatchId: string | null = null\n\n\t\tfor (const batch of bulkAddBatches) {\n\t\t\tconst { payload, batchId } = batch\n\n\t\t\tconst batchAssetIds = payload.submissions.map((x) => x.asset_id)\n\t\t\tconst batchSubmissionOfflineIds = payload.submissions.map((x) => x.offline_id)\n\t\t\tconst batchAttachmentsOfflineIds = payload.attachments.map((x) => x.offline_id)\n\n\t\t\tconst blockers = batchAssetIds\n\t\t\tif (prevBatchId) blockers.push(prevBatchId)\n\n\t\t\tconst blocks = [...batchSubmissionOfflineIds, ...batchAttachmentsOfflineIds, batchId]\n\n\t\t\tconst promise = this.enqueueRequest<{\n\t\t\t\tsubmissions: Created<FormSubmission>[]\n\t\t\t\tattachments: Created<FormSubmissionAttachment>[]\n\t\t\t\tpresigned_urls: PresignedUrlsResponse\n\t\t\t}>({\n\t\t\t\tdescription: \"Bulk add form submissions\",\n\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\turl: `/forms/revisions/${formRevision}/bulk-respond/`,\n\t\t\t\tpayload: payload,\n\t\t\t\tblockers: blockers,\n\t\t\t\tblocks: blocks,\n\t\t\t})\n\n\t\t\tvoid promise.then(({ presigned_urls }) => {\n\t\t\t\tthis.processPresignedUrls(presigned_urls)\n\t\t\t})\n\n\t\t\tprevBatchId = batchId\n\n\t\t\tbatchPromises.push(promise)\n\t\t}\n\n\t\t// Only on success of every batch request, add the submissions and attachments to the store\n\t\tvoid Promise.all(batchPromises).then((results) => {\n\t\t\tconst createdSubmissions: Created<FormSubmission>[] = []\n\t\t\tconst createdAttachments: Created<FormSubmissionAttachment>[] = []\n\n\t\t\tfor (const result of results) {\n\t\t\t\tfor (const createdSubmission of result.submissions) createdSubmissions.push(createdSubmission)\n\t\t\t\tfor (const createdAttachment of result.attachments) createdAttachments.push(createdAttachment)\n\t\t\t}\n\n\t\t\tthis.dispatch(addFormSubmissions(createdSubmissions))\n\t\t\tthis.dispatch(addFormSubmissionAttachments(createdAttachments))\n\t\t})\n\n\t\treturn batchPromises\n\t}\n\n\tasync update(\n\t\tpayload: Offline<Partial<Payload<FormSubmission>>>,\n\t): Promise<\n\t\t[\n\t\t\tStored<FormSubmission>,\n\t\t\tStored<FormSubmissionAttachment>[],\n\t\t\tPromise<Created<FormSubmission>>,\n\t\t\tPromise<Created<FormSubmissionAttachment>[]>,\n\t\t\tPromise<void>,\n\t\t]\n\t> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst submissionToBeUpdated = selectFormSubmissionById(payload.offline_id)(state)\n\n\t\tif (!submissionToBeUpdated) {\n\t\t\tthrow new Error(`Expected submission with offline_id ${payload.offline_id} to exist`)\n\t\t}\n\n\t\tconst { values, files } = separateFilesFromValues(payload.values ?? {})\n\n\t\tconst updatedSubmission: Stored<FormSubmission> = {\n\t\t\t...submissionToBeUpdated,\n\t\t\t...payload,\n\t\t\t// values could also have a partial update\n\t\t\tvalues: {\n\t\t\t\t...submissionToBeUpdated.values,\n\t\t\t\t...values,\n\t\t\t},\n\t\t}\n\n\t\tthis.dispatch(updateFormSubmission(updatedSubmission))\n\n\t\tconst promise = this.enqueueRequest<FormSubmission>({\n\t\t\tdescription: \"Delete user form submissions\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/forms/submissions/${updatedSubmission.offline_id}/`,\n\t\t\tpayload: updatedSubmission,\n\t\t\tblockers: [updatedSubmission.offline_id],\n\t\t\tblocks: [updatedSubmission.offline_id],\n\t\t})\n\n\t\tconst formSubmissionAttachments = selectAttachmentsOfFormSubmission(payload.offline_id)(state)!\n\t\tconst formSubmissionAttachmentIdsToBeDeleted: string[] = []\n\n\t\tfor (const attachment of formSubmissionAttachments) {\n\t\t\tif (attachment.field_identifier in files) {\n\t\t\t\tformSubmissionAttachmentIdsToBeDeleted.push(attachment.offline_id)\n\t\t\t}\n\t\t}\n\n\t\tconst [offlineFormSubmissionAttachments, attachmentsPromise] = await this.bulkAddSubmissionAttachments(\n\t\t\tpayload.offline_id,\n\t\t\tfiles,\n\t\t)\n\n\t\tconst deleteAttachmentsPromise = this.bulkDeleteSubmissionAttachments(\n\t\t\tpayload.offline_id,\n\t\t\tformSubmissionAttachmentIdsToBeDeleted,\n\t\t)\n\n\t\tpromise\n\t\t\t.then((result) => {\n\t\t\t\tthis.dispatch(setFormSubmission(result))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(setFormSubmission(submissionToBeUpdated))\n\t\t\t})\n\n\t\treturn [\n\t\t\tupdatedSubmission,\n\t\t\tofflineFormSubmissionAttachments,\n\t\t\tpromise,\n\t\t\tattachmentsPromise,\n\t\t\tdeleteAttachmentsPromise,\n\t\t]\n\t}\n\n\tasync delete(submissionId: string): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst submissionToBeDeleted = selectFormSubmissionById(submissionId)(state)\n\n\t\tif (!submissionToBeDeleted) {\n\t\t\tthrow new Error(`Expected submission with offline_id ${submissionId} to exist`)\n\t\t}\n\n\t\tconst submissionAttachments = selectAttachmentsOfFormSubmission(submissionId)(state)!\n\n\t\tthis.dispatch(deleteFormSubmission(submissionId))\n\t\tthis.dispatch(addActiveProjectFormSubmissionsCount(-1))\n\t\tthis.dispatch(deleteFormSubmissionAttachments(submissionAttachments.map((x) => x.offline_id)))\n\n\t\ttry {\n\t\t\t// REASON: Need to await to trigger the catch block.\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-confusing-void-expression\n\t\t\treturn await this.enqueueRequest<undefined>({\n\t\t\t\tdescription: \"Delete user form submissions\",\n\t\t\t\tmethod: HttpMethod.DELETE,\n\t\t\t\turl: `/forms/submissions/${submissionId}/`,\n\t\t\t\tblockers: [submissionId],\n\t\t\t\tblocks: [],\n\t\t\t})\n\t\t} catch (e) {\n\t\t\tthis.dispatch(addActiveProjectFormSubmissionsCount(1))\n\t\t\tthis.dispatch(addFormSubmission(submissionToBeDeleted))\n\t\t\tthis.dispatch(addFormSubmissionAttachments(submissionAttachments))\n\t\t\tthrow e\n\t\t}\n\t}\n\n\tasync refreshStore(projectId: number): Promise<void> {\n\t\tconst submissions = await this.enqueueRequest<FormSubmission[]>({\n\t\t\tdescription: \"Fetch form submissions\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/forms/in-project/${projectId}/submissions/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tthis.dispatch(initializeFormSubmissions(submissions))\n\n\t\tconst attachments = await this.enqueueRequest<FormSubmissionAttachment[]>({\n\t\t\tdescription: \"Fetch form attachments\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/forms/in-project/${projectId}/attachments/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tthis.dispatch(initializeFormSubmissionAttachments(attachments))\n\t}\n}\n","import { HttpMethod } from \"enums/api\"\nimport { addWorkspace, deleteWorkspace, initializeWorkspaces, updateWorkspace } from \"store/slices/workspaceSlice\"\nimport { Payload } from \"typings/models/base\"\nimport { Workspace } from \"typings/models/workspace\"\nimport { OptimisticModelResult } from \"../typings\"\nimport { offline } from \"utils/offline\"\nimport { OvermapRootState } from \"../../typings\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class WorkspaceService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tadd(workspace: Payload<Workspace>): OptimisticModelResult<Workspace> {\n\t\tconst { store } = this.client\n\t\tconst offlineWorkspace = offline(workspace)\n\t\tthis.dispatch(addWorkspace(offlineWorkspace))\n\t\tconst promise = this.enqueueRequest<Workspace>({\n\t\t\tdescription: \"Create Workspace\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/projects/${store.getState().projectReducer.activeProjectId}/workspaces/`,\n\t\t\tpayload: offlineWorkspace,\n\t\t\tblockers: [\"add-workspace\"],\n\t\t\tblocks: [offlineWorkspace.offline_id],\n\t\t})\n\n\t\tvoid promise\n\t\t\t.then((result) => {\n\t\t\t\tthis.dispatch(updateWorkspace(result))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(deleteWorkspace(offlineWorkspace.offline_id))\n\t\t\t})\n\n\t\treturn [offlineWorkspace, promise]\n\t}\n\n\tupdate(workspace: Workspace): OptimisticModelResult<Workspace> {\n\t\tthis.dispatch(addWorkspace(workspace))\n\t\tconst promise = this.enqueueRequest<Workspace>({\n\t\t\tdescription: \"Update Workspace\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/workspaces/${workspace.offline_id}/`,\n\t\t\tpayload: workspace,\n\t\t\tblockers: [workspace.offline_id],\n\t\t\tblocks: [workspace.offline_id],\n\t\t})\n\n\t\treturn [workspace, promise]\n\t}\n\n\tdelete(workspaceId: string): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst promise = this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Delete Workspace\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/workspaces/${workspaceId}/`,\n\t\t\tblockers: [workspaceId],\n\t\t\tblocks: [],\n\t\t})\n\t\tconst originalWorkspace = store.getState().workspaceReducer.instances[workspaceId]\n\t\tthis.dispatch(deleteWorkspace(workspaceId))\n\t\tvoid promise\n\t\t\t.then(() => {\n\t\t\t\t// After deleting a workspace, we need to fetch the initial data again because workspace indexes will have\n\t\t\t\t// changed.\n\t\t\t\t// TODO: void this.client.main.fetchInitialData(true).then()\n\t\t\t})\n\t\t\t.catch((reason) => {\n\t\t\t\tif (originalWorkspace) {\n\t\t\t\t\tthis.dispatch(addWorkspace(originalWorkspace))\n\t\t\t\t}\n\t\t\t\tthrow reason\n\t\t\t})\n\t\treturn promise\n\t}\n\n\tasync refreshStore(projectId: number): Promise<undefined> {\n\t\tconst result = await this.enqueueRequest<Workspace[]>({\n\t\t\tdescription: \"Get workspaces\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/workspaces/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t\tthis.dispatch(initializeWorkspaces(result))\n\t}\n}\n","import { HttpMethod } from \"../../enums\"\nimport { OrganizationAccess, Created, OvermapRootState } from \"../../typings\"\nimport {\n\tinitializeOrganizationAccesses,\n\tdeleteOrganizationAccess,\n\tremoveUser,\n\tupdateOrganizationAccess,\n} from \"../../store\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\n/**\n * Handles the creation of OrganizationAccess Service\n */\nexport abstract class OrganizationAccessService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tasync update(organizationAccess: OrganizationAccess): Promise<OrganizationAccess> {\n\t\tconst promise = this.enqueueRequest<Created<OrganizationAccess>>({\n\t\t\tdescription: \"Edit organization access\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/organizations/${organizationAccess.organization}/access/${organizationAccess.offline_id}/`,\n\t\t\tpayload: organizationAccess,\n\t\t\tblockers: [organizationAccess.offline_id],\n\t\t\tblocks: [organizationAccess.offline_id],\n\t\t})\n\n\t\tvoid promise.then(() => {\n\t\t\tthis.dispatch(updateOrganizationAccess(organizationAccess))\n\t\t})\n\n\t\treturn promise\n\t}\n\n\tasync remove(organizationAccess: OrganizationAccess): Promise<undefined> {\n\t\tthis.dispatch(deleteOrganizationAccess(organizationAccess.offline_id))\n\t\tthis.dispatch(removeUser(organizationAccess.user))\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Remove organization access\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/organizations/${organizationAccess.organization}/access/${organizationAccess.offline_id}/`,\n\t\t\tblockers: [organizationAccess.offline_id],\n\t\t\tblocks: [],\n\t\t})\n\t}\n\n\tasync refreshStore(organizationId: number): Promise<void> {\n\t\tconst result = await this.enqueueRequest<OrganizationAccess[]>({\n\t\t\tdescription: \"Get organization accesses\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/organizations/${organizationId}/access/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tthis.dispatch(initializeOrganizationAccesses(result))\n\t}\n}\n","import { BaseApiService } from \"./BaseApiService\"\n\n// TODO: add more methods, add error handling, add quota management etc, make it work for any Attachment\n// Goal is to not use more than 80% of quota, as full utilization would stop the Redux offline store from\n// functioning properly as well\nimport { DBSchema, IDBPDatabase, openDB } from \"idb\"\nimport { HttpMethod } from \"enums\"\nimport { fileToBlob, getFileS3Key, getRenamedFile, hashFile } from \"utils\"\nimport { selectUploadUrl, setUploadUrl } from \"store/slices/fileSlice\"\nimport { APIError } from \"../errors\"\nimport { SDKRequest } from \"../typings\"\nimport type { BaseSDK } from \"../base\"\nimport { BaseState } from \"../../typings\"\n\nexport interface GetS3UrlSuccessResponse {\n\turl: string\n\tfields: Record<string, string>\n}\n\ninterface GetS3UrlWarningResponse {\n\twarning: string\n}\n\nexport type GetS3UrlResponse = GetS3UrlSuccessResponse | GetS3UrlWarningResponse\n\ninterface DatabaseFileProperties {\n\tfile_name: string\n\tfile_sha1: string\n\t/** When uploading, this is the s3 key of the file.\n\t * When downloading, this is the s3 public url.\n\t */\n\tfile: string\n}\n\ninterface FileCacheDB extends DBSchema {\n\tfiles: {\n\t\tvalue: File\n\t\tkey: string\n\t}\n}\n\nconst cachedRequestPromises: Record<string, Promise<File> | undefined> = {}\n// Used to minimize writing to the cache.\nconst _cachedKeys = new Set<string>()\n\n// <ANALYTICS>\nlet _filePutCacheHits = 0\nlet _filePutCacheMisses = 0\nlet _totalCount = 0\nconst summarizeEvery = 20\n// </ANALYTICS>\n\nexport abstract class FileService<TState extends BaseState, TSDK extends BaseSDK<TState>> extends BaseApiService<\n\tTState,\n\tTSDK\n> {\n\thost = import.meta.env.REACT_APP_API_URL as string\n\t// NOTE: If you alter the schema (of the IndexedDB database) in any way, you must increment the version in order to\n\t// migrate the store. This allows idb to automatically migrate the user's existing data to the new schema.\n\tprivate _dbPromise = openDB<FileCacheDB>(\"fileCache\", 1, {\n\t\tupgrade(db) {\n\t\t\tdb.createObjectStore(\"files\")\n\t\t},\n\t})\n\n\tprivate async renewUploadUrl(sha1: string): Promise<GetS3UrlResponse> {\n\t\tconst file = await this.fetchCache(sha1)\n\t\tif (!file) throw new Error(`File with sha1 ${sha1} not found in cache`)\n\t\tconst key = await getFileS3Key(file, sha1)\n\n\t\tconst s3UploadUrl = await this.enqueueRequest<GetS3UrlResponse>({\n\t\t\tdescription: \"Get S3 URL\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: \"/authentication/files/presigned-upload-url/\",\n\t\t\tqueryParams: {\n\t\t\t\tsha1: await hashFile(file),\n\t\t\t\tfile_type: file.type,\n\t\t\t\textension: file.name.split(\".\").pop(),\n\t\t\t\tsize: file.size.toString(),\n\t\t\t},\n\t\t\tblockers: [],\n\t\t\tblocks: [`s3-${key}`],\n\t\t})\n\n\t\tif (\"url\" in s3UploadUrl) {\n\t\t\t// TODO: Why save it to the store?\n\t\t\tthis.dispatch(setUploadUrl({ sha1, ...s3UploadUrl }))\n\t\t}\n\t\treturn s3UploadUrl\n\t}\n\n\t/**\n\t * Adds a file to the cache using the sha1 hash as the key and returns the sha1 hash.\n\t * @param file The file to add to the cache\n\t * TODO: This should be removed once the bug described in [1] is fixed.\n\t * @param sha1 The sha1 hash of the file to cache.\n\t */\n\tasync addCache(file: File, sha1: string): Promise<void> {\n\t\tif (_cachedKeys.has(sha1)) {\n\t\t\treturn\n\t\t}\n\t\t// TODO: Check\n\t\tif (!file.type) {\n\t\t\tconst parts = file.name.split(\".\")\n\t\t\tconst extension = parts[parts.length - 1]\n\t\t\tfile = new File([file], file.name, { type: extension })\n\t\t}\n\t\tif (!file.name || !file.size || !file.type) {\n\t\t\tthrow new Error(\"Cannot add files to cache that do not have a name, size and type.\")\n\t\t}\n\t\tconst fileStorage: IDBPDatabase<FileCacheDB> = await this._dbPromise\n\t\t// TODO: Is this an improvement or not?\n\t\tconst alreadyCached = !!(await fileStorage.get(\"files\", sha1))\n\t\tif (!alreadyCached) {\n\t\t\tawait fileStorage.put(\"files\", file, sha1)\n\t\t\t_filePutCacheMisses++\n\t\t} else {\n\t\t\tconsole.error(\"File already cached (this is unexpected at this point):\", file.name, sha1)\n\t\t\t_filePutCacheHits++\n\t\t}\n\t\t_cachedKeys.add(sha1)\n\t\t_totalCount++\n\t\tif (_totalCount % summarizeEvery === 0) {\n\t\t\t// TODO: If this ends up hitting the console more often than not, they `alreadyCached` check might be more\n\t\t\t// performant than overwriting the identical file in the database. Because all file names saved are based\n\t\t\t// on the sha1 hash, we can guarantee that the files are identical, so there is no point in overwriting.\n\t\t\tconsole.debug(\n\t\t\t\t\"File cache summary: \" +\n\t\t\t\t\t`${_filePutCacheHits} hits and ${_filePutCacheMisses} misses, ` +\n\t\t\t\t\t`${(_filePutCacheHits / (_filePutCacheHits + _filePutCacheMisses)) * 100}% hit rate over ` +\n\t\t\t\t\t`${_totalCount} calls to addCache.`,\n\t\t\t)\n\t\t}\n\t}\n\n\tasync removeCache(sha1: string): Promise<void> {\n\t\tawait (await this._dbPromise).delete(\"files\", sha1)\n\t\t_cachedKeys.delete(sha1)\n\t}\n\n\tasync fetchCache(sha1: string): Promise<File | undefined> {\n\t\treturn (await this._dbPromise).get(\"files\", sha1)\n\t}\n\n\tasync getOrRenewUploadUrl(sha1: string): Promise<GetS3UrlResponse> {\n\t\tconst state = this.client.store.getState()\n\t\tconst uploadUrl = selectUploadUrl(sha1)(state)\n\n\t\treturn uploadUrl ?? (await this.renewUploadUrl(sha1))\n\t}\n\n\t/** Ensure the file has been added to the file cache before calling `uploadFileToS3()` */\n\tasync uploadFileToS3(sha1: string): Promise<[DatabaseFileProperties, Promise<undefined>]> {\n\t\tconst file = await this.fetchCache(sha1)\n\n\t\tif (!file) throw new Error(`File with sha1 ${sha1} not found in cache`)\n\n\t\tconst key = await getFileS3Key(file, sha1)\n\t\tconst dbFileProperties: DatabaseFileProperties = {\n\t\t\tfile_name: file.name,\n\t\t\tfile_sha1: sha1,\n\t\t\tfile: key,\n\t\t}\n\t\tconst fileUploadUrlResponse: GetS3UrlResponse = await this.getOrRenewUploadUrl(sha1)\n\n\t\tif (\"warning\" in fileUploadUrlResponse) {\n\t\t\tif (fileUploadUrlResponse.warning === \"already_uploaded\") {\n\t\t\t\treturn [dbFileProperties, Promise.resolve(undefined).then()]\n\t\t\t}\n\t\t\tthrow new Error(fileUploadUrlResponse.warning)\n\t\t}\n\n\t\tconst url = fileUploadUrlResponse.url\n\t\tconst promise = this.enqueueRequest<undefined>({\n\t\t\turl,\n\t\t\tdescription: \"Upload file\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\tisExternalUrl: true,\n\t\t\tisAuthNeeded: false,\n\t\t\tattachmentHash: sha1,\n\t\t\tblockers: [`s3-${key}`],\n\t\t\tblocks: [sha1],\n\t\t\ts3url: fileUploadUrlResponse,\n\t\t} satisfies SDKRequest)\n\n\t\treturn [dbFileProperties, promise]\n\t}\n\n\t/**\n\t * Fetches a file based on its URL and SHA1. SHA1 values should be known ahead of time because the SHA1 and URL of\n\t * any file is stored in a FileModelMixin (see backend). If the expected SHA1 doesn't match the actual SHA1 of the\n\t * file, an error will be thrown.\n\t * @param url The URL from which to get the file.\n\t * @param expectedSha1 The expected SHA1 of the file. If this doesn't match the actual SHA1 of the file, an error\n\t * will be thrown.\n\t * @param downloadedName (Optional) The name to give the file after download. Set to the name of an attachment, for\n\t * example.\n\t */\n\tasync fetchFileFromUrl(url: string, expectedSha1: string, downloadedName?: string | undefined): Promise<File> {\n\t\tconst requestCacheKey: string = url.split(\"?\")[0] ?? url\n\n\t\tconst cachedResult = await this.fetchCache(expectedSha1)\n\n\t\tif (cachedResult) {\n\t\t\tif (!cachedResult.name) {\n\t\t\t\tthrow new Error(\"Cached file unexpectedly has no name.\")\n\t\t\t}\n\t\t\treturn cachedResult\n\t\t}\n\n\t\tif (url.startsWith(\"blob:\")) {\n\t\t\tconst blob = await fileToBlob(url)\n\t\t\tconst file = new File([blob], downloadedName ?? expectedSha1, { type: blob.type })\n\t\t\tawait this.addCache(file, expectedSha1)\n\t\t\treturn file\n\t\t}\n\n\t\tlet promise = cachedRequestPromises[requestCacheKey]\n\t\tlet isFirstRequest = true\n\n\t\tif (!promise) {\n\t\t\tpromise = new Promise((resolve) => {\n\t\t\t\tvoid this.enqueueRequest<Blob>({\n\t\t\t\t\tdescription: \"Download file\",\n\t\t\t\t\tmethod: HttpMethod.GET,\n\t\t\t\t\turl,\n\t\t\t\t\t// If in development, we should assume the files are saved at localhost by the Django development server.\n\t\t\t\t\t// Setting this to true will lead to localhost:8000 being prepended to the URL.\n\t\t\t\t\tisExternalUrl: import.meta.env.PROD || url.startsWith(\"https://\"),\n\t\t\t\t\tisResponseBlob: true,\n\t\t\t\t\tisAuthNeeded: false,\n\t\t\t\t\tblockers: [expectedSha1],\n\t\t\t\t\tblocks: [expectedSha1],\n\t\t\t\t}).then((blob) => {\n\t\t\t\t\tconst blobToFile = new File([blob], downloadedName ?? expectedSha1, { type: blob.type })\n\t\t\t\t\tresolve(blobToFile)\n\t\t\t\t})\n\t\t\t})\n\t\t\tcachedRequestPromises[requestCacheKey] = promise\n\t\t} else {\n\t\t\tisFirstRequest = false\n\t\t}\n\n\t\tlet file: File\n\n\t\ttry {\n\t\t\tfile = await promise\n\t\t} catch (e) {\n\t\t\tif (isFirstRequest && e instanceof APIError) {\n\t\t\t\t// Don't cache failed promises\n\t\t\t\tdelete cachedRequestPromises[requestCacheKey]\n\t\t\t}\n\t\t\tthrow e\n\t\t}\n\n\t\tif (isFirstRequest) {\n\t\t\t// The first request for this image (in case there are concurrent ones) has the responsibility to cache the\n\t\t\t// file itself.\n\t\t\tconst actualSha1 = await hashFile(file)\n\t\t\tif (actualSha1 !== expectedSha1) {\n\t\t\t\tconst message = `The hash of the file returned from the server (${actualSha1}) does not match the \n\t\t\t\t\texpected hash (${expectedSha1}). This can happen if you're using a local development server and the \n\t\t\t\t\tisExternalUrl flag in the request details is set to true, because instead of requesting the local\n\t\t\t\t\tREST API, you will be requesting localhost:80 (where this app runs), resulting in a transformed blob\n\t\t\t\t\t(with an offline_id attached) being returned. Alternatively, you may be running with \n\t\t\t\t\timport.meta.env.PROD, which will result in some file requests being treated as\n\t\t\t\t\texternal URLs and therefore not prepended with VITE_API_URL.`\n\n\t\t\t\tthrow new Error(message)\n\t\t\t}\n\t\t\t// All files need a name. Otherwise, they might end up with duplicated keys in the PrimeReact FileUpload\n\t\t\t// asset (it uses the name, size and type as the key).\n\t\t\tconst extension = file.type.split(\"/\")[1]\n\t\t\tif (!extension) {\n\t\t\t\tthrow new Error(\"File has no extension\")\n\t\t\t}\n\t\t\tconst fileName = downloadedName ?? actualSha1 + \".\" + extension\n\n\t\t\tfile = getRenamedFile(file, fileName)\n\n\t\t\tif (!file.name) {\n\t\t\t\tthrow new Error(\"Failed to set file's name\")\n\t\t\t}\n\n\t\t\tawait this.addCache(file, actualSha1)\n\n\t\t\t// Overwrite the cached promise, so it returns the renamed file\n\t\t\tcachedRequestPromises[requestCacheKey] = new Promise((resolve) => {\n\t\t\t\tresolve(file)\n\t\t\t})\n\t\t}\n\n\t\treturn file\n\t}\n}\n","import { HttpMethod } from \"../../enums\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\nimport { EmailVerificationPayload, EmailVerificationReturn, OvermapRootState, VerificationCode } from \"../../typings\"\n\nexport abstract class EmailVerificationService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tasync getVerificationCode(verificationCode: string): Promise<VerificationCode> {\n\t\treturn this.enqueueRequest<VerificationCode>({\n\t\t\tdescription: \"Get verification code\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/verification/email-verification/${verificationCode}/`,\n\t\t\tisAuthNeeded: false,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t}\n\n\tvalidateVerificationCode(\n\t\tverificationCode: string,\n\t\tpayload: EmailVerificationPayload | undefined = undefined,\n\t): Promise<EmailVerificationReturn> {\n\t\treturn this.enqueueRequest<EmailVerificationReturn>({\n\t\t\tdescription: \"Validate verification code\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/verification/email-verification/${verificationCode}/`,\n\t\t\tisAuthNeeded: false,\n\t\t\tpayload,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t}\n}\n","import { HttpMethod } from \"../../enums\"\nimport { initializeEmailDomains, deleteEmailDomain, addEmailDomain } from \"../../store\"\nimport { EmailDomain, OvermapRootState } from \"../../typings\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class EmailDomainsService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tasync add(orgId: number, email: string): Promise<undefined> {\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Add email domain to organization\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/organizations/${orgId}/email-domains/`,\n\t\t\tpayload: { email },\n\t\t\tblockers: [orgId.toString(), \"create-org\"],\n\t\t\tblocks: [],\n\t\t})\n\t}\n\n\tasync remove(emailDomain: EmailDomain): Promise<undefined> {\n\t\tthis.dispatch(deleteEmailDomain(emailDomain.offline_id))\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Remove email domain from organization\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/organizations/${emailDomain.organization}/email-domains/${emailDomain.offline_id}/`,\n\t\t\tblockers: [emailDomain.domain],\n\t\t\tblocks: [],\n\t\t}).catch((e) => {\n\t\t\tthis.dispatch(addEmailDomain(emailDomain))\n\t\t\tthrow e\n\t\t})\n\t}\n\n\tasync refreshStore(organizationId: number): Promise<undefined> {\n\t\tconst result = await this.enqueueRequest<EmailDomain[]>({\n\t\t\tdescription: \"Fetch email domains for organization\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/organizations/${organizationId}/email-domains/`,\n\t\t\tblockers: [organizationId.toString()],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tthis.dispatch(initializeEmailDomains(result))\n\t}\n}\n","import { Organization, OvermapRootState } from \"../../typings\"\nimport { HttpMethod } from \"../../enums\"\nimport { setOrganizations } from \"../../store\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class OrganizationService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tcreate(name: string): Promise<Organization> {\n\t\treturn this.enqueueRequest<Organization>({\n\t\t\tdescription: \"Create organization\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: \"/organizations/\",\n\t\t\tpayload: { name },\n\t\t\tblockers: [],\n\t\t\tblocks: [`add-org-${name}`, \"create-org\"],\n\t\t})\n\t}\n\n\tasync update(organization: Organization): Promise<Organization> {\n\t\treturn this.enqueueRequest<Organization>({\n\t\t\tdescription: \"Edit organization\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/organizations/${organization.id}/`,\n\t\t\tpayload: organization,\n\t\t\tblockers: [`add-org-${organization.name}`, organization.id.toString()],\n\t\t\tblocks: [organization.id.toString()],\n\t\t})\n\t}\n\n\tasync invite(organizationId: number, email: string): Promise<undefined> {\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Invite user to organization\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/organizations/${organizationId}/invite/${email}/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t}\n\n\tasync refreshStore(projectId: number, organizationId: number): Promise<void> {\n\t\tconst organizationsRecord: Record<number, Organization> = {}\n\n\t\tconst projectOrganizations = await this.enqueueRequest<Organization[]>({\n\t\t\tdescription: \"Get organizations\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/organizations/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tfor (const organization of projectOrganizations) {\n\t\t\torganizationsRecord[organization.id] = organization\n\t\t}\n\n\t\tconst organization = await this.enqueueRequest<Organization>({\n\t\t\tdescription: \"Get organization\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/organizations/${organizationId}/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\torganizationsRecord[organization.id] = organization\n\n\t\tthis.dispatch(setOrganizations(Object.values(organizationsRecord)))\n\t}\n}\n","import { License, OvermapRootState, Project, Transaction } from \"../../typings\"\nimport { HttpMethod } from \"../../enums\"\nimport { initializeLicences, updateLicense } from \"../../store\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class LicenseService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tasync getLicense(license: License): Promise<License> {\n\t\tconst result = await this.enqueueRequest<License>({\n\t\t\tdescription: \"Get license\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/billing/${license.offline_id}/`,\n\t\t\tisAuthNeeded: true,\n\t\t\tblockers: [\n\t\t\t\tlicense.organization_owner\n\t\t\t\t\t? license.organization_owner.toString()\n\t\t\t\t\t: license.user_owner\n\t\t\t\t\t? license.user_owner.toString()\n\t\t\t\t\t: \"\",\n\t\t\t],\n\t\t\tblocks: [],\n\t\t})\n\t\tthis.dispatch(updateLicense(result))\n\t\treturn result\n\t}\n\n\tasync pauseLicense(license: License): Promise<License> {\n\t\tconst result = await this.enqueueRequest<License>({\n\t\t\tdescription: \"Pause license\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/billing/${license.offline_id}/suspend/`,\n\t\t\tisAuthNeeded: true,\n\t\t\tblockers: [\n\t\t\t\tlicense.organization_owner\n\t\t\t\t\t? license.organization_owner.toString()\n\t\t\t\t\t: license.user_owner\n\t\t\t\t\t? license.user_owner.toString()\n\t\t\t\t\t: \"\",\n\t\t\t],\n\t\t\tblocks: [],\n\t\t})\n\t\tthis.dispatch(updateLicense(result))\n\t\treturn result\n\t}\n\tasync resumeLicense(license: License): Promise<License> {\n\t\tconst result = await this.enqueueRequest<License>({\n\t\t\tdescription: \"Resume license\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/billing/${license.offline_id}/suspend/`,\n\t\t\tisAuthNeeded: true,\n\t\t\tblockers: [\n\t\t\t\tlicense.organization_owner\n\t\t\t\t\t? license.organization_owner.toString()\n\t\t\t\t\t: license.user_owner\n\t\t\t\t\t? license.user_owner.toString()\n\t\t\t\t\t: \"\",\n\t\t\t],\n\t\t\tblocks: [],\n\t\t})\n\t\tthis.dispatch(updateLicense(result))\n\t\treturn result\n\t}\n\n\tasync cancelLicense(license: License): Promise<License> {\n\t\tconst result = await this.enqueueRequest<License>({\n\t\t\tdescription: \"Cancel license\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/billing/${license.offline_id}/`,\n\t\t\tisAuthNeeded: true,\n\t\t\tblockers: [\n\t\t\t\tlicense.organization_owner\n\t\t\t\t\t? license.organization_owner.toString()\n\t\t\t\t\t: license.user_owner\n\t\t\t\t\t? license.user_owner.toString()\n\t\t\t\t\t: \"\",\n\t\t\t],\n\t\t\tblocks: [],\n\t\t})\n\t\tthis.dispatch(updateLicense(result))\n\t\treturn result\n\t}\n\n\tasync attachLicenseToProject(license: License, project: Project): Promise<License> {\n\t\tconst result = await this.enqueueRequest<License>({\n\t\t\tdescription: \"Attach license\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/billing/${license.offline_id}/project/`,\n\t\t\tisAuthNeeded: true,\n\t\t\tpayload: { project: project.id },\n\t\t\tblockers: [\n\t\t\t\tlicense.organization_owner\n\t\t\t\t\t? license.organization_owner.toString()\n\t\t\t\t\t: license.user_owner\n\t\t\t\t\t? license.user_owner.toString()\n\t\t\t\t\t: \"\",\n\t\t\t\tproject.id ? project.id.toString() : \"\",\n\t\t\t],\n\t\t\tblocks: [\"add-issue\", \"add-form-entry\", \"change-access-level\", \"add-workspace\"],\n\t\t})\n\t\tthis.dispatch(updateLicense(result))\n\t\treturn result\n\t}\n\n\tasync detachLicenseFromProject(license: License): Promise<License> {\n\t\tconst result = await this.enqueueRequest<License>({\n\t\t\tdescription: \"Detach license\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/billing/${license.offline_id}/project/`,\n\t\t\tisAuthNeeded: true,\n\t\t\tblockers: [\n\t\t\t\tlicense.organization_owner\n\t\t\t\t\t? license.organization_owner.toString()\n\t\t\t\t\t: license.user_owner\n\t\t\t\t\t? license.user_owner.toString()\n\t\t\t\t\t: \"\",\n\t\t\t],\n\t\t\tblocks: [\"add-issue\", \"add-form-entry\", \"change-access-level\", \"add-workspace\"],\n\t\t})\n\t\tthis.dispatch(updateLicense(result))\n\t\treturn result\n\t}\n\n\tasync getLatestTransaction(license: License): Promise<Transaction> {\n\t\treturn await this.enqueueRequest<Transaction>({\n\t\t\tdescription: \"Get latest transaction\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/billing/${license.offline_id}/transaction/`,\n\t\t\tisAuthNeeded: true,\n\t\t\tblockers: [license.offline_id],\n\t\t\tblocks: [license.offline_id],\n\t\t})\n\t}\n\n\tasync refreshStore(projectId: number, organizationId: number): Promise<void> {\n\t\tconst licencesRecord: Record<string, License> = {}\n\n\t\tconst organizationLicences = await this.enqueueRequest<License[]>({\n\t\t\tdescription: \"Get licenses\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/organizations/${organizationId}/licenses/`,\n\t\t\tisAuthNeeded: true,\n\t\t\tblockers: [organizationId.toString()],\n\t\t\tblocks: [\"add-issue\", \"add-form-entry\", \"change-access-level\", \"add-workspace\"],\n\t\t})\n\n\t\tfor (const license of organizationLicences) {\n\t\t\tlicencesRecord[license.offline_id] = license\n\t\t}\n\n\t\tconst projectLicences = await this.enqueueRequest<License[]>({\n\t\t\tdescription: \"Get licenses\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/licenses/`,\n\t\t\tisAuthNeeded: true,\n\t\t\tblockers: [projectId.toString()],\n\t\t\tblocks: [\"add-issue\", \"add-form-entry\", \"change-access-level\", \"add-workspace\"],\n\t\t})\n\n\t\tfor (const license of projectLicences) {\n\t\t\tlicencesRecord[license.offline_id] = license\n\t\t}\n\n\t\tthis.dispatch(initializeLicences(Object.values(licencesRecord)))\n\t}\n}\n","import { HttpMethod } from \"../../enums\"\nimport {\n\taddDocuments,\n\tmoveDocument,\n\tremoveDocuments,\n\tselectDocumentsMapping,\n\tsetDocuments,\n\tupdateDocuments,\n} from \"../../store\"\nimport { Document, DocumentPayload, MovePosition, OvermapRootState, Stored, Submitted } from \"../../typings\"\nimport { OptimisticModelResult } from \"../typings\"\nimport { offline } from \"../../utils\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class DocumentService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tadd(payload: DocumentPayload): OptimisticModelResult<Document> {\n\t\tconst { store } = this.client\n\t\tconst currentUserId = store.getState().userReducer.currentUser.id\n\t\tconst submittedAt = new Date().toISOString()\n\n\t\tconst offlineDocument: Stored<Document> = offline({\n\t\t\t...payload,\n\t\t\tcreated_by: currentUserId,\n\t\t\tsubmitted_at: submittedAt,\n\t\t})\n\n\t\tthis.dispatch(addDocuments([offlineDocument]))\n\t\tconst promise = this.enqueueRequest<Document>({\n\t\t\tdescription: \"Create Document\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: \"/documents/\",\n\t\t\tpayload: offlineDocument,\n\t\t\tqueryParams: {\n\t\t\t\tparent_document: offlineDocument.parent_document ?? undefined,\n\t\t\t},\n\t\t\t// if adding as a child of another document, need that document to exist first\n\t\t\tblockers: offlineDocument.parent_document ? [offlineDocument.parent_document] : [],\n\t\t\tblocks: [offlineDocument.offline_id],\n\t\t})\n\n\t\tpromise.catch(() => {\n\t\t\tthis.dispatch(removeDocuments([offlineDocument.offline_id]))\n\t\t})\n\n\t\treturn [offlineDocument, promise]\n\t}\n\n\tupdate(document: Submitted<Partial<Document>>): OptimisticModelResult<Document> {\n\t\tconst { store } = this.client\n\t\tconst documentToBeUpdated = store.getState().documentsReducer.documents[document.offline_id]\n\t\tif (!documentToBeUpdated) {\n\t\t\tthrow new Error(\n\t\t\t\t`attempting to update a document with offline_id ${document.offline_id} that does not exist in store.documents`,\n\t\t\t)\n\t\t}\n\t\tthis.dispatch(updateDocuments([document]))\n\t\tconst promise = this.enqueueRequest<Document>({\n\t\t\tdescription: \"Update Document\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/documents/${document.offline_id}/`,\n\t\t\tpayload: document,\n\t\t\tblockers: [document.offline_id],\n\t\t\tblocks: [document.offline_id],\n\t\t})\n\n\t\tpromise.catch(() => {\n\t\t\tupdateDocuments([documentToBeUpdated])\n\t\t})\n\n\t\tconst fullDocument = store.getState().documentsReducer.documents[document.offline_id]!\n\n\t\treturn [fullDocument, promise]\n\t}\n\n\tmove(documentId: string, targetDocumentId: string | null, position: MovePosition): Promise<Document[]> {\n\t\tconst { store } = this.client\n\t\tconst documentsMapping = selectDocumentsMapping(store.getState())\n\t\t/** the documents that need to be reverted if the move operation fails are:\n\t\t * 1. the document itself (could have attempted to change parents, changing to parent_document property)\n\t\t * 2. the parent of the document (the document could have been moved to a different parent, changing the old parents children_documents property)\n\t\t * 3. the target document (could have been the desired new parent document, changing the children_documents property)\n\t\t * 4. the parent of the target document (could have been the desired new parent document, changing the children_documents property) */\n\t\tconst documentsToRevertIfMoveFails: Document[] = []\n\n\t\tconst documentBeingMoved = documentsMapping[documentId]\n\t\tif (!documentBeingMoved) {\n\t\t\tthrow new Error(\n\t\t\t\t`attempting to move a document with offline_id ${documentId} that does not exist in store.documents`,\n\t\t\t)\n\t\t}\n\t\tdocumentsToRevertIfMoveFails.push(documentBeingMoved)\n\n\t\tif (documentBeingMoved.parent_document) {\n\t\t\tdocumentsToRevertIfMoveFails.push(documentsMapping[documentBeingMoved.parent_document]!)\n\t\t}\n\n\t\tif (targetDocumentId) {\n\t\t\tconst targetDocument = documentsMapping[targetDocumentId]\n\t\t\tif (!targetDocument) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`attempting to move a document to target with offline_id ${targetDocumentId} that does not exist in store.documents`,\n\t\t\t\t)\n\t\t\t}\n\t\t\tdocumentsToRevertIfMoveFails.push(targetDocument)\n\n\t\t\tif (targetDocument.parent_document) {\n\t\t\t\tdocumentsToRevertIfMoveFails.push(documentsMapping[targetDocument.parent_document]!)\n\t\t\t}\n\t\t}\n\n\t\tthis.dispatch(moveDocument({ documentId, targetDocumentId, position }))\n\n\t\tconst promise = this.enqueueRequest<Document[]>({\n\t\t\tdescription: \"Move Document\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/documents/${documentId}/move/`,\n\t\t\tqueryParams: {\n\t\t\t\ttarget: targetDocumentId ?? undefined,\n\t\t\t\tposition,\n\t\t\t},\n\t\t\tblockers: [documentId],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tpromise\n\t\t\t.then((result) => {\n\t\t\t\tthis.dispatch(updateDocuments(result))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(updateDocuments(documentsToRevertIfMoveFails))\n\t\t\t})\n\n\t\treturn promise\n\t}\n\n\tdelete(documentId: string): Promise<Document[]> {\n\t\tconst { store } = this.client\n\t\tconst documentsMapping = selectDocumentsMapping(store.getState())\n\t\tconst documentToBeDeleted = documentsMapping[documentId]\n\t\tif (!documentToBeDeleted) {\n\t\t\tthrow new Error(\n\t\t\t\t`attempting to delete a document with offline_id ${documentId} that does not exist in store.documents`,\n\t\t\t)\n\t\t}\n\t\tconst parentDocument = documentToBeDeleted.parent_document\n\t\t\t? documentsMapping[documentToBeDeleted.parent_document]\n\t\t\t: undefined\n\n\t\tthis.dispatch(removeDocuments([documentId]))\n\t\tconst promise = this.enqueueRequest<Document[]>({\n\t\t\tdescription: \"Delete Document\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/documents/${documentId}/`,\n\t\t\tblockers: [documentId],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tpromise\n\t\t\t.then((documentsToUpdate) => {\n\t\t\t\tthis.dispatch(updateDocuments(documentsToUpdate))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(updateDocuments([documentToBeDeleted]))\n\t\t\t\tif (parentDocument) {\n\t\t\t\t\tthis.dispatch(updateDocuments([parentDocument]))\n\t\t\t\t}\n\t\t\t})\n\n\t\treturn promise\n\t}\n\n\tasync refreshStore(projectId: number, organizationId: number): Promise<void> {\n\t\t// NOTE: below fetches are guaranteed to not have any common documents between them since documents are owned exclusively by either a project or an organization\n\n\t\tconst projectDocumentsPromise = this.enqueueRequest<Document[]>({\n\t\t\tdescription: \"Get project documents\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/documents/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tconst organizationDocumentsPromise = this.enqueueRequest<Document[]>({\n\t\t\tdescription: \"Get organization documents\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/organizations/${organizationId}/documents/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\t// Load project documents first because they are more likely to be seen\n\t\tthis.dispatch(setDocuments(await projectDocumentsPromise))\n\n\t\t// Load organization documents\n\t\tthis.dispatch(addDocuments(await organizationDocumentsPromise))\n\t}\n}\n","import { BaseAttachmentService, BuildOfflineAttachmentData } from \"./BaseAttachmentService\"\nimport {\n\taddDocumentAttachments,\n\tdeleteDocumentAttachment,\n\tdeleteDocumentAttachments,\n\tinitializeDocumentAttachments,\n\tselectDocumentAttachment,\n\tsetDocumentAttachment,\n\tupdateDocumentAttachments,\n} from \"../../store\"\nimport { AttachmentModel, Created, DocumentAttachment, OvermapRootState, Stored } from \"../../typings\"\nimport { offline } from \"../../utils\"\nimport { OptimisticMultipleModelResult } from \"../typings\"\nimport type { BaseSDK } from \"../base\"\nimport { HttpMethod } from \"../../enums\"\n\nexport abstract class DocumentAttachmentService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseAttachmentService<TState, TSDK, string, DocumentAttachment> {\n\tattachmentModel = AttachmentModel.Document\n\n\tinitializeAttachments = initializeDocumentAttachments\n\taddAttachments = addDocumentAttachments\n\tupdateAttachments = updateDocumentAttachments\n\tremoveAttachments = deleteDocumentAttachments\n\tremoveAttachment = deleteDocumentAttachment\n\tsetAttachment = setDocumentAttachment\n\n\tselectAttachment = selectDocumentAttachment\n\n\tprivate buildOfflineAttachment(data: BuildOfflineAttachmentData<string>) {\n\t\treturn offline({\n\t\t\tfile: URL.createObjectURL(data.file),\n\t\t\tfile_sha1: data.sha1,\n\t\t\tcreated_by: data.createdBy,\n\t\t\tfile_name: data.file.name,\n\t\t\tfile_type: data.file.type,\n\t\t\tsubmitted_at: data.submittedAt,\n\t\t\tdescription: data.description,\n\t\t\tdocument: data.modelId,\n\t\t}) satisfies Stored<DocumentAttachment>\n\t}\n\n\tasync attachFilesToDocument(\n\t\tfiles: File[],\n\t\tdocumentId: string,\n\t): Promise<OptimisticMultipleModelResult<DocumentAttachment>> {\n\t\treturn this.attachFiles(files, documentId, this.buildOfflineAttachment.bind(this))\n\t}\n\n\tasync deleteDocumentAttachment(attachmentId: string): Promise<void> {\n\t\treturn this.deleteAttachment(attachmentId)\n\t}\n\n\toverride async refreshStore(projectId: number, organizationId: number): Promise<void> {\n\t\tconst projectDocumentAttachments = await this.enqueueRequest<Created<DocumentAttachment>[]>({\n\t\t\tdescription: \"Get document attachments\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/document-attachments/`,\n\t\t\tblocks: [],\n\t\t\tblockers: [],\n\t\t})\n\n\t\tthis.dispatch(this.initializeAttachments(projectDocumentAttachments))\n\n\t\tconst organizationDocumentAttachments = await this.enqueueRequest<Created<DocumentAttachment>[]>({\n\t\t\tdescription: \"Get document attachments\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/organizations/${organizationId}/document-attachments/`,\n\t\t\tblocks: [],\n\t\t\tblockers: [],\n\t\t})\n\n\t\tthis.dispatch(this.addAttachments(organizationDocumentAttachments))\n\t}\n}\n","import { AgentUserConversation, OvermapRootState } from \"../../typings\"\nimport { HttpMethod } from \"../../enums\"\nimport { addConversation, setConversation, initializeConversations, updateConversation } from \"../../store\"\nimport { JSONContent } from \"@tiptap/core\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class AgentService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tasync startConversation(prompt: string): Promise<AgentUserConversation> {\n\t\tconst activeProjectId = this.client.store.getState().projectReducer.activeProjectId\n\t\treturn this.enqueueRequest<AgentUserConversation>({\n\t\t\tdescription: \"Start agent conversation\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: \"/agents/prompt/\",\n\t\t\tpayload: {\n\t\t\t\tprompt,\n\t\t\t\tactive_project: activeProjectId,\n\t\t\t},\n\t\t\tblockers: [\"prompt\"],\n\t\t\tblocks: [\"prompt\"],\n\t\t}).then((response) => {\n\t\t\tthis.dispatch(addConversation(response))\n\t\t\treturn response\n\t\t})\n\t}\n\n\t/**\n\t * Prompt the agent with a message.\n\t * @param prompt The message to prompt the agent with.\n\t * @param conversationId If continuing an existing message, the UUID of that conversation.\n\t */\n\tasync continueConversation(prompt: string, conversationId: AgentUserConversation[\"offline_id\"]): Promise<void> {\n\t\tconst { store } = this.client\n\t\tconst activeProjectId = store.getState().projectReducer.activeProjectId\n\n\t\treturn this.enqueueRequest<JSONContent[]>({\n\t\t\tdescription: \"Prompt agent\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: \"/agents/prompt/\",\n\t\t\tpayload: {\n\t\t\t\tprompt: prompt,\n\t\t\t\tactive_project: activeProjectId,\n\t\t\t},\n\t\t\tblockers: [\"prompt\"],\n\t\t\tblocks: [\"prompt\"],\n\t\t\tqueryParams: { conversation_id: conversationId },\n\t\t}).then((response) => {\n\t\t\tconst conversation = store.getState().agentsReducer.instances[conversationId]\n\t\t\tif (!conversation?.offline_id) {\n\t\t\t\tthrow new Error(\"Conversation not found\")\n\t\t\t}\n\t\t\tif (!Array.isArray(response)) {\n\t\t\t\tresponse = [response]\n\t\t\t}\n\t\t\tthis.dispatch(\n\t\t\t\tupdateConversation({\n\t\t\t\t\t...conversation,\n\t\t\t\t\ttiptap_content: [...(conversation.tiptap_content || []), ...response],\n\t\t\t\t}),\n\t\t\t)\n\t\t})\n\t}\n\n\tasync fetchDetails(conversationId: AgentUserConversation[\"offline_id\"]): Promise<void> {\n\t\treturn this.enqueueRequest<AgentUserConversation>({\n\t\t\tdescription: \"Get agent conversation\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/agents/conversations/${conversationId}/`,\n\t\t\tblockers: [\"conversation\"],\n\t\t\tblocks: [\"conversation\"],\n\t\t}).then((response) => {\n\t\t\tthis.dispatch(setConversation(response))\n\t\t})\n\t}\n\n\tasync rate(responseId: string, rating: 1 | 5): Promise<undefined> {\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Rate agent response\",\n\t\t\tmethod: HttpMethod.PUT,\n\t\t\turl: `/agents/responses/${responseId}/rate/`,\n\t\t\tpayload: { rating },\n\t\t\tblockers: [\"rate\"],\n\t\t\tblocks: [\"rate\"],\n\t\t})\n\t}\n\n\tasync refreshStore(projectId: number): Promise<void> {\n\t\tconst result = await this.enqueueRequest<AgentUserConversation[]>({\n\t\t\tdescription: \"Get agent conversation history\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/agent-conversations/`,\n\t\t\tblockers: [\"agent-conversations\"],\n\t\t\tblocks: [\"agent-conversations\"],\n\t\t})\n\t\tthis.dispatch(initializeConversations(result))\n\t}\n}\n","import { OvermapRootState, Stored, Submitted, Team, TeamPayload, User } from \"../../typings\"\nimport { OptimisticModelResult } from \"../typings\"\nimport { offline } from \"../../utils\"\nimport { addTeam, deleteTeam, selectTeamById, setTeam, initializeTeams, updateTeam } from \"../../store\"\nimport { HttpMethod } from \"../../enums\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class TeamService<TState extends OvermapRootState, TSDK extends BaseSDK<TState>> extends BaseApiService<\n\tTState,\n\tTSDK\n> {\n\tadd(teamPayload: TeamPayload, organizationId: number): OptimisticModelResult<Team> {\n\t\tconst offlineTeam: Submitted<Team> = offline({\n\t\t\t...teamPayload,\n\t\t\torganization: organizationId,\n\t\t\tsubmitted_at: new Date().toISOString(),\n\t\t\t// TODO: uncomment once supported\n\t\t\t// created_by: state.userReducer.currentUser.id,\n\t\t})\n\n\t\tthis.dispatch(addTeam(offlineTeam))\n\n\t\tconst promise = this.enqueueRequest<Team>({\n\t\t\tdescription: \"Create team\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/organizations/${organizationId}/teams/`,\n\t\t\tpayload: offlineTeam,\n\t\t\t// No blocks since users and organizations are not offline\n\t\t\tblockers: [],\n\t\t\tblocks: [offlineTeam.offline_id],\n\t\t})\n\n\t\tpromise\n\t\t\t.then((createdTeam) => {\n\t\t\t\tthis.dispatch(setTeam(createdTeam))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(deleteTeam(offlineTeam.offline_id))\n\t\t\t})\n\n\t\treturn [offlineTeam, promise]\n\t}\n\n\t// TODO: @Audiopolis / Magnus - should we pass a offline_id as one arg and a UpdatedTeamProps as a second arg instead of this set up?\n\tupdate(team: Stored<Team>): OptimisticModelResult<Team> {\n\t\tconst { store } = this.client\n\n\t\tconst teamToBeUpdated = selectTeamById(team.offline_id)(store.getState())\n\n\t\tif (!teamToBeUpdated) {\n\t\t\tthrow new Error(`Expected team with offline_id ${team.offline_id} to exist`)\n\t\t}\n\n\t\tconst offlineUpdatedTeam: Submitted<Team> = {\n\t\t\t...teamToBeUpdated,\n\t\t\t...team,\n\t\t}\n\n\t\tthis.dispatch(updateTeam(offlineUpdatedTeam))\n\n\t\tconst promise = this.enqueueRequest<Team>({\n\t\t\tdescription: \"Update team\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/organizations/teams/${team.offline_id}/`,\n\t\t\tpayload: offlineUpdatedTeam,\n\t\t\tblockers: [team.offline_id],\n\t\t\tblocks: [team.offline_id],\n\t\t})\n\n\t\tpromise\n\t\t\t.then((updatedTeam) => {\n\t\t\t\t// sync the updated team with the store\n\t\t\t\tthis.dispatch(setTeam(updatedTeam))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(setTeam(teamToBeUpdated))\n\t\t\t})\n\n\t\treturn [offlineUpdatedTeam, promise]\n\t}\n\n\tasync delete(teamId: string): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst team = selectTeamById(teamId)(state)\n\n\t\tif (!team) {\n\t\t\tthrow new Error(`Expected team with id ${teamId} to exist`)\n\t\t}\n\n\t\tthis.dispatch(deleteTeam(teamId))\n\n\t\ttry {\n\t\t\t// REASON: Need to await to trigger the catch block.\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-confusing-void-expression\n\t\t\treturn await this.enqueueRequest<undefined>({\n\t\t\t\tdescription: \"Delete team\",\n\t\t\t\tmethod: HttpMethod.DELETE,\n\t\t\t\turl: `/organizations/teams/${teamId}/`,\n\t\t\t\tblockers: [teamId],\n\t\t\t\tblocks: [teamId],\n\t\t\t})\n\t\t} catch (e) {\n\t\t\tthis.dispatch(setTeam(team))\n\t\t\tthrow e\n\t\t}\n\t}\n\n\tasync setMembers(teamId: string, members: User[\"id\"][]): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst team = selectTeamById(teamId)(store.getState())\n\n\t\tif (!team) {\n\t\t\tthrow new Error(`Expected team with id ${teamId} to exist`)\n\t\t}\n\n\t\tif (members.length !== new Set(members).size) {\n\t\t\tthrow new Error(\"Duplicate members found in the list\")\n\t\t}\n\n\t\tthis.dispatch(updateTeam({ ...team, members }))\n\n\t\tconst promise = this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Set team members\",\n\t\t\tmethod: HttpMethod.PUT,\n\t\t\turl: `/organizations/teams/${teamId}/set-members/`,\n\t\t\tpayload: {\n\t\t\t\tusers: members,\n\t\t\t},\n\t\t\tblockers: [teamId],\n\t\t\tblocks: [teamId],\n\t\t})\n\n\t\tpromise.catch(() => {\n\t\t\tthis.dispatch(setTeam(team))\n\t\t})\n\n\t\treturn promise\n\t}\n\n\tasync addMembers(teamId: string, members: User[\"id\"][]): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst team = selectTeamById(teamId)(store.getState())\n\n\t\tif (!team) {\n\t\t\tthrow new Error(`Expected team with id ${teamId} to exist`)\n\t\t}\n\n\t\tconst newMembers = [...team.members, ...members]\n\n\t\treturn this.setMembers(teamId, newMembers)\n\t}\n\n\tasync removeMembers(teamId: string, members: User[\"id\"][]): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst team = selectTeamById(teamId)(store.getState())\n\n\t\tif (!team) {\n\t\t\tthrow new Error(`Expected team with id ${teamId} to exist`)\n\t\t}\n\n\t\tconst newMembers = team.members.filter((member) => !members.includes(member))\n\n\t\treturn this.setMembers(teamId, newMembers)\n\t}\n\n\tasync refreshStore(organizationId: number): Promise<void> {\n\t\t// TODO: fetch for project as well\n\n\t\tconst result = await this.enqueueRequest<Team[]>({\n\t\t\tdescription: \"Fetch teams\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/organizations/${organizationId}/teams/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tthis.dispatch(initializeTeams(result))\n\t}\n}\n","import { BaseApiService } from \"./BaseApiService\"\nimport { setUsers } from \"../../store\"\nimport { OvermapRootState, User } from \"../../typings\"\nimport { BaseSDK } from \"../base\"\nimport { HttpMethod } from \"../../enums\"\n\nexport abstract class UserService<TState extends OvermapRootState, TSDK extends BaseSDK<TState>> extends BaseApiService<\n\tTState,\n\tTSDK\n> {\n\tasync refreshStore(projectId: number, organizationId: number): Promise<void> {\n\t\tconst usersRecord: Record<number, User> = {}\n\n\t\tconst organizationUsers = await this.enqueueRequest<User[]>({\n\t\t\tdescription: \"Fetch organization users\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/organizations/${organizationId}/users/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tfor (const user of organizationUsers) {\n\t\t\tusersRecord[user.id] = user\n\t\t}\n\n\t\tconst projectUsers = await this.enqueueRequest<User[]>({\n\t\t\tdescription: \"Fetch project users\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/users/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tfor (const user of projectUsers) {\n\t\t\tusersRecord[user.id] = user\n\t\t}\n\n\t\tthis.dispatch(setUsers(Object.values(usersRecord)))\n\t}\n}\n","import { HttpMethod } from \"../../enums\"\nimport {\n\tBulkGeoImagePayload,\n\tCreated,\n\tGeoImage,\n\tGeoImagePayload,\n\tOffline,\n\tOvermapRootState,\n\tPointGeometry,\n\tStored,\n\tSubmitted,\n} from \"../../typings\"\n\nimport { OptimisticModelResult, OptimisticMultipleModelResult, PresignedUrlsResponse } from \"../typings\"\nimport { hashFile, offline } from \"../../utils\"\nimport { FilePayload } from \"./BaseAttachmentService\"\nimport type { BaseSDK } from \"../base\"\nimport { BaseUploadService } from \"./BaseUploadService\"\nimport {\n\taddGeoImage,\n\taddGeoImages,\n\tdeleteGeoImage,\n\tdeleteGeoImages,\n\tinitializeGeoImages,\n\tselectGeoImageById,\n\tsetGeoImage,\n\tsetGeoImages,\n\tupdateGeoImage,\n} from \"../../store\"\n\ninterface BulkCreateGeoImagesPayload {\n\tsubmitted_at: string\n\tproject: number\n\tgeo_images: {\n\t\t// requireds\n\t\toffline_id: string\n\t\tsha1: string\n\t\tfile_name: string\n\t\t// optionals\n\t\ttitle?: string\n\t\tdescription?: string\n\t\tgeo_marker?: PointGeometry\n\t\tcanvas_marker?: PointGeometry\n\n\t\tdirection?: number\n\t\toriginal_date?: string\n\t}[]\n\tfiles: FilePayload[]\n}\n\ninterface CreateGeoImageResult {\n\tgeo_image: Created<GeoImage>\n\tpresigned_urls: PresignedUrlsResponse\n}\n\ninterface BulkCreateMapImagesResult {\n\tgeo_images: Created<GeoImage>[]\n\tpresigned_urls: PresignedUrlsResponse\n}\n\nexport abstract class GeoImageService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseUploadService<TState, TSDK> {\n\tasync add(payload: GeoImagePayload): Promise<OptimisticModelResult<GeoImage>> {\n\t\tconst { store } = this.client\n\n\t\tconst { file, ...payloadWithoutFile } = payload\n\n\t\tconst submittedAt = new Date().toISOString()\n\t\tconst currentUser = store.getState().userReducer.currentUser\n\t\tconst projectId = payloadWithoutFile.project\n\n\t\tconst sha1 = await hashFile(file)\n\n\t\tconst filePayload: FilePayload = {\n\t\t\tsha1,\n\t\t\tfile_type: file.type,\n\t\t\textension: file.name.split(\".\").pop()!,\n\t\t\tsize: file.size,\n\t\t}\n\n\t\tconst offlineMapImage: Stored<GeoImage> = offline({\n\t\t\t...payloadWithoutFile,\n\t\t\tfile_name: file.name,\n\t\t\tfile_sha1: sha1,\n\t\t\tfile: URL.createObjectURL(file),\n\t\t\tsubmitted_at: submittedAt,\n\t\t\tcreated_by: currentUser.id,\n\t\t})\n\n\t\tstore.dispatch(addGeoImage(offlineMapImage))\n\n\t\tconst promise = this.enqueueRequest<CreateGeoImageResult>({\n\t\t\tdescription: \"Add geo image\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: \"/geo-images/\",\n\t\t\tpayload: {\n\t\t\t\toffline_id: offlineMapImage.offline_id,\n\t\t\t\tsubmitted_at: submittedAt,\n\t\t\t\ttitle: offlineMapImage.title,\n\t\t\t\tdescription: offlineMapImage.description,\n\t\t\t\tgeo_marker: offlineMapImage.geo_marker,\n\t\t\t\tcanvas_marker: offlineMapImage.canvas_marker,\n\t\t\t\tsha1: offlineMapImage.file_sha1,\n\t\t\t\tproject: offlineMapImage.project,\n\t\t\t\tfile_name: offlineMapImage.file_name,\n\t\t\t\tdirection: offlineMapImage.direction,\n\t\t\t\toriginal_date: offlineMapImage.original_date,\n\t\t\t\tfile: filePayload,\n\t\t\t},\n\t\t\tblocks: [projectId.toString()],\n\t\t\tblockers: [projectId.toString()],\n\t\t})\n\n\t\tpromise\n\t\t\t.then((result) => {\n\t\t\t\tthis.processPresignedUrls(result.presigned_urls)\n\t\t\t\tstore.dispatch(setGeoImage(result.geo_image))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tstore.dispatch(deleteGeoImage(offlineMapImage.offline_id))\n\t\t\t})\n\n\t\treturn [offlineMapImage, promise.then((result) => result.geo_image)]\n\t}\n\n\tasync bulkAdd(\n\t\tpayloads: BulkGeoImagePayload[],\n\t\tprojectId: number,\n\t): Promise<OptimisticMultipleModelResult<GeoImage>> {\n\t\tconst { store } = this.client\n\n\t\tconst submittedAt = new Date().toISOString()\n\t\tconst currentUser = store.getState().userReducer.currentUser\n\n\t\tconst offlineGeoImages: Submitted<GeoImage>[] = []\n\t\tconst offlineIds: string[] = []\n\t\tconst geoImagePayloads: BulkCreateGeoImagesPayload[\"geo_images\"] = []\n\t\tconst filePayloadRecord: Record<string, FilePayload> = {}\n\n\t\tfor (const payloadAndFile of payloads) {\n\t\t\tconst { file, ...payload } = payloadAndFile\n\n\t\t\tconst sha1 = await hashFile(file)\n\t\t\tif (!(sha1 in filePayloadRecord)) {\n\t\t\t\tfilePayloadRecord[sha1] = {\n\t\t\t\t\tsha1,\n\t\t\t\t\tfile_type: file.type,\n\t\t\t\t\textension: file.name.split(\".\").pop()!,\n\t\t\t\t\tsize: file.size,\n\t\t\t\t}\n\t\t\t\tawait this.client.files.addCache(file, sha1)\n\t\t\t}\n\n\t\t\tconst offlineMapImage: Stored<GeoImage> = offline({\n\t\t\t\t...payload,\n\t\t\t\tfile_name: file.name,\n\t\t\t\tfile_sha1: sha1,\n\t\t\t\tfile: URL.createObjectURL(file),\n\t\t\t\tsubmitted_at: submittedAt,\n\t\t\t\tcreated_by: currentUser.id,\n\t\t\t\tproject: projectId,\n\t\t\t})\n\t\t\tofflineGeoImages.push(offlineMapImage)\n\n\t\t\tofflineIds.push(offlineMapImage.offline_id)\n\n\t\t\tgeoImagePayloads.push({\n\t\t\t\toffline_id: offlineMapImage.offline_id,\n\t\t\t\tsha1: offlineMapImage.file_sha1,\n\t\t\t\tfile_name: offlineMapImage.file_name,\n\n\t\t\t\ttitle: offlineMapImage.title,\n\t\t\t\tdescription: offlineMapImage.description,\n\t\t\t\tgeo_marker: offlineMapImage.geo_marker,\n\t\t\t\tcanvas_marker: offlineMapImage.canvas_marker,\n\t\t\t\tdirection: offlineMapImage.direction,\n\t\t\t\toriginal_date: offlineMapImage.original_date,\n\t\t\t})\n\t\t}\n\n\t\tstore.dispatch(addGeoImages(offlineGeoImages))\n\n\t\tconst promise = this.enqueueRequest<BulkCreateMapImagesResult>({\n\t\t\tdescription: \"Bulk add geo images\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: \"/geo-images/bulk/\",\n\t\t\tpayload: {\n\t\t\t\tsubmitted_at: submittedAt,\n\t\t\t\tproject: projectId,\n\t\t\t\tgeo_images: geoImagePayloads,\n\t\t\t\tfiles: Object.values(filePayloadRecord),\n\t\t\t} satisfies BulkCreateGeoImagesPayload,\n\t\t\tblocks: [projectId.toString()],\n\t\t\tblockers: offlineIds,\n\t\t})\n\n\t\tpromise\n\t\t\t.then((result) => {\n\t\t\t\tthis.processPresignedUrls(result.presigned_urls)\n\t\t\t\tstore.dispatch(setGeoImages(result.geo_images))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tstore.dispatch(deleteGeoImages(offlineIds))\n\t\t\t})\n\n\t\treturn [offlineGeoImages, promise.then((result) => result.geo_images)]\n\t}\n\n\tupdate(payload: Offline<Partial<Pick<GeoImagePayload, \"title\" | \"description\">>>): OptimisticModelResult<GeoImage> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst geoImageToUpdate = selectGeoImageById(payload.offline_id)(state)\n\n\t\tif (!geoImageToUpdate) {\n\t\t\tthrow new Error(`Map image with offline_id ${payload.offline_id} does not exist in the store`)\n\t\t}\n\n\t\tconst updatedGeoImage: Stored<GeoImage> = { ...geoImageToUpdate, ...payload }\n\n\t\tstore.dispatch(updateGeoImage(updatedGeoImage))\n\n\t\tconst promise = this.enqueueRequest<Created<GeoImage>>({\n\t\t\tdescription: \"Update geo image\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/geo-images/${payload.offline_id}/`,\n\t\t\tpayload: payload,\n\t\t\tblocks: [payload.offline_id],\n\t\t\tblockers: [payload.offline_id],\n\t\t})\n\n\t\tpromise\n\t\t\t.then((result) => {\n\t\t\t\tstore.dispatch(setGeoImage(result))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tstore.dispatch(setGeoImage(geoImageToUpdate))\n\t\t\t})\n\n\t\treturn [updatedGeoImage, promise]\n\t}\n\n\tasync delete(geoImageId: string): Promise<void> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst geoImageToDelete = selectGeoImageById(geoImageId)(state)\n\n\t\tif (!geoImageToDelete) {\n\t\t\tthrow new Error(`Map image with offline_id ${geoImageId} does not exist in the store`)\n\t\t}\n\n\t\tstore.dispatch(deleteGeoImage(geoImageId))\n\n\t\tconst promise = this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Delete geo image\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/geo-images/${geoImageId}/`,\n\t\t\tblocks: [geoImageId],\n\t\t\tblockers: [geoImageId],\n\t\t})\n\n\t\tpromise.catch(() => {\n\t\t\tstore.dispatch(setGeoImage(geoImageToDelete))\n\t\t})\n\n\t\treturn promise\n\t}\n\n\tasync refreshStore(projectId: number): Promise<void> {\n\t\tconst { store } = this.client\n\n\t\tconst result = await this.enqueueRequest<Created<GeoImage>[]>({\n\t\t\tdescription: \"Get geo images\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/geo-images/`,\n\t\t\tblocks: [projectId.toString()],\n\t\t\tblockers: [],\n\t\t})\n\n\t\tstore.dispatch(initializeGeoImages(result))\n\t}\n}\n","import type { IssueAssociation, OvermapRootState, Payload, Stored } from \"../../typings\"\n\nimport type { OptimisticModelResult } from \"../typings\"\nimport type { BaseSDK } from \"../base\"\nimport { BaseUploadService } from \"./BaseUploadService\"\nimport { offline } from \"../../utils\"\nimport {\n\taddIssueAssociation,\n\tdeleteIssueAssociation,\n\tinitializeIssueAssociations,\n\tselectIssueAssociationById,\n\tupdateIssueAssociation,\n} from \"../../store\"\nimport { HttpMethod } from \"../../enums\"\n\nexport abstract class IssueAssociationService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseUploadService<TState, TSDK> {\n\tadd(payload: Payload<IssueAssociation>): OptimisticModelResult<IssueAssociation> {\n\t\tconst { store } = this.client\n\n\t\tconst submittedAt = new Date().toISOString()\n\t\tconst createdBy = store.getState().userReducer.currentUser.id\n\n\t\tconst offlineIssueAssociation = offline({\n\t\t\t...payload,\n\t\t\tsubmitted_at: submittedAt,\n\t\t\tcreated_by: createdBy,\n\t\t}) satisfies Stored<IssueAssociation>\n\n\t\tthis.dispatch(addIssueAssociation(offlineIssueAssociation))\n\n\t\tconst promise = this.enqueueRequest<IssueAssociation>({\n\t\t\tdescription: \"Add issue association\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: \"/issues/associations/\",\n\t\t\tpayload: {\n\t\t\t\toffline_id: offlineIssueAssociation.offline_id,\n\t\t\t\tsubmitted_at: submittedAt,\n\t\t\t\tcreated_by: createdBy,\n\t\t\t\t...payload,\n\t\t\t},\n\t\t\tblockers: [\n\t\t\t\tpayload.associated_issue,\n\t\t\t\t...(payload.issue ? [payload.issue] : []),\n\t\t\t\t...(payload.asset ? [payload.asset] : []),\n\t\t\t],\n\t\t\tblocks: [offlineIssueAssociation.offline_id],\n\t\t})\n\n\t\tpromise\n\t\t\t.then((issueAssociation) => {\n\t\t\t\tthis.dispatch(updateIssueAssociation(issueAssociation))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(deleteIssueAssociation(offlineIssueAssociation.offline_id))\n\t\t\t})\n\n\t\treturn [offlineIssueAssociation, promise]\n\t}\n\n\tasync delete(id: string): Promise<void> {\n\t\tconst { store } = this.client\n\n\t\tconst issueAssociation = selectIssueAssociationById(id)(store.getState())\n\n\t\tif (!issueAssociation) {\n\t\t\tthrow new Error(`Issue association with id ${id} not found in store.`)\n\t\t}\n\n\t\tthis.dispatch(deleteIssueAssociation(id))\n\n\t\tconst promise = this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Delete issue association\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/issues/associations/${id}/`,\n\t\t\tblockers: [id],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tpromise.catch(() => {\n\t\t\tthis.dispatch(addIssueAssociation(issueAssociation))\n\t\t})\n\n\t\treturn promise\n\t}\n\n\tasync refreshStore(projectId: number): Promise<void> {\n\t\tconst issueAssociations = await this.enqueueRequest<IssueAssociation[]>({\n\t\t\tdescription: \"Fetch issue associations\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: \"/issues/associations/\",\n\t\t\tqueryParams: { project_id: projectId.toString() },\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tthis.dispatch(initializeIssueAssociations(issueAssociations))\n\t}\n}\n"],"names":["HttpMethod","IssuePriority","IssueStatus","DepGraph","request","uuid","randomString","VERSION_REDUCER_KEY","_a","migration","initialState","createSlice","saveAs","uuidv4","self","useRef","useEffect","gray","gold","brown","yellow","amber","orange","red","crimson","pink","plum","purple","violet","iris","indigo","blue","cyan","jade","grass","lime","mint","sky","createSelector","today","ProjectAccessLevel","OrganizationAccessLevel","AttachmentModel","IssueUpdateChange","VerificationCodeType","PaddleCheckoutEvent","LicenseLevel","LicenseStatus","document","combineReducers","createNextState","clientStore","offline","clientSDK","coordinator","unsafeShowToast","RESET_STATE","blocks","issueAttachmentReducer","assetAttachmentReducer","assetTypeAttachmentReducer","documentAttachmentReducer","projectAttachmentReducer","formRevisionAttachmentReducer","formSubmissionAttachmentReducer","geoImageReducer","result","requestDetails","openDB","file","organization"],"mappings":";;;;;;;;;;;AAAkB,MAAA,+BAAAA,gBAAX;AACNA,gBAAA,KAAM,IAAA;AACNA,gBAAA,MAAO,IAAA;AACPA,gBAAA,OAAQ,IAAA;AACRA,gBAAA,KAAM,IAAA;AACNA,gBAAA,QAAS,IAAA;AALQA,WAAAA;AAAAA,EAAA,GAAA,cAAA,CAAA,CAAA;ACAN,MAAA,kCAAAC,mBAAL;AACNA,mBAAAA,eAAA,YAAS,CAAT,IAAA;AACAA,mBAAAA,eAAA,SAAM,CAAN,IAAA;AACAA,mBAAAA,eAAA,YAAS,CAAT,IAAA;AACAA,mBAAAA,eAAA,UAAO,CAAP,IAAA;AACAA,mBAAAA,eAAA,aAAU,CAAV,IAAA;AALWA,WAAAA;AAAAA,EAAA,GAAA,iBAAA,CAAA,CAAA;AAQA,MAAA,gCAAAC,iBAAL;AACNA,iBAAAA,aAAA,aAAU,CAAV,IAAA;AACAA,iBAAAA,aAAA,cAAW,CAAX,IAAA;AACAA,iBAAAA,aAAA,UAAO,CAAP,IAAA;AAHWA,WAAAA;AAAAA,EAAA,GAAA,eAAA,CAAA,CAAA;AAAA,ECDL,MAAM,kBAAkB;AAAA,IAI9B,cAAc;AAHd;AACA;AAGM,WAAA,QAAQ,IAAIC,gBAAAA;AACjB,WAAK,wBAAwB;IAC9B;AAAA;AAAA;AAAA;AAAA,IAKA,OAAO,YAAY,QAAmC;AAC/C,YAAA,MAAM,IAAI;AAEhB,eAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACjC,cAAA,aAAa,OAAO,CAAC;AAC3B,YAAI,CAAC,YAAY;AAChB,kBAAQ,MAAM,2BAA2B;AACzC;AAAA,QACD;AACA,YAAI,aAAa,UAAU;AAE3B,iBAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AACrB,gBAAA,qBAAqB,OAAO,CAAC;AACnC,cAAI,CAAC,oBAAoB;AACxB,oBAAQ,MAAM,oCAAoC;AAClD;AAAA,UACD;AACA,cAAI,mBAAmB,QAAQ,SAAS,WAAW,QAAQ,MAAM;AAChE;AAAA,UACD;AACA,cAAI,mBAAmB,QAAQ,OAAO,KAAK,CAAC,UAAU,WAAW,QAAQ,SAAS,SAAS,KAAK,CAAC,GAAG;AACjF,8BAAA;AAAA,cACjB,WAAW,QAAQ;AAAA,cACnB,mBAAmB,QAAQ;AAAA,cAC3B,IAAI;AAAA,YAAA;AAAA,UAEN;AAAA,QACD;AAAA,MACD;AACO,aAAA;AAAA,IACR;AAAA,IAEA,eAAe,MAAc,IAAY;AACxC,wBAAkB,eAAe,MAAM,IAAI,KAAK,KAAK;AAAA,IACtD;AAAA,IAEA,OAAO,eAAe,MAAc,IAAY,OAAoC;AACnF,UAAI,SAAS,IAAI;AAChB,cAAM,IAAI,MAAM,gDAAgD,IAAI,EAAE;AAAA,MACvE;AACM,YAAA,aAAa,MAAM,QAAQ,IAAI;AACrC,UAAI,CAAC,YAAY;AAChB,cAAM,IAAI,MAAM,mDAAmD,IAAI,cAAc,EAAE,GAAG;AAAA,MAC3F;AACM,YAAA,WAAW,MAAM,QAAQ,EAAE;AACjC,UAAI,CAAC,UAAU;AACd,cAAM,IAAI,MAAM,iDAAiD,EAAE,gBAAgB,IAAI,GAAG;AAAA,MAC3F;AACM,YAAA,cAAc,MAAM,EAAE;AAAA,IAC7B;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,WAAWC,UAA4B;AACtC,WAAK,MAAM,QAAQA,SAAQ,QAAQ,MAAMA,QAAO;AAE5C,UAAAA,SAAQ,QAAQ,SAAS,WAAW,KAAK,KAAK,MAAM,KAAK,MAAM,GAAG;AAGrE;AAAA,MACD;AAGA,iBAAW,QAAQ,KAAK,MAAM,aAAA,GAAgB;AACzC,YAAA,SAASA,SAAQ,QAAQ;AAAM;AACnC,cAAM,UAAU,KAAK,MAAM,YAAY,IAAI;AAE3C,YAAIA,SAAQ,QAAQ,SAAS,KAAK,CAAC,YAAY,QAAQ,QAAQ,OAAO,SAAS,OAAO,CAAC,GAAG;AACzF,eAAK,eAAeA,SAAQ,QAAQ,MAAM,IAAI;AAAA,QAC/C;AAAA,MACD;AAAA,IACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASA,cAAcA,UAA4B;AACzC,WAAK,MAAM,QAAQA,SAAQ,QAAQ,MAAMA,QAAO;AAGhD,iBAAW,QAAQ,KAAK,MAAM,aAAA,GAAgB;AACzC,YAAA,SAASA,SAAQ,QAAQ;AAAM;AACnC,cAAM,UAAU,KAAK,MAAM,YAAY,IAAI;AAE3C,YAAI,QAAQ,QAAQ,SAAS,KAAK,CAAC,YAAYA,SAAQ,QAAQ,OAAO,SAAS,OAAO,CAAC,GAAG;AACzF,eAAK,eAAe,MAAMA,SAAQ,QAAQ,IAAI;AAAA,QAC/C;AAAA,MACD;AAAA,IACD;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,aAAaA,UAA4B;AACxC,WAAK,MAAM,QAAQA,SAAQ,QAAQ,MAAMA,QAAO;AAAA,IACjD;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,eAAmC;AAClC,YAAM,YAAY,KAAK,MAAM,aAAa,IAAI;AAC9C,UAAI,cAAc;AACd,UAAA;AACJ,iBAAW,QAAQ,WAAW;AAC7B,cAAM,WAAW,KAAK,sBAAsB,IAAI,KAAK;AACrD,YAAI,WAAW,aAAa;AACb,wBAAA;AACI,4BAAA;AAAA,QACnB;AAAA,MACD;AACO,aAAA;AAAA,IACR;AAAA;AAAA;AAAA;AAAA,IAKA,OAAsC;AAC/B,YAAA,WAAW,KAAK;AACtB,UAAI,CAAC;AAAiB,eAAA;AACf,aAAA,KAAK,MAAM,YAAY,QAAQ;AAAA,IACvC;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,OAAOC,OAAoB;AACrB,WAAA,MAAM,WAAWA,KAAI;AACnB,aAAA,KAAK,sBAAsBA,KAAI;AAAA,IACvC;AAAA;AAAA;AAAA;AAAA,IAKA,MAAqC;AAC9B,YAAA,qBAAqB,KAAK;AAChC,UAAI,oBAAoB;AACvB,aAAK,MAAM,WAAW,mBAAmB,QAAQ,IAAI;AAAA,MACtD;AACO,aAAA;AAAA,IACR;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,WAAgC;AAC/B,YAAM,MAAM,KAAK,MAAM,aAAe,EAAA,IAAI,CAAC,aAAa,KAAK,MAAM,YAAY,QAAQ,CAAC;AAIlF,YAAA,WAAW,KAAK;AACtB,UAAI,UAAU;AACb,cAAM,qBAAqB,KAAK,MAAM,YAAY,QAAQ;AAC1D,cAAM,mBAAmB,IAAI;AAAA,UAC5B,CAACD,aAAYA,SAAQ,QAAQ,SAAS,mBAAmB,QAAQ;AAAA,QAAA;AAElE,YAAI,qBAAqB,IAAI;AACxB,cAAA,OAAO,kBAAkB,CAAC;AAC9B,cAAI,QAAQ,kBAAkB;AAAA,QAC/B;AAAA,MACD;AAEO,aAAA;AAAA,IACR;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,WAAgC;AAC/B,UAAI,MAAM,KAAK,MAAM,aAAa,IAAI,EAAE,IAAI,CAAC,aAAa,KAAK,MAAM,YAAY,QAAQ,CAAC;AAE1F,YAAM,IAAI,KAAK,CAAC,GAAG,MAAM;AACjB,eAAA,EAAE,KAAK,QAAQ,OAAO,UAAU,cAAc,EAAE,KAAK,QAAQ,OAAO,SAAS;AAAA,MAAA,CACpF;AAED,YAAM,IAAI,KAAK,CAAC,GAAG,MAAM;AACxB,cAAM,YAAY,KAAK,sBAAsB,EAAE,QAAQ,IAAI,KAAK;AAChE,cAAM,YAAY,KAAK,sBAAsB,EAAE,QAAQ,IAAI,KAAK;AAGhE,eAAO,YAAY;AAAA,MAAA,CACnB;AACM,aAAA;AAAA,IACR;AAAA,IAEA,cAAcC,OAAoB;AACjC,WAAK,sBAAsBA,KAAI,KAAK,KAAK,sBAAsBA,KAAI,KAAK,KAAK;AAAA,IAC9E;AAAA,EACD;AC/MA,QAAM,wBAAwB;AAC9B,QAAM,2BAA2B;AACjC,QAAM,gBAAgB,CAAC,oBAAoB,QAAQ;AAOnD,WAAS,oBAAoB,UAAwC,KAAkC;AAClG,QAAA;AACJ,QAAI,qCAAU,MAAM;AACf,UAAA,OAAO,SAAS,SAAS,UAAU;AACtC,cAAM,eAAe,SAAS;AAK1B,YAAA,OAAO,aAAa,UAAU,UAAU;AAC3C,gBAAM,aAAa;AAAA,QACT,WAAA,OAAO,aAAa,YAAY,UAAU;AACpD,gBAAM,aAAa;AAAA,QAAA,WACT,aAAa,MAAM;AAazB,cAAA;AACG,kBAAA,OAAO,QAAQ,aAAa,IAAI,EACpC,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM;AAClB,kBAAA,OAAO,UAAU,UAAU;AAC1B,oBAAA,cAAc,SAAS,GAAG;AAAU,yBAAA;AACjC,uBAAA,GAAG,GAAG,KAAK,KAAK;AAAA,cACxB;AACI,kBAAA,MAAM,QAAQ,KAAK,GAAG;AACrB,oBAAA,cAAc,SAAS,GAAG;AAAU,yBAAA,MAAM,KAAK,IAAI;AAChD,uBAAA,MAAM,IAAI,CAAC,MAAM,GAAG,GAAG,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI;AAAA,cAClD;AACA,qBAAO,GAAG,GAAG,KAAK,KAAK,UAAU,KAAK,CAAC;AAAA,YAAA,CACvC,EACA,KAAK,IAAI;AAAA,mBACH,GAAG;AACH,oBAAA,MAAM,sDAAsD,CAAC;AAAA,UACtE;AAAA,QACD;AAAA,MACU,WAAA,OAAO,SAAS,SAAS,UAAU;AAC7C,cAAM,SAAS;AAAA,MAChB;AAAA,IAAA,WACU,qCAAU,MAAM;AAC1B,YAAM,SAAS;AAAA,IAAA,WACL,eAAe,OAAO;AAChC,YAAM,IAAI;AAAA,IACX;AAIA,QAAI,CAAC,OAAO,IAAI,SAAS,0BAA0B;AAC3C,aAAA;AAAA,IACR;AACO,WAAA;AAAA,EACR;AAAA,EAEO,MAAM,iBAAiB,MAAM;AAAA,IAOnC,YAAY,SAA0B;AACrC,YAAM,qBAAqB;AAN5B;AAAA;AACA;AACA;AACA;AAIO,YAAA,EAAE,UAAU,WAAe,IAAA;AACjC,WAAK,UAAU,QAAQ,WAAW,oBAAoB,UAAU,UAAU,KAAK;AAC1E,WAAA,UAAS,qCAAU,WAAU;AAClC,WAAK,WAAW;AACR,cAAA,UAAU,QAAQ,WAAW;AACrC,WAAK,UAAU;AAAA,IAChB;AAAA,EACD;AAAA,EC1EO,MAAM,gBAAyC;AAAA,IAYrD,cAAc;AAXd,0BAAC,IAAsB;AAEf;AACA;AACA;AACA,oCAA+C;AAOtD,WAAK,WAAW;AAChB,WAAK,UAAU;AAEf,WAAK,WAAW,IAAI,QAAW,CAAC,SAAS,WAAW;AACnD,aAAK,WAAW;AAChB,aAAK,UAAU;AAAA,MAAA,CACf;AAAA,IACF;AAAA,IAZA,IAAW,QAA8C;AACxD,aAAO,KAAK;AAAA,IACb;AAAA,IAYO,KACN,aACA,YAC+B;AAC/B,aAAO,KAAK,SAAS,KAAK,aAAa,UAAU;AAAA,IAClD;AAAA,IAEO,MAAe,YAAwF;AACtG,aAAA,KAAK,SAAS,MAAM,UAAU;AAAA,IACtC;AAAA,IAEO,QAAQ,OAAkC;AAChD,UAAI,CAAC,KAAK;AAAgB,cAAA,IAAI,MAAM,qBAAqB;AACzD,WAAK,SAAS,KAAK;AACnB,WAAK,SAAS;AAAA,IACf;AAAA,IAEO,OAAO,QAAwB;AACrC,UAAI,CAAC,KAAK;AAAe,cAAA;AACzB,WAAK,QAAQ,MAAM;AACnB,WAAK,SAAS;AAAA,IACf;AAAA,IAEO,QAAQ,YAA0D;AAClE,YAAA,IAAI,MAAM,2BAA2B;AAAA,IAC5C;AAAA,EACD;EA/CE,YAAO;ACAT,MAAI,eAAe,SAASC,gBAAe;AACzC,WAAO,KAAK,OAAM,EAAG,SAAS,EAAE,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,EAAE,KAAK,GAAG;AAAA,EACnE;AAEkB,GAAA;AAAA,IAChB,MAAM,iBAAiB,aAAc;AAAA,IACrC,SAAS,oBAAoB,aAAc;AAAA,IAC3C,sBAAsB,SAAS,uBAAuB;AACpD,aAAO,iCAAiC;IACzC;AAAA,EACH;AAylBA,WAAS,UAAU;AACjB,aAAS,OAAO,UAAU,QAAQ,QAAQ,IAAI,MAAM,IAAI,GAAG,OAAO,GAAG,OAAO,MAAM,QAAQ;AACxF,YAAM,IAAI,IAAI,UAAU,IAAI;AAAA,IAC7B;AAED,QAAI,MAAM,WAAW,GAAG;AACtB,aAAO,SAAU,KAAK;AACpB,eAAO;AAAA,MACb;AAAA,IACG;AAED,QAAI,MAAM,WAAW,GAAG;AACtB,aAAO,MAAM,CAAC;AAAA,IACf;AAED,WAAO,MAAM,OAAO,SAAU,GAAG,GAAG;AAClC,aAAO,WAAY;AACjB,eAAO,EAAE,EAAE,MAAM,QAAQ,SAAS,CAAC;AAAA,MACzC;AAAA,IACA,CAAG;AAAA,EACH;ACzoBA,QAAMC,wBAAsB;AAK5B,QAAM,gBAAgB,MAAM,WAAW,SAAS;AAIhD,QAAM,oBAA8B,CAAC,UAAU;AAC9C,UAAMA,qBAAmB,IAAI,EAAE,SAAS,cAAgB,EAAA;AACjD,WAAA;AAAA,EACR;AAGA,QAAM,UAAoB,MAAM;AAExB,WAAA,kBAAkB,CAAA,CAAE;AAAA,EAC5B;AAGA,QAAM,oBAA8B,CAAC,UAAU;AAC9C,QAAI,MAAM,eAAe;AAClB,YAAA,cAAc,kBAAkB;IACvC;AACO,WAAA;AAAA,EACR;AAGA,QAAM,gBAA8B,CAAC,aAAa,CAAC,UAAU;;AAG5D,QAAI,UAAU,QAAW;AACxB,cAAQ,CAAA;AAAA,IACT;AAEA,UAAIC,MAAA,MAAMD,qBAAmB,MAAzB,gBAAAC,IAA4B,aAAY,cAAc;AAAU,aAAA;AAEpE,WAAO,SAAS,KAAK;AAAA,EACtB;AAKA,QAAM,aAAyB,CAAC,mBAAmB,SAAS,SAAS,iBAAiB;AAG/E,QAAM,WAAqB,OAAO,YAAY,WAAW,IAAI,CAACC,YAAW,MAAM,CAAC,GAAG,cAAcA,UAAS,CAAC,CAAC,CAAC;AC3CpH,QAAMC,iBAA0B;AAAA,IAC/B,aAAa;AAAA,IACb,cAAc;AAAA,IACd,YAAY;AAAA,EACb;AAKa,QAAA,YAAYC,QAAAA,YAAY;AAAA,IACpC,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,WAAW,CAAC,OAAO,WAAqC;AACjD,cAAA,cAAc,OAAO,QAAQ;AAC7B,cAAA,eAAe,OAAO,QAAQ;AAAA,MACrC;AAAA,MACA,aAAa,CAAC,UAAU;AACvB,cAAM,cAAc;AACpB,cAAM,eAAe;AAAA,MACtB;AAAA,MACA,aAAa,CAAC,OAAO,WAAmC;AACnD,YAAA,CAAC,OAAO,SAAS;AACV,oBAAA,aAAa,YAAY,KAAK;AAAA,QACzC;AACA,cAAM,aAAa,OAAO;AAAA,MAC3B;AAAA,IACD;AAAA,EACD,CAAC;AAEY,QAAA,EAAE,WAAW,aAAa,gBAAgB,UAAU;AACpD,QAAA,oBAAoB,CAAC,UAAqB,MAAM,YAAY;AAC5D,QAAA,mBAAmB,CAAC,UAAqB,MAAM,YAAY;AAE3D,QAAA,cAAkC,UAAU;ACzC5C,QAAA,uBAAuB,CAAC,gBAA8C;AAC3E,WAAA,EAAE,KAAK,YAAY,CAAC,GAAG,KAAK,YAAY,CAAC;EACjD;AAGa,QAAA,uBAAuB,CAAC,YAA0C;AAC9E,WAAO,CAAC,QAAQ,KAAK,QAAQ,GAAG;AAAA,EACjC;AAKa,QAAA,kBAAkB,CAAC,gBAA4C;AAC3E,WAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAAC,CAAC;AAAA,EACvC;AAEa,QAAA,aAAa,CAAC,WAA2B;AAC9C,WAAA,CAAC,gBAAgB,OAAO,CAAC,CAAC,GAAG,gBAAgB,OAAO,CAAC,CAAC,CAAC;AAAA,EAC/D;AAEgB,WAAA,uBACf,kBACA,WACA,WACkB;AACZ,UAAA,EAAE,KAAK,IAAQ,IAAA;AACrB,UAAM,cAAc;AACpB,UAAM,kBAAmB,IAAI,KAAK,KAAK,cAAe;AAEhD,UAAA,SAAS,MAAM,YAAY,kBAAkB,KAAK,IAAK,MAAM,KAAK,KAAM,GAAG;AAC3E,UAAA,SAAS,MAAM,YAAY;AACjC,WAAO,EAAE,KAAK,QAAQ,KAAK,OAAO;AAAA,EACnC;AAEa,QAAA,sBAAsB,CAAC,gBAA4C;AACxE,WAAA;AAAA,MACN,MAAM;AAAA,MACN;AAAA,IAAA;AAAA,EAEF;AAEa,QAAA,sBAAsB,CAAC,GAAgB,MAA4B;AACxE,WAAA,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,CAAC;AAAA,EACrC;AAiBa,QAAA,oBAAoB,CAAC,aAA6C,kBAA2B;AACzG,QAAI,CAAC;AAAoB,aAAA;AACzB,UAAM,EAAE,KAAK,IAAI,IAAI,qBAAqB,WAAW;AACjD,QAAA;AAAsB,aAAA,GAAG,IAAI,QAAQ,aAAa,CAAC,KAAK,IAAI,QAAQ,aAAa,CAAC;AAC/E,WAAA,GAAG,GAAG,KAAK,GAAG;AAAA,EACtB;AAEa,QAAA,uBAAuB,CAAC,gBAA6B;AACjE,UAAM,EAAE,KAAK,IAAI,IAAI,qBAAqB,WAAW;AAC9C,WAAA,GAAG,GAAG,MAAM,GAAG;AAAA,EACvB;AAGa,QAAA,yBAAyB,CAAC,gBAA6B;AACnE,UAAM,MAAM,mDAAmD,qBAAqB,WAAW,CAAC;AAChG,WAAO,KAAK,GAAG;AAAA,EAChB;AAEa,QAAA,6BAA6B,CAAC,eAA4B,gBAA6B;AAC7F,UAAA,mBAAmB,qBAAqB,aAAa;AACrD,UAAA,iBAAiB,qBAAqB,WAAW;AACvD,UAAM,MAAM,iDAAiD,gBAAgB,gBAAgB,cAAc;AAC3G,WAAO,KAAK,GAAG;AAAA,EAChB;AAEO,QAAM,cAAkC;AAAA,IAC9C,MAAM;AAAA,IACN,aAAa;AAAA,MACZ,CAAC,IAAI,IAAI;AAAA,MACT,CAAC,KAAK,GAAG;AAAA,IACV;AAAA,EACD;AAEa,QAAA,2BAA2B,CAAC,gBAAgE;AACjG,WAAA;AAAA,MACN,MAAM;AAAA,MACN;AAAA,IAAA;AAAA,EAEF;AClGO,WAAS,cAAc,MAA+D;AAC5F,UAAM,UAAoB,CAAA;AAC1B,eAAW,OAAO,MAAM;AACvB,UAAI,CAAC,KAAK;AACT;AAAA,MACD;AACI,UAAA,OAAO,QAAQ,UAAU;AAC5B,gBAAQ,KAAK,GAAG;AAAA,MAAA,WACN,OAAO,QAAQ,UAAU;AACnC,mBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC/C,cAAI,OAAO;AACV,oBAAQ,KAAK,GAAG;AAAA,UACjB;AAAA,QACD;AAAA,MACD;AAAA,IACD;AACO,WAAA,QAAQ,KAAK,GAAG;AAAA,EACxB;ACjBA,WAAS,IAAI,QAAiC;AACvC,UAAA,YAAY,IAAI,WAAW,MAAM;AAEvC,WAAO,UAAU,OAAO,CAAC,MAAM,SAAS,OAAO,KAAK,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,GAAG,EAAE;AAAA,EACtF;AAEa,QAAA,eAAe,OAAO,MAAY,SAAkB;AAChE,QAAI,CAAC,MAAM;AACH,aAAA,MAAM,SAAS,IAAI;AAAA,IAC3B;AACA,QAAI,WAAW,KAAK;AAChB,QAAA,SAAS,SAAS,GAAG,GAAG;AAC3B,iBAAW,SAAS,MAAM,GAAG,EAAE,CAAC;AAAA,IACjC;AACA,QAAI,CAAC,UAAU;AACd,YAAM,IAAI,MAAM,oCAAoC,KAAK,IAAI,EAAE;AAAA,IAChE;AACO,WAAA,GAAG,IAAI,IAAI,QAAQ;AAAA,EAC3B;AAEO,WAAS,SAAS,MAA6B;AACrD,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACjC,YAAA,SAAS,IAAI;AAGnB,aAAO,SAAS,MAAM;AACrB,cAAM,aAAa,OAAO;AAC1B,YAAI,CAAC,YAAY;AACT;AACP;AAAA,QACD;AAEK,aAAA,OAAO,OAAO,OAAO,SAAS,UAAU,EAAE,KAAK,CAAC,SAAS;AACvD,gBAAA,aAAa,IAAI,IAAI;AAC3B,kBAAQ,UAAU;AAAA,QAAA,CAClB;AAAA,MAAA;AAKF,aAAO,kBAAkB,IAAI;AAAA,IAAA,CAC7B;AAAA,EACF;AAEO,WAAS,kBAAkB,MAAoB;AACjD,QAAA,CAAC,KAAK,QAAQ,CAAC,KAAK,QAAQ,CAAC,KAAK,MAAM;AAC3C,YAAM,UAAU;AAChB,cAAQ,MAAM,GAAG,OAAO,IAAI,IAAI;AAChC,YAAM,IAAI,MAAM,GAAG,OAAO,GAAG;AAAA,IAC9B;AACO,WAAA,GAAG,KAAK,IAAI,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI;AAAA,EAC7C;AAEgB,WAAA,eAAe,MAAY,SAA0C;AAC7E,WAAA,IAAI,KAAK,CAAC,IAAI,GAAG,SAAS,EAAE,MAAM,KAAK,KAAA,CAAM;AAAA,EACrD;AAEgB,WAAA,qBAAqB,UAAkB,MAAc;AAC9D,UAAA,UAAU,SAAS,cAAc,GAAG;AAC1C,YAAQ,aAAa,QAAQ,mCAAmC,mBAAmB,IAAI,CAAC;AAChF,YAAA,aAAa,YAAY,QAAQ;AAEzC,YAAQ,MAAM,UAAU;AACf,aAAA,KAAK,YAAY,OAAO;AAEjC,YAAQ,MAAM;AAEL,aAAA,KAAK,YAAY,OAAO;AAAA,EAClC;AAGa,QAAA,gCAAgC,OAAO,UAAgD;AACnG,UAAM,eAAkD,CAAA;AACxD,eAAW,QAAQ,OAAO;AACnB,YAAA,OAAO,MAAM,SAAS,IAAI;AAChC,mBAAa,IAAI,IAAI;AAAA,QACpB;AAAA,QACA,WAAW,KAAK,KAAK,MAAM,GAAG,EAAE,SAAS;AAAA,QACzC,WAAW,KAAK;AAAA,QAChB,MAAM,KAAK;AAAA,MAAA;AAAA,IAEb;AACO,WAAA,OAAO,OAAO,YAAY;AAAA,EAClC;AAEa,QAAA,aAAa,OAAO,YAAmC;AAGnE,YAAQ,MAAM,MAAM,OAAO,GAAG,KAAK;AAAA,EACpC;AAEa,QAAA,eAAe,CAAC,SAAgC;AAC5D,WAAO,IAAI,QAAQ,CAAC,SAAS,MAAM;AAC5B,YAAA,SAAS,IAAI;AACnB,aAAO,YAAY,MAAM;;AACxB,kBAAQF,MAAA,OAAO,WAAP,gBAAAA,IAAe,eAAc,EAAE;AAAA,MAAA;AAExC,aAAO,cAAc,IAAI;AAAA,IAAA,CACzB;AAAA,EACF;AAKO,WAAS,aAAa,MAAY;AACxC,UAAM,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC;AACrBI,cAAAA,OAAA,MAAM,KAAK,IAAI;AAAA,EACvB;AC/GA,QAAM,WAAgE,CAAA;AAY/D,WAAS,YACf,OACA,OACA,UACG,MACF;AACK,UAAA,iBAAiB,SAAS,KAAK;AACrC,QAAI,YAAY;AAChB,QAAI,CAAC,gBAAgB;AACpB,eAAS,KAAK,IAAI,EAAE,CAAC,KAAK,GAAG,KAAK;AACtB,kBAAA;AAAA,IAAA,OACN;AACA,YAAA,yBAAyB,eAAe,KAAK;AACnD,UAAI,CAAC,wBAAwB;AAC5B,uBAAe,KAAK,IAAI;AACZ,oBAAA;AAAA,MACb;AAAA,IACD;AACA,QAAI,WAAW;AACN,cAAA,KAAK,EAAE,GAAG,IAAI;AAAA,IACvB;AAAA,EACD;AC1BO,WAAS,QAAW,OAAsB;AAChD,WAAO,EAAE,GAAG,OAAO,YAAYC,KAAAA,GAAS,EAAA;AAAA,EACzC;AAOO,WAAS,kBAA+C,OAAyC;AACvG,UAAM,YAAoC,CAAA;AAC1C,eAAW,QAAQ,OAAO;AACf,gBAAA,KAAK,UAAU,IAAI;AAAA,IAC9B;AACO,WAAA;AAAA,EACR;ACnBa,QAAA,sBAAsB,CAAC,OAAsB,QAAoD;AACtG,WAAA;AAAA,MACN,OAAO,MAAM,SAAS;AAAA,MACtB,WAAW;AAAA,MACX;AAAA,MACA,MAAM;AAAA,IAAA;AAAA,EAER;ACAO,WAAS,qBAAqB,KAAa,YAAgC,QAAW,YAAY,KAAa;AACjH,QAAA,MAAM,IAAI,QAAQ,mBAAmB,GAAG,EAAE,QAAQ,UAAU,GAAG;AACnE,QAAI,CAAC,WAAW;AACT,YAAA,QAAQ,IAAI,MAAM,GAAG;AACvB,UAAA,MAAM,SAAS,GAAG;AACT,oBAAA,MAAM,MAAM,SAAS,CAAC;AAAA,MACnC;AAAA,IACD;AACA,QAAI,aAAa,CAAC,UAAU,WAAW,GAAG,GAAG;AAC5C,kBAAY,MAAM;AAAA,IACnB;AACM,UAAA,4BAA4B,YAAY,UAAU,SAAS;AAE7D,QAAA,IAAI,SAAS,4BAA4B,WAAW;AACvD,YAAM,IAAI,MAAM,GAAG,YAAY,yBAAyB,KAAK,aAAa;AAAA,IAC3E;AACO,WAAA;AAAA,EACR;AAEO,WAAS,oBAAoB,OAAuB;AAC1D,WAAO,MAAM,YAAc,EAAA,QAAQ,KAAK,GAAG;AAAA,EAC5C;AAEgB,WAAA,QAAQ,KAAa,aAAa,OAAO;AACxD,WAAO,IACL,UAAU,MAAM,EAChB,YAAA,EACA,QAAQ,aAAa,EAAE,EACvB,KACA,EAAA,QAAQ,WAAW,aAAa,MAAM,GAAG;AAAA,EAC5C;AAQgB,WAAA,SAAS,KAAa,WAAmB;AACpD,QAAA,IAAI,UAAU,WAAW;AACrB,aAAA;AAAA,IACR;AAEA,UAAM,YAAY,IAAI,MAAM,GAAG,YAAY,CAAC;AAC5C,WAAO,UAAU,MAAM,GAAG,UAAU,YAAY,GAAG,CAAC,IAAI;AAAA,EACzD;AClDa,QAAA,oCACZ,CAAc,aACd,CAAC,SACD,CAAC,UACA,SAAS,OAAO,IAAI;AAEN,WAAA,qBAAqB,OAAqB,OAAeC,OAAsB;AACvF,WAAAA,MAAK,UAAU,CAAC,MAAM,EAAE,eAAe,MAAM,UAAU,MAAM;AAAA,EACrE;AAEgB,WAAA,iBAAiB,OAAwB,OAAeA,OAAyB;AAE/F,WAAAA,MAAK,UAAU,CAAC,MAAuB;AAC/B,aAAA,EAAE,cAAc,MAAM;AAAA,IAC7B,CAAA,MAAM;AAAA,EAET;AAOgB,WAAA,mBAAmB,QAAoC,aAAmC;AAEzG,WACC,OAAO,CAAC,EAAE,CAAC,IAAI,YAAY,CAAC,KAC5B,OAAO,CAAC,EAAE,CAAC,IAAI,YAAY,CAAC,KAC5B,OAAO,CAAC,EAAE,CAAC,IAAI,YAAY,CAAC,KAC5B,OAAO,CAAC,EAAE,CAAC,IAAI,YAAY,CAAC;AAAA,EAE9B;AAEO,QAAM,aAAa;ACpC1B,MAAI,QAAQ;AAEZ,QAAM,8BAA+B,CAAA,EAAgB,+BAAsD;AAE3G,MAAI,CAAC,QAAQ,GAAG,EAAE,SAAS,4BAA4B,YAAA,CAAa,GAAG;AAC9D,YAAA;AAAA,EACT;AAEgB,WAAA,aAAa,MAA+B,MAA+B;AAE1F,QAAI,SAAS;AAAa,aAAA;AAEtB,QAAA,OAAO,SAAS,OAAO,MAAM;AACzB,aAAA;AAAA,IACR;AAEM,UAAA,QAAQ,OAAO,KAAK,IAAI;AACxB,UAAA,QAAQ,OAAO,KAAK,IAAI;AAG9B,UAAM,cAAc,MAAM;AAC1B,QAAI,gBAAgB,MAAM;AAAe,aAAA;AAEzC,aAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AAC/B,YAAA,MAAM,MAAM,CAAC;AACnB,UAAI,CAAC,OAAO,UAAU,eAAe,KAAK,MAAM,GAAG,KAAK,KAAK,GAAG,MAAM,KAAK,GAAG,GAAG;AACzE,eAAA;AAAA,MACR;AAAA,IACD;AAEO,WAAA;AAAA,EACR;AAEO,WAAS,QAAiD,MAAY;AAE5E,UAAM,OAAO,CAAA;AAEb,WAAO,WAAY;AAElB,YAAM,OAAO,MAAM,UAAU,MAAM,KAAK,SAAS;AAMjD,UAAI,QAAQ,MAAM;AACjB,YAAI,OAAO;AACV,kBAAQ,MAAM,uDAAuD,KAAK,SAAU,CAAA,KAAK,MAAM,GAAG;AAAA,QACnG;AAGA,eAAO,KAAK,IAAI;AAAA,MAAA,OACV;AACN,YAAI,OAAO;AACV,kBAAQ,MAAM,4CAA4C,KAAK,SAAU,CAAA,KAAK,MAAM,GAAG;AAAA,QACxF;AAGA,eAAQ,KAAK,IAAI,IAAI,KAAK,MAAM,MAAM,IAAI;AAAA,MAC3C;AAAA,IAAA;AAAA,EAEF;AAIgB,WAAA,eACf,MACA,SACqB;AAEf,UAAA,cAAcC,MAAAA,OAAe,MAAS;AAC5C,UAAM,WAA+B,YAAY;AAI3C,UAAA,UAAU,QAAQ,UAAU,IAAI;AAKtCC,UAAAA,UAAU,MAAM;AACf,UAAI,CAAC,SAAS;AACb,oBAAY,UAAU;AAAA,MACvB;AAAA,IAAA,CACA;AAGD,WAAO,UAAU,WAAW;AAAA,EAC7B;AAMgB,WAAA,eAAe,OAAkB,QAAmB;AAC/D,QAAA,MAAM,WAAW,OAAO;AAAe,aAAA;AAC3C,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACtC,UAAI,MAAM,CAAC,MAAM,OAAO,CAAC;AAAU,eAAA;AAAA,IACpC;AACO,WAAA;AAAA,EACR;AAEa,QAAA,cAAsC,MAAM;AC7E5C,QAAA,eAAyB;AACzB,QAAA,eAAyB;AACzB,QAAA,eAAyB;AACzB,QAAA,aAAuB;AACvB,QAAA,QAAkB;AAClB,QAAA,SAAmB;AAOzB,QAAM,SAAmC;AAAA,IAC/C,MAAOC,OAAkC,KAAA;AAAA,IACzC,MAAOC,OAAkC,KAAA;AAAA,IACzC,OAAQC,OAAmC,MAAA;AAAA,IAC3C,QAASC,OAAoC,OAAA;AAAA,IAC7C,OAAQC,OAAmC,MAAA;AAAA,IAC3C,QAASC,OAAoC,OAAA;AAAA,IAC7C,KAAMC,OAAiC,IAAA;AAAA,IACvC,SAAUC,OAAqC,QAAA;AAAA,IAC/C,MAAOC,OAAkC,KAAA;AAAA,IACzC,MAAOC,OAAkC,KAAA;AAAA,IACzC,QAASC,OAAoC,OAAA;AAAA,IAC7C,QAASC,OAAoC,OAAA;AAAA,IAC7C,MAAOC,OAAkC,KAAA;AAAA,IACzC,QAASC,OAAoC,OAAA;AAAA,IAC7C,MAAOC,OAAkC,KAAA;AAAA,IACzC,MAAOC,OAAkC,KAAA;AAAA,IACzC,MAAOC,OAAkC,KAAA;AAAA,IACzC,OAAQC,OAAmC,MAAA;AAAA,IAC3C,MAAOC,OAAkC,KAAA;AAAA,IACzC,MAAOC,OAAkC,KAAA;AAAA,IACzC,KAAMC,OAAiC,IAAA;AAAA,EACxC;AAGO,QAAM,mBAA6C;AAAA,IACzD,QAASP,OAAoC,OAAA;AAAA,IAC7C,KAAMP,OAAiC,IAAA;AAAA,IACvC,QAASK,OAAoC,OAAA;AAAA,IAC7C,QAASR,OAAoC,OAAA;AAAA,IAC7C,MAAOa,OAAkC,KAAA;AAAA,IACzC,MAAOD,OAAkC,KAAA;AAAA,IACzC,MAAOd,OAAkC,KAAA;AAAA,IACzC,QAASI,OAAoC,OAAA;AAAA,IAC7C,MAAOa,OAAkC,KAAA;AAAA,IACzC,KAAME,OAAiC,IAAA;AAAA,IACvC,MAAOZ,OAAkC,KAAA;AAAA,EAC1C;AAEa,QAAA,oBAA8B;AAG9B,QAAA,sBAAsB,CAAC,aAAoC;AACjE,UAAA,QAAQ,SAAS,QAAQ;AACzB,UAAA,SAAS,SAAS,MAAM;AAC9B,UAAM,kBAA4B,MAAM,OAAO,IAAI,EAAE,IAAI;AAEzD,UAAM,YAAY,MAAM,UAAU,OAAO,QAAQ,YAAY;AAKtD,WAAA,EAAE,iBAAiB;EAC3B;AAEO,WAAS,cAAc,OAAyB;AAC/C,WAAA,OAAO,OAAO,gBAAgB,EAAE,QAAQ,OAAO,KAAK,gBAAgB,EAAE,MAAM;AAAA,EACpF;AC7Fa,QAAA,qBAAqB,QAAQ,CAAC,SAAyC;AACnF,QAAI,CAAC;AAAa,aAAA;AACZ,UAAA,SAAS,IAAI,KAAK,IAAI;AAC5B,UAAM,aAAa,OAAO,YAAY,MAAM,MAAM,YAAY;AAC9D,UAAM,UAAsC,EAAE,KAAK,WAAW,OAAO,QAAQ;AAC7E,QAAI,CAAC;AAAY,cAAQ,OAAO;AAChC,WAAO,OAAO,mBAAmB,CAAC,GAAG,OAAO;AAAA,EAC7C,CAAC;AAED,QAAM,WAAW,IAAI,KAAK,mBAAmB,CAAI,GAAA,EAAE,OAAO,QAAQ,SAAS,OAAA,CAAQ;AACnF,QAAM,UAAU,MAAO;AACvB,QAAM,4BAAY;AAGL,QAAA,UAAU,CAAC,SAAiC;AACxD,WAAO,IAAI,KAAK,IAAI,EAAE,aAAa,MAAM,MAAM;EAChD;AAMa,QAAA,6BAA6B,QAAQ,CAAC,MAA8B,KAAa,QAAgB;AAC7G,UAAM,OAAO,KAAK,OAAO,IAAI,KAAK,IAAI,EAAE,QAAY,IAAA,MAAM,QAAQ,KAAK,OAAO;AAC1E,QAAA,OAAO,OAAO,OAAO;AAAK,aAAO,mBAAmB,IAAI;AACrD,WAAA,SAAS,OAAO,MAAM,MAAM;AAAA,EACpC,CAAC;ACbM,WAAS,mBAA2B,gBAAwE;AAC5G,UAAA,SAAS,CAAoC,OAAe,WAAkC;AAE7F,YAAA,KAAK,eAAe,OAAO,OAAO;AAClC,YAAA,UAAU,EAAE,IAAI,OAAO;AAAA,IAAA;AAGxB,UAAA,UAAU,CAAoC,OAAe,WAAoC;AAC3F,iBAAA,SAAS,OAAO,SAAS;AAE7B,cAAA,KAAK,eAAe,KAAK;AACzB,cAAA,UAAU,EAAE,IAAI;AAAA,MACvB;AAAA,IAAA;AAGK,UAAA,SAAS,CAAoC,OAAe,WAAkC;AAC7F,YAAA,KAAK,eAAe,OAAO,OAAO;AAClC,YAAA,UAAU,EAAE,IAAI,OAAO;AAAA,IAAA;AAGxB,UAAA,UAAU,CAAoC,OAAe,WAAoC;AAC3F,iBAAA,SAAS,OAAO,SAAS;AAC7B,cAAA,KAAK,eAAe,KAAK;AACzB,cAAA,UAAU,EAAE,IAAI;AAAA,MACvB;AAAA,IAAA;AAGK,UAAA,YAAY,CAAoC,OAAe,WAAkC;AAChG,YAAA,KAAK,eAAe,OAAO,OAAO;AAClC,YAAA,UAAU,EAAE,IAAI,OAAO;AAAA,IAAA;AAGxB,UAAA,aAAa,CAAoC,OAAe,WAAoC;AAC9F,iBAAA,SAAS,OAAO,SAAS;AAC7B,cAAA,KAAK,eAAe,KAAK;AACzB,cAAA,UAAU,EAAE,IAAI;AAAA,MACvB;AAAA,IAAA;AAGK,UAAA,YAAY,CAAoC,OAAe,WAAkC;AAC/F,aAAA,MAAM,UAAU,OAAO,OAAO;AAAA,IAAA;AAGhC,UAAA,aAAa,CAAoC,OAAe,WAAoC;AAC9F,iBAAA,MAAM,OAAO,SAAS;AACzB,eAAA,MAAM,UAAU,EAAE;AAAA,MAC1B;AAAA,IAAA;AAGK,UAAA,aAAa,CAAoC,OAAe,WAAoC;AACzG,YAAM,YAAY;AACP,iBAAA,SAAS,OAAO,SAAS;AAE7B,cAAA,KAAK,eAAe,KAAK;AACzB,cAAA,UAAU,EAAE,IAAI;AAAA,MACvB;AAAA,IAAA;AAGK,UAAA,kBAAkB,CAAwB,UAAkB;AAC1D,aAAA;AAAA,QACN,GAAG;AAAA,QACH,WAAW,CAAC;AAAA,MAAA;AAAA,IACb;AAGM,WAAA;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEF;ACrFA,QAAM,kBAAkB,mBAAqC,CAAC,aAAa,SAAS,UAAU;AAE9F,QAAMf,iBAA8B,gBAAgB,gBAAgB,CAAA,CAAE;AAEzD,QAAA,gBAAgBC,QAAAA,YAAY;AAAA,IACxC,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,sBAAsB,gBAAgB;AAAA,MACtC,aAAa,gBAAgB;AAAA,MAC7B,gBAAgB,gBAAgB;AAAA,MAChC,gBAAgB,gBAAgB;AAAA,IACjC;AAAA,EACD,CAAC;AAEM,QAAM,EAAE,sBAAsB,aAAa,gBAAgB,mBAAmB,cAAc;AAEtF,QAAA,wBAAwB,CAAC,UAA4B,MAAM,gBAAgB;AAE3E,QAAA,mBAAmB4B,QAAAA,eAAe,CAAC,qBAAqB,GAAG,CAAC,oBAAoB;AACrF,WAAA,OAAO,OAAO,eAAe;AAAA,EACrC,CAAC;AAEM,QAAM,qBACZ,CAAC,OAA+B,CAAC,UAAU;AACnC,WAAA,MAAM,gBAAgB,UAAU,EAAE;AAAA,EAC1C;AAEY,QAAA,wBAAwB;AAAA,IACpCA,QAAA;AAAA,MACC,CAAC,uBAAuB,CAAC,QAAQ,gBAA0C,WAAW;AAAA,MACtF,CAAC,iBAAiB,gBAAgB;AACjC,cAAM,aAAiC,CAAA;AAEvC,mBAAW,cAAc,aAAa;AAC/B,gBAAA,WAAW,gBAAgB,UAAU;AAE3C,cAAI,UAAU;AACb,uBAAW,KAAK,QAAQ;AAAA,UAAA,OAClB;AACE,oBAAA,KAAK,uDAAuD,UAAU;AAAA,UAC/E;AAAA,QACD;AAEO,eAAA;AAAA,MACR;AAAA,IACD;AAAA,EACD;AAEa,QAAA,8BACZ;AAAA,IACCA,QAAA;AAAA,MAAe,CAAC,kBAAkB,CAAC,QAAQ,gBAAwB,WAAW;AAAA,MAAG,CAAC,YAAY,gBAC7F,WAAW,OAAO,CAAC,aAAa,SAAS,cAAc,WAAW;AAAA,IACnE;AAAA,EACD;AAEM,QAAM,6BACZ,CAAC,eAAe,CAAC,UAA4B;AAC5C,WAAO,OAAO,OAAO,MAAM,aAAa,SAAS,EAAE,OAAO,CAAC,UAAU,MAAM,aAAa,UAAU,EAAE;AAAA,EACrG;AAEY,QAAA,kBAA0C,cAAc;AC9DrE,QAAM,oBAAoB,mBAAuC,CAAC,eAAe,WAAW,UAAU;AAEtG,QAAM5B,iBAAe,kBAAkB,gBAAgB,CAAA,CAAE;AAE5C,QAAA,kBAAkBC,QAAAA,YAAY;AAAA,IAC1C,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,kBAAkB,kBAAkB;AAAA,MACpC,UAAU,kBAAkB;AAAA,MAC5B,WAAW,kBAAkB;AAAA,MAC7B,aAAa,kBAAkB;AAAA,MAC/B,cAAc,kBAAkB;AAAA,MAChC,cAAc,kBAAkB;AAAA,IACjC;AAAA,EACD,CAAC;AAEY,QAAA,qBAAoF,CAAC,UACjG,MAAM,kBAAkB;AAEZ,QAAA,uBACZ;AAAA,IACC4B,uBAAe,CAAC,oBAAoB,CAAC,QAAQ,YAAoB,OAAO,GAAG,CAAC,cAAc,YAAY;AACrG,aAAO,aAAa,OAAO;AAAA,IAAA,CAC3B;AAAA,EACF;AAEY,QAAA,oBAAoBA,QAAAA,eAAe,CAAC,kBAAkB,GAAG,CAAC,iBAAiB;AAChF,WAAA,OAAO,OAAO,YAAY;AAAA,EAClC,CAAC;AAEY,QAAA,+BAGT;AAAA,IACHA,uBAAe,CAAC,mBAAmB,CAAC,QAAQ,iBAA2B,YAAY,GAAG,CAAC,QAAQ,iBAAiB;AACzG,YAAA,kBAAkB,IAAI,IAAI,YAAY;AAC5C,YAAM,MAAoC,CAAA;AAC1C,iBAAW,SAAS,QAAQ;AAC3B,YAAI,gBAAgB,IAAI,MAAM,UAAU,GAAG;AAC1C,cAAI,CAAC,IAAI,MAAM,UAAU,GAAG;AACvB,gBAAA,MAAM,UAAU,IAAI;UACzB;AACA,cAAI,MAAM,UAAU,EAAG,KAAK,KAAK;AAAA,QAClC;AAAA,MACD;AACA,iBAAW,OAAO,KAAK;AACtB,YAAI,GAAG,IAAI,IAAI,GAAG,EAAG,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ;AAAA,MAC5D;AACO,aAAA;AAAA,IAAA,CACP;AAAA,EACF;AAEa,QAAA,+BAGT;AAAA,IACHA,uBAAe,CAAC,oBAAoB,CAAC,QAAQ,gBAAwB,WAAW,GAAG,CAAC,eAAe,gBAAgB;AAClH,YAAM,yBAAqD,CAAA;AAC3D,iBAAW,CAAC,SAAS,KAAK,KAAK,OAAO,QAAQ,aAAa,GAAG;AACzD,YAAA,MAAM,eAAe,aAAa;AACrC,iCAAuB,OAAO,IAAI;AAAA,QACnC;AAAA,MACD;AACO,aAAA;AAAA,IAAA,CACP;AAAA,EACF;AAEa,QAAA,0BAAyE;AAAA,IACrFA,uBAAe,CAAC,mBAAmB,CAAC,QAAQ,gBAAwB,WAAW,GAAG,CAAC,QAAQ,gBAAgB;AAC1G,aAAO,OAAO,OAAO,CAAC,UAAU,MAAM,eAAe,WAAW,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ;AAAA,IAAA,CACxG;AAAA,EACF;AAEa,QAAA,yBAAyB;AAAA,IACrCA,uBAAe,CAAC,oBAAoB,CAAC,QAAQ,aAAuB,QAAQ,GAAG,CAAC,cAAc,aAAa;AAC1G,YAAM,cAAoC,CAAA;AAE1C,iBAAW,WAAW,UAAU;AACzB,cAAA,QAAQ,aAAa,OAAO;AAElC,YAAI,OAAO;AACV,sBAAY,KAAK,KAAK;AAAA,QAAA,OAChB;AACE,kBAAA,KAAK,yDAAyD,OAAO;AAAA,QAC9E;AAAA,MACD;AAEO,aAAA;AAAA,IAAA,CACP;AAAA,EACF;AAGa,QAAA,iCAGT;AAAA,IACHA,uBAAe,CAAC,oBAAoB,CAAC,QAAQ,aAAuB,QAAQ,GAAG,CAAC,cAAc,aAAa;AAC1G,YAAM,MAA8B,CAAA;AACpC,iBAAW,WAAW,UAAU;AACzB,cAAA,QAAQ,aAAa,OAAO;AAClC,YAAI,CAAC,OAAO;AACL,gBAAA,IAAI,MAAM,iCAAiC,OAAO;AAAA,QACzD;AACA,YAAI,MAAM,MAAM;AACX,cAAA,OAAO,IAAI,MAAM;AAAA,QACtB;AAAA,MACD;AACO,aAAA;AAAA,IAAA,CACP;AAAA,EACF;AAEa,QAAA,EAAE,kBAAkB,UAAU,WAAW,cAAc,cAAc,YAAA,IACjF,gBAAgB;AAEJ,QAAA,oBAA8C,gBAAgB;AC3G3E,QAAM,mBAAmB,mBAAsC,CAAC,cAAc,UAAU,UAAU;AAElG,QAAM5B,iBAA+B,iBAAiB,gBAAgB,CAAA,CAAE;AAE3D,QAAA,iBAAiBC,QAAAA,YAAY;AAAA,IACzC,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,sBAAsB,iBAAiB;AAAA,MACvC,cAAc,iBAAiB;AAAA,MAC/B,iBAAiB,iBAAiB;AAAA,IACnC;AAAA,EACD,CAAC;AAEY,QAAA,EAAE,cAAc,sBAAsB,oBAAoB,eAAe;AAEzE,QAAA,0BAAsE,CAAC,UACnF,MAAM,iBAAiB;AAEX,QAAA,mBAAiD4B,QAAA;AAAA,IAAe,CAAC,uBAAuB;AAAA,IAAG,CAAC,YACxG,OAAO,OAAO,OAAO;AAAA,EACtB;AAEO,QAAM,sBACZ,CAAC,OAAgC,CAAC,UAAU;AACpC,WAAA,MAAM,iBAAiB,UAAU,EAAE;AAAA,EAC3C;AAEY,QAAA,wBAAwB;AAAA,IACpCA,QAAA;AAAA,MACC,CAAC,oBAAoB,CAAC,QAAQ,iBAA4C,YAAY;AAAA,MACtF,CAAC,kBAAkB,iBAAiB;AACnC,cAAM,aAAmC,CAAA;AAEzC,mBAAW,WAAW,cAAc;AAC7B,gBAAA,QAAQ,iBAAiB,OAAO;AAEtC,cAAI,OAAO;AACV,uBAAW,KAAK,KAAK;AAAA,UAAA,OACf;AACE,oBAAA,KAAK,sDAAsD,OAAO;AAAA,UAC3E;AAAA,QACD;AAEO,eAAA;AAAA,MACR;AAAA,IACD;AAAA,EACD;AAEa,QAAA,mBAA4C,eAAe;AClDxE,QAAM,eAAe,mBAAkC,CAAC,UAAU,MAAM,UAAU;AAElF,QAAM5B,iBAA2B,aAAa,gBAAgB,CAAA,CAAE;AAEnD,QAAA,aAAaC,QAAAA,YAAY;AAAA,IACrC,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,kBAAkB,CAAC,OAAO,WAAmC;AAC/C,qBAAA,WAAW,OAAO,MAAM;AACxB,qBAAA;AAAA,MACd;AAAA,MACA,UAAU,CAAC,OAAO,WAAiC;AACrC,qBAAA,OAAO,OAAO,MAAM;AACpB,qBAAA;AAAA,MACd;AAAA,MACA,WAAW,CAAC,OAAO,WAAwD;AAC7D,qBAAA,QAAQ,OAAO,MAAM;AACrB,qBAAA;AAAA,MACd;AAAA,MACA,UAAU,CAAC,OAAO,WAAiC;AACrC,qBAAA,OAAO,OAAO,MAAM;AACpB,qBAAA;AAAA,MACd;AAAA,MACA,WAAW,CAAC,OAAO,WAAmC;AACxC,qBAAA,QAAQ,OAAO,MAAM;AACrB,qBAAA;AAAA,MACd;AAAA,MAEA,aAAa,CAAC,OAAO,WAAiC;AACxC,qBAAA,UAAU,OAAO,MAAM;AACvB,qBAAA;AAAA,MACd;AAAA,MACA,cAAc,CAAC,OAAO,WAAmC;AAC3C,qBAAA,WAAW,OAAO,MAAM;AACxB,qBAAA;AAAA,MACd;AAAA,MACA,aAAa,CAAC,OAAO,WAAkC;AACzC,qBAAA,UAAU,OAAO,MAAM;AACvB,qBAAA;AAAA,MACd;AAAA,MACA,cAAc,CAAC,OAAO,WAAoC;AAC5C,qBAAA,WAAW,OAAO,MAAM;AACxB,qBAAA;AAAA,MACd;AAAA,IACD;AAAA,EACD,CAAC;AAEY,QAAA;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI,WAAW;AAOf,MAAI,aAA6B;AACpB,QAAA,eAAe,CAAC,UAA4B;AACxD,QAAI,CAAC,YAAY;AAChB,mBAAa,OAAO,OAAO,MAAM,aAAa,SAAS;AAAA,IACxD;AACO,WAAA;AAAA,EACR;AAEa,QAAA,sBAAsB,CAAC,UAA4B,MAAM,aAAa;AAEtE,QAAA,0BAAoE;AAAA,IAChF4B,uBAAe,CAAC,cAAc,CAAC,QAAQ,gBAAwB,WAAW,GAAG,CAAC,YAAY,gBAAgB;AACzG,aAAO,WAAW,OAAO,CAAC,UAAU,MAAM,eAAe,WAAW;AAAA,IAAA,CACpE;AAAA,EACF;AAEO,QAAM,kBAA0D,CAAC,YAAY,CAAC,UAA4B;AACzG,WAAA,MAAM,aAAa,UAAU,OAAO;AAAA,EAC5C;AAEa,QAAA,oBAAoB;AAAA,IAChCA,uBAAe,CAAC,qBAAqB,CAAC,GAAG,aAAuB,QAAQ,GAAG,CAAC,eAAe,aAAa;AACvG,YAAM,SAA0B,CAAA;AAEhC,iBAAW,WAAW,UAAU;AACzB,cAAA,QAAQ,cAAc,OAAO;AAE/B,YAAA;AAAO,iBAAO,KAAK,KAAK;AAAA,MAC7B;AAEO,aAAA;AAAA,IAAA,CACP;AAAA,EACF;AAEa,QAAA,gCAA4EA,QAAA;AAAA,IACxF,CAAC,cAAc,uBAAuB;AAAA,IACtC,CAAC,QAAQ,qBAAqB;AAC7B,YAAM,MAAiC,CAAA;AAEvC,iBAAW,SAAS,QAAQ;AACrB,cAAA,YAAY,iBAAiB,MAAM,UAAU;AAEnD,YAAI,CAAC,WAAW;AACP,kBAAA;AAAA,YACP,sBAAsB,MAAM,UAAU;AAAA;AAAA;AAAA,UAAA;AAIvC,iBAAO;QACR;AACI,YAAA,MAAM,UAAU,IAAI;AAAA,MACzB;AAEO,aAAA;AAAA,IACR;AAAA,EACD;AAEO,QAAM,kCACZ,CAAC,gBAAgB,CAAC,UAAU;;AAC3B,QAAI,CAAC;AAAoB,aAAA;AACzB,YAAO9B,MAAA,wBAAwB,WAAW,EAAE,KAAK,MAA1C,gBAAAA,IAA6C;AAAA,EACrD;AAEM,QAAM,0BACZ,CAAC,iBAA2B,CAAC,UAA4B;AACxD,WAAO,aAAa,OAAoB,CAAC,KAAK,gBAAgB;AAC7D,YAAM,YAAY,MAAM,iBAAiB,UAAU,WAAW;AAC9D,UAAI,WAAW;AACd,YAAI,KAAK,SAAS;AAAA,MACnB;AACO,aAAA;AAAA,IACR,GAAG,CAAE,CAAA;AAAA,EACN;AAEY,QAAA,eAAoC,WAAW;ACrJ5D,QAAM,yBAAyB,mBAA4C,CAAC,eAAe,WAAW,UAAU;AAEhH,QAAME,iBAAe,uBAAuB,gBAAgB,CAAA,CAAE;AAEjD,QAAA,uBAAuBC,QAAAA,YAAY;AAAA,IAC/C,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,4BAA4B,uBAAuB;AAAA,MACnD,oBAAoB,uBAAuB;AAAA,MAC3C,qBAAqB,uBAAuB;AAAA,MAC5C,oBAAoB,uBAAuB;AAAA,MAC3C,qBAAqB,uBAAuB;AAAA,MAC5C,uBAAuB,uBAAuB;AAAA,MAC9C,wBAAwB,uBAAuB;AAAA,MAC/C,uBAAuB,uBAAuB;AAAA,MAC9C,wBAAwB,uBAAuB;AAAA,IAChD;AAAA,EACD,CAAC;AAEY,QAAA;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI,qBAAqB;AAEZ,QAAA,+BAA+B,CAAC,UAA4B,MAAM,uBAAuB;AAEzF,QAAA,yBAAqE4B,QAAA;AAAA,IACjF,CAAC,4BAA4B;AAAA,IAC7B,CAAC,YAAY,OAAO,OAAO,OAAO;AAAA,EACnC;AAEO,QAAM,wBACZ,CAAC,iBAAyB,CAAC,UAAU;AAC7B,WAAA,MAAM,uBAAuB,UAAU,YAAY;AAAA,EAC3D;AAEY,QAAA,2BAA2B;AAAA,IACvCA,QAAA;AAAA,MACC,CAAC,wBAAwB,CAAC,QAA0B,YAAoB,OAAO;AAAA,MAC/E,CAAC,aAAa,YAAY;AACzB,eAAO,YAAY,OAAO,CAAC,EAAE,MAAM,MAAM,YAAY,KAAK;AAAA,MAC3D;AAAA,IACD;AAAA,EACD;AAEa,QAAA,iCAAiC;AAAA,IAC7CA,QAAA;AAAA,MACC,CAAC,wBAAwB,CAAC,QAA0B,YAAoB,OAAO;AAAA,MAC/E,CAAC,aAAa,YAAY;AACnB,cAAA,qBAAqB,YAAY,OAAO,CAAC,EAAE,YAAY,YAAY,KAAK;AAC9E,cAAM,kBAAkB,mBAAmB;AAAA;AAAA,UAE1C,CAAC,EAAE,UAAU,MAAM,CAAC,aAAa,CAAC,UAAU,WAAW,QAAQ;AAAA,QAAA;AAEhE,cAAM,mBAAmB,mBAAmB;AAAA;AAAA,UAE3C,CAAC,EAAE,UAAA,MAAgB,aAAa,UAAU,WAAW,QAAQ;AAAA,QAAA;AAEvD,eAAA,EAAE,iBAAiB;MAC3B;AAAA,IACD;AAAA,EACD;AAEa,QAAA,yBAAwD,qBAAqB;AClE1F,QAAM5B,iBAA0C;AAAA,IAC/C,sBAAsB,CAAC;AAAA,EACxB;AAGa,QAAA,4BAA4BC,QAAAA,YAAY;AAAA,IACpD,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,oBAAoB,CAAC,OAAO,WAAgD;AAC3E,YAAI,+BAA+B,MAAM,qBAAqB,OAAO,QAAQ,KAAK;AAClF,YAAI,CAAC,8BAA8B;AAClC,yCAA+B,CAAA;AAC/B,gBAAM,qBAAqB,OAAO,QAAQ,KAAK,IAAI;AAAA,QACpD;AACA,qCAA6B,OAAO,QAAQ,KAAK,KAAQ,oBAAA,KAAA,GAAO;MACjE;AAAA,MACA,qBAAqB,CAAC,OAAO,WAAkD;AACnE,mBAAA,CAAC,SAAS,8BAA8B,KAAK,OAAO,QAAQ,OAAO,OAAO,GAAG;AACvF,cAAI,OAAO,KAAK,8BAA8B,EAAE,WAAW;AAC1D,kBAAM,IAAI,MAAM,uEAAuE,OAAO,EAAE;AAC7F,cAAA,uBAAuB,MAAM,qBAAqB,OAAO;AAC7D,cAAI,yBAAyB,QAAW;AACvC,mCAAuB,CAAA;AAAA,UACxB;AAEA,qBAAW,CAAC,SAAS,cAAc,KAAK,OAAO,QAAQ,8BAA8B,GAAG;AACvF,iCAAqB,OAAO,IAAI;AAAA,UACjC;AAEM,gBAAA,qBAAqB,OAAO,IAAI;AAAA,QACvC;AAAA,MACD;AAAA,MACA,wBAAwB,CAAC,OAAO,WAAkD;AACtE,mBAAA,cAAc,OAAO,SAAS;AACxC,gBAAM,uBAAuB,MAAM,qBAAqB,WAAW,KAAK;AAExE,cAAI,CAAC,wBAAwB,EAAE,WAAW,SAAS,uBAAuB;AAGjE,oBAAA;AAAA,cACP;AAAA,YAAA;AAGD;AAAA,UACD;AACO,iBAAA,qBAAqB,WAAW,KAAK;AAAA,QAC7C;AAAA,MACD;AAAA,MACA,qBAAqB,CAAC,OAAO,WAAkD;AAC9E,cAAM,uBAAuB,OAAO;AAAA,MACrC;AAAA,IACD;AAAA,EACD,CAAC;AACM,QAAM,EAAE,oBAAoB,qBAAqB,wBAAwB,wBAC/E,0BAA0B;AAEd,QAAA,wBAAwB,CAAC,UAA4B;AACjE,WAAO,MAAM,4BAA4B;AAAA,EAC1C;AAEa,QAAA,kCACZ;AAAA,IACC4B,uBAAe,CAAC,uBAAuB,CAAC,QAAQ,UAAiB,KAAK,GAAG,CAAC,iBAAiB,UAAU;AACpG,aAAO,OAAO,KAAK,gBAAgB,MAAM,UAAU,KAAK,CAAA,CAAE;AAAA,IAAA,CAC1D;AAAA,EACF;AAEY,QAAA,8BAAkE,0BAA0B;ACrEzG,QAAM,6BAA6B;AAAA,IAClC,CAAC,eAAe,WAAW;AAAA,EAC5B;AAEA,QAAM5B,iBAAe,2BAA2B,gBAAgB,CAAA,CAAE;AAErD,QAAA,2BAA2BC,QAAAA,YAAY;AAAA,IACnD,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,gCAAgC,2BAA2B;AAAA,MAC3D,wBAAwB,2BAA2B;AAAA,MACnD,yBAAyB,2BAA2B;AAAA,MACpD,wBAAwB,2BAA2B;AAAA,MACnD,yBAAyB,2BAA2B;AAAA,MACpD,2BAA2B,2BAA2B;AAAA,MACtD,4BAA4B,2BAA2B;AAAA,MACvD,2BAA2B,2BAA2B;AAAA,MACtD,4BAA4B,2BAA2B;AAAA,IACxD;AAAA,EACD,CAAC;AAEY,QAAA;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI,yBAAyB;AAEhB,QAAA,mCAAmC,CAAC,UAA4B,MAAM,2BAA2B;AAEjG,QAAA,6BAA6E4B,QAAA;AAAA,IACzF,CAAC,gCAAgC;AAAA,IACjC,CAAC,YAAY,OAAO,OAAO,OAAO;AAAA,EACnC;AAEO,QAAM,4BACZ,CAAC,iBAAyB,CAAC,UAAU;AAC7B,WAAA,MAAM,2BAA2B,UAAU,YAAY;AAAA,EAC/D;AAEY,QAAA,+BAA+B;AAAA,IAC3CA,QAAA;AAAA,MACC,CAAC,4BAA4B,CAAC,QAA0B,gBAAwB,WAAW;AAAA,MAC3F,CAAC,aAAa,gBAAgB;AAC7B,eAAO,YAAY,OAAO,CAAC,EAAE,WAAW,MAAM,gBAAgB,UAAU;AAAA,MACzE;AAAA,IACD;AAAA,EACD;AAEa,QAAA,qCAAqC;AAAA,IACjDA,QAAA;AAAA,MACC,CAAC,4BAA4B,CAAC,QAA0B,gBAAwB,WAAW;AAAA,MAC3F,CAAC,aAAa,gBAAgB;AACvB,cAAA,yBAAyB,YAAY,OAAO,CAAC,EAAE,iBAAiB,eAAe,WAAW;AAChG,cAAM,kBAAkB,uBAAuB;AAAA;AAAA,UAE9C,CAAC,EAAE,UAAU,MAAM,CAAC,aAAa,CAAC,UAAU,WAAW,QAAQ;AAAA,QAAA;AAEhE,cAAM,mBAAmB,uBAAuB;AAAA;AAAA,UAE/C,CAAC,EAAE,UAAA,MAAgB,aAAa,UAAU,WAAW,QAAQ;AAAA,QAAA;AAEvD,eAAA,EAAE,iBAAiB;MAC3B;AAAA,IACD;AAAA,EACD;AAEa,QAAA,6BAAgE,yBAAyB;ACjFtG,QAAM,mBAAmB,mBAA8B,CAAC,cAAc,UAAU,UAAU;AAE1F,QAAM5B,iBAA+B,iBAAiB,gBAAgB,CAAA,CAAE;AAE3D,QAAA,iBAAiBC,QAAAA,YAAY;AAAA,IACzC,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,UAAU;AAAA,MACT,sBAAsB,iBAAiB;AAAA,MACvC,eAAe,iBAAiB;AAAA,MAChC,cAAc,iBAAiB;AAAA,MAC/B,iBAAiB,iBAAiB;AAAA,MAClC,iBAAiB,iBAAiB;AAAA,IACnC;AAAA,EACD,CAAC;AAEM,QAAM,EAAE,sBAAsB,eAAe,cAAc,iBAAiB,gBAAA,IAClF,eAAe;AAEH,QAAA,yBAAqE,CAAC,UAClF,MAAM,iBAAiB;AAEX,QAAA,mBAAmB4B,QAAAA,eAAe,CAAC,sBAAsB,GAAG,CAAC,YAAY,OAAO,OAAO,OAAO,CAAC;AAE/F,QAAA,sBAA8DA,QAAA;AAAA,IAC1E,CAAC,gBAAgB;AAAA,IACjB,CAAC,eAAe;AACR,aAAA,WAAW,KAAK,CAAC,cAAc,UAAU,KAAK,kBAAkB,MAAM;AAAA,IAC9E;AAAA,EACD;AAEO,QAAM,sBAA0E,CAAC,gBAAgB,CAAC,UAAU;AAC3G,WAAA,MAAM,iBAAiB,UAAU,WAAW;AAAA,EACpD;AAEa,QAAA,8BAA4DA,QAAA;AAAA,IACxE,CAAC,sBAAsB;AAAA,IACvB,CAAC,YAAY;AACZ,aAAO,IAAI;AAAA,QACV,OAAO,OAAO,OAAO,EACnB,OAAO,CAAC,cAAyB,UAAU,SAAS,EACpD,IAAI,CAAC,cAAyB,UAAU,UAAU;AAAA,MAAA;AAAA,IAEtD;AAAA,EACD;AAEa,QAAA,mBAA4C,eAAe;ACrCxE,QAAM,kBAAkB;AAUxB,QAAM,eAAe,mBAAkC,CAAC,UAAU,MAAM,UAAU;AAElF,QAAM5B,iBAA2B,aAAa,gBAAgB;AAAA,IAC7D,gBAAgB,CAAC;AAAA,EAClB,CAAC;AAEY,QAAA,aAAaC,QAAAA,YAAY;AAAA,IACrC,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YACf,QAAQ,QAAQ,SAAS,CAAC,UAAU;AAC5B,aAAA,OAAO,OAAOA,cAAY;AAAA,IAAA,CACjC;AAAA,IACF,UAAU;AAAA,MACT,kBAAkB,aAAa;AAAA,MAC/B,UAAU,aAAa;AAAA,MACvB,WAAW,aAAa;AAAA,MACxB,aAAa,aAAa;AAAA,MAC1B,aAAa,aAAa;AAAA,MAC1B,cAAc,aAAa;AAAA,MAE3B,mBAAmB,CAAC,UAAU;AACvB,cAAA,iBAAiB,MAAM,eAAe,OAAO,CAAC,gBAAgB,MAAM,UAAU,YAAY,SAAS,CAAC;AAAA,MAC3G;AAAA,MACA,mBAAmB,CAAC,OAAO,WAAgC;AACpD,cAAA,iBAAiB,MAAM,eAAe;AAAA,UAC3C,CAAC,gBAAgB,YAAY,cAAc,OAAO;AAAA,QAAA;AAEnD,cAAM,eAAe,KAAK,EAAE,WAAW,OAAO,QAAQ,YAAY,GAAG,qBAAqB,KAAK,IAAI,EAAG,CAAA;AAElG,YAAA,MAAM,eAAe,SAAS,iBAAiB;AAClD,gBAAM,eAAe;QACtB;AAAA,MACD;AAAA,MACA,mBAAmB,CAAC,UAAU;AAC7B,cAAM,iBAAiB;MACxB;AAAA,MACA,mBAAmB,CAAC,OAAO,WAAkC;AAC5D,cAAM,gBAAgB,MAAM,eAAe,UAAU,CAAC,SAAS;AACvD,iBAAA,KAAK,aAAa,OAAO;AAAA,QAAA,CAChC;AACD,YAAI,kBAAkB,IAAI;AACnB,gBAAA,eAAe,OAAO,eAAe,CAAC;AAAA,QAC7C;AAAA,MACD;AAAA,IACD;AAAA,EACD,CAAC;AAEY,QAAA;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI,WAAW;AASF,QAAA,qBAAqB,CAAC,UAA4B,MAAM,aAAa;AACrE,QAAA,uBAAuB,CAAC,UAA4B,MAAM,aAAa;AAE7E,QAAM,kBACZ,CAAC,OAAe,CAAC,UAA4B;AACrC,WAAA,MAAM,aAAa,UAAU,EAAE;AAAA,EACvC;AAGY,QAAA,eACZ;AAAA,IACC4B,QAAA;AAAA,MACC,CAAC,oBAAoB,wBAAwB,CAAC,QAAQ,eAA2B,UAAU;AAAA,MAC3F,CAAC,SAAS,kBAAkB,eAAe;AAC1C,YAAI,aAAa,WAAW;AAC5B,cAAM,aAAa,WAAW;AAC9B,qBAAa,WAAW;AACxB,cAAM,MAAqC,CAAA;AACrC,cAAA,SAAS,OAAO,OAAO,OAAO;AAEpC,YAAI,YAAY;AAChB,mBAAW,SAAS,QAAQ;AAKvB,cAAA,CAAC,MAAM,iBAAiB;AAC3B;AAAA,cACC;AAAA,cACA,MAAM;AAAA,cACN;AAAA,cACA,SAAS,MAAM,UAAU;AAAA,YAAA;AAE1B;AAAA,UACD;AACM,gBAAA,YAAY,iBAAiB,MAAM,eAAe;AAExD,cAAI,CAAC,WAAW;AACf;AAAA,cACC;AAAA,cACA,MAAM;AAAA,cACN;AAAA,cACA,uEAAuE,MAAM,UAAU;AAAA,yBACrE,MAAM,eAAe;AAAA,cACvC,OAAO,KAAK,gBAAgB;AAAA,YAAA;AAE7B;AAAA,UACD;AAEA,gBAAM,wBAAwB,UAAU;AACxC,cAAI,CAAC,uBAAuB;AAC3B;AAAA,cACC;AAAA,cACA,UAAU;AAAA,cACV;AAAA,cACA,aAAa,UAAU,IAAI;AAAA,YAAA;AAE5B;AAAA,UACD;AACM,gBAAA,MAAM,WAAW,QAAQ,GAAG,sBAAsB,YAAa,CAAA,IAAI,MAAM,KAAK,KAAK;AACzF,eACE,MAAM,SAAS,IAAI,cAAc,SAAS,UAAU,KACpD,OAAO,IAAI,YAAc,EAAA,SAAS,UAAU,GAC5C;AACD,gBAAI,KAAK,oBAAoB,OAAO,GAAG,CAAC;AACxC;AACI,gBAAA,cAAc,aAAa,YAAY;AACnC,qBAAA;AAAA,YACR;AAAA,UACD;AAAA,QACD;AACO,eAAA;AAAA,MACR;AAAA,IACD;AAAA,EACD;AAEY,QAAA,oBAAoB;AAAA,IAChCA,uBAAe,CAAC,oBAAoB,CAAC,GAAG,aAAuB,QAAQ,GAAG,CAAC,eAAe,aAAa;AACtG,YAAM,SAA0B,CAAA;AAEhC,iBAAW,WAAW,UAAU;AACzB,cAAA,QAAQ,cAAc,OAAO;AACnC,YAAI,OAAO;AACV,iBAAO,KAAK,KAAK;AAAA,QAAA,OACX;AACE,kBAAA,KAAK,kDAAkD,OAAO;AAAA,QACvE;AAAA,MACD;AAEO,aAAA;AAAA,IAAA,CACP;AAAA,EACF;AAEa,QAAA,oCACZA,QAAA;AAAA,IACC,CAAC,oBAAoB,sBAAsB,sBAAsB;AAAA,IACjE,CAAC,cAAc,gBAAgB,qBAAqB;AACnD,YAAM,MAA+C,CAAA;AACrD,iBAAW,qBAAqB,gBAAgB;AACzC,cAAA,QAAQ,aAAa,kBAAkB,SAAS;AACtD,YAAI,CAAC,OAAO;AAEX,kBAAQ,KAAK,+BAA+B;AAC5C;AAAA,QACD;AACI,YAAA,WAAW,SAAS,MAAM,iBAAiB;AACxC,gBAAA,iBAAiB,iBAAiB,MAAM,eAAe;AAC7D,cAAI,CAAC,gBAAgB;AAEpB;AAAA,cACC;AAAA,cACA,MAAM;AAAA,cACN;AAAA,cACA,SAAS,MAAM,UAAU;AAAA;AAAA;AAAA,YAAA;AAI1B;AAAA,UACD;AACA,gBAAM,eAAe,GAAG,eAAe,YAAY,IAAI,MAAM,KAAK;AAClE,gBAAM,eAAe;AAAA,YACpB,GAAG,oBAAoB,OAAO,YAAY;AAAA,YAC1C,qBAAqB,kBAAkB;AAAA,UAAA;AAExC,cAAI,KAAK,YAAY;AAAA,QACtB;AAAA,MACD;AACO,aAAA;AAAA,IACR;AAAA,EACD;AAEY,QAAA,eAAoC,WAAW;AChN5D,QAAM,mBAAmB,mBAAsC,CAAC,cAAc,UAAU,UAAU;AAElG,QAAM5B,iBAA+B,iBAAiB,gBAAgB,CAAA,CAAE;AAE3D,QAAA,iBAAiBC,QAAAA,YAAY;AAAA,IACzC,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YACf,QAAQ,QAAQ,SAAS,CAAC,UAAU;AAC5B,aAAA,OAAO,OAAOA,cAAY;AAAA,IAAA,CACjC;AAAA,IACF,UAAU;AAAA,MACT,sBAAsB,iBAAiB;AAAA,MACvC,cAAc,iBAAiB;AAAA,MAC/B,cAAc,iBAAiB;AAAA,MAC/B,iBAAiB,iBAAiB;AAAA,MAClC,iBAAiB,iBAAiB;AAAA,IACnC;AAAA,EACD,CAAC;AAEM,QAAM,EAAE,sBAAsB,cAAc,cAAc,iBAAiB,gBAAA,IACjF,eAAe;AAEH,QAAA,yBAAuE,CAAC,UAAU;AAC9F,WAAO,MAAM,iBAAiB;AAAA,EAC/B;AAEa,QAAA,mBAAyD4B,QAAA;AAAA,IACrE;AAAA,IACA,CAAC,eAAe;AACR,aAAA,OAAO,OAAO,UAAU;AAAA,IAChC;AAAA,EACD;AAEO,QAAM,sBACZ,CAAC,gBAAwB,CAAC,UAA4B;AAC9C,WAAA,MAAM,iBAAiB,UAAU,WAAW;AAAA,EACpD;AAEM,QAAM,wBACZ,CAAC,iBAA2B,CAAC,UAA4B;AACxD,UAAM,aAAkC,CAAA;AAExC,eAAW,eAAe,cAAc;AACvC,YAAM,YAAY,MAAM,iBAAiB,UAAU,WAAW;AAC9D,UAAI,WAAW;AACd,mBAAW,KAAK,SAAS;AAAA,MAAA,OACnB;AACE,gBAAA,KAAK,2DAA2D,WAAW;AAAA,MACpF;AAAA,IACD;AAEO,WAAA;AAAA,EACR;AAEY,QAAA,iCACZ;AAAA,IACCA,QAAA;AAAA,MACC,CAAC,kBAAkB,CAAC,GAAG,mBAA2B,cAAc;AAAA,MAChE,CAAC,YAAY,mBAAmB;AAC/B,eAAO,WAAW,OAAO,CAAC,cAAc,UAAU,iBAAiB,cAAc;AAAA,MAClF;AAAA,IACD;AAAA,EACD;AAEY,QAAA,0BACZ;AAAA,IACCA,QAAA;AAAA,MACC,CAAC,CAAC,UAA4B,MAAM,aAAa,WAAW,CAAC,GAAG,gBAAwB,WAAW;AAAA,MACnG,CAAC,eAAe,gBAAgB;AACxB,eAAA,OAAO,OAAO,aAAa,EAAE,OAAO,CAAC,UAAU,MAAM,eAAe,WAAW;AAAA,MACvF;AAAA,IACD;AAAA,EACD;AAEM,QAAM,+BACZ,CAAC,gBAAwB,CAAC,UAAU;;AACnC,aAAO9B,MAAA,wBAAwB,WAAW,EAAE,KAAK,MAA1C,gBAAAA,IAA6C,WAAU;AAAA,EAC/D;AAEY,QAAA,mBAA4C,eAAe;AC7ExE,QAAME,iBAA0B;AAAA,IAC/B,QAAQ,CAAC;AAAA,EACV;AAEA,QAAM,YAAY,MAAO,KAAK;AAC9B,QAAM,YAAY,YAAY,KAAK;AAKtB,QAAA,YAAYC,QAAAA,YAAY;AAAA,IACpC,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,cAAc,CAAC,OAAO,WAAwC;AAC7D,cAAM,EAAE,KAAK,QAAQ,KAAA,IAAS,OAAO;AAC/B,cAAA6B,6BAAY;AAClB,cAAM,gBAAgB,IAAI,KAAKA,OAAM,QAAA,IAAY,SAAS;AAEpD,cAAA,OAAO,IAAI,IAAI;AAAA,UACpB;AAAA,UACA;AAAA,UACA,KAAK,cAAc,QAAQ;AAAA,QAAA;AAAA,MAE7B;AAAA,IACD;AAAA,EACD,CAAC;AAEY,QAAA,EAAE,aAAa,IAAI,UAAU;AAEnC,QAAM,kBAAoE,CAAC,SAAiB,CAAC,UAAU;AAC7G,UAAM,MAAM,MAAM,YAAY,OAAO,IAAI;AACzC,QAAI,CAAC,KAAK;AACF,aAAA;AAAA,IACR;AAEA,UAAMA,UAAQ,oBAAI,KAAK,GAAE,QAAQ;AACjC,UAAM,wBAAwB,IAAI,OAAOA,UAASA,SAAQ;AACtD,QAAA;AAA6B,aAAA;AAE1B,WAAA;AAAA,EACR;AAEa,QAAA,cAAkC,UAAU;ACxD7C,MAAA,uCAAAC,wBAAL;AACNA,wBAAAA,oBAAA,WAAQ,CAAR,IAAA;AACAA,wBAAAA,oBAAA,WAAQ,CAAR,IAAA;AAFWA,WAAAA;AAAAA,EAAA,GAAA,sBAAA,CAAA,CAAA;AAYA,MAAA,4CAAAC,6BAAL;AACNA,6BAAAA,yBAAA,WAAQ,CAAR,IAAA;AACAA,6BAAAA,yBAAA,WAAQ,CAAR,IAAA;AAFWA,WAAAA;AAAAA,EAAA,GAAA,2BAAA,CAAA,CAAA;ACOA,MAAA,oCAAAC,qBAAL;AACNA,qBAAA,OAAQ,IAAA;AACRA,qBAAA,OAAQ,IAAA;AACRA,qBAAA,WAAY,IAAA;AACZA,qBAAA,SAAU,IAAA;AACVA,qBAAA,UAAW,IAAA;AALAA,WAAAA;AAAAA,EAAA,GAAA,mBAAA,CAAA,CAAA;AC8EA,MAAA,sCAAAC,uBAAL;AACNA,uBAAA,QAAS,IAAA;AACTA,uBAAA,UAAW,IAAA;AACXA,uBAAA,UAAW,IAAA;AACXA,uBAAA,aAAc,IAAA;AACdA,uBAAA,OAAQ,IAAA;AACRA,uBAAA,aAAc,IAAA;AACdA,uBAAA,UAAW,IAAA;AAPAA,WAAAA;AAAAA,EAAA,GAAA,qBAAA,CAAA,CAAA;AChGA,MAAA,yCAAAC,0BAAL;AACNA,0BAAAA,sBAAA,uBAAoB,CAApB,IAAA;AACAA,0BAAAA,sBAAA,wBAAqB,CAArB,IAAA;AACAA,0BAAAA,sBAAA,oBAAiB,CAAjB,IAAA;AACAA,0BAAAA,sBAAA,yBAAsB,CAAtB,IAAA;AACAA,0BAAAA,sBAAA,sBAAmB,CAAnB,IAAA;AACAA,0BAAAA,sBAAA,oBAAiB,EAAjB,IAAA;AANWA,WAAAA;AAAAA,EAAA,GAAA,wBAAA,CAAA,CAAA;ACRA,MAAA,wCAAAC,yBAAL;AACNA,yBAAA,WAAY,IAAA;AACZA,yBAAA,QAAS,IAAA;AAFEA,WAAAA;AAAAA,EAAA,GAAA,uBAAA,CAAA,CAAA;AAIA,MAAA,iCAAAC,kBAAL;AACNA,kBAAAA,cAAA,SAAM,CAAN,IAAA;AADWA,WAAAA;AAAAA,EAAA,GAAA,gBAAA,CAAA,CAAA;AAIA,MAAA,kCAAAC,mBAAL;AACNA,mBAAAA,eAAA,YAAS,CAAT,IAAA;AACAA,mBAAAA,eAAA,YAAS,CAAT,IAAA;AACAA,mBAAAA,eAAA,eAAY,CAAZ,IAAA;AACAA,mBAAAA,eAAA,cAAW,CAAX,IAAA;AACAA,mBAAAA,eAAA,cAAW,CAAX,IAAA;AALWA,WAAAA;AAAAA,EAAA,GAAA,iBAAA,CAAA,CAAA;ACDZ,QAAMrC,iBAA0B;AAAA,IAC/B,OAAO,CAAC;AAAA,IACR,aAAa;AAAA,MACZ,IAAI;AAAA,MACJ,UAAU;AAAA,MACV,OAAO;AAAA,MACP,SAAS,EAAE,MAAM,MAAM,WAAW,MAAM,uBAAuB,CAAI,GAAA,WAAW,GAAG;AAAA,IAClF;AAAA,EACD;AAEa,QAAA,YAAYC,QAAAA,YAAY;AAAA,IACpC,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,UAAU,CAAC,OAAO,WAAgC;AACjD,cAAM,eAAqC,CAAA;AACpC,eAAA,QAAQ,QAAQ,CAAC,SAAS;AACnB,uBAAA,KAAK,EAAE,IAAI;AAAA,QAAA,CACxB;AACD,cAAM,QAAQ;AAAA,MACf;AAAA,MACA,UAAU,CAAC,OAAO,WAAgC;AACtC,mBAAA,QAAQ,OAAO,SAAS;AAC5B,gBAAA,MAAM,KAAK,EAAE,IAAI;AAAA,QACxB;AAAA,MACD;AAAA,MACA,gBAAgB,CAAC,OAAO,WAA8B;AACrD,cAAM,cAAc,OAAO;AAAA,MAC5B;AAAA,MACA,mBAAmB,CAAC,OAAO,WAA+D;AACzF,cAAM,YAAY,QAAQ,OAAO,OAAO,QAAQ,QAAQ;AACxD,cAAM,YAAY,QAAQ,YAAY,OAAO,QAAQ,aAAa;AAElE,cAAM,cAAc,MAAM,MAAM,MAAM,YAAY,EAAE;AAEpD,YAAI,CAAC,aAAa;AACX,gBAAA,IAAI,MAAM,4CAA4C;AAAA,QAC7D;AAEA,oBAAY,QAAQ,OAAO,OAAO,QAAQ,QAAQ;AAClD,oBAAY,QAAQ,YAAY,OAAO,QAAQ,aAAa;AAAA,MAC7D;AAAA,MACA,uBAAuB,CAAC,OAAO,WAAgC;AAC9D,cAAM,YAAY,QAAQ,sBAAsB,KAAK,OAAO,OAAO;AAAA,MACpE;AAAA,MACA,0BAA0B,CAAC,OAAO,WAAgC;AACjE,cAAM,YAAY,QAAQ,wBAAwB,MAAM,YAAY,QAAQ,sBAAsB;AAAA,UACjG,CAAC,OAAO,OAAO,OAAO;AAAA,QAAA;AAAA,MAExB;AAAA,MACA,aAAa,CAAC,OAAO,WAAgC;AAC9C,cAAA,YAAY,QAAQ,YAAY,OAAO;AAAA,MAC9C;AAAA,MACA,YAAY,CAAC,OAAO,WAAgC;AAC5C,eAAA,MAAM,MAAM,OAAO,OAAO;AAAA,MAClC;AAAA,IACD;AAAA,EACD,CAAC;AAEY,QAAA;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI,UAAU;AAEP,QAAM,cAAkC,UAAU;AAE5C,QAAA,oBAAoB,CAAC,UAA4B,MAAM,YAAY;AAEnE,QAAA,qBAAqB,CAAC,UAA4B,MAAM,YAAY;AAE1E,QAAM,aAAuE,CAAC,WAAW,CAAC,UAAU;AAC1G,QAAI,WAAW;AAAa,aAAA;AACrB,WAAA,MAAM,YAAY,MAAM,MAAM;AAAA,EACtC;AAEO,QAAM,iBAAwD,CAAC,WAAW,CAAC,UAAU;AACpF,WAAA,MAAM,YAAY,MAAM,MAAM;AAAA,EACtC;AAEa,QAAA,mBAA8D;AAAA,IAC1E4B,uBAAe,CAAC,oBAAoB,CAAC,QAAQ,YAAsB,OAAO,GAAG,CAAC,cAAc,YAAY;AACvG,YAAM,QAAgB,CAAA;AAEtB,iBAAW,UAAU,SAAS;AACvB,cAAA,OAAO,aAAa,MAAM;AAChC,YAAI,MAAM;AACT,gBAAM,KAAK,IAAI;AAAA,QAAA,OACT;AACE,kBAAA,KAAK,gDAAgD,MAAM;AAAA,QACpE;AAAA,MACD;AAEO,aAAA;AAAA,IAAA,CACP;AAAA,EACF;AAEO,QAAM,0BAA0B,CAAC,UACvC,MAAM,YAAY,YAAY,QAAQ;ACxGvC,QAAM,4BAA4B;AAAA,IACjC,CAAC,uBAAuB,mBAAmB;AAAA,EAC5C;AAEA,QAAM5B,iBAAwC,0BAA0B,gBAAgB,CAAA,CAAE;AAE7E,QAAA,0BAA0BC,QAAAA,YAAY;AAAA,IAClD,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,gCAAgC,0BAA0B;AAAA,MAC1D,0BAA0B,0BAA0B;AAAA,MACpD,0BAA0B,0BAA0B;AAAA,IACrD;AAAA,EACD,CAAC;AAEY,QAAA,EAAE,gCAAgC,0BAA0B,6BACxE,wBAAwB;AAEZ,QAAA,6BAA6B,CAAC,UAA4B;AACtE,WAAO,MAAM,0BAA0B;AAAA,EACxC;AAEO,QAAM,+BACZ,CAAC,yBAAiC,CAAC,UAA4B;AACvD,WAAA,MAAM,0BAA0B,UAAU,oBAAoB;AAAA,EACtE;AAEY,QAAA,iCAA6E4B,QAAA;AAAA,IACzF,CAAC,mBAAmB,0BAA0B;AAAA,IAC9C,CAAC,aAAmB,yBAA+D;AAClF,YAAM,2BAA2B,OAAO,OAAO,oBAAoB,EAAE;AAAA,QACpE,CAAC,uBAA2C,mBAAmB,SAAS,YAAY;AAAA,MAAA;AAErF,aAAO,4BAA4B;AAAA,IACpC;AAAA,EACD;AAEO,QAAM,kCACZ,CAAC,SAAe,CAAC,UAA4B;AAC5C,WAAO,OAAO,OAAO,MAAM,0BAA0B,SAAS,EAAE;AAAA,MAC/D,CAAC,uBAA2C,mBAAmB,SAAS,KAAK;AAAA,IAAA;AAAA,EAE/E;AAEY,QAAA,sCAAsC,CAAC,UAAgE;AACnH,UAAM,uBAA2D,CAAA;AACjE,eAAW,sBAAsB,OAAO,OAAO,MAAM,0BAA0B,SAAS,GAAG;AACrE,2BAAA,mBAAmB,IAAI,IAAI;AAAA,IACjD;AACO,WAAA;AAAA,EACR;AAEa,QAAA,4BAA8D,wBAAwB;ACxDnG,QAAM,iBAAiB,mBAA4B,CAAC,YAAY,QAAQ,UAAU;AAElF,QAAM5B,iBAA6B,eAAe,gBAAgB,CAAA,CAAE;AAEvD,QAAA,eAAeC,QAAAA,YAAY;AAAA,IACvC,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,oBAAoB,eAAe;AAAA,MACnC,aAAa,eAAe;AAAA,MAC5B,eAAe,eAAe;AAAA,IAC/B;AAAA,EACD,CAAC;AAEY,QAAA,EAAE,oBAAoB,aAAa,kBAAkB,aAAa;AAElE,QAAA,iBAA2D,CAAC,UAA4B;AACpG,WAAO,MAAM,eAAe;AAAA,EAC7B;AAEa,QAAA,gBACZ,CAAC,cAAsB,CAAC,UACvB,MAAM,eAAe,UAAU,SAAS;AAE7B,QAAA,sBAAuD,CAAC,UACpE,OAAO,OAAO,MAAM,eAAe,SAAS,EAAE;AAAA,IAC7C,CAAC,YAAY,QAAQ,YAAY,MAAM,eAAe;AAAA,EACvD,KAAK;AAEC,QAAM,0BACZ,CAAC,cAAsB,CAAC,UACvB,OAAO,OAAO,MAAM,eAAe,SAAS,EAAE,KAAK,CAAC,YAAY,QAAQ,YAAY,SAAS;AAElF,QAAA,6BAAyD4B,QAAA;AAAA,IACrE,CAAC,cAAc;AAAA,IACf,CAAC,aAAsC,OAAO,OAAO,QAAQ,EAAE,OAAO,CAAC,YAAY,QAAQ,SAAS;AAAA,EACrG;AAEa,QAAA,mCAA6EA,QAAA;AAAA,IACzF,CAAC,cAAc;AAAA,IACf,CAAC,aACA,OAAO,OAAO,QAAQ,EACpB,OAAO,CAAC,YAAY,QAAQ,OAAO,EACnC,OAAO,CAAC,OAAO,aAAa,EAAE,GAAG,OAAO,CAAC,QAAQ,OAAQ,GAAG,YAAY,EAAE;AAAA,EAC9E;AAEa,QAAA,iBAAwC,aAAa;AC/ClE,QAAM,uBAAuB,mBAAkC,CAAC,kBAAkB,cAAc,UAAU;AAE1G,QAAM5B,iBAAmC,qBAAqB,gBAAgB,CAAA,CAAE;AAEnE,QAAA,qBAAqBC,QAAAA,YAAY;AAAA,IAC7C,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,2BAA2B,qBAAqB;AAAA,MAChD,qBAAqB,qBAAqB;AAAA,MAC1C,qBAAqB,qBAAqB;AAAA,MAC1C,uBAAuB,qBAAqB;AAAA,IAC7C;AAAA,EACD,CAAC;AAEM,QAAM,EAAE,2BAA2B,qBAAqB,qBAAqB,0BACnF,mBAAmB;AAEP,QAAA,6BAA6B,CAAC,UAA4B;AACtE,WAAO,MAAM,qBAAqB;AAAA,EACnC;AAEa,QAAA,wBAAkE4B,QAAA;AAAA,IAC9E;AAAA,IACA,CAAC,oBAAoB;AACb,aAAA,OAAO,OAAO,eAAe;AAAA,IACrC;AAAA,EACD;AAEO,QAAM,0BACZ,CAAC,oBAA4B,CAAC,UAA4B;AAClD,WAAA,MAAM,qBAAqB,UAAU,eAAe;AAAA,EAC5D;AAEY,QAAA,4BAAmE,CAAC,UAA4B;AACtG,UAAA,cAAc,MAAM,YAAY;AAChC,UAAA,kBAAkB,MAAM,eAAe;AAE5C,WAAA,OAAO,OAAO,MAAM,qBAAqB,SAAS,EAAE,KAAK,CAAC,kBAAiC;AAC1F,aAAO,cAAc,SAAS,YAAY,MAAM,cAAc,YAAY;AAAA,IAC1E,CAAA,KAAK;AAAA,EAER;AAEO,QAAM,6BACZ,CAAC,SAAe,CAAC,UAA4B;AAC5C,WAAO,OAAO,OAAO,MAAM,qBAAqB,SAAS,EAAE;AAAA,MAC1D,CAAC,kBAAiC,cAAc,SAAS,KAAK;AAAA,IAAA;AAAA,EAEhE;AAEY,QAAA,iCAAiF,CAC7F,UACI;AACJ,UAAM,kBAAiD,CAAA;AACvD,eAAW,iBAAiB,OAAO,OAAO,MAAM,qBAAqB,SAAS,GAAG;AAChE,sBAAA,cAAc,IAAI,IAAI;AAAA,IACvC;AACO,WAAA;AAAA,EACR;AAEa,QAAA,uBAAoD,mBAAmB;AClDpF,QAAM5B,iBAA6B;AAAA,IAClC,UAAU,CAAC;AAAA,IACX,iBAAiB;AAAA,EAClB;AAEa,QAAA,eAAeC,QAAAA,YAAY;AAAA,IACvC,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,aAAa,CAAC,OAAO,WAAmC;AACvD,cAAM,cAAuC,CAAA;AACtC,eAAA,QAAQ,QAAQ,CAAC,YAAY;AACvB,sBAAA,QAAQ,EAAE,IAAI;AAAA,QAAA,CAC1B;AACD,cAAM,WAAW;AAAA,MAClB;AAAA,MACA,oBAAoB,CAAC,OAAO,WAAuC;AAClE,cAAM,kBAAkB,OAAO;AAAA,MAChC;AAAA,MACA,uBAAuB,CAAC,OAAO,WAAiC;AAC/D,cAAM,SAAS,OAAO,QAAQ,EAAE,IAAI,OAAO;AAAA,MAC5C;AAAA;AAAA;AAAA,MAGA,wBAAwB,CAAC,OAAO,WAAmC;AAC3D,eAAA,QAAQ,QAAQ,CAAC,YAAY;AAC7B,gBAAA,SAAS,QAAQ,EAAE,IAAI;AAAA,QAAA,CAC7B;AAAA,MACF;AAAA,MACA,eAAe,CAAC,OAAO,WAAiC;AACvD,eAAO,MAAM,SAAS,OAAO,QAAQ,EAAE;AAAA,MACxC;AAAA,MACA,qBAAqB,CAAC,OAAO,WAAgC;AACxD,YAAA,OAAO,WAAW,MAAM,UAAU;AACrC,gBAAM,SAAS,OAAO,OAAO,EAAG,UAAU;AAAA,QAAA,OACpC;AACA,gBAAA,IAAI,MAAM,oDAAoD;AAAA,QACrE;AAAA,MACD;AAAA,MACA,6BAA6B,CAAC,OAAO,WAAgC;AACpE,YAAI,CAAC,MAAM,mBAAmB,EAAE,MAAM,mBAAmB,MAAM,WAAW;AACnE,gBAAA,IAAI,MAAM,wCAAwC;AAAA,QACzD;AAEA,YAAI,CAAC,MAAM,SAAS,MAAM,eAAe,EAAG,cAAc;AACzD,gBAAM,SAAS,MAAM,eAAe,EAAG,eAAe,OAAO;AAAA,QAAA,OACvD;AACN,gBAAM,SAAS,MAAM,eAAe,EAAG,gBAAiB,OAAO;AAAA,QAChE;AAAA,MACD;AAAA,MACA,sCAAsC,CAAC,OAAO,WAAgC;AAC7E,YAAI,MAAM,mBAAmB,MAAM,mBAAmB,MAAM,UAAU;AACrE,cAAI,CAAC,MAAM,SAAS,MAAM,eAAe,EAAG,wBAAwB;AACnE,kBAAM,SAAS,MAAM,eAAe,EAAG,yBAAyB,OAAO;AAAA,UAAA,OACjE;AACN,kBAAM,SAAS,MAAM,eAAe,EAAG,0BAA2B,OAAO;AAAA,UAC1E;AAAA,QAAA,OACM;AACA,gBAAA,IAAI,MAAM,kDAAkD;AAAA,QACnE;AAAA,MACD;AAAA,IACD;AAAA,EACD,CAAC;AAEY,QAAA;AAAA,IACZ;AAAA,IACA;AAAA,IACA,wBAAwB;AAAA,IACxB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI,aAAa;AAEV,QAAM,iBAAwC,aAAa;AAErD,QAAA,uBAAiE,CAAC,UAC9E,MAAM,eAAe;AAET,QAAA,wBAAwB,CAAC,UAA2C,MAAM,eAAe;AAEzF,QAAA,sBAAsB,CAAC,UAA4C;AACzE,UAAA,kBAAkB,sBAAsB,KAAK;AACnD,QAAI,CAAC,iBAAiB;AACd,aAAA;AAAA,IACR;AACA,WAAO,MAAM,eAAe,SAAS,eAAe,KAAK;AAAA,EAC1D;AAEO,QAAM,oBACZ,CAAC,cAAsB,CAAC,UAA4B;AAC5C,WAAA,MAAM,eAAe,SAAS,SAAS;AAAA,EAC/C;AAEY,QAAA,wBAAmD4B,QAAA;AAAA,IAC/D,CAAC,0BAA0B;AAAA,IAC3B,CAAC,oBACA,OAAO,OAAO,eAAe,EAAE,IAAI,CAAC,kBAAiC,cAAc,IAAI;AAAA,EACzF;AAEa,QAAA,8BAAqEA,QAAA;AAAA,IACjF,CAAC,uBAAuB,kBAAkB;AAAA,IAC1C,CAAC,gBAAgB,UAAU,eAAe,OAAO,CAAC,OAAO,YAAY,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,MAAM,MAAM,EAAE,IAAI,EAAE;AAAA,EAChH;AAEa,QAAA,2BAAuDA,QAAA;AAAA,IACnE,CAAC,oBAAoB;AAAA,IACrB,CAAC,aAAsC,OAAO,OAAO,QAAQ,EAAE,OAAO,CAAC,YAAY,CAAC,QAAQ,OAAO;AAAA,EACpG;AAEa,QAAA,2BAAoDA,QAAA;AAAA,IAChE,CAAC,mBAAmB,6BAA6B,8BAA8B;AAAA,IAC/E,CAAC,aAAmB,aAAmC,yBAAwD;AAC9G,aAAO,OAAO,OAAO,WAAW,EAAE,KAAK,CAAC,OAAO,UAAU;AACpD,YAAA,MAAM,OAAO,YAAY,IAAI;AACzB,iBAAA;AAAA,QACG,WAAA,MAAM,OAAO,YAAY,IAAI;AAChC,iBAAA;AAAA,QACR;AACM,cAAA,mBAAmB,qBAAqB,MAAM,EAAE;AAChD,cAAA,mBAAmB,qBAAqB,MAAM,EAAE;AAClD,aAAA,qDAAkB,mBAAiB,qDAAkB,eAAc;AACtE,iBAAO,MAAM,SAAS,cAAc,MAAM,QAAQ;AAAA,QACnD;AACI,aAAA,qDAAkB,kBAAiB,mBAAmB,OAAO;AACzD,iBAAA;AAAA,QACR;AACO,eAAA;AAAA,MAAA,CACP;AAAA,IACF;AAAA,EACD;ACjIA,QAAM5B,iBAAkC;AAAA,IACvC,eAAe,CAAC;AAAA,EACjB;AAEa,QAAA,oBAAoBC,QAAAA,YAAY;AAAA,IAC5C,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,kBAAkB,CAAC,OAAO,WAA0C;AACxD,mBAAA,OAAO,OAAO,SAAS;AAC3B,gBAAA,cAAc,IAAI,EAAE,IAAI;AAAA,QAC/B;AAAA,MACD;AAAA,IACD;AAAA,EACD,CAAC;AAEY,QAAA,EAAE,iBAAiB,IAAI,kBAAkB;AAEzC,QAAA,sBAAuD,CAAC,UAA4B;AAChG,WAAO,OAAO,OAAO,MAAM,oBAAoB,aAAa;AAAA,EAC7D;AAEa,QAAA,6BAA4E,CAAC,UAA4B;AACrH,WAAO,MAAM,oBAAoB;AAAA,EAClC;AAEa,QAAA,gCAAiE4B,QAAA;AAAA,IAC7E,CAAC,mBAAmB;AAAA,IACpB,CAAC,kBACA,OAAO,OAAO,aAAa,EAAE,OAAO,CAAC,iBAA+B,aAAa,UAAU;AAAA,EAC7F;AAEO,QAAM,yBAAwE,CAAC,mBAAmB,CAAC,UAAU;AAC5G,WAAA,MAAM,oBAAoB,cAAc,cAAc;AAAA,EAC9D;AAEa,QAAA,6BAAwDA,QAAA;AAAA,IACpE,CAAC,0BAA0B;AAAA,IAC3B,CAAC,yBACA,OAAO,OAAO,oBAAoB,EAAE,IAAI,CAAC,uBAA2C,mBAAmB,IAAI;AAAA,EAC7G;AAEa,QAAA,+BACZ;AAAA,IACCA,QAAA;AAAA,MACC,CAAC,sBAAsB,CAAC,GAAG,mBAA2B,cAAc;AAAA,MACpE,CAAC,UAAU,mBAAmB;AACtB,eAAA,OAAO,OAAO,QAAQ,EAAE,OAAO,CAAC,YAAY,QAAQ,uBAAuB,cAAc;AAAA,MACjG;AAAA,IACD;AAAA,EACD;AAEY,QAAA,+BACZ;AAAA,IACCA,uBAAe,CAAC,gBAAgB,CAAC,GAAG,mBAA2B,cAAc,GAAG,CAAC,UAAU,mBAAmB;AACtG,aAAA,OAAO,OAAO,QAAQ,EAAE,OAAO,CAAC,YAAY,QAAQ,uBAAuB,cAAc;AAAA,IAAA,CAChG;AAAA,EACF;AAEY,QAAA,mCAA0EA,QAAA;AAAA,IACtF,CAAC,4BAA4B,kBAAkB;AAAA,IAC/C,CAAC,qBAA+B,UAC/B,oBAAoB,OAAO,CAAC,OAAO,YAAY,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,MAAM,MAAM,EAAE,IAAI,EAAE;AAAA,EAC3F;AAEa,QAAA,gCAAyDA,QAAA;AAAA,IACrE,CAAC,mBAAmB,kCAAkC,mCAAmC;AAAA,IACzF,CACC,aACA,aACA,8BACI;AACJ,aAAO,OAAO,OAAO,WAAW,EAAE,KAAK,CAAC,OAAa,UAAgB;AAChE,YAAA,MAAM,OAAO,YAAY,IAAI;AACzB,iBAAA;AAAA,QACG,WAAA,MAAM,OAAO,YAAY,IAAI;AAChC,iBAAA;AAAA,QACR;AACM,cAAA,wBAAwD,0BAA0B,MAAM,EAAE;AAC1F,cAAA,wBAAwD,0BAA0B,MAAM,EAAE;AAC5F,aAAA,+DAAuB,mBAAiB,+DAAuB,eAAc;AAChF,iBAAO,MAAM,SAAS,cAAc,MAAM,QAAQ;AAAA,QACnD;AACI,aAAA,+DAAuB,kBAAiB,wBAAwB,OAAO;AACnE,iBAAA;AAAA,QACR;AACO,eAAA;AAAA,MAAA,CACP;AAAA,IACF;AAAA,EACD;AAEO,QAAM,qBACZ,CAAC,OAAe,CAAC,UAA4B;AACrC,WAAA,MAAM,oBAAoB,cAAc,EAAE;AAAA,EAClD;AAEY,QAAA,sBAAkD,kBAAkB;AChHpE,QAAA,sBAAsB,CAAClC,UAAqB,SAAiB,gBAA2C;AAC9G,UAAA,kBAAkBA,SAAQ,OAAQA,WAA6B,EAAE,GAAGA,UAAS,MAAMS,KAAA,GAAA;AAClF,WAAA;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,MACN,MAAM;AAAA,QACL,SAAS;AAAA,UACR,QAAQ;AAAA,YACP,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,YAClC,SAAS;AAAA,YACT,UAAU;AAAA,YACV;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,IAAA;AAAA,EAEF;AASA,QAAMH,iBAA4B;AAAA,IACjC,iBAAiB,CAAC;AAAA,IAClB,iBAAiB;AAAA,EAClB;AAQa,QAAA,cAAcC,QAAAA,YAAY;AAAA,IACtC,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA;AAAA;AAAA;AAAA,MAIT,gBAAgB;AAAA,QACf,SAAS,CAAC,OAAO,YAA2C;AACpD,iBAAA;AAAA,QACR;AAAA,QACA,SAAS,CAAC,YAAuF;AACxF,kBAAA,MAAM,gCAAgC,OAAO;AACrD,gBAAM,EAAE,UAAU,aAAa,GAAG,SAAS;AACpC,iBAAA,oBAAoB,MAAM,UAAU,WAAW;AAAA,QACvD;AAAA,MACD;AAAA,MACA,gBAAgB,OAAO,QAA+B;AAC/C,cAAA,gBAAgB,KAAK,OAAO,OAAO;AAAA,MAC1C;AAAA,MACA,cAAc,OAAO,QAA+B;AACnD,cAAM,QAAQ,MAAM,gBAAgB,QAAQ,OAAO,OAAO;AAC1D,YAAI,UAAU;AAAU,gBAAA,gBAAgB,OAAO,OAAO,CAAC;AAAA,MACxD;AAAA,MACA,qBAAqB,CAAC,OAAO,WAAkC;AAC9D,cAAM,kBAAkB,OAAO;AAAA,MAChC;AAAA,IACD;AAAA,EACD,CAAC;AAEY,QAAA,wBAAwB,CAAC,UAA4B,MAAM,cAAc;AACzE,QAAA,wBAAwB,CAAC,UAA4B,MAAM,cAAc;AAE/E,QAAM,EAAE,gBAAgB,iBAAiB,eAAe,wBAAwB,YAAY;AACtF,QAAA,gBAAsC,YAAY;AC1D/D,QAAMA,iBAAiC;AAAA,IACtC,cAAc,CAAC;AAAA,IACf,qBAAqB;AAAA,IACrB,wBAAwB;AAAA,EACzB;AAEa,QAAA,mBAAmBC,QAAAA,YAAY;AAAA,IAC3C,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,0BAA0B,CAAC,OAAO,WAAuC;AAC/D,iBAAA,WAAW,OAAO,SAAS;AACnC,cAAI,OAAO,QAAQ;AACf,cAAA,KAAK,SAAS,GAAG,GAAG;AACf,oBAAA,KAAK,6DAA6D,IAAI;AAMxE,kBAAA,QAAQ,KAAK,MAAM,GAAG;AACxB,gBAAA,MAAM,SAAS,GAAG;AACf,oBAAA,IAAI,MAAM,kBAAkB,IAAI;AAAA,YACvC;AACA,kBAAM,WAAW,mBAAmB,MAAM,MAAM,SAAS,CAAC,CAAE;AAErD,mBAAA,MAAM,MAAM,GAAG,EAAE,EAAE,KAAK,GAAG,IAAI,MAAM;AACpC,oBAAA,KAAK,cAAc,IAAI;AACrB,sBAAA,EAAE,GAAG,SAAS;UACzB;AACM,gBAAA,aAAa,QAAQ,UAAU,IAAI;AAAA,QAC1C;AAAA,MACD;AAAA,MACA,yBAAyB,CAAC,OAAO,WAAqC;AACjE,YAAA,CAAC,OAAO,QAAQ,SAAS;AACtB,gBAAA,IAAI,MAAM,mEAAmE;AAAA,QACpF;AACA,cAAM,aAAa,OAAO,QAAQ,UAAU,IAAI,OAAO;AAAA,MACxD;AAAA,MACA,2BAA2B,CAAC,OAAO,WAAiC;AACnE,cAAM,yBAAyB,OAAO;AAAA,MACvC;AAAA,MACA,6BAA6B,CAAC,OAAO,WAA4C;AAChF,cAAM,sBAAsB,MAAM;AAClC,YAAI,CAAC,qBAAqB;AACnB,gBAAA,IAAI,MAAM,mFAAmF;AAAA,QACpG;AACA,YAAI,CAAC,MAAM,aAAa,mBAAmB,GAAG;AAC7C,gBAAM,IAAI;AAAA,YACT,0EAA0E,mBAAmB;AAAA;AAAA,UAAA;AAAA,QAG/F;AACA,cAAM,aAAa,mBAAmB,EAAG,SAAS,OAAO;AAAA,MAC1D;AAAA;AAAA,MAEA,wBAAwB,CAAC,OAAO,WAAuC;AACtE,cAAM,sBAAsB,OAAO;AAAA,MACpC;AAAA,MACA,mBAAmB,CAAC,OAAO,WAAgC;AACnD,eAAA,MAAM,aAAa,OAAO,OAAO;AAAA,MACzC;AAAA,MACA,6BAA6B,CAAC,OAAO,WAAgC;AACpE,cAAM,gBAAgB,OAAO,OAAO,MAAM,YAAY,EAAE,OAAO,CAAC,SAAS,KAAK,YAAY,OAAO,OAAO;AACxG,mBAAW,QAAQ,eAAe;AAC1B,iBAAA,MAAM,aAAa,KAAK,UAAU;AAAA,QAC1C;AAAA,MACD;AAAA,MACA,4BAA4B,CAAC,UAAU,UAAc;AACzC,mBAAA,OAAO,MAAM,cAAc;AAC9B,iBAAA,MAAM,aAAa,GAAG,EAAG;AAAA,QACjC;AAAA,MACD;AAAA,IACD;AAAA,EACD,CAAC;AAEY,QAAA;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI,iBAAiB;AAER,QAAA,2BAA2B,CAAC,UAA4B,MAAM,mBAAmB;AAEjF,QAAA,qBAAqB4B,QAAA;AAAA,IACjC,CAAC,0BAA0B,qBAAqB;AAAA,IAChD,CAAC,SAAS,oBAAoB;AAC7B,aAAO,OAAO,OAAO,OAAO,EAC1B,OAAO,CAAC,SAAS,KAAK,YAAY,eAAe,EACjD,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,OAAO;AAAA,IACvC;AAAA,EACD;AAEa,QAAA,4BAA4D,CAAC,UACzE,MAAM,mBAAmB;AAEb,QAAA,+BAAyD,CAAC,UACtE,MAAM,mBAAmB;AAEnB,QAAM,wBACZ,CAAC,OAAe,CAAC,UAA4B;AACrC,WAAA,MAAM,mBAAmB,aAAa,EAAE;AAAA,EAChD;AAEY,QAAA,qBAAgD,iBAAiB;AC1H9E,QAAM,2BAA2B,mBAA8C,CAAC,eAAe,WAAW,UAAU;AAEpH,QAAM5B,iBAAuC,yBAAyB,gBAAgB,CAAA,CAAE;AAE3E,QAAA,yBAAyBC,QAAAA,YAAY;AAAA,IACjD,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,8BAA8B,yBAAyB;AAAA,MACvD,sBAAsB,yBAAyB;AAAA,MAC/C,uBAAuB,yBAAyB;AAAA,MAChD,sBAAsB,yBAAyB;AAAA,MAC/C,uBAAuB,yBAAyB;AAAA,MAChD,yBAAyB,yBAAyB;AAAA,MAClD,0BAA0B,yBAAyB;AAAA,MACnD,yBAAyB,yBAAyB;AAAA,MAClD,0BAA0B,yBAAyB;AAAA,IACpD;AAAA,EACD,CAAC;AAEY,QAAA;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI,uBAAuB;AAEd,QAAA,iCAAiC,CAAC,UAA4B,MAAM,yBAAyB;AAE7F,QAAA,8BAA4E4B,QAAA;AAAA,IACxF,CAAC,8BAA8B;AAAA,IAC/B,CAAC,YAAY,OAAO,OAAO,OAAO;AAAA,EACnC;AAEO,QAAM,0BACZ,CAAC,iBAAyB,CAAC,UAA4B;AAC/C,WAAA,MAAM,yBAAyB,UAAU,YAAY;AAAA,EAC7D;AAEY,QAAA,6BAA6B;AAAA,IACzCA,QAAA;AAAA,MACC,CAAC,6BAA6B,CAAC,QAA0B,cAAsB,SAAS;AAAA,MACxF,CAAC,aAAa,cAAc;AAC3B,eAAO,YAAY,OAAO,CAAC,EAAE,QAAQ,MAAM,cAAc,OAAO;AAAA,MACjE;AAAA,IACD;AAAA,EACD;AACa,QAAA,mCAAmC;AAAA,IAC/CA,QAAA;AAAA,MACC,CAAC,6BAA6B,CAAC,QAA0B,cAAsB,SAAS;AAAA,MACxF,CAAC,aAAa,cAAc;AACrB,cAAA,uBAAuB,YAAY,OAAO,CAAC,EAAE,cAAc,cAAc,OAAO;AACtF,cAAM,kBAAkB,qBAAqB;AAAA;AAAA,UAE5C,CAAC,EAAE,UAAU,MAAM,CAAC,aAAa,CAAC,UAAU,WAAW,QAAQ;AAAA,QAAA;AAEhE,cAAM,mBAAmB,qBAAqB;AAAA;AAAA,UAE7C,CAAC,EAAE,UAAA,MAAgB,aAAa,UAAU,WAAW,QAAQ;AAAA,QAAA;AAEvD,eAAA,EAAE,iBAAiB;MAC3B;AAAA,IACD;AAAA,EACD;AAEa,QAAA,2BAA4D,uBAAuB;ACtEhG,QAAM5B,iBAAgC;AAAA,IACrC,cAAc;AAAA,EACf;AAIa,QAAA,kBAAkBC,QAAAA,YAAY;AAAA,IAC1C,MAAM;AAAA,IAAA,cACND;AAAAA;AAAAA,IAEA,UAAU;AAAA,MACT,eAAe,CAAC,OAAO,WAAmC;AACzD,cAAM,eAAe,OAAO;AAAA,MAC7B;AAAA,IACD;AAAA,EACD,CAAC;AAEY,QAAA,EAAE,cAAc,IAAI,gBAAgB;AAKpC,QAAA,mBAAmB,CAAC,UAA4B,MAAM,kBAAkB;AAExE,QAAA,oBAA8C,gBAAgB;AC/B9D,QAAA,qBAAqB,CAAC,eAAqC,kBAAwC;AAC/G,UAAM,YAAY,cAAc;AAChC,UAAM,YAAY,cAAc;AAE5B,QAAA,cAAc,aAAa,cAAc,WAAW;AACvD,aAAO,cAAc,eAAe,cAAc,eAAe,KAAK;AAAA,IAAA,WAC5D,cAAc,WAAW;AAC5B,aAAA;AAAA,IAAA,WACG,cAAc,WAAW;AAC5B,aAAA;AAAA,IAAA,OACD;AACC,aAAA,YAAY,YAAY,KAAK;AAAA,IACrC;AAAA,EACD;ACNA,QAAM,sBAAsB,mBAAyC,CAAC,aAAa,SAAS,UAAU;AAEtG,QAAMA,iBAAkC,oBAAoB,gBAAgB,CAAA,CAAE;AAEjE,QAAA,qBAAqBC,QAAAA,YAAY;AAAA,IAC7C,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,yBAAyB,oBAAoB;AAAA,MAC7C,iBAAiB,oBAAoB;AAAA,MACrC,iBAAiB,oBAAoB;AAAA,MACrC,kBAAkB,oBAAoB;AAAA,MACtC,oBAAoB,oBAAoB;AAAA,MACxC,qBAAqB,oBAAoB;AAAA,IAC1C;AAAA,EACD,CAAC;AAEY,QAAA;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI,mBAAmB;AAEV,QAAA,4BAA4B,CAAC,UAA4B,MAAM,oBAAoB;AAEnF,QAAA,sBAAsB4B,QAAA;AAAA,IAAe,CAAC,yBAAyB;AAAA,IAAG,CAAC,kBAC/E,OAAO,OAAO,aAAa;AAAA,EAC5B;AAEO,QAAM,yBACZ,CAAC,mBAA2B,CAAC,UAA4B;AACjD,WAAA,MAAM,oBAAoB,UAAU,cAAc;AAAA,EAC1D;AAGY,QAAA,4BAA4B,CACxC,eACA,WAC0B;AAC1B,QAAI,MAAmC;AAEvC,eAAW,aAAa,OAAO,OAAO,aAAa,GAAG;AACjD,UAAA,UAAU,SAAS,WAAW,CAAC,OAAO,IAAI,WAAW,UAAU,WAAW;AACvE,cAAA;AAAA,MACP;AAAA,IACD;AAEA,QAAI,CAAC,KAAK;AACH,YAAA,IAAI,MAAM,qCAAqC,MAAM;AAAA,IAC5D;AAEO,WAAA;AAAA,EACR;AAEa,QAAA,iCAGT;AAAA,IACHA,QAAA;AAAA,MACC,CAAC,2BAA2B,CAAC,QAA0B,WAAmB,MAAM;AAAA,MAChF,CAAC,WAAW,WAAW;AAChB,cAAA,kBAAkB,OAAO,OAAO,SAAS,EAAE,OAAO,CAAC,aAAa,SAAS,SAAS,MAAM;AAE9F,YAAI,gBAAgB,WAAW;AAAU,iBAAA;AAEnC,cAAA,kBAAkB,gBAAgB,KAAK,kBAAkB;AAE/D,cAAM,iBAAiB,gBAAgB,gBAAgB,SAAS,CAAC;AAE1D,eAAA,UAAU,eAAe,UAAU;AAAA,MAC3C;AAAA,IACD;AAAA,EACD;AAEa,QAAA,4BACZ;AAAA,IACCA,QAAA;AAAA,MACC,CAAC,qBAAqB,CAAC,QAA0B,WAAmB,MAAM;AAAA,MAC1E,CAAC,WAAW,WAAW;AACf,eAAA,UAAU,OAAO,CAAC,aAAa;AACrC,iBAAO,SAAS,SAAS;AAAA,QAAA,CACzB;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAEY,QAAA,wCAGT;AAAA,IACHA,QAAA;AAAA,MACC;AAAA,QACC,CAAC,UAA4B,MAAM,YAAY;AAAA,QAC/C;AAAA,QACA,CAAC,QAA0B,iBAA2B;AAAA,MACvD;AAAA,MACA,CAAC,cAAc,WAAW,iBAAiB;AACpC,cAAA,kBAAkB,IAAI,IAAI,YAAY;AAC5C,cAAM,oBAAkD,CAAA;AACxD,cAAM,MAA4C,CAAA;AAElD,mBAAW,QAAQ,OAAO,OAAO,YAAY,GAAG;AAC/C,cAAI,KAAK,cAAc,gBAAgB,IAAI,KAAK,UAAU,GAAG;AAC1C,8BAAA,KAAK,UAAU,IAAI;AAAA,UACtC;AAAA,QACD;AAEA,mBAAW,YAAY,OAAO,OAAO,SAAS,GAAG;AAE1C,gBAAA,OAAO,kBAAkB,SAAS,IAAI;AAE5C,cACC,CAAC,QACD,CAAC,KAAK,cACL,IAAI,KAAK,UAAU,KAAK,mBAAmB,IAAI,KAAK,UAAU,GAAI,QAAQ,IAAI;AAE/E;AAEG,cAAA,KAAK,UAAU,IAAI;AAAA,QACxB;AAEO,eAAA;AAAA,MACR;AAAA,IACD;AAAA,EACD;AAEa,QAAA,iCACZA,QAAAA,eAAe,CAAC,yBAAyB,GAAG,CAAC,cAAc;AAC1D,UAAM,kBAAgD,CAAA;AACtD,eAAW,YAAY,OAAO,OAAO,SAAS,GAAG;AAChD,YAAM,SAAS,SAAS;AAClB,YAAA,wBAAwB,gBAAgB,MAAM;AACpD,UAAI,CAAC,yBAAyB,sBAAsB,WAAW,SAAS,UAAU;AACjF,wBAAgB,MAAM,IAAI;AAAA,MAC3B;AAAA,IACD;AACO,WAAA;AAAA,EACR,CAAC;AAEW,QAAA,sBAAkD,mBAAmB;AC3IlF,QAAM,cAAc,mBAAiC,CAAC,SAAS,KAAK,UAAU;AAE9E,QAAM5B,iBAA0B,YAAY,gBAAgB,CAAA,CAAE;AAEjD,QAAA,YAAYC,QAAAA,YAAY;AAAA,IACpC,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,iBAAiB,YAAY;AAAA,MAC7B,SAAS,YAAY;AAAA,MACrB,SAAS,YAAY;AAAA,MACrB,UAAU,YAAY;AAAA,MACtB,YAAY,YAAY;AAAA,MACxB,YAAY,YAAY;AAAA,IACzB;AAAA,EACD,CAAC;AAEY,QAAA,EAAE,iBAAiB,SAAS,SAAS,UAAU,YAAY,WAAA,IAAe,UAAU;AASpF,QAAA,qBAAwF,CAAC,UAAU;AAC/G,WAAO,MAAM,YAAY;AAAA,EAC1B;AAEa,QAAA,sBACZ;AAAA,IACC4B,QAAA;AAAA,MACC;AAAA,QACC,CAAC,UAA4B,MAAM,YAAY;AAAA,QAC/C,CAAC,UAA4B,MAAM,oBAAoB;AAAA,QACvD,CAAC,QAA0B,WAA2B;AAAA,MACvD;AAAA,MACA,CAAC,cAAc,WAAW,WAAW;AACpC,cAAM,EAAE,YAAY,YAAY,WAAW,iBAAiB;AAE5D,cAAM,kBAAgC,CAAA;AACtC,cAAM,iBAA+B,CAAA;AAErC,mBAAW,CAAC,QAAQ,IAAI,KAAK,OAAO,QAAQ,YAAY,GAAG;AAEtD,cAAA,cAAc,UAAa,KAAK,YAAY;AAAW;AAG3D,cAAI,OAAO,UAAU,YAAY,KAAK,iBAAiB,KAAK,cAAc;AACzE;AAAA,UACD;AAGM,gBAAA,iBAAiB,0BAA0B,WAAW,MAAM;AAE9D,cAAA,eAAe,MAAM,YAAY,EAAE,SAAS,WAAW,YAAA,CAAa,GAAG;AAC1E,gBAAI,KAAK,UAAU;AAClB,8BAAgB,KAAK,EAAE,GAAG,MAAM,eAAgC,CAAA;AAAA,YAAA,OAC1D;AACN,6BAAe,KAAK,EAAE,GAAG,MAAM,eAAgC,CAAA;AAAA,YAChE;AAAA,UACD;AAII,cAAA,gBAAgB,UAAU,YAAY;AACzC;AAAA,UACD;AAAA,QACD;AAEM,cAAA,oBAAoB,aAAa,gBAAgB;AAEhD,eAAA,CAAC,GAAG,iBAAiB,GAAG,eAAe,MAAM,GAAG,iBAAiB,CAAC;AAAA,MAC1E;AAAA;AAAA,MAEA,EAAE,gBAAgB,EAAE,eAAe,eAAe;AAAA,IACnD;AAAA,EACD;AAEY,QAAA,oBAAuF,CACnG,UACI;AACJ,WAAO,MAAM,YAAY;AAAA,EAC1B;AAEO,QAAM,iBACZ,CAAC,WAAmB,CAAC,UAA4B;AACzC,WAAA,MAAM,YAAY,UAAU,MAAM;AAAA,EAC1C;AAEY,QAAA,wBAAuE;AAAA,IACnFA,QAAA;AAAA,MACC,CAAC,mBAAmB,CAAC,QAA0B,gBAAwB,WAAW;AAAA,MAClF,CAAC,cAAc,gBAAgB;AACvB,eAAA,OAAO,OAAO,YAAY,EAAE,KAAK,CAAC,SAAS,KAAK,eAAe,WAAW;AAAA,MAClF;AAAA,IACD;AAAA,EACD;AAEa,QAAA,wBAAuE;AAAA,IACnFA,QAAA;AAAA,MACC,CAAC,mBAAmB,CAAC,QAA0B,gBAAwB,WAAW;AAAA,MAClF,CAAC,cAAc,gBAAgB;AACvB,eAAA,OAAO,OAAO,YAAY,EAAE,KAAK,CAAC,SAAS,KAAK,eAAe,WAAW;AAAA,MAClF;AAAA,IACD;AAAA,EACD;AAGa,QAAA,mBAA4CA,QAAAA,eAAe,CAAC,iBAAiB,GAAG,CAAC,iBAAiB;AACvG,WAAA,OAAO,KAAK,YAAY,EAAE;AAAA,EAClC,CAAC;AAGY,QAAA,yBAAkDA,QAAAA,eAAe,CAAC,iBAAiB,GAAG,CAAC,iBAAiB;AAC7G,WAAA,OAAO,OAAO,YAAY,EAAE,OAAO,CAAC,SAAS,CAAC,KAAK,UAAU,EAAE;AAAA,EACvE,CAAC;AAEY,QAAA,cAAkC,UAAU;AC1HzD,QAAM,oBAAoB,mBAA2C,CAAC,eAAe,WAAW,UAAU;AAE1G,QAAM5B,iBAAoC,kBAAkB,gBAAgB,CAAA,CAAE;AAEjE,QAAA,sBAAsBC,QAAAA,YAAY;AAAA,IAC9C,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,2BAA2B,kBAAkB;AAAA,MAC7C,mBAAmB,kBAAkB;AAAA,MACrC,oBAAoB,kBAAkB;AAAA,MACtC,mBAAmB,kBAAkB;AAAA,MACrC,oBAAoB,kBAAkB;AAAA,MACtC,sBAAsB,kBAAkB;AAAA,MACxC,uBAAuB,kBAAkB;AAAA,MACzC,sBAAsB,kBAAkB;AAAA,MACxC,uBAAuB,kBAAkB;AAAA,IAC1C;AAAA,EACD,CAAC;AAEY,QAAA;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI,oBAAoB;AAEX,QAAA,+BAAkF,CAAC,UAAU;AACzG,WAAO,MAAM,sBAAsB;AAAA,EACpC;AAEa,QAAA,wBAAmE4B,QAAA;AAAA,IAC/E,CAAC,4BAA4B;AAAA,IAC7B,CAAC,gBAAgB;AACT,aAAA,OAAO,OAAO,WAAW;AAAA,IACjC;AAAA,EACD;AAEO,QAAM,2BACZ,CAAC,iBAAiB,CAAC,UAA4B;AACvC,WAAA,MAAM,sBAAsB,UAAU,YAAY;AAAA,EAC1D;AAEY,QAAA,8BACZ;AAAA,IACCA,QAAA;AAAA,MACC;AAAA,QACC;AAAA,QACA;AAAA,QACA,CAAC,QAA0B,WAAmB;AAAA,MAC/C;AAAA,MACA,CAAC,aAAa,iBAAiB,WAAW;AACnC,cAAA,kBAAkB,OAAO,OAAO,eAAe,EAAE,OAAO,CAAC,aAAa,SAAS,SAAS,MAAM;AAC9F,cAAA,cAAc,IAAI,IAAI,gBAAgB,IAAI,CAAC,aAAa,SAAS,UAAU,CAAC;AAElF,eAAO,OAAO,OAAO,WAAW,EAAE,OAAO,CAAC,eAAe;AACjD,iBAAA,YAAY,IAAI,WAAW,aAAa;AAAA,QAAA,CAC/C;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAEY,QAAA,uCACZA,uBAAe,CAAC,2BAA2B,qBAAqB,GAAG,CAAC,WAAW,gBAAgB;;AAC9F,UAAM,oBAA8D,CAAA;AACpE,eAAW,cAAc,WAAW;AACjB,wBAAA,UAAU,IAAI;IACjC;AACA,eAAW,cAAc,aAAa;AACrC,OAAA9B,MAAA,kBAAkB,WAAW,aAAa,MAA1C,gBAAAA,IAA6C,KAAK;AAAA,IACnD;AACO,WAAA;AAAA,EACR,CAAC;AAEW,QAAA,oCACZ;AAAA,IACC8B,QAAA;AAAA,MACC;AAAA,QACC;AAAA,QACA;AAAA,QACA,CAAC,QAA0B,WAAmB;AAAA,MAC/C;AAAA,MACA,CAAC,kBAAkB,uBAAuB,WAAW;AACpD,cAAM,6BAAuE,CAAA;AAE7E,mBAAW,cAAc,kBAAkB;AACpC,gBAAA,WAAW,iBAAiB,UAAU;AACtC,gBAAA,wBAAwB,sBAAsB,UAAU;AAC9D,cAAI,YAAY,yBAAyB,SAAS,SAAS,QAAQ;AACvC,uCAAA,UAAU,IAAI,sBAAsB;AAAA,cAAK,CAAC,GAAG,MACvE,EAAE,eAAe,EAAE,eAAe,KAAK;AAAA,YAAA;AAAA,UAEzC;AAAA,QACD;AAEA,eAAO,OAAO,QAAQ,0BAA0B,EAC9C,KAAK,CAAC,GAAG,MAAM;AACf,gBAAM,YAAY,iBAAiB,EAAE,CAAC,CAAC;AACvC,gBAAM,YAAY,iBAAiB,EAAE,CAAC,CAAC;AAChC,iBAAA,mBAAmB,WAAW,SAAS;AAAA,QAAA,CAC9C,EACA,IAAI,CAAC,CAAC,aAAa,WAAW,MAAM,WAAW,EAC/C;MACH;AAAA,IACD;AAAA,EACD;AAEY,QAAA,+BAA+B;AAAA,IAC3CA,QAAA;AAAA,MACC,CAAC,uBAAuB,CAAC,QAA0B,YAAoB,OAAO;AAAA,MAC9E,CAAC,aAAa,YAAY;AACzB,eAAO,OAAO,OAAO,WAAW,EAAE,OAAO,CAAC,eAAe;AACxD,iBAAO,WAAW,UAAU;AAAA,QAAA,CAC5B;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAEa,QAAA,uCAAuC;AAAA,IACnDA,QAAA;AAAA,MACC;AAAA,QACC,CAAC,UAA4B,MAAM,aAAa;AAAA,QAChD,CAAC,UAA4B,MAAM,YAAY;AAAA,QAC/C,CAAC,UAA4B,MAAM,oBAAoB;AAAA,QACvD,CAAC,UAA4B,MAAM,sBAAsB;AAAA,QACzD,CAAC,QAA0B,YAAoB;AAAA,MAChD;AAAA,MACA,CAAC,QAAQ,OAAO,eAAe,aAAa,YAAY;AAEjD,cAAA,QAAQ,OAAO,OAAO;AAE5B,YAAI,CAAC;AAAO,iBAAO;AAEf,YAAA,CAAC,MAAM,YAAY;AACf,iBAAA,OAAO,OAAO,WAAW,EAAE,OAAO,CAAC,eAAe,WAAW,UAAU,OAAO;AAAA,QACtF;AAGA,cAAM,iBAAiB,IAAI;AAAA,UAC1B,OAAO,KAAK,KAAK,EAAE,OAAO,CAAC,WAAW,MAAM,MAAM,EAAG,eAAe,MAAM,UAAU;AAAA,QAAA;AAIrF,cAAM,yBAAyB,IAAI;AAAA,UAClC,OAAO,KAAK,aAAa,EAAE;AAAA,YAAO,CAAC,mBAClC,eAAe,IAAI,cAAc,cAAc,EAAG,IAAI;AAAA,UACvD;AAAA,QAAA;AAIM,eAAA,OAAO,OAAO,WAAW,EAAE;AAAA,UACjC,CAAC,eAAe,WAAW,UAAU,WAAW,CAAC,uBAAuB,IAAI,WAAW,aAAa;AAAA,QAAA;AAAA,MAEtG;AAAA,IACD;AAAA,EACD;AAEa,QAAA,gCAGT;AAAA,IACHA,QAAA;AAAA,MACC,CAAC,uBAAuB,CAAC,QAA0B,aAAuB,QAAQ;AAAA,MAClF,CAAC,aAAa,aAAa;;AAC1B,cAAM,mBAA6D,CAAA;AACnE,mBAAW,WAAW,UAAU;AACd,2BAAA,OAAO,IAAI;QAC7B;AACA,mBAAW,cAAc,aAAa;AACrC,cAAI,WAAW,SAAS,SAAS,SAAS,WAAW,KAAK,GAAG;AAC5D,aAAA9B,MAAA,iBAAiB,WAAW,KAAK,MAAjC,gBAAAA,IAAoC,KAAK;AAAA,UAC1C;AAAA,QACD;AACO,eAAA;AAAA,MACR;AAAA,IACD;AAAA,EACD;AAEa,QAAA,+BAA+B;AAAA,IAC3C8B,QAAA;AAAA,MACC,CAAC,uBAAuB,CAAC,QAA0B,YAAoB,OAAO;AAAA,MAC9E,CAAC,aAAa,YAAY;AAClB,eAAA,YAAY,OAAO,CAAC,eAAe;AACzC,iBAAO,WAAW,UAAU;AAAA,QAAA,CAC5B;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAEa,QAAA,uCAAuC;AAAA,IACnDA,QAAA;AAAA,MACC;AAAA,QACC,CAAC,UAA4B,MAAM,aAAa;AAAA,QAChD,CAAC,UAA4B,MAAM,YAAY;AAAA,QAC/C,CAAC,UAA4B,MAAM,oBAAoB;AAAA,QACvD,CAAC,UAA4B,MAAM,sBAAsB;AAAA,QACzD,CAAC,QAA0B,YAAoB;AAAA,MAChD;AAAA,MACA,CAAC,QAAQ,OAAO,eAAe,aAAa,YAAY;AAEjD,cAAA,QAAQ,OAAO,OAAO;AAE5B,YAAI,CAAC;AAAO,iBAAO;AAEf,YAAA,CAAC,MAAM,YAAY;AACf,iBAAA,OAAO,OAAO,WAAW,EAAE,OAAO,CAAC,eAAe,WAAW,UAAU,OAAO;AAAA,QACtF;AAGA,cAAM,iBAAiB,IAAI;AAAA,UAC1B,OAAO,KAAK,KAAK,EAAE,OAAO,CAAC,WAAW,MAAM,MAAM,EAAG,eAAe,MAAM,UAAU;AAAA,QAAA;AAIrF,cAAM,yBAAyB,IAAI;AAAA,UAClC,OAAO,KAAK,aAAa,EAAE;AAAA,YAAO,CAAC,mBAClC,eAAe,IAAI,cAAc,cAAc,EAAG,IAAI;AAAA,UACvD;AAAA,QAAA;AAIM,eAAA,OAAO,OAAO,WAAW,EAAE;AAAA,UACjC,CAAC,eAAe,WAAW,UAAU,WAAW,CAAC,uBAAuB,IAAI,WAAW,aAAa;AAAA,QAAA;AAAA,MAEtG;AAAA,IACD;AAAA,EACD;AAEa,QAAA,gCAA2FA,QAAA;AAAA,IACvG,CAAC,8BAA8B,mBAAmB;AAAA,IAClD,CAAC,aAAa,WAAW;;AACxB,YAAM,yBAA2D,CAAA;AACjE,iBAAW,WAAW,QAAQ;AACN,+BAAA,OAAO,IAAI;MACnC;AACA,iBAAW,gBAAgB,aAAa;AACjC,cAAA,aAAa,YAAY,YAAY;AAC3C,YAAI,WAAW,OAAO;AACrB,WAAA9B,MAAA,uBAAuB,WAAW,KAAK,MAAvC,gBAAAA,IAA0C,KAAK;AAAA,QAChD;AAAA,MACD;AACO,aAAA;AAAA,IACR;AAAA,EACD;AAEa,QAAA,wBAAsD,oBAAoB;ACxPvF,QAAM,kCAAkC;AAAA,IACvC,CAAC,eAAe,WAAW;AAAA,EAC5B;AAEA,QAAME,iBAA8C,gCAAgC,gBAAgB,CAAA,CAAE;AAEzF,QAAA,gCAAgCC,QAAAA,YAAY;AAAA,IACxD,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,qCAAqC,gCAAgC;AAAA,MACrE,6BAA6B,gCAAgC;AAAA,MAC7D,8BAA8B,gCAAgC;AAAA,MAC9D,6BAA6B,gCAAgC;AAAA,MAC7D,8BAA8B,gCAAgC;AAAA,MAC9D,gCAAgC,gCAAgC;AAAA,MAChE,iCAAiC,gCAAgC;AAAA,MACjE,gCAAgC,gCAAgC;AAAA,MAChE,iCAAiC,gCAAgC;AAAA,IAClE;AAAA,EACD,CAAC;AAEY,QAAA;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI,8BAA8B;AAErB,QAAA,yCAAsG,CAClH,UACI;AACJ,WAAO,MAAM,gCAAgC;AAAA,EAC9C;AAEa,QAAA,uCAAuC;AAAA,IACnD4B,QAAA;AAAA,MACC,CAAC,wCAAwC,CAAC,GAAG,kBAA4B,aAAa;AAAA,MACtF,CAAC,SAAS,kBAAkB;AACrB,cAAA,mBAAmB,IAAI,IAAI,aAAa;AAEvC,eAAA,OAAO,OAAO,OAAO,EAAE,OAAO,CAAC,eAAe,iBAAiB,IAAI,WAAW,UAAU,CAAC;AAAA,MACjG;AAAA,IACD;AAAA,EACD;AAEa,QAAA,oCACZ;AAAA,IACCA,QAAA;AAAA,MACC,CAAC,wCAAwC,CAAC,QAA0B,iBAAyB,YAAY;AAAA,MACzG,CAAC,oBAAoB,iBAAiB;AAC9B,eAAA,OAAO,OAAO,kBAAkB,EAAE,OAAO,CAAC,eAAe,WAAW,eAAe,YAAY;AAAA,MACvG;AAAA,IACD;AAAA,EACD;AAEY,QAAA,kCACZ,8BAA8B;ACrE/B,QAAM,gCAAgC;AAAA,IACrC,CAAC,eAAe,WAAW;AAAA,EAC5B;AAEA,QAAM5B,iBAA4C,8BAA8B,gBAAgB,CAAA,CAAE;AAErF,QAAA,8BAA8BC,QAAAA,YAAY;AAAA,IACtD,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,mCAAmC,8BAA8B;AAAA,MACjE,2BAA2B,8BAA8B;AAAA,MACzD,4BAA4B,8BAA8B;AAAA,MAC1D,2BAA2B,8BAA8B;AAAA,MACzD,4BAA4B,8BAA8B;AAAA,MAC1D,8BAA8B,8BAA8B;AAAA,MAC5D,+BAA+B,8BAA8B;AAAA,MAC7D,8BAA8B,8BAA8B;AAAA,MAC5D,+BAA+B,8BAA8B;AAAA,IAC9D;AAAA,EACD,CAAC;AAEY,QAAA;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI,4BAA4B;AAEnB,QAAA,uCAAkG,CAC9G,UACI;AACJ,WAAO,MAAM,8BAA8B;AAAA,EAC5C;AAEa,QAAA,kCACZ;AAAA,IACC4B,QAAA;AAAA,MACC,CAAC,sCAAsC,CAAC,QAAQ,eAAuB,UAAU;AAAA,MACjF,CAAC,aAAa,eAAe;AACrB,eAAA,OAAO,OAAO,WAAW,EAAE,OAAO,CAAC,eAAe,WAAW,aAAa,UAAU;AAAA,MAC5F;AAAA,IACD;AAAA,EACD;AAEY,QAAA,gCAAsE,4BAA4B;ACnD/G,QAAM,qBAAqB,mBAAgC,CAAC,gBAAgB,YAAY,UAAU;AAElG,QAAM5B,iBAAe,mBAAmB,gBAAgB,CAAA,CAAE;AAE7C,QAAA,oBAAoBC,QAAAA,YAAY;AAAA,IAC5C,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,UAAU;AAAA,MACT,wBAAwB,mBAAmB;AAAA,MAC3C,gBAAgB,mBAAmB;AAAA,MACnC,mBAAmB,mBAAmB;AAAA,IACvC;AAAA,EACD,CAAC;AAEY,QAAA,EAAE,wBAAwB,gBAAgB,sBAAsB,kBAAkB;AAElF,QAAA,8BAA4E,CAAC,UACzF,MAAM,oBAAoB;AAEpB,QAAM,qBAAqB,CAAC,UAClC,OAAO,OAAO,MAAM,oBAAoB,SAAS;AAErC,QAAA,mCAAmC;AAAA,IAC/C4B,QAAA;AAAA,MACC,CAAC,oBAAoB,CAAC,GAAG,mBAA2B,cAAc;AAAA,MAClE,CAAC,cAAc,mBAAmB;AACjC,eAAO,aAAa,OAAO,CAAC,gBAAgB,YAAY,iBAAiB,cAAc;AAAA,MACxF;AAAA,IACD;AAAA,EACD;AAEa,QAAA,sBAAiD,kBAAkB;ACjBhF,QAAM5B,iBAA8B;AAAA,IACnC,WAAW,CAAC;AAAA,EACb;AAEa,QAAA,gBAAgBC,QAAAA,YAAY;AAAA,IACxC,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YACf,QAAQ,QAAQ,SAAS,CAAC,UAAU;AAC5B,aAAA,OAAO,OAAOA,cAAY;AAAA,IAAA,CACjC;AAAA,IACF,UAAU;AAAA,MACT,cAAc,CAAC,OAAO,WAA4C;AAC7D,YAAA,OAAO,QAAQ,OAAO,oBAAoB,EAAE,WAAW,OAAO,QAAQ,QAAQ;AAC3E,gBAAA,IAAI,MAAM,oDAAoD;AAAA,QACrE;AACM,cAAA,YAAY,kBAAkB,OAAO,OAAO;AAAA,MACnD;AAAA,MACA,cAAc,CAAC,OAAO,WAA4C;AACtD,mBAAAsC,aAAY,OAAO,SAAS;AAClC,cAAAA,UAAS,cAAc,MAAM,WAAW;AAC3C,kBAAM,IAAI;AAAA,cACT,gDAAgDA,UAAS,UAAU;AAAA,YAAA;AAAA,UAErE;AAAA,QACD;AACW,mBAAAA,aAAY,OAAO,SAAS;AAClC,cAAAA,UAAS,mBAAmB,CAAC,CAAC,MAAM,UAAUA,UAAS,eAAe,GAAG;AAC5E,kBAAM,iBAAiB,MAAM,UAAUA,UAAS,eAAe;AACzD,kBAAA,UAAUA,UAAS,eAAe,IAAI;AAAA,cAC3C,GAAG;AAAA,cACH,oBAAoB,CAAC,GAAG,eAAe,oBAAoBA,UAAS,UAAU;AAAA,YAAA;AAAA,UAEhF;AACM,gBAAA,UAAUA,UAAS,UAAU,IAAIA;AAAA,QACxC;AAAA,MACD;AAAA,MACA,iBAAiB,CAAC,OAAO,WAAgE;AAC7E,mBAAAA,aAAY,OAAO,SAAS;AACtC,cAAI,EAAEA,UAAS,cAAc,MAAM,YAAY;AAC9C,kBAAM,IAAI;AAAA,cACT,mDAAmDA,UAAS,UAAU;AAAA,YAAA;AAAA,UAExE;AAAA,QACD;AACW,mBAAAA,aAAY,OAAO,SAAS;AACtC,gBAAM,mBAAmB,MAAM,UAAUA,UAAS,UAAU;AAC5D,cAAIA,UAAS,iBAAiB,UAAaA,UAAS,iBAAiB,iBAAiB,cAAc;AAC7F,kBAAA,IAAI,MAAM,gCAAgC;AAAA,UACjD;AACA,cAAIA,UAAS,YAAY,UAAaA,UAAS,YAAY,iBAAiB,SAAS;AAC9E,kBAAA,IAAI,MAAM,2BAA2B;AAAA,UAC5C;AACM,gBAAA,UAAUA,UAAS,UAAU,IAAI;AAAA,YACtC,GAAG;AAAA,YACH,GAAGA;AAAA;AAAA;AAAA,UAAA;AAAA,QAIL;AAAA,MACD;AAAA,MACA,cAAc,CAAC,OAAO,WAA6C;AAClE,cAAM,EAAE,YAAY,kBAAkB,SAAA,IAAa,OAAO;AACtD,YAAA,EAAE,cAAc,MAAM,YAAY;AACrC,gBAAM,IAAI;AAAA,YACT,iDAAiD,UAAU;AAAA,UAAA;AAAA,QAE7D;AAGM,cAAAA,YAAW,MAAM,UAAU,UAAU;AAC3C,YAAIA,UAAS,mBAAmB,MAAM,UAAUA,UAAS,eAAe,GAAG;AAC1E,gBAAM,EAAE,mBAAmB,IAAI,MAAM,UAAUA,UAAS,eAAe;AACvE,gBAAM,UAAUA,UAAS,eAAe,EAAG,mBAAmB;AAAA,YAC7D,mBAAmB,QAAQA,UAAS,UAAU;AAAA,YAC9C;AAAA,UAAA;AAAA,QAEF;AAEA,YAAI,kBAAkB;AACf,gBAAA,iBAAiB,MAAM,UAAU,gBAAgB;AACvD,gBAAM,qBAAoB,iDAAgB,mBACvC,MAAM,UAAU,eAAe,eAAe,IAC9C;AAEH,kBAAQ,UAAU;AAAA,YACjB,KAAK;AACJ,kBAAI,CAAC,mBAAmB;AACvB,sBAAM,IAAI;AAAA,kBACT;AAAA,gBAAA;AAAA,cAEF;AAEA,oBAAM,UAAU,eAAgB,eAAgB,EAAG,mBAAmB;AAAA,gBACrE,kBAAkB,mBAAmB,QAAQ,eAAgB,UAAU;AAAA,gBACvE;AAAA,gBACAA,UAAS;AAAA,cAAA;AAEV,oBAAM,UAAU,UAAU,EAAG,kBAAkB,kBAAkB;AACjE;AAAA,YACD,KAAK;AACJ,kBAAI,CAAC,mBAAmB;AACvB,sBAAM,IAAI;AAAA,kBACT;AAAA,gBAAA;AAAA,cAEF;AAEA,oBAAM,UAAU,eAAgB,eAAgB,EAAG,mBAAmB;AAAA,gBACrE,kBAAkB,mBAAmB,QAAQ,eAAgB,UAAU,IAAI;AAAA,gBAC3E;AAAA,gBACAA,UAAS;AAAA,cAAA;AAEV,oBAAM,UAAU,UAAU,EAAG,kBAAkB,kBAAkB;AACjE;AAAA,YACD,KAAK;AACJ,kBAAI,CAAC,gBAAgB;AACpB,sBAAM,IAAI;AAAA,kBACT;AAAA,gBAAA;AAAA,cAEF;AACA,oBAAM,UAAU,gBAAgB,EAAG,mBAAmB,QAAQA,UAAS,UAAU;AACjF,oBAAM,UAAU,UAAU,EAAG,kBAAkB,eAAe;AAE9D;AAAA,YACD,KAAK;AACJ,kBAAI,CAAC,gBAAgB;AACpB,sBAAM,IAAI;AAAA,kBACT;AAAA,gBAAA;AAAA,cAEF;AACA,oBAAM,UAAU,gBAAgB,EAAG,mBAAmB,KAAKA,UAAS,UAAU;AAC9E,oBAAM,UAAU,UAAU,EAAG,kBAAkB,eAAe;AAAA,UAChE;AAAA,QAAA,OACM;AACA,gBAAA,UAAU,UAAU,EAAG,kBAAkB;AAAA,QAChD;AAAA,MACD;AAAA,MACA,iBAAiB,CAAC,OAAO,WAAkC;AAC/C,mBAAA,cAAc,OAAO,SAAS;AACpC,cAAA,EAAE,cAAc,MAAM,YAAY;AACrC,kBAAM,IAAI;AAAA,cACT,mDAAmD,UAAU;AAAA,YAAA;AAAA,UAE/D;AAAA,QACD;AACW,mBAAA,cAAc,OAAO,SAAS;AAClC,gBAAAA,YAAW,MAAM,UAAU,UAAU;AACvC,cAAAA,UAAS,mBAAmB,CAAC,CAAC,MAAM,UAAUA,UAAS,eAAe,GAAG;AAC5E,kBAAM,iBAAiB,MAAM,UAAUA,UAAS,eAAe;AACzD,kBAAA,UAAUA,UAAS,eAAe,IAAI;AAAA,cAC3C,GAAG;AAAA,cACH,oBAAoB,eAAe,mBAAmB;AAAA,gBACrD,CAAC,eAAe,eAAeA,UAAS;AAAA,cACzC;AAAA,YAAA;AAAA,UAEF;AACO,iBAAA,MAAM,UAAU,UAAU;AAAA,QAClC;AAAA,MACD;AAAA,IACD;AAAA,EACD,CAAC;AAEM,QAAM,EAAE,cAAc,cAAc,iBAAiB,cAAc,gBAAA,IAAoB,cAAc;AAE/F,QAAA,yBAA4E,CAAC,UACzF,MAAM,iBAAiB;AAEX,QAAA,kBAAuDV,QAAA;AAAA,IACnE,CAAC,sBAAsB;AAAA,IACvB,CAAC,YAAY,OAAO,OAAO,OAAO;AAAA,EACnC;AAEO,QAAM,qBACZ,CAAC,eAAuC,CAAC,UAAU;AAC3C,WAAA,MAAM,iBAAiB,UAAU,UAAU;AAAA,EACnD;AAEY,QAAA,uBAAuB;AAAA,IACnCA,QAAA;AAAA,MACC,CAAC,wBAAwB,CAAC,QAAQ,gBAA0C,WAAW;AAAA,MACvF,CAAC,SAAS,gBAAgB;AACzB,cAAM,YAAgC,CAAA;AAEtC,mBAAW,cAAc,aAAa;AAC/B,gBAAAU,YAAW,QAAQ,UAAU;AACnC,cAAIA,WAAU;AACb,sBAAU,KAAKA,SAAQ;AAAA,UAAA,OACjB;AACE,oBAAA,KAAK,uDAAuD,UAAU;AAAA,UAC/E;AAAA,QACD;AACO,eAAA;AAAA,MACR;AAAA,IACD;AAAA,EACD;AAEa,QAAA,8BAA8B;AAAA,IAC1CV,uBAAe,CAAC,wBAAwB,CAAC,QAAQ,eAAuB,UAAU,GAAG,CAAC,SAAS,eAAe;AAC7G,YAAM,kBAA4B,CAAA;AAC5B,YAAAU,YAAW,QAAQ,UAAU;AAC/B,UAAA,CAACA,aAAY,CAACA,UAAS;AAAwB,eAAA;AAE/C,UAAA,kBAAkB,QAAQA,UAAS,eAAe;AAEtD,aAAO,iBAAiB;AACP,wBAAA,KAAK,gBAAgB,UAAU;AAC7B,0BAAA,QAAQ,gBAAgB,mBAAmB,EAAE;AAAA,MAChE;AACO,aAAA;AAAA,IAAA,CACP;AAAA,EACF;AAEa,QAAA,sBAAsBV,QAAA;AAAA,IAAe,CAAC,eAAe;AAAA,IAAG,CAAC,cACrE,UAAU,OAAO,CAACU,cAAa,CAACA,UAAS,eAAe;AAAA,EACzD;AAEa,QAAA,mBAA2C,cAAc;ACtOtE,QAAM,4BAA4B,mBAA+C,CAAC,eAAe,WAAW,UAAU;AAEtH,QAAMtC,iBAAe,0BAA0B,gBAAgB,CAAA,CAAE;AAEpD,QAAA,0BAA0BC,QAAAA,YAAY;AAAA,IAClD,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,+BAA+B,0BAA0B;AAAA,MACzD,uBAAuB,0BAA0B;AAAA,MACjD,wBAAwB,0BAA0B;AAAA,MAClD,uBAAuB,0BAA0B;AAAA,MACjD,wBAAwB,0BAA0B;AAAA,MAClD,0BAA0B,0BAA0B;AAAA,MACpD,2BAA2B,0BAA0B;AAAA,MACrD,0BAA0B,0BAA0B;AAAA,MACpD,2BAA2B,0BAA0B;AAAA,IACtD;AAAA,EACD,CAAC;AAEY,QAAA;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI,wBAAwB;AAEf,QAAA,kCAAkC,CAAC,UAA4B,MAAM,0BAA0B;AAE/F,QAAA,+BAA8E4B,QAAA;AAAA,IAC1F,CAAC,+BAA+B;AAAA,IAChC,CAAC,YAAY,OAAO,OAAO,OAAO;AAAA,EACnC;AAEO,QAAM,2BACZ,CAAC,iBAAyB,CAAC,UAA4B;AAC/C,WAAA,MAAM,0BAA0B,UAAU,YAAY;AAAA,EAC9D;AAEY,QAAA,8BAA8B;AAAA,IAC1CA,QAAA;AAAA,MACC,CAAC,8BAA8B,CAAC,QAA0B,eAAuB,UAAU;AAAA,MAC3F,CAAC,aAAa,eAAe;AAC5B,eAAO,YAAY,OAAO,CAAC,EAAE,UAAAU,UAAS,MAAM,eAAeA,SAAQ;AAAA,MACpE;AAAA,IACD;AAAA,EACD;AAEa,QAAA,oCAAoC;AAAA,IAChDV,QAAA;AAAA,MACC,CAAC,8BAA8B,CAAC,QAA0B,eAAuB,UAAU;AAAA,MAC3F,CAAC,aAAa,eAAe;AACtB,cAAA,uBAAuB,YAAY,OAAO,CAAC,EAAE,UAAAU,gBAAe,eAAeA,SAAQ;AACzF,cAAM,kBAAkB,qBAAqB;AAAA;AAAA,UAE5C,CAAC,EAAE,UAAU,MAAM,CAAC,aAAa,CAAC,UAAU,WAAW,QAAQ;AAAA,QAAA;AAEhE,cAAM,mBAAmB,qBAAqB;AAAA;AAAA,UAE7C,CAAC,EAAE,UAAA,MAAgB,aAAa,UAAU,WAAW,QAAQ;AAAA,QAAA;AAEvD,eAAA,EAAE,iBAAiB;MAC3B;AAAA,IACD;AAAA,EACD;AAEa,QAAA,4BAA8D,wBAAwB;AChEnG,QAAM,cAAc,mBAAiC,CAAC,SAAS,KAAK,UAAU;AAE9E,QAAMtC,iBAA0B,YAAY,gBAAgB,CAAA,CAAE;AAEjD,QAAA,YAAYC,QAAAA,YAAY;AAAA,IACpC,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,SAAS,YAAY;AAAA,MACrB,iBAAiB,YAAY;AAAA,MAC7B,SAAS,YAAY;AAAA,MACrB,YAAY,YAAY;AAAA,MACxB,YAAY,YAAY;AAAA,IACzB;AAAA,EACD,CAAC;AAEM,QAAM,EAAE,SAAS,iBAAiB,SAAS,YAAY,WAAA,IAAe,UAAU;AAE1E,QAAA,qBAA8D,CAAC,UAC3E,MAAM,YAAY;AAEN,QAAA,cAA+C4B,QAAAA,eAAe,CAAC,kBAAkB,GAAG,CAAC,UAAU;AACpG,WAAA,OAAO,OAAO,KAAK;AAAA,EAC3B,CAAC;AAEM,QAAM,iBACZ,CAAC,WAAmB,CAAC,UAA4B;AACzC,WAAA,MAAM,YAAY,UAAU,MAAM;AAAA,EAC1C;AAEY,QAAA,4BACZ;AAAA,IACCA,QAAA;AAAA,MACC,CAAC,aAAa,CAAC,QAA0B,mBAAuC,cAAc;AAAA,MAC9F,CAAC,OAAO,mBAAmB;AAC1B,eAAO,MAAM,OAAO,CAAC,SAAS,KAAK,iBAAiB,cAAc;AAAA,MACnE;AAAA,IACD;AAAA,EACD;AAEY,QAAA,oBAAyE;AAAA,IACrFA,uBAAe,CAAC,aAAa,CAAC,QAA0B,WAAuB,MAAM,GAAG,CAAC,OAAO,WAAW;AACnG,aAAA,MAAM,OAAO,CAAC,SAAS,KAAK,QAAQ,SAAS,MAAM,CAAC;AAAA,IAAA,CAC3D;AAAA,EACF;AAEa,QAAA,cAAkC,UAAU;ACvDzD,QAAM,+BAA+B;AAAA,IACpC,CAAC,iBAAiB,aAAa;AAAA,EAChC;AAEA,QAAM5B,iBAAe,6BAA6B,gBAAgB,CAAA,CAAE;AAEvD,QAAA,cAAcC,QAAAA,YAAY;AAAA,IACtC,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,yBAAyB,6BAA6B;AAAA,MACtD,iBAAiB,6BAA6B;AAAA,MAC9C,iBAAiB,6BAA6B;AAAA,MAC9C,oBAAoB,6BAA6B;AAAA,IAClD;AAAA,EACD,CAAC;AAEM,QAAM,EAAE,yBAAyB,iBAAiB,iBAAiB,uBAAuB,YAAY;AAChG,QAAA,4BAA4B,CAAC,UAA4B,MAAM,cAAc;AAE7E,QAAA,sBAAgE4B,QAAA;AAAA,IAC5E,CAAC,yBAAyB;AAAA,IAC1B,CAAC,wBAAwB,OAAO,OAAO,mBAAmB;AAAA,EAC3D;AAEa,QAAA,qBAAqB;AAAA,IACjCA,QAAA;AAAA,MACC,CAAC,2BAA2B,CAAC,QAAQ,mBAA2B,cAAc;AAAA,MAC9E,CAAC,qBAAqB,mBAAmB,oBAAoB,cAAc;AAAA,IAC5E;AAAA,EACD;AAEa,QAAA,gBAAsC,YAAY;ACjC/D,QAAM,sBAAsB,mBAAyC,CAAC,YAAY,QAAQ,UAAU;AAEpG,QAAM5B,iBAAkC,oBAAoB,gBAAgB,CAAA,CAAE;AAEjE,QAAA,oBAAoBC,QAAAA,YAAY;AAAA,IAC5C,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,iBAAiB,oBAAoB;AAAA,MACrC,kBAAkB,oBAAoB;AAAA,MACtC,iBAAiB,oBAAoB;AAAA,MACrC,kBAAkB,oBAAoB;AAAA,MACtC,oBAAoB,oBAAoB;AAAA,MACxC,qBAAqB,oBAAoB;AAAA,IAC1C;AAAA,EACD,CAAC;AAEY,QAAA;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI,kBAAkB;AAET,QAAA,4BAA4B,CAAC,UAA4B,MAAM,oBAAoB;AAEnF,QAAA,wBAAwB;AAAA,IACpC4B,QAAA;AAAA,MACC,CAAC,2BAA2B,CAAC,QAAQ,YAAoB,OAAO;AAAA,MAChE,CAAC,gBAAgB,YAAoB;AAC7B,eAAA,OAAO,OAAO,cAAc,EAAE,OAAO,CAAC,YAAY,QAAQ,UAAU,OAAO;AAAA,MACnF;AAAA,IACD;AAAA,EACD;AAEa,QAAA,sBAAkD,kBAAkB;ACtCjF,QAAM,qBAAqB,mBAAwC,CAAC,gBAAgB,YAAY,UAAU;AAE1G,QAAM5B,iBAAiC,mBAAmB,gBAAgB,CAAA,CAAE;AAE/D,QAAA,mBAAmBC,QAAAA,YAAY;AAAA,IAC3C,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,wBAAwB,mBAAmB;AAAA,MAC3C,gBAAgB,mBAAmB;AAAA,MACnC,gBAAgB,mBAAmB;AAAA,MACnC,iBAAiB,mBAAmB;AAAA,MACpC,mBAAmB,mBAAmB;AAAA,MACtC,oBAAoB,mBAAmB;AAAA,IACxC;AAAA,EACD,CAAC;AAEY,QAAA;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI,iBAAiB;AAER,QAAA,2BAA2B,CAAC,UAA4B,MAAM,mBAAmB;AAEjF,QAAA,4BAA4B;AAAA,IACxC4B,QAAA;AAAA,MACC,CAAC,0BAA0B,CAAC,QAA0B,YAAoB,OAAO;AAAA,MACjF,CAAC,SAAS,YAAY;AACd,eAAA,OAAO,OAAO,OAAO,EAAE,OAAO,CAAC,WAAW,OAAO,UAAU,OAAO;AAAA,MAC1E;AAAA,IACD;AAAA,EACD;AAEa,QAAA,qBAAgD,iBAAiB;ACtC9E,QAAM,yBAAyB,mBAA4C,CAAC,eAAe,WAAW,UAAU;AAEhH,QAAM5B,iBAAqC,uBAAuB,gBAAgB,CAAA,CAAE;AAEvE,QAAA,uBAAuBC,QAAAA,YAAY;AAAA,IAC/C,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAOA,cAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,4BAA4B,uBAAuB;AAAA,MACnD,oBAAoB,uBAAuB;AAAA,MAC3C,qBAAqB,uBAAuB;AAAA,MAC5C,oBAAoB,uBAAuB;AAAA,MAC3C,qBAAqB,uBAAuB;AAAA,MAC5C,uBAAuB,uBAAuB;AAAA,MAC9C,wBAAwB,uBAAuB;AAAA,MAC/C,uBAAuB,uBAAuB;AAAA,MAC9C,wBAAwB,uBAAuB;AAAA,IAChD;AAAA,EACD,CAAC;AAEY,QAAA;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI,qBAAqB;AAEZ,QAAA,+BAA+B,CAAC,UAA4B,MAAM,uBAAuB;AACzF,QAAA,yBAAqE4B,QAAA;AAAA,IACjF,CAAC,4BAA4B;AAAA,IAC7B,CAAC,YAAY,OAAO,OAAO,OAAO;AAAA,EACnC;AAEa,QAAA,2BAA2B;AAAA,IACvCA,QAAA;AAAA,MACC,CAAC,wBAAwB,CAAC,QAA0B,YAAoB,OAAO;AAAA,MAC/E,CAAC,aAAa,YAAY;AACzB,eAAO,YAAY,OAAO,CAAC,EAAE,MAAM,MAAM,YAAY,KAAK;AAAA,MAC3D;AAAA,IACD;AAAA,EACD;AAEO,QAAM,wBACZ,CAAC,iBAAyB,CAAC,SAA2B;AAC9C,WAAA,KAAK,uBAAuB,UAAU,YAAY;AAAA,EAC1D;AAEY,QAAA,iCAAiC;AAAA,IAC7CA,QAAA;AAAA,MACC,CAAC,wBAAwB,CAAC,QAA0B,YAAoB,OAAO;AAAA,MAC/E,CAAC,aAAa,YAAY;AACnB,cAAA,qBAAqB,YAAY,OAAO,CAAC,EAAE,YAAY,UAAU,OAAO;AAC9E,cAAM,kBAAkB,mBAAmB;AAAA;AAAA,UAE1C,CAAC,EAAE,UAAU,MAAM,CAAC,aAAa,CAAC,UAAU,WAAW,QAAQ;AAAA,QAAA;AAEhE,cAAM,mBAAmB,mBAAmB;AAAA;AAAA,UAE3C,CAAC,EAAE,UAAA,MAAgB,aAAa,UAAU,WAAW,QAAQ;AAAA,QAAA;AAEvD,eAAA,EAAE,iBAAiB;MAC3B;AAAA,IACD;AAAA,EACD;AAEa,QAAA,yBAAwD,qBAAqB;ACzE1F,QAAM5B,iBAAgC;AAAA,IACrC,SAAS;AAAA,EACV;AAKa,QAAA,kBAAkBC,QAAAA,YAAY;AAAA,IAC1C,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,UAAU,CAAC;AAAA,EACZ,CAAC;AAEY,QAAA,oBAA8C,gBAAgB;ACX3E,QAAM,kBAAkB,mBAA6B,CAAC,UAAU,MAAM,UAAU;AAEhF,QAAMA,iBAAmC,gBAAgB,gBAAgB,CAAA,CAAE;AAE9D,QAAA,gBAAgBC,QAAAA,YAAY;AAAA,IACxC,MAAM;AAAA,IAAA,cACND;AAAAA,IACA,eAAe,CAAC,YAAY;AACnB,cAAA,QAAQ,SAAS,CAAC,UAAU;AAC5B,eAAA,OAAO,OAAOA,cAAY;AAAA,MAAA,CACjC;AAAA,IACF;AAAA,IACA,UAAU;AAAA,MACT,qBAAqB,gBAAgB;AAAA,MACrC,aAAa,gBAAgB;AAAA,MAC7B,cAAc,gBAAgB;AAAA,MAC9B,aAAa,gBAAgB;AAAA,MAC7B,cAAc,gBAAgB;AAAA,MAC9B,gBAAgB,gBAAgB;AAAA,MAChC,iBAAiB,gBAAgB;AAAA,MACjC,gBAAgB,gBAAgB;AAAA,MAChC,iBAAiB,gBAAgB;AAAA,IAClC;AAAA,EACD,CAAC;AAEY,QAAA;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI,cAAc;AAEL,QAAA,wBAAwB,CAAC,UAA4B,MAAM,gBAAgB;AAEjF,QAAM,kBAAkB,CAAC,UAA4B,OAAO,OAAO,MAAM,gBAAgB,SAAS;AAElG,QAAM,qBAAqB,CAAC,OAAe,CAAC,UAA4B;AACvE,WAAA,MAAM,gBAAgB,UAAU,EAAE;AAAA,EAC1C;AAEa,QAAA,2BAA2B;AAAA,IACvC4B,uBAAe,CAAC,iBAAiB,CAAC,GAAG,cAAsB,SAAS,GAAG,CAAC,WAAW,cAAc;AAChG,aAAO,UAAU,OAAO,CAAC,aAAa,SAAS,YAAY,SAAS;AAAA,IAAA,CACpE;AAAA,EACF;AAEa,QAAA,kBAA+C,cAAc;ACnD1E,QAAM,0BAA0B,mBAA6C,CAAC,UAAU,MAAM,UAAU;AAExG,QAAM,eAA2C,wBAAwB,gBAAgB,CAAA,CAAE;AAE9E,QAAA,wBAAwB3B,QAAAA,YAAY;AAAA,IAChD,MAAM;AAAA,IACN;AAAA,IACA,eAAe,CAAC,YAAY,QAAQ,QAAQ,SAAS,CAAC,UAAU,OAAO,OAAO,OAAO,YAAY,CAAC;AAAA,IAClG,UAAU;AAAA,MACT,6BAA6B,wBAAwB;AAAA,MACrD,qBAAqB,wBAAwB;AAAA,MAC7C,sBAAsB,wBAAwB;AAAA,MAC9C,qBAAqB,wBAAwB;AAAA,MAC7C,sBAAsB,wBAAwB;AAAA,MAC9C,wBAAwB,wBAAwB;AAAA,MAChD,yBAAyB,wBAAwB;AAAA,MACjD,wBAAwB,wBAAwB;AAAA,MAChD,yBAAyB,wBAAwB;AAAA,IAClD;AAAA,EACD,CAAC;AAEY,QAAA;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI,sBAAsB;AAEb,QAAA,gCAAgC,CAAC,UAC7C,MAAM,wBAAwB;AAElB,QAAA,0BAA0B2B,QAAAA,eAAe,CAAC,6BAA6B,GAAG,CAAC,iBAAiB;AACjG,WAAA,OAAO,OAAO,YAAY;AAAA,EAClC,CAAC;AAEM,QAAM,6BACZ,CAAC,OAAO,CAAC,UAAU;AACX,WAAA,MAAM,wBAAwB,UAAU,EAAE;AAAA,EAClD;AAEY,QAAA,iCAAiC;AAAA,IAC7CA,QAAA;AAAA,MACC,CAAC,+BAA+B,CAAC,QAAQ,YAAoB,OAAO;AAAA,MACpE,CAAC,oBAAoB,YAAY;AACzB,eAAA,OAAO,OAAO,kBAAkB,EAAE,OAAO,CAAC,UAAU,MAAM,qBAAqB,OAAO;AAAA,MAC9F;AAAA,IACD;AAAA,EACD;AAEa,QAAA,iCAAiC;AAAA,IAC7CA,QAAA;AAAA,MACC,CAAC,+BAA+B,CAAC,QAAQ,YAAoB,OAAO;AAAA,MACpE,CAAC,oBAAoB,YAAY;AACzB,eAAA,OAAO,OAAO,kBAAkB,EAAE,OAAO,CAAC,UAAU,MAAM,UAAU,OAAO;AAAA,MACnF;AAAA,IACD;AAAA,EACD;AAEa,QAAA,iCAAiC;AAAA,IAC7CA,QAAA;AAAA,MACC,CAAC,+BAA+B,CAAC,QAAQ,YAAoB,OAAO;AAAA,MACpE,CAAC,oBAAoB,YAAY;AACzB,eAAA,OAAO,OAAO,kBAAkB,EAAE,OAAO,CAAC,UAAU,MAAM,UAAU,OAAO;AAAA,MACnF;AAAA,IACD;AAAA,EACD;AAEa,QAAA,0BAA+D,sBAAsB;AC/E3F,QAAM,sBAAsB;ACC5B,QAAM,uBAAuB,YAAY;AACnC,QAAA,yBAAyB,cAAc;ACH7C,QAAM,qBAAqB;ACOlC,MAAI;AAEG,WAAS,eAAyC,OAA6B;AACvE,kBAAA;AAAA,EACf;AAEO,WAAS,iBAAsD;AAC9D,WAAA;AAAA,EACR;AAEA,MAAI;AAEG,WAAS,aAAuC,SAA0B;AACpE,gBAAA;AAAA,EACb;AAEO,WAAS,eAA+C;AACvD,WAAA;AAAA,EACR;ACpBO,QAAM,wBAAoF,CAAA;AAAA,EAK1F,MAAe,YAAoE;AAAA,IAI/E,YAAY,KAAW;AAHd;AAII,4BAAA,KAAK,YAAY,IAAI,IAAI;AAC/C,WAAK,SAAS;AAAA,IACf;AAAA,IAEA,MAAgB,eAAwB,gBAA8C;AAG9E,aAAA,KAAK,OAAO,eAAe,gBAAgB,KAAK,MAAM,KAAK,YAAY,IAAI;AAAA,IACnF;AAAA,IAEU,SAAS,QAAmB;AAChC,WAAA,OAAO,MAAM,SAAS,MAAM;AAAA,IAClC;AAAA,EACD;ACkGa,QAAA,sBAAsB;AAE5B,QAAM,kBAAkB;AAAA;AAAA,IAE9B,CAAC,mBAAmB,GAAG;AAAA,IACvB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AAyCA,QAAM,iBAAiBW,QAAAA,gBAAgB,eAAe;AAIzC,QAAA,aAAa;AAE1B,WAAS,uBAAuB,OAAyB,QAAyB;AACjF,UAAM,cAAe,OAA2C;AAChE,UAAM,2BAA2B,OAAO,OAAO,MAAM,aAAa,SAAS,EAAE;AAAA,MAAO,CAAC,UACpF,MAAM,sBAAsB,SAAS,WAAW;AAAA,IAAA;AAG3C,UAAA,gBAAgB,oBAAoB,KAAK;AAC/C,QAAI,CAAC,eAAe;AACb,YAAA,IAAI,MAAM,0BAA0B;AAAA,IAC3C;AACI,QAAA,OAAO,YAAY,cAAc,YAAY;AAC1C,YAAA,IAAI,MAAM,gCAAgC;AAAA,IACjD;AAGA,UAAM,4BAA4B,IAAI;AAAA,OACpC,4BAA4B,WAAW,EAAE,KAAK,KAAK,IAAI,IAAI,CAAC,aAAa,SAAS,UAAU;AAAA,IAAA;AAE9F,eAAW,SAAS,0BAA0B;AAC7C,UAAI,MAAM,YAAY,0BAA0B,IAAI,MAAM,QAAQ,GAAG;AACpE,cAAM,WAAW;AAAA,MAClB;AAAA,IACD;AAMA,UAAM,+BAA+B,yBAAyB;AAAA,MAC7D,CAAC,UAAU,MAAM,oBAAoB,OAAO;AAAA,IAAA;AAG7C,eAAW,SAAS,8BAA8B;AAGjD,YAAM,kBAAkB,cAAc;AACtC,UAAI,CAAC,MAAM,sBAAsB,SAAS,cAAc,UAAU,GAAG;AAC9D,cAAA,sBAAsB,KAAK,cAAc,UAAU;AAAA,MAC1D;AAAA,IACD;AAGA,eAAW,SAAS,0BAA0B;AAC7C,YAAM,mBAAmB,MAAM,sBAAsB,QAAQ,WAAW;AACxE,UAAI,qBAAqB,IAAI;AAEtB,cAAA,IAAI,MAAM,sDAAsD;AAAA,MACvE;AACM,YAAA,sBAAsB,OAAO,kBAAkB,CAAC;AAAA,IACvD;AAGA,eAAW,SAAS,0BAA0B;AACzC,UAAA,MAAM,sBAAsB,WAAW,GAAG;AAC7C,cAAM,IAAI,MAAM,2BAA2B,MAAM,UAAU,+BAA+B;AAAA,MAC3F;AACA,UAAI,MAAM,oBAAoB,OAAO,WAAW,CAAC,MAAM,iBAAiB;AACvE,cAAM,IAAI,MAAM,6CAA6C,MAAM,UAAU,oBAAoB;AAAA,MAClG;AAAA,IACD;AAAA,EACD;AAIa,QAAA,qBAAgD,CAAC,OAAO,WAA6B;AAEjG,QAAI,OAAO,SAAS,sBAAsB,CAAC,OAAO,SAAS;AACnD,aAAA,eAAe,QAAW,MAAM;AAAA,IACxC;AAEA,QAAI,eAAe;AAEf,QAAA,SAAS,OAAO,SAAS,6BAA6B;AAC1C,qBAAAC,QAAA,gBAAgB,OAAO,CAAC,UAAU;AAChD,+BAAuB,OAAO,MAAM;AAAA,MAAA,CACpC;AAAA,IACF;AAEO,WAAA,eAAe,cAAc,MAAM;AAAA,EAC3C;AAYA,MAAI,uBAAiD;AAE9C,WAAS,uBAAiD;AAChE,UAAMC,eAAc;AACpB,QAAI,CAACA,cAAa;AACjB,cAAQ,KAAK,0DAA0D;AAChE,aAAA;AAAA,IACR;AACA,QAAI,sBAAsB;AAClB,aAAA;AAAA,IACR;AACA,UAAM,SAASA,aAAY,SAAS,EAAE,QAAQ;AACxC,UAAA,cAAc,kBAAkB,YAAY,MAAM;AACjC,2BAAA;AAChB,WAAA;AAAA,EACR;AAIA,QAAM,kBAAkB,CAAC,QAAsB;AAC1C,QAAA;AAAW,YAAA;AACf,UAAMA,eAAc;AACpB,QAAIA,cAAa;AAChB,MAAAA,aAAY,SAAS,EAAE,MAAM,4BAA4B,SAAS,MAAM;AAAA,IAAA,OAClE;AACN,cAAQ,MAAM,sBAAsB;AAAA,IACrC;AAAA,EACD;AAEa,QAAA,UAAsC,CAAC,QAAQ,MAAM,aAAa;AAC9E,UAAM,cAAc;AACpB,QAAI,CAAC,aAAa;AACjB,cAAQ,KAAK,yDAAyD;AACtE,aAAO;IACR;AACA,gBAAY,WAAW,IAAyB;AAChD,WAAO,YAAY;EACpB;AAEa,QAAA,UAAsC,CAAC,QAAQ,MAAM,aAAa;AAC9E,UAAM,cAAc;AACpB,QAAI,CAAC,aAAa;AACjB,cAAQ,KAAK,yDAAyD;AACtE,aAAO;IACR;AAIA,UAAM,OAAO,KAAK;AACZ,UAAA9C,QAAO,KAAK,cAAc,QAAQ;AACxC,gBAAY,OAAOA,KAAI;AACvB,WAAO,YAAY;EACpB;AAGA,iBAAe,OAAO,SAA4B,QAA2B;AAGxE,QAAA,CAAC,OAAO,SAAS;AACd,YAAA,IAAI,MAAM,wBAAwB;AAAA,IACzC;AAIA,WAAO,cAAc,MAAM;AAAA,EAC5B;AAEA,QAAM,eAAgC;AAAA,IACrC,GAAG;AAAA,IACH;AAAA;AAAA;AAAA,IAGA;AAAA,IACA,gBAAgB;AAAA,IAChB;AAAA,IACA;AAAA;AAAA;AAAA,IAGA,gBAAgB,EAAE,SAAS,YAAY;AAAA;AAAA;AAAA;AAAA,IAIvC,OAAO;AAAA,MACN,GAAG,cAAc;AAAA,MACjB;AAAA,MACA;AAAA;AAAA,MAEA,MAAM,IAAI,SAAS,KAAK,GAAI,IAAgC;AAAA,IAC7D;AAAA,EACD;AAGA,QAAM,YAAY,gBAAgB,UAAU,mBAAmB;AAMlD,QAAA,kBAAkB,QAAQ+C,aAAAA,QAAQ,YAAY,GAAG,SAAS;AAMvE,WAAS,yBAAyB,OAA8C;AAC/E,aAAS,WAAW,UAAiD;AAEpE,YAAM,YAAY,CAAC,MAAM,YAAY,eAAe,eAAe,OAAO;AACnE,aAAA,OAAO,aAAa,YAAY,aAAa,QAAQ,UAAU,MAAM,CAAC,QAAQ,OAAO,QAAQ;AAAA,IACrG;AAEA,QAAI,WAAW,KAAK;AAAU,aAAA;AAC9B,QAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAChD,YAAM,aAAa;AACf,UAAA,WAAW,WAAW,QAAQ;AAAG,eAAO,WAAW;AACvD,UAAI,WAAW,YAAY,WAAW,WAAW,SAAS,QAAQ;AAAG,eAAO,WAAW,SAAS;AAAA,IACjG;AACO,WAAA;AAAA,EACR;AAGsB,iBAAA,eAAe,QAA2B,QAAuD;AACtH,UAAM,mBAAmB,sBAAsB,OAAO,KAAK,QAAQ,OAAO,WAAW;AAErF,QAAI,CAAC,kBAAkB;AAChB,YAAA,IAAI,MAAM,WAAW,OAAO,KAAK,QAAQ,OAAO,WAAW,YAAY;AAAA,IAC9E;AAEA,UAAM,eAAe,4BAA4B;AAE3C,UAAA,QAAQ,OAAO,MAAM,SAAS;AACpC,QAAI,MAAM,cAAc,gBAAgB,SAAS,OAAO,QAAQ,IAAI,GAAG;AAGhE,YAAA,IAAI,MAAM,iCAAiC;AAAA,IAClD;AAEA,QAAI,gBAAgB,OAAO,QAAQ,cAAc,OAAO;AACjD,YAAA,iBAAiB,KAAK;IAC7B;AAEA,UAAM,kBAAkB;AAAA,MACvB,aAAa;AAAA,MACb,cAAc;AAAA,IAAA;AAGT,UAAA,gBAAgB,OAAO,KAAK,QAAQ;AACpC,UAAA,EAAE,SAAS,SAAS,QAAQ,aAAa,gBAAgB,eAAe,cAAc,mBAAmB;AAAA,MAC9G,GAAG;AAAA,MACH,GAAG,cAAc;AAAA,IAAA;AAElB,UAAM,iBAAiB,cAAc;AACrC,QAAI,MAAM,eAAe;AACzB,UAAM,OAAO,iBAAiB,MAAM,OAAO,MAAM,WAAW,cAAc,IAAI;AAE1E,QAAA,kBAAkB,CAAC,MAAM;AAC5B,YAAM,IAAI,MAAM,sBAAsB,cAAc,2BAA2B;AAAA,IAChF;AAEK,SAAA,CAAC,iBAAiB,UAAwB,CAAC,IAAI,WAAW,MAAM,GAAG;AACnE,UAAA,CAAC,IAAI,WAAW,GAAG,KAAK,CAAC,IAAI,WAAW,OAAO,GAAG;AACrD,cAAM,MAAM;AAAA,MAIb;AACA,YAAM,OAAO,KAAK,QAAQ,OAAO,WAAW;AAAA,IAC7C;AAEM,UAAA,aAAa,CAAC,QAAmC;AACtD,UAAI,gBAAgB;AACnB,cAAM,QAAQ,eAAe;AAC7B,YAAI,CAAC;AAAO,gBAAM,IAAI,MAAM,sBAAsB,cAAc,EAAE;AAClE,YAAI,aAAa;AAAO,gBAAM,IAAI,MAAM,2BAA2B,cAAc,EAAE;AACnF,YAAI,CAAC;AAAM,gBAAM,IAAI,MAAM,oBAAoB,cAAc,EAAE;AACzD,cAAA,iBAAiB,MAAM,OAAO,qBAAqB;AACzD,YAAI,CAAC;AAAgB,gBAAM,IAAI,MAAM,wBAAwB,cAAc,EAAE;AAC7E,eAAO,IACL,IAAI,uBAAuB,cAAc,EACzC,MAAM,EAAE,GAAG,SAAS,GAAG,MAAM,OAAQ,CAAA,EACrC,OAAO,QAAQ,IAAuB;AAAA,MACzC;AACO,aAAA,IAAI,KAAK,OAAO;AAAA,IAAA;AAGxB,UAAM,uBAA4E;AAAA,MACjF,CAAC,WAAW,GAAG,GAAG,MAAM;AACvB,YAAI,gBAAgB;AACnB,iBAAO,QAAQ,IAAI,IAAI,UAAU,EAAE,aAAa,MAAM;AAAA,QACvD;AACA,eAAO,QAAQ,IAAI,IAAI,SAAU,CAAA;AAAA,MAClC;AAAA,MACA,CAAC,WAAW,IAAI,GAAG,MAAM;AACxB,cAAM,MAAM,QAAQ,KAAK,IAAI,SAAU,CAAA;AACvC,eAAO,WAAW,GAAG;AAAA,MACtB;AAAA,MACA,CAAC,WAAW,KAAK,GAAG,MAAM;AACzB,cAAM,MAAM,QAAQ,MAAM,IAAI,SAAU,CAAA;AACxC,eAAO,WAAW,GAAG;AAAA,MACtB;AAAA,MACA,CAAC,WAAW,GAAG,GAAG,MAAM;AACvB,cAAM,MAAM,QAAQ,IAAI,IAAI,SAAU,CAAA;AACtC,eAAO,WAAW,GAAG;AAAA,MACtB;AAAA,MACA,CAAC,WAAW,MAAM,GAAG,MAAM;AAC1B,cAAM,MAAM,QAAQ,OAAO,IAAI,SAAU,CAAA;AACzC,eAAO,WAAW,GAAG;AAAA,MACtB;AAAA,IAAA;AAGK,UAAA,kBAAkB,qBAAqB,MAAM;AAEnD,QAAI,gBAAgB;AACpB,QAAI,gBAAgB,cAAc;AAC3B,YAAA,aAAa,iBAAiB,KAAK,cAAc;AACvC,sBAAA,cAAc,IAAI,iBAAiB,UAAU;AAAA,IAC9D;AACA,QAAI,SAAS;AACI,sBAAA,cAAc,IAAI,OAAO;AAAA,IAC1C;AAEI,QAAA;AACI,aAAA,MAAM,cAAc,MAAM,WAAW;AAAA,aACpC,OAAO;AAGT,YAAA,gBAAgB,yBAAyB,KAAK;AACpD,YAAM,SAA6B,+CAAe;AAE9C,UAAA,gBAAgB,WAAW,KAAK;AACnC,cAAM,iBAAiB,KAAK,mBAAmB,eAAe,aAAc;AACrE,eAAA,cAAc,MAAM,WAAW;AAAA,MACvC;AAIA,YAAM,IAAI,SAAS,EAAE,UAAU,eAAe,YAAY,OAAO,SAAS,gBAAgB,SAAS,MAAO,EAAG,CAAA;AAAA,IAC9G;AAAA,EACD;AAAA,EAOA,MAAM,yBAAyB;AAAA,IAI9B,YAAY,SAA4B;AAHxC;AACA;AAGM,WAAA,OAAO,CAAC,OAAO;AACpB,WAAK,YAAY;AACjB,WAAK,OAAO,KAAK,KAAK,KAAK,IAAI;AAC/B,WAAK,UAAU,KAAK,QAAQ,KAAK,IAAI;AAAA,IACtC;AAAA,IAEA,KAAK,MAA4C;AAChD,UAAI,KAAK;AAAW,aAAK,UAAU,OAAO;AACrC,WAAA,KAAK,KAAK,IAAI;AACnB,WAAK,YAAY;AAEV,aAAA;AAAA;AAAA,QAEN,MAAM,KAAK;AAAA;AAAA,QAEX,SAAS,KAAK;AAAA,MAAA;AAAA,IAEhB;AAAA,IAEA,UAAU;AACT,aAAO,KAAK;AAAA,IACb;AAAA,EACD;AAAA,EAEA,MAAe,kBAAkB;AAAA,IAGhC,cAAc;AAFd;AAGC,WAAK,OAAO;AAAA,IACb;AAAA,IAEA,KAAK,MAA4C;AAChD,aAAO,IAAI,yBAAyB,IAAI,EAAE,KAAK,IAAI;AAAA,IACpD;AAAA,IAEA,MAAM,IAAI,QAA6D;AACtE,UAAI,KAAK,MAAM;AACP,eAAA,KAAK,KAAK,IAAI,MAAM;AAAA,MAAA,OACrB;AACE,gBAAA,MAAM,4CAA4C,MAAM;AAEhE,cAAMD,eAAc;AACpB,YAAI,CAACA;AAAmB,gBAAA,IAAI,MAAM,sBAAsB;AAExD,cAAME,aAAY;AAClB,YAAI,CAACA;AAAiB,gBAAA,IAAI,MAAM,oBAAoB;AAG7C,eAAA,eAAe,QAAQA,UAAS;AAAA,MACxC;AAAA,IACD;AAAA,EACD;AAAA,EAEA,MAAM,mCAAmC,kBAAkB;AAAA,IAC1D,MAAM,IAAI,QAA6D;AAE/D,aAAA,MAAM,IAAI,MAAM;AAAA,IACxB;AAAA,EACD;AAAA,EAEA,MAAM,+BAA+B,kBAAkB;AAAA,IACtD,MAAM,IAAI,QAA6D;AAE/D,aAAA,MAAM,IAAI,MAAM;AAAA,IACxB;AAAA,EACD;AAEA,QAAM,gBAAgB,IAAI,6BAA6B,KAAK,IAAI,uBAAwB,CAAA,EAAE;AAE1F,WAAS,cAAc,QAA2B;;AACjD,YAAO7C,MAAA,cAAc,CAAC,MAAf,gBAAAA,IAAkB,IAAI;AAAA,EAC9B;AAIA,QAAM,kBAAkB,CAAC,KAAK,KAAK,KAAK,KAAK,KAAK,GAAG;AACrD,QAAM,iBAAyD;AAAA,IAC9D,KAAK,EAAE,OAAO,aAAa,aAAa,kDAAkD,aAAa,MAAM;AAAA,IAC7G,KAAK,EAAE,OAAO,aAAa,aAAa,yCAAyC,aAAa,MAAM;AAAA,IACpG,KAAK;AAAA,MACJ,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,IACd;AAAA,IACA,KAAK;AAAA,MACJ,OAAO;AAAA,MACP,aACC;AAAA,MAED,aAAa;AAAA,IACd;AAAA,EACD;AAIO,WAAS,QAAQ,QAAiB,QAA2B,UAAU,GAAY;;AAIjF,YAAA;AAAA,MACP;AAAA,MACA;AAAA,MACA,IAAI,OAAO,MAAM;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAGG,QAAA,EAAE,kBAAkB,QAAQ;AACvB,cAAA;AAAA,QACP;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAEK,YAAA;AAAA,IACP;AAEA,UAAM2C,eAAc;AACd,UAAA,QAAQA,aAAa;AACrB,UAAA,kBAAkB,MAAM,cAAc;AACtC,UAAA9C,QAAO,OAAO,QAAQ;AAI5B,aAAS,mBAAyB;AACpB,MAAA8C,aAAA,SAAS,cAAc9C,KAAI,CAAC;AACzC,YAAMiD,eAAc;AACpB,UAAI,CAACA,cAAa;AACX,cAAA,IAAI,MAAM,4BAA4B;AAAA,MAC7C;AACAA,mBAAY,OAAO,OAAO,QAAQ,IAAI;AAChC,YAAA,iBAAiB,OAAO,KAAK,QAAQ;AAC3C,UAAI,gBAAgB;AACX,gBAAA,KAAK,0CAA0C,MAAM;AAC7D,QAAAH,aAAa,SAAS,cAAc;AAAA,MACrC;AACM,YAAA;AAAA,IACP;AAEA,QAAI,kBAAkB,YAAY,OAAO,QAAQ,SAAS;AACjD,cAAA,MAAM,+CAA+C,MAAM;AACnE,aAAO,iBAAiB;AAAA,IACzB;AAEI,QAAA,gBAAgB,SAAS9C,KAAI,GAAG;AAC3B,cAAA,MAAM,uCAAuC,MAAM;AAC3D,aAAO,iBAAiB;AAAA,IACzB;AAEA,QAAI,kBAAkB,UAAU;AAC/B,YAAM,SAA6B,OAAO,YAAUG,MAAA,OAAO,aAAP,gBAAAA,IAAiB;AACrE,UAAI,CAAC,QAAQ;AACJ,gBAAA,KAAK,6BAA6B,MAAM;AAAA,MACjD;AACA,UAAI,WAAW,UAAa,gBAAgB,SAAS,MAAM,GAAG;AAC7D,gBAAQ,KAAK,oCAAoC,QAAQ,aAAa,MAAM;AACtE,cAAA,UAAU,eAAe,MAAM;AACrC,YAAI,SAAS;AACZ,cAAI+C,wBAAiB;AACpBA,mBAAA,gBAAgB,OAAO;AAAA,UAAA,OACjB;AACE,oBAAA,MAAM,sCAAsC,MAAM,oCAAoC;AAAA,UAC/F;AAAA,QACD;AACA,cAAMD,eAAc;AACpB,YAAI,CAACA,cAAa;AACX,gBAAA,IAAI,MAAM,4BAA4B;AAAA,QAC7C;AACAA,qBAAY,OAAO,OAAO,QAAQ,IAAI;AACtC,eAAO,QAAQ,UAAU;AACR;MAClB;AAAA,IACD;AAEA,YAAQ,MAAM,oCAAoC,OAAO,QAAQ,IAAI;AAGrE,UAAM,cAAc;AACpB,QAAI,CAAC,aAAa;AACX,YAAA,IAAI,MAAM,4BAA4B;AAAA,IAC7C;AACY,gBAAA,cAAc,OAAO,QAAQ,IAAI;AACtC,WAAA;AAAA,EACR;AAIA,WAAS,KACR,QACA,OACA,UAC4B;;AACrB,YAAA9C,MAAA,qBAAA,MAAA,gBAAAA,IAAwB;AAAA,EAChC;AAGA,WAAS,MAAM,SAA4B,UAAsC;AAEjE,mBAAA,EAAG,SAAS,qBAAoB,oBAAI,QAAO,QAAS,CAAA,CAAC;AAC7D,WAAA;AAAA,EACR;AAAA,ECtuBO,MAAe,QAAkC;AAAA,IAI7C,YAAY,OAA6B;AAH1C;AAIR,WAAK,QAAQ;AAAA,IACd;AAAA,IAEA,MAAa,eACZ,gBACA,MACA,aACmB;AAGZ,aAAA,KAAK,gBAAyB,gBAAgB,MAAM,WAAW,EAAE,KAAK,CAAC,WAAW;AACxF,YAAI,kBAAkB,UAAU;AACzB,gBAAA;AAAA,QACP;AACO,eAAA;AAAA,MAAA,CACP;AAAA,IACF;AAAA,IAEQ,gBACP,gBACA,MACA,aACsC;AAGhC,YAAA,UAAU,IAAI;AAGpB,YAAM,4BAA4B,EAAE,GAAG,gBAAgB,UAAU,MAAM;AAEvE,UAAI,eAAe,WAAW;AAC7B,cAAM,kBAAkB;AAAA,UACvB,GAAG;AAAA,UACH,MAAM,eAAe,QAAQK,QAAO;AAAA,QAAA;AAKrC,cAAM,oBAAuC;AAAA,UAC5C,SAAS;AAAA,UACT,MAAM;AAAA,UACN,MAAM;AAAA,YACL,SAAS;AAAA,cACR,QAAQ;AAAA,gBACP,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,gBAClC,SAAS;AAAA,gBACT,UAAU;AAAA,gBACV;AAAA,cACD;AAAA,YACD;AAAA,UACD;AAAA,QAAA;AAED,uBAAe,mBAAmB,IAAI,EACpC,KAAK,CAAC,WAAW;AACT,kBAAA,QAAQ,OAAO,IAAe;AAAA,QAAA,CACtC,EACA,MAAM,CAAC,UAAU;AACjB,kBAAQ,OAAO,iBAAiB;AAChC,kBAAQ,OAAO,KAAK;AAAA,QAAA,CACpB;AAAA,MAAA,OACI;AACA,cAAA,eAA0C,KAAK,MAAM;AAAA,UAC1D,eAAe,yBAAyB;AAAA,QAAA;AAGnC,cAAA,4BAA4B,CAAC,aAA2C;AAC7E,cAAI,UAAU;AACL,oBAAA,QAAQ,SAAS,IAAe;AAAA,UAAA,OAClC;AACA,kBAAA,QAAQ,IAAI,SAAS;AAAA,cAC1B,SAAS;AAAA,cACT;AAAA,cACA,SAAS;AAAA,YAAA,CACT;AACD,oBAAQ,OAAO,KAAK;AAAA,UACrB;AAAA,QAAA;AASK,cAAA,eAAe,CAAC,UAAmB;AACxC,cAAI,iBAAiB,UAAU;AAC9B,kBAAM,QAAQ,UAAU;AAAA,UAAA,OAClB;AACE,oBAAA;AAAA,cACP;AAAA,cACA;AAAA,cACA;AAAA,YAAA;AAED,oBAAQ,IAAI,SAAS;AAAA,cACpB,SAAS;AAAA,cACT,YAAY;AAAA,cACZ,SAAS;AAAA,YAAA,CACT;AAAA,UACF;AACA,kBAAQ,OAAO,KAAK;AAAA,QAAA;AAGR,qBAAA,KAAK,2BAA2B,YAAY;AAAA,MAC1D;AAEO,aAAA;AAAA,IACR;AAAA;AAAA,EAGD;AC3Ha,QAAA,UAAU,CACtB,OACA,QACI;AACE,UAAA,cAAc,IAAI,IAAI,KAAK;AACjC,iBAAa,WAAW;AACxB,mBAAe,KAAK;AAEb,WAAA;AAAA,EACR;AAAA,ECVO,MAAe,wBAAgF,YAGpG;AAAA,IACS,YAAY,KAAW;AAChC,YAAM,GAAG;AAAA,IACV;AAAA,EAWD;ACTA,QAAM,0BAA0B;AAIhC,WAAS,YAAY,UAA0D;AAC9E,QAAI,CAAC,SAAS;AAAc,YAAA,IAAI,MAAM,sBAAsB;AAC5D,QAAI,CAAC,SAAS;AAAe,YAAA,IAAI,MAAM,uBAAuB;AAC9D,WAAO,EAAE,aAAa,SAAS,QAAQ,cAAc,SAAS;EAC/D;AAAA,EAKO,MAAe,mBAA2E,gBAG/F;AAAA,IAHK;AAAA;AAsBE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,+CAAoB,OAAO,iBAAyD;AAMrF,cAAA,UAAU,KAAK,eAA+B;AAAA,UACnD,aAAa;AAAA,UACb,QAAQ,WAAW;AAAA,UACnB,KAAK,KAAK;AAAA,UACV,SAAS,EAAE,SAAS,aAAa;AAAA,UACjC,cAAc;AAAA,UACd,UAAU,CAAC;AAAA,UACX,QAAQ,CAAC;AAAA;AAAA,UAET,WAAW;AAAA;AAAA,UAEX,WAAW;AAAA,QAAA,CACX;AAED,YAAI,WAAuC;AACvC,YAAA;AACH,qBAAW,MAAM;AAAA,iBACT,GAAG;AAGH,kBAAA,MAAM,yCAAyC,CAAC;AACxD,eAAK,UAAU;AACR,iBAAA;AAAA,QACR;AAEA,YAAI,CAAC,SAAS;AAAc,gBAAA,IAAI,MAAM,sBAAsB;AAErD,eAAA,EAAE,aAAa,SAAS,QAAQ,cAAc,SAAS,WAAW,KAAK,gBAAA;MAAkB;AAAA;AAAA;AAAA;AAAA;AAAA,IAMjG,YAAY;AAIX,cAAQ,MAAM,KAAK,YAAY,MAAM,gBAAgB;AAEhD,WAAA,SAAS,YAAY,KAAK,CAAC;AAChC,WAAK,YAAY;AAEjB,WAAK,SAAS,EAAE,MAAM2C,UAAAA,YAAa,CAAA;AAGnC,WAAK,SAAS,EAAE,MAAM,WAAY,CAAA;AAAA,IACnC;AAAA;AAAA;AAAA;AAAA,IAKA,MAAM,cAAc;AACb,YAAA,oBAAoB,KAAK;AAC/B,UAAI,CAAC,mBAAmB;AACjB,cAAA,IAAI,MAAM,wBAAwB;AAAA,MACzC;AAEA,cAAQ,MAAM,KAAK,YAAY,MAAM,iBAAiB;AAElD,UAAA;AACH,cAAM,SAAS,MAAM,KAAK,kBAAkB,iBAAiB;AAC7D,YAAI,CAAC,QAAQ;AACL,iBAAA;AAAA,QACR;AACA,gBAAQ,IAAI,oBAAoB;AAChC,aAAK,UAAU,MAAM;AAAA,eACb,GAAG;AAIH,gBAAA,MAAM,yCAAyC,CAAC;AACxD,aAAK,UAAU;AACT,cAAA;AAAA,MACP;AAAA,IACD;AAAA,IAEA,sBAA+B;AACxB,YAAA,cAAc,KAAK;AACzB,UAAI,CAAC,aAAa;AAEV,eAAA;AAAA,MACR;AAEM,YAAA,cAAc,KAAK,IAAA,IAAQ;AAE7B,UAAA;AAEA,UAAA;AAKU,qBAAA,UAAsB,WAAW,EAAE,OAAO;AAAA,MAAA,QAChD;AAEM,qBAAA;AAAA,MACd;AACA,YAAM,qBAAqB,aAAa;AACxC,aAAO,qBAAqB;AAAA,IAC7B;AAAA,IAEO,gBAAgB;AAChB,YAAA,cAAc,KAAK;AACzB,aAAO,UAAU,WAAW;AAAA,IAC7B;AAAA,IAEA,MAAa,cAAc;AACtB,UAAA,CAAC,KAAK,oBAAoB;AAAG;AAEjC,cAAQ,MAAM,KAAK,YAAY,MAAM,gBAAgB;AACjD,UAAA;AACH,cAAM,KAAK;eACH,GAAG;AACX,YAAI,aAAa,UAAU;AAE1B,eAAK,UAAU;AAAA,QAChB;AACO,eAAA,QAAQ,OAAO,CAAC;AAAA,MACxB;AAAA,IACD;AAAA;AAAA,IAGA,MAAa,mBAAmBpD,UAAoC,UAA4B;AAC/F,YAAM,QAAQ,KAAK,OAAO,MAAM,SAAS;AAIzC,UAAIA,SAAQ,IAAI,SAAS,iBAAiB,GAAG;AAExC,YAAA,MAAM,YAAY,YAAY;AAEjC,kBAAQ,KAAK,gCAAgC;AAAA,QAC9C;AACA,aAAK,UAAU;AACf,cAAM,IAAI,SAAS;AAAA,UAClB,SAAS;AAAA,UACT;AAAA,UACA,SAAS;AAAA,QAAA,CACT;AAAA,MACF;AACI,UAAA,MAAM,YAAY,YAAY;AACjC,cAAM,KAAK;MAAY,OACjB;AAGN,gBAAQ,MAAM,mCAAmC;AACjD,cAAM,IAAI,SAAS;AAAA,UAClB,SAAS;AAAA,UACT;AAAA,UACA,SAAS;AAAA,QAAA,CACT;AAAA,MACF;AAAA,IACD;AAAA,IAEA,MAAM,SAAS,SAAqC;AAEnD,YAAMC,SAAOQ,KAAAA;AAEb,cAAQ,MAAM,KAAK,YAAY,MAAM,iBAAiB;AAChD,YAAA,UAAU,KAAK,eAAoD;AAAA,QAAA,MACxER;AAAAA,QACA,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,KAAK;AAAA,QACV;AAAA,QACA,cAAc;AAAA,QACd,WAAW;AAAA,QACX,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT,EAAE,KAAK,WAAW;AAGnB,YAAM,UAAU;AAChB,UAAI,WAAW;AAEf,YAAM,iBAAiB,IAAI,QAAmB,CAAC,GAAG,WAAW;AAC5D,mBAAW,MAAM;AACL,qBAAA;AACN,eAAA,SAAS,gBAAgBA,MAAI,CAAC;AAC5B,iBAAA,IAAI,SAAS,EAAE,SAAS,2BAA2B,OAAO,WAAY,CAAA,CAAC;AAAA,QAAA,GAC5E,UAAU,GAAI;AAAA,MAAA,CACjB;AAED,YAAM,iBAAqC,QAAQ,KAAK,CAAC,WAAW;AACnE,YAAI,UAAU;AACN,iBAAA;AAAA,QACR;AACA,aAAK,UAAU,MAAM;AAAA,MAAA,CACrB;AAED,aAAO,QAAQ,KAAK,CAAC,gBAAgB,cAAc,CAAC;AAAA,IACrD;AAAA,EACD;AAAA,EC9OO,MAAe,uBAA+E,YAGnG;AAAA,IAGD,YAAY,KAAW,MAAqC;AAC3D,YAAM,GAAG;AAHD;AAIR,WAAK,OAAO;AAAA,IACb;AAAA,EACD;AAAA,ECNO,MAAe,wBAGZ,eAA6B;AAAA,IACtC,IAAI,UAAgD,aAAsD;AACnG,YAAA,kBAAkB,QAAQ,QAAQ;AACxC,YAAM,wBAAwB,EAAE,GAAG,iBAAiB,WAAW,YAAY;AACtE,WAAA,SAAS,YAAY,qBAAqB,CAAC;AAE1C,YAAA,UAAU,KAAK,eAAyB;AAAA,QAC7C,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK;AAAA,QACL,aAAa;AAAA,UACZ,cAAc,YAAY,SAAS;AAAA,QACpC;AAAA,QACA,SAAS;AAAA,QACT,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC,gBAAgB,UAAU;AAAA,MAAA,CACnC;AACM,aAAA,CAAC,uBAAuB,OAAO;AAAA,IACvC;AAAA,IAEA,OAAO,UAAsC,aAAsD;AAClG,YAAM,QAAQ,KAAK,OAAO,MAAM,SAAS;AACzC,YAAM,mBAAmB,mBAAmB,SAAS,UAAU,EAAE,KAAK;AAEtE,UAAI,CAAC,kBAAkB;AACtB,cAAM,IAAI,MAAM,iDAAiD,SAAS,UAAU,EAAE;AAAA,MACvF;AAEA,YAAM,qBAAuC,EAAE,GAAG,kBAAkB,GAAG,SAAS;AAC3E,WAAA,SAAS,eAAe,kBAAkB,CAAC;AAE1C,YAAA,UAAU,KAAK,eAAkC;AAAA,QACtD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,eAAe,SAAS,UAAU;AAAA,QACvC,aAAa;AAAA,UACZ,cAAc,YAAY,SAAS;AAAA,QACpC;AAAA,QACA,SAAS;AAAA,QACT,UAAU,CAAC,SAAS,UAAU;AAAA,QAC9B,QAAQ,CAAC,SAAS,UAAU;AAAA,MAAA,CAC5B;AAEM,aAAA,CAAC,oBAAoB,OAAO;AAAA,IACpC;AAAA,IAEA,OAAO,UAAoB,aAAyC;AACnE,WAAK,SAAS,eAAe,SAAS,UAAU,CAAC;AACjD,aAAO,KAAK,eAA0B;AAAA,QACrC,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,eAAe,SAAS,UAAU;AAAA;AAAA,QAEvC,aAAa;AAAA,UACZ,cAAc,YAAY,SAAS;AAAA,QACpC;AAAA,QACA,UAAU,CAAC,SAAS,UAAU;AAAA,QAC9B,QAAQ,CAAC;AAAA,MAAA,CACT;AAAA,IACF;AAAA,IAEA,MAAM,aAAa,WAAuC;AACnD,YAAA,SAAS,MAAM,KAAK,eAA2B;AAAA,QACpD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS;AAAA,QAC3B,QAAQ,CAAC;AAAA,QACT,UAAU,CAAC;AAAA,MAAA,CACX;AACI,WAAA,SAAS,qBAAqB,MAAM,CAAC;AAAA,IAC3C;AAAA,EACD;ACtFgB,WAAA,WAAc,KAAU,WAAmB;AAC1D,UAAM,SAAgB,CAAA;AACtB,QAAI,QAAQ;AACZ,UAAM,YAAY,IAAI;AAEtB,WAAO,QAAQ,WAAW;AACzB,aAAO,KAAK,IAAI,MAAM,OAAQ,SAAS,SAAU,CAAC;AAAA,IACnD;AAEO,WAAA;AAAA,EACR;AAAA,ECkBO,MAAe,qBAGZ,eAA6B;AAAA;AAAA,IAEtC,IAAI,OAAuB,aAAmD;AAC7E,UAAI,CAAC,MAAM,iBAAiB,CAAC,MAAM,YAAY;AACxC,cAAA,IAAI,MAAM,sDAAsD;AAAA,MACvE;AAEM,YAAA,eAAe,QAAQ,KAAK;AAC7B,WAAA,SAAS,SAAS,YAAY,CAAC;AAC9B,YAAA,UAAU,KAAK,eAAsB;AAAA,QAC1C,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,iBAAiB,aAAa,UAAU;AAAA,QAC7C,aAAa;AAAA,UACZ,cAAc,YAAY,SAAS;AAAA,QACpC;AAAA,QACA,SAAS,EAAE,QAAQ,CAAC,YAAY,EAAE;AAAA,QAClC,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC,aAAa,UAAU;AAAA,MAAA,CAChC;AACM,aAAA,CAAC,cAAc,OAAO;AAAA,IAC9B;AAAA,IAEA,OAAO,OAAc,aAAmD;AACvE,UAAI,CAAC,MAAM,iBAAiB,CAAC,MAAM,YAAY;AACxC,cAAA,IAAI,MAAM,sDAAsD;AAAA,MACvE;AAEA,WAAK,OAAO,MAAM,SAAS,YAAY,KAAK,CAAC;AACvC,YAAA,UAAU,KAAK,eAAsB;AAAA,QAC1C,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,WAAW,MAAM,UAAU;AAAA,QAChC,aAAa;AAAA,UACZ,cAAc,YAAY,SAAS;AAAA,QACpC;AAAA,QACA,SAAS;AAAA,QACT,UAAU,CAAC,MAAM,UAAU;AAAA,QAC3B,QAAQ,CAAC,MAAM,UAAU;AAAA,MAAA,CACzB;AACM,aAAA,CAAC,OAAO,OAAO;AAAA,IACvB;AAAA,IACA,MAAM,OAAO,SAAqC;AAC3C,YAAA,EAAE,MAAM,IAAI,KAAK;AACjB,YAAA,QAAQ,MAAM;AACpB,YAAM,mBAAmB,gBAAgB,OAAO,EAAE,KAAK;AAEvD,UAAI,CAAC;AAAkB,cAAM,IAAI,MAAM,oBAAoB,OAAO,qBAAqB;AAEvF,YAAM,sBAAsB,yBAAyB,OAAO,EAAE,KAAK;AACnE,YAAM,0BAA0B,6BAA6B,OAAO,EAAE,KAAK;AAC3E,YAAM,oBAAoB,+BAA+B,OAAO,EAAE,KAAK;AAElE,WAAA,SAAS,YAAY,OAAO,CAAC;AAG9B,UAAA,oBAAoB,SAAS,GAAG;AACnC,cAAM,wBAAwB,oBAAoB,IAAI,CAAC,EAAE,WAAA,MAAiB,UAAU;AAC/E,aAAA,SAAS,uBAAuB,qBAAqB,CAAC;AAAA,MAC5D;AAGI,UAAA,wBAAwB,SAAS,GAAG;AACvC,cAAM,4BAA4B,wBAAwB,IAAI,CAAC,EAAE,WAAA,MAAiB,UAAU;AACvF,aAAA,SAAS,sBAAsB,yBAAyB,CAAC;AAAA,MAC/D;AAEI,UAAA,kBAAkB,SAAS,GAAG;AACjC,cAAM,uBAAuB,kBAAkB,IAAI,CAAC,EAAE,WAAA,MAAiB,UAAU;AAC5E,aAAA,SAAS,wBAAwB,oBAAoB,CAAC;AAAA,MAC5D;AAEA,aAAO,KAAK,eAA0B;AAAA,QACrC,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,WAAW,OAAO;AAAA,QACvB,UAAU,CAAC,OAAO;AAAA,QAClB,QAAQ,CAAC;AAAA,MAAA,CACT,EAAE,MAAM,CAAC,QAAQ;AACZ,aAAA,SAAS,SAAS,gBAAgB,CAAC;AACnC,aAAA,SAAS,oBAAoB,mBAAmB,CAAC;AACjD,aAAA,SAAS,mBAAmB,uBAAuB,CAAC;AACpD,aAAA,SAAS,qBAAqB,iBAAiB,CAAC;AAC/C,cAAA;AAAA,MAAA,CACN;AAAA,IACF;AAAA,IACA,MAAM,2BAA2B,aAAyC;AACnE,YAAA,EAAE,MAAM,IAAI,KAAK;AACjB,YAAA,QAA0B,MAAM;AAEtC,YAAM,uBAAuB,wBAAwB,WAAW,EAAE,KAAK,KAAK,CAAA;AAC5E,YAAM,0BAA0B,qBAAqB,IAAI,CAAC,MAAM,EAAE,UAAU;AAC5E,YAAM,qBAAqB,CAAC,aAAa,GAAG,uBAAuB;AAE7D,YAAA,SAAS,aAAa,uBAAuB,CAAC;AAEpD,aAAO,KAAK,eAA0B;AAAA,QACrC,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,iBAAiB,WAAW;AAAA,QACjC,UAAU;AAAA,QACV,QAAQ;AAAA,MAAA,CACR,EAAE,MAAM,CAAC,QAAQ;AAEX,cAAA,SAAS,UAAU,oBAAoB,CAAC;AACxC,cAAA;AAAA,MAAA,CACN;AAAA,IACF;AAAA;AAAA,IAGA,QACC,gBACA,aACA,aAEA,WAC8B;AACxB,YAAA,EAAE,MAAM,IAAI,KAAK;AAcvB,YAAM,eAAc,oBAAI,KAAK,GAAE,YAAY;AAC3C,YAAM,gBAAgBQ,KAAAA;AAEtB,YAAM,eAAoC,WAAW,gBAAgB,SAAS,EAAE,IAAI,CAAC,eAAe;AACnG,cAAM,gBAAoC,WAAW,IAAI,CAAC,iBAAiB;AAC1E,iBAAO,QAAQ;AAAA,YACd,GAAG;AAAA,YACH,cAAc;AAAA,UAAA,CACd;AAAA,QAAA,CACD;AAEM,eAAA;AAAA,UACN,SAASA,KAAAA,GAAO;AAAA,UAChB,SAAS;AAAA,YACR,gBAAgB;AAAA,YAChB,QAAQ;AAAA,UACT;AAAA,QAAA;AAAA,MACD,CACA;AAED,YAAM,gBAA6C,CAAA;AACnD,UAAI,cAA6B;AAEjC,iBAAW,cAAc,cAAc;AAChC,cAAA,EAAE,SAAS,QAAY,IAAA;AAE7B,cAAM,uBAAuB,QAAQ,OAAO,IAAI,CAAC,MAAM,EAAE,UAAU;AAE7D,cAAA,WAAW,CAAC,WAAW;AACzB,YAAA;AAAa,mBAAS,KAAK,WAAW;AAE1C,cAAM4C,UAAS;AACf,QAAAA,QAAO,KAAK,OAAO;AAEb,cAAA,UAAU,KAAK,eAAiC;AAAA,UACrD,aAAa;AAAA,UACb,QAAQ,WAAW;AAAA,UACnB,KAAK,iBAAiB,WAAW;AAAA,UACjC,aAAa;AAAA,YACZ,cAAc,YAAY,SAAS;AAAA,UACpC;AAAA,UACA;AAAA,UACA;AAAA,UACA,QAAAA;AAAA,QAAA,CACA;AAED,sBAAc,WAAW;AAEzB,sBAAc,KAAK,OAAO;AAAA,MAC3B;AAEA,WAAK,QAAQ,IAAI,aAAa,EAAE,KAAK,CAAC,WAAW;AAC1C,cAAA,mBAAmB,OAAO;AAC1B,cAAA,SAAS,UAAU,gBAAgB,CAAC;AAAA,MAAA,CAC1C;AAEM,aAAA;AAAA,IACR;AAAA,IAEA,MAAM,aAAa,WAAkC;AAC9C,YAAA,SAAS,MAAM,KAAK,eAAwB;AAAA,QACjD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS;AAAA,QAC3B,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AACI,WAAA,SAAS,iBAAiB,MAAM,CAAC;AAAA,IACvC;AAAA,EACD;AAAA,EC/NO,MAAe,oCAGZ,eAA6B;AAAA,IACtC,IAAI,SAAiB,SAA8D;;AAC5E,YAAA,EAAE,MAAM,IAAI,KAAK;AACvB,YAAM,eAAcjD,MAAA,gBAAgB,OAAO,EAAE,MAAM,SAAA,CAAU,MAAzC,gBAAAA,IAA4C;AAEhE,UAAI,CAAC,aAAa;AACjB,cAAM,IAAI,MAAM,yBAAyB,OAAO,YAAY;AAAA,MAC7D;AAEA,YAAM,yBAAyB,QAAQ;AAAA,QACtC,OAAO;AAAA,QACP,OAAO;AAAA,MAAA,CACP;AAEI,WAAA,SAAS,mBAAmB,sBAAsB,CAAC;AAElD,YAAA,UAAU,KAAK,eAA8C;AAAA,QAClE,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,iBAAiB,WAAW;AAAA;AAAA,QAEjC,SAAS,EAAE,aAAa,CAAC,EAAE,GAAG,wBAAwB,eAAc,oBAAI,QAAO,YAAY,IAAM,CAAA,EAAE;AAAA,QACnG,UAAU,CAAC,SAAS,OAAO;AAAA,QAC3B,QAAQ,CAAC,uBAAuB,UAAU;AAAA,MAAA,CAC1C;AAEM,aAAA,CAAC,wBAAwB,OAAO;AAAA,IACxC;AAAA,IACA,MAAM,aAAa,WAAkC;AAC9C,YAAA,SAAS,MAAM,KAAK,eAAuC;AAAA,QAChE,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS;AAAA,QAC3B,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AACI,WAAA,SAAS,oBAAoB,MAAM,CAAC;AAAA,IAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASA,MAAM,QAAQ,aAAqB,kBAAmD;AACrF,YAAM,0BAA0B,iBAAiB,IAAI,CAAC,eAAe;AACpE,eAAO,QAAQ,UAAU;AAAA,MAAA,CACzB;AACD,YAAM,YAAoC,CAAA;AAC1C,iBAAW,cAAc,kBAAkB;AAC1C,cAAM,+BAA+B,UAAU,WAAW,KAAK,KAAK,CAAA;AACpE,qCAA6B,WAAW,KAAK,KAAQ,oBAAA,KAAA,GAAO;AAClD,kBAAA,WAAW,KAAK,IAAI;AAAA,MAC/B;AACK,WAAA,SAAS,oBAAoB,SAAS,CAAC;AAC5C,YAAM,KAAK,eAA0B;AAAA,QACpC,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,iBAAiB,WAAW;AAAA,QACjC,SAAS;AAAA,UACR,aAAa;AAAA,QACd;AAAA,QACA,UAAU,CAAC,aAAa,GAAG,iBAAiB,IAAI,CAAC,MAAM,EAAE,KAAK,GAAG,GAAG,iBAAiB,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AAAA,QACxG,QAAQ,wBAAwB,IAAI,CAAC,MAAM,EAAE,UAAU;AAAA,MAAA,CACvD;AAAA,IACF;AAAA,IACA,WAAW,SAAiB,UAAwC;AACnE,YAAM,2BAAmD,SAAS,IAAI,CAAC,YAAY;AAC3E,eAAA;AAAA,UACN,OAAO;AAAA,UACP,OAAO;AAAA,QAAA;AAAA,MACR,CACA;AACI,WAAA,SAAS,uBAAuB,wBAAwB,CAAC;AAC9D,aAAO,KAAK,eAA0B;AAAA,QACrC,aAAa,kBAAkB,SAAS,MAAM;AAAA;AAAA,QAE9C,QAAQ,WAAW;AAAA,QACnB,KAAK,kBAAkB,OAAO;AAAA,QAC9B,SAAS;AAAA,UACR,QAAQ;AAAA,QACT;AAAA,QACA,UAAU,CAAC,SAAS,GAAG,QAAQ;AAAA,QAC/B,QAAQ,CAAC;AAAA,MAAA,CACT;AAAA,IACF;AAAA,EACD;AAAA,ECpFO,MAAe,0BAGZ,eAA6B;AAAA,IACtC,MAAM,iBACL,gBACA,aACA,aACwB;AACxB,YAAM,UAA+B,eAAe,IAAI,CAAC,UAAU;AAClE,eAAO,QAAQ,KAAK;AAAA,MAAA,CACpB;AACD,YAAM,aAA2B,QAAQ,IAAI,CAAC,UAAU;AACvD,eAAO,EAAE,GAAG,OAAO,YAAY,YAAY;AAAA,MAAA,CAC3C;AACI,WAAA,SAAS,UAAU,UAAU,CAAC;AACnC,aAAO,KAAK,eAA6B;AAAA,QACxC,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,iBAAiB,WAAW;AAAA,QACjC,SAAS;AAAA,UACR,QAAQ;AAAA,QACT;AAAA,QACA,aAAa;AAAA,UACZ,cAAc,YAAY,SAAS;AAAA,QACpC;AAAA,QACA,UAAU,CAAC,aAAa,WAAW;AAAA,QACnC,QAAQ,QAAQ,IAAI,CAAC,EAAE,WAAA,MAAiB,UAAU;AAAA,MAAA,CAClD;AAAA,IACF;AAAA,IAEA,MAAM,iBAAiB,gBAA8B,aAA4C;AAC1F,YAAA,QAAQ,KAAK,OAAO;AACpB,YAAA,QAAQ,MAAM;AACd,YAAA,aAAa,uBAAuB,eAAe,IAAI,CAAC,EAAE,WAAA,MAAiB,UAAU,CAAC,EAAE,KAAK;AAE9F,WAAA,SAAS,aAAa,cAAc,CAAC;AAE1C,aAAO,KAAK,eAA6B;AAAA,QACxC,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,iBAAiB,WAAW;AAAA,QACjC,SAAS;AAAA,UACR,QAAQ;AAAA,QACT;AAAA,QACA,UAAU,CAAC,WAAW;AAAA,QACtB,QAAQ,eAAe,IAAI,CAAC,EAAE,WAAA,MAAiB,UAAU;AAAA,MAAA,CACzD,EAAE,MAAM,CAAC,MAAM;AAET,cAAA,SAAS,aAAa,UAAU,CAAC;AACjC,cAAA;AAAA,MAAA,CACN;AAAA,IACF;AAAA,IAEA,MAAM,WAAW,aAA2C;AACtD,WAAA,SAAS,aAAa,WAAW,CAAC;AACvC,aAAO,KAAK,eAAe;AAAA,QAC1B,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK;AAAA,QACL,SAAS;AAAA,UACR,WAAW;AAAA,QACZ;AAAA,QACA,UAAU;AAAA,QACV,QAAQ,CAAC;AAAA,MAAA,CACT;AAAA,IACF;AAAA,IAEA,MAAM,OAAO,YAA4C;AACxD,WAAK,SAAS,UAAU,CAAC,UAAU,CAAC,CAAC;AACrC,aAAO,KAAK,eAAe;AAAA,QAC1B,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,kBAAkB,WAAW,UAAU;AAAA,QAC5C,SAAS;AAAA,QACT,UAAU,CAAC,WAAW,UAAU;AAAA,QAChC,QAAQ,CAAC,WAAW,UAAU;AAAA,MAAA,CAC9B;AAAA,IACF;AAAA,IAEA,MAAM,SAAS,SAAiB,QAAoC;AAC7D,YAAA,EAAE,MAAM,IAAI,KAAK;AAEvB,YAAM,QAAQ,MAAM,SAAA,EAAW,kBAAkB,UAAU,OAAO;AAElE,UAAI,CAAC,OAAO;AACX,cAAM,IAAI,MAAM,0BAA0B,OAAO,qBAAqB;AAAA,MACvE;AAEK,WAAA,SAAS,YAAY,EAAE,GAAG,OAAO,MAAM,OAAQ,CAAA,CAAC;AACjD,UAAA;AACH,cAAM,KAAK,eAAe;AAAA,UACzB,aAAa;AAAA,UACb,QAAQ,WAAW;AAAA,UACnB,KAAK,kBAAkB,OAAO;AAAA,UAC9B,SAAS,EAAE,MAAM,OAAO;AAAA,UACxB,UAAU,CAAC,SAAS,MAAM;AAAA,UAC1B,QAAQ,CAAC,OAAO;AAAA,QAAA,CAChB;AAAA,eACO,GAAG;AACN,aAAA,SAAS,SAAS,KAAK,CAAC;AACvB,cAAA;AAAA,MACP;AAAA,IACD;AAAA,IAEA,MAAM,WAAW,SAAiB,QAAoC;AAC/D,YAAA,EAAE,MAAM,IAAI,KAAK;AAEvB,YAAM,QAAQ,MAAM,SAAA,EAAW,kBAAkB,UAAU,OAAO;AAElE,UAAI,CAAC,OAAO;AACX,cAAM,IAAI,MAAM,0BAA0B,OAAO,qBAAqB;AAAA,MACvE;AAEK,WAAA,SAAS,YAAY,EAAE,GAAG,OAAO,MAAM,OAAW,CAAA,CAAC;AAEpD,UAAA;AACH,cAAM,KAAK,eAAe;AAAA,UACzB,aAAa;AAAA,UACb,QAAQ,WAAW;AAAA,UACnB,KAAK,kBAAkB,OAAO;AAAA,UAC9B,UAAU,CAAC,SAAS,MAAM;AAAA,UAC1B,QAAQ,CAAC,OAAO;AAAA,QAAA,CAChB;AAAA,eACO,GAAG;AACN,aAAA,SAAS,SAAS,KAAK,CAAC;AACvB,cAAA;AAAA,MACP;AAAA,IACD;AAAA,IAEA,MAAM,aAAa,WAAuC;AACnD,YAAA,SAAS,MAAM,KAAK,eAA6B;AAAA,QACtD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS;AAAA,QAC3B,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AACI,WAAA,SAAS,iBAAiB,MAAM,CAAC;AAAA,IACvC;AAAA,EACD;AAAA,ECrJO,MAAe,0BAGZ,eAA6B;AAAA,IAC5B,+BAA+B,MAAc;AAChD,YAAA;AAAA,QACL,wBAAAkD;AAAA,QACA,wBAAAC;AAAA,QACA,4BAAAC;AAAA,QACA,2BAAAC;AAAA,QACA,0BAAAC;AAAA,QACA,+BAAAC;AAAA,QACA,iCAAAC;AAAA,QACA,iBAAAC;AAAA,MACG,IAAA,KAAK,OAAO,MAAM,SAAS;AAIzB,YAAA,kBAA4C,CAAA,EAA+B;AAAA,QAChF,OAAO,OAAOP,wBAAuB,SAAS;AAAA,QAC9C,OAAO,OAAOC,wBAAuB,SAAS;AAAA,QAC9C,OAAO,OAAOC,4BAA2B,SAAS;AAAA,QAClD,OAAO,OAAOC,2BAA0B,SAAS;AAAA,QACjD,OAAO,OAAOC,0BAAyB,SAAS;AAAA,QAChD,OAAO,OAAOC,+BAA8B,SAAS;AAAA,QACrD,OAAO,OAAOC,iCAAgC,SAAS;AAAA,QACvD,OAAO,OAAOC,iBAAgB,SAAS;AAAA,MAAA;AAGxC,aAAO,gBAAgB,OAAO,CAAC,WAAW,OAAO,cAAc,IAAI,EAAE;AAAA,IACtE;AAAA,IAEU,qBAAqB,eAAsC;AACpE,iBAAW,CAAC,MAAM,YAAY,KAAK,OAAO,QAAQ,aAAa,GAAG;AACjE,aAAK,KAAK,eAA0B;AAAA,UACnC,KAAK,aAAa;AAAA,UAClB,aAAa;AAAA,UACb,QAAQ,WAAW;AAAA,UACnB,eAAe;AAAA,UACf,cAAc;AAAA,UACd,gBAAgB;AAAA;AAAA,UAEhB,UAAU,CAAC,MAAM,aAAa,OAAO,GAAG,EAAE;AAAA,UAC1C,QAAQ,CAAC,IAAI;AAAA,UACb,OAAO;AAAA,QAAA,CACc;AAAA,MACvB;AAAA,IACD;AAAA,EACD;ACZA,QAAM,sBAGF;AAAA,IACH,CAAC,gBAAgB,KAAK,GAAG;AAAA,MACxB,MAAM;AAAA,MACN,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,IAClB;AAAA,IACA,CAAC,gBAAgB,KAAK,GAAG;AAAA,MACxB,MAAM;AAAA,MACN,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,IAClB;AAAA,IACA,CAAC,gBAAgB,SAAS,GAAG;AAAA,MAC5B,MAAM;AAAA,MACN,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,IAClB;AAAA,IACA,CAAC,gBAAgB,OAAO,GAAG;AAAA,MAC1B,MAAM;AAAA,MACN,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,IAClB;AAAA,IACA,CAAC,gBAAgB,QAAQ,GAAG;AAAA,MAC3B,MAAM;AAAA,MACN,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,IAClB;AAAA,EACD;AAAA,EAEO,MAAe,8BAKZ,kBAAgC;AAAA,IAczC,MAAgB,YACf,OACA,SACA,wBACsD;AAChD,YAAA,EAAE,MAAM,IAAI,KAAK;AAEvB,YAAM,cAAc,MAAM,SAAS,EAAE,YAAY;AACjD,YAAM,eAAc,oBAAI,KAAK,GAAE,YAAY;AAE3C,YAAM,qBAA4C,CAAA;AAClD,YAAM,qBAA0C,CAAA;AAChD,YAAM,eAAyD,CAAA;AAE/D,iBAAW,QAAQ,OAAO;AAEnB,cAAA,OAAO,MAAM,SAAS,IAAI;AAG5B,YAAA,EAAE,QAAQ,eAAe;AAC5B,uBAAa,IAAI,IAAI;AAAA,YACpB;AAAA,YACA,WAAW,KAAK;AAAA,YAChB,WAAW,KAAK,KAAK,MAAM,GAAG,EAAE,IAAI;AAAA,YACpC,MAAM,KAAK;AAAA,UAAA;AAEZ,gBAAM,KAAK,OAAO,MAAM,SAAS,MAAM,IAAI;AAAA,QAC5C;AAGA,cAAM,oBAAoB,uBAAuB;AAAA,UAChD;AAAA,UACA;AAAA,UACA;AAAA,UACA,WAAW,YAAY;AAAA,UACvB,aAAa;AAAA,UACb;AAAA,QAAA,CACA;AACD,2BAAmB,KAAK,iBAAiB;AAGzC,2BAAmB,KAAK;AAAA,UACvB,YAAY,kBAAkB;AAAA,UAC9B,MAAM,kBAAkB;AAAA,UACxB,MAAM,kBAAkB;AAAA,UACxB,aAAa,kBAAkB;AAAA,QAAA,CAC/B;AAAA,MACF;AAEA,WAAK,SAAS,KAAK,eAAe,kBAAkB,CAAC;AAE/C,YAAA,OAAO,oBAAoB,KAAK,eAAe;AAE/C,YAAA,UAAU,KAAK,eAGlB;AAAA,QACF,aAAa,mBAAmB,KAAK,IAAI;AAAA,QACzC,QAAQ,WAAW;AAAA,QACnB,KAAK,GAAG,KAAK,eAAe,IAAI,OAAO;AAAA,QACvC,SAAS;AAAA,UACR,cAAc;AAAA,UACd,aAAa;AAAA,UACb,OAAO,OAAO,OAAO,YAAY;AAAA,QAClC;AAAA,QACA,QAAQ,mBAAmB,IAAI,CAAC,eAAe,WAAW,UAAU;AAAA,QACpE,UAAU,mBAAmB,IAAI,CAAC,eAAe,WAAW,SAAS;AAAA,MAAA,CACrE;AAED,cACE,KAAK,CAAC,EAAE,aAAa,qBAAqB;AAC1C,aAAK,SAAS,KAAK,kBAAkB,WAAW,CAAC;AACjD,aAAK,qBAAqB,cAAc;AAAA,MAAA,CACxC,EACA,MAAM,MAAM;AACP,aAAA,SAAS,KAAK,kBAAkB,mBAAmB,IAAI,CAAC,eAAe,WAAW,UAAU,CAAC,CAAC;AAAA,MAAA,CACnG;AAEK,aAAA,CAAC,oBAAoB,QAAQ,KAAK,CAAC,EAAE,YAAkB,MAAA,WAAW,CAAC;AAAA,IAC3E;AAAA,IAEA,MAAgB,iBAAiB,cAAqC;AAC/D,YAAA,EAAE,MAAM,IAAI,KAAK;AACvB,YAAM,aAAa,KAAK,iBAAiB,YAAY,EAAE,MAAM,UAAU;AAEvE,UAAI,CAAC,YAAY;AAChB,cAAM,IAAI;AAAA,UACT,mDAAmD,YAAY;AAAA,QAAA;AAAA,MAEjE;AAEA,WAAK,SAAS,KAAK,iBAAiB,WAAW,UAAU,CAAC;AAEpD,YAAA,OAAO,oBAAoB,KAAK,eAAe;AAE/C,YAAA,UAAU,KAAK,eAA0B;AAAA,QAC9C,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,GAAG,KAAK,eAAe,gBAAgB,YAAY;AAAA,QACxD,UAAU,CAAC,YAAY;AAAA,QACvB,QAAQ,CAAC;AAAA,MAAA,CACT;AAED,cACE,KAAK,MAAM;AACX,YAAI,KAAK,+BAA+B,WAAW,SAAS,MAAM,GAAG;AACpE,eAAK,KAAK,OAAO,MAAM,YAAY,WAAW,SAAS;AAAA,QACxD;AAAA,MAAA,CACA,EACA,MAAM,MAAM;AACZ,aAAK,SAAS,KAAK,cAAc,UAAU,CAAC;AAAA,MAAA,CAC5C;AAEK,aAAA;AAAA,IACR;AAAA;AAAA;AAAA,IAIA,MAAM,aAAa,WAAmB,iBAAyC;AACxE,YAAA,OAAO,oBAAoB,KAAK,eAAe;AAE/C,YAAA,SAAS,MAAM,KAAK,eAAuC;AAAA,QAChE,aAAa,OAAO,KAAK,IAAI;AAAA,QAC7B,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS,GAAG,KAAK,eAAe;AAAA,QAClD,QAAQ,CAAC;AAAA,QACT,UAAU,CAAC;AAAA,MAAA,CACX;AAED,WAAK,SAAS,KAAK,sBAAsB,MAAM,CAAC;AAAA,IACjD;AAAA,EACD;AAAA,ECrNO,MAAe,+BAGZ,sBAA6D;AAAA,IAHhE;AAAA;AAIN,6CAAkB,gBAAgB;AAElC,mDAAwB;AACxB,4CAAiB;AACjB,+CAAoB;AACpB,+CAAoB;AACpB,8CAAmB;AACnB,2CAAgB;AAEhB,8CAAmB;AAAA;AAAA,IAEX,uBAAuB,MAA0C;AACxE,aAAO,QAAQ;AAAA,QACd,MAAM,IAAI,gBAAgB,KAAK,IAAI;AAAA,QACnC,WAAW,KAAK;AAAA,QAChB,YAAY,KAAK;AAAA,QACjB,WAAW,KAAK,KAAK;AAAA,QACrB,WAAW,KAAK,KAAK;AAAA,QACrB,cAAc,KAAK;AAAA,QACnB,aAAa,KAAK;AAAA,QAClB,OAAO,KAAK;AAAA,MAAA,CACZ;AAAA,IACF;AAAA,IAEA,MAAM,mBAAmB,OAAe,SAA0E;AAC1G,aAAA,KAAK,YAAY,OAAO,SAAS,KAAK,uBAAuB,KAAK,IAAI,CAAC;AAAA,IAC/E;AAAA,IAEA,MAAM,sBAAsB,cAAqC;AACzD,aAAA,KAAK,iBAAiB,YAAY;AAAA,IAC1C;AAAA,EACD;AAAA,EC/BO,MAAe,yBAGZ,eAA6B;AAAA,IACtC,IAAI,WAAiE;AAC9D,YAAA,mBAAmB,QAAQ,SAAS;AACpC,YAAA,EAAE,MAAM,IAAI,KAAK;AACvB,YAAM,kBAAkB,MAAM,SAAS,EAAE,eAAe;AAEnD,WAAA,SAAS,aAAa,gBAAgB,CAAC;AACtC,YAAA,UAAU,KAAK,eAA0B;AAAA,QAC9C,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,eAAe;AAAA,QACjC,SAAS,EAAE,GAAG,iBAAiB;AAAA,QAC/B,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC,iBAAiB,UAAU;AAAA,MAAA,CACpC;AACM,aAAA,CAAC,kBAAkB,OAAO;AAAA,IAClC;AAAA,IAEA,OAAO,WAA0C;AAC3C,WAAA,SAAS,aAAa,SAAS,CAAC;AACrC,aAAO,KAAK,eAAe;AAAA,QAC1B,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,iBAAiB,UAAU,UAAU;AAAA,QAC1C,SAAS;AAAA,QACT,UAAU,CAAC,UAAU,UAAU;AAAA,QAC/B,QAAQ,CAAC,UAAU,UAAU;AAAA,MAAA,CAC7B;AAAA,IACF;AAAA,IAEA,MAAM,OAAO,aAAyC;AAC/C,YAAA,EAAE,MAAM,IAAI,KAAK;AACjB,YAAA,QAAQ,MAAM;AAEpB,YAAM,YAAY,oBAAoB,WAAW,EAAE,KAAK;AACxD,UAAI,CAAC,WAAW;AACf,cAAM,IAAI,MAAM,uCAAuC,WAAW,WAAW;AAAA,MAC9E;AACA,YAAM,oBAAoB,wBAAwB,WAAW,EAAE,KAAK,KAAK,CAAA;AACzE,YAAM,yBAAyB,6BAA6B,WAAW,EAAE,KAAK;AAEzE,WAAA,SAAS,gBAAgB,WAAW,CAAC;AAGtC,UAAA,kBAAkB,SAAS,GAAG;AACjC,cAAM,uBAAuB,kBAAkB,IAAI,CAAC,eAA2B,WAAW,UAAU;AAC/F,aAAA,SAAS,aAAa,oBAAoB,CAAC;AAAA,MACjD;AAGI,UAAA,uBAAuB,SAAS,GAAG;AAEtC,cAAM,4BAA4B,uBAAuB,IAAI,CAAC,EAAE,WAAA,MAAiB,UAAU;AACtF,aAAA,SAAS,2BAA2B,yBAAyB,CAAC;AAAA,MACpE;AAEA,aAAO,KAAK,eAA0B;AAAA,QACrC,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,iBAAiB,WAAW;AAAA,QACjC,UAAU,CAAC,WAAW;AAAA,QACtB,QAAQ,CAAC;AAAA,MAAA,CACT,EAAE,MAAM,CAAC,MAAM;AACV,aAAA,SAAS,aAAa,SAAS,CAAC;AAChC,aAAA,SAAS,UAAU,iBAAiB,CAAC;AACrC,aAAA,SAAS,wBAAwB,sBAAsB,CAAC;AACvD,cAAA;AAAA,MAAA,CACN;AAAA,IACF;AAAA,IAEA,MAAM,aAAa,WAAkC;AAC9C,YAAA,SAAS,MAAM,KAAK,eAA4B;AAAA,QACrD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS;AAAA,QAC3B,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AACI,WAAA,SAAS,qBAAqB,MAAM,CAAC;AAAA,IAC3C;AAAA,EACD;AAAA,ECvFO,MAAe,mCAGZ,sBAAiE;AAAA,IAHpE;AAAA;AAIN,6CAAkB,gBAAgB;AAElC,mDAAwB;AACxB,4CAAiB;AACjB,+CAAoB;AACpB,+CAAoB;AACpB,8CAAmB;AACnB,2CAAgB;AAEhB,8CAAmB;AAAA;AAAA,IAEX,uBAAuB,MAA0C;AACxE,aAAO,QAAQ;AAAA,QACd,MAAM,IAAI,gBAAgB,KAAK,IAAI;AAAA,QACnC,WAAW,KAAK;AAAA,QAChB,YAAY,KAAK;AAAA,QACjB,WAAW,KAAK,KAAK;AAAA,QACrB,WAAW,KAAK,KAAK;AAAA,QACrB,cAAc,KAAK;AAAA,QACnB,aAAa,KAAK;AAAA,QAClB,YAAY,KAAK;AAAA,MAAA,CACjB;AAAA,IACF;AAAA,IAEA,MAAM,uBACL,OACA,aAC8D;AACvD,aAAA,KAAK,YAAY,OAAO,aAAa,KAAK,uBAAuB,KAAK,IAAI,CAAC;AAAA,IACnF;AAAA,IAEA,MAAM,0BAA0B,cAAqC;AAC7D,aAAA,KAAK,iBAAiB,YAAY;AAAA,IAC1C;AAAA,EACD;AAAA,EC7CO,MAAe,4BAGZ,eAA6B;AAAA;AAAA,IAEtC,IAAI,SAAsG;AACnG,YAAA,EAAE,MAAM,IAAI,KAAK;AAEvB,YAAM,iBAA0C,QAAQ;AAAA,QACvD,GAAG;AAAA,QACH,QAAQ,MAAM,SAAS,EAAE,YAAY,YAAY;AAAA,QACjD,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,MAAA,CACrC;AAEI,WAAA,SAAS,gBAAgB,cAAc,CAAC;AAEvC,YAAA,UAAU,KAAK,eAAsC;AAAA,QAC1D,aAAa,GAAG,SAAS,QAAQ,SAAS,EAAE,CAAC;AAAA,QAC7C,QAAQ,WAAW;AAAA,QACnB,KAAK,WAAW,QAAQ,KAAK;AAAA,QAC7B,SAAS;AAAA,QACT,UAAU,CAAC,QAAQ,KAAK;AAAA,QACxB,QAAQ,CAAC,eAAe,UAAU;AAAA,MAAA,CAClC;AAED,cAAQ,MAAM,MAAM;AACnB,aAAK,SAAS,mBAAmB,eAAe,UAAU,CAAC;AAAA,MAAA,CAC3D;AAEM,aAAA,CAAC,gBAAgB,OAAO;AAAA,IAChC;AAAA,IAEA,OAAO,SAAuE;AACvE,YAAA,EAAE,MAAM,IAAI,KAAK;AAEvB,YAAM,kBAAkB,MAAM,WAAW,oBAAoB,UAAU,QAAQ,UAAU;AACzF,UAAI,CAAC,iBAAiB;AACrB,cAAM,IAAI,MAAM,2BAA2B,QAAQ,UAAU,qBAAqB;AAAA,MACnF;AAEK,WAAA,SAAS,gBAAgB,OAAO,CAAC;AAEhC,YAAA,UAAU,KAAK,eAAsC;AAAA,QAC1D,aAAa,iBAAiB,SAAS,QAAQ,SAAS,EAAE,CAAC;AAAA,QAC3D,QAAQ,WAAW;AAAA,QACnB,KAAK,oBAAoB,QAAQ,UAAU;AAAA,QAC3C,SAAS;AAAA,QACT,UAAU,CAAC,QAAQ,KAAK;AAAA,QACxB,QAAQ,CAAC,QAAQ,UAAU;AAAA,MAAA,CAC3B;AAED,cAAQ,MAAM,MAAM;AACd,aAAA,SAAS,gBAAgB,eAAe,CAAC;AAAA,MAAA,CAC9C;AAEM,aAAA,CAAC,SAAS,OAAO;AAAA,IACzB;AAAA,IAEA,OAAO,YAAwC;AACxC,YAAA,kBAAkB,KAAK,OAAO,MAAM,WAAW,oBAAoB,UAAU,UAAU;AAC7F,UAAI,CAAC,iBAAiB;AACrB,cAAM,IAAI,MAAM,2BAA2B,UAAU,qBAAqB;AAAA,MAC3E;AAEK,WAAA,SAAS,mBAAmB,UAAU,CAAC;AAEtC,YAAA,UAAU,KAAK,eAA0B;AAAA,QAC9C,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,oBAAoB,UAAU;AAAA,QACnC,UAAU,CAAC,UAAU;AAAA,QACrB,QAAQ,CAAC;AAAA,MAAA,CACT;AAED,cAAQ,MAAM,MAAM;AACd,aAAA,SAAS,gBAAgB,eAAe,CAAC;AAAA,MAAA,CAC9C;AAEM,aAAA;AAAA,IACR;AAAA,IAEA,MAAM,aAAa,WAAkC;AAC9C,YAAA,SAAS,MAAM,KAAK,eAAwC;AAAA,QACjE,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS;AAAA,QAC3B,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AACI,WAAA,SAAS,iBAAiB,MAAM,CAAC;AAAA,IACvC;AAAA,EACD;AAAA,EC5FO,MAAe,2BAGZ,eAA6B;AAAA,IACtC,MAAM,aAAa,WAAkC;AAC9C,YAAA,SAAS,MAAM,KAAK,eAAuC;AAAA,QAChE,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS;AAAA,QAC3B,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AAEG,UAAA,iBAAiB,OAAO,OAAO,oBAAoB;AACtC,uBAAA,eAAe,IAAI,CAAC,YAAY;AACzC,eAAA,EAAE,GAAG;MAAQ,CACpB;AACG,UAAA,OAAO,WAAW,eAAe,QAAQ;AACpC,gBAAA;AAAA,UACP,wDAAwD,eAAe,MAAM;AAAA,QAAA;AAAA,MAE/E;AACK,WAAA,SAAS,uBAAuB,cAAc,CAAC;AAAA,IACrD;AAAA,EACD;AAAA,EChBO,MAAe,+BAGZ,sBAA6D;AAAA,IAHhE;AAAA;AAIN,6CAAkB,gBAAgB;AAElC,mDAAwB;AACxB,4CAAiB;AACjB,+CAAoB;AACpB,+CAAoB;AACpB,8CAAmB;AACnB,2CAAgB;AAEhB,8CAAmB;AAAA;AAAA,IAEX,uBAAuB,MAA0C;AACxE,aAAO,QAAQ;AAAA,QACd,MAAM,IAAI,gBAAgB,KAAK,IAAI;AAAA,QACnC,WAAW,KAAK;AAAA,QAChB,YAAY,KAAK;AAAA,QACjB,WAAW,KAAK,KAAK;AAAA,QACrB,WAAW,KAAK,KAAK;AAAA,QACrB,cAAc,KAAK;AAAA,QACnB,aAAa,KAAK;AAAA,QAClB,OAAO,KAAK;AAAA,MAAA,CACZ;AAAA,IACF;AAAA,IAEA,MAAM,mBAAmB,OAAe,SAA0E;AAC1G,aAAA,KAAK,YAAY,OAAO,SAAS,KAAK,uBAAuB,KAAK,IAAI,CAAC;AAAA,IAC/E;AAAA,IAEA,MAAM,sBAAsB,cAAqC;AACzD,aAAA,KAAK,iBAAiB,YAAY;AAAA,IAC1C;AAAA,EACD;AAAA,ECDO,MAAe,qBAGZ,eAA6B;AAAA;AAAA;AAAA;AAAA,IAItC,IACC,OACA,aACA,YAA4C,MACb;AACzB,YAAA,EAAE,MAAM,IAAI,KAAK;AACjB,YAAA,8CAA8B;AAC9B,YAAA,QAAQ,MAAM;AACd,YAAA,gBAAgB,MAAM,YAAY,YAAY;AACpD,8BAAwB,gBAAgB,CAAC;AAEzC,UAAI,CAAC,aAAa;AACX,cAAA,IAAI,MAAM,8CAA8C;AAAA,MAC/D;AAEA,YAAM,eAAiC,QAAQ;AAAA,QAC9C,GAAG;AAAA,QACH,cAAc,wBAAwB,YAAY;AAAA,QAClD,iBAAiB;AAAA,QACjB,YAAY;AAAA,QACZ,QAAQ,MAAM,UAAU;AAAA,QACxB,UAAU,MAAM,YAAY;AAAA,MAAA,CAC5B;AAEI,WAAA,SAAS,SAAS,YAAY,CAAC;AACpC,WAAK,SAAS,kBAAkB,aAAa,UAAU,CAAC;AACnD,WAAA,SAAS,4BAA4B,CAAC,CAAC;AAEtC,YAAA,UAAU,KAAK,eAA+B;AAAA,QACnD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK;AAAA,QACL,aAAa;AAAA,UACZ,cAAc;AAAA,UACd,GAAI,YAAY,EAAE,YAAY,cAAc,CAAC;AAAA,QAC9C;AAAA,QACA,SAAS;AAAA,QACT,UAAU;AAAA,UACT;AAAA,UACA,GAAI,aAAa,kBAAkB,CAAC,aAAa,eAAe,IAAI,CAAC;AAAA,UACrE,GAAG,aAAa;AAAA,QACjB;AAAA,QACA,QAAQ,CAAC,aAAa,UAAU;AAAA,MAAA,CAChC;AACI,WAAA,QACH,KAAK,CAAC,WAA2B;AAC5B,aAAA,SAAS,YAAY,MAAM,CAAC;AAAA,MAAA,CACjC,EACA,MAAM,CAAC,UAAU;;AACjB,gBAAQ,MAAM,KAAK;AACnB,YAAI,iBAAiB,UAAU;AACZV,WAAAA,MAAAA,2BAAAA,gBAAAA,IAAAA,aAAA;AAAA,YACjB,OAAO;AAAA,YACP,aAAa,MAAM;AAAA,YACnB,aAAa;AAAA,UAAA;AAAA,QAEf;AACA,aAAK,SAAS,YAAY,aAAa,UAAU,CAAC;AAC7C,aAAA,SAAS,4BAA4B,EAAE,CAAC;AACvC,cAAA;AAAA,MAAA,CACN;AACK,aAAA,CAAC,cAAc,OAAO;AAAA,IAC9B;AAAA,IAEA,OAAO,OAAgE;AACtE,YAAM,QAAQ,KAAK,OAAO,MAAM,SAAS;AACzC,YAAM,mBAAmB,gBAAgB,MAAM,UAAU,EAAE,KAAK;AAEhE,UAAI,CAAC,kBAAkB;AACtB,cAAM,IAAI;AAAA,UACT,iDAAiD,MAAM,UAAU;AAAA,QAAA;AAAA,MAEnE;AAEA,YAAM,eAA8B,EAAE,GAAG,kBAAkB,GAAG,MAAM;AAE/D,WAAA,SAAS,YAAY,YAAY,CAAC;AAEvC,YAAM,UAAkC,CAAA;AAExC,iBAAW,qBAAqB;AAAA,QAC/B,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,MAAA,GAChB;AACF,YAAI,qBAAqB,SAAS,MAAM,iBAAiB,MAAM,iBAAiB,iBAAiB,GAAG;AACnG,kBAAQ,mBAAmB;AAAA,YAC1B,KAAK,YAAY;AAChB,kBAAI,iBAAkC;AAChC,oBAAA,mBAAmB,MAAM,iBAAiB;AAChD,kBAAI,kBAAkB;AACrB,iCAAiB,MAAM,gBAAgB,UAAU,gBAAgB,KAAK;AAEtE,oBAAI,CAAC;AACJ,wBAAM,IAAI;AAAA,oBACT,sCAAsC,gBAAgB;AAAA,kBAAA;AAAA,cAEzD;AACQ,sBAAA,iBAAiB,IAAI,iBAC1B;AAAA,gBACA,MAAM,eAAe;AAAA,gBACrB,OAAO,eAAe;AAAA,gBACtB,YAAY,eAAe;AAAA,cAE3B,IAAA;AACH;AAAA,YACD;AAAA,YACA,KAAK,eAAe;AACnB,kBAAI,aAA0B;AACxB,oBAAA,eAAe,MAAM,iBAAiB;AAC5C,kBAAI,cAAc;AACjB,6BAAa,MAAM,YAAY,MAAM,YAAY,KAAK;AAEtD,oBAAI,CAAC;AACJ,wBAAM,IAAI;AAAA,oBACT,yCAAyC,YAAY;AAAA,kBAAA;AAAA,cAExD;AACQ,sBAAA,iBAAiB,IAAI,aAC1B;AAAA,gBACA,WAAW,WAAW;AAAA,gBACtB,IAAI,WAAW;AAAA,cAEf,IAAA;AACH;AAAA,YACD;AAAA,YACA,KAAK;AACJ,sBAAQ,iBAAiB,IAAI,MAAM,iBAAiB,KAAK;AACzD;AAAA,YACD,KAAK;AACJ,sBAAQ,iBAAiB,IAAI,MAAM,iBAAiB,KAAK;AACzD;AAAA,YACD,KAAK;AACI,sBAAA,iBAAiB,IAAI,MAAM,iBAAiB;AACpD;AAAA,YACD,KAAK;AACI,sBAAA,iBAAiB,IAAI,MAAM,iBAAiB;AACpD;AAAA,YACD,KAAK;AACJ,sBAAQ,iBAAiB,IAAI,MAAM,iBAAiB,IAChD,MAAM,iBAAiB,IACxB;AAAA,UACL;AAAA,QACD;AAAA,MACD;AAEA,YAAM,qBAA6C,QAAQ;AAAA,QAC1D,YAAY,MAAM,YAAY,YAAY;AAAA,QAC1C,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,QACrC,OAAO,iBAAiB;AAAA,QACxB;AAAA,MAAA,CACA;AAEI,WAAA,SAAS,eAAe,kBAAkB,CAAC;AAE1C,YAAA,UAAU,KAAK,eAA+B;AAAA,QACnD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,WAAW,MAAM,UAAU;AAAA,QAChC,SAAS;AAAA,QACT,UAAU,CAAC,MAAM,UAAU;AAAA,QAC3B,QAAQ,CAAC,MAAM,UAAU;AAAA,MAAA,CACzB;AAED,cAAQ,MAAM,MAAM;AAEd,aAAA,SAAS,YAAY,gBAAgB,CAAC;AAC3C,aAAK,SAAS,kBAAkB,mBAAmB,UAAU,CAAC;AAAA,MAAA,CAC9D;AAEM,aAAA,CAAC,cAAc,OAAO;AAAA,IAC9B;AAAA,IAEA,MAAM,OAAO,IAAgC;AACtC,YAAA,EAAE,MAAM,IAAI,KAAK;AACjB,YAAA,QAAQ,MAAM;AAEpB,YAAM,SAAS,gBAAgB,EAAE,EAAE,KAAK;AAExC,UAAI,CAAC,QAAQ;AACZ,cAAM,IAAI,MAAM,oBAAoB,EAAE,qBAAqB;AAAA,MAC5D;AAEA,YAAM,qBAAqB,yBAAyB,EAAE,EAAE,KAAK;AAC7D,YAAM,iBAAiB,0BAA0B,EAAE,EAAE,KAAK;AAC1D,YAAM,yBAAyB,6BAA6B,EAAE,EAAE,KAAK;AAErE,YAAM,0BAAoE,CAAA;AAE1E,iBAAW,oBAAoB,+BAA+B,EAAE,EAAE,KAAK;AAC9C,gCAAA,iBAAiB,UAAU,IAAI;AACxD,iBAAW,oBAAoB,+BAA+B,EAAE,EAAE,KAAK;AAC9C,gCAAA,iBAAiB,UAAU,IAAI;AAElD,YAAA,oBAAoB,OAAO,OAAO,uBAAuB;AAE1D,WAAA,SAAS,YAAY,EAAE,CAAC;AACxB,WAAA,SAAS,4BAA4B,EAAE,CAAC;AAC7C,UAAI,mBAAmB,SAAS;AAC1B,aAAA,SAAS,uBAAuB,mBAAmB,IAAI,CAAC,EAAE,WAAW,MAAM,UAAU,CAAC,CAAC;AAC7F,UAAI,eAAe,SAAS;AACtB,aAAA,SAAS,mBAAmB,eAAe,IAAI,CAAC,EAAE,WAAW,MAAM,UAAU,CAAC,CAAC;AACrF,UAAI,uBAAuB,SAAS;AAC9B,aAAA,SAAS,sBAAsB,uBAAuB,IAAI,CAAC,EAAE,WAAW,MAAM,UAAU,CAAC,CAAC;AAChG,UAAI,kBAAkB,SAAS;AACzB,aAAA,SAAS,wBAAwB,kBAAkB,IAAI,CAAC,EAAE,WAAW,MAAM,UAAU,CAAC,CAAC;AAIzF,UAAA;AAGI,eAAA,MAAM,KAAK,eAA0B;AAAA,UAC3C,aAAa;AAAA,UACb,QAAQ,WAAW;AAAA,UACnB,KAAK,WAAW,EAAE;AAAA,UAClB,UAAU,CAAC,EAAE;AAAA,UACb,QAAQ,CAAC;AAAA,QAAA,CACT;AAAA,eACO,GAAG;AACN,aAAA,SAAS,SAAS,MAAM,CAAC;AACzB,aAAA,SAAS,oBAAoB,kBAAkB,CAAC;AAChD,aAAA,SAAS,gBAAgB,cAAc,CAAC;AACxC,aAAA,SAAS,4BAA4B,CAAC,CAAC;AACvC,aAAA,SAAS,mBAAmB,sBAAsB,CAAC;AACnD,aAAA,SAAS,qBAAqB,iBAAiB,CAAC;AAE/C,cAAA;AAAA,MACP;AAAA,IACD;AAAA;AAAA,IAGA,MAAM,aAAa,WAAuC;AACnD,YAAA,SAAS,MAAM,KAAK,eAAiC;AAAA,QAC1D,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS;AAAA,QAC3B,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT,EAAE,KAAK,CAACW,YAAW;AACb,cAAA,iBAAiBA,QAAO,OAAO,oBAAoB;AACrDA,YAAAA,QAAO,WAAW,eAAe,QAAQ;AACpC,kBAAA;AAAA,YACP,sDAAsD,eAAe,MAAM;AAAA;AAAA,UAAA;AAAA,QAG7E;AACO,eAAA;AAAA,MAAA,CACP;AAEI,WAAA,SAAS,iBAAiB,MAAM,CAAC;AAAA,IACvC;AAAA,EACD;AAAA,ECtSO,MAAe,yBAGZ,eAA6B;AAAA,IACtC,IAAI,SAA2B,gBAA0D;AAClF,YAAA,EAAE,MAAM,IAAI,KAAK;AACjB,YAAA,QAAQ,MAAM;AAEpB,YAAM,mBAAsC,QAAQ;AAAA,QACnD,GAAG;AAAA,QACH,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,QACrC,YAAY,MAAM,YAAY,YAAY;AAAA,QAC1C,cAAc;AAAA,MAAA,CACd;AAEI,WAAA,SAAS,aAAa,gBAAgB,CAAC;AAEtC,YAAA,UAAU,KAAK,eAAmC;AAAA,QACvD,QAAQ,WAAW;AAAA,QACnB,KAAK,kBAAkB,cAAc;AAAA;AAAA,QAErC,SAAS;AAAA,UACR,YAAY,iBAAiB;AAAA,UAC7B,cAAc,iBAAiB;AAAA,UAC/B,MAAM,iBAAiB;AAAA,UACvB,OAAO,iBAAiB;AAAA,UACxB,MAAM,iBAAiB;AAAA,UACvB,aAAa,iBAAiB;AAAA,QAC/B;AAAA,QACA,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC,iBAAiB,UAAU;AAAA,MAAA,CACpC;AAGC,cAAA,KAAK,CAAC,qBAAqB;AACtB,aAAA,SAAS,aAAa,gBAAgB,CAAC;AAAA,MAAA,CAC5C,EACA,MAAM,MAAM;AACZ,aAAK,SAAS,gBAAgB,iBAAiB,UAAU,CAAC;AAAA,MAAA,CAC1D;AAEK,aAAA,CAAC,kBAAkB,OAAO;AAAA,IAClC;AAAA,IAEA,OAAO,SAAwE;AACxE,YAAA,EAAE,MAAM,IAAI,KAAK;AACjB,YAAA,QAAQ,MAAM;AAEpB,YAAM,uBAAuB,oBAAoB,QAAQ,UAAU,EAAE,KAAK;AAE1E,UAAI,CAAC,sBAAsB;AAC1B,cAAM,IAAI,MAAM,6BAA6B,QAAQ,UAAU,+BAA+B;AAAA,MAC/F;AAEA,YAAM,0BAA6C;AAAA,QAClD,GAAG;AAAA,QACH,GAAG;AAAA,MAAA;AAGC,WAAA,SAAS,gBAAgB,uBAAuB,CAAC;AAEhD,YAAA,UAAU,KAAK,eAAkC;AAAA,QACtD,QAAQ,WAAW;AAAA,QACnB,KAAK,iBAAiB,QAAQ,UAAU;AAAA,QACxC;AAAA,QACA,UAAU,CAAC,QAAQ,UAAU;AAAA,QAC7B,QAAQ,CAAC,QAAQ,UAAU;AAAA,MAAA,CAC3B;AAGC,cAAA,KAAK,CAAC,qBAAqB;AACtB,aAAA,SAAS,aAAa,gBAAgB,CAAC;AAAA,MAAA,CAC5C,EACA,MAAM,MAAM;AACP,aAAA,SAAS,aAAa,oBAAoB,CAAC;AAAA,MAAA,CAChD;AAEK,aAAA,CAAC,yBAAyB,OAAO;AAAA,IACzC;AAAA,IAEA,OAAO,aAAoC;AACpC,YAAA,EAAE,MAAM,IAAI,KAAK;AACjB,YAAA,QAAQ,MAAM;AAEpB,YAAM,oBAAoB,oBAAoB,WAAW,EAAE,KAAK;AAEhE,UAAI,CAAC,mBAAmB;AACvB,cAAM,IAAI,MAAM,6BAA6B,WAAW,+BAA+B;AAAA,MACxF;AAEA,YAAM,oBAAoB,wBAAwB,WAAW,EAAE,KAAK,KAAK,CAAA;AAEpE,WAAA,SAAS,gBAAgB,WAAW,CAAC;AAErC,WAAA,SAAS,aAAa,kBAAkB,IAAI,CAAC,UAAU,MAAM,UAAU,CAAC,CAAC;AAIxE,YAAA,UAAU,KAAK,eAA0B;AAAA,QAC9C,QAAQ,WAAW;AAAA,QACnB,KAAK,iBAAiB,WAAW;AAAA,QACjC,UAAU,CAAC,WAAW;AAAA,QACtB,QAAQ,CAAC;AAAA,MAAA,CACT;AAED,cAAQ,MAAM,MAAM;AACd,aAAA,SAAS,aAAa,iBAAiB,CAAC;AACxC,aAAA,SAAS,UAAU,iBAAiB,CAAC;AAAA,MAAA,CAC1C;AAEM,aAAA;AAAA,IACR;AAAA,IAEA,MAAM,aAAa,gBAAuC;AAGnD,YAAA,SAAS,MAAM,KAAK,eAAqC;AAAA,QAC9D,QAAQ,WAAW;AAAA,QACnB,KAAK,kBAAkB,cAAc;AAAA,QACrC,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AAEI,WAAA,SAAS,qBAAqB,MAAM,CAAC;AAAA,IAC3C;AAAA,EACD;AAAA,ECtIO,MAAe,6BAGZ,eAA6B;AAAA,IACtC,MAAM,SAAS,WAA6C;AAC3D,aAAO,KAAK,eAAgC;AAAA,QAC3C,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS;AAAA,QAC3B,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AAAA,IACF;AAAA,IAEA,MAAM,OAAO,eAAsD;AAC7D,WAAA,SAAS,oBAAoB,aAAa,CAAC;AAChD,aAAO,KAAK,eAA8B;AAAA,QACzC,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,WAAW,cAAc,UAAU;AAAA,QACxC,SAAS;AAAA,QACT,UAAU,CAAC,cAAc,YAAY,qBAAqB;AAAA,QAC1D,QAAQ,CAAC,cAAc,UAAU;AAAA,MAAA,CACjC;AAAA,IACF;AAAA;AAAA,IAEA,MAAM,OAAO,eAAkD;AAC9D,WAAK,SAAS,oBAAoB,cAAc,UAAU,CAAC;AAE3D,aAAO,KAAK,eAA0B;AAAA,QACrC,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,WAAW,cAAc,UAAU;AAAA,QACxC,UAAU,CAAC,cAAc,UAAU;AAAA,QACnC,QAAQ,CAAC;AAAA,MAAA,CACT;AAAA,IACF;AAAA,IAEA,MAAM,aAAa,WAAuC;AACnD,YAAA,UAAU,KAAK,SAAS,SAAS;AACvC,YAAM,SAA0B,MAAM;AACjC,WAAA,SAAS,0BAA0B,MAAM,CAAC;AAAA,IAChD;AAAA,EACD;AAAA,EClCO,MAAe,2BAGZ,eAA6B;AAAA,IACtC,MAAM,aAAa,WAAkC;AAC9C,YAAA,SAAS,MAAM,KAAK,eAA8B;AAAA,QACvD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS;AAAA,QAC3B,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AACD,WAAK,SAAS,yBAAyB,CAAA,CAAE,CAAC;AACrC,WAAA,SAAS,yBAAyB,MAAM,CAAC;AAAA,IAC/C;AAAA,IAEA,MAAM,aAAa,MAAyC;AACvD,UAAA,CAAC,KAAK,YAAY;AACrB,cAAM,IAAI;AAAA,UACT;AAAA,QAAA;AAAA,MAEF;AACM,YAAA,eAAmC,EAAE,GAAG;AAC9C,aAAO,aAAa;AACd,YAAA,UAAU,KAAK,eAA4B;AAAA,QAChD,QAAQ,WAAW;AAAA,QACnB,KAAK,mBAAmB,KAAK,UAAU;AAAA,QACvC,SAAS;AAAA,QACT,UAAU,CAAC,KAAK,UAAU;AAAA,QAC1B,QAAQ,CAAC,KAAK,UAAU;AAAA,MAAA,CACxB;AACI,WAAA,QAAQ,KAAK,CAAC,WAAW;AACxB,aAAA,SAAS,wBAAwB,MAAM,CAAC;AAAA,MAAA,CAC7C;AACM,aAAA;AAAA,IACR;AAAA;AAAA,IAGA,aAAmD;AAC5C,YAAA,EAAE,MAAM,IAAI,KAAK;AACjB,YAAA,QAAQ,MAAM;AACd,YAAA,sBAAsB,MAAM,mBAAmB;AAC/C,YAAA,kBAAkB,MAAM,eAAe;AAC7C,UAAI,CAAC,qBAAqB;AACnB,cAAA,IAAI,MAAM,wBAAwB;AAAA,MACzC;AACA,UAAI,CAAC,iBAAiB;AACf,cAAA,IAAI,MAAM,mBAAmB;AAAA,MACpC;AACA,YAAM,oBAAoB,MAAM,mBAAmB,aAAa,mBAAmB;AACnF,UAAI,CAAC,mBAAmB;AACjB,cAAA,IAAI,MAAM,wBAAwB;AAAA,MACzC;AAEA,UAAI,CAAC,kBAAkB,UAAU,CAAC,kBAAkB,eAAe;AAC5D,cAAA,IAAI,MAAM,2DAA2D;AAAA,MAC5E;AAEI,UAAA;AACE,YAAA,WAAW,OAAO,kBAAkB,SAAS,YAAY,CAAC,kBAAkB,KAAK,WAAW,OAAO;AACzG,UAAI,UAAU;AACP,cAAA,eAAmC,EAAE,GAAG;AAC9C,eAAO,aAAa;AACH,yBAAA;AAAA,UAChB,QAAQ,WAAW;AAAA,UACnB,KAAK,mBAAmB,mBAAmB;AAAA,UAC3C,SAAS;AAAA,UACT,UAAU,CAAC,mBAAmB;AAAA,UAC9B,QAAQ,CAAC,mBAAmB;AAAA,QAAA;AAAA,MAC7B,OACM;AACN,yBAAiB,IAAI,QAAoB,CAAC,SAAS,WAAW;AACxD,eAAA,OAAO,MACV,eAAe,kBAAkB,SAAS,EAC1C,KAAK,CAAC,CAAC,SAAS,MAAM;AACd,oBAAA;AAAA,cACP,QAAQ,WAAW;AAAA,cACnB,KAAK,aAAa,eAAe;AAAA,cACjC,SAAS;AAAA,gBACR,GAAG;AAAA,gBACH,GAAG;AAAA,cACJ;AAAA,cACA,UAAU,CAAC,mBAAmB;AAAA,cAC9B,QAAQ,CAAC,mBAAmB;AAAA,YAAA,CAC5B;AAAA,UAAA,CACD,EACA,MAAM,MAAM;AAAA,QAAA,CACd;AAAA,MACF;AACA,YAAM,UAAU,QAAQ,QAAQ,cAAc,EAAE,KAAK,CAACC,oBAAmB;AACjE,eAAA,KAAK,eAA4BA,eAAc;AAAA,MAAA,CACtD;AACI,WAAA,QAAQ,KAAK,CAAC,WAAW;AACxB,aAAA,SAAS,wBAAwB,MAAM,CAAC;AAAA,MAAA,CAC7C;AACD,WAAK,SAAS,2BAA2B;AACpC,WAAA,SAAS,uBAAuB,IAAI,CAAC;AACrC,WAAA,SAAS,0BAA0B,KAAK,CAAC;AACvC,aAAA,CAAC,mBAAmB,OAAO;AAAA,IACnC;AAAA,IAEA,OAAO,eAA2C;AAC5C,WAAA,SAAS,kBAAkB,aAAa,CAAC;AAC9C,aAAO,KAAK,eAA0B;AAAA,QACrC,QAAQ,WAAW;AAAA,QACnB,KAAK,mBAAmB,aAAa;AAAA,QACrC,UAAU,CAAC,aAAa;AAAA,QACxB,QAAQ,CAAC;AAAA,MAAA,CACT;AAAA,IACF;AAAA,EACD;AAAA,ECjHO,MAAe,iCAGZ,sBAA+D;AAAA,IAHlE;AAAA;AAIN,6CAAkB,gBAAgB;AAElC,mDAAwB;AACxB,4CAAiB;AACjB,+CAAoB;AACpB,+CAAoB;AACpB,8CAAmB;AACnB,2CAAgB;AAEhB,8CAAmB;AAAA;AAAA,IAEX,uBAAuB,MAA0C;AACxE,aAAO,QAAQ;AAAA,QACd,MAAM,IAAI,gBAAgB,KAAK,IAAI;AAAA,QACnC,WAAW,KAAK;AAAA,QAChB,YAAY,KAAK;AAAA,QACjB,WAAW,KAAK,KAAK;AAAA,QACrB,WAAW,KAAK,KAAK;AAAA,QACrB,cAAc,KAAK;AAAA,QACnB,aAAa,KAAK;AAAA,QAClB,SAAS,KAAK;AAAA,MAAA,CACd;AAAA,IACF;AAAA,IAEA,MAAM,qBACL,OACA,WAC4D;AACrD,aAAA,KAAK,YAAY,OAAO,WAAW,KAAK,uBAAuB,KAAK,IAAI,CAAC;AAAA,IACjF;AAAA,IAEA,MAAM,wBAAwB,cAAqC;AAC3D,aAAA,KAAK,iBAAiB,YAAY;AAAA,IAC1C;AAAA,EACD;AAAA,ECxBO,MAAe,uBAGZ,eAA6B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOtC,MAAM,IAAI,SAA6C;AACtD,UAAI,CAAC,QAAQ,sBAAsB,CAAC,QAAQ,YAAY;AACjD,cAAA,IAAI,MAAM,6DAA6D;AAAA,MAC9E;AAEA,UAAI,CAAC,QAAQ,UAAU,CAAC,QAAQ,eAAe;AACxC,cAAA,IAAI,MAAM,sDAAsD;AAAA,MACvE;AAEM,YAAA,wBAAwB,CAAC,CAAC,QAAQ;AAExC,YAAM,MAAM,wBAAwB,kBAAkB,QAAQ,kBAAkB,eAAe;AACzF,YAAA,cAAc,wBACjB,EAAE,oBAAoB,QAAQ,mBAC9B,IAAA,EAAE,YAAY,QAAQ;AAElB,aAAA,MAAM,KAAK,eAAiC;AAAA,QAClD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB;AAAA,QACA,SAAS;AAAA,UACR,MAAM,QAAQ;AAAA,UACd,QAAQ,QAAQ;AAAA,UAChB,GAAG;AAAA,QACJ;AAAA,QACA,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AAAA,IACF;AAAA,IAEA,MAAM,OAAO,SAAoC;AAChD,UAAI,CAAC,QAAQ,UAAU,CAAC,QAAQ,eAAe;AACxC,cAAA,IAAI,MAAM,sDAAsD;AAAA,MACvE;AAEK,WAAA,SAAS,sBAAsB,OAAO,CAAC;AACrC,aAAA,MAAM,KAAK,eAAwB;AAAA,QACzC,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,QAAQ,EAAE;AAAA,QAC5B,SAAS;AAAA,UACR,MAAM,QAAQ;AAAA,UACd,QAAQ,QAAQ;AAAA,QACjB;AAAA,QACA,UAAU,CAAC,QAAQ,GAAG,UAAU;AAAA,QAChC,QAAQ,CAAC,QAAQ,GAAG,UAAU;AAAA,MAAA,CAC9B;AAAA,IACF;AAAA,IAEA,MAAM,OAAO,WAAkC;AACxC,YAAA,EAAE,MAAM,IAAI,KAAK;AACjB,YAAA,QAAQ,MAAM;AACd,YAAA,WAAW,qBAAqB,KAAK;AACrC,YAAA,UAAU,SAAS,SAAS;AAClC,UAAI,CAAC,SAAS;AACP,cAAA,IAAI,MAAM,2BAA2B;AAAA,MAC5C;AAIM,YAAA,gBAAgB,mBAAmB,KAAK,EAAE,OAAO,CAAC,SAAS,KAAK,YAAY,SAAS;AAC3F,WAAK,SAAS,4BAA4B,QAAQ,EAAE,CAAC;AAGrD,YAAM,uBAAuB,2BAA2B,QAAQ,EAAE,EAAE,KAAK;AACpE,WAAA,SAAS,yBAAyB,qBAAqB,IAAI,CAAC,EAAE,WAAW,MAAM,UAAU,CAAC,CAAC;AAG1F,YAAA,kBAAkB,sBAAsB,KAAK;AAC9C,WAAA,SAAS,sBAAsB,gBAAgB,IAAI,CAAC,EAAE,WAAW,MAAM,UAAU,CAAC,CAAC;AAGxF,WAAK,SAAS,EAAE,MAAM,4BAA4B,SAAS,OAAO;AAC7D,WAAA,SAAS,cAAc,OAAO,CAAC;AAEpC,YAAM,UAAU,wBAAwB,QAAQ,EAAE,EAAE,KAAK;AAEzD,UAAI,SAAS;AACP,aAAA,SAAS,cAAc,EAAE,GAAG,SAAS,SAAS,KAAiB,CAAA,CAAC;AAAA,MACtE;AAEI,UAAA;AACH,cAAM,KAAK,eAA0B;AAAA,UACpC,aAAa;AAAA,UACb,QAAQ,WAAW;AAAA,UACnB,KAAK,aAAa,SAAS;AAAA,UAC3B,UAAU,CAAC,UAAU,UAAU;AAAA,UAC/B,QAAQ,CAAC;AAAA,QAAA,CACT;AACD,aAAK,SAAS,EAAE,MAAM,4BAA4B,SAAS,MAAM;AAAA,eACzD,GAAG;AACX,aAAK,SAAS,YAAY,OAAO,OAAO,QAAQ,CAAC,CAAC;AAClD,aAAK,SAAS,0BAA0B,OAAO,OAAO,eAAe,CAAC,CAAC;AAClE,aAAA,SAAS,yBAAyB,aAAa,CAAC;AAChD,aAAA,SAAS,sBAAsB,oBAAoB,CAAC;AACzD,aAAK,SAAS,EAAE,MAAM,4BAA4B,SAAS,MAAM;AACjE,YAAI,SAAS;AACP,eAAA,SAAS,cAAc,EAAE,GAAG,SAAS,SAAS,QAAQ,GAAe,CAAA,CAAC;AAAA,QAC5E;AACM,cAAA;AAAA,MACP;AAAA,IACD;AAAA,IAEA,OAAO,WAAmB,OAAmC;AAC5D,YAAM,aAAqBtD,KAAAA;AAC3B,aAAO,KAAK,eAA0B;AAAA,QACrC,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS,WAAW,KAAK;AAAA,QAC3C,SAAS;AAAA,UACR;AAAA,QACD;AAAA,QACA,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC,UAAU;AAAA,MAAA,CACnB;AAAA,IACF;AAAA,IAEA,YAAY,WAAmB,QAAgB,YAAkD;AAChG,aAAO,KAAK,eAAoC;AAAA,QAC/C,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS,iBAAiB,MAAM,IAAI,UAAU;AAAA,QAChE,cAAc;AAAA,QACd,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AAAA,IACF;AAAA,IAEA,MAAM,aAAa,WAAkC;AACpD,aAAO,KAAK,eAA0B;AAAA,QACrC,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS;AAAA,QAC3B,UAAU,CAAC,UAAU,UAAU;AAAA,QAC/B,QAAQ,CAAC,UAAU,UAAU;AAAA,MAAA,CAC7B,EAAE,KAAK,MAAM;AACR,aAAA,SAAS,oBAAoB,SAAS,CAAC;AAAA,MAAA,CAC5C;AAAA,IACF;AAAA,EACD;AC5IA,QAAM,0BAA0B,OAAO,WAA+B;AACrE,UAAM,SAA+B,CAAA;AACrC,UAAM,YAAgC,CAAA;AACtC,eAAW,WAAW,QAAQ;AACzB,UAAA,QAAQ,SAAS,WAAW;AAC/B,cAAM,IAAI,MAAM,uDAAuD,QAAQ,IAAI,WAAW;AAAA,MAC/F;AAEM,YAAA,EAAE,QAAQ,cAAkB,IAAA;AAClC,YAAM,mBAA2C,CAAA;AACjD,iBAAW,SAAS,eAAe;AAClC,YAAI,MAAM,OAAO;AACZ,cAAA,MAAM,iBAAiB,SAAS;AAC/B,gBAAA;AACH,qBAAO,MAAM,UAAU,IAAI,MAAM,MAAM;AAAA,qBAC/B,GAAG;AACH,sBAAA,MAAM,oCAAoC,CAAC;AAAA,YACpD;AAAA,UAAA,OACM;AACC,mBAAA,MAAM,UAAU,IAAI,MAAM;AAAA,UAClC;AACA,iBAAO,MAAM;AAAA,QACd;AACA,yBAAiB,KAAK,KAAK;AAAA,MAC5B;AACA,gBAAU,KAAK,EAAE,GAAG,SAAS,QAAQ,kBAAkB;AAAA,IACxD;AAEO,WAAA,EAAE,QAAQ,WAAW;EAC7B;AAAA,EAEO,MAAe,oBAGZ,kBAAgC;AAAA,IACzC,MAAc,2BACb,YACA,OACiE;AASjE,YAAM,eAAc,oBAAI,KAAK,GAAE,YAAY;AAC3C,YAAM,YAAY,KAAK,OAAO,MAAM,WAAW,YAAY,YAAY;AAEvE,YAAM,eAAyD,CAAA;AAC/D,YAAM,iCAAmE,CAAA;AACzE,YAAM,qBAA0C,CAAA;AAEhD,iBAAW,CAAC,iBAAiB,IAAI,KAAK,OAAO,QAAQ,KAAK,GAAG;AACtD,cAAA,OAAO,MAAM,SAAS,IAAI;AAE5B,YAAA,EAAE,QAAQ,eAAe;AAC5B,uBAAa,IAAI,IAAI;AAAA,YACpB;AAAA,YACA,WAAW,KAAK;AAAA,YAChB,WAAW,KAAK,KAAK,MAAM,GAAG,EAAE,IAAI;AAAA,YACpC,MAAM,KAAK;AAAA,UAAA;AAEZ,gBAAM,KAAK,OAAO,MAAM,SAAS,MAAM,IAAI;AAAA,QAC5C;AAEA,cAAM,gCAAgE,QAAQ;AAAA,UAC7E,MAAM,IAAI,gBAAgB,IAAI;AAAA,UAC9B,WAAW,KAAK;AAAA,UAChB,WAAW,KAAK;AAAA,UAChB,WAAW;AAAA,UACX,YAAY;AAAA,UACZ,UAAU;AAAA,UACV,cAAc;AAAA,UACd,kBAAkB;AAAA,QAAA,CAClB;AACD,uCAA+B,KAAK,6BAA6B;AAEjE,cAAM,oBAAuC;AAAA,UAC5C,YAAY,8BAA8B;AAAA,UAC1C,MAAM,KAAK;AAAA,UACX,kBAAkB;AAAA,UAClB;AAAA,QAAA;AAED,2BAAmB,KAAK,iBAAiB;AAAA,MAC1C;AAEK,WAAA,SAAS,2BAA2B,8BAA8B,CAAC;AAElE,YAAA,UAAU,KAAK,eAGlB;AAAA,QACF,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,oBAAoB,UAAU;AAAA,QACnC,SAAS;AAAA,UACR,cAAc;AAAA,UACd,aAAa;AAAA,UACb,OAAO,OAAO,OAAO,YAAY;AAAA,QAClC;AAAA,QACA,UAAU,CAAC,UAAU;AAAA,QACrB,QAAQ,+BAA+B,IAAI,CAAC,eAAe,WAAW,UAAU;AAAA,MAAA,CAChF;AAGC,cAAA,KAAK,CAAC,WAAW;AACZ,aAAA,qBAAqB,OAAO,cAAc;AAC/C,aAAK,SAAS,8BAA8B,OAAO,WAAW,CAAC;AAAA,MAAA,CAC/D,EACA,MAAM,MAAM;AACP,aAAA;AAAA,UACJ;AAAA,YACC,+BAA+B,IAAI,CAAC,eAAe,WAAW,UAAU;AAAA,UACzE;AAAA,QAAA;AAAA,MACD,CACA;AAEK,aAAA,CAAC,gCAAgC,QAAQ,KAAK,CAAC,EAAE,YAAkB,MAAA,WAAW,CAAC;AAAA,IACvF;AAAA,IAEA,MAAc,IACb,SACA,MACA,iBACA,WASC;AAaD,YAAM,EAAE,QAAQ,WAAW,MAAM,wBAAwB,gBAAgB,MAAM;AAE/E,YAAM,sBAA+C,QAAQ;AAAA,QAC5D,GAAG;AAAA,QACH;AAAA,QACA,YAAY,KAAK;AAAA,QACjB,MAAM,KAAK;AAAA,QACX,cAAc,KAAK;AAAA,QACnB,UAAU;AAAA,MAAA,CACV;AAEI,WAAA,SAAS,QAAQ,IAAI,CAAC;AACtB,WAAA,SAAS,gBAAgB,mBAAmB,CAAC;AAE5C,YAAA,cAAc,KAAK,eAA6B;AAAA,QACrD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK;AAAA,QACL,SAAS;AAAA;AAAA,UAER,YAAY,KAAK;AAAA,UACjB,cAAc,KAAK;AAAA,UACnB,kBAAkB;AAAA,YACjB,YAAY,oBAAoB;AAAA,YAChC,cAAc,oBAAoB;AAAA,YAClC,OAAO,oBAAoB;AAAA,YAC3B,aAAa,oBAAoB;AAAA,YACjC,QAAQ,oBAAoB;AAAA,UAC7B;AAAA,QACD;AAAA,QACA,UAAU,CAAC,OAAO;AAAA,QAClB,QAAQ,CAAC,KAAK,YAAY,oBAAoB,UAAU;AAAA,MAAA,CACxD;AAED,YAAM,CAAC,gCAAgC,kBAAkB,IAAI,MAAM,KAAK;AAAA,QACvE,oBAAoB;AAAA,QACpB;AAAA,MAAA;AAGI,WAAA,YAAY,MAAM,CAAC,MAAM;AAC7B,aAAK,SAAS,WAAW,KAAK,UAAU,CAAC;AACzC,aAAK,SAAS,mBAAmB,oBAAoB,UAAU,CAAC;AAE1D,cAAA;AAAA,MAAA,CACN;AAED,aAAO,CAAC,MAAM,qBAAqB,gCAAgC,aAAa,kBAAkB;AAAA,IACnG;AAAA,IAEA,mBAAmB,gBAAwB,iBAAsC;AAChF,YAAM,QAA0B,KAAK,OAAO,MAAM,SAAS;AAE3D,YAAM,cAA+B,QAAQ;AAAA,QAC5C,UAAU;AAAA,QACV,YAAY,MAAM,YAAY,YAAY;AAAA,QAC1C,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,QACrC,cAAc;AAAA,MAAA,CACd;AAED,aAAO,KAAK;AAAA,QACX,eAAe,SAAS;AAAA,QACxB;AAAA,QACA;AAAA,QACA,kBAAkB,cAAc;AAAA,MAAA;AAAA,IAElC;AAAA,IAEA,cAAc,WAAmB,iBAAsC;AACtE,YAAM,QAA0B,KAAK,OAAO,MAAM,SAAS;AAE3D,YAAM,cAA+B,QAAQ;AAAA,QAC5C,UAAU;AAAA,QACV,YAAY,MAAM,YAAY,YAAY;AAAA,QAC1C,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,QACrC,SAAS;AAAA,MAAA,CACT;AAEM,aAAA,KAAK,IAAI,UAAU,SAAA,GAAY,aAAa,iBAAiB,aAAa,SAAS,eAAe;AAAA,IAC1G;AAAA,IAEA,gBAAgB,aAAqB,iBAAsC;AAC1E,YAAM,QAA0B,KAAK,OAAO,MAAM,SAAS;AAE3D,YAAM,cAA+B,QAAQ;AAAA,QAC5C,UAAU;AAAA,QACV,YAAY,MAAM,YAAY,YAAY;AAAA,QAC1C,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,QACrC,YAAY;AAAA,MAAA,CACZ;AAED,aAAO,KAAK,IAAI,aAAa,aAAa,iBAAiB,iBAAiB,WAAW,eAAe;AAAA,IACvG;AAAA,IAEA,gBAAgB,aAAqB,iBAAsC;AAC1E,YAAM,QAA0B,KAAK,OAAO,MAAM,SAAS;AAE3D,YAAM,cAA+B,QAAQ;AAAA,QAC5C,UAAU;AAAA,QACV,YAAY,MAAM,YAAY,YAAY;AAAA,QAC1C,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,QACrC,YAAY;AAAA,MAAA,CACZ;AAED,aAAO,KAAK,IAAI,aAAa,aAAa,iBAAiB,iBAAiB,WAAW,eAAe;AAAA,IACvG;AAAA,IAEA,MAAM,eACL,QACA,UAQC;AACK,YAAA,kBAAkB,QAAQ,QAAQ;AAClC,YAAA,EAAE,MAAM,IAAI,KAAK;AACjB,YAAA,QAAQ,MAAM;AAEd,YAAA,kBAAkB,MAAM,eAAe;AAC7C,UAAI,CAAC,iBAAiB;AACf,cAAA,IAAI,MAAM,8DAA8D;AAAA,MAC/E;AACM,YAAA,gBAAgB,MAAM,YAAY,YAAY;AAEpD,YAAM,EAAE,QAAQ,WAAW,MAAM,wBAAwB,gBAAgB,MAAM;AAE/E,YAAM,eAAwC;AAAA,QAC7C,GAAG;AAAA,QACH;AAAA,QACA,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,MAAM;AAAA,QACN,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,MAAA;AAGjC,WAAA,SAAS,gBAAgB,YAAY,CAAC;AAErC,YAAA,UAAU,KAAK,eAA6B;AAAA,QACjD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,UAAU,MAAM;AAAA,QACrB,SAAS;AAAA,UACR,kBAAkB;AAAA,YACjB,YAAY,aAAa;AAAA,YACzB,cAAc,aAAa;AAAA,YAC3B,OAAO,aAAa;AAAA,YACpB,aAAa,aAAa;AAAA,YAC1B,QAAQ,aAAa;AAAA,UACtB;AAAA,QACD;AAAA,QACA,UAAU,CAAC,MAAM;AAAA,QACjB,QAAQ,CAAC,gBAAgB,UAAU;AAAA,MAAA,CACnC;AAED,YAAM,CAAC,gCAAgC,kBAAkB,IAAI,MAAM,KAAK;AAAA,QACvE,aAAa;AAAA,QACb;AAAA,MAAA;AAGI,WAAA,QACH,KAAK,CAAC,WAAW;AACZ,aAAA,SAAS,gBAAgB,MAAM,CAAC;AAAA,MAAA,CACrC,EACA,MAAM,MAAM;AACZ,aAAK,SAAS,mBAAmB,aAAa,UAAU,CAAC;AAAA,MAAA,CACzD;AAEF,aAAO,CAAC,cAAc,gCAAgC,SAAS,kBAAkB;AAAA,IAClF;AAAA,IAEA,MAAM,SAAS,QAAoC;AAC5C,YAAA,EAAE,MAAM,IAAI,KAAK;AACjB,YAAA,QAAQ,MAAM;AAEd,YAAA,kBAAkB,MAAM,eAAe;AAC7C,YAAM,OAAO,MAAM,YAAY,UAAU,MAAM;AAE/C,UAAI,CAAC,MAAM;AACV,cAAM,IAAI,MAAM,+BAA+B,IAAI,EAAE;AAAA,MACtD;AAEK,WAAA,SAAS,WAAW,EAAE,GAAG,MAAM,UAAU,KAAM,CAAA,CAAC;AAEjD,UAAA;AACH,cAAM,KAAK,eAAe;AAAA,UACzB,aAAa;AAAA,UACb,QAAQ,WAAW;AAAA,UACnB,KAAK,UAAU,MAAM,aAAa,eAAe;AAAA,UACjD,UAAU,CAAC,QAAQ,YAAY,MAAM,EAAE;AAAA,UACvC,QAAQ,CAAC,YAAY,MAAM,EAAE;AAAA,QAAA,CAC7B;AAAA,eACO,GAAG;AACN,aAAA,SAAS,WAAW,IAAI,CAAC;AACxB,cAAA;AAAA,MACP;AAAA,IACD;AAAA,IAEA,MAAM,WAAW,QAAoC;AAC9C,YAAA,EAAE,MAAM,IAAI,KAAK;AACjB,YAAA,QAAQ,MAAM;AAEd,YAAA,kBAAkB,MAAM,eAAe;AAC7C,YAAM,OAAO,MAAM,YAAY,UAAU,MAAM;AAE/C,UAAI,CAAC,MAAM;AACV,cAAM,IAAI,MAAM,+BAA+B,IAAI,EAAE;AAAA,MACtD;AAEK,WAAA,SAAS,WAAW,EAAE,GAAG,MAAM,UAAU,MAAO,CAAA,CAAC;AAElD,UAAA;AAGI,eAAA,MAAM,KAAK,eAA0B;AAAA,UAC3C,aAAa;AAAA,UACb,QAAQ,WAAW;AAAA,UACnB,KAAK,UAAU,MAAM,eAAe,eAAe;AAAA,UACnD,UAAU,CAAC,QAAQ,YAAY,MAAM,EAAE;AAAA,UACvC,QAAQ,CAAC,YAAY,MAAM,EAAE;AAAA,QAAA,CAC7B;AAAA,eACO,GAAG;AACN,aAAA,SAAS,WAAW,IAAI,CAAC;AACxB,cAAA;AAAA,MACP;AAAA,IACD;AAAA,IAEA,MAAM,OAAO,QAAoC;AAC1C,YAAA,EAAE,MAAM,IAAI,KAAK;AACjB,YAAA,QAAQ,MAAM;AACpB,YAAM,OAAO,eAAe,MAAM,EAAE,KAAK;AACzC,UAAI,CAAC,MAAM;AACJ,cAAA,IAAI,MAAM,wBAAwB;AAAA,MACzC;AAEA,YAAM,kBAAkB,4BAA4B,MAAM,EAAE,KAAK;AAC7D,UAAA,mBAAmB,gBAAgB,SAAS,GAAG;AAC7C,aAAA,SAAS,sBAAsB,gBAAgB,IAAI,CAAC,EAAE,WAAW,MAAM,UAAU,CAAC,CAAC;AAAA,MACzF;AAGA,YAAM,gBAAgB,0BAA0B,MAAM,EAAE,KAAK;AACzD,UAAA,iBAAiB,cAAc,SAAS,GAAG;AACzC,aAAA,SAAS,oBAAoB,cAAc,IAAI,CAAC,EAAE,WAAW,MAAM,UAAU,CAAC,CAAC;AAAA,MACrF;AAGK,WAAA,SAAS,WAAW,MAAM,CAAC;AAE5B,UAAA;AAGI,eAAA,MAAM,KAAK,eAA0B;AAAA,UAC3C,aAAa;AAAA,UACb,QAAQ,WAAW;AAAA,UACnB,KAAK,UAAU,MAAM;AAAA,UACrB,UAAU,CAAC,MAAM;AAAA,UACjB,QAAQ,CAAC;AAAA,QAAA,CACT;AAAA,eACO,GAAG;AACN,aAAA,SAAS,QAAQ,IAAI,CAAC;AACvB,YAAA,iBAAiB,cAAc,SAAS,GAAG;AACzC,eAAA,SAAS,iBAAiB,aAAa,CAAC;AAAA,QAC9C;AACI,YAAA,mBAAmB,gBAAgB,SAAS,GAAG;AAC7C,eAAA,SAAS,mBAAmB,eAAe,CAAC;AAAA,QAClD;AACM,cAAA;AAAA,MACP;AAAA,IACD;AAAA,IAEA,MAAM,aAAa,WAAkC;AAOpD,YAAM,QAAyB,CAAA;AAC/B,YAAM,YAAqC,CAAA;AAC3C,YAAM,cAAiD,CAAA;AAEjD,YAAA,qBAAqB,MAAM,KAAK,eAAiC;AAAA,QACtE,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS;AAAA,QAC3B,UAAU,CAAC,UAAU,UAAU;AAAA,QAC/B,QAAQ,CAAC;AAAA,MAAA,CACT;AAED,iBAAW,QAAQ,mBAAmB;AAAO,cAAM,KAAK,IAAI;AAC5D,iBAAW,YAAY,mBAAmB;AAAW,kBAAU,KAAK,QAAQ;AAC5E,iBAAW,cAAc,mBAAmB;AAAa,oBAAY,KAAK,UAAU;AAE9E,YAAA,0BAA0B,MAAM,KAAK,eAAiC;AAAA,QAC3E,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS;AAAA,QAC3B,UAAU,CAAC,UAAU,UAAU;AAAA,QAC/B,QAAQ,CAAC;AAAA,MAAA,CACT;AAED,iBAAW,QAAQ,wBAAwB;AAAO,cAAM,KAAK,IAAI;AACjE,iBAAW,YAAY,wBAAwB;AAAW,kBAAU,KAAK,QAAQ;AACjF,iBAAW,cAAc,wBAAwB;AAAa,oBAAY,KAAK,UAAU;AAEnF,YAAA,uBAAuB,MAAM,KAAK,eAAiC;AAAA,QACxE,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS;AAAA,QAC3B,UAAU,CAAC,UAAU,UAAU;AAAA,QAC/B,QAAQ,CAAC;AAAA,MAAA,CACT;AAED,iBAAW,QAAQ,qBAAqB;AAAO,cAAM,KAAK,IAAI;AAC9D,iBAAW,YAAY,qBAAqB;AAAW,kBAAU,KAAK,QAAQ;AAC9E,iBAAW,cAAc,qBAAqB;AAAa,oBAAY,KAAK,UAAU;AAEhF,YAAA,uBAAuB,MAAM,KAAK,eAAiC;AAAA,QACxE,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS;AAAA,QAC3B,UAAU,CAAC,UAAU,UAAU;AAAA,QAC/B,QAAQ,CAAC;AAAA,MAAA,CACT;AAED,iBAAW,QAAQ,qBAAqB;AAAO,cAAM,KAAK,IAAI;AAC9D,iBAAW,YAAY,qBAAqB;AAAW,kBAAU,KAAK,QAAQ;AAC9E,iBAAW,cAAc,qBAAqB;AAAa,oBAAY,KAAK,UAAU;AAEjF,WAAA,SAAS,gBAAgB,KAAK,CAAC;AAC/B,WAAA,SAAS,wBAAwB,SAAS,CAAC;AAC3C,WAAA,SAAS,kCAAkC,WAAW,CAAC;AAAA,IAC7D;AAAA,EACD;AC/eA,QAAM,iBAAiB,CAAC,UAAoC;AAC3D,WAAO,MAAM,QAAQ,KAAK,KAAK,MAAM,CAAC,aAAa;AAAA,EACpD;AAIA,QAAM,0BAA0B,CAAC,WAA4C;AAC5E,UAAM,QAAgC,CAAA;AACtC,UAAM,YAAwC,CAAA;AAC9C,eAAW,OAAO,QAAQ;AACnB,YAAA,QAAQ,OAAO,GAAG;AAExB,UAAI,UAAU;AAAiB,cAAA,IAAI,MAAM,8BAA8B;AAEvE,UAAI,iBAAiB,MAAM;AACpB,cAAA,GAAG,IAAI,CAAC,KAAK;AAAA,MAAA,WACT,eAAe,KAAK,GAAG;AACjC,cAAM,GAAG,IAAI;AAAA,MAAA,OACP;AACN,kBAAU,GAAG,IAAI;AAAA,MAClB;AAAA,IACD;AAEO,WAAA,EAAE,QAAQ,WAAW;EAC7B;AAAA,EAQO,MAAe,8BAGZ,kBAAgC;AAAA,IACzC,MAAc,6BACb,cACA,OACmE;AASnE,YAAM,eAAc,oBAAI,KAAK,GAAE,YAAY;AAC3C,YAAM,YAAY,KAAK,OAAO,MAAM,WAAW,YAAY,YAAY;AAEvE,YAAM,eAAyD,CAAA;AAC/D,YAAM,mCAAuE,CAAA;AAC7E,YAAM,qBAA0C,CAAA;AAEhD,iBAAW,CAAC,iBAAiB,UAAU,KAAK,OAAO,QAAQ,KAAK,GAAG;AAClE,mBAAW,QAAQ,YAAY;AACxB,gBAAA,OAAO,MAAM,SAAS,IAAI;AAE5B,cAAA,EAAE,QAAQ,eAAe;AAC5B,yBAAa,IAAI,IAAI;AAAA,cACpB;AAAA,cACA,WAAW,KAAK;AAAA,cAChB,WAAW,KAAK,KAAK,MAAM,GAAG,EAAE,IAAI;AAAA,cACpC,MAAM,KAAK;AAAA,YAAA;AAEZ,kBAAM,KAAK,OAAO,MAAM,SAAS,MAAM,IAAI;AAAA,UAC5C;AAEA,gBAAM,kCAAoE,QAAQ;AAAA,YACjF,MAAM,IAAI,gBAAgB,IAAI;AAAA,YAC9B,WAAW,KAAK;AAAA,YAChB,WAAW,KAAK;AAAA,YAChB,WAAW;AAAA,YACX,YAAY;AAAA,YACZ,YAAY;AAAA,YACZ,cAAc;AAAA,YACd,kBAAkB;AAAA,UAAA,CAClB;AACD,2CAAiC,KAAK,+BAA+B;AAErE,gBAAM,oBAAuC;AAAA,YAC5C,YAAY,gCAAgC;AAAA,YAC5C,MAAM,KAAK;AAAA,YACX;AAAA,YACA,kBAAkB;AAAA,UAAA;AAEnB,6BAAmB,KAAK,iBAAiB;AAAA,QAC1C;AAAA,MACD;AAEK,WAAA,SAAS,6BAA6B,gCAAgC,CAAC;AAEtE,YAAA,UAAU,KAAK,eAGlB;AAAA,QACF,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,sBAAsB,YAAY;AAAA,QACvC,SAAS;AAAA,UACR,cAAc;AAAA,UACd,aAAa;AAAA,UACb,OAAO,OAAO,OAAO,YAAY;AAAA,QAClC;AAAA,QACA,UAAU,CAAC,YAAY;AAAA,QACvB,QAAQ,iCAAiC,IAAI,CAAC,eAAe,WAAW,UAAU;AAAA,MAAA,CAClF;AAGC,cAAA,KAAK,CAAC,WAAW;AACZ,aAAA,qBAAqB,OAAO,cAAc;AAC/C,aAAK,SAAS,gCAAgC,OAAO,WAAW,CAAC;AAAA,MAAA,CACjE,EACA,MAAM,MAAM;AACP,aAAA;AAAA,UACJ;AAAA,YACC,iCAAiC,IAAI,CAAC,eAAe,WAAW,UAAU;AAAA,UAC3E;AAAA,QAAA;AAAA,MACD,CACA;AAEK,aAAA,CAAC,kCAAkC,QAAQ,KAAK,CAAC,EAAE,YAAkB,MAAA,WAAW,CAAC;AAAA,IACzF;AAAA,IAEA,MAAc,gCAAgC,cAAsB,gBAAyC;AACtG,YAAA,EAAE,MAAM,IAAI,KAAK;AACjB,YAAA,QAAQ,MAAM;AAEpB,YAAM,4BAA4B,qCAAqC,cAAc,EAAE,KAAK;AAEvF,WAAA,SAAS,gCAAgC,cAAc,CAAC;AAEzD,UAAA;AACH,cAAM,KAAK,eAA0B;AAAA,UACpC,aAAa;AAAA,UACb,QAAQ,WAAW;AAAA,UACnB,KAAK,sBAAsB,YAAY;AAAA,UACvC,SAAS,EAAE,aAAa,eAAe;AAAA,UACvC,UAAU,CAAC,cAAc,GAAG,cAAc;AAAA,UAC1C,QAAQ,CAAC;AAAA,QAAA,CACT;AAAA,eACO,GAAG;AACN,aAAA,SAAS,6BAA6B,yBAAyB,CAAC;AAC/D,cAAA;AAAA,MACP;AAAA,IACD;AAAA;AAAA,IAGA,MAAM,IACL,SAQC;AACK,YAAA,EAAE,MAAM,IAAI,KAAK;AACjB,YAAA,QAAQ,MAAM;AACd,YAAA,kBAAkB,MAAM,eAAe;AAE7C,UAAI,CAAC,iBAAiB;AACf,cAAA,IAAI,MAAM,4BAA4B;AAAA,MAC7C;AAEA,YAAM,EAAE,QAAQ,MAAA,IAAU,wBAAwB,QAAQ,MAAM;AAEhE,YAAM,oBAA+C,QAAQ;AAAA,QAC5D,GAAG;AAAA,QACH;AAAA,QACA,YAAY,MAAM,YAAY,YAAY;AAAA,QAC1C,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,MAAA,CACrC;AAEK,YAAA,UAAU,KAAK,eAA+B;AAAA,QACnD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,oBAAoB,QAAQ,aAAa;AAAA,QAC9C,SAAS,EAAE,GAAG,mBAAmB,SAAS,gBAAgB;AAAA,QAC1D,UAAU,CAAC,QAAQ,OAAO,QAAQ,OAAO,QAAQ,aAAa,gBAAgB,EAAE;AAAA,UAC/E,CAAC,MAAM,MAAM;AAAA,QACd;AAAA,QACA,QAAQ,CAAC,kBAAkB,UAAU;AAAA,MAAA,CACrC;AAEI,WAAA,SAAS,kBAAkB,iBAAiB,CAAC;AAElD,YAAM,CAAC,kCAAkC,kBAAkB,IAAI,MAAM,KAAK;AAAA,QACzE,kBAAkB;AAAA,QAClB;AAAA,MAAA;AAIC,cAAA,KAAK,CAAC,WAAW;AACZ,aAAA,SAAS,qCAAqC,CAAC,CAAC;AAChD,aAAA,SAAS,kBAAkB,MAAM,CAAC;AAChC,eAAA;AAAA,MAAA,CACP,EACA,MAAM,MAAM;AACZ,aAAK,SAAS,qBAAqB,kBAAkB,UAAU,CAAC;AAC3D,aAAA,SAAS,qCAAqC,EAAE,CAAC;AAAA,MAAA,CACtD;AAEF,aAAO,CAAC,mBAAmB,kCAAkC,SAAS,kBAAkB;AAAA,IACzF;AAAA;AAAA;AAAA,IAIA,MAAM,QACL,MAKA,WACgD;AAwChD,YAAM,EAAE,cAAc,mBAAmB,mBAAA,IAAuB;AAIhE,YAAM,EAAE,QAAQ,gCAAgC,OAAO,gBACtD,wBAAwB,iBAAiB;AAE1C,YAAM,eAAc,oBAAI,KAAK,GAAE,YAAY;AAC3C,YAAM,gBAAgBA,KAAAA;AAEtB,YAAM,iBAAiB,WAAW,OAAO,KAAK,kBAAkB,GAAG,SAAS;AAEtE,YAAA,iBAAiC,MAAM,QAAQ;AAAA,QACpD,eAAe,IAAI,OAAO,iBAAiB;AAC1C,gBAAM,UAAUA,KAAAA;AAChB,gBAAM,qBAA0C,CAAA;AAChD,gBAAM,qBAAyC,CAAA;AACzC,gBAAA,QAAgC,EAAE,GAAG;AAE3C,qBAAW,WAAW,cAAc;AAC7B,kBAAA,EAAE,QAAQ,uCAAuC,OAAO,wBAAA,IAC7D,wBAAwB,mBAAmB,OAAO,KAAK,CAAA,CAAE;AAEnD,mBAAA,OAAO,OAAO,uBAAuB;AAE5C,kBAAM,oBAAuC,QAAQ;AAAA,cACpD,UAAU;AAAA,cACV,WAAW;AAAA,YAAA,CACX;AAED,+BAAmB,KAAK,iBAAiB;AAEzC,uBAAW,CAAC,iBAAiB,SAAS,KAAK,OAAO,QAAQ,KAAK,GAAG;AACjE,yBAAW,QAAQ,WAAW;AACvB,sBAAA,OAAO,MAAM,SAAS,IAAI;AAChC,sBAAM,KAAK,OAAO,MAAM,SAAS,MAAM,IAAI;AAE3C,sBAAM,oBAAsC,QAAQ;AAAA,kBACnD,eAAe,kBAAkB;AAAA,kBACjC;AAAA,kBACA,MAAM,KAAK;AAAA,kBACX,kBAAkB;AAAA,gBAAA,CAClB;AACD,mCAAmB,KAAK,iBAAiB;AAAA,cAC1C;AAAA,YACD;AAAA,UACD;AAEA,gBAAM,cAA6B,CAAA;AAEnC,qBAAW,QAAQ,OAAO,OAAO,KAAK,EAAE,QAAQ;AACzC,kBAAA,OAAO,MAAM,SAAS,IAAI;AAChC,kBAAM,cAA2B;AAAA,cAChC;AAAA,cACA,WAAW,KAAK,KAAK,MAAM,GAAG,EAAE,SAAS;AAAA,cACzC,WAAW,KAAK;AAAA,cAChB,MAAM,KAAK;AAAA,YAAA;AAGZ,wBAAY,KAAK,WAAW;AAAA,UAC7B;AAEO,iBAAA;AAAA,YACN;AAAA,YACA,SAAS;AAAA,cACR,gBAAgB;AAAA,cAChB,WAAW;AAAA,cACX,cAAc;AAAA,cACd,aAAa;AAAA,cACb,aAAa;AAAA,cACb,OAAO;AAAA,YACR;AAAA,UAAA;AAAA,QACD,CACA;AAAA,MAAA;AAGF,YAAM,gBAAsD,CAAA;AAC5D,UAAI,cAA6B;AAEjC,iBAAW,SAAS,gBAAgB;AAC7B,cAAA,EAAE,SAAS,QAAY,IAAA;AAE7B,cAAM,gBAAgB,QAAQ,YAAY,IAAI,CAAC,MAAM,EAAE,QAAQ;AAC/D,cAAM,4BAA4B,QAAQ,YAAY,IAAI,CAAC,MAAM,EAAE,UAAU;AAC7E,cAAM,6BAA6B,QAAQ,YAAY,IAAI,CAAC,MAAM,EAAE,UAAU;AAE9E,cAAM,WAAW;AACb,YAAA;AAAa,mBAAS,KAAK,WAAW;AAE1C,cAAM4C,UAAS,CAAC,GAAG,2BAA2B,GAAG,4BAA4B,OAAO;AAE9E,cAAA,UAAU,KAAK,eAIlB;AAAA,UACF,aAAa;AAAA,UACb,QAAQ,WAAW;AAAA,UACnB,KAAK,oBAAoB,YAAY;AAAA,UACrC;AAAA,UACA;AAAA,UACA,QAAAA;AAAA,QAAA,CACA;AAED,aAAK,QAAQ,KAAK,CAAC,EAAE,qBAAqB;AACzC,eAAK,qBAAqB,cAAc;AAAA,QAAA,CACxC;AAEa,sBAAA;AAEd,sBAAc,KAAK,OAAO;AAAA,MAC3B;AAGA,WAAK,QAAQ,IAAI,aAAa,EAAE,KAAK,CAAC,YAAY;AACjD,cAAM,qBAAgD,CAAA;AACtD,cAAM,qBAA0D,CAAA;AAEhE,mBAAW,UAAU,SAAS;AAC7B,qBAAW,qBAAqB,OAAO;AAAa,+BAAmB,KAAK,iBAAiB;AAC7F,qBAAW,qBAAqB,OAAO;AAAa,+BAAmB,KAAK,iBAAiB;AAAA,QAC9F;AAEK,aAAA,SAAS,mBAAmB,kBAAkB,CAAC;AAC/C,aAAA,SAAS,6BAA6B,kBAAkB,CAAC;AAAA,MAAA,CAC9D;AAEM,aAAA;AAAA,IACR;AAAA,IAEA,MAAM,OACL,SASC;AACK,YAAA,EAAE,MAAM,IAAI,KAAK;AACjB,YAAA,QAAQ,MAAM;AAEpB,YAAM,wBAAwB,yBAAyB,QAAQ,UAAU,EAAE,KAAK;AAEhF,UAAI,CAAC,uBAAuB;AAC3B,cAAM,IAAI,MAAM,uCAAuC,QAAQ,UAAU,WAAW;AAAA,MACrF;AAEM,YAAA,EAAE,QAAQ,MAAM,IAAI,wBAAwB,QAAQ,UAAU,CAAA,CAAE;AAEtE,YAAM,oBAA4C;AAAA,QACjD,GAAG;AAAA,QACH,GAAG;AAAA;AAAA,QAEH,QAAQ;AAAA,UACP,GAAG,sBAAsB;AAAA,UACzB,GAAG;AAAA,QACJ;AAAA,MAAA;AAGI,WAAA,SAAS,qBAAqB,iBAAiB,CAAC;AAE/C,YAAA,UAAU,KAAK,eAA+B;AAAA,QACnD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,sBAAsB,kBAAkB,UAAU;AAAA,QACvD,SAAS;AAAA,QACT,UAAU,CAAC,kBAAkB,UAAU;AAAA,QACvC,QAAQ,CAAC,kBAAkB,UAAU;AAAA,MAAA,CACrC;AAED,YAAM,4BAA4B,kCAAkC,QAAQ,UAAU,EAAE,KAAK;AAC7F,YAAM,yCAAmD,CAAA;AAEzD,iBAAW,cAAc,2BAA2B;AAC/C,YAAA,WAAW,oBAAoB,OAAO;AACF,iDAAA,KAAK,WAAW,UAAU;AAAA,QAClE;AAAA,MACD;AAEA,YAAM,CAAC,kCAAkC,kBAAkB,IAAI,MAAM,KAAK;AAAA,QACzE,QAAQ;AAAA,QACR;AAAA,MAAA;AAGD,YAAM,2BAA2B,KAAK;AAAA,QACrC,QAAQ;AAAA,QACR;AAAA,MAAA;AAIC,cAAA,KAAK,CAAC,WAAW;AACZ,aAAA,SAAS,kBAAkB,MAAM,CAAC;AAAA,MAAA,CACvC,EACA,MAAM,MAAM;AACP,aAAA,SAAS,kBAAkB,qBAAqB,CAAC;AAAA,MAAA,CACtD;AAEK,aAAA;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,IAEF;AAAA,IAEA,MAAM,OAAO,cAA0C;AAChD,YAAA,EAAE,MAAM,IAAI,KAAK;AACjB,YAAA,QAAQ,MAAM;AAEpB,YAAM,wBAAwB,yBAAyB,YAAY,EAAE,KAAK;AAE1E,UAAI,CAAC,uBAAuB;AAC3B,cAAM,IAAI,MAAM,uCAAuC,YAAY,WAAW;AAAA,MAC/E;AAEA,YAAM,wBAAwB,kCAAkC,YAAY,EAAE,KAAK;AAE9E,WAAA,SAAS,qBAAqB,YAAY,CAAC;AAC3C,WAAA,SAAS,qCAAqC,EAAE,CAAC;AACjD,WAAA,SAAS,gCAAgC,sBAAsB,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAEzF,UAAA;AAGI,eAAA,MAAM,KAAK,eAA0B;AAAA,UAC3C,aAAa;AAAA,UACb,QAAQ,WAAW;AAAA,UACnB,KAAK,sBAAsB,YAAY;AAAA,UACvC,UAAU,CAAC,YAAY;AAAA,UACvB,QAAQ,CAAC;AAAA,QAAA,CACT;AAAA,eACO,GAAG;AACN,aAAA,SAAS,qCAAqC,CAAC,CAAC;AAChD,aAAA,SAAS,kBAAkB,qBAAqB,CAAC;AACjD,aAAA,SAAS,6BAA6B,qBAAqB,CAAC;AAC3D,cAAA;AAAA,MACP;AAAA,IACD;AAAA,IAEA,MAAM,aAAa,WAAkC;AAC9C,YAAA,cAAc,MAAM,KAAK,eAAiC;AAAA,QAC/D,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,qBAAqB,SAAS;AAAA,QACnC,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AAEI,WAAA,SAAS,0BAA0B,WAAW,CAAC;AAE9C,YAAA,cAAc,MAAM,KAAK,eAA2C;AAAA,QACzE,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,qBAAqB,SAAS;AAAA,QACnC,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AAEI,WAAA,SAAS,oCAAoC,WAAW,CAAC;AAAA,IAC/D;AAAA,EACD;AAAA,EC1hBO,MAAe,yBAGZ,eAA6B;AAAA,IACtC,IAAI,WAAiE;AAC9D,YAAA,EAAE,MAAM,IAAI,KAAK;AACjB,YAAA,mBAAmB,QAAQ,SAAS;AACrC,WAAA,SAAS,aAAa,gBAAgB,CAAC;AACtC,YAAA,UAAU,KAAK,eAA0B;AAAA,QAC9C,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,MAAM,SAAS,EAAE,eAAe,eAAe;AAAA,QACjE,SAAS;AAAA,QACT,UAAU,CAAC,eAAe;AAAA,QAC1B,QAAQ,CAAC,iBAAiB,UAAU;AAAA,MAAA,CACpC;AAEI,WAAA,QACH,KAAK,CAAC,WAAW;AACZ,aAAA,SAAS,gBAAgB,MAAM,CAAC;AAAA,MAAA,CACrC,EACA,MAAM,MAAM;AACZ,aAAK,SAAS,gBAAgB,iBAAiB,UAAU,CAAC;AAAA,MAAA,CAC1D;AAEK,aAAA,CAAC,kBAAkB,OAAO;AAAA,IAClC;AAAA,IAEA,OAAO,WAAwD;AACzD,WAAA,SAAS,aAAa,SAAS,CAAC;AAC/B,YAAA,UAAU,KAAK,eAA0B;AAAA,QAC9C,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,eAAe,UAAU,UAAU;AAAA,QACxC,SAAS;AAAA,QACT,UAAU,CAAC,UAAU,UAAU;AAAA,QAC/B,QAAQ,CAAC,UAAU,UAAU;AAAA,MAAA,CAC7B;AAEM,aAAA,CAAC,WAAW,OAAO;AAAA,IAC3B;AAAA,IAEA,OAAO,aAAyC;AACzC,YAAA,EAAE,MAAM,IAAI,KAAK;AACjB,YAAA,UAAU,KAAK,eAA0B;AAAA,QAC9C,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,eAAe,WAAW;AAAA,QAC/B,UAAU,CAAC,WAAW;AAAA,QACtB,QAAQ,CAAC;AAAA,MAAA,CACT;AACD,YAAM,oBAAoB,MAAM,SAAA,EAAW,iBAAiB,UAAU,WAAW;AAC5E,WAAA,SAAS,gBAAgB,WAAW,CAAC;AACrC,WAAA,QACH,KAAK,MAAM;AAAA,MAAA,CAIX,EACA,MAAM,CAAC,WAAW;AAClB,YAAI,mBAAmB;AACjB,eAAA,SAAS,aAAa,iBAAiB,CAAC;AAAA,QAC9C;AACM,cAAA;AAAA,MAAA,CACN;AACK,aAAA;AAAA,IACR;AAAA,IAEA,MAAM,aAAa,WAAuC;AACnD,YAAA,SAAS,MAAM,KAAK,eAA4B;AAAA,QACrD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS;AAAA,QAC3B,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AACI,WAAA,SAAS,qBAAqB,MAAM,CAAC;AAAA,IAC3C;AAAA,EACD;AAAA,EC1EO,MAAe,kCAGZ,eAA6B;AAAA,IACtC,MAAM,OAAO,oBAAqE;AAC3E,YAAA,UAAU,KAAK,eAA4C;AAAA,QAChE,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,kBAAkB,mBAAmB,YAAY,WAAW,mBAAmB,UAAU;AAAA,QAC9F,SAAS;AAAA,QACT,UAAU,CAAC,mBAAmB,UAAU;AAAA,QACxC,QAAQ,CAAC,mBAAmB,UAAU;AAAA,MAAA,CACtC;AAEI,WAAA,QAAQ,KAAK,MAAM;AAClB,aAAA,SAAS,yBAAyB,kBAAkB,CAAC;AAAA,MAAA,CAC1D;AAEM,aAAA;AAAA,IACR;AAAA,IAEA,MAAM,OAAO,oBAA4D;AACxE,WAAK,SAAS,yBAAyB,mBAAmB,UAAU,CAAC;AACrE,WAAK,SAAS,WAAW,mBAAmB,IAAI,CAAC;AACjD,aAAO,KAAK,eAA0B;AAAA,QACrC,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,kBAAkB,mBAAmB,YAAY,WAAW,mBAAmB,UAAU;AAAA,QAC9F,UAAU,CAAC,mBAAmB,UAAU;AAAA,QACxC,QAAQ,CAAC;AAAA,MAAA,CACT;AAAA,IACF;AAAA,IAEA,MAAM,aAAa,gBAAuC;AACnD,YAAA,SAAS,MAAM,KAAK,eAAqC;AAAA,QAC9D,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,kBAAkB,cAAc;AAAA,QACrC,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AAEI,WAAA,SAAS,+BAA+B,MAAM,CAAC;AAAA,IACrD;AAAA,EACD;ACjBA,QAAM,wBAAmE,CAAA;AAEzE,QAAM,kCAAkB;AAGxB,MAAI,oBAAoB;AACxB,MAAI,sBAAsB;AAC1B,MAAI,cAAc;AAClB,QAAM,iBAAiB;AAAA,EAGhB,MAAe,oBAA4E,eAGhG;AAAA,IAHK;AAAA;AAIN,kCAAO,CAAA,EAAgB;AAGf;AAAA;AAAA,wCAAaW,IAAAA,OAAoB,aAAa,GAAG;AAAA,QACxD,QAAQ,IAAI;AACX,aAAG,kBAAkB,OAAO;AAAA,QAC7B;AAAA,MAAA,CACA;AAAA;AAAA,IAED,MAAc,eAAe,MAAyC;AACrE,YAAM,OAAO,MAAM,KAAK,WAAW,IAAI;AACvC,UAAI,CAAC;AAAM,cAAM,IAAI,MAAM,kBAAkB,IAAI,qBAAqB;AACtE,YAAM,MAAM,MAAM,aAAa,MAAM,IAAI;AAEnC,YAAA,cAAc,MAAM,KAAK,eAAiC;AAAA,QAC/D,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK;AAAA,QACL,aAAa;AAAA,UACZ,MAAM,MAAM,SAAS,IAAI;AAAA,UACzB,WAAW,KAAK;AAAA,UAChB,WAAW,KAAK,KAAK,MAAM,GAAG,EAAE,IAAI;AAAA,UACpC,MAAM,KAAK,KAAK,SAAS;AAAA,QAC1B;AAAA,QACA,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC,MAAM,GAAG,EAAE;AAAA,MAAA,CACpB;AAED,UAAI,SAAS,aAAa;AAEzB,aAAK,SAAS,aAAa,EAAE,MAAM,GAAG,YAAa,CAAA,CAAC;AAAA,MACrD;AACO,aAAA;AAAA,IACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQA,MAAM,SAAS,MAAY,MAA6B;AACnD,UAAA,YAAY,IAAI,IAAI,GAAG;AAC1B;AAAA,MACD;AAEI,UAAA,CAAC,KAAK,MAAM;AACf,cAAM,QAAQ,KAAK,KAAK,MAAM,GAAG;AACjC,cAAM,YAAY,MAAM,MAAM,SAAS,CAAC;AACjC,eAAA,IAAI,KAAK,CAAC,IAAI,GAAG,KAAK,MAAM,EAAE,MAAM,UAAA,CAAW;AAAA,MACvD;AACI,UAAA,CAAC,KAAK,QAAQ,CAAC,KAAK,QAAQ,CAAC,KAAK,MAAM;AACrC,cAAA,IAAI,MAAM,mEAAmE;AAAA,MACpF;AACM,YAAA,cAAyC,MAAM,KAAK;AAE1D,YAAM,gBAAgB,CAAC,CAAE,MAAM,YAAY,IAAI,SAAS,IAAI;AAC5D,UAAI,CAAC,eAAe;AACnB,cAAM,YAAY,IAAI,SAAS,MAAM,IAAI;AACzC;AAAA,MAAA,OACM;AACN,gBAAQ,MAAM,2DAA2D,KAAK,MAAM,IAAI;AACxF;AAAA,MACD;AACA,kBAAY,IAAI,IAAI;AACpB;AACI,UAAA,cAAc,mBAAmB,GAAG;AAI/B,gBAAA;AAAA,UACP,uBACI,iBAAiB,aAAa,mBAAmB,YAChD,qBAAqB,oBAAoB,uBAAwB,GAAG,mBACrE,WAAW;AAAA,QAAA;AAAA,MAEjB;AAAA,IACD;AAAA,IAEA,MAAM,YAAY,MAA6B;AAC9C,aAAO,MAAM,KAAK,YAAY,OAAO,SAAS,IAAI;AAClD,kBAAY,OAAO,IAAI;AAAA,IACxB;AAAA,IAEA,MAAM,WAAW,MAAyC;AACzD,cAAQ,MAAM,KAAK,YAAY,IAAI,SAAS,IAAI;AAAA,IACjD;AAAA,IAEA,MAAM,oBAAoB,MAAyC;AAClE,YAAM,QAAQ,KAAK,OAAO,MAAM,SAAS;AACzC,YAAM,YAAY,gBAAgB,IAAI,EAAE,KAAK;AAE7C,aAAO,aAAc,MAAM,KAAK,eAAe,IAAI;AAAA,IACpD;AAAA;AAAA,IAGA,MAAM,eAAe,MAAqE;AACzF,YAAM,OAAO,MAAM,KAAK,WAAW,IAAI;AAEvC,UAAI,CAAC;AAAM,cAAM,IAAI,MAAM,kBAAkB,IAAI,qBAAqB;AAEtE,YAAM,MAAM,MAAM,aAAa,MAAM,IAAI;AACzC,YAAM,mBAA2C;AAAA,QAChD,WAAW,KAAK;AAAA,QAChB,WAAW;AAAA,QACX,MAAM;AAAA,MAAA;AAEP,YAAM,wBAA0C,MAAM,KAAK,oBAAoB,IAAI;AAEnF,UAAI,aAAa,uBAAuB;AACnC,YAAA,sBAAsB,YAAY,oBAAoB;AACzD,iBAAO,CAAC,kBAAkB,QAAQ,QAAQ,MAAS,EAAE,MAAM;AAAA,QAC5D;AACM,cAAA,IAAI,MAAM,sBAAsB,OAAO;AAAA,MAC9C;AAEA,YAAM,MAAM,sBAAsB;AAC5B,YAAA,UAAU,KAAK,eAA0B;AAAA,QAC9C;AAAA,QACA,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,eAAe;AAAA,QACf,cAAc;AAAA,QACd,gBAAgB;AAAA,QAChB,UAAU,CAAC,MAAM,GAAG,EAAE;AAAA,QACtB,QAAQ,CAAC,IAAI;AAAA,QACb,OAAO;AAAA,MAAA,CACc;AAEf,aAAA,CAAC,kBAAkB,OAAO;AAAA,IAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAYA,MAAM,iBAAiB,KAAa,cAAsB,gBAAoD;AAC7G,YAAM,kBAA0B,IAAI,MAAM,GAAG,EAAE,CAAC,KAAK;AAErD,YAAM,eAAe,MAAM,KAAK,WAAW,YAAY;AAEvD,UAAI,cAAc;AACb,YAAA,CAAC,aAAa,MAAM;AACjB,gBAAA,IAAI,MAAM,uCAAuC;AAAA,QACxD;AACO,eAAA;AAAA,MACR;AAEI,UAAA,IAAI,WAAW,OAAO,GAAG;AACtB,cAAA,OAAO,MAAM,WAAW,GAAG;AACjC,cAAMC,QAAO,IAAI,KAAK,CAAC,IAAI,GAAG,kBAAkB,cAAc,EAAE,MAAM,KAAK,KAAM,CAAA;AAC3E,cAAA,KAAK,SAASA,OAAM,YAAY;AAC/BA,eAAAA;AAAAA,MACR;AAEI,UAAA,UAAU,sBAAsB,eAAe;AACnD,UAAI,iBAAiB;AAErB,UAAI,CAAC,SAAS;AACH,kBAAA,IAAI,QAAQ,CAAC,YAAY;AAClC,eAAK,KAAK,eAAqB;AAAA,YAC9B,aAAa;AAAA,YACb,QAAQ,WAAW;AAAA,YACnB;AAAA;AAAA;AAAA,YAGA,eAAe;AAAA,YACf,gBAAgB;AAAA,YAChB,cAAc;AAAA,YACd,UAAU,CAAC,YAAY;AAAA,YACvB,QAAQ,CAAC,YAAY;AAAA,UAAA,CACrB,EAAE,KAAK,CAAC,SAAS;AACjB,kBAAM,aAAa,IAAI,KAAK,CAAC,IAAI,GAAG,kBAAkB,cAAc,EAAE,MAAM,KAAK,KAAM,CAAA;AACvF,oBAAQ,UAAU;AAAA,UAAA,CAClB;AAAA,QAAA,CACD;AACD,8BAAsB,eAAe,IAAI;AAAA,MAAA,OACnC;AACW,yBAAA;AAAA,MAClB;AAEI,UAAA;AAEA,UAAA;AACH,eAAO,MAAM;AAAA,eACL,GAAG;AACP,YAAA,kBAAkB,aAAa,UAAU;AAE5C,iBAAO,sBAAsB,eAAe;AAAA,QAC7C;AACM,cAAA;AAAA,MACP;AAEA,UAAI,gBAAgB;AAGb,cAAA,aAAa,MAAM,SAAS,IAAI;AACtC,YAAI,eAAe,cAAc;AAC1B,gBAAA,UAAU,kDAAkD,UAAU;AAAA,sBAC1D,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAOxB,gBAAA,IAAI,MAAM,OAAO;AAAA,QACxB;AAGA,cAAM,YAAY,KAAK,KAAK,MAAM,GAAG,EAAE,CAAC;AACxC,YAAI,CAAC,WAAW;AACT,gBAAA,IAAI,MAAM,uBAAuB;AAAA,QACxC;AACM,cAAA,WAAW,kBAAkB,aAAa,MAAM;AAE/C,eAAA,eAAe,MAAM,QAAQ;AAEhC,YAAA,CAAC,KAAK,MAAM;AACT,gBAAA,IAAI,MAAM,2BAA2B;AAAA,QAC5C;AAEM,cAAA,KAAK,SAAS,MAAM,UAAU;AAGpC,8BAAsB,eAAe,IAAI,IAAI,QAAQ,CAAC,YAAY;AACjE,kBAAQ,IAAI;AAAA,QAAA,CACZ;AAAA,MACF;AAEO,aAAA;AAAA,IACR;AAAA,EACD;AAAA,ECjSO,MAAe,iCAGZ,eAA6B;AAAA,IACtC,MAAM,oBAAoB,kBAAqD;AAC9E,aAAO,KAAK,eAAiC;AAAA,QAC5C,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,oCAAoC,gBAAgB;AAAA,QACzD,cAAc;AAAA,QACd,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AAAA,IACF;AAAA,IAEA,yBACC,kBACA,UAAgD,QACb;AACnC,aAAO,KAAK,eAAwC;AAAA,QACnD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,oCAAoC,gBAAgB;AAAA,QACzD,cAAc;AAAA,QACd;AAAA,QACA,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AAAA,IACF;AAAA,EACD;AAAA,EC5BO,MAAe,4BAGZ,eAA6B;AAAA,IACtC,MAAM,IAAI,OAAe,OAAmC;AAC3D,aAAO,KAAK,eAA0B;AAAA,QACrC,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,kBAAkB,KAAK;AAAA,QAC5B,SAAS,EAAE,MAAM;AAAA,QACjB,UAAU,CAAC,MAAM,SAAA,GAAY,YAAY;AAAA,QACzC,QAAQ,CAAC;AAAA,MAAA,CACT;AAAA,IACF;AAAA,IAEA,MAAM,OAAO,aAA8C;AAC1D,WAAK,SAAS,kBAAkB,YAAY,UAAU,CAAC;AACvD,aAAO,KAAK,eAA0B;AAAA,QACrC,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,kBAAkB,YAAY,YAAY,kBAAkB,YAAY,UAAU;AAAA,QACvF,UAAU,CAAC,YAAY,MAAM;AAAA,QAC7B,QAAQ,CAAC;AAAA,MAAA,CACT,EAAE,MAAM,CAAC,MAAM;AACV,aAAA,SAAS,eAAe,WAAW,CAAC;AACnC,cAAA;AAAA,MAAA,CACN;AAAA,IACF;AAAA,IAEA,MAAM,aAAa,gBAA4C;AACxD,YAAA,SAAS,MAAM,KAAK,eAA8B;AAAA,QACvD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,kBAAkB,cAAc;AAAA,QACrC,UAAU,CAAC,eAAe,UAAU;AAAA,QACpC,QAAQ,CAAC;AAAA,MAAA,CACT;AAEI,WAAA,SAAS,uBAAuB,MAAM,CAAC;AAAA,IAC7C;AAAA,EACD;AAAA,ECxCO,MAAe,4BAGZ,eAA6B;AAAA,IACtC,OAAO,MAAqC;AAC3C,aAAO,KAAK,eAA6B;AAAA,QACxC,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK;AAAA,QACL,SAAS,EAAE,KAAK;AAAA,QAChB,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC,WAAW,IAAI,IAAI,YAAY;AAAA,MAAA,CACxC;AAAA,IACF;AAAA,IAEA,MAAM,OAAO,cAAmD;AAC/D,aAAO,KAAK,eAA6B;AAAA,QACxC,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,kBAAkB,aAAa,EAAE;AAAA,QACtC,SAAS;AAAA,QACT,UAAU,CAAC,WAAW,aAAa,IAAI,IAAI,aAAa,GAAG,UAAU;AAAA,QACrE,QAAQ,CAAC,aAAa,GAAG,UAAU;AAAA,MAAA,CACnC;AAAA,IACF;AAAA,IAEA,MAAM,OAAO,gBAAwB,OAAmC;AACvE,aAAO,KAAK,eAA0B;AAAA,QACrC,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,kBAAkB,cAAc,WAAW,KAAK;AAAA,QACrD,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AAAA,IACF;AAAA,IAEA,MAAM,aAAa,WAAmB,gBAAuC;AAC5E,YAAM,sBAAoD,CAAA;AAEpD,YAAA,uBAAuB,MAAM,KAAK,eAA+B;AAAA,QACtE,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS;AAAA,QAC3B,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AAED,iBAAWC,iBAAgB,sBAAsB;AAC5BA,4BAAAA,cAAa,EAAE,IAAIA;AAAAA,MACxC;AAEM,YAAA,eAAe,MAAM,KAAK,eAA6B;AAAA,QAC5D,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,kBAAkB,cAAc;AAAA,QACrC,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AAEmB,0BAAA,aAAa,EAAE,IAAI;AAEvC,WAAK,SAAS,iBAAiB,OAAO,OAAO,mBAAmB,CAAC,CAAC;AAAA,IACnE;AAAA,EACD;AAAA,EC/DO,MAAe,uBAGZ,eAA6B;AAAA,IACtC,MAAM,WAAW,SAAoC;AAC9C,YAAA,SAAS,MAAM,KAAK,eAAwB;AAAA,QACjD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,YAAY,QAAQ,UAAU;AAAA,QACnC,cAAc;AAAA,QACd,UAAU;AAAA,UACT,QAAQ,qBACL,QAAQ,mBAAmB,SAC3B,IAAA,QAAQ,aACR,QAAQ,WAAW,SACnB,IAAA;AAAA,QACJ;AAAA,QACA,QAAQ,CAAC;AAAA,MAAA,CACT;AACI,WAAA,SAAS,cAAc,MAAM,CAAC;AAC5B,aAAA;AAAA,IACR;AAAA,IAEA,MAAM,aAAa,SAAoC;AAChD,YAAA,SAAS,MAAM,KAAK,eAAwB;AAAA,QACjD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,YAAY,QAAQ,UAAU;AAAA,QACnC,cAAc;AAAA,QACd,UAAU;AAAA,UACT,QAAQ,qBACL,QAAQ,mBAAmB,SAC3B,IAAA,QAAQ,aACR,QAAQ,WAAW,SACnB,IAAA;AAAA,QACJ;AAAA,QACA,QAAQ,CAAC;AAAA,MAAA,CACT;AACI,WAAA,SAAS,cAAc,MAAM,CAAC;AAC5B,aAAA;AAAA,IACR;AAAA,IACA,MAAM,cAAc,SAAoC;AACjD,YAAA,SAAS,MAAM,KAAK,eAAwB;AAAA,QACjD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,YAAY,QAAQ,UAAU;AAAA,QACnC,cAAc;AAAA,QACd,UAAU;AAAA,UACT,QAAQ,qBACL,QAAQ,mBAAmB,SAC3B,IAAA,QAAQ,aACR,QAAQ,WAAW,SACnB,IAAA;AAAA,QACJ;AAAA,QACA,QAAQ,CAAC;AAAA,MAAA,CACT;AACI,WAAA,SAAS,cAAc,MAAM,CAAC;AAC5B,aAAA;AAAA,IACR;AAAA,IAEA,MAAM,cAAc,SAAoC;AACjD,YAAA,SAAS,MAAM,KAAK,eAAwB;AAAA,QACjD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,YAAY,QAAQ,UAAU;AAAA,QACnC,cAAc;AAAA,QACd,UAAU;AAAA,UACT,QAAQ,qBACL,QAAQ,mBAAmB,SAC3B,IAAA,QAAQ,aACR,QAAQ,WAAW,SACnB,IAAA;AAAA,QACJ;AAAA,QACA,QAAQ,CAAC;AAAA,MAAA,CACT;AACI,WAAA,SAAS,cAAc,MAAM,CAAC;AAC5B,aAAA;AAAA,IACR;AAAA,IAEA,MAAM,uBAAuB,SAAkB,SAAoC;AAC5E,YAAA,SAAS,MAAM,KAAK,eAAwB;AAAA,QACjD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,YAAY,QAAQ,UAAU;AAAA,QACnC,cAAc;AAAA,QACd,SAAS,EAAE,SAAS,QAAQ,GAAG;AAAA,QAC/B,UAAU;AAAA,UACT,QAAQ,qBACL,QAAQ,mBAAmB,SAC3B,IAAA,QAAQ,aACR,QAAQ,WAAW,SACnB,IAAA;AAAA,UACH,QAAQ,KAAK,QAAQ,GAAG,SAAa,IAAA;AAAA,QACtC;AAAA,QACA,QAAQ,CAAC,aAAa,kBAAkB,uBAAuB,eAAe;AAAA,MAAA,CAC9E;AACI,WAAA,SAAS,cAAc,MAAM,CAAC;AAC5B,aAAA;AAAA,IACR;AAAA,IAEA,MAAM,yBAAyB,SAAoC;AAC5D,YAAA,SAAS,MAAM,KAAK,eAAwB;AAAA,QACjD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,YAAY,QAAQ,UAAU;AAAA,QACnC,cAAc;AAAA,QACd,UAAU;AAAA,UACT,QAAQ,qBACL,QAAQ,mBAAmB,SAC3B,IAAA,QAAQ,aACR,QAAQ,WAAW,SACnB,IAAA;AAAA,QACJ;AAAA,QACA,QAAQ,CAAC,aAAa,kBAAkB,uBAAuB,eAAe;AAAA,MAAA,CAC9E;AACI,WAAA,SAAS,cAAc,MAAM,CAAC;AAC5B,aAAA;AAAA,IACR;AAAA,IAEA,MAAM,qBAAqB,SAAwC;AAC3D,aAAA,MAAM,KAAK,eAA4B;AAAA,QAC7C,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,YAAY,QAAQ,UAAU;AAAA,QACnC,cAAc;AAAA,QACd,UAAU,CAAC,QAAQ,UAAU;AAAA,QAC7B,QAAQ,CAAC,QAAQ,UAAU;AAAA,MAAA,CAC3B;AAAA,IACF;AAAA,IAEA,MAAM,aAAa,WAAmB,gBAAuC;AAC5E,YAAM,iBAA0C,CAAA;AAE1C,YAAA,uBAAuB,MAAM,KAAK,eAA0B;AAAA,QACjE,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,kBAAkB,cAAc;AAAA,QACrC,cAAc;AAAA,QACd,UAAU,CAAC,eAAe,UAAU;AAAA,QACpC,QAAQ,CAAC,aAAa,kBAAkB,uBAAuB,eAAe;AAAA,MAAA,CAC9E;AAED,iBAAW,WAAW,sBAAsB;AAC5B,uBAAA,QAAQ,UAAU,IAAI;AAAA,MACtC;AAEM,YAAA,kBAAkB,MAAM,KAAK,eAA0B;AAAA,QAC5D,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS;AAAA,QAC3B,cAAc;AAAA,QACd,UAAU,CAAC,UAAU,UAAU;AAAA,QAC/B,QAAQ,CAAC,aAAa,kBAAkB,uBAAuB,eAAe;AAAA,MAAA,CAC9E;AAED,iBAAW,WAAW,iBAAiB;AACvB,uBAAA,QAAQ,UAAU,IAAI;AAAA,MACtC;AAEA,WAAK,SAAS,mBAAmB,OAAO,OAAO,cAAc,CAAC,CAAC;AAAA,IAChE;AAAA,EACD;AAAA,ECxJO,MAAe,wBAGZ,eAA6B;AAAA,IACtC,IAAI,SAA2D;AACxD,YAAA,EAAE,MAAM,IAAI,KAAK;AACvB,YAAM,gBAAgB,MAAM,SAAS,EAAE,YAAY,YAAY;AAC/D,YAAM,eAAc,oBAAI,KAAK,GAAE,YAAY;AAE3C,YAAM,kBAAoC,QAAQ;AAAA,QACjD,GAAG;AAAA,QACH,YAAY;AAAA,QACZ,cAAc;AAAA,MAAA,CACd;AAED,WAAK,SAAS,aAAa,CAAC,eAAe,CAAC,CAAC;AACvC,YAAA,UAAU,KAAK,eAAyB;AAAA,QAC7C,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK;AAAA,QACL,SAAS;AAAA,QACT,aAAa;AAAA,UACZ,iBAAiB,gBAAgB,mBAAmB;AAAA,QACrD;AAAA;AAAA,QAEA,UAAU,gBAAgB,kBAAkB,CAAC,gBAAgB,eAAe,IAAI,CAAC;AAAA,QACjF,QAAQ,CAAC,gBAAgB,UAAU;AAAA,MAAA,CACnC;AAED,cAAQ,MAAM,MAAM;AACnB,aAAK,SAAS,gBAAgB,CAAC,gBAAgB,UAAU,CAAC,CAAC;AAAA,MAAA,CAC3D;AAEM,aAAA,CAAC,iBAAiB,OAAO;AAAA,IACjC;AAAA,IAEA,OAAOtB,WAAyE;AACzE,YAAA,EAAE,MAAM,IAAI,KAAK;AACvB,YAAM,sBAAsB,MAAM,WAAW,iBAAiB,UAAUA,UAAS,UAAU;AAC3F,UAAI,CAAC,qBAAqB;AACzB,cAAM,IAAI;AAAA,UACT,mDAAmDA,UAAS,UAAU;AAAA,QAAA;AAAA,MAExE;AACA,WAAK,SAAS,gBAAgB,CAACA,SAAQ,CAAC,CAAC;AACnC,YAAA,UAAU,KAAK,eAAyB;AAAA,QAC7C,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,cAAcA,UAAS,UAAU;AAAA,QACtC,SAASA;AAAA,QACT,UAAU,CAACA,UAAS,UAAU;AAAA,QAC9B,QAAQ,CAACA,UAAS,UAAU;AAAA,MAAA,CAC5B;AAED,cAAQ,MAAM,MAAM;AACH,wBAAA,CAAC,mBAAmB,CAAC;AAAA,MAAA,CACrC;AAED,YAAM,eAAe,MAAM,WAAW,iBAAiB,UAAUA,UAAS,UAAU;AAE7E,aAAA,CAAC,cAAc,OAAO;AAAA,IAC9B;AAAA,IAEA,KAAK,YAAoB,kBAAiC,UAA6C;AAChG,YAAA,EAAE,MAAM,IAAI,KAAK;AACvB,YAAM,mBAAmB,uBAAuB,MAAM,SAAU,CAAA;AAMhE,YAAM,+BAA2C,CAAA;AAE3C,YAAA,qBAAqB,iBAAiB,UAAU;AACtD,UAAI,CAAC,oBAAoB;AACxB,cAAM,IAAI;AAAA,UACT,iDAAiD,UAAU;AAAA,QAAA;AAAA,MAE7D;AACA,mCAA6B,KAAK,kBAAkB;AAEpD,UAAI,mBAAmB,iBAAiB;AACvC,qCAA6B,KAAK,iBAAiB,mBAAmB,eAAe,CAAE;AAAA,MACxF;AAEA,UAAI,kBAAkB;AACf,cAAA,iBAAiB,iBAAiB,gBAAgB;AACxD,YAAI,CAAC,gBAAgB;AACpB,gBAAM,IAAI;AAAA,YACT,2DAA2D,gBAAgB;AAAA,UAAA;AAAA,QAE7E;AACA,qCAA6B,KAAK,cAAc;AAEhD,YAAI,eAAe,iBAAiB;AACnC,uCAA6B,KAAK,iBAAiB,eAAe,eAAe,CAAE;AAAA,QACpF;AAAA,MACD;AAEA,WAAK,SAAS,aAAa,EAAE,YAAY,kBAAkB,SAAU,CAAA,CAAC;AAEhE,YAAA,UAAU,KAAK,eAA2B;AAAA,QAC/C,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,cAAc,UAAU;AAAA,QAC7B,aAAa;AAAA,UACZ,QAAQ,oBAAoB;AAAA,UAC5B;AAAA,QACD;AAAA,QACA,UAAU,CAAC,UAAU;AAAA,QACrB,QAAQ,CAAC;AAAA,MAAA,CACT;AAGC,cAAA,KAAK,CAAC,WAAW;AACZ,aAAA,SAAS,gBAAgB,MAAM,CAAC;AAAA,MAAA,CACrC,EACA,MAAM,MAAM;AACP,aAAA,SAAS,gBAAgB,4BAA4B,CAAC;AAAA,MAAA,CAC3D;AAEK,aAAA;AAAA,IACR;AAAA,IAEA,OAAO,YAAyC;AACzC,YAAA,EAAE,MAAM,IAAI,KAAK;AACvB,YAAM,mBAAmB,uBAAuB,MAAM,SAAU,CAAA;AAC1D,YAAA,sBAAsB,iBAAiB,UAAU;AACvD,UAAI,CAAC,qBAAqB;AACzB,cAAM,IAAI;AAAA,UACT,mDAAmD,UAAU;AAAA,QAAA;AAAA,MAE/D;AACA,YAAM,iBAAiB,oBAAoB,kBACxC,iBAAiB,oBAAoB,eAAe,IACpD;AAEH,WAAK,SAAS,gBAAgB,CAAC,UAAU,CAAC,CAAC;AACrC,YAAA,UAAU,KAAK,eAA2B;AAAA,QAC/C,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,cAAc,UAAU;AAAA,QAC7B,UAAU,CAAC,UAAU;AAAA,QACrB,QAAQ,CAAC;AAAA,MAAA,CACT;AAGC,cAAA,KAAK,CAAC,sBAAsB;AACvB,aAAA,SAAS,gBAAgB,iBAAiB,CAAC;AAAA,MAAA,CAChD,EACA,MAAM,MAAM;AACZ,aAAK,SAAS,gBAAgB,CAAC,mBAAmB,CAAC,CAAC;AACpD,YAAI,gBAAgB;AACnB,eAAK,SAAS,gBAAgB,CAAC,cAAc,CAAC,CAAC;AAAA,QAChD;AAAA,MAAA,CACA;AAEK,aAAA;AAAA,IACR;AAAA,IAEA,MAAM,aAAa,WAAmB,gBAAuC;AAGtE,YAAA,0BAA0B,KAAK,eAA2B;AAAA,QAC/D,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS;AAAA,QAC3B,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AAEK,YAAA,+BAA+B,KAAK,eAA2B;AAAA,QACpE,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,kBAAkB,cAAc;AAAA,QACrC,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AAGD,WAAK,SAAS,aAAa,MAAM,uBAAuB,CAAC;AAGzD,WAAK,SAAS,aAAa,MAAM,4BAA4B,CAAC;AAAA,IAC/D;AAAA,EACD;AAAA,ECxLO,MAAe,kCAGZ,sBAAgE;AAAA,IAHnE;AAAA;AAIN,6CAAkB,gBAAgB;AAElC,mDAAwB;AACxB,4CAAiB;AACjB,+CAAoB;AACpB,+CAAoB;AACpB,8CAAmB;AACnB,2CAAgB;AAEhB,8CAAmB;AAAA;AAAA,IAEX,uBAAuB,MAA0C;AACxE,aAAO,QAAQ;AAAA,QACd,MAAM,IAAI,gBAAgB,KAAK,IAAI;AAAA,QACnC,WAAW,KAAK;AAAA,QAChB,YAAY,KAAK;AAAA,QACjB,WAAW,KAAK,KAAK;AAAA,QACrB,WAAW,KAAK,KAAK;AAAA,QACrB,cAAc,KAAK;AAAA,QACnB,aAAa,KAAK;AAAA,QAClB,UAAU,KAAK;AAAA,MAAA,CACf;AAAA,IACF;AAAA,IAEA,MAAM,sBACL,OACA,YAC6D;AACtD,aAAA,KAAK,YAAY,OAAO,YAAY,KAAK,uBAAuB,KAAK,IAAI,CAAC;AAAA,IAClF;AAAA,IAEA,MAAM,yBAAyB,cAAqC;AAC5D,aAAA,KAAK,iBAAiB,YAAY;AAAA,IAC1C;AAAA,IAEA,MAAe,aAAa,WAAmB,gBAAuC;AAC/E,YAAA,6BAA6B,MAAM,KAAK,eAA8C;AAAA,QAC3F,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS;AAAA,QAC3B,QAAQ,CAAC;AAAA,QACT,UAAU,CAAC;AAAA,MAAA,CACX;AAED,WAAK,SAAS,KAAK,sBAAsB,0BAA0B,CAAC;AAE9D,YAAA,kCAAkC,MAAM,KAAK,eAA8C;AAAA,QAChG,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,kBAAkB,cAAc;AAAA,QACrC,QAAQ,CAAC;AAAA,QACT,UAAU,CAAC;AAAA,MAAA,CACX;AAED,WAAK,SAAS,KAAK,eAAe,+BAA+B,CAAC;AAAA,IACnE;AAAA,EACD;AAAA,ECrEO,MAAe,qBAGZ,eAA6B;AAAA,IACtC,MAAM,kBAAkB,QAAgD;AACvE,YAAM,kBAAkB,KAAK,OAAO,MAAM,WAAW,eAAe;AACpE,aAAO,KAAK,eAAsC;AAAA,QACjD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK;AAAA,QACL,SAAS;AAAA,UACR;AAAA,UACA,gBAAgB;AAAA,QACjB;AAAA,QACA,UAAU,CAAC,QAAQ;AAAA,QACnB,QAAQ,CAAC,QAAQ;AAAA,MAAA,CACjB,EAAE,KAAK,CAAC,aAAa;AAChB,aAAA,SAAS,gBAAgB,QAAQ,CAAC;AAChC,eAAA;AAAA,MAAA,CACP;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,MAAM,qBAAqB,QAAgB,gBAAoE;AACxG,YAAA,EAAE,MAAM,IAAI,KAAK;AACvB,YAAM,kBAAkB,MAAM,SAAS,EAAE,eAAe;AAExD,aAAO,KAAK,eAA8B;AAAA,QACzC,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK;AAAA,QACL,SAAS;AAAA,UACR;AAAA,UACA,gBAAgB;AAAA,QACjB;AAAA,QACA,UAAU,CAAC,QAAQ;AAAA,QACnB,QAAQ,CAAC,QAAQ;AAAA,QACjB,aAAa,EAAE,iBAAiB,eAAe;AAAA,MAAA,CAC/C,EAAE,KAAK,CAAC,aAAa;AACrB,cAAM,eAAe,MAAM,SAAA,EAAW,cAAc,UAAU,cAAc;AACxE,YAAA,EAAC,6CAAc,aAAY;AACxB,gBAAA,IAAI,MAAM,wBAAwB;AAAA,QACzC;AACA,YAAI,CAAC,MAAM,QAAQ,QAAQ,GAAG;AAC7B,qBAAW,CAAC,QAAQ;AAAA,QACrB;AACK,aAAA;AAAA,UACJ,mBAAmB;AAAA,YAClB,GAAG;AAAA,YACH,gBAAgB,CAAC,GAAI,aAAa,kBAAkB,CAAC,GAAI,GAAG,QAAQ;AAAA,UAAA,CACpE;AAAA,QAAA;AAAA,MACF,CACA;AAAA,IACF;AAAA,IAEA,MAAM,aAAa,gBAAoE;AACtF,aAAO,KAAK,eAAsC;AAAA,QACjD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,yBAAyB,cAAc;AAAA,QAC5C,UAAU,CAAC,cAAc;AAAA,QACzB,QAAQ,CAAC,cAAc;AAAA,MAAA,CACvB,EAAE,KAAK,CAAC,aAAa;AAChB,aAAA,SAAS,gBAAgB,QAAQ,CAAC;AAAA,MAAA,CACvC;AAAA,IACF;AAAA,IAEA,MAAM,KAAK,YAAoB,QAAmC;AACjE,aAAO,KAAK,eAA0B;AAAA,QACrC,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,qBAAqB,UAAU;AAAA,QACpC,SAAS,EAAE,OAAO;AAAA,QAClB,UAAU,CAAC,MAAM;AAAA,QACjB,QAAQ,CAAC,MAAM;AAAA,MAAA,CACf;AAAA,IACF;AAAA,IAEA,MAAM,aAAa,WAAkC;AAC9C,YAAA,SAAS,MAAM,KAAK,eAAwC;AAAA,QACjE,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS;AAAA,QAC3B,UAAU,CAAC,qBAAqB;AAAA,QAChC,QAAQ,CAAC,qBAAqB;AAAA,MAAA,CAC9B;AACI,WAAA,SAAS,wBAAwB,MAAM,CAAC;AAAA,IAC9C;AAAA,EACD;AAAA,EC3FO,MAAe,oBAAmF,eAGvG;AAAA,IACD,IAAI,aAA0B,gBAAqD;AAClF,YAAM,cAA+B,QAAQ;AAAA,QAC5C,GAAG;AAAA,QACH,cAAc;AAAA,QACd,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA;AAAA;AAAA,MAAA,CAGrC;AAEI,WAAA,SAAS,QAAQ,WAAW,CAAC;AAE5B,YAAA,UAAU,KAAK,eAAqB;AAAA,QACzC,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,kBAAkB,cAAc;AAAA,QACrC,SAAS;AAAA;AAAA,QAET,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC,YAAY,UAAU;AAAA,MAAA,CAC/B;AAGC,cAAA,KAAK,CAAC,gBAAgB;AACjB,aAAA,SAAS,QAAQ,WAAW,CAAC;AAAA,MAAA,CAClC,EACA,MAAM,MAAM;AACZ,aAAK,SAAS,WAAW,YAAY,UAAU,CAAC;AAAA,MAAA,CAChD;AAEK,aAAA,CAAC,aAAa,OAAO;AAAA,IAC7B;AAAA;AAAA,IAGA,OAAO,MAAiD;AACjD,YAAA,EAAE,MAAM,IAAI,KAAK;AAEvB,YAAM,kBAAkB,eAAe,KAAK,UAAU,EAAE,MAAM,UAAU;AAExE,UAAI,CAAC,iBAAiB;AACrB,cAAM,IAAI,MAAM,iCAAiC,KAAK,UAAU,WAAW;AAAA,MAC5E;AAEA,YAAM,qBAAsC;AAAA,QAC3C,GAAG;AAAA,QACH,GAAG;AAAA,MAAA;AAGC,WAAA,SAAS,WAAW,kBAAkB,CAAC;AAEtC,YAAA,UAAU,KAAK,eAAqB;AAAA,QACzC,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,wBAAwB,KAAK,UAAU;AAAA,QAC5C,SAAS;AAAA,QACT,UAAU,CAAC,KAAK,UAAU;AAAA,QAC1B,QAAQ,CAAC,KAAK,UAAU;AAAA,MAAA,CACxB;AAGC,cAAA,KAAK,CAAC,gBAAgB;AAEjB,aAAA,SAAS,QAAQ,WAAW,CAAC;AAAA,MAAA,CAClC,EACA,MAAM,MAAM;AACP,aAAA,SAAS,QAAQ,eAAe,CAAC;AAAA,MAAA,CACtC;AAEK,aAAA,CAAC,oBAAoB,OAAO;AAAA,IACpC;AAAA,IAEA,MAAM,OAAO,QAAoC;AAC1C,YAAA,EAAE,MAAM,IAAI,KAAK;AACjB,YAAA,QAAQ,MAAM;AAEpB,YAAM,OAAO,eAAe,MAAM,EAAE,KAAK;AAEzC,UAAI,CAAC,MAAM;AACV,cAAM,IAAI,MAAM,yBAAyB,MAAM,WAAW;AAAA,MAC3D;AAEK,WAAA,SAAS,WAAW,MAAM,CAAC;AAE5B,UAAA;AAGI,eAAA,MAAM,KAAK,eAA0B;AAAA,UAC3C,aAAa;AAAA,UACb,QAAQ,WAAW;AAAA,UACnB,KAAK,wBAAwB,MAAM;AAAA,UACnC,UAAU,CAAC,MAAM;AAAA,UACjB,QAAQ,CAAC,MAAM;AAAA,QAAA,CACf;AAAA,eACO,GAAG;AACN,aAAA,SAAS,QAAQ,IAAI,CAAC;AACrB,cAAA;AAAA,MACP;AAAA,IACD;AAAA,IAEA,MAAM,WAAW,QAAgB,SAA2C;AACrE,YAAA,EAAE,MAAM,IAAI,KAAK;AACvB,YAAM,OAAO,eAAe,MAAM,EAAE,MAAM,UAAU;AAEpD,UAAI,CAAC,MAAM;AACV,cAAM,IAAI,MAAM,yBAAyB,MAAM,WAAW;AAAA,MAC3D;AAEA,UAAI,QAAQ,WAAW,IAAI,IAAI,OAAO,EAAE,MAAM;AACvC,cAAA,IAAI,MAAM,qCAAqC;AAAA,MACtD;AAEA,WAAK,SAAS,WAAW,EAAE,GAAG,MAAM,QAAS,CAAA,CAAC;AAExC,YAAA,UAAU,KAAK,eAA0B;AAAA,QAC9C,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,wBAAwB,MAAM;AAAA,QACnC,SAAS;AAAA,UACR,OAAO;AAAA,QACR;AAAA,QACA,UAAU,CAAC,MAAM;AAAA,QACjB,QAAQ,CAAC,MAAM;AAAA,MAAA,CACf;AAED,cAAQ,MAAM,MAAM;AACd,aAAA,SAAS,QAAQ,IAAI,CAAC;AAAA,MAAA,CAC3B;AAEM,aAAA;AAAA,IACR;AAAA,IAEA,MAAM,WAAW,QAAgB,SAA2C;AACrE,YAAA,EAAE,MAAM,IAAI,KAAK;AACvB,YAAM,OAAO,eAAe,MAAM,EAAE,MAAM,UAAU;AAEpD,UAAI,CAAC,MAAM;AACV,cAAM,IAAI,MAAM,yBAAyB,MAAM,WAAW;AAAA,MAC3D;AAEA,YAAM,aAAa,CAAC,GAAG,KAAK,SAAS,GAAG,OAAO;AAExC,aAAA,KAAK,WAAW,QAAQ,UAAU;AAAA,IAC1C;AAAA,IAEA,MAAM,cAAc,QAAgB,SAA2C;AACxE,YAAA,EAAE,MAAM,IAAI,KAAK;AACvB,YAAM,OAAO,eAAe,MAAM,EAAE,MAAM,UAAU;AAEpD,UAAI,CAAC,MAAM;AACV,cAAM,IAAI,MAAM,yBAAyB,MAAM,WAAW;AAAA,MAC3D;AAEM,YAAA,aAAa,KAAK,QAAQ,OAAO,CAAC,WAAW,CAAC,QAAQ,SAAS,MAAM,CAAC;AAErE,aAAA,KAAK,WAAW,QAAQ,UAAU;AAAA,IAC1C;AAAA,IAEA,MAAM,aAAa,gBAAuC;AAGnD,YAAA,SAAS,MAAM,KAAK,eAAuB;AAAA,QAChD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,kBAAkB,cAAc;AAAA,QACrC,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AAEI,WAAA,SAAS,gBAAgB,MAAM,CAAC;AAAA,IACtC;AAAA,EACD;AAAA,EC/KO,MAAe,oBAAmF,eAGvG;AAAA,IACD,MAAM,aAAa,WAAmB,gBAAuC;AAC5E,YAAM,cAAoC,CAAA;AAEpC,YAAA,oBAAoB,MAAM,KAAK,eAAuB;AAAA,QAC3D,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,kBAAkB,cAAc;AAAA,QACrC,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AAED,iBAAW,QAAQ,mBAAmB;AACzB,oBAAA,KAAK,EAAE,IAAI;AAAA,MACxB;AAEM,YAAA,eAAe,MAAM,KAAK,eAAuB;AAAA,QACtD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS;AAAA,QAC3B,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AAED,iBAAW,QAAQ,cAAc;AACpB,oBAAA,KAAK,EAAE,IAAI;AAAA,MACxB;AAEA,WAAK,SAAS,SAAS,OAAO,OAAO,WAAW,CAAC,CAAC;AAAA,IACnD;AAAA,EACD;AAAA,ECqBO,MAAe,wBAGZ,kBAAgC;AAAA,IACzC,MAAM,IAAI,SAAoE;AACvE,YAAA,EAAE,MAAM,IAAI,KAAK;AAEvB,YAAM,EAAE,MAAM,GAAG,mBAAA,IAAuB;AAExC,YAAM,eAAc,oBAAI,KAAK,GAAE,YAAY;AAC3C,YAAM,cAAc,MAAM,SAAS,EAAE,YAAY;AACjD,YAAM,YAAY,mBAAmB;AAE/B,YAAA,OAAO,MAAM,SAAS,IAAI;AAEhC,YAAM,cAA2B;AAAA,QAChC;AAAA,QACA,WAAW,KAAK;AAAA,QAChB,WAAW,KAAK,KAAK,MAAM,GAAG,EAAE,IAAI;AAAA,QACpC,MAAM,KAAK;AAAA,MAAA;AAGZ,YAAM,kBAAoC,QAAQ;AAAA,QACjD,GAAG;AAAA,QACH,WAAW,KAAK;AAAA,QAChB,WAAW;AAAA,QACX,MAAM,IAAI,gBAAgB,IAAI;AAAA,QAC9B,cAAc;AAAA,QACd,YAAY,YAAY;AAAA,MAAA,CACxB;AAEK,YAAA,SAAS,YAAY,eAAe,CAAC;AAErC,YAAA,UAAU,KAAK,eAAqC;AAAA,QACzD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK;AAAA,QACL,SAAS;AAAA,UACR,YAAY,gBAAgB;AAAA,UAC5B,cAAc;AAAA,UACd,OAAO,gBAAgB;AAAA,UACvB,aAAa,gBAAgB;AAAA,UAC7B,YAAY,gBAAgB;AAAA,UAC5B,eAAe,gBAAgB;AAAA,UAC/B,MAAM,gBAAgB;AAAA,UACtB,SAAS,gBAAgB;AAAA,UACzB,WAAW,gBAAgB;AAAA,UAC3B,WAAW,gBAAgB;AAAA,UAC3B,eAAe,gBAAgB;AAAA,UAC/B,MAAM;AAAA,QACP;AAAA,QACA,QAAQ,CAAC,UAAU,UAAU;AAAA,QAC7B,UAAU,CAAC,UAAU,UAAU;AAAA,MAAA,CAC/B;AAGC,cAAA,KAAK,CAAC,WAAW;AACZ,aAAA,qBAAqB,OAAO,cAAc;AAC/C,cAAM,SAAS,YAAY,OAAO,SAAS,CAAC;AAAA,MAAA,CAC5C,EACA,MAAM,MAAM;AACZ,cAAM,SAAS,eAAe,gBAAgB,UAAU,CAAC;AAAA,MAAA,CACzD;AAEK,aAAA,CAAC,iBAAiB,QAAQ,KAAK,CAAC,WAAW,OAAO,SAAS,CAAC;AAAA,IACpE;AAAA,IAEA,MAAM,QACL,UACA,WACmD;AAC7C,YAAA,EAAE,MAAM,IAAI,KAAK;AAEvB,YAAM,eAAc,oBAAI,KAAK,GAAE,YAAY;AAC3C,YAAM,cAAc,MAAM,SAAS,EAAE,YAAY;AAEjD,YAAM,mBAA0C,CAAA;AAChD,YAAM,aAAuB,CAAA;AAC7B,YAAM,mBAA6D,CAAA;AACnE,YAAM,oBAAiD,CAAA;AAEvD,iBAAW,kBAAkB,UAAU;AACtC,cAAM,EAAE,MAAM,GAAG,QAAA,IAAY;AAEvB,cAAA,OAAO,MAAM,SAAS,IAAI;AAC5B,YAAA,EAAE,QAAQ,oBAAoB;AACjC,4BAAkB,IAAI,IAAI;AAAA,YACzB;AAAA,YACA,WAAW,KAAK;AAAA,YAChB,WAAW,KAAK,KAAK,MAAM,GAAG,EAAE,IAAI;AAAA,YACpC,MAAM,KAAK;AAAA,UAAA;AAEZ,gBAAM,KAAK,OAAO,MAAM,SAAS,MAAM,IAAI;AAAA,QAC5C;AAEA,cAAM,kBAAoC,QAAQ;AAAA,UACjD,GAAG;AAAA,UACH,WAAW,KAAK;AAAA,UAChB,WAAW;AAAA,UACX,MAAM,IAAI,gBAAgB,IAAI;AAAA,UAC9B,cAAc;AAAA,UACd,YAAY,YAAY;AAAA,UACxB,SAAS;AAAA,QAAA,CACT;AACD,yBAAiB,KAAK,eAAe;AAE1B,mBAAA,KAAK,gBAAgB,UAAU;AAE1C,yBAAiB,KAAK;AAAA,UACrB,YAAY,gBAAgB;AAAA,UAC5B,MAAM,gBAAgB;AAAA,UACtB,WAAW,gBAAgB;AAAA,UAE3B,OAAO,gBAAgB;AAAA,UACvB,aAAa,gBAAgB;AAAA,UAC7B,YAAY,gBAAgB;AAAA,UAC5B,eAAe,gBAAgB;AAAA,UAC/B,WAAW,gBAAgB;AAAA,UAC3B,eAAe,gBAAgB;AAAA,QAAA,CAC/B;AAAA,MACF;AAEM,YAAA,SAAS,aAAa,gBAAgB,CAAC;AAEvC,YAAA,UAAU,KAAK,eAA0C;AAAA,QAC9D,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK;AAAA,QACL,SAAS;AAAA,UACR,cAAc;AAAA,UACd,SAAS;AAAA,UACT,YAAY;AAAA,UACZ,OAAO,OAAO,OAAO,iBAAiB;AAAA,QACvC;AAAA,QACA,QAAQ,CAAC,UAAU,UAAU;AAAA,QAC7B,UAAU;AAAA,MAAA,CACV;AAGC,cAAA,KAAK,CAAC,WAAW;AACZ,aAAA,qBAAqB,OAAO,cAAc;AAC/C,cAAM,SAAS,aAAa,OAAO,UAAU,CAAC;AAAA,MAAA,CAC9C,EACA,MAAM,MAAM;AACN,cAAA,SAAS,gBAAgB,UAAU,CAAC;AAAA,MAAA,CAC1C;AAEK,aAAA,CAAC,kBAAkB,QAAQ,KAAK,CAAC,WAAW,OAAO,UAAU,CAAC;AAAA,IACtE;AAAA,IAEA,OAAO,SAA4G;AAC5G,YAAA,EAAE,MAAM,IAAI,KAAK;AACjB,YAAA,QAAQ,MAAM;AAEpB,YAAM,mBAAmB,mBAAmB,QAAQ,UAAU,EAAE,KAAK;AAErE,UAAI,CAAC,kBAAkB;AACtB,cAAM,IAAI,MAAM,6BAA6B,QAAQ,UAAU,8BAA8B;AAAA,MAC9F;AAEA,YAAM,kBAAoC,EAAE,GAAG,kBAAkB,GAAG,QAAQ;AAEtE,YAAA,SAAS,eAAe,eAAe,CAAC;AAExC,YAAA,UAAU,KAAK,eAAkC;AAAA,QACtD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,eAAe,QAAQ,UAAU;AAAA,QACtC;AAAA,QACA,QAAQ,CAAC,QAAQ,UAAU;AAAA,QAC3B,UAAU,CAAC,QAAQ,UAAU;AAAA,MAAA,CAC7B;AAGC,cAAA,KAAK,CAAC,WAAW;AACX,cAAA,SAAS,YAAY,MAAM,CAAC;AAAA,MAAA,CAClC,EACA,MAAM,MAAM;AACN,cAAA,SAAS,YAAY,gBAAgB,CAAC;AAAA,MAAA,CAC5C;AAEK,aAAA,CAAC,iBAAiB,OAAO;AAAA,IACjC;AAAA,IAEA,MAAM,OAAO,YAAmC;AACzC,YAAA,EAAE,MAAM,IAAI,KAAK;AACjB,YAAA,QAAQ,MAAM;AAEpB,YAAM,mBAAmB,mBAAmB,UAAU,EAAE,KAAK;AAE7D,UAAI,CAAC,kBAAkB;AACtB,cAAM,IAAI,MAAM,6BAA6B,UAAU,8BAA8B;AAAA,MACtF;AAEM,YAAA,SAAS,eAAe,UAAU,CAAC;AAEnC,YAAA,UAAU,KAAK,eAA0B;AAAA,QAC9C,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,eAAe,UAAU;AAAA,QAC9B,QAAQ,CAAC,UAAU;AAAA,QACnB,UAAU,CAAC,UAAU;AAAA,MAAA,CACrB;AAED,cAAQ,MAAM,MAAM;AACb,cAAA,SAAS,YAAY,gBAAgB,CAAC;AAAA,MAAA,CAC5C;AAEM,aAAA;AAAA,IACR;AAAA,IAEA,MAAM,aAAa,WAAkC;AAC9C,YAAA,EAAE,MAAM,IAAI,KAAK;AAEjB,YAAA,SAAS,MAAM,KAAK,eAAoC;AAAA,QAC7D,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,aAAa,SAAS;AAAA,QAC3B,QAAQ,CAAC,UAAU,UAAU;AAAA,QAC7B,UAAU,CAAC;AAAA,MAAA,CACX;AAEK,YAAA,SAAS,oBAAoB,MAAM,CAAC;AAAA,IAC3C;AAAA,EACD;AAAA,EC7QO,MAAe,gCAGZ,kBAAgC;AAAA,IACzC,IAAI,SAA6E;AAC1E,YAAA,EAAE,MAAM,IAAI,KAAK;AAEvB,YAAM,eAAc,oBAAI,KAAK,GAAE,YAAY;AAC3C,YAAM,YAAY,MAAM,SAAS,EAAE,YAAY,YAAY;AAE3D,YAAM,0BAA0B,QAAQ;AAAA,QACvC,GAAG;AAAA,QACH,cAAc;AAAA,QACd,YAAY;AAAA,MAAA,CACZ;AAEI,WAAA,SAAS,oBAAoB,uBAAuB,CAAC;AAEpD,YAAA,UAAU,KAAK,eAAiC;AAAA,QACrD,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK;AAAA,QACL,SAAS;AAAA,UACR,YAAY,wBAAwB;AAAA,UACpC,cAAc;AAAA,UACd,YAAY;AAAA,UACZ,GAAG;AAAA,QACJ;AAAA,QACA,UAAU;AAAA,UACT,QAAQ;AAAA,UACR,GAAI,QAAQ,QAAQ,CAAC,QAAQ,KAAK,IAAI,CAAC;AAAA,UACvC,GAAI,QAAQ,QAAQ,CAAC,QAAQ,KAAK,IAAI,CAAC;AAAA,QACxC;AAAA,QACA,QAAQ,CAAC,wBAAwB,UAAU;AAAA,MAAA,CAC3C;AAGC,cAAA,KAAK,CAAC,qBAAqB;AACtB,aAAA,SAAS,uBAAuB,gBAAgB,CAAC;AAAA,MAAA,CACtD,EACA,MAAM,MAAM;AACZ,aAAK,SAAS,uBAAuB,wBAAwB,UAAU,CAAC;AAAA,MAAA,CACxE;AAEK,aAAA,CAAC,yBAAyB,OAAO;AAAA,IACzC;AAAA,IAEA,MAAM,OAAO,IAA2B;AACjC,YAAA,EAAE,MAAM,IAAI,KAAK;AAEvB,YAAM,mBAAmB,2BAA2B,EAAE,EAAE,MAAM,UAAU;AAExE,UAAI,CAAC,kBAAkB;AACtB,cAAM,IAAI,MAAM,6BAA6B,EAAE,sBAAsB;AAAA,MACtE;AAEK,WAAA,SAAS,uBAAuB,EAAE,CAAC;AAElC,YAAA,UAAU,KAAK,eAA0B;AAAA,QAC9C,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK,wBAAwB,EAAE;AAAA,QAC/B,UAAU,CAAC,EAAE;AAAA,QACb,QAAQ,CAAC;AAAA,MAAA,CACT;AAED,cAAQ,MAAM,MAAM;AACd,aAAA,SAAS,oBAAoB,gBAAgB,CAAC;AAAA,MAAA,CACnD;AAEM,aAAA;AAAA,IACR;AAAA,IAEA,MAAM,aAAa,WAAkC;AAC9C,YAAA,oBAAoB,MAAM,KAAK,eAAmC;AAAA,QACvE,aAAa;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,KAAK;AAAA,QACL,aAAa,EAAE,YAAY,UAAU,WAAW;AAAA,QAChD,UAAU,CAAC;AAAA,QACX,QAAQ,CAAC;AAAA,MAAA,CACT;AAEI,WAAA,SAAS,4BAA4B,iBAAiB,CAAC;AAAA,IAC7D;AAAA,EACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","x_google_ignoreList":[5]}
1
+ {"version":3,"file":"overmap-core.umd.cjs","sources":["../src/enums/api.ts","../src/enums/issue.ts","../src/sdk/classes/OutboxCoordinator.ts","../src/sdk/errors.ts","../src/utils/async/DeferredPromise.ts","../node_modules/redux/es/redux.js","../src/store/migrations.ts","../src/store/slices/authSlice.ts","../src/utils/coordinates.ts","../src/utils/css.ts","../src/utils/file.ts","../src/utils/logging.ts","../src/utils/offline.ts","../src/utils/search.ts","../src/utils/string.ts","../src/utils/utils.ts","../src/utils/optimization.ts","../src/utils/colors.ts","../src/utils/date.ts","../src/store/adapter.ts","../src/store/slices/categorySlice.ts","../src/store/slices/assetTypeSlice.ts","../src/store/slices/assetSlice.ts","../src/store/slices/assetAttachmentSlice.ts","../src/store/slices/assetStageCompletionSlice.ts","../src/store/slices/assetStageSlice.ts","../src/store/slices/assetTypeAttachmentSlice.ts","../src/store/slices/workspaceSlice.ts","../src/store/slices/issueSlice.ts","../src/store/slices/issueTypeSlice.ts","../src/store/slices/fileSlice.ts","../src/typings/models/access.ts","../src/typings/models/attachments.ts","../src/typings/models/issues.ts","../src/typings/models/emailVerification.ts","../src/typings/models/license.ts","../src/store/slices/userSlice.ts","../src/store/slices/organizationAccessSlice.ts","../src/store/slices/licenseSlice.ts","../src/store/slices/projectAccessSlice.ts","../src/store/slices/projectSlice.ts","../src/store/slices/organizationSlice.ts","../src/store/slices/outboxSlice.ts","../src/store/slices/projectFileSlice.ts","../src/store/slices/projectAttachmentSlice.ts","../src/store/slices/rehydratedSlice.ts","../src/utils/forms.ts","../src/store/slices/formRevisionSlice.ts","../src/store/slices/formSlice.ts","../src/store/slices/formSubmissionSlice.ts","../src/store/slices/formSubmissionAttachmentSlice.ts","../src/store/slices/formRevisionAttachmentSlice.ts","../src/store/slices/emailDomainsSlice.ts","../src/store/slices/documentSlice.ts","../src/store/slices/documentAttachmentSlice.ts","../src/store/slices/teamSlice.ts","../src/store/slices/agentsSlice.ts","../src/store/slices/issueCommentSlice.ts","../src/store/slices/issueUpdateSlice.ts","../src/store/slices/issueAttachmentSlice.ts","../src/store/slices/versioningSlice.ts","../src/store/slices/geoImageSlice.ts","../src/store/slices/issueAssociationSlice.ts","../src/constants/ui.ts","../src/constants/defaults.ts","../src/constants/offline.ts","../src/sdk/globals.ts","../src/sdk/services/BaseService.ts","../src/store/store.ts","../src/sdk/base.ts","../src/sdk/sdk.ts","../src/sdk/services/BaseAuthService.ts","../src/sdk/services/JWTAuthService.ts","../src/sdk/services/BaseApiService.ts","../src/sdk/services/CategoryService.ts","../src/utils/array.ts","../src/sdk/services/AssetService.ts","../src/sdk/services/AssetStageCompletionService.ts","../src/sdk/services/AssetStageService.ts","../src/sdk/services/BaseUploadService.ts","../src/sdk/services/BaseAttachmentService.ts","../src/sdk/services/AssetAttachmentService.ts","../src/sdk/services/AssetTypeService.ts","../src/sdk/services/AssetTypeAttachmentService.ts","../src/sdk/services/IssueCommentService.ts","../src/sdk/services/IssueUpdateService.ts","../src/sdk/services/IssueAttachmentService.ts","../src/sdk/services/IssueService.ts","../src/sdk/services/IssueTypeService.ts","../src/sdk/services/ProjectAccessService.ts","../src/sdk/services/ProjectFileService.ts","../src/sdk/services/ProjectAttachmentService.ts","../src/sdk/services/ProjectService.ts","../src/sdk/services/FormService.ts","../src/sdk/services/FormSubmissionService.ts","../src/sdk/services/WorkspaceService.ts","../src/sdk/services/OrganizationAccessService.ts","../src/sdk/services/FileService.ts","../src/sdk/services/EmailVerificationService.ts","../src/sdk/services/EmailDomainsService.ts","../src/sdk/services/OrganizationService.ts","../src/sdk/services/LicenseService.ts","../src/sdk/services/DocumentService.ts","../src/sdk/services/DocumentAttachmentService.ts","../src/sdk/services/AgentService.ts","../src/sdk/services/TeamService.ts","../src/sdk/services/UserService.ts","../src/sdk/services/GeoImageService.ts","../src/sdk/services/IssueAssociationService.ts"],"sourcesContent":["export const enum HttpMethod {\n\tGET = \"GET\",\n\tPOST = \"POST\",\n\tPATCH = \"PATCH\",\n\tPUT = \"PUT\",\n\tDELETE = \"DELETE\",\n\t// TODO: Add support\n\t// OPTIONS = \"OPTIONS\",\n}\n","export enum IssuePriority {\n\tLOWEST = 0,\n\tLOW = 2,\n\tMEDIUM = 4,\n\tHIGH = 6,\n\tHIGHEST = 8,\n}\n\nexport enum IssueStatus {\n\tBACKLOG = 0,\n\tSELECTED = 2,\n\tDONE = 4,\n}\n","import { DepGraph } from \"dependency-graph\"\nimport type { FullOfflineAction } from \"../../store\"\nimport { Outbox } from \"@redux-offline/redux-offline/lib/types\"\n\n// TODO: Tests:\n// - Bulk-create components, then delete one of those components. Ensure the dependency to the bulk-create is found.\n\nexport class OutboxCoordinator {\n\tgraph: DepGraph<FullOfflineAction>\n\trequestAttemptCounter: Record<string, number>\n\n\tconstructor() {\n\t\tthis.graph = new DepGraph()\n\t\tthis.requestAttemptCounter = {}\n\t}\n\n\t/**\n\t * Used when the app is loaded. Reconstructs the dependency graph based on an outbox from the redux-offline store.\n\t */\n\tstatic _fromOutbox(outbox: Outbox): OutboxCoordinator {\n\t\tconst ret = new OutboxCoordinator()\n\n\t\tfor (let i = 0; i < outbox.length; i++) {\n\t\t\tconst outboxItem = outbox[i] as FullOfflineAction | undefined\n\t\t\tif (!outboxItem) {\n\t\t\t\tconsole.error(\"Outbox item was undefined\")\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tret.sneakRequest(outboxItem)\n\t\t\t// Add any dependencies to requests that were added before this one\n\t\t\tfor (let j = 0; j < i; j++) {\n\t\t\t\tconst previousOutboxItem = outbox[j] as FullOfflineAction | undefined\n\t\t\t\tif (!previousOutboxItem) {\n\t\t\t\t\tconsole.error(\"Previous outbox item was undefined\")\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (previousOutboxItem.payload.uuid === outboxItem.payload.uuid) {\n\t\t\t\t\tcontinue // Skip self\n\t\t\t\t}\n\t\t\t\tif (previousOutboxItem.payload.blocks.some((block) => outboxItem.payload.blockers.includes(block))) {\n\t\t\t\t\tOutboxCoordinator._addDependency(\n\t\t\t\t\t\toutboxItem.payload.uuid,\n\t\t\t\t\t\tpreviousOutboxItem.payload.uuid,\n\t\t\t\t\t\tret.graph,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn ret\n\t}\n\n\t_addDependency(from: string, to: string) {\n\t\tOutboxCoordinator._addDependency(from, to, this.graph)\n\t}\n\n\tstatic _addDependency(from: string, to: string, graph: DepGraph<FullOfflineAction>) {\n\t\tif (from === to) {\n\t\t\tthrow new Error(`Tried to add dependency from node to itself: ${from}`)\n\t\t}\n\t\tconst fromExists = graph.hasNode(from)\n\t\tif (!fromExists) {\n\t\t\tthrow new Error(`Tried to add dependency from non-existent node: ${from} (to node: ${to})`)\n\t\t}\n\t\tconst toExists = graph.hasNode(to)\n\t\tif (!toExists) {\n\t\t\tthrow new Error(`Tried to add dependency to non-existent node: ${to} (from node: ${from})`)\n\t\t}\n\t\tgraph.addDependency(from, to)\n\t}\n\n\t/**\n\t * If there are one or more nodes in the graph, we find all nodes that match a dependency of the request and add a\n\t * dependency from the new request node to that node.\n\t */\n\taddRequest(request: FullOfflineAction) {\n\t\tthis.graph.addNode(request.payload.uuid, request)\n\n\t\tif (request.payload.blockers.length === 0 || this.graph.size() === 1) {\n\t\t\t// The request has no dependencies, or there are no other nodes in the graph, so there are no dependencies\n\t\t\t// to create.\n\t\t\treturn\n\t\t}\n\n\t\t// Create dependencies according to the request's blockers\n\t\tfor (const node of this.graph.overallOrder()) {\n\t\t\tif (node === request.payload.uuid) continue // Skip the node we just added\n\t\t\tconst details = this.graph.getNodeData(node)\n\t\t\t// 1. Any node matching this request's offline_id\n\t\t\tif (request.payload.blockers.some((blocker) => details.payload.blocks.includes(blocker))) {\n\t\t\t\tthis._addDependency(request.payload.uuid, node)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Inserts a request at the beginning of the queue. This could be used for requests that were popped, then failed,\n\t * and need to be re-enqueued at the front of the queue. Any requests that were previously blocked by this request\n\t * will be blocked by this request again. No blockers will be added to this request because it is assumed that the\n\t * request was already unblocked when it was popped.\n\t * @param request The request to insert at the beginning of the queue.\n\t */\n\tinsertRequest(request: FullOfflineAction) {\n\t\tthis.graph.addNode(request.payload.uuid, request)\n\n\t\t// Create dependencies according to the request's blockers\n\t\tfor (const node of this.graph.overallOrder()) {\n\t\t\tif (node === request.payload.uuid) continue // Skip the request we just inserted\n\t\t\tconst details = this.graph.getNodeData(node)\n\t\t\t// 1. Any node matching this request's offline_id\n\t\t\tif (details.payload.blockers.some((blocker) => request.payload.blocks.includes(blocker))) {\n\t\t\t\tthis._addDependency(node, request.payload.uuid)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sneaks a request into the dependency graph without creating any blockers. Useful for reconstructing the graph\n\t * (from the offline store's outbox state) when the app is loaded.\n\t */\n\tsneakRequest(request: FullOfflineAction) {\n\t\tthis.graph.addNode(request.payload.uuid, request)\n\t}\n\n\t/**\n\t * Returns the next node in line to be sent. This is the unblocked node with the fewest number of attempts. If there\n\t * are multiple nodes with the same number of attempts, the first one (by insertion order) will be returned.\n\t */\n\t_getNextNode(): string | undefined {\n\t\tconst leafNodes = this.graph.overallOrder(true)\n\t\tlet minAttempts = Infinity\n\t\tlet minAttemptsNode: string | undefined\n\t\tfor (const node of leafNodes) {\n\t\t\tconst attempts = this.requestAttemptCounter[node] || 0\n\t\t\tif (attempts < minAttempts) {\n\t\t\t\tminAttempts = attempts\n\t\t\t\tminAttemptsNode = node\n\t\t\t}\n\t\t}\n\t\treturn minAttemptsNode\n\t}\n\n\t/**\n\t * Returns the next request in line to be sent without removing it.\n\t */\n\tpeek(): FullOfflineAction | undefined {\n\t\tconst nextNode = this._getNextNode()\n\t\tif (!nextNode) return undefined\n\t\treturn this.graph.getNodeData(nextNode)\n\t}\n\n\t/**\n\t * Removes a request from the graph. This should be called when a request is successfully sent.\n\t * @param uuid The UUID of the request to remove.\n\t */\n\tremove(uuid: string): void {\n\t\tthis.graph.removeNode(uuid)\n\t\tdelete this.requestAttemptCounter[uuid]\n\t}\n\n\t/**\n\t * Returns the next request in line to be sent and removes it from the graph.\n\t */\n\tpop(): FullOfflineAction | undefined {\n\t\tconst nextRequestDetails = this.peek()\n\t\tif (nextRequestDetails) {\n\t\t\tthis.graph.removeNode(nextRequestDetails.payload.uuid)\n\t\t}\n\t\treturn nextRequestDetails\n\t}\n\n\t/**\n\t * Gets the current queue for the outbox. Should be called to get a new value for the outbox slice every time a\n\t * request is enqueued. It will be used to render the outbox items in a single lane.\n\t */\n\tgetQueue(): FullOfflineAction[] {\n\t\tconst ret = this.graph.overallOrder().map((nodeName) => this.graph.getNodeData(nodeName))\n\n\t\t// We will return the normal overall order, except we put the request with the fewest number of attempts at the\n\t\t// front of the queue, assuming it is not blocked.\n\t\tconst nextNode = this._getNextNode()\n\t\tif (nextNode) {\n\t\t\tconst nextRequestDetails = this.graph.getNodeData(nextNode)\n\t\t\tconst nextRequestIndex = ret.findIndex(\n\t\t\t\t(request) => request.payload.uuid === nextRequestDetails.payload.uuid,\n\t\t\t)\n\t\t\tif (nextRequestIndex !== -1) {\n\t\t\t\tret.splice(nextRequestIndex, 1)\n\t\t\t\tret.unshift(nextRequestDetails)\n\t\t\t}\n\t\t}\n\n\t\treturn ret\n\t}\n\n\t/**\n\t * Gets a list of requests that can currently be sent (requests with no unresolved dependencies). Used to process\n\t * the next ready request in case the request at the front of the queue is failing.\n\t */\n\tgetReady(): FullOfflineAction[] {\n\t\tlet ret = this.graph.overallOrder(true).map((nodeName) => this.graph.getNodeData(nodeName))\n\t\t// First, order by insertion order\n\t\tret = ret.sort((a, b) => {\n\t\t\treturn a.meta.offline.effect.timestamp.localeCompare(b.meta.offline.effect.timestamp)\n\t\t})\n\t\t// Then, order by number of attempts\n\t\tret = ret.sort((a, b) => {\n\t\t\tconst aAttempts = this.requestAttemptCounter[a.payload.uuid] || 0\n\t\t\tconst bAttempts = this.requestAttemptCounter[b.payload.uuid] || 0\n\t\t\t// If these are equal, we want to keep the insertion order, which should be maintained from the previous\n\t\t\t// sort if we return 0.\n\t\t\treturn aAttempts - bAttempts\n\t\t})\n\t\treturn ret\n\t}\n\n\tregisterRetry(uuid: string): void {\n\t\tthis.requestAttemptCounter[uuid] = (this.requestAttemptCounter[uuid] || 0) + 1\n\t}\n}\n\n// TODO: Consider auto-discovering UUIDs instead of (or in addition to) explicitly passing them to `enqueueRequest`\n/**\n * Given a request, returns an array of discovered UUIDs referenced in the request.\n * Discovers UUIDs in the URL, body, and query string.\n * @param request\n */\n/*\nfunction _discoverUuids(request: RequestDetails): Set<string> {\n\t// We need to consider:\n\t// 1. Any UUID in the URL\n\t// 2. Any UUID in the body\n\t// 3. Any UUID in the query parameters\n\n\tconst ret = new Set<string>()\n\n\tfunction discoverUuidsInArray(values: unknown[]): void {\n\t\tfor (const value of values) {\n\t\t\tif (typeof value === \"string\" && value.length === 36 && UUID_REGEX.test(value)) {\n\t\t\t\tret.add(value)\n\t\t\t}\n\t\t}\n\t}\n\n\tconst urlParts = request.url.split(\"/\")\n\n\tdiscoverUuidsInArray(urlParts)\n\n\tif (request.payload) {\n\t\tdiscoverUuidsInArray(Object.values(request.payload))\n\t}\n\n\tif (request.queryParams) {\n\t\tdiscoverUuidsInArray(Object.values(request.queryParams))\n\t}\n\n\treturn ret\n}\n */\n","// Contains custom error classes used by the SDK\n\nimport request from \"superagent\"\n\nexport interface APIErrorOptions {\n\tresponse?: request.Response\n\tinnerError?: unknown // Most likely an Error\n\tmessage?: string\n\tdiscard?: boolean\n}\n\nconst UNKNOWN_ERROR_MESSAGE = \"An unknown error occurred\"\nconst MAX_ERROR_MESSAGE_LENGTH = 500\nconst _SPECIAL_KEYS = [\"non_field_errors\", \"detail\"]\n\n/**\n * Makes a best-effort attempt to extract an error message from a request.Response or an error object.\n * @param errorRes The response object from a request, if available\n * @param err The error object, if available\n */\nfunction extractErrorMessage(errorRes: request.Response | undefined, err: unknown): string | undefined {\n\tlet ret: string | undefined\n\tif (errorRes?.body) {\n\t\tif (typeof errorRes.body === \"object\") {\n\t\t\tconst responseBody = errorRes.body as {\n\t\t\t\terror?: string\n\t\t\t\tmessage?: string\n\t\t\t\tbody?: Record<string, string | string[]>\n\t\t\t}\n\t\t\tif (typeof responseBody.error === \"string\") {\n\t\t\t\tret = responseBody.error\n\t\t\t} else if (typeof responseBody.message === \"string\") {\n\t\t\t\tret = responseBody.message\n\t\t\t} else if (responseBody.body) {\n\t\t\t\t// The error message may be something like this:\n\t\t\t\t// \t\t{\n\t\t\t\t// \t\t\tname: [\"This name is already taken.\", \"This name is too short.\"],\n\t\t\t\t// \t\t\temail: \"This email is already taken\",\n\t\t\t\t//\t\t\tnon_field_errors: [\"This username is already taken.\"]\n\t\t\t\t// \t\t}\n\t\t\t\t// We want to convert this into:\n\t\t\t\t// \t\tName: This name is already taken.\n\t\t\t\t// \t\tName: This name is too short.\n\t\t\t\t// \t\tEmail: This email is already taken\n\t\t\t\t//\t\tThis username is already taken.\n\t\t\t\t// TODO: Support bold field names without using unsafe HTML\n\t\t\t\ttry {\n\t\t\t\t\tret = Object.entries(responseBody.body)\n\t\t\t\t\t\t.map(([key, value]) => {\n\t\t\t\t\t\t\tif (typeof value === \"string\") {\n\t\t\t\t\t\t\t\tif (_SPECIAL_KEYS.includes(key)) return value\n\t\t\t\t\t\t\t\treturn `${key}: ${value}`\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (Array.isArray(value)) {\n\t\t\t\t\t\t\t\tif (_SPECIAL_KEYS.includes(key)) return value.join(\"\\n\")\n\t\t\t\t\t\t\t\treturn value.map((v) => `${key}: ${v}`).join(\"\\n\")\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn `${key}: ${JSON.stringify(value)}`\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.join(\"\\n\")\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconsole.error(\"Failed to extract error message from response body\", e)\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (typeof errorRes.body === \"string\") {\n\t\t\tret = errorRes.body\n\t\t}\n\t} else if (errorRes?.text) {\n\t\tret = errorRes.text\n\t} else if (err instanceof Error) {\n\t\tret = err.message\n\t}\n\n\t// Check the length of the message. If it's too long, show a generic message instead.\n\t// This can happen if the backend returns a document instead of a JSON object.\n\tif (!ret || ret.length > MAX_ERROR_MESSAGE_LENGTH) {\n\t\treturn UNKNOWN_ERROR_MESSAGE\n\t}\n\treturn ret\n}\n\nexport class APIError extends Error {\n\t// NOTE: Needs to conform to NetworkError in @redux-offline/redux-offline, which has `status` and `response`.\n\tstatus: number\n\tresponse: request.Response | undefined\n\tmessage: string\n\toptions: APIErrorOptions\n\n\tconstructor(options: APIErrorOptions) {\n\t\tsuper(UNKNOWN_ERROR_MESSAGE)\n\t\tconst { response, innerError } = options\n\t\tthis.message = options.message ?? extractErrorMessage(response, innerError) ?? UNKNOWN_ERROR_MESSAGE\n\t\tthis.status = response?.status ?? 0\n\t\tthis.response = response\n\t\toptions.discard = options.discard ?? false\n\t\tthis.options = options\n\t}\n}\n","// https://gist.github.com/GFoley83/5877f6c09fbcfd62569c51dc91444cf0\n\n/**\n * A new instance of deferred is constructed by calling `new DeferredPromise<T>()`.\n * The purpose of the deferred object is to expose the associated Promise\n * instance APIs that can be used for signaling the successful\n * or unsuccessful completion, as well as the state of the task.\n * @export\n * @class DeferredPromise\n * @implements {Promise<T>}\n * @template T\n * @example\n * const deferred = new DeferredPromise<string>()\n * console.log(deferred.state) // \"pending\"\n *\n * deferred\n * .then(str => console.log(str))\n * .catch(err => console.error(err))\n *\n * deferred.resolve(\"Foo\")\n * console.log(deferred.state) // \"fulfilled\"\n * // deferred.reject(\"Bar\")\n */\nexport class DeferredPromise<T> implements Promise<T> {\n\t[Symbol.toStringTag] = \"Promise\"\n\n\tprivate _promise: Promise<T>\n\tprivate _resolve: null | ((value?: T | PromiseLike<T>) => void)\n\tprivate _reject: null | ((reason?: unknown) => void)\n\tprivate _state: \"pending\" | \"fulfilled\" | \"rejected\" = \"pending\"\n\n\tpublic get state(): \"pending\" | \"fulfilled\" | \"rejected\" {\n\t\treturn this._state\n\t}\n\n\tconstructor() {\n\t\tthis._resolve = null\n\t\tthis._reject = null\n\n\t\tthis._promise = new Promise<T>((resolve, reject) => {\n\t\t\tthis._resolve = resolve as (value?: T | PromiseLike<T>) => void\n\t\t\tthis._reject = reject\n\t\t})\n\t}\n\n\tpublic then<TResult1, TResult2>(\n\t\tonFulfilled?: (value: T) => TResult1 | PromiseLike<TResult1>,\n\t\tonRejected?: (reason: unknown) => TResult2 | PromiseLike<TResult2>,\n\t): Promise<TResult1 | TResult2> {\n\t\treturn this._promise.then(onFulfilled, onRejected)\n\t}\n\n\tpublic catch<TResult>(onRejected?: (reason: unknown) => TResult | PromiseLike<TResult>): Promise<T | TResult> {\n\t\treturn this._promise.catch(onRejected)\n\t}\n\n\tpublic resolve(value?: T | PromiseLike<T>): void {\n\t\tif (!this._resolve) throw new Error(\"No resolve callback\")\n\t\tthis._resolve(value)\n\t\tthis._state = \"fulfilled\"\n\t}\n\n\tpublic reject(reason?: unknown): void {\n\t\tif (!this._reject) throw reason\n\t\tthis._reject(reason)\n\t\tthis._state = \"rejected\"\n\t}\n\n\tpublic finally(_onFinally?: (() => void) | undefined | null): Promise<T> {\n\t\tthrow new Error(\"`finally` not implemented\")\n\t}\n}\n","import _objectSpread from '@babel/runtime/helpers/esm/objectSpread2';\n\n/**\n * Adapted from React: https://github.com/facebook/react/blob/master/packages/shared/formatProdErrorMessage.js\n *\n * Do not require this module directly! Use normal throw error calls. These messages will be replaced with error codes\n * during build.\n * @param {number} code\n */\nfunction formatProdErrorMessage(code) {\n return \"Minified Redux error #\" + code + \"; visit https://redux.js.org/Errors?code=\" + code + \" for the full message or \" + 'use the non-minified dev environment for full errors. ';\n}\n\n// Inlined version of the `symbol-observable` polyfill\nvar $$observable = (function () {\n return typeof Symbol === 'function' && Symbol.observable || '@@observable';\n})();\n\n/**\n * These are private action types reserved by Redux.\n * For any unknown actions, you must return the current state.\n * If the current state is undefined, you must return the initial state.\n * Do not reference these action types directly in your code.\n */\nvar randomString = function randomString() {\n return Math.random().toString(36).substring(7).split('').join('.');\n};\n\nvar ActionTypes = {\n INIT: \"@@redux/INIT\" + randomString(),\n REPLACE: \"@@redux/REPLACE\" + randomString(),\n PROBE_UNKNOWN_ACTION: function PROBE_UNKNOWN_ACTION() {\n return \"@@redux/PROBE_UNKNOWN_ACTION\" + randomString();\n }\n};\n\n/**\n * @param {any} obj The object to inspect.\n * @returns {boolean} True if the argument appears to be a plain object.\n */\nfunction isPlainObject(obj) {\n if (typeof obj !== 'object' || obj === null) return false;\n var proto = obj;\n\n while (Object.getPrototypeOf(proto) !== null) {\n proto = Object.getPrototypeOf(proto);\n }\n\n return Object.getPrototypeOf(obj) === proto;\n}\n\n// Inlined / shortened version of `kindOf` from https://github.com/jonschlinkert/kind-of\nfunction miniKindOf(val) {\n if (val === void 0) return 'undefined';\n if (val === null) return 'null';\n var type = typeof val;\n\n switch (type) {\n case 'boolean':\n case 'string':\n case 'number':\n case 'symbol':\n case 'function':\n {\n return type;\n }\n }\n\n if (Array.isArray(val)) return 'array';\n if (isDate(val)) return 'date';\n if (isError(val)) return 'error';\n var constructorName = ctorName(val);\n\n switch (constructorName) {\n case 'Symbol':\n case 'Promise':\n case 'WeakMap':\n case 'WeakSet':\n case 'Map':\n case 'Set':\n return constructorName;\n } // other\n\n\n return type.slice(8, -1).toLowerCase().replace(/\\s/g, '');\n}\n\nfunction ctorName(val) {\n return typeof val.constructor === 'function' ? val.constructor.name : null;\n}\n\nfunction isError(val) {\n return val instanceof Error || typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number';\n}\n\nfunction isDate(val) {\n if (val instanceof Date) return true;\n return typeof val.toDateString === 'function' && typeof val.getDate === 'function' && typeof val.setDate === 'function';\n}\n\nfunction kindOf(val) {\n var typeOfVal = typeof val;\n\n if (process.env.NODE_ENV !== 'production') {\n typeOfVal = miniKindOf(val);\n }\n\n return typeOfVal;\n}\n\n/**\n * @deprecated\n *\n * **We recommend using the `configureStore` method\n * of the `@reduxjs/toolkit` package**, which replaces `createStore`.\n *\n * Redux Toolkit is our recommended approach for writing Redux logic today,\n * including store setup, reducers, data fetching, and more.\n *\n * **For more details, please read this Redux docs page:**\n * **https://redux.js.org/introduction/why-rtk-is-redux-today**\n *\n * `configureStore` from Redux Toolkit is an improved version of `createStore` that\n * simplifies setup and helps avoid common bugs.\n *\n * You should not be using the `redux` core package by itself today, except for learning purposes.\n * The `createStore` method from the core `redux` package will not be removed, but we encourage\n * all users to migrate to using Redux Toolkit for all Redux code.\n *\n * If you want to use `createStore` without this visual deprecation warning, use\n * the `legacy_createStore` import instead:\n *\n * `import { legacy_createStore as createStore} from 'redux'`\n *\n */\n\nfunction createStore(reducer, preloadedState, enhancer) {\n var _ref2;\n\n if (typeof preloadedState === 'function' && typeof enhancer === 'function' || typeof enhancer === 'function' && typeof arguments[3] === 'function') {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(0) : 'It looks like you are passing several store enhancers to ' + 'createStore(). This is not supported. Instead, compose them ' + 'together to a single function. See https://redux.js.org/tutorials/fundamentals/part-4-store#creating-a-store-with-enhancers for an example.');\n }\n\n if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {\n enhancer = preloadedState;\n preloadedState = undefined;\n }\n\n if (typeof enhancer !== 'undefined') {\n if (typeof enhancer !== 'function') {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(1) : \"Expected the enhancer to be a function. Instead, received: '\" + kindOf(enhancer) + \"'\");\n }\n\n return enhancer(createStore)(reducer, preloadedState);\n }\n\n if (typeof reducer !== 'function') {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(2) : \"Expected the root reducer to be a function. Instead, received: '\" + kindOf(reducer) + \"'\");\n }\n\n var currentReducer = reducer;\n var currentState = preloadedState;\n var currentListeners = [];\n var nextListeners = currentListeners;\n var isDispatching = false;\n /**\n * This makes a shallow copy of currentListeners so we can use\n * nextListeners as a temporary list while dispatching.\n *\n * This prevents any bugs around consumers calling\n * subscribe/unsubscribe in the middle of a dispatch.\n */\n\n function ensureCanMutateNextListeners() {\n if (nextListeners === currentListeners) {\n nextListeners = currentListeners.slice();\n }\n }\n /**\n * Reads the state tree managed by the store.\n *\n * @returns {any} The current state tree of your application.\n */\n\n\n function getState() {\n if (isDispatching) {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(3) : 'You may not call store.getState() while the reducer is executing. ' + 'The reducer has already received the state as an argument. ' + 'Pass it down from the top reducer instead of reading it from the store.');\n }\n\n return currentState;\n }\n /**\n * Adds a change listener. It will be called any time an action is dispatched,\n * and some part of the state tree may potentially have changed. You may then\n * call `getState()` to read the current state tree inside the callback.\n *\n * You may call `dispatch()` from a change listener, with the following\n * caveats:\n *\n * 1. The subscriptions are snapshotted just before every `dispatch()` call.\n * If you subscribe or unsubscribe while the listeners are being invoked, this\n * will not have any effect on the `dispatch()` that is currently in progress.\n * However, the next `dispatch()` call, whether nested or not, will use a more\n * recent snapshot of the subscription list.\n *\n * 2. The listener should not expect to see all state changes, as the state\n * might have been updated multiple times during a nested `dispatch()` before\n * the listener is called. It is, however, guaranteed that all subscribers\n * registered before the `dispatch()` started will be called with the latest\n * state by the time it exits.\n *\n * @param {Function} listener A callback to be invoked on every dispatch.\n * @returns {Function} A function to remove this change listener.\n */\n\n\n function subscribe(listener) {\n if (typeof listener !== 'function') {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(4) : \"Expected the listener to be a function. Instead, received: '\" + kindOf(listener) + \"'\");\n }\n\n if (isDispatching) {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(5) : 'You may not call store.subscribe() while the reducer is executing. ' + 'If you would like to be notified after the store has been updated, subscribe from a ' + 'component and invoke store.getState() in the callback to access the latest state. ' + 'See https://redux.js.org/api/store#subscribelistener for more details.');\n }\n\n var isSubscribed = true;\n ensureCanMutateNextListeners();\n nextListeners.push(listener);\n return function unsubscribe() {\n if (!isSubscribed) {\n return;\n }\n\n if (isDispatching) {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(6) : 'You may not unsubscribe from a store listener while the reducer is executing. ' + 'See https://redux.js.org/api/store#subscribelistener for more details.');\n }\n\n isSubscribed = false;\n ensureCanMutateNextListeners();\n var index = nextListeners.indexOf(listener);\n nextListeners.splice(index, 1);\n currentListeners = null;\n };\n }\n /**\n * Dispatches an action. It is the only way to trigger a state change.\n *\n * The `reducer` function, used to create the store, will be called with the\n * current state tree and the given `action`. Its return value will\n * be considered the **next** state of the tree, and the change listeners\n * will be notified.\n *\n * The base implementation only supports plain object actions. If you want to\n * dispatch a Promise, an Observable, a thunk, or something else, you need to\n * wrap your store creating function into the corresponding middleware. For\n * example, see the documentation for the `redux-thunk` package. Even the\n * middleware will eventually dispatch plain object actions using this method.\n *\n * @param {Object} action A plain object representing “what changed”. It is\n * a good idea to keep actions serializable so you can record and replay user\n * sessions, or use the time travelling `redux-devtools`. An action must have\n * a `type` property which may not be `undefined`. It is a good idea to use\n * string constants for action types.\n *\n * @returns {Object} For convenience, the same action object you dispatched.\n *\n * Note that, if you use a custom middleware, it may wrap `dispatch()` to\n * return something else (for example, a Promise you can await).\n */\n\n\n function dispatch(action) {\n if (!isPlainObject(action)) {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(7) : \"Actions must be plain objects. Instead, the actual type was: '\" + kindOf(action) + \"'. You may need to add middleware to your store setup to handle dispatching other values, such as 'redux-thunk' to handle dispatching functions. See https://redux.js.org/tutorials/fundamentals/part-4-store#middleware and https://redux.js.org/tutorials/fundamentals/part-6-async-logic#using-the-redux-thunk-middleware for examples.\");\n }\n\n if (typeof action.type === 'undefined') {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(8) : 'Actions may not have an undefined \"type\" property. You may have misspelled an action type string constant.');\n }\n\n if (isDispatching) {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(9) : 'Reducers may not dispatch actions.');\n }\n\n try {\n isDispatching = true;\n currentState = currentReducer(currentState, action);\n } finally {\n isDispatching = false;\n }\n\n var listeners = currentListeners = nextListeners;\n\n for (var i = 0; i < listeners.length; i++) {\n var listener = listeners[i];\n listener();\n }\n\n return action;\n }\n /**\n * Replaces the reducer currently used by the store to calculate the state.\n *\n * You might need this if your app implements code splitting and you want to\n * load some of the reducers dynamically. You might also need this if you\n * implement a hot reloading mechanism for Redux.\n *\n * @param {Function} nextReducer The reducer for the store to use instead.\n * @returns {void}\n */\n\n\n function replaceReducer(nextReducer) {\n if (typeof nextReducer !== 'function') {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(10) : \"Expected the nextReducer to be a function. Instead, received: '\" + kindOf(nextReducer));\n }\n\n currentReducer = nextReducer; // This action has a similiar effect to ActionTypes.INIT.\n // Any reducers that existed in both the new and old rootReducer\n // will receive the previous state. This effectively populates\n // the new state tree with any relevant data from the old one.\n\n dispatch({\n type: ActionTypes.REPLACE\n });\n }\n /**\n * Interoperability point for observable/reactive libraries.\n * @returns {observable} A minimal observable of state changes.\n * For more information, see the observable proposal:\n * https://github.com/tc39/proposal-observable\n */\n\n\n function observable() {\n var _ref;\n\n var outerSubscribe = subscribe;\n return _ref = {\n /**\n * The minimal observable subscription method.\n * @param {Object} observer Any object that can be used as an observer.\n * The observer object should have a `next` method.\n * @returns {subscription} An object with an `unsubscribe` method that can\n * be used to unsubscribe the observable from the store, and prevent further\n * emission of values from the observable.\n */\n subscribe: function subscribe(observer) {\n if (typeof observer !== 'object' || observer === null) {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(11) : \"Expected the observer to be an object. Instead, received: '\" + kindOf(observer) + \"'\");\n }\n\n function observeState() {\n if (observer.next) {\n observer.next(getState());\n }\n }\n\n observeState();\n var unsubscribe = outerSubscribe(observeState);\n return {\n unsubscribe: unsubscribe\n };\n }\n }, _ref[$$observable] = function () {\n return this;\n }, _ref;\n } // When a store is created, an \"INIT\" action is dispatched so that every\n // reducer returns their initial state. This effectively populates\n // the initial state tree.\n\n\n dispatch({\n type: ActionTypes.INIT\n });\n return _ref2 = {\n dispatch: dispatch,\n subscribe: subscribe,\n getState: getState,\n replaceReducer: replaceReducer\n }, _ref2[$$observable] = observable, _ref2;\n}\n/**\n * Creates a Redux store that holds the state tree.\n *\n * **We recommend using `configureStore` from the\n * `@reduxjs/toolkit` package**, which replaces `createStore`:\n * **https://redux.js.org/introduction/why-rtk-is-redux-today**\n *\n * The only way to change the data in the store is to call `dispatch()` on it.\n *\n * There should only be a single store in your app. To specify how different\n * parts of the state tree respond to actions, you may combine several reducers\n * into a single reducer function by using `combineReducers`.\n *\n * @param {Function} reducer A function that returns the next state tree, given\n * the current state tree and the action to handle.\n *\n * @param {any} [preloadedState] The initial state. You may optionally specify it\n * to hydrate the state from the server in universal apps, or to restore a\n * previously serialized user session.\n * If you use `combineReducers` to produce the root reducer function, this must be\n * an object with the same shape as `combineReducers` keys.\n *\n * @param {Function} [enhancer] The store enhancer. You may optionally specify it\n * to enhance the store with third-party capabilities such as middleware,\n * time travel, persistence, etc. The only store enhancer that ships with Redux\n * is `applyMiddleware()`.\n *\n * @returns {Store} A Redux store that lets you read the state, dispatch actions\n * and subscribe to changes.\n */\n\nvar legacy_createStore = createStore;\n\n/**\n * Prints a warning in the console if it exists.\n *\n * @param {String} message The warning message.\n * @returns {void}\n */\nfunction warning(message) {\n /* eslint-disable no-console */\n if (typeof console !== 'undefined' && typeof console.error === 'function') {\n console.error(message);\n }\n /* eslint-enable no-console */\n\n\n try {\n // This error was thrown as a convenience so that if you enable\n // \"break on all exceptions\" in your console,\n // it would pause the execution at this line.\n throw new Error(message);\n } catch (e) {} // eslint-disable-line no-empty\n\n}\n\nfunction getUnexpectedStateShapeWarningMessage(inputState, reducers, action, unexpectedKeyCache) {\n var reducerKeys = Object.keys(reducers);\n var argumentName = action && action.type === ActionTypes.INIT ? 'preloadedState argument passed to createStore' : 'previous state received by the reducer';\n\n if (reducerKeys.length === 0) {\n return 'Store does not have a valid reducer. Make sure the argument passed ' + 'to combineReducers is an object whose values are reducers.';\n }\n\n if (!isPlainObject(inputState)) {\n return \"The \" + argumentName + \" has unexpected type of \\\"\" + kindOf(inputState) + \"\\\". Expected argument to be an object with the following \" + (\"keys: \\\"\" + reducerKeys.join('\", \"') + \"\\\"\");\n }\n\n var unexpectedKeys = Object.keys(inputState).filter(function (key) {\n return !reducers.hasOwnProperty(key) && !unexpectedKeyCache[key];\n });\n unexpectedKeys.forEach(function (key) {\n unexpectedKeyCache[key] = true;\n });\n if (action && action.type === ActionTypes.REPLACE) return;\n\n if (unexpectedKeys.length > 0) {\n return \"Unexpected \" + (unexpectedKeys.length > 1 ? 'keys' : 'key') + \" \" + (\"\\\"\" + unexpectedKeys.join('\", \"') + \"\\\" found in \" + argumentName + \". \") + \"Expected to find one of the known reducer keys instead: \" + (\"\\\"\" + reducerKeys.join('\", \"') + \"\\\". Unexpected keys will be ignored.\");\n }\n}\n\nfunction assertReducerShape(reducers) {\n Object.keys(reducers).forEach(function (key) {\n var reducer = reducers[key];\n var initialState = reducer(undefined, {\n type: ActionTypes.INIT\n });\n\n if (typeof initialState === 'undefined') {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(12) : \"The slice reducer for key \\\"\" + key + \"\\\" returned undefined during initialization. \" + \"If the state passed to the reducer is undefined, you must \" + \"explicitly return the initial state. The initial state may \" + \"not be undefined. If you don't want to set a value for this reducer, \" + \"you can use null instead of undefined.\");\n }\n\n if (typeof reducer(undefined, {\n type: ActionTypes.PROBE_UNKNOWN_ACTION()\n }) === 'undefined') {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(13) : \"The slice reducer for key \\\"\" + key + \"\\\" returned undefined when probed with a random type. \" + (\"Don't try to handle '\" + ActionTypes.INIT + \"' or other actions in \\\"redux/*\\\" \") + \"namespace. They are considered private. Instead, you must return the \" + \"current state for any unknown actions, unless it is undefined, \" + \"in which case you must return the initial state, regardless of the \" + \"action type. The initial state may not be undefined, but can be null.\");\n }\n });\n}\n/**\n * Turns an object whose values are different reducer functions, into a single\n * reducer function. It will call every child reducer, and gather their results\n * into a single state object, whose keys correspond to the keys of the passed\n * reducer functions.\n *\n * @param {Object} reducers An object whose values correspond to different\n * reducer functions that need to be combined into one. One handy way to obtain\n * it is to use ES6 `import * as reducers` syntax. The reducers may never return\n * undefined for any action. Instead, they should return their initial state\n * if the state passed to them was undefined, and the current state for any\n * unrecognized action.\n *\n * @returns {Function} A reducer function that invokes every reducer inside the\n * passed object, and builds a state object with the same shape.\n */\n\n\nfunction combineReducers(reducers) {\n var reducerKeys = Object.keys(reducers);\n var finalReducers = {};\n\n for (var i = 0; i < reducerKeys.length; i++) {\n var key = reducerKeys[i];\n\n if (process.env.NODE_ENV !== 'production') {\n if (typeof reducers[key] === 'undefined') {\n warning(\"No reducer provided for key \\\"\" + key + \"\\\"\");\n }\n }\n\n if (typeof reducers[key] === 'function') {\n finalReducers[key] = reducers[key];\n }\n }\n\n var finalReducerKeys = Object.keys(finalReducers); // This is used to make sure we don't warn about the same\n // keys multiple times.\n\n var unexpectedKeyCache;\n\n if (process.env.NODE_ENV !== 'production') {\n unexpectedKeyCache = {};\n }\n\n var shapeAssertionError;\n\n try {\n assertReducerShape(finalReducers);\n } catch (e) {\n shapeAssertionError = e;\n }\n\n return function combination(state, action) {\n if (state === void 0) {\n state = {};\n }\n\n if (shapeAssertionError) {\n throw shapeAssertionError;\n }\n\n if (process.env.NODE_ENV !== 'production') {\n var warningMessage = getUnexpectedStateShapeWarningMessage(state, finalReducers, action, unexpectedKeyCache);\n\n if (warningMessage) {\n warning(warningMessage);\n }\n }\n\n var hasChanged = false;\n var nextState = {};\n\n for (var _i = 0; _i < finalReducerKeys.length; _i++) {\n var _key = finalReducerKeys[_i];\n var reducer = finalReducers[_key];\n var previousStateForKey = state[_key];\n var nextStateForKey = reducer(previousStateForKey, action);\n\n if (typeof nextStateForKey === 'undefined') {\n var actionType = action && action.type;\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(14) : \"When called with an action of type \" + (actionType ? \"\\\"\" + String(actionType) + \"\\\"\" : '(unknown type)') + \", the slice reducer for key \\\"\" + _key + \"\\\" returned undefined. \" + \"To ignore an action, you must explicitly return the previous state. \" + \"If you want this reducer to hold no value, you can return null instead of undefined.\");\n }\n\n nextState[_key] = nextStateForKey;\n hasChanged = hasChanged || nextStateForKey !== previousStateForKey;\n }\n\n hasChanged = hasChanged || finalReducerKeys.length !== Object.keys(state).length;\n return hasChanged ? nextState : state;\n };\n}\n\nfunction bindActionCreator(actionCreator, dispatch) {\n return function () {\n return dispatch(actionCreator.apply(this, arguments));\n };\n}\n/**\n * Turns an object whose values are action creators, into an object with the\n * same keys, but with every function wrapped into a `dispatch` call so they\n * may be invoked directly. This is just a convenience method, as you can call\n * `store.dispatch(MyActionCreators.doSomething())` yourself just fine.\n *\n * For convenience, you can also pass an action creator as the first argument,\n * and get a dispatch wrapped function in return.\n *\n * @param {Function|Object} actionCreators An object whose values are action\n * creator functions. One handy way to obtain it is to use ES6 `import * as`\n * syntax. You may also pass a single function.\n *\n * @param {Function} dispatch The `dispatch` function available on your Redux\n * store.\n *\n * @returns {Function|Object} The object mimicking the original object, but with\n * every action creator wrapped into the `dispatch` call. If you passed a\n * function as `actionCreators`, the return value will also be a single\n * function.\n */\n\n\nfunction bindActionCreators(actionCreators, dispatch) {\n if (typeof actionCreators === 'function') {\n return bindActionCreator(actionCreators, dispatch);\n }\n\n if (typeof actionCreators !== 'object' || actionCreators === null) {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(16) : \"bindActionCreators expected an object or a function, but instead received: '\" + kindOf(actionCreators) + \"'. \" + \"Did you write \\\"import ActionCreators from\\\" instead of \\\"import * as ActionCreators from\\\"?\");\n }\n\n var boundActionCreators = {};\n\n for (var key in actionCreators) {\n var actionCreator = actionCreators[key];\n\n if (typeof actionCreator === 'function') {\n boundActionCreators[key] = bindActionCreator(actionCreator, dispatch);\n }\n }\n\n return boundActionCreators;\n}\n\n/**\n * Composes single-argument functions from right to left. The rightmost\n * function can take multiple arguments as it provides the signature for\n * the resulting composite function.\n *\n * @param {...Function} funcs The functions to compose.\n * @returns {Function} A function obtained by composing the argument functions\n * from right to left. For example, compose(f, g, h) is identical to doing\n * (...args) => f(g(h(...args))).\n */\nfunction compose() {\n for (var _len = arguments.length, funcs = new Array(_len), _key = 0; _key < _len; _key++) {\n funcs[_key] = arguments[_key];\n }\n\n if (funcs.length === 0) {\n return function (arg) {\n return arg;\n };\n }\n\n if (funcs.length === 1) {\n return funcs[0];\n }\n\n return funcs.reduce(function (a, b) {\n return function () {\n return a(b.apply(void 0, arguments));\n };\n });\n}\n\n/**\n * Creates a store enhancer that applies middleware to the dispatch method\n * of the Redux store. This is handy for a variety of tasks, such as expressing\n * asynchronous actions in a concise manner, or logging every action payload.\n *\n * See `redux-thunk` package as an example of the Redux middleware.\n *\n * Because middleware is potentially asynchronous, this should be the first\n * store enhancer in the composition chain.\n *\n * Note that each middleware will be given the `dispatch` and `getState` functions\n * as named arguments.\n *\n * @param {...Function} middlewares The middleware chain to be applied.\n * @returns {Function} A store enhancer applying the middleware.\n */\n\nfunction applyMiddleware() {\n for (var _len = arguments.length, middlewares = new Array(_len), _key = 0; _key < _len; _key++) {\n middlewares[_key] = arguments[_key];\n }\n\n return function (createStore) {\n return function () {\n var store = createStore.apply(void 0, arguments);\n\n var _dispatch = function dispatch() {\n throw new Error(process.env.NODE_ENV === \"production\" ? formatProdErrorMessage(15) : 'Dispatching while constructing your middleware is not allowed. ' + 'Other middleware would not be applied to this dispatch.');\n };\n\n var middlewareAPI = {\n getState: store.getState,\n dispatch: function dispatch() {\n return _dispatch.apply(void 0, arguments);\n }\n };\n var chain = middlewares.map(function (middleware) {\n return middleware(middlewareAPI);\n });\n _dispatch = compose.apply(void 0, chain)(store.dispatch);\n return _objectSpread(_objectSpread({}, store), {}, {\n dispatch: _dispatch\n });\n };\n };\n}\n\nexport { ActionTypes as __DO_NOT_USE__ActionTypes, applyMiddleware, bindActionCreators, combineReducers, compose, createStore, legacy_createStore };\n","// TODO: This is deprecated and moved into redux-persist. See: https://github.com/wildlifela/redux-persist-migrate\n// It also doesn't seem to be doing much.\n\nimport type { Manifest, Migrator } from \"../typings\"\n\n// NOTE: If changing, also change it in store.ts (avoid circular imports)\nconst VERSION_REDUCER_KEY = \"versioning\"\n\ntype WrapMigrator = (migrator: Migrator) => Migrator\n\n// gets the most recent (largest) version number\nconst latestVersion = () => migrations.length - 1\n\n// if unset, set the app version to the latest\n// this is the case when someone opens the app for the first time\nconst initialVersioning: Migrator = (state) => {\n\tstate[VERSION_REDUCER_KEY] = { version: latestVersion() }\n\treturn state\n}\n\n// migration that signs the user out due to the redux store being changed in a breaking way\nconst signOut: Migrator = () => {\n\t// set the app version to the latest so that this migration is not run again\n\treturn initialVersioning({})\n}\n\n// Added a new state to the outbox slice\nconst createOutboxState: Migrator = (state) => {\n\tif (state.outboxReducer) {\n\t\tstate.outboxReducer.deletedRequests = []\n\t}\n\treturn state\n}\n\n// wraps migrations with the skipAfterInitialVersioning check for convenience\nconst wrapMigration: WrapMigrator = (migrator) => (state) => {\n\t// REASON: This happened to GCS\n\t// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n\tif (state === undefined) {\n\t\tstate = {}\n\t}\n\n\tif (state[VERSION_REDUCER_KEY]?.version === latestVersion()) return state\n\n\treturn migrator(state)\n}\n\n// migrations take in a RootState, modify it, and then return the updated root state\n// add new migrations to the **end** of this array\n// ensure initialVersioning() is always the first migration\nconst migrations: Migrator[] = [initialVersioning, signOut, signOut, createOutboxState]\n\n// used by redux-persist-migrate to run the migrations when rehydrating the app\nexport const manifest: Manifest = Object.fromEntries(migrations.map((migration, i) => [i, wrapMigration(migration)]))\n","import { createSlice, PayloadAction, Reducer } from \"@reduxjs/toolkit\"\nimport { TokenPair } from \"sdk/typings\"\nimport { BaseState } from \"../../typings\"\n\nexport interface AuthState {\n\taccessToken: string\n\trefreshToken: string\n\tisLoggedIn: boolean\n}\n\nconst initialState: AuthState = {\n\taccessToken: \"\",\n\trefreshToken: \"\",\n\tisLoggedIn: false,\n}\n\n/**\n * Stores the auth state of the app (tokens, and whether user is logged in or not)\n */\nexport const authSlice = createSlice({\n\tname: \"auth\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tsetTokens: (state, action: PayloadAction<TokenPair>) => {\n\t\t\tstate.accessToken = action.payload.accessToken\n\t\t\tstate.refreshToken = action.payload.refreshToken\n\t\t},\n\t\tclearTokens: (state) => {\n\t\t\tstate.accessToken = \"\"\n\t\t\tstate.refreshToken = \"\"\n\t\t},\n\t\tsetLoggedIn: (state, action: PayloadAction<boolean>) => {\n\t\t\tif (!action.payload) {\n\t\t\t\tauthSlice.caseReducers.clearTokens(state)\n\t\t\t}\n\t\t\tstate.isLoggedIn = action.payload\n\t\t},\n\t},\n})\n\nexport const { setTokens, clearTokens, setLoggedIn } = authSlice.actions\nexport const selectAccessToken = (state: BaseState) => state.authReducer.accessToken\nexport const selectIsLoggedIn = (state: BaseState) => state.authReducer.isLoggedIn\n\nexport const authReducer: Reducer<AuthState> = authSlice.reducer\n","import L from \"leaflet\"\nimport { Bounds, Coordinates, MultiPointGeometry, PointGeometry } from \"../typings\"\n\n// Convert our Coordinates type into a Leaflet LatLngLiteral\nexport const coordinatesToLiteral = (coordinates: Coordinates): L.LatLngLiteral => {\n\treturn { lng: coordinates[0], lat: coordinates[1] }\n}\n\n// Convert a Leaflet LatLngLiteral into our Coordinates type\nexport const literalToCoordinates = (literal: L.LatLngLiteral): Coordinates => {\n\treturn [literal.lng, literal.lat]\n}\n\n/**\n * Flip coordinates from [lng, lat] to [lat, lng]\n */\nexport const flipCoordinates = (coordinates: L.LatLngTuple): Coordinates => {\n\treturn [coordinates[1], coordinates[0]]\n}\n\nexport const flipBounds = (bounds: Bounds): Bounds => {\n\treturn [flipCoordinates(bounds[0]), flipCoordinates(bounds[1])]\n}\n\nexport function offsetPositionByMeters(\n\toriginalPosition: L.LatLng,\n\tlatMeters: number,\n\tlngMeters: number,\n): L.LatLngLiteral {\n\tconst { lat, lng } = originalPosition\n\tconst earthRadius = 6378137 // Earth's radius in meters.\n\tconst metersPerDegree = (2 * Math.PI * earthRadius) / 360\n\t// The significance of one degree decreases the closer you get to a pole. This accounts for that.\n\tconst newLng = lng + lngMeters / metersPerDegree / Math.cos((lat * Math.PI) / 180)\n\tconst newLat = lat - latMeters / metersPerDegree\n\treturn { lat: newLat, lng: newLng }\n}\n\nexport const createPointGeometry = (coordinates: Coordinates): PointGeometry => {\n\treturn {\n\t\ttype: \"Point\",\n\t\tcoordinates,\n\t}\n}\n\nexport const coordinatesAreEqual = (a: Coordinates, b: Coordinates): boolean => {\n\treturn a[0] === b[0] && a[1] === b[1]\n}\n\n// export const coordinatesAreNearlyEqual = (a: Coordinates, b: Coordinates, thresholdMeters: number): boolean => {\n// return a === b\n// TODO: Fix\n// const diffLat = Math.abs(a[1] - b[1])\n// Length in km of 1° of latitude = always 111.32 km\n// const diffLatMeters = diffLat * 111320\n// if (diffLatMeters < thresholdMeters) return true\n// Length in km of 1° of longitude = 40075 km * cos(latitude) / 360'\n// const aVal = a[0] // Optimization\n// const diffLong = Math.abs(aVal - b[0])\n// const diffLongMeters = diffLong * ((40075000 * Math.cos(aVal)) / 360)\n// return diffLongMeters < thresholdMeters\n// }\n\n// This converts a Coordinate [lng, lat] to \"lat, lng\" string format with an option to round the numbers\nexport const coordinatesToText = (coordinates: Coordinates | null | undefined, decimalPlaces?: number) => {\n\tif (!coordinates) return \"(No Location)\"\n\tconst { lat, lng } = coordinatesToLiteral(coordinates)\n\tif (decimalPlaces) return `${lat.toFixed(decimalPlaces)}, ${lng.toFixed(decimalPlaces)}`\n\treturn `${lat}, ${lng}`\n}\n\nexport const coordinatesToUrlText = (coordinates: Coordinates) => {\n\tconst { lat, lng } = coordinatesToLiteral(coordinates)\n\treturn `${lat}%2C${lng}`\n}\n\n// Opens coordinates in Google maps\nexport const openCoordsInGoogleMaps = (coordinates: Coordinates) => {\n\tconst url = `https://www.google.com/maps/search/?api=1&query=${coordinatesToUrlText(coordinates)}`\n\twindow.open(url)\n}\n\nexport const openDirectionsInGoogleMaps = (startingPoint: Coordinates, destination: Coordinates) => {\n\tconst startingPointUrl = coordinatesToUrlText(startingPoint)\n\tconst destinationUrl = coordinatesToUrlText(destination)\n\tconst url = `https://www.google.com/maps/dir/?api=1&origin=${startingPointUrl}&destination=${destinationUrl}`\n\twindow.open(url)\n}\n\nexport const worldBounds: MultiPointGeometry = {\n\ttype: \"MultiPoint\",\n\tcoordinates: [\n\t\t[90, -180],\n\t\t[-90, 180],\n\t],\n}\n\nexport const createMultiPointGeometry = (coordinates: [Coordinates, Coordinates]): MultiPointGeometry => {\n\treturn {\n\t\ttype: \"MultiPoint\",\n\t\tcoordinates,\n\t}\n}\n","/**\n * Combines multiple class names into a single string. Keys are class names and values are booleans.\n * If the value is true, the key is added to the string.\n */\nexport function classNames(...args: (object | string | undefined | null | number)[]): string {\n\tconst classes: string[] = []\n\tfor (const arg of args) {\n\t\tif (!arg) {\n\t\t\tcontinue\n\t\t}\n\t\tif (typeof arg === \"string\") {\n\t\t\tclasses.push(arg)\n\t\t} else if (typeof arg === \"object\") {\n\t\t\tfor (const [key, value] of Object.entries(arg)) {\n\t\t\t\tif (value) {\n\t\t\t\t\tclasses.push(key)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn classes.join(\" \")\n}\n","import { saveAs } from \"file-saver\"\nimport { FileUploadPayload } from \"../typings\"\n\n// See: https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#converting_a_digest_to_a_hex_string\nfunction hex(buffer: ArrayBufferLike): string {\n\tconst hashArray = new Uint8Array(buffer)\n\n\treturn hashArray.reduce((data, byte) => data + byte.toString(16).padStart(2, \"0\"), \"\")\n}\n\nexport const getFileS3Key = async (file: File, hash?: string) => {\n\tif (!hash) {\n\t\thash = await hashFile(file)\n\t}\n\tlet fileType = file.type\n\tif (fileType.includes(\"/\")) {\n\t\tfileType = fileType.split(\"/\")[1]!\n\t}\n\tif (!fileType) {\n\t\tthrow new Error(`Could not extract file type from ${file.type}`)\n\t}\n\treturn `${hash}.${fileType}`\n}\n\nexport function hashFile(file: Blob): Promise<string> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst reader = new FileReader()\n\t\t// Provide an onload callback for this instance of FileReader\n\t\t// This is called once reader.readAsArrayBuffer() is done\n\t\treader.onload = () => {\n\t\t\tconst fileResult = reader.result as ArrayBuffer | null\n\t\t\tif (!fileResult) {\n\t\t\t\treject()\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tvoid crypto.subtle.digest(\"SHA-1\", fileResult).then((hash) => {\n\t\t\t\tconst sha1result = hex(hash)\n\t\t\t\tresolve(sha1result)\n\t\t\t})\n\t\t}\n\n\t\t// calling reader.readAsArrayBuffer and providing a file should trigger the callback above\n\t\t// as soon as readAsArrayBuffer is complete\n\t\treader.readAsArrayBuffer(file)\n\t})\n}\n\nexport function getFileIdentifier(file: File): string {\n\tif (!file.name || !file.type || !file.size) {\n\t\tconst message = \"File has no name, type, and/or size\"\n\t\tconsole.error(`${message}`, file)\n\t\tthrow new Error(`${message}.`)\n\t}\n\treturn `${file.name}&${file.type}${file.size}`\n}\n\nexport function getRenamedFile(file: File, newName: string): File & { name: string } {\n\treturn new File([file], newName, { type: file.type })\n}\n\nexport function downloadInMemoryFile(filename: string, text: string) {\n\tconst element = document.createElement(\"a\")\n\telement.setAttribute(\"href\", \"data:text/plain;charset=utf-8,\" + encodeURIComponent(text))\n\telement.setAttribute(\"download\", filename)\n\n\telement.style.display = \"none\"\n\tdocument.body.appendChild(element)\n\n\telement.click()\n\n\tdocument.body.removeChild(element)\n}\n\n// TODO: implement to not block ui when hashing https://developer.chrome.com/blog/introducing-scheduler-yield-origin-trial\nexport const constructUploadedFilePayloads = async (files: File[]): Promise<FileUploadPayload[]> => {\n\tconst filePayloads: Record<string, FileUploadPayload> = {}\n\tfor (const file of files) {\n\t\tconst sha1 = await hashFile(file)\n\t\tfilePayloads[sha1] = {\n\t\t\tsha1,\n\t\t\textension: file.name.split(\".\").pop() || \"\",\n\t\t\tfile_type: file.type,\n\t\t\tsize: file.size,\n\t\t}\n\t}\n\treturn Object.values(filePayloads)\n}\n\nexport const fileToBlob = async (dataUrl: string): Promise<Blob> => {\n\t// TODO: Is this as reliable and supported as this?\n\t// https://www.nixtu.info/2013/06/how-to-upload-canvas-data-to-server.html\n\treturn (await fetch(dataUrl)).blob()\n}\n\nexport const blobToBase64 = (blob: Blob): Promise<string> => {\n\treturn new Promise((resolve, _) => {\n\t\tconst reader = new FileReader()\n\t\treader.onloadend = () => {\n\t\t\tresolve(reader.result?.toString() || \"\")\n\t\t}\n\t\treader.readAsDataURL(blob)\n\t})\n}\n\n// TODO:\n/** Converts a profile `file` and `fileSha1` into an img src that can be rendered. This relies on an API request. */\n\nexport function downloadFile(file: File) {\n\tconst blob = new Blob([file])\n\tsaveAs(blob, file.name)\n}\n","const logCache: Record<string, Record<string, boolean> | undefined> = {}\n\n/**\n * Logging the same message over and over again in a loop takes a lot of resources and makes the app laggy. This utility\n * function accepts a log ID (e.g. \"issue-has-no-index-workspace\") and an object ID (e.g. the offline_id of an issue),\n * and only logs the message on the first call with the same combination of logId and objId.\n * @param logId An arbitrary but unique identifier for this \"type of message\".\n * @param objId A unique identifier for the object the message regards. Can be an arbitrary string, e.g. \"current-user\"\n * or an actual object ID, e.g. the offline_id of an issue.\n * @param level The log level to use. For example, \"debug\" means `console.debug` will be called.\n * @param args The arguments to pass to the console log method.\n */\nexport function logOnlyOnce(\n\tlogId: string,\n\tobjId: string,\n\tlevel: \"debug\" | \"info\" | \"warn\" | \"error\",\n\t...args: unknown[]\n) {\n\tconst thisLogIdCache = logCache[logId]\n\tlet shouldLog = false\n\tif (!thisLogIdCache) {\n\t\tlogCache[logId] = { [objId]: true }\n\t\tshouldLog = true\n\t} else {\n\t\tconst hasLoggedForThisObject = thisLogIdCache[objId]\n\t\tif (!hasLoggedForThisObject) {\n\t\t\tthisLogIdCache[objId] = true\n\t\t\tshouldLog = true\n\t\t}\n\t}\n\tif (shouldLog) {\n\t\tconsole[level](...args)\n\t}\n}\n","import { Offline, OfflineModel } from \"../typings\"\nimport { v4 as uuidv4 } from \"uuid\"\n\n/**\n * Adds a generated UUID to the \"offline_id\" key of the object.\n * @param draft The model data to add the offline_id to\n */\nexport function offline<T>(draft: T): Offline<T> {\n\treturn { ...draft, offline_id: uuidv4() } as Offline<T>\n}\n\n/**\n * Converts an array of OfflineModel objects to a Record<string, TModel>, mapping an offline ID to the object with that\n * offline ID.\n * @param array An array of offline model instances\n */\nexport function toOfflineIdRecord<TModel extends OfflineModel>(array: TModel[]): Record<string, TModel> {\n\tconst asMapping: Record<string, TModel> = {}\n\tfor (const item of array) {\n\t\tasMapping[item.offline_id] = item\n\t}\n\treturn asMapping\n}\n","import { SearchResult, Stored } from \"../typings\"\nimport { Issue } from \"../typings\"\n\nexport const issueToSearchResult = (issue: Stored<Issue>, tag: string | null): SearchResult<Stored<Issue>> => {\n\treturn {\n\t\tlabel: issue.title || \"\",\n\t\ttypeLabel: \"issue\",\n\t\ttag: tag,\n\t\titem: issue,\n\t}\n}\n","/**\n * Returns a file-safe string from arbitrary text. Will return maximum 255 characters, which is the longest safe\n * Long File Name (LFN).\n * WARNING! May give poor performance in big loops.\n * @param str The string to make safe for file names.\n * @param extension An extension (not including a period) to be added after a period at the end of the string. The\n * character limit of the returned string includes the extension, meaning characters from str will be removed to\n * accommodate it if necessary.\n * @param maxLength The maximum length of the resulting file name. Defaults to 255.\n */\nexport function toFileNameSafeString(str: string, extension: string | undefined = undefined, maxLength = 255): string {\n\tlet ret = str.replace(/[^a-z0-9_\\-.]/gi, \"_\").replace(/_{2,}/g, \"_\")\n\tif (!extension) {\n\t\tconst parts = str.split(\".\")\n\t\tif (parts.length > 1) {\n\t\t\textension = parts[parts.length - 1]\n\t\t}\n\t}\n\tif (extension && !extension.startsWith(\".\")) {\n\t\textension = \".\" + extension\n\t}\n\tconst extensionLengthWithPeriod = extension ? extension.length : 0\n\n\tif (ret.length + extensionLengthWithPeriod > maxLength) {\n\t\tret = ret.slice(0, maxLength - extensionLengthWithPeriod) + (extension || \"\")\n\t}\n\treturn ret\n}\n\nexport function spacesToDashesLower(value: string): string {\n\treturn value.toLowerCase().replace(\" \", \"-\")\n}\n\nexport function slugify(str: string, underscore = false) {\n\treturn str\n\t\t.normalize(\"NFKD\")\n\t\t.toLowerCase()\n\t\t.replace(/[^\\w\\s-]/g, \"\")\n\t\t.trim()\n\t\t.replace(/[-\\s]+/g, underscore ? \"_\" : \"-\")\n}\n\n/**\n * Given a string, returns a truncated version of it with an ellipsis character at the end if it is longer than\n * maxLength. The resulting string will be no longer than maxLength. Note that the ellipsis is only one character long.\n * @param str The string to truncate.\n * @param maxLength The maximum length of the resulting string, including the ellipsis.\n */\nexport function truncate(str: string, maxLength: number) {\n\tif (str.length <= maxLength) {\n\t\treturn str\n\t}\n\t// -1 to account for the ellipsis character\n\tconst subString = str.slice(0, maxLength - 1)\n\treturn subString.slice(0, subString.lastIndexOf(\" \")) + \"…\"\n}\n","import { Coordinates, IssueAttachment, OfflineModel, OvermapRootState } from \"../typings\"\n\ntype MemoizedSelectorWithArgs<TArgs, TRet> = (state: OvermapRootState, args: TArgs) => TRet\n\n// makes the createSelector function fit the current pattern for selectors with arguments\nexport const restructureCreateSelectorWithArgs =\n\t<TArgs, TRet>(selector: MemoizedSelectorWithArgs<TArgs, TRet>) =>\n\t(args: TArgs) =>\n\t(state: OvermapRootState) =>\n\t\tselector(state, args)\n\nexport function onlyUniqueOfflineIds(value: OfflineModel, index: number, self: OfflineModel[]) {\n\treturn self.findIndex((v) => v.offline_id === value.offline_id) === index\n}\n\nexport function onlyUniqueHashes(value: IssueAttachment, index: number, self: IssueAttachment[]) {\n\treturn (\n\t\tself.findIndex((v: IssueAttachment) => {\n\t\t\treturn v.file_sha1 === value.file_sha1\n\t\t}) === index\n\t)\n}\n\n/**\n *\n * @param bounds order: [northEast, southWest]\n * @param coordinates\n */\nexport function boundsContainPoint(bounds: [Coordinates, Coordinates], coordinates: Coordinates): boolean {\n\t// TODO: this is flipped for Marker (Geometry)\n\treturn (\n\t\tbounds[0][0] > coordinates[0] &&\n\t\tbounds[1][0] < coordinates[0] &&\n\t\tbounds[0][1] > coordinates[1] &&\n\t\tbounds[1][1] < coordinates[1]\n\t)\n}\n\nexport const emailRegex = /^.+@.+\\..+$/\n","import React, { useEffect, useRef } from \"react\"\n\nlet debug = false\n\nconst REACT_APP_DEBUG_MEMOIZATION = (import.meta.env.REACT_APP_DEBUG_MEMOIZATION as string | undefined) || \"\"\n\nif ([\"true\", \"1\"].includes(REACT_APP_DEBUG_MEMOIZATION.toLowerCase())) {\n\tdebug = true\n}\n\nexport function shallowEqual(objA: Record<string, unknown>, objB: Record<string, unknown>) {\n\t// Check if they're the same object (objA is objB) -- just a quick reference check\n\tif (objA === objB) return true\n\n\tif (typeof objA !== typeof objB) {\n\t\treturn false\n\t}\n\n\tconst keysA = Object.keys(objA)\n\tconst keysB = Object.keys(objB)\n\n\t// Only calculate this once\n\tconst keysALength = keysA.length\n\tif (keysALength !== keysB.length) return false\n\n\tfor (let i = 0; i < keysALength; i++) {\n\t\tconst key = keysA[i]!\n\t\tif (!Object.prototype.hasOwnProperty.call(objB, key) || objA[key] !== objB[key]) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\nexport function memoize<T extends (...args: never[]) => unknown>(func: T): T {\n\t// Taken from https://www.sitepoint.com/implementing-memoization-in-javascript/\n\tconst memo = {}\n\n\treturn function () {\n\t\t// eslint-disable-next-line prefer-rest-params\n\t\tconst args = Array.prototype.slice.call(arguments) as never[]\n\n\t\t// SEE: https://stackoverflow.com/questions/10173956/how-to-use-array-as-key-in-javascript\n\n\t\t// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n\t\t// @ts-expect-error\n\t\tif (args in memo) {\n\t\t\tif (debug) {\n\t\t\t\tconsole.debug(`Memoization debug: Using memorized return value for ${func.toString()}(`, args, \")\")\n\t\t\t}\n\t\t\t// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n\t\t\t// @ts-expect-error\n\t\t\treturn memo[args] as T\n\t\t} else {\n\t\t\tif (debug) {\n\t\t\t\tconsole.debug(`Memoization debug: Cache miss! Memoizing ${func.toString()}(`, args, \")\")\n\t\t\t}\n\t\t\t// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n\t\t\t// @ts-expect-error\n\t\t\treturn (memo[args] = func.apply(this, args))\n\t\t}\n\t} as T\n}\n\nexport type EqualityChecker<TArgs> = (current: TArgs, previous: TArgs) => boolean\n\nexport function useMemoCompare<TValue>(\n\tnext: TValue | undefined,\n\tcompare: (prev: TValue | undefined, next: TValue | undefined) => boolean,\n): TValue | undefined {\n\t// Ref for storing previous value\n\tconst previousRef = useRef<TValue>(undefined)\n\tconst previous: TValue | undefined = previousRef.current\n\n\t// Pass previous and next value to compare function\n\t// to determine whether to consider them equal.\n\tconst isEqual = compare(previous, next)\n\n\t// If not equal update previousRef to next value.\n\t// We only update if not equal so that this hook continues to return\n\t// the same old value if compare keeps returning true.\n\tuseEffect(() => {\n\t\tif (!isEqual) {\n\t\t\tpreviousRef.current = next\n\t\t}\n\t})\n\n\t// Finally, if equal then return the previous value\n\treturn isEqual ? previous : next\n}\n\n/**\n * Performs an equality check by contents in order.\n * Reference types like objects and arrays are compared by reference.\n */\nexport function areArraysEqual(first: unknown[], second: unknown[]) {\n\tif (first.length !== second.length) return false\n\tfor (let i = 0; i < first.length; i++) {\n\t\tif (first[i] !== second[i]) return false\n\t}\n\treturn true\n}\n\nexport const genericMemo: <T>(component: T) => T = React.memo\n","import { default as ColorCls } from \"color\"\nimport {\n\tgray,\n\tgold,\n\tbrown,\n\tyellow,\n\tamber,\n\torange,\n\tred,\n\tcrimson,\n\tpink,\n\tplum,\n\tpurple,\n\tviolet,\n\tiris,\n\tindigo,\n\tblue,\n\tcyan,\n\tjade,\n\tgrass,\n\tlime,\n\tmint,\n\tsky,\n} from \"@radix-ui/colors\"\nimport { CSSColor } from \"../typings\"\n\n// TODO: Move most of these constants into src/theme/variables.ts\nexport const primaryColor: CSSColor = \"#2D55E2\"\nexport const successColor: CSSColor = \"#349C55\"\nexport const warningColor: CSSColor = \"#FFA620\"\nexport const errorColor: CSSColor = \"#E24C4C\"\nexport const GREEN: CSSColor = \"#1fd155\"\nexport const YELLOW: CSSColor = \"#f5de14\"\nexport interface BadgeColors {\n\tbackgroundColor: CSSColor\n\ttextColor: CSSColor\n}\n\n// Colors used for color selection purposes\nexport const Colors: Record<string, CSSColor> = {\n\tgray: (gray as Record<string, CSSColor>).gray9!,\n\tgold: (gold as Record<string, CSSColor>).gold9!,\n\tbrown: (brown as Record<string, CSSColor>).brown9!,\n\tyellow: (yellow as Record<string, CSSColor>).yellow9!,\n\tamber: (amber as Record<string, CSSColor>).amber9!,\n\torange: (orange as Record<string, CSSColor>).orange9!,\n\tred: (red as Record<string, CSSColor>).red9!,\n\tcrimson: (crimson as Record<string, CSSColor>).crimson9!,\n\tpink: (pink as Record<string, CSSColor>).pink9!,\n\tplum: (plum as Record<string, CSSColor>).plum9!,\n\tpurple: (purple as Record<string, CSSColor>).purple9!,\n\tviolet: (violet as Record<string, CSSColor>).violet9!,\n\tiris: (iris as Record<string, CSSColor>).iris9!,\n\tindigo: (indigo as Record<string, CSSColor>).indigo9!,\n\tblue: (blue as Record<string, CSSColor>).blue9!,\n\tcyan: (cyan as Record<string, CSSColor>).cyan9!,\n\tjade: (jade as Record<string, CSSColor>).jade9!,\n\tgrass: (grass as Record<string, CSSColor>).grass9!,\n\tlime: (lime as Record<string, CSSColor>).lime9!,\n\tmint: (mint as Record<string, CSSColor>).mint9!,\n\tsky: (sky as Record<string, CSSColor>).sky9!,\n}\n\n// Colors used for asset stages\nexport const AssetStageColors: Record<string, CSSColor> = {\n\tindigo: (indigo as Record<string, CSSColor>).indigo9!,\n\tred: (red as Record<string, CSSColor>).red9!,\n\tviolet: (violet as Record<string, CSSColor>).violet9!,\n\tyellow: (yellow as Record<string, CSSColor>).yellow9!,\n\tjade: (jade as Record<string, CSSColor>).jade9!,\n\tcyan: (cyan as Record<string, CSSColor>).cyan9!,\n\tgold: (gold as Record<string, CSSColor>).gold9!,\n\torange: (orange as Record<string, CSSColor>).orange9!,\n\tlime: (lime as Record<string, CSSColor>).lime9!,\n\tsky: (sky as Record<string, CSSColor>).sky9!,\n\tpink: (pink as Record<string, CSSColor>).pink9!,\n}\n\nexport const defaultBadgeColor: CSSColor = \"#868686\"\n\n// This function adjusts a given colour into two variations for use as badge colours\nexport const generateBadgeColors = (rawColor: CSSColor): BadgeColors => {\n\tconst color = ColorCls(rawColor)\n\tconst safety = ColorCls(YELLOW)\n\tconst backgroundColor: CSSColor = color.darken(0.09).hex() as CSSColor\n\t// If the color matches the special yellow safety color, make the text black\n\tconst textColor = color.hex() === safety.hex() ? \"#000000\" : \"#FFFFFF\"\n\t// Alternate style:\n\t// const backgroundColor = color.lighten(0.4).hex()\n\t// const textColor = color.darken(0.6).hex()\n\n\treturn { backgroundColor, textColor }\n}\n\nexport function getStageColor(index: number): CSSColor {\n\treturn Object.values(AssetStageColors)[index % Object.keys(AssetStageColors).length]!\n}\n","import { memoize } from \"./optimization\"\n\n/** Only shows year if a past year */\nexport const getLocalDateString = memoize((date?: string | null | Date | number) => {\n\tif (!date) return \"\"\n\tconst asDate = new Date(date)\n\tconst isThisYear = asDate.getFullYear() === today.getFullYear()\n\tconst options: Intl.DateTimeFormatOptions = { day: \"numeric\", month: \"short\" }\n\tif (!isThisYear) options.year = \"numeric\"\n\treturn asDate.toLocaleDateString([], options)\n})\n\nconst relative = new Intl.RelativeTimeFormat([], { style: \"long\", numeric: \"auto\" })\nconst msInDay = 1000 * 86400\nconst today = new Date()\n\n/** Returns true if the given date is today */\nexport const isToday = (date: string | Date | number) => {\n\treturn new Date(date).toDateString() === today.toDateString()\n}\n\n/*\nDisplays a relative message \"in 2 days\" or \"today\" if within the given period (min, max)\nOtherwise, falls back to getLocalDateString()\n*/\nexport const getLocalRelativeDateString = memoize((date: string | Date | number, min: number, max: number) => {\n\tconst days = Math.round((new Date(date).getTime() - today.getTime()) / msInDay)\n\tif (days < min || days > max) return getLocalDateString(date)\n\treturn relative.format(days, \"days\")\n})\n","import { PayloadAction } from \"@reduxjs/toolkit\"\nimport { ModelState } from \"./typings\"\n\nexport interface OvermapModelAdapter<TModel> {\n\taddOne: <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel>) => void\n\taddMany: <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel[]>) => void\n\tsetOne: <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel>) => void\n\tsetMany: <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel[]>) => void\n\tupdateOne: <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel>) => void\n\tupdateMany: <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel[]>) => void\n\tdeleteOne: <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<string>) => void\n\tdeleteMany: <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<string[]>) => void\n\tinitialize: <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel[]>) => void\n\tgetInitialState: <TState extends object>(state: TState) => TState & ModelState<TModel>\n}\n\nexport function createModelAdapter<TModel>(computeModelId: (model: TModel) => string): OvermapModelAdapter<TModel> {\n\tconst addOne = <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel>) => {\n\t\t// TODO: error check here if the model already exists?\n\t\tconst id = computeModelId(action.payload)\n\t\tstate.instances[id] = action.payload\n\t}\n\n\tconst addMany = <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel[]>) => {\n\t\tfor (const model of action.payload) {\n\t\t\t// TODO: error check here if the model already exists?\n\t\t\tconst id = computeModelId(model)\n\t\t\tstate.instances[id] = model\n\t\t}\n\t}\n\n\tconst setOne = <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel>) => {\n\t\tconst id = computeModelId(action.payload)\n\t\tstate.instances[id] = action.payload\n\t}\n\n\tconst setMany = <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel[]>) => {\n\t\tfor (const model of action.payload) {\n\t\t\tconst id = computeModelId(model)\n\t\t\tstate.instances[id] = model\n\t\t}\n\t}\n\n\tconst updateOne = <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel>) => {\n\t\tconst id = computeModelId(action.payload)\n\t\tstate.instances[id] = action.payload\n\t}\n\n\tconst updateMany = <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel[]>) => {\n\t\tfor (const model of action.payload) {\n\t\t\tconst id = computeModelId(model)\n\t\t\tstate.instances[id] = model\n\t\t}\n\t}\n\n\tconst deleteOne = <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<string>) => {\n\t\tdelete state.instances[action.payload]\n\t}\n\n\tconst deleteMany = <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<string[]>) => {\n\t\tfor (const id of action.payload) {\n\t\t\tdelete state.instances[id]\n\t\t}\n\t}\n\n\tconst initialize = <TState extends ModelState<TModel>>(state: TState, action: PayloadAction<TModel[]>) => {\n\t\tstate.instances = {}\n\t\tfor (const model of action.payload) {\n\t\t\t// TODO: error check here if the model already exists?\n\t\t\tconst id = computeModelId(model)\n\t\t\tstate.instances[id] = model\n\t\t}\n\t}\n\n\tconst getInitialState = <TState extends object>(state: TState) => {\n\t\treturn {\n\t\t\t...state,\n\t\t\tinstances: {} as Record<string, TModel>,\n\t\t}\n\t}\n\n\treturn {\n\t\taddOne,\n\t\taddMany,\n\t\tsetOne,\n\t\tsetMany,\n\t\tupdateOne,\n\t\tupdateMany,\n\t\tdeleteOne,\n\t\tdeleteMany,\n\t\tinitialize,\n\t\tgetInitialState,\n\t}\n}\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport { Category, OvermapRootState, OvermapSelectorWithArgs, Stored } from \"../../typings\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\n\nexport type CategoryState = ModelState<Stored<Category>>\n\nconst categoryAdapter = createModelAdapter<Stored<Category>>((category) => category.offline_id)\n\nconst initialState: CategoryState = categoryAdapter.getInitialState({})\n\nexport const categorySlice = createSlice({\n\tname: \"categories\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeCategories: categoryAdapter.initialize,\n\t\taddCategory: categoryAdapter.addOne,\n\t\tupdateCategory: categoryAdapter.updateOne,\n\t\tdeleteCategory: categoryAdapter.deleteOne,\n\t},\n})\n\nexport const { initializeCategories, addCategory, updateCategory, deleteCategory } = categorySlice.actions\n\nexport const selectCategoryMapping = (state: OvermapRootState) => state.categoryReducer.instances\n\nexport const selectCategories = createSelector([selectCategoryMapping], (categoryMapping) => {\n\treturn Object.values(categoryMapping)\n})\n\nexport const selectCategoryById: OvermapSelectorWithArgs<string, Stored<Category> | undefined> =\n\t(id: Category[\"offline_id\"]) => (state) => {\n\t\treturn state.categoryReducer.instances[id]\n\t}\n\nexport const selectCategoriesByIds = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectCategoryMapping, (_state, categoryIds: Category[\"offline_id\"][]) => categoryIds],\n\t\t(categoryMapping, categoryIds) => {\n\t\t\tconst categories: Stored<Category>[] = []\n\n\t\t\tfor (const categoryId of categoryIds) {\n\t\t\t\tconst category = categoryMapping[categoryId]\n\n\t\t\t\tif (category) {\n\t\t\t\t\tcategories.push(category)\n\t\t\t\t} else {\n\t\t\t\t\tconsole.warn(\"selectCategoryByIds: No category exists with the id\", categoryId)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn categories\n\t\t},\n\t),\n)\n\nexport const selectCategoriesOfWorkspace: OvermapSelectorWithArgs<string, Category[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector([selectCategories, (_state, workspaceId: string) => workspaceId], (categories, workspaceId) =>\n\t\t\tcategories.filter((category) => category.workspace === workspaceId),\n\t\t),\n\t)\n\nexport const selectIssueCountOfCategory: OvermapSelectorWithArgs<string | null, number> =\n\t(categoryId) => (state: OvermapRootState) => {\n\t\treturn Object.values(state.issueReducer.instances).filter((issue) => issue.category === categoryId).length\n\t}\n\nexport const categoryReducer: Reducer<CategoryState> = categorySlice.reducer\n","import type { Reducer } from \"@reduxjs/toolkit\"\nimport { createSelector, createSlice } from \"@reduxjs/toolkit\"\nimport { AssetType, OvermapRootState, OvermapSelector, OvermapSelectorWithArgs, Stored } from \"../../typings\"\nimport type { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport type AssetTypeState = ModelState<Stored<AssetType>>\n\nconst assetTypeAdapter = createModelAdapter<Stored<AssetType>>((assetType) => assetType.offline_id)\n\nconst initialState: AssetTypeState = assetTypeAdapter.getInitialState({})\n\nexport const assetTypeSlice = createSlice({\n\tname: \"assetTypes\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeAssetTypes: assetTypeAdapter.initialize,\n\t\taddAssetType: assetTypeAdapter.addOne,\n\t\tdeleteAssetType: assetTypeAdapter.deleteOne,\n\t},\n})\n\nexport const { addAssetType, initializeAssetTypes, deleteAssetType } = assetTypeSlice.actions\n\nexport const selectAssetTypesMapping: OvermapSelector<Record<string, AssetType>> = (state: OvermapRootState) =>\n\tstate.assetTypeReducer.instances\n\nexport const selectAssetTypes: OvermapSelector<AssetType[]> = createSelector([selectAssetTypesMapping], (mapping) =>\n\tObject.values(mapping),\n)\n\nexport const selectAssetTypeById: OvermapSelectorWithArgs<AssetType[\"offline_id\"], Stored<AssetType> | undefined> =\n\t(id: AssetType[\"offline_id\"]) => (state) => {\n\t\treturn state.assetTypeReducer.instances[id]\n\t}\n\nexport const selectAssetTypesByIds = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectAssetTypesMapping, (_state, assetTypeIds: AssetType[\"offline_id\"][]) => assetTypeIds],\n\t\t(assetTypeMapping, assetTypeIds) => {\n\t\t\tconst assetTypes: Stored<AssetType>[] = []\n\n\t\t\tfor (const assetTypeId of assetTypeIds) {\n\t\t\t\tconst assetType = assetTypeMapping[assetTypeId]\n\n\t\t\t\tif (assetType) {\n\t\t\t\t\tassetTypes.push(assetType)\n\t\t\t\t} else {\n\t\t\t\t\tconsole.warn(\"selectAssetTypesByIds: No assetType exists with the id\", assetTypeId)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn assetTypes\n\t\t},\n\t),\n)\n\nexport const assetTypeReducer: Reducer<AssetTypeState> = assetTypeSlice.reducer\n","import { createSelector, createSlice, PayloadAction, Reducer } from \"@reduxjs/toolkit\"\nimport {\n\tAsset,\n\tAssetType,\n\tOvermapRootState,\n\tOvermapSelector,\n\tOvermapSelectorWithArgs,\n\tStored,\n\tSubmitted,\n} from \"../../typings\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\nimport { selectAssetTypesMapping } from \"./assetTypeSlice\"\nimport { createModelAdapter } from \"../adapter\"\nimport { ModelState } from \"../typings\"\n\nexport type AssetState = ModelState<Stored<Asset>>\n\nconst assetAdapter = createModelAdapter<Stored<Asset>>((asset) => asset.offline_id)\n\nconst initialState: AssetState = assetAdapter.getInitialState({})\n\nexport const assetSlice = createSlice({\n\tname: \"assets\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeAssets: (state, action: PayloadAction<Asset[]>) => {\n\t\t\tassetAdapter.initialize(state, action)\n\t\t\tprevAssets = null\n\t\t},\n\t\taddAsset: (state, action: PayloadAction<Asset>) => {\n\t\t\tassetAdapter.addOne(state, action)\n\t\t\tprevAssets = null\n\t\t},\n\t\taddAssets: (state, action: PayloadAction<(Asset | Submitted<Asset>)[]>) => {\n\t\t\tassetAdapter.addMany(state, action)\n\t\t\tprevAssets = null\n\t\t},\n\t\tsetAsset: (state, action: PayloadAction<Asset>) => {\n\t\t\tassetAdapter.setOne(state, action)\n\t\t\tprevAssets = null\n\t\t},\n\t\tsetAssets: (state, action: PayloadAction<Asset[]>) => {\n\t\t\tassetAdapter.setMany(state, action)\n\t\t\tprevAssets = null\n\t\t},\n\n\t\tupdateAsset: (state, action: PayloadAction<Asset>) => {\n\t\t\tassetAdapter.updateOne(state, action)\n\t\t\tprevAssets = null\n\t\t},\n\t\tupdateAssets: (state, action: PayloadAction<Asset[]>) => {\n\t\t\tassetAdapter.updateMany(state, action)\n\t\t\tprevAssets = null\n\t\t},\n\t\tdeleteAsset: (state, action: PayloadAction<string>) => {\n\t\t\tassetAdapter.deleteOne(state, action)\n\t\t\tprevAssets = null\n\t\t},\n\t\tdeleteAssets: (state, action: PayloadAction<string[]>) => {\n\t\t\tassetAdapter.deleteMany(state, action)\n\t\t\tprevAssets = null\n\t\t},\n\t},\n})\n\nexport const {\n\tinitializeAssets,\n\taddAsset,\n\taddAssets,\n\tupdateAsset,\n\tupdateAssets,\n\tdeleteAsset,\n\tdeleteAssets,\n\tsetAsset,\n\tsetAssets,\n} = assetSlice.actions\n\n// TODO: Reusable helper for this\n// When calling a selector, it returns a new object/array on each call. This causes hooks and assets that depend on\n// assets to rerender, even if the assets themselves haven't changed. We know when assets change (only when\n// one of the reducers above are called), so we can improve the performance of the app significantly by returning an old\n// reference until the cache has been invalidated.\nlet prevAssets: Asset[] | null = null\nexport const selectAssets = (state: OvermapRootState) => {\n\tif (!prevAssets) {\n\t\tprevAssets = Object.values(state.assetReducer.instances)\n\t}\n\treturn prevAssets\n}\n\nexport const selectAssetsMapping = (state: OvermapRootState) => state.assetReducer.instances\n\nexport const selectAssetsOfAssetType: OvermapSelectorWithArgs<string, Asset[]> = restructureCreateSelectorWithArgs(\n\tcreateSelector([selectAssets, (_state, assetTypeId: string) => assetTypeId], (components, assetTypeId) => {\n\t\treturn components.filter((asset) => asset.asset_type === assetTypeId)\n\t}),\n)\n\nexport const selectAssetById: OvermapSelectorWithArgs<string, Asset | undefined> =\n\t(assetId) => (state: OvermapRootState) => {\n\t\treturn state.assetReducer.instances[assetId]\n\t}\n\nexport const selectAssetsByIds = restructureCreateSelectorWithArgs(\n\tcreateSelector([selectAssetsMapping, (_, assetIds: string[]) => assetIds], (assetsMapping, assetIds) => {\n\t\tconst assets: Stored<Asset>[] = []\n\n\t\tfor (const assetId of assetIds) {\n\t\t\tconst asset = assetsMapping[assetId]\n\n\t\t\tif (asset) assets.push(asset)\n\t\t}\n\n\t\treturn assets\n\t}),\n)\n\nexport const selectAssetToAssetTypeMapping: OvermapSelector<Record<string, AssetType>> = createSelector(\n\t[selectAssets, selectAssetTypesMapping],\n\t(assets, assetTypeMapping) => {\n\t\tconst ret: Record<string, AssetType> = {}\n\n\t\tfor (const asset of assets) {\n\t\t\tconst assetType = assetTypeMapping[asset.asset_type]\n\t\t\t// TODO: need to make sure that all asset types are populated for loaded assets, otherwise this error will be produced\n\t\t\tif (!assetType) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t`Asset type with ID ${asset.asset_type} not found.\n\t\t\t\tExpected all referenced asset types to be populated.\n\t\t\t\tReturning empty object to avoid fatal errors.`,\n\t\t\t\t)\n\t\t\t\treturn {}\n\t\t\t}\n\t\t\tret[asset.offline_id] = assetType\n\t\t}\n\n\t\treturn ret\n\t},\n)\n\nexport const selectNumberOfAssetsOfAssetType: OvermapSelectorWithArgs<string, number> = (assetTypeId) => (state) => {\n\treturn selectAssetsOfAssetType(assetTypeId)(state).length\n}\n\nexport const assetReducer: Reducer<AssetState> = assetSlice.reducer\n","import { createSlice, Reducer, createSelector } from \"@reduxjs/toolkit\"\nimport { ModelState } from \"../typings\"\nimport { AssetAttachment, OvermapRootState, OvermapSelector, OvermapSelectorWithArgs, Stored } from \"../../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport type AssetAttachmentState = ModelState<Stored<AssetAttachment>>\n\nconst assetAttachmentAdapter = createModelAdapter<Stored<AssetAttachment>>((attachment) => attachment.offline_id)\n\nconst initialState = assetAttachmentAdapter.getInitialState({})\n\nexport const assetAttachmentSlice = createSlice({\n\tname: \"assetAttachments\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeAssetAttachments: assetAttachmentAdapter.initialize,\n\t\taddAssetAttachment: assetAttachmentAdapter.addOne,\n\t\taddAssetAttachments: assetAttachmentAdapter.addMany,\n\t\tsetAssetAttachment: assetAttachmentAdapter.setOne,\n\t\tsetAssetAttachments: assetAttachmentAdapter.setMany,\n\t\tupdateAssetAttachment: assetAttachmentAdapter.updateOne,\n\t\tupdateAssetAttachments: assetAttachmentAdapter.updateMany,\n\t\tdeleteAssetAttachment: assetAttachmentAdapter.deleteOne,\n\t\tdeleteAssetAttachments: assetAttachmentAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tinitializeAssetAttachments,\n\taddAssetAttachment,\n\taddAssetAttachments,\n\tsetAssetAttachment,\n\tsetAssetAttachments,\n\tupdateAssetAttachment,\n\tupdateAssetAttachments,\n\tdeleteAssetAttachment,\n\tdeleteAssetAttachments,\n} = assetAttachmentSlice.actions\n\nexport const selectAssetAttachmentMapping = (state: OvermapRootState) => state.assetAttachmentReducer.instances\n\nexport const selectAssetAttachments: OvermapSelector<Stored<AssetAttachment>[]> = createSelector(\n\t[selectAssetAttachmentMapping],\n\t(mapping) => Object.values(mapping),\n)\n\nexport const selectAssetAttachment: OvermapSelectorWithArgs<string, Stored<AssetAttachment> | undefined> =\n\t(attachmentId: string) => (state) => {\n\t\treturn state.assetAttachmentReducer.instances[attachmentId]\n\t}\n\nexport const selectAttachmentsOfAsset = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectAssetAttachments, (_state: OvermapRootState, assetId: string) => assetId],\n\t\t(attachments, assetId) => {\n\t\t\treturn attachments.filter(({ asset }) => assetId === asset)\n\t\t},\n\t),\n)\n\nexport const selectAttachmentsOfAssetByType = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectAssetAttachments, (_state: OvermapRootState, assetId: string) => assetId],\n\t\t(attachments, assetId) => {\n\t\t\tconst attachmentsOfAsset = attachments.filter(({ asset }) => assetId === asset)\n\t\t\tconst fileAttachments = attachmentsOfAsset.filter(\n\t\t\t\t// this null check here is necessary, there are cases where file_type is null or undefined\n\t\t\t\t({ file_type }) => !file_type || !file_type.startsWith(\"image/\"),\n\t\t\t)\n\t\t\tconst imageAttachments = attachmentsOfAsset.filter(\n\t\t\t\t// this null check here is necessary, there are cases where file_type is null or undefined\n\t\t\t\t({ file_type }) => file_type && file_type.startsWith(\"image/\"),\n\t\t\t)\n\t\t\treturn { fileAttachments, imageAttachments }\n\t\t},\n\t),\n)\n\nexport const assetAttachmentReducer: Reducer<AssetAttachmentState> = assetAttachmentSlice.reducer\n","import { createSlice, Reducer, PayloadAction, createSelector } from \"@reduxjs/toolkit\"\nimport {\n\tCompletedStagesMapping,\n\tAsset,\n\tOvermapRootState,\n\tOvermapSelectorWithArgs,\n\tAssetStageCompletion,\n} from \"../../typings\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport interface AssetStageCompletionState {\n\tcompletionsByAssetId: CompletedStagesMapping\n}\n\nconst initialState: AssetStageCompletionState = {\n\tcompletionsByAssetId: {},\n}\n\n// TODO: It would be much more performant if completions are stored with assetId keys and stageId[] values\nexport const assetStageCompletionSlice = createSlice({\n\tname: \"assetStageCompletions\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\taddStageCompletion: (state, action: PayloadAction<AssetStageCompletion>) => {\n\t\t\tlet stageToCompletionDateMapping = state.completionsByAssetId[action.payload.asset]\n\t\t\tif (!stageToCompletionDateMapping) {\n\t\t\t\tstageToCompletionDateMapping = {}\n\t\t\t\tstate.completionsByAssetId[action.payload.asset] = stageToCompletionDateMapping\n\t\t\t}\n\t\t\tstageToCompletionDateMapping[action.payload.stage] = new Date().toISOString()\n\t\t},\n\t\taddStageCompletions: (state, action: PayloadAction<CompletedStagesMapping>) => {\n\t\t\tfor (const [assetId, stageIdToCompletionDateMapping] of Object.entries(action.payload)) {\n\t\t\t\tif (Object.keys(stageIdToCompletionDateMapping).length === 0)\n\t\t\t\t\tthrow new Error(`Encountered empty stageIdToCompletionDateMapping argument for asset ${assetId}`)\n\t\t\t\tlet thisAssetCompletions = state.completionsByAssetId[assetId]\n\t\t\t\tif (thisAssetCompletions === undefined) {\n\t\t\t\t\tthisAssetCompletions = {}\n\t\t\t\t}\n\n\t\t\t\tfor (const [stageId, completionDate] of Object.entries(stageIdToCompletionDateMapping)) {\n\t\t\t\t\tthisAssetCompletions[stageId] = completionDate\n\t\t\t\t}\n\n\t\t\t\tstate.completionsByAssetId[assetId] = thisAssetCompletions\n\t\t\t}\n\t\t},\n\t\tremoveStageCompletions: (state, action: PayloadAction<AssetStageCompletion[]>) => {\n\t\t\tfor (const completion of action.payload) {\n\t\t\t\tconst thisAssetCompletions = state.completionsByAssetId[completion.asset]\n\n\t\t\t\tif (!thisAssetCompletions || !(completion.stage in thisAssetCompletions)) {\n\t\t\t\t\t// TODO: This should be an error. We should not construct completions to remove if the stage is not\n\t\t\t\t\t// completed for the asset.\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\"Skipping removal of uncompleted stage. This message indicates completion objects \" +\n\t\t\t\t\t\t\t\"are created unnecessarily.\",\n\t\t\t\t\t)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tdelete thisAssetCompletions[completion.stage]\n\t\t\t}\n\t\t},\n\t\tsetStageCompletions: (state, action: PayloadAction<CompletedStagesMapping>) => {\n\t\t\tstate.completionsByAssetId = action.payload\n\t\t},\n\t},\n})\nexport const { addStageCompletion, addStageCompletions, removeStageCompletions, setStageCompletions } =\n\tassetStageCompletionSlice.actions\n\nexport const selectCompletedStages = (state: OvermapRootState) => {\n\treturn state.assetStageCompletionReducer.completionsByAssetId\n}\n\nexport const selectCompletedStageIdsForAsset: OvermapSelectorWithArgs<Asset, string[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector([selectCompletedStages, (_state, asset: Asset) => asset], (completedStages, asset) => {\n\t\t\treturn Object.keys(completedStages[asset.offline_id] ?? {})\n\t\t}),\n\t)\n\nexport const assetStageCompletionReducer: Reducer<AssetStageCompletionState> = assetStageCompletionSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport { AssetStage, OvermapSelector, OvermapSelectorWithArgs, Stored } from \"../../typings\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\n\nexport type AssetStageState = ModelState<Stored<AssetStage>>\n\nconst assetStageAdapter = createModelAdapter<Stored<AssetStage>>((assetStage) => assetStage.offline_id)\n\nconst initialState = assetStageAdapter.getInitialState({})\n\nexport const assetStageSlice = createSlice({\n\tname: \"assetStages\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeStages: assetStageAdapter.initialize,\n\t\tsetStage: assetStageAdapter.setOne,\n\t\taddStages: assetStageAdapter.addMany,\n\t\tupdateStage: assetStageAdapter.updateOne,\n\t\tupdateStages: assetStageAdapter.updateMany,\n\t\tremoveStages: assetStageAdapter.deleteMany,\n\t},\n})\n\nexport const selectStageMapping: OvermapSelector<Record<AssetStage[\"offline_id\"], AssetStage>> = (state) =>\n\tstate.assetStageReducer.instances\n\nexport const selectAssetStageById: OvermapSelectorWithArgs<string, AssetStage | undefined> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector([selectStageMapping, (_state, stageId: string) => stageId], (stageMapping, stageId) => {\n\t\t\treturn stageMapping[stageId]\n\t\t}),\n\t)\n\nexport const selectAssetStages = createSelector([selectStageMapping], (stageMapping) => {\n\treturn Object.values(stageMapping)\n})\n\nexport const selectStagesFromAssetTypeIds: OvermapSelectorWithArgs<\n\tstring[],\n\tRecord<string, AssetStage[]>\n> = restructureCreateSelectorWithArgs(\n\tcreateSelector([selectAssetStages, (_state, assetTypeIds: string[]) => assetTypeIds], (stages, assetTypeIds) => {\n\t\tconst assetTypeIdsSet = new Set(assetTypeIds)\n\t\tconst ret: Record<string, AssetStage[]> = {}\n\t\tfor (const stage of stages) {\n\t\t\tif (assetTypeIdsSet.has(stage.asset_type)) {\n\t\t\t\tif (!ret[stage.asset_type]) {\n\t\t\t\t\tret[stage.asset_type] = []\n\t\t\t\t}\n\t\t\t\tret[stage.asset_type]!.push(stage)\n\t\t\t}\n\t\t}\n\t\tfor (const key in ret) {\n\t\t\tret[key] = ret[key]!.sort((a, b) => a.priority - b.priority)\n\t\t}\n\t\treturn ret\n\t}),\n)\n\nexport const selectAssetTypeStagesMapping: OvermapSelectorWithArgs<\n\tstring,\n\tRecord<string, AssetStage>\n> = restructureCreateSelectorWithArgs(\n\tcreateSelector([selectStageMapping, (_state, assetTypeId: string) => assetTypeId], (stagesMapping, assetTypeId) => {\n\t\tconst assetTypeStagesMapping: Record<string, AssetStage> = {}\n\t\tfor (const [stageId, stage] of Object.entries(stagesMapping)) {\n\t\t\tif (stage.asset_type === assetTypeId) {\n\t\t\t\tassetTypeStagesMapping[stageId] = stage\n\t\t\t}\n\t\t}\n\t\treturn assetTypeStagesMapping\n\t}),\n)\n\nexport const selectStagesOfAssetType: OvermapSelectorWithArgs<string, AssetStage[]> = restructureCreateSelectorWithArgs(\n\tcreateSelector([selectAssetStages, (_state, assetTypeId: string) => assetTypeId], (stages, assetTypeId) => {\n\t\treturn stages.filter((stage) => stage.asset_type === assetTypeId).sort((a, b) => a.priority - b.priority)\n\t}),\n)\n\nexport const selectAssetStagesByIds = restructureCreateSelectorWithArgs(\n\tcreateSelector([selectStageMapping, (_state, stageIds: string[]) => stageIds], (stageMapping, stageIds) => {\n\t\tconst assetStages: Stored<AssetStage>[] = []\n\n\t\tfor (const stageId of stageIds) {\n\t\t\tconst stage = stageMapping[stageId]\n\n\t\t\tif (stage) {\n\t\t\t\tassetStages.push(stage)\n\t\t\t} else {\n\t\t\t\tconsole.warn(\"selectStagesFromStageIds: No stage exists with the id\", stageId)\n\t\t\t}\n\t\t}\n\n\t\treturn assetStages\n\t}),\n)\n\n// Takes an array of stage ids and returns a record of stage ids to form ids, if the stage has a form\nexport const selectStageFormIdsFromStageIds: OvermapSelectorWithArgs<\n\tstring[],\n\tRecord<string, string>\n> = restructureCreateSelectorWithArgs(\n\tcreateSelector([selectStageMapping, (_state, stageIds: string[]) => stageIds], (stageMapping, stageIds) => {\n\t\tconst ret: Record<string, string> = {}\n\t\tfor (const stageId of stageIds) {\n\t\t\tconst stage = stageMapping[stageId]\n\t\t\tif (!stage) {\n\t\t\t\tthrow new Error(\"No stage exists with the id \" + stageId)\n\t\t\t}\n\t\t\tif (stage.form) {\n\t\t\t\tret[stageId] = stage.form\n\t\t\t}\n\t\t}\n\t\treturn ret\n\t}),\n)\n\nexport const { initializeStages, setStage, addStages, updateStages, removeStages, updateStage } =\n\tassetStageSlice.actions\n\nexport const assetStageReducer: Reducer<AssetStageState> = assetStageSlice.reducer\n","import { createSlice, createSelector, Reducer } from \"@reduxjs/toolkit\"\nimport {\n\tAssetTypeAttachment,\n\ttype OvermapRootState,\n\ttype OvermapSelector,\n\ttype OvermapSelectorWithArgs,\n\tStored,\n} from \"../../typings\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport type AssetTypeAttachmentState = ModelState<Stored<AssetTypeAttachment>>\n\nconst assetTypeAttachmentAdapter = createModelAdapter<Stored<AssetTypeAttachment>>(\n\t(attachment) => attachment.offline_id,\n)\n\nconst initialState = assetTypeAttachmentAdapter.getInitialState({})\n\nexport const assetTypeAttachmentSlice = createSlice({\n\tname: \"assetTypeAttachments\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeAssetTypeAttachments: assetTypeAttachmentAdapter.initialize,\n\t\taddAssetTypeAttachment: assetTypeAttachmentAdapter.addOne,\n\t\taddAssetTypeAttachments: assetTypeAttachmentAdapter.addMany,\n\t\tsetAssetTypeAttachment: assetTypeAttachmentAdapter.setOne,\n\t\tsetAssetTypeAttachments: assetTypeAttachmentAdapter.setMany,\n\t\tupdateAssetTypeAttachment: assetTypeAttachmentAdapter.updateOne,\n\t\tupdateAssetTypeAttachments: assetTypeAttachmentAdapter.updateMany,\n\t\tdeleteAssetTypeAttachment: assetTypeAttachmentAdapter.deleteOne,\n\t\tdeleteAssetTypeAttachments: assetTypeAttachmentAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tinitializeAssetTypeAttachments,\n\taddAssetTypeAttachment,\n\taddAssetTypeAttachments,\n\tsetAssetTypeAttachment,\n\tsetAssetTypeAttachments,\n\tupdateAssetTypeAttachment,\n\tupdateAssetTypeAttachments,\n\tdeleteAssetTypeAttachment,\n\tdeleteAssetTypeAttachments,\n} = assetTypeAttachmentSlice.actions\n\nexport const selectAssetTypeAttachmentMapping = (state: OvermapRootState) => state.assetTypeAttachmentReducer.instances\n\nexport const selectAssetTypeAttachments: OvermapSelector<Stored<AssetTypeAttachment>[]> = createSelector(\n\t[selectAssetTypeAttachmentMapping],\n\t(mapping) => Object.values(mapping),\n)\n\nexport const selectAssetTypeAttachment: OvermapSelectorWithArgs<string, Stored<AssetTypeAttachment> | undefined> =\n\t(attachmentId: string) => (state) => {\n\t\treturn state.assetTypeAttachmentReducer.instances[attachmentId]\n\t}\n\nexport const selectAttachmentsOfAssetType = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectAssetTypeAttachments, (_state: OvermapRootState, assetTypeId: string) => assetTypeId],\n\t\t(attachments, assetTypeId) => {\n\t\t\treturn attachments.filter(({ asset_type }) => assetTypeId === asset_type)\n\t\t},\n\t),\n)\n\nexport const selectAttachmentsOfAssetTypeByType = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectAssetTypeAttachments, (_state: OvermapRootState, assetTypeId: string) => assetTypeId],\n\t\t(attachments, assetTypeId) => {\n\t\t\tconst attachmentsOfAssetType = attachments.filter(({ asset_type }) => asset_type === assetTypeId)\n\t\t\tconst fileAttachments = attachmentsOfAssetType.filter(\n\t\t\t\t// this null check here is necessary, there are cases where file_type is null or undefined\n\t\t\t\t({ file_type }) => !file_type || !file_type.startsWith(\"image/\"),\n\t\t\t)\n\t\t\tconst imageAttachments = attachmentsOfAssetType.filter(\n\t\t\t\t// this null check here is necessary, there are cases where file_type is null or undefined\n\t\t\t\t({ file_type }) => file_type && file_type.startsWith(\"image/\"),\n\t\t\t)\n\t\t\treturn { fileAttachments, imageAttachments }\n\t\t},\n\t),\n)\n\nexport const assetTypeAttachmentReducer: Reducer<AssetTypeAttachmentState> = assetTypeAttachmentSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport { OvermapRootState, OvermapSelector, OvermapSelectorWithArgs, Stored, Workspace } from \"../../typings\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\n\nexport type WorkspaceState = ModelState<Workspace>\n\nconst workspaceAdapter = createModelAdapter<Workspace>((workspace) => workspace.offline_id)\n\nconst initialState: WorkspaceState = workspaceAdapter.getInitialState({})\n\nexport const workspaceSlice = createSlice({\n\tname: \"workspace\",\n\tinitialState,\n\treducers: {\n\t\tinitializeWorkspaces: workspaceAdapter.initialize,\n\t\tsetWorkspaces: workspaceAdapter.setMany,\n\t\taddWorkspace: workspaceAdapter.addOne,\n\t\tupdateWorkspace: workspaceAdapter.updateOne,\n\t\tdeleteWorkspace: workspaceAdapter.deleteOne,\n\t},\n})\n\nexport const { initializeWorkspaces, setWorkspaces, addWorkspace, updateWorkspace, deleteWorkspace } =\n\tworkspaceSlice.actions\n\nexport const selectWorkspaceMapping: OvermapSelector<Record<string, Workspace>> = (state: OvermapRootState) =>\n\tstate.workspaceReducer.instances\n\nexport const selectWorkspaces = createSelector([selectWorkspaceMapping], (mapping) => Object.values(mapping))\n\nexport const selectMainWorkspace: OvermapSelector<Workspace | undefined> = createSelector(\n\t[selectWorkspaces],\n\t(workspaces) => {\n\t\treturn workspaces.find((workspace) => workspace.name.toLowerCase() === \"main\")\n\t},\n)\n\nexport const selectWorkspaceById: OvermapSelectorWithArgs<string, Stored<Workspace> | undefined> = (id) => (state) => {\n\treturn state.workspaceReducer.instances[id]\n}\n\nexport const selectPermittedWorkspaceIds: OvermapSelector<Set<string>> = createSelector(\n\t[selectWorkspaceMapping],\n\t(mapping) => {\n\t\treturn new Set(\n\t\t\tObject.values(mapping)\n\t\t\t\t.filter((workspace: Workspace) => workspace.permitted)\n\t\t\t\t.map((workspace: Workspace) => workspace.offline_id),\n\t\t)\n\t},\n)\n\nexport const workspaceReducer: Reducer<WorkspaceState> = workspaceSlice.reducer\n","import { createSelector, createSlice, PayloadAction, Reducer } from \"@reduxjs/toolkit\"\nimport {\n\tIssue,\n\tOvermapRootState,\n\tOvermapSelector,\n\tOvermapSelectorWithArgs,\n\tSearchableRecentResult,\n\tSearchArgs,\n\tSearchResult,\n\tStored,\n} from \"../../typings\"\nimport { issueToSearchResult, logOnlyOnce, restructureCreateSelectorWithArgs } from \"../../utils\"\nimport { selectWorkspaceMapping } from \"./workspaceSlice\"\nimport { createModelAdapter } from \"../adapter\"\nimport { ModelState } from \"../typings\"\n\nconst maxRecentIssues = 10\ninterface RecentIssueId {\n\tofflineId: string\n\tlastOpenedEpochTime: number\n}\n\nexport interface IssueState extends ModelState<Stored<Issue>> {\n\trecentIssueIds: RecentIssueId[]\n}\n\nconst issueAdapter = createModelAdapter<Stored<Issue>>((issue) => issue.offline_id)\n\nconst initialState: IssueState = issueAdapter.getInitialState({\n\trecentIssueIds: [],\n})\n\nexport const issueSlice = createSlice({\n\tname: \"issues\",\n\tinitialState,\n\textraReducers: (builder) =>\n\t\tbuilder.addCase(\"RESET\", (state) => {\n\t\t\tObject.assign(state, initialState)\n\t\t}),\n\treducers: {\n\t\tinitializeIssues: issueAdapter.initialize,\n\t\taddIssue: issueAdapter.addOne,\n\t\taddIssues: issueAdapter.addMany,\n\t\tupdateIssue: issueAdapter.updateOne,\n\t\tdeleteIssue: issueAdapter.deleteOne,\n\t\tdeleteIssues: issueAdapter.deleteMany,\n\n\t\tcleanRecentIssues: (state) => {\n\t\t\tstate.recentIssueIds = state.recentIssueIds.filter((recentIssue) => state.instances[recentIssue.offlineId])\n\t\t},\n\t\taddToRecentIssues: (state, action: { payload: string }) => {\n\t\t\tstate.recentIssueIds = state.recentIssueIds.filter(\n\t\t\t\t(recentIssue) => recentIssue.offlineId !== action.payload,\n\t\t\t)\n\t\t\tstate.recentIssueIds.push({ offlineId: action.payload.toLowerCase(), lastOpenedEpochTime: Date.now() })\n\n\t\t\tif (state.recentIssueIds.length > maxRecentIssues) {\n\t\t\t\tstate.recentIssueIds.shift()\n\t\t\t}\n\t\t},\n\t\tresetRecentIssues: (state) => {\n\t\t\tstate.recentIssueIds = []\n\t\t},\n\t\tremoveRecentIssue: (state, action: PayloadAction<string>) => {\n\t\t\tconst indexToRemove = state.recentIssueIds.findIndex((item) => {\n\t\t\t\treturn item.offlineId == action.payload\n\t\t\t})\n\t\t\tif (indexToRemove !== -1) {\n\t\t\t\tstate.recentIssueIds.splice(indexToRemove, 1)\n\t\t\t}\n\t\t},\n\t},\n})\n\nexport const {\n\tinitializeIssues,\n\taddIssue,\n\taddIssues,\n\tupdateIssue,\n\tdeleteIssue,\n\tdeleteIssues,\n\n\taddToRecentIssues,\n\tcleanRecentIssues,\n\tremoveRecentIssue,\n\tresetRecentIssues,\n} = issueSlice.actions\n\nexport interface IssueFilterArgs {\n\tfilterByAssignedTo: boolean\n\tfilterByStatus: boolean\n\tfilterByCategory: boolean\n\tfilterByWorkspace: boolean\n}\n\nexport const selectIssueMapping = (state: OvermapRootState) => state.issueReducer.instances\nexport const selectRecentIssueIds = (state: OvermapRootState) => state.issueReducer.recentIssueIds\n\nexport const selectIssueById: OvermapSelectorWithArgs<string, Stored<Issue> | undefined> =\n\t(id: string) => (state: OvermapRootState) => {\n\t\treturn state.issueReducer.instances[id]\n\t}\n\n// TODO: Cache?\nexport const searchIssues: OvermapSelectorWithArgs<SearchArgs, SearchResult<Stored<Issue>>[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector(\n\t\t\t[selectIssueMapping, selectWorkspaceMapping, (_state, searchArgs: SearchArgs) => searchArgs],\n\t\t\t(mapping, workspaceMapping, searchArgs) => {\n\t\t\t\tlet searchTerm = searchArgs.searchTerm\n\t\t\t\tconst maxResults = searchArgs.maxResults\n\t\t\t\tsearchTerm = searchTerm.toLowerCase()\n\t\t\t\tconst ret: SearchResult<Stored<Issue>>[] = []\n\t\t\t\tconst issues = Object.values(mapping)\n\t\t\t\t// This is more performant than repeatedly calling .length\n\t\t\t\tlet nbResults = 0\n\t\t\t\tfor (const issue of issues) {\n\t\t\t\t\t// First, get rid of any issues with no index_workspace. This can happen if the index workspace was deleted,\n\t\t\t\t\t// but the server hasn't responded with a new index in the main workspace. If no index_workspace is\n\t\t\t\t\t// available, we can't calculate the \"tag\" of the search result.\n\t\t\t\t\t// TODO: It's still possible to support search by showing a blank tag.\n\t\t\t\t\tif (!issue.index_workspace) {\n\t\t\t\t\t\tlogOnlyOnce(\n\t\t\t\t\t\t\t\"issue-has-no-index-workspace\",\n\t\t\t\t\t\t\tissue.offline_id,\n\t\t\t\t\t\t\t\"warn\",\n\t\t\t\t\t\t\t`Issue ${issue.offline_id} has no index_workspace and cannot be searched.`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tconst workspace = workspaceMapping[issue.index_workspace]\n\n\t\t\t\t\tif (!workspace) {\n\t\t\t\t\t\tlogOnlyOnce(\n\t\t\t\t\t\t\t\"issue-has-non-existent-index-workspace\",\n\t\t\t\t\t\t\tissue.offline_id,\n\t\t\t\t\t\t\t\"warn\",\n\t\t\t\t\t\t\t`Encountered issue with an index_workspace that doesn't exist. Issue ${issue.offline_id} has \n\t\t\t\t\tindex_workspace = ${issue.index_workspace}, which does not exist in:`,\n\t\t\t\t\t\t\tObject.keys(workspaceMapping),\n\t\t\t\t\t\t)\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\n\t\t\t\t\tconst workspaceAbbreviation = workspace.abbreviation\n\t\t\t\t\tif (!workspaceAbbreviation) {\n\t\t\t\t\t\tlogOnlyOnce(\n\t\t\t\t\t\t\t\"workspace-has-no-abbreviation\",\n\t\t\t\t\t\t\tworkspace.offline_id,\n\t\t\t\t\t\t\t\"error\",\n\t\t\t\t\t\t\t`Workspace ${workspace.name} has no abbreviation. Not including any issues in search.`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tconst tag = \"index\" in issue ? `${workspaceAbbreviation.toUpperCase()}-${issue.index}` : null\n\t\t\t\t\tif (\n\t\t\t\t\t\t(issue.title || \"\").toLowerCase().includes(searchTerm) ||\n\t\t\t\t\t\t(tag && tag.toLowerCase().includes(searchTerm))\n\t\t\t\t\t) {\n\t\t\t\t\t\tret.push(issueToSearchResult(issue, tag))\n\t\t\t\t\t\tnbResults++\n\t\t\t\t\t\tif (maxResults && nbResults >= maxResults) {\n\t\t\t\t\t\t\treturn ret\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn ret\n\t\t\t},\n\t\t),\n\t)\n\nexport const selectIssuesByIds = restructureCreateSelectorWithArgs(\n\tcreateSelector([selectIssueMapping, (_, issueIds: string[]) => issueIds], (issuesMapping, issueIds) => {\n\t\tconst issues: Stored<Issue>[] = []\n\n\t\tfor (const issueId of issueIds) {\n\t\t\tconst issue = issuesMapping[issueId]\n\t\t\tif (issue) {\n\t\t\t\tissues.push(issue)\n\t\t\t} else {\n\t\t\t\tconsole.warn(\"selectIssuesByIds: No issue exists with the id\", issueId)\n\t\t\t}\n\t\t}\n\n\t\treturn issues\n\t}),\n)\n\nexport const selectRecentIssuesAsSearchResults: OvermapSelector<SearchableRecentResult<Stored<Issue>>[]> =\n\tcreateSelector(\n\t\t[selectIssueMapping, selectRecentIssueIds, selectWorkspaceMapping],\n\t\t(issueMapping, recentIssueIds, workspaceMapping) => {\n\t\t\tconst ret: SearchableRecentResult<Stored<Issue>>[] = []\n\t\t\tfor (const recentIssueResult of recentIssueIds) {\n\t\t\t\tconst issue = issueMapping[recentIssueResult.offlineId]\n\t\t\t\tif (!issue) {\n\t\t\t\t\t// Recent issue has been deleted. Remove it from the list.\n\t\t\t\t\tconsole.info(\"Recent issue no longer exists\")\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (\"index\" in issue && issue.index_workspace) {\n\t\t\t\t\tconst indexWorkspace = workspaceMapping[issue.index_workspace]\n\t\t\t\t\tif (!indexWorkspace) {\n\t\t\t\t\t\t// Prevent repeated logging, which hurts performance.\n\t\t\t\t\t\tlogOnlyOnce(\n\t\t\t\t\t\t\t\"issue-has-index-but-not-index-workspace\",\n\t\t\t\t\t\t\tissue.offline_id,\n\t\t\t\t\t\t\t\"warn\",\n\t\t\t\t\t\t\t`Issue ${issue.offline_id} has an index but no index_workspace. This may be because the \n\t\t\t\t\tworkspace has been deleted, but the new index has not been returned by the server yet. It will not\n\t\t\t\t\tbe included in search results.`,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tconst workspaceTag = `${indexWorkspace.abbreviation}-${issue.index}`\n\t\t\t\t\tconst searchResult = {\n\t\t\t\t\t\t...issueToSearchResult(issue, workspaceTag),\n\t\t\t\t\t\tlastOpenedEpochTime: recentIssueResult.lastOpenedEpochTime,\n\t\t\t\t\t} satisfies SearchableRecentResult<Stored<Issue>>\n\t\t\t\t\tret.push(searchResult)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn ret\n\t\t},\n\t)\n\nexport const issueReducer: Reducer<IssueState> = issueSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport {\n\tIssue,\n\tIssueType,\n\tOrganization,\n\tOvermapRootState,\n\tOvermapSelector,\n\tOvermapSelectorWithArgs,\n\tStored,\n} from \"../../typings\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\nimport { createModelAdapter } from \"../adapter\"\nimport { ModelState } from \"../typings\"\n\n// TODO: add attachment support for issue type descriptions\n\nexport type IssueTypeState = ModelState<Stored<IssueType>>\n\nconst issueTypeAdapter = createModelAdapter<Stored<IssueType>>((issueType) => issueType.offline_id)\n\nconst initialState: IssueTypeState = issueTypeAdapter.getInitialState({})\n\nexport const issueTypeSlice = createSlice({\n\tname: \"issueTypes\",\n\tinitialState,\n\textraReducers: (builder) =>\n\t\tbuilder.addCase(\"RESET\", (state) => {\n\t\t\tObject.assign(state, initialState)\n\t\t}),\n\treducers: {\n\t\tinitializeIssueTypes: issueTypeAdapter.initialize,\n\t\tsetIssueType: issueTypeAdapter.setOne,\n\t\taddIssueType: issueTypeAdapter.addOne,\n\t\tupdateIssueType: issueTypeAdapter.updateOne,\n\t\tremoveIssueType: issueTypeAdapter.deleteOne,\n\t},\n})\n\nexport const { initializeIssueTypes, setIssueType, addIssueType, updateIssueType, removeIssueType } =\n\tissueTypeSlice.actions\n\nexport const selectIssueTypeMapping: OvermapSelector<IssueTypeState[\"instances\"]> = (state) => {\n\treturn state.issueTypeReducer.instances\n}\n\nexport const selectIssueTypes: OvermapSelector<Stored<IssueType>[]> = createSelector(\n\tselectIssueTypeMapping,\n\t(issueTypes) => {\n\t\treturn Object.values(issueTypes)\n\t},\n)\n\nexport const selectIssueTypeById: OvermapSelectorWithArgs<string, Stored<IssueType> | undefined> = (id) => (state) => {\n\treturn state.issueTypeReducer.instances[id]\n}\n\nexport const selectIssueTypesByIds: OvermapSelectorWithArgs<string[], Stored<IssueType>[]> =\n\t(issueTypeIds: string[]) => (state: OvermapRootState) => {\n\t\tconst issueTypes: Stored<IssueType>[] = []\n\n\t\tfor (const issueTypeId of issueTypeIds) {\n\t\t\tconst issueType = state.issueTypeReducer.instances[issueTypeId]\n\t\t\tif (issueType) {\n\t\t\t\tissueTypes.push(issueType)\n\t\t\t} else {\n\t\t\t\tconsole.warn(\"selectIssueTypesByIds: No issue type exists with the id\", issueTypeId)\n\t\t\t}\n\t\t}\n\n\t\treturn issueTypes\n\t}\n\nexport const selectIssueTypesOfOrganization: OvermapSelectorWithArgs<Organization[\"id\"], Stored<IssueType>[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector(\n\t\t\t[selectIssueTypes, (_, organizationId: number) => organizationId],\n\t\t\t(issueTypes, organizationId) => {\n\t\t\t\treturn issueTypes.filter((issueType) => issueType.organization === organizationId)\n\t\t\t},\n\t\t),\n\t)\n\nexport const selectIssuesOfIssueType: OvermapSelectorWithArgs<IssueType[\"offline_id\"], Stored<Issue>[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector(\n\t\t\t[(state: OvermapRootState) => state.issueReducer.instances, (_, issueTypeId: string) => issueTypeId],\n\t\t\t(issuesMapping, issueTypeId) => {\n\t\t\t\treturn Object.values(issuesMapping).filter((issue) => issue.issue_type === issueTypeId)\n\t\t\t},\n\t\t),\n\t)\n\nexport const selectIssuesOfIssueTypeCount: OvermapSelectorWithArgs<IssueType[\"offline_id\"], number> =\n\t(issueTypeId: string) => (state) => {\n\t\treturn selectIssuesOfIssueType(issueTypeId)(state).length\n\t}\n\nexport const issueTypeReducer: Reducer<IssueTypeState> = issueTypeSlice.reducer\n","import { createSlice, PayloadAction, Reducer } from \"@reduxjs/toolkit\"\nimport { BaseState, SelectorWithArgs } from \"typings\"\n\ninterface S3UploadUrl {\n\turl: string\n\tfields: Record<string, string>\n\t/** the time the upload url expires */\n\texp?: number\n}\n\nexport interface FileState {\n\t// maps sha1 hash to upload URL\n\ts3Urls: Record<string, S3UploadUrl>\n}\n\ninterface S3UrlPayload {\n\tsha1: string\n\turl: string\n\tfields: Record<string, string>\n}\n\nconst initialState: FileState = {\n\ts3Urls: {},\n}\n\nconst msPerHour = 1000 * 60 * 60\nconst msPerWeek = msPerHour * 24 * 7\n\n/**\n * Stores the auth state of the app (tokens, and whether user is logged in or not)\n */\nexport const fileSlice = createSlice({\n\tname: \"file\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tsetUploadUrl: (state, action: PayloadAction<S3UrlPayload>) => {\n\t\t\tconst { url, fields, sha1 } = action.payload\n\t\t\tconst today = new Date()\n\t\t\tconst weekFromToday = new Date(today.getTime() + msPerWeek)\n\n\t\t\tstate.s3Urls[sha1] = {\n\t\t\t\turl,\n\t\t\t\tfields,\n\t\t\t\texp: weekFromToday.getTime(),\n\t\t\t}\n\t\t},\n\t},\n})\n\nexport const { setUploadUrl } = fileSlice.actions\n\nexport const selectUploadUrl: SelectorWithArgs<BaseState, string, S3UploadUrl | undefined> =\n\t(sha1: string) => (state) => {\n\t\tconst url = state.fileReducer.s3Urls[sha1]\n\t\tif (!url) {\n\t\t\treturn undefined\n\t\t}\n\n\t\tconst today = new Date().getTime()\n\t\tconst expiringWithinAnHour = (url.exp ?? today) - today < msPerHour\n\t\tif (expiringWithinAnHour) return undefined\n\n\t\treturn url\n\t}\n\nexport const fileReducer: Reducer<FileState> = fileSlice.reducer\n","import { OfflineModel } from \"./base\"\n\nexport interface ProjectAccess extends OfflineModel {\n\tuser: number\n\tproject: number\n\taccess_level: ProjectAccessLevel\n\tview_only: boolean\n}\n\nexport enum ProjectAccessLevel {\n\tBASIC = 0,\n\tADMIN = 2,\n}\n\nexport interface OrganizationAccess extends OfflineModel {\n\tuser: number\n\torganization: number\n\taccess_level: OrganizationAccessLevel\n}\n\n// TODO: Move\nexport enum OrganizationAccessLevel {\n\tBASIC = 0,\n\tADMIN = 2,\n}\n","import { CreatedByModel, OfflineModel, SubmittedAtModel } from \"./base\"\nimport { FileModel, FileWithNameModel, MaybeObjectURL } from \"../files\"\n\nexport interface Attachment extends OfflineModel, SubmittedAtModel, FileWithNameModel, CreatedByModel {\n\tdescription?: string\n\tfile_type: string\n}\n\nexport interface IssueAttachment extends Attachment {\n\tissue: string\n}\n\nexport interface AssetAttachment extends Attachment {\n\tasset: string\n}\n\nexport interface AssetTypeAttachment extends Attachment {\n\tasset_type: string\n}\n\nexport interface ProjectAttachment extends Attachment {\n\tproject: number\n}\n\nexport interface DocumentAttachment extends Attachment {\n\tdocument: string\n}\n\nexport enum AttachmentModel {\n\tIssue = \"issue\",\n\tAsset = \"asset\",\n\tAssetType = \"asset_type\",\n\tProject = \"project\",\n\tDocument = \"document\",\n}\n\n/** to get an AttachmentPayload for a specific type, pass in the given AttachmentType\n * ex. AttachmentPayload<IssueAttachment> */\nexport type AttachmentPayload<TAttachment> = Omit<TAttachment, \"file\" | \"submitted_at\" | \"created_by\"> & {\n\tfile: MaybeObjectURL<File>\n}\n\nexport type ProfilePic = FileModel\n","// This is not a model, but a set of fields that can also be used for issue forms where there are no attachments yet\nimport type { CreatedByModel, Offline, OfflineModel, SubmittedAtModel } from \"./base\"\nimport { IssuePriority, IssueStatus } from \"../../enums\"\nimport type { WorkspaceIndexedModel } from \"./workspace\"\nimport type { CanvasMarkableModel, MarkableModel } from \"./geo\"\nimport type { CreatedForm, Form, SubmittedForm } from \"./forms\"\nimport type { User } from \"./users\"\nimport type { CSSColor } from \"../colors\"\n\n// TODO: Add more ternary operations for other models. I think this will be a good pattern. Move elsewhere.\n// TODO: Remove \"id\" from Omit when it's no longer used (only use offline_id)\n/**\n * Represents a model instance that has been submitted to the backend. Some properties (depending on which model, but in\n * all cases, the `offline_id`) are guaranteed to be set.\n */\nexport type Submitted<TModel> = Offline<TModel> &\n\t(TModel extends Issue\n\t\t? SubmittedIssue\n\t\t: TModel extends Form\n\t\t? SubmittedForm\n\t\t: Omit<TModel, \"created_at\" | \"created_by\" | \"id\">)\n/**\n * Represents a model instance that has been submitted to the backend, accepted, then downloaded. Created models\n * typically have additional properties that are only known once it has been processed and accepted by the API, such as\n * the `created_at` timestamp, which is the time at which the data was written to the database.\n */\nexport type Created<TModel> = Submitted<TModel> &\n\t(TModel extends Issue\n\t\t? CreatedIssue\n\t\t: TModel extends IssueComment\n\t\t? CreatedIssueComment\n\t\t: TModel extends Form\n\t\t? CreatedForm\n\t\t: TModel)\n/**\n * Model instances that are stored in the Redux store can be already-created (and will likely be gotten with the initial\n * data load), or to-be-created. In the former case, you will get a `Created<TModel>`. In the latter case, you will get\n * a `Submitted<TModel>`.\n */\nexport type Stored<TModel> = Created<TModel> | Submitted<TModel>\n\n/**\n * Represents the properties you can always expect on any object representing an issue. These are the minimal details\n * required when creating an issue.\n */\nexport interface Issue extends Pick<WorkspaceIndexedModel, \"index_workspace\">, MarkableModel, CanvasMarkableModel {\n\ttitle?: string | null\n\tdescription?: string | null\n\tpriority?: IssuePriority\n\tstatus?: IssueStatus\n\tassigned_to?: number | null\n\tdue_date?: string | Date | null\n\tcategory?: string | null\n\tvisible_in_workspaces: string[]\n\t// TODO: add issue_type here\n\tissue_type?: string | null\n}\n\n/**\n * These details need to be provided by the frontend code before submitting to the backend.\n */\nexport interface SubmittedIssue extends OfflineModel, CreatedByModel {\n\tsubmitted_at: string\n\tstatus: Exclude<Issue[\"status\"], undefined>\n\tpriority: Exclude<Issue[\"priority\"], undefined>\n}\n\n/**\n * These details exist on issues that have been successfully submitted, accepted, created, and serialized by the\n * backend, then downloaded by the frontend.\n */\nexport interface CreatedIssue extends SubmittedIssue, Pick<WorkspaceIndexedModel, \"index\"> {\n\t// Some of these have defaults in the backend, so they will have some defined value once created. Others can be\n\t// null, but not undefined.\n\ttitle: Exclude<Issue[\"title\"], undefined>\n\tdescription: Exclude<Issue[\"description\"], undefined>\n\tassigned_to: Exclude<Issue[\"assigned_to\"], undefined>\n\tdue_date: Exclude<Issue[\"due_date\"], undefined>\n\tcategory: Exclude<Issue[\"category\"], undefined>\n\tgeo_marker: Exclude<Issue[\"geo_marker\"], undefined>\n\n\t// These are generated by the backend upon receipt of the Issue payload. (`created_by` is also included in this, but\n\t// we can safely assume the current user will be the creator, so we set it when submitting, so it's available in the\n\t// store\n\tcreated_at: string\n}\n\nexport interface IssueComment extends OfflineModel {\n\tissue: string\n\tcontent: string\n\tauthor?: number\n\tcreated_at?: string\n\tsubmitted_at: string\n}\n\nexport interface SubmittedIssueComment {\n\tcreated_at: Exclude<IssueComment[\"created_at\"], undefined>\n}\n\nexport interface CreatedIssueComment {\n\tauthor: Exclude<IssueComment[\"author\"], undefined>\n\tcreated_at: Exclude<IssueComment[\"created_at\"], undefined>\n}\n\nexport type IssueCommentPayload = Omit<IssueComment, \"author\" | \"created_at\" | \"offline_id\">\n\nexport enum IssueUpdateChange {\n\tSTATUS = \"status\",\n\tPRIORITY = \"priority\",\n\tCATEGORY = \"category\",\n\tDESCRIPTION = \"description\",\n\tTITLE = \"title\",\n\tASSIGNED_TO = \"assigned_to\",\n\tDUE_DATE = \"due_date\",\n}\n\nexport interface IssueUpdateChangeTypes {\n\tstatus: IssueStatus\n\tpriority: IssuePriority\n\tcategory: {\n\t\tname: string\n\t\tcolor: CSSColor\n\t\toffline_id: OfflineModel[\"offline_id\"]\n\t} | null\n\tdescription: string\n\ttitle: string\n\tassigned_to: {\n\t\tfull_name: string\n\t\tid: User[\"id\"]\n\t} | null\n\tdue_date: string\n}\n\nexport interface IssueUpdate extends OfflineModel, CreatedByModel {\n\tsubmitted_at: string\n\tissue: OfflineModel[\"offline_id\"]\n\tchanges: Partial<Record<IssueUpdateChange, IssueUpdateChangeTypes[IssueUpdateChange]>>\n}\n\nexport interface IssueAssociation extends OfflineModel, SubmittedAtModel, CreatedByModel {\n\tassociated_issue: string\n\tissue?: string\n\tasset?: string\n}\n","import { RegistrationPayload } from \"./users\"\nimport { OfflineModel } from \"./base\"\n\nexport type EmailVerificationPayload = undefined | RegistrationPayload | Omit<RegistrationPayload, \"username\" | \"email\">\n\nexport interface EmailVerificationReturn {\n\tusername?: string\n\tproject?: number\n}\n\nexport enum VerificationCodeType {\n\tUSER_REGISTRATION = 0,\n\tAPPLICATION_INVITE = 2,\n\tPROJECT_INVITE = 4,\n\tORGANIZATION_INVITE = 6,\n\tADD_EMAIL_DOMAIN = 8,\n\tRESET_PASSWORD = 10,\n}\n\nexport interface VerificationCode extends OfflineModel {\n\tverification_code: string\n\tverification_type: VerificationCodeType\n\torganization?: number\n\tproject?: number\n\tuser?: number\n}\n","import { OfflineModel, OwnedByUserOrOrganization } from \"./base\"\n\nexport enum PaddleCheckoutEvent {\n\tCOMPLETED = \"checkout.completed\",\n\tCLOSED = \"checkout.closed\",\n}\nexport enum LicenseLevel {\n\tPRO = 0,\n}\n\nexport enum LicenseStatus {\n\tACTIVE = 0,\n\tPAUSED = 2,\n\tCANCELLED = 4,\n\tINACTIVE = 6,\n\tPAST_DUE = 8,\n}\n\nexport interface Transaction {\n\tid: string\n}\n\nexport interface License extends OfflineModel, OwnedByUserOrOrganization {\n\tproject: number | null\n\tlevel: LicenseLevel\n\tstatus: LicenseStatus\n\tis_special: boolean\n\tis_active: boolean\n\tnext_billing_date: Date\n}\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport { OvermapRootState, OvermapSelectorWithArgs, User } from \"../../typings\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport interface UserState {\n\tcurrentUser: User\n\tusers: Record<number, User>\n}\n\nconst initialState: UserState = {\n\tusers: {},\n\tcurrentUser: {\n\t\tid: 0,\n\t\tusername: \"\",\n\t\temail: \"\",\n\t\tprofile: { file: null, file_sha1: null, favourite_project_ids: [], tour_step: -1 },\n\t},\n}\n\nexport const userSlice = createSlice({\n\tname: \"users\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tsetUsers: (state, action: { payload: User[] }) => {\n\t\t\tconst usersMapping: Record<string, User> = {}\n\t\t\taction.payload.forEach((user) => {\n\t\t\t\tusersMapping[user.id] = user\n\t\t\t})\n\t\t\tstate.users = usersMapping\n\t\t},\n\t\taddUsers: (state, action: { payload: User[] }) => {\n\t\t\tfor (const user of action.payload) {\n\t\t\t\tstate.users[user.id] = user\n\t\t\t}\n\t\t},\n\t\tsetCurrentUser: (state, action: { payload: User }) => {\n\t\t\tstate.currentUser = action.payload\n\t\t},\n\t\tsetProfilePicture: (state, action: { payload: { file?: string; file_sha1?: string } }) => {\n\t\t\tstate.currentUser.profile.file = action.payload.file ?? null\n\t\t\tstate.currentUser.profile.file_sha1 = action.payload.file_sha1 ?? null\n\n\t\t\tconst currentUser = state.users[state.currentUser.id]\n\n\t\t\tif (!currentUser) {\n\t\t\t\tthrow new Error(\"Unable to find current user in users slice\")\n\t\t\t}\n\n\t\t\tcurrentUser.profile.file = action.payload.file ?? null\n\t\t\tcurrentUser.profile.file_sha1 = action.payload.file_sha1 ?? null\n\t\t},\n\t\taddFavouriteProjectId: (state, action: { payload: number }) => {\n\t\t\tstate.currentUser.profile.favourite_project_ids.push(action.payload)\n\t\t},\n\t\tremoveFavouriteProjectId: (state, action: { payload: number }) => {\n\t\t\tstate.currentUser.profile.favourite_project_ids = state.currentUser.profile.favourite_project_ids.filter(\n\t\t\t\t(id) => id !== action.payload,\n\t\t\t)\n\t\t},\n\t\tsetTourStep: (state, action: { payload: number }) => {\n\t\t\tstate.currentUser.profile.tour_step = action.payload\n\t\t},\n\t\tremoveUser: (state, action: { payload: number }) => {\n\t\t\tdelete state.users[action.payload]\n\t\t},\n\t},\n})\n\nexport const {\n\tsetCurrentUser,\n\tsetProfilePicture,\n\tsetUsers,\n\taddUsers,\n\taddFavouriteProjectId,\n\tremoveFavouriteProjectId,\n\tsetTourStep,\n\tremoveUser,\n} = userSlice.actions\n\nexport const userReducer: Reducer<UserState> = userSlice.reducer\n\nexport const selectCurrentUser = (state: OvermapRootState) => state.userReducer.currentUser\n\nexport const selectUsersMapping = (state: OvermapRootState) => state.userReducer.users\n\nexport const selectUser: OvermapSelectorWithArgs<number | null, User | undefined> = (userId) => (state) => {\n\tif (userId === null) return undefined\n\treturn state.userReducer.users[userId]\n}\n\nexport const selectUserById: OvermapSelectorWithArgs<number, User | undefined> = (id) => (state) => {\n\treturn state.userReducer.users[id]\n}\n\nexport const selectUsersByIds = restructureCreateSelectorWithArgs(\n\tcreateSelector([selectUsersMapping, (_state, userIds: number[]) => userIds], (usersMapping, userIds) => {\n\t\tconst users: User[] = []\n\n\t\tfor (const userId of userIds) {\n\t\t\tconst user = usersMapping[userId]\n\t\t\tif (user) {\n\t\t\t\tusers.push(user)\n\t\t\t} else {\n\t\t\t\tconsole.warn(\"selectUsersByIds: No user exists with the id\", userId)\n\t\t\t}\n\t\t}\n\n\t\treturn users\n\t}),\n)\n\nexport const selectFavouriteProjects = (state: OvermapRootState): number[] =>\n\tstate.userReducer.currentUser.profile.favourite_project_ids\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport { OvermapRootState, OvermapSelector, OvermapSelectorWithArgs } from \"typings\"\nimport { OfflineIdMapping, OrganizationAccess, User } from \"typings/models\"\nimport { selectCurrentUser } from \"./userSlice\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\n\nexport type OrganizationAccessState = ModelState<OrganizationAccess>\n\nconst organizationAccessAdapter = createModelAdapter<OrganizationAccess>(\n\t(organizationAccess) => organizationAccess.offline_id,\n)\n\nconst initialState: OrganizationAccessState = organizationAccessAdapter.getInitialState({})\n\nexport const organizationAccessSlice = createSlice({\n\tname: \"organizationAccess\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeOrganizationAccesses: organizationAccessAdapter.initialize,\n\t\tupdateOrganizationAccess: organizationAccessAdapter.updateOne,\n\t\tdeleteOrganizationAccess: organizationAccessAdapter.deleteOne,\n\t},\n})\n\nexport const { initializeOrganizationAccesses, updateOrganizationAccess, deleteOrganizationAccess } =\n\torganizationAccessSlice.actions\n\nexport const selectOrganizationAccesses = (state: OvermapRootState) => {\n\treturn state.organizationAccessReducer.instances\n}\n\nexport const selectOrganizationAccessById: OvermapSelectorWithArgs<string, OrganizationAccess | undefined> =\n\t(id) => (state) => {\n\t\treturn state.organizationAccessReducer.instances[id]\n\t}\n\nexport const selectActiveOrganizationAccess: OvermapSelector<OrganizationAccess | null> = createSelector(\n\t[selectCurrentUser, selectOrganizationAccesses],\n\t(currentUser: User, organizationAccesses: OfflineIdMapping<OrganizationAccess>) => {\n\t\tconst activeOrganizationAccess = Object.values(organizationAccesses).find(\n\t\t\t(organizationAccess: OrganizationAccess) => organizationAccess.user === currentUser.id,\n\t\t)\n\t\treturn activeOrganizationAccess ?? null\n\t},\n)\n\nexport const selectOrganizationAccessForUser: OvermapSelectorWithArgs<User, OrganizationAccess | undefined> =\n\t(user: User) => (state: OvermapRootState) => {\n\t\treturn Object.values(state.organizationAccessReducer.instances).find(\n\t\t\t(organizationAccess: OrganizationAccess) => organizationAccess.user === user.id,\n\t\t)\n\t}\n\nexport const selectOrganizationAccessUserMapping = (state: OvermapRootState): Record<number, OrganizationAccess> => {\n\tconst organizationAccesses: Record<number, OrganizationAccess> = {}\n\tfor (const organizationAccess of Object.values(state.organizationAccessReducer.instances)) {\n\t\torganizationAccesses[organizationAccess.user] = organizationAccess\n\t}\n\treturn organizationAccesses\n}\n\nexport const organizationAccessReducer: Reducer<OrganizationAccessState> = organizationAccessSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport { License, OvermapRootState, OvermapSelector, OvermapSelectorWithArgs } from \"../../typings\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\n\nexport type LicenseState = ModelState<License>\n\nconst licenseAdapter = createModelAdapter<License>((license) => license.offline_id)\n\nconst initialState: LicenseState = licenseAdapter.getInitialState({})\n\nexport const licenseSlice = createSlice({\n\tname: \"license\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeLicences: licenseAdapter.initialize,\n\t\taddLicenses: licenseAdapter.addMany,\n\t\tupdateLicense: licenseAdapter.updateOne,\n\t},\n})\n\nexport const { initializeLicences, addLicenses, updateLicense } = licenseSlice.actions\n\nexport const selectLicenses: OvermapSelector<Record<string, License>> = (state: OvermapRootState) => {\n\treturn state.licenseReducer.instances\n}\n\nexport const selectLicense: OvermapSelectorWithArgs<string, License | undefined> = (id) => (state) =>\n\tstate.licenseReducer.instances[id]\n\nexport const selectActiveLicense: OvermapSelector<License | null> = (state: OvermapRootState) =>\n\tObject.values(state.licenseReducer.instances).find(\n\t\t(license) => license.project === state.projectReducer.activeProjectId,\n\t) ?? null\n\nexport const selectLicenseForProject: OvermapSelectorWithArgs<number, License | undefined> =\n\t(projectId: number) => (state: OvermapRootState) =>\n\t\tObject.values(state.licenseReducer.instances).find((license) => license.project === projectId)\n\nexport const selectActiveStatusLicenses: OvermapSelector<License[]> = createSelector(\n\t[selectLicenses],\n\t(licenses: Record<string, License>) => Object.values(licenses).filter((license) => license.is_active),\n)\n\nexport const selectLicensesForProjectsMapping: OvermapSelector<Record<number, License>> = createSelector(\n\t[selectLicenses],\n\t(licenses: Record<string, License>) =>\n\t\tObject.values(licenses)\n\t\t\t.filter((license) => license.project)\n\t\t\t.reduce((accum, license) => ({ ...accum, [license.project!]: license }), {}),\n)\n\nexport const licenseReducer: Reducer<LicenseState> = licenseSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport { OvermapRootState, OvermapSelector, OvermapSelectorWithArgs, ProjectAccess, Stored, User } from \"../../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { ModelState } from \"../typings\"\n\nexport type ProjectAccessState = ModelState<ProjectAccess>\n\nconst projectAccessAdapter = createModelAdapter<ProjectAccess>((projectAccess) => projectAccess.offline_id)\n\nconst initialState: ProjectAccessState = projectAccessAdapter.getInitialState({})\n\nexport const projectAccessSlice = createSlice({\n\tname: \"projectAccess\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeProjectAccesses: projectAccessAdapter.initialize,\n\t\tupdateProjectAccess: projectAccessAdapter.updateOne,\n\t\tdeleteProjectAccess: projectAccessAdapter.deleteOne,\n\t\tdeleteProjectAccesses: projectAccessAdapter.deleteMany,\n\t},\n})\n\nexport const { initializeProjectAccesses, updateProjectAccess, deleteProjectAccess, deleteProjectAccesses } =\n\tprojectAccessSlice.actions\n\nexport const selectProjectAccessMapping = (state: OvermapRootState) => {\n\treturn state.projectAccessReducer.instances\n}\n\nexport const selectProjectAccesses: OvermapSelector<Stored<ProjectAccess>[]> = createSelector(\n\tselectProjectAccessMapping,\n\t(projectAccesses) => {\n\t\treturn Object.values(projectAccesses)\n\t},\n)\n\nexport const selectProjectAccessById: OvermapSelectorWithArgs<string, ProjectAccess | undefined> = (id) => (state) => {\n\treturn state.projectAccessReducer.instances[id]\n}\n\nexport const selectActiveProjectAccess: OvermapSelector<ProjectAccess | null> = (state: OvermapRootState) => {\n\tconst currentUser = state.userReducer.currentUser\n\tconst activeProjectId = state.projectReducer.activeProjectId\n\treturn (\n\t\tObject.values(state.projectAccessReducer.instances).find((projectAccess: ProjectAccess) => {\n\t\t\treturn projectAccess.user === currentUser.id && projectAccess.project === activeProjectId\n\t\t}) ?? null\n\t)\n}\n\nexport const selectProjectAccessForUser: OvermapSelectorWithArgs<User, ProjectAccess | undefined> =\n\t(user: User) => (state: OvermapRootState) => {\n\t\treturn Object.values(state.projectAccessReducer.instances).find(\n\t\t\t(projectAccess: ProjectAccess) => projectAccess.user === user.id,\n\t\t)\n\t}\n\nexport const selectProjectAccessUserMapping: OvermapSelector<Record<string, ProjectAccess>> = (\n\tstate: OvermapRootState,\n) => {\n\tconst projectAccesses: Record<string, ProjectAccess> = {}\n\tfor (const projectAccess of Object.values(state.projectAccessReducer.instances)) {\n\t\tprojectAccesses[projectAccess.user] = projectAccess\n\t}\n\treturn projectAccesses\n}\n\nexport const projectAccessReducer: Reducer<ProjectAccessState> = projectAccessSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport {\n\tOfflineIdMapping,\n\tOvermapRootState,\n\tOvermapSelector,\n\tOvermapSelectorWithArgs,\n\tProject,\n\tProjectAccess,\n\tProjectAccessLevel,\n\tUser,\n} from \"../../typings\"\nimport { selectProjectAccessMapping, selectProjectAccessUserMapping } from \"./projectAccessSlice\"\nimport { selectCurrentUser, selectUsersMapping } from \"./userSlice\"\n\nexport interface ProjectState {\n\tprojects: Record<number, Project>\n\tactiveProjectId: number | null\n}\n\nconst initialState: ProjectState = {\n\tprojects: {},\n\tactiveProjectId: null,\n}\n\nexport const projectSlice = createSlice({\n\tname: \"projects\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tsetProjects: (state, action: { payload: Project[] }) => {\n\t\t\tconst projectsMap: Record<number, Project> = {}\n\t\t\taction.payload.forEach((project) => {\n\t\t\t\tprojectsMap[project.id] = project\n\t\t\t})\n\t\t\tstate.projects = projectsMap\n\t\t},\n\t\tsetActiveProjectId: (state, action: { payload: number | null }) => {\n\t\t\tstate.activeProjectId = action.payload\n\t\t},\n\t\tupdateOrCreateProject: (state, action: { payload: Project }) => {\n\t\t\tstate.projects[action.payload.id] = action.payload\n\t\t},\n\t\t// Takes a list of Projects and updates existing ones to match the payload, or adds them\n\t\t// to the store if they are not already present\n\t\tupdateOrCreateProjects: (state, action: { payload: Project[] }) => {\n\t\t\taction.payload.forEach((project) => {\n\t\t\t\tstate.projects[project.id] = project\n\t\t\t})\n\t\t},\n\t\tdeleteProject: (state, action: { payload: Project }) => {\n\t\t\tdelete state.projects[action.payload.id]\n\t\t},\n\t\tacceptProjectInvite: (state, action: { payload: number }) => {\n\t\t\tif (action.payload in state.projects) {\n\t\t\t\tstate.projects[action.payload]!.invited = false\n\t\t\t} else {\n\t\t\t\tthrow new Error(\"Accept project invite: user is not in this project\")\n\t\t\t}\n\t\t},\n\t\taddActiveProjectIssuesCount: (state, action: { payload: number }) => {\n\t\t\tif (!state.activeProjectId || !(state.activeProjectId in state.projects)) {\n\t\t\t\tthrow new Error(\"Update issues count: no active project\")\n\t\t\t}\n\n\t\t\tif (!state.projects[state.activeProjectId]!.issues_count) {\n\t\t\t\tstate.projects[state.activeProjectId]!.issues_count = action.payload\n\t\t\t} else {\n\t\t\t\tstate.projects[state.activeProjectId]!.issues_count! += action.payload\n\t\t\t}\n\t\t},\n\t\taddActiveProjectFormSubmissionsCount: (state, action: { payload: number }) => {\n\t\t\tif (state.activeProjectId && state.activeProjectId in state.projects) {\n\t\t\t\tif (!state.projects[state.activeProjectId]!.form_submissions_count) {\n\t\t\t\t\tstate.projects[state.activeProjectId]!.form_submissions_count = action.payload\n\t\t\t\t} else {\n\t\t\t\t\tstate.projects[state.activeProjectId]!.form_submissions_count! += action.payload\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new Error(\"Update form submissions count: no active project\")\n\t\t\t}\n\t\t},\n\t},\n})\n\nexport const {\n\tsetProjects,\n\tupdateOrCreateProject,\n\tupdateOrCreateProjects: addOrReplaceProjects,\n\tsetActiveProjectId,\n\tdeleteProject,\n\tacceptProjectInvite,\n\taddActiveProjectIssuesCount,\n\taddActiveProjectFormSubmissionsCount,\n} = projectSlice.actions\n\nexport const projectReducer: Reducer<ProjectState> = projectSlice.reducer\n\nexport const selectProjectMapping: OvermapSelector<Record<number, Project>> = (state: OvermapRootState) =>\n\tstate.projectReducer.projects\n\nexport const selectActiveProjectId = (state: OvermapRootState): number | null => state.projectReducer.activeProjectId\n\nexport const selectActiveProject = (state: OvermapRootState): Project | null => {\n\tconst activeProjectId = selectActiveProjectId(state)\n\tif (!activeProjectId) {\n\t\treturn null\n\t}\n\treturn state.projectReducer.projects[activeProjectId] ?? null\n}\n\nexport const selectProjectById: OvermapSelectorWithArgs<number, Project | undefined> = (id) => (state) => {\n\treturn state.projectReducer.projects[id]\n}\n\nexport const selectProjectUsersIds: OvermapSelector<number[]> = createSelector(\n\t[selectProjectAccessMapping],\n\t(projectAccesses: OfflineIdMapping<ProjectAccess>) =>\n\t\tObject.values(projectAccesses).map((projectAccess: ProjectAccess) => projectAccess.user),\n)\n\nexport const selectProjectUsersAsMapping: OvermapSelector<Record<number, User>> = createSelector(\n\t[selectProjectUsersIds, selectUsersMapping],\n\t(projectUserIds, users) => projectUserIds.reduce((accum, userId) => ({ ...accum, [userId]: users[userId] }), {}),\n)\n\nexport const selectProjectsWithAccess: OvermapSelector<Project[]> = createSelector(\n\t[selectProjectMapping],\n\t(projects: Record<number, Project>) => Object.values(projects).filter((project) => !project.invited),\n)\n\nexport const selectSortedProjectUsers: OvermapSelector<User[]> = createSelector(\n\t[selectCurrentUser, selectProjectUsersAsMapping, selectProjectAccessUserMapping],\n\t(currentUser: User, userMapping: Record<number, User>, projectAccessMapping: Record<number, ProjectAccess>) => {\n\t\treturn Object.values(userMapping).sort((userA, userB) => {\n\t\t\tif (userA.id === currentUser.id) {\n\t\t\t\treturn -1\n\t\t\t} else if (userB.id === currentUser.id) {\n\t\t\t\treturn 1\n\t\t\t}\n\t\t\tconst projectAccessesA = projectAccessMapping[userA.id]\n\t\t\tconst projectAccessesB = projectAccessMapping[userB.id]\n\t\t\tif (projectAccessesA?.access_level === projectAccessesB?.access_level) {\n\t\t\t\treturn userA.username.localeCompare(userB.username)\n\t\t\t}\n\t\t\tif (projectAccessesA?.access_level === ProjectAccessLevel.ADMIN) {\n\t\t\t\treturn -1\n\t\t\t}\n\t\t\treturn 1\n\t\t})\n\t},\n)\n","import { createSelector, createSlice, PayloadAction, Reducer } from \"@reduxjs/toolkit\"\nimport { OvermapSelector, OvermapSelectorWithArgs } from \"typings/store\"\nimport {\n\tLicense,\n\tOfflineIdMapping,\n\tOrganization,\n\tOrganizationAccess,\n\tOrganizationAccessLevel,\n\tOvermapRootState,\n\tProject,\n\tUser,\n} from \"../../typings\"\nimport { selectCurrentUser, selectUsersMapping } from \"./userSlice\"\nimport { selectOrganizationAccesses, selectOrganizationAccessUserMapping } from \"./organizationAccessSlice\"\nimport { selectLicenses } from \"./licenseSlice\"\nimport { selectProjectMapping } from \"./projectSlice\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport interface OrganizationState {\n\torganizations: Record<number, Organization>\n}\n\nconst initialState: OrganizationState = {\n\torganizations: {},\n}\n\nexport const organizationSlice = createSlice({\n\tname: \"organizations\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tsetOrganizations: (state, action: PayloadAction<Organization[]>) => {\n\t\t\tfor (const org of action.payload) {\n\t\t\t\tstate.organizations[org.id] = org\n\t\t\t}\n\t\t},\n\t},\n})\n\nexport const { setOrganizations } = organizationSlice.actions\n\nexport const selectOrganizations: OvermapSelector<Organization[]> = (state: OvermapRootState) => {\n\treturn Object.values(state.organizationReducer.organizations)\n}\n\nexport const selectOrganizationsMapping: OvermapSelector<Record<number, Organization>> = (state: OvermapRootState) => {\n\treturn state.organizationReducer.organizations\n}\n\nexport const selectOrganizationsWithAccess: OvermapSelector<Organization[]> = createSelector(\n\t[selectOrganizations],\n\t(organizations: Record<number, Organization>) =>\n\t\tObject.values(organizations).filter((organization: Organization) => organization.has_access),\n)\n\nexport const selectOrganizationById: OvermapSelectorWithArgs<number, Organization | undefined> = (id) => (state) => {\n\treturn state.organizationReducer.organizations[id]\n}\n\nexport const selectOrganizationUsersIds: OvermapSelector<number[]> = createSelector(\n\t[selectOrganizationAccesses],\n\t(organizationAccesses: OfflineIdMapping<OrganizationAccess>) =>\n\t\tObject.values(organizationAccesses).map((organizationAccess: OrganizationAccess) => organizationAccess.user),\n)\n\nexport const selectProjectsOfOrganization: OvermapSelectorWithArgs<number, Project[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector(\n\t\t\t[selectProjectMapping, (_, organizationId: number) => organizationId],\n\t\t\t(projects, organizationId) => {\n\t\t\t\treturn Object.values(projects).filter((project) => project.organization_owner === organizationId)\n\t\t\t},\n\t\t),\n\t)\n\nexport const selectLicensesOfOrganization: OvermapSelectorWithArgs<number, License[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector([selectLicenses, (_, organizationId: number) => organizationId], (licenses, organizationId) => {\n\t\t\treturn Object.values(licenses).filter((license) => license.organization_owner === organizationId)\n\t\t}),\n\t)\n\nexport const selectOrganizationUsersAsMapping: OvermapSelector<Record<number, User>> = createSelector(\n\t[selectOrganizationUsersIds, selectUsersMapping],\n\t(organizationUserIds: number[], users: Record<number, User>) =>\n\t\torganizationUserIds.reduce((accum, userId) => ({ ...accum, [userId]: users[userId] }), {}),\n)\n\nexport const selectSortedOrganizationUsers: OvermapSelector<User[]> = createSelector(\n\t[selectCurrentUser, selectOrganizationUsersAsMapping, selectOrganizationAccessUserMapping],\n\t(\n\t\tcurrentUser: User,\n\t\tuserMapping: Record<number, User>,\n\t\torganizationAccessMapping: Record<number, OrganizationAccess>,\n\t) => {\n\t\treturn Object.values(userMapping).sort((userA: User, userB: User) => {\n\t\t\tif (userA.id === currentUser.id) {\n\t\t\t\treturn -1\n\t\t\t} else if (userB.id === currentUser.id) {\n\t\t\t\treturn 1\n\t\t\t}\n\t\t\tconst organizationAccessesA: OrganizationAccess | undefined = organizationAccessMapping[userA.id]\n\t\t\tconst organizationAccessesB: OrganizationAccess | undefined = organizationAccessMapping[userB.id]\n\t\t\tif (organizationAccessesA?.access_level === organizationAccessesB?.access_level) {\n\t\t\t\treturn userA.username.localeCompare(userB.username)\n\t\t\t}\n\t\t\tif (organizationAccessesA?.access_level === OrganizationAccessLevel.ADMIN) {\n\t\t\t\treturn -1\n\t\t\t}\n\t\t\treturn 1\n\t\t})\n\t},\n)\n\nexport const selectOrganization: OvermapSelectorWithArgs<number, Organization | undefined> =\n\t(id: number) => (state: OvermapRootState) => {\n\t\treturn state.organizationReducer.organizations[id]\n\t}\n\nexport const organizationReducer: Reducer<OrganizationState> = organizationSlice.reducer\n","import { createSlice, PayloadAction, Reducer } from \"@reduxjs/toolkit\"\nimport type { FullOfflineAction } from \"../store\"\nimport type { RequestDetails } from \"../../sdk\"\nimport { v4 as uuidv4 } from \"uuid\"\nimport { SDKRequest } from \"../../sdk\"\nimport { OvermapRootState } from \"../../typings\"\n\nexport const createOfflineAction = (request: SDKRequest, baseUrl: string, serviceName: string): FullOfflineAction => {\n\tconst requestWithUuid = request.uuid ? (request as RequestDetails) : { ...request, uuid: uuidv4() }\n\treturn {\n\t\tpayload: requestWithUuid,\n\t\ttype: \"\",\n\t\tmeta: {\n\t\t\toffline: {\n\t\t\t\teffect: {\n\t\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t\t\trequest: requestWithUuid,\n\t\t\t\t\tBASE_URL: baseUrl,\n\t\t\t\t\tserviceName: serviceName,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n}\n\nexport interface OutboxState {\n\t/** A list of requests marked for deletion. Once the offline slice encounters one of these, */\n\tdeletedRequests: string[]\n\t/** The timestamp of the last retry of an outgoing request. (Number of milliseconds since the epoch.) */\n\tlatestRetryTime: number\n}\n\nconst initialState: OutboxState = {\n\tdeletedRequests: [],\n\tlatestRetryTime: 0,\n}\n\n/**\n * This slice primarily exists as an interface to enqueue API requests to the redux-offline slice. Any dispatched action\n * with an `offline` field in its metadata will be handled by redux-offline. This slice is just a sensible place to\n * \"dump\" no-op actions for enqueueing requests to the outbox. At the same time, we can use this slice to keep track of\n * requests that have been marked for deletion, so that we can skip them instead of sending the request.\n */\nexport const outboxSlice = createSlice({\n\tname: \"outbox\",\n\tinitialState: initialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\t// enqueueActions is a reducer that does nothing but enqueue API request to the Redux Offline outbox\n\t\t// Whenever an issue is being created, a reducer addIssue() is responsible for adding it to the offline store\n\t\t// Then this reducer enqueueRequest() is responsible for adding the actual request data to the outbox\n\t\tenqueueRequest: {\n\t\t\treducer: (state, _action: PayloadAction<RequestDetails>) => {\n\t\t\t\treturn state\n\t\t\t},\n\t\t\tprepare: (payload: SDKRequest & { BASE_URL: string; serviceName: string }): FullOfflineAction => {\n\t\t\t\tconsole.debug(\"Preparing to enqueue request\", payload)\n\t\t\t\tconst { BASE_URL, serviceName, ...rest } = payload\n\t\t\t\treturn createOfflineAction(rest, BASE_URL, serviceName)\n\t\t\t},\n\t\t},\n\t\tmarkForDeletion(state, action: PayloadAction<string>) {\n\t\t\tstate.deletedRequests.push(action.payload)\n\t\t},\n\t\tmarkAsDeleted(state, action: PayloadAction<string>) {\n\t\t\tconst index = state.deletedRequests.indexOf(action.payload)\n\t\t\tif (index !== -1) state.deletedRequests.splice(index, 1)\n\t\t},\n\t\t_setLatestRetryTime: (state, action: PayloadAction<number>) => {\n\t\t\tstate.latestRetryTime = action.payload\n\t\t},\n\t},\n})\n\nexport const selectDeletedRequests = (state: OvermapRootState) => state.outboxReducer.deletedRequests\nexport const selectLatestRetryTime = (state: OvermapRootState) => state.outboxReducer.latestRetryTime\n\nexport const { enqueueRequest, markForDeletion, markAsDeleted, _setLatestRetryTime } = outboxSlice.actions\nexport const outboxReducer: Reducer<OutboxState> = outboxSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport {\n\tMultiPointGeometry,\n\tOvermapRootState,\n\tOvermapSelector,\n\tOvermapSelectorWithArgs,\n\tProjectFile,\n} from \"../../typings\"\nimport { selectActiveProjectId } from \"./projectSlice\"\n\nexport interface ProjectFileState {\n\tprojectFiles: Record<string, ProjectFile>\n\tactiveProjectFileId: string | null\n\t/**\n\t * State variable which is set true by web client to mark that the activeProjectFile is a new one that was just\n\t * imported and not a pre-existing one which is being edited\n\t */\n\tisImportingProjectFile: boolean\n}\n\nconst initialState: ProjectFileState = {\n\tprojectFiles: {},\n\tactiveProjectFileId: null,\n\tisImportingProjectFile: false,\n}\n\nexport const projectFileSlice = createSlice({\n\tname: \"projectFiles\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\taddOrReplaceProjectFiles: (state, action: { payload: ProjectFile[] }) => {\n\t\t\tfor (let fileObj of action.payload) {\n\t\t\t\tlet file = fileObj.file\n\t\t\t\tif (file.includes(\"+\")) {\n\t\t\t\t\tconsole.warn(\"Attempting to apply fix for image URL with '+' character:\", file)\n\t\t\t\t\t// We have a src such as this:\n\t\t\t\t\t// https://example.com/my-svg.svg+xml\n\t\t\t\t\t// Or:\n\t\t\t\t\t// blob://.../my-svg.svg+xml\n\t\t\t\t\t// We want just the `my-svg.svg+xml` part.\n\t\t\t\t\tconst parts = file.split(\"/\")\n\t\t\t\t\tif (parts.length < 2) {\n\t\t\t\t\t\tthrow new Error(\"Invalid URL: \" + file)\n\t\t\t\t\t}\n\t\t\t\t\tconst lastPart = encodeURIComponent(parts[parts.length - 1]!)\n\t\t\t\t\t// Reconstruct the URL with the fixed last part.\n\t\t\t\t\tfile = parts.slice(0, -1).join(\"/\") + \"/\" + lastPart\n\t\t\t\t\tconsole.warn(\"Fixed URL:\", file)\n\t\t\t\t\tfileObj = { ...fileObj, file }\n\t\t\t\t}\n\t\t\t\tstate.projectFiles[fileObj.offline_id] = fileObj\n\t\t\t}\n\t\t},\n\t\taddOrReplaceProjectFile: (state, action: { payload: ProjectFile }) => {\n\t\t\tif (!action.payload.project) {\n\t\t\t\tthrow new Error(\"ProjectFile has no project. A project must be set before storing.\")\n\t\t\t}\n\t\t\tstate.projectFiles[action.payload.offline_id] = action.payload\n\t\t},\n\t\tsetIsImportingProjectFile: (state, action: { payload: boolean }) => {\n\t\t\tstate.isImportingProjectFile = action.payload\n\t\t},\n\t\tsaveActiveProjectFileBounds: (state, action: { payload: MultiPointGeometry }) => {\n\t\t\tconst activeProjectFileId = state.activeProjectFileId\n\t\t\tif (!activeProjectFileId) {\n\t\t\t\tthrow new Error(\"Tried to save bounds for active project file, but no active project file was set.\")\n\t\t\t}\n\t\t\tif (!state.projectFiles[activeProjectFileId]) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Tried to save bounds for active project file, but project file with ID ${activeProjectFileId} \n\t\t\t\t\tdoesn't exist.`,\n\t\t\t\t)\n\t\t\t}\n\t\t\tstate.projectFiles[activeProjectFileId]!.bounds = action.payload\n\t\t},\n\t\t// TODO: Move to MapContext. Should not be persisted.\n\t\tsetActiveProjectFileId: (state, action: { payload: string | null }) => {\n\t\t\tstate.activeProjectFileId = action.payload\n\t\t},\n\t\tremoveProjectFile: (state, action: { payload: string }) => {\n\t\t\tdelete state.projectFiles[action.payload]\n\t\t},\n\t\tremoveProjectFilesOfProject: (state, action: { payload: number }) => {\n\t\t\tconst filesToDelete = Object.values(state.projectFiles).filter((file) => file.project === action.payload)\n\t\t\tfor (const file of filesToDelete) {\n\t\t\t\tdelete state.projectFiles[file.offline_id]\n\t\t\t}\n\t\t},\n\t\tresetProjectFileObjectUrls: (state, ..._args: []) => {\n\t\t\tfor (const key in state.projectFiles) {\n\t\t\t\tdelete state.projectFiles[key]!.objectURL\n\t\t\t}\n\t\t},\n\t},\n})\n\nexport const {\n\taddOrReplaceProjectFiles,\n\taddOrReplaceProjectFile,\n\tsetIsImportingProjectFile,\n\tsetActiveProjectFileId,\n\tsaveActiveProjectFileBounds,\n\tremoveProjectFile,\n\tremoveProjectFilesOfProject,\n\tresetProjectFileObjectUrls,\n} = projectFileSlice.actions\n\nexport const selectProjectFileMapping = (state: OvermapRootState) => state.projectFileReducer.projectFiles\n\nexport const selectProjectFiles = createSelector(\n\t[selectProjectFileMapping, selectActiveProjectId],\n\t(mapping, activeProjectId) => {\n\t\treturn Object.values(mapping)\n\t\t\t.filter((file) => file.project === activeProjectId)\n\t\t\t.sort((a, b) => a.z_index - b.z_index)\n\t},\n)\n\nexport const selectActiveProjectFileId: OvermapSelector<string | null> = (state: OvermapRootState) =>\n\tstate.projectFileReducer.activeProjectFileId\n\nexport const selectIsImportingProjectFile: OvermapSelector<boolean> = (state: OvermapRootState) =>\n\tstate.projectFileReducer.isImportingProjectFile\n\nexport const selectProjectFileById: OvermapSelectorWithArgs<string, ProjectFile | undefined> = (id) => (state) => {\n\treturn state.projectFileReducer.projectFiles[id]\n}\n\nexport const projectFileReducer: Reducer<ProjectFileState> = projectFileSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport { ModelState } from \"../typings\"\nimport { OvermapRootState, OvermapSelector, OvermapSelectorWithArgs, ProjectAttachment, Stored } from \"../../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport type ProjectAttachmentState = ModelState<Stored<ProjectAttachment>>\n\nconst projectAttachmentAdapter = createModelAdapter<Stored<ProjectAttachment>>((attachment) => attachment.offline_id)\n\nconst initialState: ProjectAttachmentState = projectAttachmentAdapter.getInitialState({})\n\nexport const projectAttachmentSlice = createSlice({\n\tname: \"projectAttachments\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeProjectAttachments: projectAttachmentAdapter.initialize,\n\t\taddProjectAttachment: projectAttachmentAdapter.addOne,\n\t\taddProjectAttachments: projectAttachmentAdapter.addMany,\n\t\tsetProjectAttachment: projectAttachmentAdapter.setOne,\n\t\tsetProjectAttachments: projectAttachmentAdapter.setMany,\n\t\tupdateProjectAttachment: projectAttachmentAdapter.updateOne,\n\t\tupdateProjectAttachments: projectAttachmentAdapter.updateMany,\n\t\tdeleteProjectAttachment: projectAttachmentAdapter.deleteOne,\n\t\tdeleteProjectAttachments: projectAttachmentAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tinitializeProjectAttachments,\n\taddProjectAttachment,\n\taddProjectAttachments,\n\tsetProjectAttachment,\n\tsetProjectAttachments,\n\tupdateProjectAttachment,\n\tupdateProjectAttachments,\n\tdeleteProjectAttachment,\n\tdeleteProjectAttachments,\n} = projectAttachmentSlice.actions\n\nexport const selectProjectAttachmentMapping = (state: OvermapRootState) => state.projectAttachmentReducer.instances\n\nexport const selectAllProjectAttachments: OvermapSelector<Stored<ProjectAttachment>[]> = createSelector(\n\t[selectProjectAttachmentMapping],\n\t(mapping) => Object.values(mapping),\n)\n\nexport const selectProjectAttachment: OvermapSelectorWithArgs<string, ProjectAttachment | undefined> =\n\t(id) => (state) => {\n\t\treturn state.projectAttachmentReducer.instances[id]\n\t}\n\nexport const selectAttachmentsOfProject = restructureCreateSelectorWithArgs(\n\tcreateSelector([selectAllProjectAttachments, (_, projectId: number) => projectId], (attachments, projectId) => {\n\t\treturn attachments.filter(({ project }) => projectId === project)\n\t}),\n)\nexport const selectAttachmentsOfProjectByType = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectAllProjectAttachments, (_state: OvermapRootState, projectId: number) => projectId],\n\t\t(attachments, projectId) => {\n\t\t\tconst attachmentsOfProject = attachments.filter(({ project }) => projectId === project)\n\t\t\tconst fileAttachments = attachmentsOfProject.filter(\n\t\t\t\t// this null check here is necessary, there are cases where file_type is null or undefined\n\t\t\t\t({ file_type }) => !file_type || !file_type.startsWith(\"image/\"),\n\t\t\t)\n\t\t\tconst imageAttachments = attachmentsOfProject.filter(\n\t\t\t\t// this null check here is necessary, there are cases where file_type is null or undefined\n\t\t\t\t({ file_type }) => file_type && file_type.startsWith(\"image/\"),\n\t\t\t)\n\t\t\treturn { fileAttachments, imageAttachments }\n\t\t},\n\t),\n)\n\nexport const projectAttachmentReducer: Reducer<ProjectAttachmentState> = projectAttachmentSlice.reducer\n","import { createSlice, PayloadAction, Reducer } from \"@reduxjs/toolkit\"\nimport { OvermapRootState } from \"../../typings\"\n\n// TODO: this slice can be moved to /web ?\n\nexport interface RehydratedState {\n\tisRehydrated: boolean\n}\n\nconst initialState: RehydratedState = {\n\tisRehydrated: false,\n}\n\n// rehydratedSlice is used to indicate when the Redux store has finished rehydrating its state from localForage\n// Once finished, the app renders, which prevents the annoying login screen flickering issue\nexport const rehydratedSlice = createSlice({\n\tname: \"rehydrated\",\n\tinitialState,\n\t// The `reducers` field lets us define reducers and generate associated actions\n\treducers: {\n\t\tsetRehydrated: (state, action: PayloadAction<boolean>) => {\n\t\t\tstate.isRehydrated = action.payload\n\t\t},\n\t},\n})\n\nexport const { setRehydrated } = rehydratedSlice.actions\n\n// The function below is called a selector and allows us to select a value from\n// the state. Selectors can also be defined inline where they're used instead of\n// in the slice file. For example: `useSelector((state: RootState) => state.counter.value)`\nexport const selectRehydrated = (state: OvermapRootState) => state.rehydratedReducer.isRehydrated\n\nexport const rehydratedReducer: Reducer<RehydratedState> = rehydratedSlice.reducer\n","import { Stored, FormRevision } from \"../typings\"\n\nexport const formRevisionSortFn = (formRevisionA: Stored<FormRevision>, formRevisionB: Stored<FormRevision>) => {\n\tconst revisionA = formRevisionA.revision\n\tconst revisionB = formRevisionB.revision\n\n\tif (revisionA === \"Pending\" && revisionB === \"Pending\") {\n\t\treturn formRevisionA.submitted_at < formRevisionB.submitted_at ? -1 : 1\n\t} else if (revisionA === \"Pending\") {\n\t\treturn 1\n\t} else if (revisionB === \"Pending\") {\n\t\treturn -1\n\t} else {\n\t\treturn revisionA < revisionB ? -1 : 1\n\t}\n}\n","import { createSlice, Reducer, createSelector } from \"@reduxjs/toolkit\"\nimport { OvermapRootState, OvermapSelector, OvermapSelectorWithArgs, Stored, Form, FormRevision } from \"../../typings\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\nimport { formRevisionSortFn } from \"../../utils/forms\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\n\nexport type FormRevisionState = ModelState<Stored<FormRevision>>\n\nconst formRevisionAdapter = createModelAdapter<Stored<FormRevision>>((revision) => revision.offline_id)\n\nconst initialState: FormRevisionState = formRevisionAdapter.getInitialState({})\n\nexport const formRevisionsSlice = createSlice({\n\tname: \"formRevisions\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeFormRevisions: formRevisionAdapter.initialize,\n\t\tsetFormRevision: formRevisionAdapter.setOne,\n\t\taddFormRevision: formRevisionAdapter.addOne,\n\t\taddFormRevisions: formRevisionAdapter.addMany,\n\t\tdeleteFormRevision: formRevisionAdapter.deleteOne,\n\t\tdeleteFormRevisions: formRevisionAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tsetFormRevision,\n\tinitializeFormRevisions,\n\taddFormRevision,\n\taddFormRevisions,\n\tdeleteFormRevision,\n\tdeleteFormRevisions,\n} = formRevisionsSlice.actions\n\nexport const selectFormRevisionMapping = (state: OvermapRootState) => state.formRevisionReducer.instances\n\nexport const selectFormRevisions = createSelector([selectFormRevisionMapping], (formRevisions) =>\n\tObject.values(formRevisions),\n)\n\nexport const selectFormRevisionById: OvermapSelectorWithArgs<string, Stored<FormRevision> | undefined> =\n\t(formRevisionId: string) => (state: OvermapRootState) => {\n\t\treturn state.formRevisionReducer.instances[formRevisionId]\n\t}\n\n// takes user form state revisions instead of the whole state as an argument\nexport const _selectLatestFormRevision = (\n\tformRevisions: FormRevisionState[\"instances\"],\n\tformId: string,\n): Stored<FormRevision> => {\n\tlet ret: Stored<FormRevision> | null = null\n\n\tfor (const candidate of Object.values(formRevisions)) {\n\t\tif (candidate.form === formId && (!ret || ret.revision < candidate.revision)) {\n\t\t\tret = candidate\n\t\t}\n\t}\n\n\tif (!ret) {\n\t\tthrow new Error(\"No form revision found for form \" + formId)\n\t}\n\n\treturn ret\n}\n\nexport const selectLatestFormRevisionOfForm: OvermapSelectorWithArgs<string, Stored<FormRevision> | undefined> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector(\n\t\t\t[selectFormRevisionMapping, (_state: OvermapRootState, formId: string) => formId],\n\t\t\t(revisions, formId) => {\n\t\t\t\tconst revisionsOfForm = Object.values(revisions).filter((revision) => revision.form === formId)\n\n\t\t\t\tif (revisionsOfForm.length === 0) return undefined\n\n\t\t\t\tconst sortedRevisions = revisionsOfForm.sort(formRevisionSortFn)\n\n\t\t\t\tconst latestRevision = sortedRevisions[revisionsOfForm.length - 1]!\n\n\t\t\t\treturn revisions[latestRevision.offline_id]\n\t\t\t},\n\t\t),\n\t)\n\nexport const selectFormRevisionsOfForm: OvermapSelectorWithArgs<string, Stored<FormRevision>[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector(\n\t\t\t[selectFormRevisions, (_state: OvermapRootState, formId: string) => formId],\n\t\t\t(revisions, formId) => {\n\t\t\t\treturn revisions.filter((revision) => {\n\t\t\t\t\treturn revision.form === formId\n\t\t\t\t})\n\t\t\t},\n\t\t),\n\t)\n\nexport const selectLatestFormRevisionsOfAssetTypes: OvermapSelectorWithArgs<\n\tstring[],\n\tRecord<string, Stored<FormRevision>>\n> = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[\n\t\t\t(state: OvermapRootState) => state.formReducer.instances,\n\t\t\tselectFormRevisionMapping,\n\t\t\t(_state: OvermapRootState, assetTypeIds: string[]) => assetTypeIds,\n\t\t],\n\t\t(formsMapping, revisions, assetTypeIds) => {\n\t\t\tconst assetTypeIdsSet = new Set(assetTypeIds)\n\t\t\tconst formsOfAssetTypes: Record<string, Stored<Form>> = {}\n\t\t\tconst ret: Record<string, Stored<FormRevision>> = {}\n\n\t\t\tfor (const form of Object.values(formsMapping)) {\n\t\t\t\tif (form.asset_type && assetTypeIdsSet.has(form.asset_type)) {\n\t\t\t\t\tformsOfAssetTypes[form.offline_id] = form\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const revision of Object.values(revisions)) {\n\t\t\t\t// look up if a asset type form exists for the current revision\n\t\t\t\tconst form = formsOfAssetTypes[revision.form]\n\n\t\t\t\tif (\n\t\t\t\t\t!form ||\n\t\t\t\t\t!form.asset_type ||\n\t\t\t\t\t(ret[form.asset_type] && formRevisionSortFn(ret[form.asset_type]!, revision) > 0)\n\t\t\t\t)\n\t\t\t\t\tcontinue\n\n\t\t\t\tret[form.asset_type] = revision\n\t\t\t}\n\n\t\t\treturn ret\n\t\t},\n\t),\n)\n\nexport const selectLatestFormRevisionByForm: OvermapSelector<Record<Stored<Form>[\"offline_id\"], Stored<FormRevision>>> =\n\tcreateSelector([selectFormRevisionMapping], (revisions) => {\n\t\tconst latestRevisions: Record<string, FormRevision> = {}\n\t\tfor (const revision of Object.values(revisions)) {\n\t\t\tconst formId = revision.form\n\t\t\tconst currentLatestRevision = latestRevisions[formId]\n\t\t\tif (!currentLatestRevision || currentLatestRevision.revision < revision.revision) {\n\t\t\t\tlatestRevisions[formId] = revision\n\t\t\t}\n\t\t}\n\t\treturn latestRevisions\n\t})\n\nexport const formRevisionReducer: Reducer<FormRevisionState> = formRevisionsSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport { CachedForm, Form } from \"typings/models/forms\"\nimport { SearchArgs } from \"typings/search\"\nimport { OvermapSelector, OvermapSelectorWithArgs } from \"typings/store\"\nimport { restructureCreateSelectorWithArgs } from \"utils/utils\"\nimport { OvermapRootState, Stored } from \"../../typings\"\nimport { _selectLatestFormRevision } from \"./formRevisionSlice\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { shallowEqual } from \"../../utils\"\n\nexport type FormState = ModelState<Stored<Form>>\n\nconst formAdapter = createModelAdapter<Stored<Form>>((form) => form.offline_id)\n\nconst initialState: FormState = formAdapter.getInitialState({})\n\nexport const formSlice = createSlice({\n\tname: \"forms\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeForms: formAdapter.initialize,\n\t\tsetForm: formAdapter.setOne,\n\t\taddForm: formAdapter.addOne,\n\t\taddForms: formAdapter.addMany,\n\t\tupdateForm: formAdapter.updateOne,\n\t\tdeleteForm: formAdapter.deleteOne,\n\t},\n})\n\nexport const { initializeForms, setForm, addForm, addForms, updateForm, deleteForm } = formSlice.actions\n\nexport type FormSearchArgs = SearchArgs<{\n\t/** `undefined` means don't filter by favorite. `boolean` filters forms. */\n\tfavorites?: boolean\n\t/** organization owner */\n\torganization?: number\n}>\n\nexport const selectFormsMapping: OvermapSelector<Record<Stored<Form>[\"offline_id\"], Stored<Form>>> = (state) => {\n\treturn state.formReducer.instances\n}\n\nexport const selectFilteredForms: OvermapSelectorWithArgs<FormSearchArgs, CachedForm[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector(\n\t\t\t[\n\t\t\t\t(state: OvermapRootState) => state.formReducer.instances,\n\t\t\t\t(state: OvermapRootState) => state.formRevisionReducer.instances,\n\t\t\t\t(_state: OvermapRootState, search: FormSearchArgs) => search,\n\t\t\t],\n\t\t\t(formsMapping, revisions, search) => {\n\t\t\t\tconst { searchTerm, maxResults, favorites, organization } = search\n\n\t\t\t\tconst favoriteMatches: CachedForm[] = []\n\t\t\t\tconst regularMatches: CachedForm[] = []\n\n\t\t\t\tfor (const [formId, form] of Object.entries(formsMapping)) {\n\t\t\t\t\t// if filtering by favorites, skip forms with the wrong favorite status\n\t\t\t\t\tif (favorites !== undefined && form.favorite != favorites) continue\n\n\t\t\t\t\t// if filtering by organizations, skip forms with the wrong organization\n\t\t\t\t\tif (Number.isInteger(organization) && organization !== form.organization) {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\n\t\t\t\t\t// find the latest revision for this form (note: expensive)\n\t\t\t\t\tconst latestRevision = _selectLatestFormRevision(revisions, formId)\n\n\t\t\t\t\tif (latestRevision.title.toLowerCase().includes(searchTerm.toLowerCase())) {\n\t\t\t\t\t\tif (form.favorite) {\n\t\t\t\t\t\t\tfavoriteMatches.push({ ...form, latestRevision: latestRevision })\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tregularMatches.push({ ...form, latestRevision: latestRevision })\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// if we've found enough matches, stop searching\n\t\t\t\t\t// only count favorites as favorites are displayed first\n\t\t\t\t\tif (favoriteMatches.length >= maxResults) {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst maxRegularMatches = maxResults - favoriteMatches.length\n\n\t\t\t\treturn [...favoriteMatches, ...regularMatches.slice(0, maxRegularMatches)]\n\t\t\t},\n\t\t\t// as the argument is an object, we check the first level of properties for equality\n\t\t\t{ memoizeOptions: { equalityCheck: shallowEqual } },\n\t\t),\n\t)\n\nexport const selectFormMapping: OvermapSelector<Record<Stored<Form>[\"offline_id\"], Stored<Form>>> = (\n\tstate: OvermapRootState,\n) => {\n\treturn state.formReducer.instances\n}\n\nexport const selectFormById: OvermapSelectorWithArgs<string, Stored<Form> | undefined> =\n\t(formId: string) => (state: OvermapRootState) => {\n\t\treturn state.formReducer.instances[formId]\n\t}\n\nexport const selectFormOfAssetType: OvermapSelectorWithArgs<string, Stored<Form> | undefined> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector(\n\t\t\t[selectFormMapping, (_state: OvermapRootState, assetTypeId: string) => assetTypeId],\n\t\t\t(formsMapping, assetTypeId) => {\n\t\t\t\treturn Object.values(formsMapping).find((form) => form.asset_type === assetTypeId)\n\t\t\t},\n\t\t),\n\t)\n\nexport const selectFormOfIssueType: OvermapSelectorWithArgs<string, Stored<Form> | undefined> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector(\n\t\t\t[selectFormMapping, (_state: OvermapRootState, issueTypeId: string) => issueTypeId],\n\t\t\t(formsMapping, issueTypeId) => {\n\t\t\t\treturn Object.values(formsMapping).find((form) => form.issue_type === issueTypeId)\n\t\t\t},\n\t\t),\n\t)\n\n// Total number of user forms\nexport const selectFormsCount: OvermapSelector<number> = createSelector([selectFormMapping], (formsMapping) => {\n\treturn Object.keys(formsMapping).length\n})\n\n// Number of user forms not related to a asset type\nexport const selectGeneralFormCount: OvermapSelector<number> = createSelector([selectFormMapping], (formsMapping) => {\n\treturn Object.values(formsMapping).filter((form) => !form.asset_type).length\n})\n\nexport const formReducer: Reducer<FormState> = formSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport { OvermapRootState, OvermapSelector, OvermapSelectorWithArgs, Stored, FormSubmission } from \"../../typings\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\nimport { selectFormRevisionMapping } from \"./formRevisionSlice\"\nimport { selectAssetsMapping } from \"./assetSlice\"\nimport { formRevisionSortFn } from \"../../utils/forms\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\n\nexport type FormSubmissionState = ModelState<Stored<FormSubmission>>\n\nconst submissionAdapter = createModelAdapter<Stored<FormSubmission>>((submission) => submission.offline_id)\n\nconst initialState: FormSubmissionState = submissionAdapter.getInitialState({})\n\nexport const formSubmissionSlice = createSlice({\n\tname: \"formSubmissions\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeFormSubmissions: submissionAdapter.initialize,\n\t\tsetFormSubmission: submissionAdapter.setOne,\n\t\tsetFormSubmissions: submissionAdapter.setMany,\n\t\taddFormSubmission: submissionAdapter.addOne,\n\t\taddFormSubmissions: submissionAdapter.addMany,\n\t\tupdateFormSubmission: submissionAdapter.updateOne,\n\t\tupdateFormSubmissions: submissionAdapter.updateMany,\n\t\tdeleteFormSubmission: submissionAdapter.deleteOne,\n\t\tdeleteFormSubmissions: submissionAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tinitializeFormSubmissions,\n\tsetFormSubmission,\n\tsetFormSubmissions,\n\taddFormSubmission,\n\taddFormSubmissions,\n\tupdateFormSubmission,\n\tupdateFormSubmissions,\n\tdeleteFormSubmission,\n\tdeleteFormSubmissions,\n} = formSubmissionSlice.actions\n\nexport const selectFormSubmissionsMapping: OvermapSelector<FormSubmissionState[\"instances\"]> = (state) => {\n\treturn state.formSubmissionReducer.instances\n}\n\nexport const selectFormSubmissions: OvermapSelector<Stored<FormSubmission>[]> = createSelector(\n\t[selectFormSubmissionsMapping],\n\t(submissions) => {\n\t\treturn Object.values(submissions)\n\t},\n)\n\nexport const selectFormSubmissionById: OvermapSelectorWithArgs<string, Stored<FormSubmission> | undefined> =\n\t(submissionId) => (state: OvermapRootState) => {\n\t\treturn state.formSubmissionReducer.instances[submissionId]\n\t}\n\nexport const selectFormSubmissionsOfForm: OvermapSelectorWithArgs<string, Stored<FormSubmission>[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector(\n\t\t\t[\n\t\t\t\tselectFormSubmissionsMapping,\n\t\t\t\tselectFormRevisionMapping,\n\t\t\t\t(_state: OvermapRootState, formId: string) => formId,\n\t\t\t],\n\t\t\t(submissions, revisionMapping, formId) => {\n\t\t\t\tconst revisionsOfForm = Object.values(revisionMapping).filter((revision) => revision.form === formId)\n\t\t\t\tconst revisionIds = new Set(revisionsOfForm.map((revision) => revision.offline_id))\n\n\t\t\t\treturn Object.values(submissions).filter((submission) => {\n\t\t\t\t\treturn revisionIds.has(submission.form_revision)\n\t\t\t\t})\n\t\t\t},\n\t\t),\n\t)\n\nexport const selectFormSubmissionsByFormRevisions: OvermapSelector<Record<string, Stored<FormSubmission>[]>> =\n\tcreateSelector([selectFormRevisionMapping, selectFormSubmissions], (revisions, submissions) => {\n\t\tconst submissionMapping: Record<string, Stored<FormSubmission>[]> = {}\n\t\tfor (const revisionId in revisions) {\n\t\t\tsubmissionMapping[revisionId] = []\n\t\t}\n\t\tfor (const submission of submissions) {\n\t\t\tsubmissionMapping[submission.form_revision]?.push(submission)\n\t\t}\n\t\treturn submissionMapping\n\t})\n\nexport const selectSortedFormSubmissionsOfForm: OvermapSelectorWithArgs<string, Stored<FormSubmission>[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector(\n\t\t\t[\n\t\t\t\tselectFormRevisionMapping,\n\t\t\t\tselectFormSubmissionsByFormRevisions,\n\t\t\t\t(_state: OvermapRootState, formId: string) => formId,\n\t\t\t],\n\t\t\t(revisionsMapping, submissionsByRevision, formId) => {\n\t\t\t\tconst submissionsByFormRevisions: Record<string, Stored<FormSubmission>[]> = {}\n\n\t\t\t\tfor (const revisionId in revisionsMapping) {\n\t\t\t\t\tconst revision = revisionsMapping[revisionId]\n\t\t\t\t\tconst submissionsOfRevision = submissionsByRevision[revisionId]\n\t\t\t\t\tif (revision && submissionsOfRevision && revision.form === formId) {\n\t\t\t\t\t\tsubmissionsByFormRevisions[revisionId] = submissionsOfRevision.sort((a, b) =>\n\t\t\t\t\t\t\ta.submitted_at < b.submitted_at ? -1 : 1,\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn Object.entries(submissionsByFormRevisions)\n\t\t\t\t\t.sort((a, b) => {\n\t\t\t\t\t\tconst aRevision = revisionsMapping[a[0]]!\n\t\t\t\t\t\tconst bRevision = revisionsMapping[b[0]]!\n\t\t\t\t\t\treturn formRevisionSortFn(aRevision, bRevision)\n\t\t\t\t\t})\n\t\t\t\t\t.map(([_revisionId, submissions]) => submissions)\n\t\t\t\t\t.flat()\n\t\t\t},\n\t\t),\n\t)\n\nexport const selectFormSubmissionsOfIssue = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectFormSubmissions, (_state: OvermapRootState, issueId: string) => issueId],\n\t\t(submissions, issueId) => {\n\t\t\treturn Object.values(submissions).filter((submission) => {\n\t\t\t\treturn submission.issue === issueId\n\t\t\t})\n\t\t},\n\t),\n)\n\nexport const selectAttachedFormSubmissionsOfIssue = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[\n\t\t\t(state: OvermapRootState) => state.issueReducer.instances,\n\t\t\t(state: OvermapRootState) => state.formReducer.instances,\n\t\t\t(state: OvermapRootState) => state.formRevisionReducer.instances,\n\t\t\t(state: OvermapRootState) => state.formSubmissionReducer.instances,\n\t\t\t(_state: OvermapRootState, issueId: string) => issueId,\n\t\t],\n\t\t(issues, forms, formRevisions, submissions, issueId) => {\n\t\t\t// step 1: check if issue has an issue type\n\t\t\tconst issue = issues[issueId]\n\n\t\t\tif (!issue) return []\n\n\t\t\tif (!issue.issue_type) {\n\t\t\t\treturn Object.values(submissions).filter((submission) => submission.issue === issueId)\n\t\t\t}\n\n\t\t\t// step 2: find the ids for forms of the issue type\n\t\t\tconst issueTypeForms = new Set(\n\t\t\t\tObject.keys(forms).filter((formId) => forms[formId]!.issue_type === issue.issue_type),\n\t\t\t)\n\n\t\t\t// step 3: find the ids for form revisions of the forms\n\t\t\tconst issueTypeFormRevisions = new Set(\n\t\t\t\tObject.keys(formRevisions).filter((formRevisionId) =>\n\t\t\t\t\tissueTypeForms.has(formRevisions[formRevisionId]!.form),\n\t\t\t\t),\n\t\t\t)\n\n\t\t\t// step 4: filter out any submissions whos revision is in the set\n\t\t\treturn Object.values(submissions).filter(\n\t\t\t\t(submission) => submission.issue === issueId && !issueTypeFormRevisions.has(submission.form_revision),\n\t\t\t)\n\t\t},\n\t),\n)\n\nexport const selectFormSubmissionsByIssues: OvermapSelectorWithArgs<\n\tstring[],\n\tRecord<string, Stored<FormSubmission>[]>\n> = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectFormSubmissions, (_state: OvermapRootState, issueIds: string[]) => issueIds],\n\t\t(submissions, issueIds) => {\n\t\t\tconst issueSubmissions: Record<string, Stored<FormSubmission>[]> = {}\n\t\t\tfor (const issueId of issueIds) {\n\t\t\t\tissueSubmissions[issueId] = []\n\t\t\t}\n\t\t\tfor (const submission of submissions) {\n\t\t\t\tif (submission.issue && issueIds.includes(submission.issue)) {\n\t\t\t\t\tissueSubmissions[submission.issue]?.push(submission)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn issueSubmissions\n\t\t},\n\t),\n)\n\nexport const selectFormSubmissionsOfAsset = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectFormSubmissions, (_state: OvermapRootState, assetId: string) => assetId],\n\t\t(submissions, assetId) => {\n\t\t\treturn submissions.filter((submission) => {\n\t\t\t\treturn submission.asset === assetId\n\t\t\t})\n\t\t},\n\t),\n)\n\nexport const selectAttachedFormSubmissionsOfAsset = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[\n\t\t\t(state: OvermapRootState) => state.assetReducer.instances,\n\t\t\t(state: OvermapRootState) => state.formReducer.instances,\n\t\t\t(state: OvermapRootState) => state.formRevisionReducer.instances,\n\t\t\t(state: OvermapRootState) => state.formSubmissionReducer.instances,\n\t\t\t(_state: OvermapRootState, assetId: string) => assetId,\n\t\t],\n\t\t(assets, forms, formRevisions, submissions, assetId) => {\n\t\t\t// step 1: check if asset has an asset type\n\t\t\tconst asset = assets[assetId]\n\n\t\t\tif (!asset) return []\n\n\t\t\tif (!asset.asset_type) {\n\t\t\t\treturn Object.values(submissions).filter((submission) => submission.asset === assetId)\n\t\t\t}\n\n\t\t\t// step 2: find the ids for forms of the asset type\n\t\t\tconst issueTypeForms = new Set(\n\t\t\t\tObject.keys(forms).filter((formId) => forms[formId]!.asset_type === asset.asset_type),\n\t\t\t)\n\n\t\t\t// step 3: find the ids for form revisions of the forms\n\t\t\tconst issueTypeFormRevisions = new Set(\n\t\t\t\tObject.keys(formRevisions).filter((formRevisionId) =>\n\t\t\t\t\tissueTypeForms.has(formRevisions[formRevisionId]!.form),\n\t\t\t\t),\n\t\t\t)\n\n\t\t\t// step 4: filter out any submissions whos revision is in the set\n\t\t\treturn Object.values(submissions).filter(\n\t\t\t\t(submission) => submission.asset === assetId && !issueTypeFormRevisions.has(submission.form_revision),\n\t\t\t)\n\t\t},\n\t),\n)\n\nexport const selectFormSubmissionsByAssets: OvermapSelector<Record<string, Stored<FormSubmission>[]>> = createSelector(\n\t[selectFormSubmissionsMapping, selectAssetsMapping],\n\t(submissions, assets) => {\n\t\tconst assetSubmissionMapping: Record<string, FormSubmission[]> = {}\n\t\tfor (const assetId in assets) {\n\t\t\tassetSubmissionMapping[assetId] = []\n\t\t}\n\t\tfor (const submissionId in submissions) {\n\t\t\tconst submission = submissions[submissionId]!\n\t\t\tif (submission.asset) {\n\t\t\t\tassetSubmissionMapping[submission.asset]?.push(submission)\n\t\t\t}\n\t\t}\n\t\treturn assetSubmissionMapping\n\t},\n)\n\nexport const formSubmissionReducer: Reducer<FormSubmissionState> = formSubmissionSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport { ModelState } from \"../typings\"\nimport {\n\tFormSubmissionAttachment,\n\tOvermapRootState,\n\tOvermapSelector,\n\tOvermapSelectorWithArgs,\n\tStored,\n} from \"../../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport type FormSubmissionAttachmentState = ModelState<Stored<FormSubmissionAttachment>>\n\nconst formSubmissionAttachmentAdapter = createModelAdapter<Stored<FormSubmissionAttachment>>(\n\t(attachment) => attachment.offline_id,\n)\n\nconst initialState: FormSubmissionAttachmentState = formSubmissionAttachmentAdapter.getInitialState({})\n\nexport const formSubmissionAttachmentSlice = createSlice({\n\tname: \"formSubmissionAttachments\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeFormSubmissionAttachments: formSubmissionAttachmentAdapter.initialize,\n\t\taddFormSubmissionAttachment: formSubmissionAttachmentAdapter.addOne,\n\t\taddFormSubmissionAttachments: formSubmissionAttachmentAdapter.addMany,\n\t\tsetFormSubmissionAttachment: formSubmissionAttachmentAdapter.setOne,\n\t\tsetFormSubmissionAttachments: formSubmissionAttachmentAdapter.setMany,\n\t\tupdateFormSubmissionAttachment: formSubmissionAttachmentAdapter.updateOne,\n\t\tupdateFormSubmissionAttachments: formSubmissionAttachmentAdapter.updateMany,\n\t\tdeleteFormSubmissionAttachment: formSubmissionAttachmentAdapter.deleteOne,\n\t\tdeleteFormSubmissionAttachments: formSubmissionAttachmentAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tinitializeFormSubmissionAttachments,\n\taddFormSubmissionAttachment,\n\taddFormSubmissionAttachments,\n\tsetFormSubmissionAttachment,\n\tsetFormSubmissionAttachments,\n\tupdateFormSubmissionAttachment,\n\tupdateFormSubmissionAttachments,\n\tdeleteFormSubmissionAttachment,\n\tdeleteFormSubmissionAttachments,\n} = formSubmissionAttachmentSlice.actions\n\nexport const selectFormSubmissionAttachmentsMapping: OvermapSelector<FormSubmissionAttachmentState[\"instances\"]> = (\n\tstate,\n) => {\n\treturn state.formSubmissionAttachmentReducer.instances\n}\n\nexport const selectFormSubmissionAttachemntsByIds = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectFormSubmissionAttachmentsMapping, (_, attachmentIds: string[]) => attachmentIds],\n\t\t(mapping, attachmentIds) => {\n\t\t\tconst attachmentIdsSet = new Set(attachmentIds)\n\n\t\t\treturn Object.values(mapping).filter((attachment) => attachmentIdsSet.has(attachment.offline_id))\n\t\t},\n\t),\n)\n\nexport const selectAttachmentsOfFormSubmission: OvermapSelectorWithArgs<string, Stored<FormSubmissionAttachment>[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector(\n\t\t\t[selectFormSubmissionAttachmentsMapping, (_state: OvermapRootState, submissionId: string) => submissionId],\n\t\t\t(attachmentsMapping, submissionId) => {\n\t\t\t\treturn Object.values(attachmentsMapping).filter((attachment) => attachment.submission === submissionId)\n\t\t\t},\n\t\t),\n\t)\n\nexport const formSubmissionAttachmentReducer: Reducer<FormSubmissionAttachmentState> =\n\tformSubmissionAttachmentSlice.reducer\n","import { createSlice, Reducer, createSelector } from \"@reduxjs/toolkit\"\nimport { ModelState } from \"../typings\"\nimport { OvermapSelector, OvermapSelectorWithArgs, Stored, FormRevisionAttachment } from \"../../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport type FormRevisionAttachmentState = ModelState<Stored<FormRevisionAttachment>>\n\nconst formRevisionAttachmentAdapter = createModelAdapter<Stored<FormRevisionAttachment>>(\n\t(attachment) => attachment.offline_id,\n)\n\nconst initialState: FormRevisionAttachmentState = formRevisionAttachmentAdapter.getInitialState({})\n\nexport const formRevisionAttachmentSlice = createSlice({\n\tname: \"formRevisionAttachments\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeFormRevisionAttachments: formRevisionAttachmentAdapter.initialize,\n\t\taddFormRevisionAttachment: formRevisionAttachmentAdapter.addOne,\n\t\taddFormRevisionAttachments: formRevisionAttachmentAdapter.addMany,\n\t\tsetFormRevisionAttachment: formRevisionAttachmentAdapter.setOne,\n\t\tsetFormRevisionAttachments: formRevisionAttachmentAdapter.setMany,\n\t\tupdateFormRevisionAttachment: formRevisionAttachmentAdapter.updateOne,\n\t\tupdateFormRevisionAttachments: formRevisionAttachmentAdapter.updateMany,\n\t\tdeleteFormRevisionAttachment: formRevisionAttachmentAdapter.deleteOne,\n\t\tdeleteFormRevisionAttachments: formRevisionAttachmentAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tinitializeFormRevisionAttachments,\n\taddFormRevisionAttachment,\n\taddFormRevisionAttachments,\n\tsetFormRevisionAttachment,\n\tsetFormRevisionAttachments,\n\tupdateFormRevisionAttachment,\n\tupdateFormRevisionAttachments,\n\tdeleteFormRevisionAttachment,\n\tdeleteFormRevisionAttachments,\n} = formRevisionAttachmentSlice.actions\n\nexport const selectFormRevisionAttachmentsMapping: OvermapSelector<FormRevisionAttachmentState[\"instances\"]> = (\n\tstate,\n) => {\n\treturn state.formRevisionAttachmentReducer.instances\n}\n\nexport const selectAttachmentsOfFormRevision: OvermapSelectorWithArgs<string, Stored<FormRevisionAttachment>[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector(\n\t\t\t[selectFormRevisionAttachmentsMapping, (_state, revisionId: string) => revisionId],\n\t\t\t(attachments, revisionId) => {\n\t\t\t\treturn Object.values(attachments).filter((attachment) => attachment.revision === revisionId)\n\t\t\t},\n\t\t),\n\t)\n\nexport const formRevisionAttachmentReducer: Reducer<FormRevisionAttachmentState> = formRevisionAttachmentSlice.reducer\n","import { EmailDomain, OvermapSelector, OvermapRootState } from \"../../typings\"\nimport { createSlice, Reducer, createSelector } from \"@reduxjs/toolkit\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport type EmailDomainState = ModelState<EmailDomain>\n\nconst emailDomainAdapter = createModelAdapter<EmailDomain>((emailDomain) => emailDomain.offline_id)\n\nconst initialState = emailDomainAdapter.getInitialState({})\n\nexport const emailDomainsSlice = createSlice({\n\tname: \"emailDomains\",\n\tinitialState,\n\treducers: {\n\t\tinitializeEmailDomains: emailDomainAdapter.initialize,\n\t\taddEmailDomain: emailDomainAdapter.addOne,\n\t\tdeleteEmailDomain: emailDomainAdapter.deleteOne,\n\t},\n})\n\nexport const { initializeEmailDomains, addEmailDomain, deleteEmailDomain } = emailDomainsSlice.actions\n\nexport const selectEmailDomainsAsMapping: OvermapSelector<Record<number, EmailDomain>> = (state: OvermapRootState) =>\n\tstate.emailDomainsReducer.instances\n\nexport const selectEmailDomains = (state: OvermapRootState): EmailDomain[] =>\n\tObject.values(state.emailDomainsReducer.instances)\n\nexport const selectEmailDomainsOfOrganization = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectEmailDomains, (_, organizationId: number) => organizationId],\n\t\t(emailDomains, organizationId) => {\n\t\t\treturn emailDomains.filter((emailDomain) => emailDomain.organization === organizationId)\n\t\t},\n\t),\n)\n\nexport const emailDomainsReducer: Reducer<EmailDomainState> = emailDomainsSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport {\n\tDocument,\n\tMovePosition,\n\tOvermapRootState,\n\tOvermapSelector,\n\tOvermapSelectorWithArgs,\n\tStored,\n\tSubmitted,\n} from \"../../typings\"\nimport { onlyUniqueOfflineIds, restructureCreateSelectorWithArgs, toOfflineIdRecord } from \"../../utils\"\n\nexport interface DocumentState {\n\tdocuments: Record<string, Stored<Document>>\n}\n\nexport interface MoveDocumentPayload {\n\tdocumentId: Document[\"offline_id\"]\n\ttargetDocumentId: Document[\"offline_id\"] | null\n\tposition: MovePosition\n}\n\nconst initialState: DocumentState = {\n\tdocuments: {},\n}\n\nexport const documentSlice = createSlice({\n\tname: \"documents\",\n\tinitialState: initialState,\n\textraReducers: (builder) =>\n\t\tbuilder.addCase(\"RESET\", (state) => {\n\t\t\tObject.assign(state, initialState)\n\t\t}),\n\treducers: {\n\t\tsetDocuments: (state, action: { payload: Stored<Document>[] }) => {\n\t\t\tif (action.payload.filter(onlyUniqueOfflineIds).length !== action.payload.length) {\n\t\t\t\tthrow new Error(\"Tried to use setIssues reducer with duplicate ID's\")\n\t\t\t}\n\t\t\tstate.documents = toOfflineIdRecord(action.payload)\n\t\t},\n\t\taddDocuments: (state, action: { payload: Stored<Document>[] }) => {\n\t\t\tfor (const document of action.payload) {\n\t\t\t\tif (document.offline_id in state.documents) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`attempting to add a document with offline_id ${document.offline_id} which already exists in state.documents.`,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (const document of action.payload) {\n\t\t\t\tif (document.parent_document && !!state.documents[document.parent_document]) {\n\t\t\t\t\tconst parentDocument = state.documents[document.parent_document]!\n\t\t\t\t\tstate.documents[document.parent_document] = {\n\t\t\t\t\t\t...parentDocument,\n\t\t\t\t\t\tchildren_documents: [...parentDocument.children_documents, document.offline_id],\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tstate.documents[document.offline_id] = document\n\t\t\t}\n\t\t},\n\t\tupdateDocuments: (state, action: { payload: Submitted<Partial<Stored<Document>>>[] }) => {\n\t\t\tfor (const document of action.payload) {\n\t\t\t\tif (!(document.offline_id in state.documents)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`attempting to update a document with offline_id ${document.offline_id} which doesn't exists in state.documents.`,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (const document of action.payload) {\n\t\t\t\tconst existingDocument = state.documents[document.offline_id]!\n\t\t\t\tif (document.organization !== undefined && document.organization !== existingDocument.organization) {\n\t\t\t\t\tthrow new Error(\"organization cannot be updated\")\n\t\t\t\t}\n\t\t\t\tif (document.project !== undefined && document.project !== existingDocument.project) {\n\t\t\t\t\tthrow new Error(\"project cannot be updated\")\n\t\t\t\t}\n\t\t\t\tstate.documents[document.offline_id] = {\n\t\t\t\t\t...existingDocument,\n\t\t\t\t\t...document,\n\t\t\t\t\t// Without the cast, TypeScript doesn't realize that we have guaranteed that the document doesn't\n\t\t\t\t\t// have both a project and an organization.\n\t\t\t\t} as Stored<Document>\n\t\t\t}\n\t\t},\n\t\tmoveDocument: (state, action: { payload: MoveDocumentPayload }) => {\n\t\t\tconst { documentId, targetDocumentId, position } = action.payload\n\t\t\tif (!(documentId in state.documents)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`attempting to move a document with offline_id ${documentId} which doesn't exist in state.documents`,\n\t\t\t\t)\n\t\t\t}\n\n\t\t\t// even if a document is being moved to the same parent, it needs to be removed since its position in its parent would be changing\n\t\t\tconst document = state.documents[documentId]!\n\t\t\tif (document.parent_document && state.documents[document.parent_document]) {\n\t\t\t\tconst { children_documents } = state.documents[document.parent_document]!\n\t\t\t\tstate.documents[document.parent_document]!.children_documents.splice(\n\t\t\t\t\tchildren_documents.indexOf(document.offline_id),\n\t\t\t\t\t1,\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tif (targetDocumentId) {\n\t\t\t\tconst targetDocument = state.documents[targetDocumentId]\n\t\t\t\tconst newParentDocument = targetDocument?.parent_document\n\t\t\t\t\t? state.documents[targetDocument.parent_document]\n\t\t\t\t\t: null\n\n\t\t\t\tswitch (position) {\n\t\t\t\t\tcase \"left\":\n\t\t\t\t\t\tif (!newParentDocument) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t\"attempting to move a document to the left of a document with no parent_document\",\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// if newParentDocument exists, then targetDocument must exist\n\t\t\t\t\t\tstate.documents[targetDocument!.parent_document!]!.children_documents.splice(\n\t\t\t\t\t\t\tnewParentDocument.children_documents.indexOf(targetDocument!.offline_id),\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\tdocument.offline_id,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tstate.documents[documentId]!.parent_document = newParentDocument.offline_id\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase \"right\":\n\t\t\t\t\t\tif (!newParentDocument) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t\"attempting to move a document to the left of a document with no parent_document\",\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// if newParentDocument exists, then targetDocument must exist\n\t\t\t\t\t\tstate.documents[targetDocument!.parent_document!]!.children_documents.splice(\n\t\t\t\t\t\t\tnewParentDocument.children_documents.indexOf(targetDocument!.offline_id) + 1,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\tdocument.offline_id,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tstate.documents[documentId]!.parent_document = newParentDocument.offline_id\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase \"left-child\":\n\t\t\t\t\t\tif (!targetDocument) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t\"attempting to move a document to the left-child of a document that doesn't exist\",\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstate.documents[targetDocumentId]!.children_documents.unshift(document.offline_id)\n\t\t\t\t\t\tstate.documents[documentId]!.parent_document = targetDocument.offline_id\n\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase \"right-child\":\n\t\t\t\t\t\tif (!targetDocument) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t\"attempting to move a document to the left-child of a document that doesn't exist\",\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstate.documents[targetDocumentId]!.children_documents.push(document.offline_id)\n\t\t\t\t\t\tstate.documents[documentId]!.parent_document = targetDocument.offline_id\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tstate.documents[documentId]!.parent_document = null\n\t\t\t}\n\t\t},\n\t\tremoveDocuments: (state, action: { payload: string[] }) => {\n\t\t\tfor (const documentId of action.payload) {\n\t\t\t\tif (!(documentId in state.documents)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`attempting to delete a document with offline_id ${documentId} which doesn't exists in state.documents.`,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (const documentId of action.payload) {\n\t\t\t\tconst document = state.documents[documentId]!\n\t\t\t\tif (document.parent_document && !!state.documents[document.parent_document]) {\n\t\t\t\t\tconst parentDocument = state.documents[document.parent_document]!\n\t\t\t\t\tstate.documents[document.parent_document] = {\n\t\t\t\t\t\t...parentDocument,\n\t\t\t\t\t\tchildren_documents: parentDocument.children_documents.filter(\n\t\t\t\t\t\t\t(offline_id) => offline_id !== document.offline_id,\n\t\t\t\t\t\t),\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdelete state.documents[documentId]\n\t\t\t}\n\t\t},\n\t},\n})\n\nexport const { setDocuments, addDocuments, updateDocuments, moveDocument, removeDocuments } = documentSlice.actions\n\nexport const selectDocumentsMapping: OvermapSelector<Record<string, Stored<Document>>> = (state: OvermapRootState) =>\n\tstate.documentsReducer.documents\n\nexport const selectDocuments: OvermapSelector<Stored<Document>[]> = createSelector(\n\t[selectDocumentsMapping],\n\t(mapping) => Object.values(mapping),\n)\n\nexport const selectDocumentById: OvermapSelectorWithArgs<string, Stored<Document> | undefined> =\n\t(documentId: Document[\"offline_id\"]) => (state) => {\n\t\treturn state.documentsReducer.documents[documentId]\n\t}\n\nexport const selectDocumentsByIds = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectDocumentsMapping, (_state, documentIds: Document[\"offline_id\"][]) => documentIds],\n\t\t(mapping, documentIds) => {\n\t\t\tconst documents: Stored<Document>[] = []\n\n\t\t\tfor (const documentId of documentIds) {\n\t\t\t\tconst document = mapping[documentId]\n\t\t\t\tif (document) {\n\t\t\t\t\tdocuments.push(document)\n\t\t\t\t} else {\n\t\t\t\t\tconsole.warn(\"selectDocumentByIds: No document exists with the id\", documentId)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn documents\n\t\t},\n\t),\n)\n\nexport const selectAncestorIdsOfDocument = restructureCreateSelectorWithArgs(\n\tcreateSelector([selectDocumentsMapping, (_state, documentId: string) => documentId], (mapping, documentId) => {\n\t\tconst listOfAncestors: string[] = []\n\t\tconst document = mapping[documentId]\n\t\tif (!document || !document.parent_document) return listOfAncestors\n\n\t\tlet currentAncestor = mapping[document.parent_document]\n\n\t\twhile (currentAncestor) {\n\t\t\tlistOfAncestors.push(currentAncestor.offline_id)\n\t\t\tcurrentAncestor = mapping[currentAncestor.parent_document ?? \"\"]\n\t\t}\n\t\treturn listOfAncestors\n\t}),\n)\n\nexport const selectRootDocuments = createSelector([selectDocuments], (documents) =>\n\tdocuments.filter((document) => !document.parent_document),\n)\n\nexport const documentsReducer: Reducer<DocumentState> = documentSlice.reducer\n","import { createSlice, createSelector, Reducer } from \"@reduxjs/toolkit\"\nimport { ModelState } from \"../typings\"\nimport { DocumentAttachment, OvermapRootState, OvermapSelector, OvermapSelectorWithArgs, Stored } from \"../../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport type DocumentAttachmentState = ModelState<Stored<DocumentAttachment>>\n\nconst documentAttachmentAdapter = createModelAdapter<Stored<DocumentAttachment>>((attachment) => attachment.offline_id)\n\nconst initialState = documentAttachmentAdapter.getInitialState({})\n\nexport const documentAttachmentSlice = createSlice({\n\tname: \"documentAttachments\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeDocumentAttachments: documentAttachmentAdapter.initialize,\n\t\taddDocumentAttachment: documentAttachmentAdapter.addOne,\n\t\taddDocumentAttachments: documentAttachmentAdapter.addMany,\n\t\tsetDocumentAttachment: documentAttachmentAdapter.setOne,\n\t\tsetDocumentAttachments: documentAttachmentAdapter.setMany,\n\t\tupdateDocumentAttachment: documentAttachmentAdapter.updateOne,\n\t\tupdateDocumentAttachments: documentAttachmentAdapter.updateMany,\n\t\tdeleteDocumentAttachment: documentAttachmentAdapter.deleteOne,\n\t\tdeleteDocumentAttachments: documentAttachmentAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tinitializeDocumentAttachments,\n\taddDocumentAttachment,\n\taddDocumentAttachments,\n\tsetDocumentAttachment,\n\tsetDocumentAttachments,\n\tupdateDocumentAttachment,\n\tupdateDocumentAttachments,\n\tdeleteDocumentAttachment,\n\tdeleteDocumentAttachments,\n} = documentAttachmentSlice.actions\n\nexport const selectDocumentAttachmentMapping = (state: OvermapRootState) => state.documentAttachmentReducer.instances\n\nexport const selectAllDocumentAttachments: OvermapSelector<Stored<DocumentAttachment>[]> = createSelector(\n\t[selectDocumentAttachmentMapping],\n\t(mapping) => Object.values(mapping),\n)\n\nexport const selectDocumentAttachment: OvermapSelectorWithArgs<string, Stored<DocumentAttachment> | undefined> =\n\t(attachmentId: string) => (state: OvermapRootState) => {\n\t\treturn state.documentAttachmentReducer.instances[attachmentId]\n\t}\n\nexport const selectAttachmentsOfDocument = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectAllDocumentAttachments, (_state: OvermapRootState, documentId: string) => documentId],\n\t\t(attachments, documentId) => {\n\t\t\treturn attachments.filter(({ document }) => documentId === document)\n\t\t},\n\t),\n)\n\nexport const selectAttachmentsOfDocumentByType = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectAllDocumentAttachments, (_state: OvermapRootState, documentId: string) => documentId],\n\t\t(attachments, documentId) => {\n\t\t\tconst attachmentsOfProject = attachments.filter(({ document }) => documentId === document)\n\t\t\tconst fileAttachments = attachmentsOfProject.filter(\n\t\t\t\t// this null check here is necessary, there are cases where file_type is null or undefined\n\t\t\t\t({ file_type }) => !file_type || !file_type.startsWith(\"image/\"),\n\t\t\t)\n\t\t\tconst imageAttachments = attachmentsOfProject.filter(\n\t\t\t\t// this null check here is necessary, there are cases where file_type is null or undefined\n\t\t\t\t({ file_type }) => file_type && file_type.startsWith(\"image/\"),\n\t\t\t)\n\t\t\treturn { fileAttachments, imageAttachments }\n\t\t},\n\t),\n)\n\nexport const documentAttachmentReducer: Reducer<DocumentAttachmentState> = documentAttachmentSlice.reducer\n","import { createSlice, Reducer, createSelector } from \"@reduxjs/toolkit\"\nimport {\n\tTeam,\n\tOvermapRootState,\n\tStored,\n\tOvermapSelector,\n\tOvermapSelectorWithArgs,\n\tOrganization,\n\tUser,\n} from \"../../typings\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\n\nexport type TeamState = ModelState<Stored<Team>>\n\nconst teamAdapter = createModelAdapter<Stored<Team>>((team) => team.offline_id)\n\nconst initialState: TeamState = teamAdapter.getInitialState({})\n\nexport const teamSlice = createSlice({\n\tname: \"teams\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tsetTeam: teamAdapter.setOne,\n\t\tinitializeTeams: teamAdapter.initialize,\n\t\taddTeam: teamAdapter.addOne,\n\t\tupdateTeam: teamAdapter.updateOne,\n\t\tdeleteTeam: teamAdapter.deleteOne,\n\t},\n})\n\nexport const { setTeam, initializeTeams, addTeam, updateTeam, deleteTeam } = teamSlice.actions\n\nexport const selectTeamsMapping: OvermapSelector<TeamState[\"instances\"]> = (state: OvermapRootState) =>\n\tstate.teamReducer.instances\n\nexport const selectTeams: OvermapSelector<Stored<Team>[]> = createSelector([selectTeamsMapping], (teams) => {\n\treturn Object.values(teams)\n})\n\nexport const selectTeamById: OvermapSelectorWithArgs<string, Stored<Team> | undefined> = (id) => (state) => {\n\treturn state.teamReducer.instances[id]\n}\n\nexport const selectTeamsOfOrganization: OvermapSelectorWithArgs<Organization[\"id\"], Stored<Team>[]> =\n\trestructureCreateSelectorWithArgs(\n\t\tcreateSelector(\n\t\t\t[selectTeams, (_state: OvermapRootState, organizationId: Organization[\"id\"]) => organizationId],\n\t\t\t(teams, organizationId) => {\n\t\t\t\treturn teams.filter((team) => team.organization === organizationId)\n\t\t\t},\n\t\t),\n\t)\n\nexport const selectTeamsOfUser: OvermapSelectorWithArgs<User[\"id\"], Stored<Team>[]> = restructureCreateSelectorWithArgs(\n\tcreateSelector([selectTeams, (_state: OvermapRootState, userId: User[\"id\"]) => userId], (teams, userId) => {\n\t\treturn teams.filter((team) => team.members.includes(userId))\n\t}),\n)\n\nexport const teamReducer: Reducer<TeamState> = teamSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport { AgentUserConversation, OvermapRootState, OvermapSelector } from \"../../typings\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\n\nexport type AgentsState = ModelState<AgentUserConversation>\n\nconst agentUserConversationAdapter = createModelAdapter<AgentUserConversation>(\n\t(conversation) => conversation.offline_id,\n)\n\nconst initialState = agentUserConversationAdapter.getInitialState({})\n\nexport const agentsSlice = createSlice({\n\tname: \"agents\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeConversations: agentUserConversationAdapter.initialize,\n\t\taddConversation: agentUserConversationAdapter.addOne,\n\t\tsetConversation: agentUserConversationAdapter.setOne,\n\t\tupdateConversation: agentUserConversationAdapter.updateOne,\n\t},\n})\n\nexport const { initializeConversations, addConversation, setConversation, updateConversation } = agentsSlice.actions\nexport const selectConversationMapping = (state: OvermapRootState) => state.agentsReducer.instances\n\nexport const selectConversations: OvermapSelector<AgentUserConversation[]> = createSelector(\n\t[selectConversationMapping],\n\t(conversationMapping) => Object.values(conversationMapping),\n)\n\nexport const selectConversation = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectConversationMapping, (_state, conversationId: string) => conversationId],\n\t\t(conversationMapping, conversationId) => conversationMapping[conversationId],\n\t),\n)\n\nexport const agentsReducer: Reducer<AgentsState> = agentsSlice.reducer\n","import { createSlice, Reducer, createSelector } from \"@reduxjs/toolkit\"\nimport { ModelState } from \"../typings\"\nimport { IssueComment, OvermapRootState, Stored } from \"../../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport type IssueCommentState = ModelState<Stored<IssueComment>>\n\nconst issueCommentAdapter = createModelAdapter<Stored<IssueComment>>((comment) => comment.offline_id)\n\nconst initialState: IssueCommentState = issueCommentAdapter.getInitialState({})\n\nexport const issueCommentSlice = createSlice({\n\tname: \"issueComments\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\taddIssueComment: issueCommentAdapter.addOne,\n\t\taddIssueComments: issueCommentAdapter.addMany,\n\t\tsetIssueComment: issueCommentAdapter.setOne,\n\t\tsetIssueComments: issueCommentAdapter.setMany,\n\t\tdeleteIssueComment: issueCommentAdapter.deleteOne,\n\t\tdeleteIssueComments: issueCommentAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tsetIssueComments,\n\tsetIssueComment,\n\taddIssueComment,\n\taddIssueComments,\n\tdeleteIssueComment,\n\tdeleteIssueComments,\n} = issueCommentSlice.actions\n\nexport const selectIssueCommentMapping = (state: OvermapRootState) => state.issueCommentReducer.instances\n\nexport const selectCommentsOfIssue = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectIssueCommentMapping, (_state, issueId: string) => issueId],\n\t\t(commentMapping, issueId: string) => {\n\t\t\treturn Object.values(commentMapping).filter((comment) => comment.issue === issueId)\n\t\t},\n\t),\n)\n\nexport const issueCommentReducer: Reducer<IssueCommentState> = issueCommentSlice.reducer\n","import { createSlice, Reducer, createSelector } from \"@reduxjs/toolkit\"\nimport { IssueUpdate, OvermapRootState, Stored } from \"../../typings\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport type IssueUpdateState = ModelState<Stored<IssueUpdate>>\n\nconst issueUpdateAdapter = createModelAdapter<Stored<IssueUpdate>>((issueUpdate) => issueUpdate.offline_id)\n\nconst initialState: IssueUpdateState = issueUpdateAdapter.getInitialState({})\n\nexport const issueUpdateSlice = createSlice({\n\tname: \"issueUpdates\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeIssueUpdates: issueUpdateAdapter.setMany,\n\t\tsetIssueUpdate: issueUpdateAdapter.setOne,\n\t\taddIssueUpdate: issueUpdateAdapter.addOne,\n\t\taddIssueUpdates: issueUpdateAdapter.addMany,\n\t\tdeleteIssueUpdate: issueUpdateAdapter.deleteOne,\n\t\tdeleteIssueUpdates: issueUpdateAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tinitializeIssueUpdates,\n\tsetIssueUpdate,\n\taddIssueUpdate,\n\taddIssueUpdates,\n\tdeleteIssueUpdate,\n\tdeleteIssueUpdates,\n} = issueUpdateSlice.actions\n\nexport const selectIssueUpdateMapping = (state: OvermapRootState) => state.issueUpdateReducer.instances\n\nexport const selectIssueUpdatesOfIssue = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectIssueUpdateMapping, (_state: OvermapRootState, issueId: string) => issueId],\n\t\t(updates, issueId) => {\n\t\t\treturn Object.values(updates).filter((update) => update.issue === issueId)\n\t\t},\n\t),\n)\n\nexport const issueUpdateReducer: Reducer<IssueUpdateState> = issueUpdateSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport { IssueAttachment, OvermapRootState, OvermapSelector, OvermapSelectorWithArgs, Stored } from \"../../typings\"\nimport { ModelState } from \"../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport type IssueAttachmentState = ModelState<Stored<IssueAttachment>>\n\nconst issueAttachmentAdapter = createModelAdapter<Stored<IssueAttachment>>((attachment) => attachment.offline_id)\n\nconst initialState: IssueAttachmentState = issueAttachmentAdapter.getInitialState({})\n\nexport const issueAttachmentSlice = createSlice({\n\tname: \"issueAttachments\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeIssueAttachments: issueAttachmentAdapter.initialize,\n\t\taddIssueAttachment: issueAttachmentAdapter.addOne,\n\t\taddIssueAttachments: issueAttachmentAdapter.addMany,\n\t\tsetIssueAttachment: issueAttachmentAdapter.setOne,\n\t\tsetIssueAttachments: issueAttachmentAdapter.setMany,\n\t\tupdateIssueAttachment: issueAttachmentAdapter.updateOne,\n\t\tupdateIssueAttachments: issueAttachmentAdapter.updateMany,\n\t\tdeleteIssueAttachment: issueAttachmentAdapter.deleteOne,\n\t\tdeleteIssueAttachments: issueAttachmentAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tinitializeIssueAttachments,\n\taddIssueAttachment,\n\taddIssueAttachments,\n\tsetIssueAttachment,\n\tsetIssueAttachments,\n\tupdateIssueAttachment,\n\tupdateIssueAttachments,\n\tdeleteIssueAttachment,\n\tdeleteIssueAttachments,\n} = issueAttachmentSlice.actions\n\nexport const selectIssueAttachmentMapping = (state: OvermapRootState) => state.issueAttachmentReducer.instances\nexport const selectIssueAttachments: OvermapSelector<Stored<IssueAttachment>[]> = createSelector(\n\t[selectIssueAttachmentMapping],\n\t(mapping) => Object.values(mapping),\n)\n\nexport const selectAttachmentsOfIssue = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectIssueAttachments, (_state: OvermapRootState, issueId: string) => issueId],\n\t\t(attachments, issueId) => {\n\t\t\treturn attachments.filter(({ issue }) => issueId === issue)\n\t\t},\n\t),\n)\n\nexport const selectIssueAttachmentById: OvermapSelectorWithArgs<string, Stored<IssueAttachment> | undefined> =\n\t(id: string) => (root: OvermapRootState) => {\n\t\treturn root.issueAttachmentReducer.instances[id]\n\t}\n\nexport const selectAttachmentsOfIssueByType = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectIssueAttachments, (_state: OvermapRootState, issueId: string) => issueId],\n\t\t(attachments, issueId) => {\n\t\t\tconst attachmentsOfIssue = attachments.filter(({ issue }) => issue === issueId)\n\t\t\tconst fileAttachments = attachmentsOfIssue.filter(\n\t\t\t\t// this null check here is necessary, there are cases where file_type is null or undefined\n\t\t\t\t({ file_type }) => !file_type || !file_type.startsWith(\"image/\"),\n\t\t\t)\n\t\t\tconst imageAttachments = attachmentsOfIssue.filter(\n\t\t\t\t// this null check here is necessary, there are cases where file_type is null or undefined\n\t\t\t\t({ file_type }) => file_type && file_type.startsWith(\"image/\"),\n\t\t\t)\n\t\t\treturn { fileAttachments, imageAttachments }\n\t\t},\n\t),\n)\n\nexport const issueAttachmentReducer: Reducer<IssueAttachmentState> = issueAttachmentSlice.reducer\n","import { createSlice, Reducer } from \"@reduxjs/toolkit\"\n\nexport interface VersioningState {\n\tversion: number\n}\n\nconst initialState: VersioningState = {\n\tversion: 0,\n}\n\n/**\n * Version of the offline redux store\n */\nexport const versioningSlice = createSlice({\n\tname: \"versioning\",\n\tinitialState,\n\treducers: {},\n})\n\nexport const versioningReducer: Reducer<VersioningState> = versioningSlice.reducer\n","import { createSlice, Reducer, createSelector } from \"@reduxjs/toolkit\"\nimport { GeoImage, OvermapRootState, Stored } from \"../../typings\"\nimport { createModelAdapter } from \"../adapter\"\nimport { ModelState } from \"../typings\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\n\nexport type GeoImageSliceState = ModelState<Stored<GeoImage>>\n\nconst geoImageAdapter = createModelAdapter<GeoImage>((model) => model.offline_id)\n\nconst initialState: GeoImageSliceState = geoImageAdapter.getInitialState({})\n\nexport const geoImageSlice = createSlice({\n\tname: \"geoImages\",\n\tinitialState,\n\textraReducers: (builder) => {\n\t\tbuilder.addCase(\"RESET\", (state) => {\n\t\t\tObject.assign(state, initialState)\n\t\t})\n\t},\n\treducers: {\n\t\tinitializeGeoImages: geoImageAdapter.initialize,\n\t\tsetGeoImage: geoImageAdapter.setOne,\n\t\tsetGeoImages: geoImageAdapter.setMany,\n\t\taddGeoImage: geoImageAdapter.addOne,\n\t\taddGeoImages: geoImageAdapter.addMany,\n\t\tupdateGeoImage: geoImageAdapter.updateOne,\n\t\tupdateGeoImages: geoImageAdapter.updateMany,\n\t\tdeleteGeoImage: geoImageAdapter.deleteOne,\n\t\tdeleteGeoImages: geoImageAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tinitializeGeoImages,\n\tsetGeoImage,\n\tsetGeoImages,\n\taddGeoImage,\n\taddGeoImages,\n\tupdateGeoImage,\n\tupdateGeoImages,\n\tdeleteGeoImage,\n\tdeleteGeoImages,\n} = geoImageSlice.actions\n\nexport const selectGeoImageMapping = (state: OvermapRootState) => state.geoImageReducer.instances\n\nexport const selectGeoImages = (state: OvermapRootState) => Object.values(state.geoImageReducer.instances)\n\nexport const selectGeoImageById = (id: string) => (state: OvermapRootState) => {\n\treturn state.geoImageReducer.instances[id]\n}\n\nexport const selectGeoImagesOfProject = restructureCreateSelectorWithArgs(\n\tcreateSelector([selectGeoImages, (_, projectId: number) => projectId], (mapImages, projectId) => {\n\t\treturn mapImages.filter((mapImage) => mapImage.project === projectId)\n\t}),\n)\n\nexport const geoImageReducer: Reducer<GeoImageSliceState> = geoImageSlice.reducer\n","import { createSelector, createSlice, Reducer } from \"@reduxjs/toolkit\"\nimport type { IssueAssociation, OvermapRootState, OvermapSelectorWithArgs, Stored } from \"../../typings\"\nimport { restructureCreateSelectorWithArgs } from \"../../utils\"\nimport { createModelAdapter } from \"../adapter\"\nimport type { ModelState } from \"../typings\"\n\nexport type IssueAssociationSliceState = ModelState<Stored<IssueAssociation>>\n\nconst issueAssociationAdapter = createModelAdapter<Stored<IssueAssociation>>((assoc) => assoc.offline_id)\n\nconst initialState: IssueAssociationSliceState = issueAssociationAdapter.getInitialState({})\n\nexport const issueAssociationSlice = createSlice({\n\tname: \"issueAssociations\",\n\tinitialState,\n\textraReducers: (builder) => builder.addCase(\"RESET\", (state) => Object.assign(state, initialState)),\n\treducers: {\n\t\tinitializeIssueAssociations: issueAssociationAdapter.initialize,\n\t\taddIssueAssociation: issueAssociationAdapter.addOne,\n\t\taddIssueAssociations: issueAssociationAdapter.addMany,\n\t\tsetIssueAssociation: issueAssociationAdapter.setOne,\n\t\tsetIssueAssociations: issueAssociationAdapter.setMany,\n\t\tupdateIssueAssociation: issueAssociationAdapter.updateOne,\n\t\tupdateIssueAssociations: issueAssociationAdapter.updateMany,\n\t\tdeleteIssueAssociation: issueAssociationAdapter.deleteOne,\n\t\tdeleteIssueAssociations: issueAssociationAdapter.deleteMany,\n\t},\n})\n\nexport const {\n\tinitializeIssueAssociations,\n\tsetIssueAssociations,\n\tsetIssueAssociation,\n\tupdateIssueAssociation,\n\tupdateIssueAssociations,\n\taddIssueAssociation,\n\taddIssueAssociations,\n\tdeleteIssueAssociation,\n\tdeleteIssueAssociations,\n} = issueAssociationSlice.actions\n\nexport const selectIssueAssociationMapping = (state: OvermapRootState): Record<string, Stored<IssueAssociation>> =>\n\tstate.issueAssociationReducer.instances\n\nexport const selectIssueAssociations = createSelector([selectIssueAssociationMapping], (associations) => {\n\treturn Object.values(associations)\n})\n\nexport const selectIssueAssociationById: OvermapSelectorWithArgs<string, Stored<IssueAssociation> | undefined> =\n\t(id) => (state) => {\n\t\treturn state.issueAssociationReducer.instances[id]\n\t}\n\nexport const selectIssueAssociationsToIssue = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectIssueAssociationMapping, (_state, issueId: string) => issueId],\n\t\t(associationMapping, issueId) => {\n\t\t\treturn Object.values(associationMapping).filter((assoc) => assoc.associated_issue === issueId)\n\t\t},\n\t),\n)\n\nexport const selectIssueAssociationsOfIssue = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectIssueAssociationMapping, (_state, issueId: string) => issueId],\n\t\t(associationMapping, issueId) => {\n\t\t\treturn Object.values(associationMapping).filter((assoc) => assoc.issue === issueId)\n\t\t},\n\t),\n)\n\nexport const selectIssueAssociationsOfAsset = restructureCreateSelectorWithArgs(\n\tcreateSelector(\n\t\t[selectIssueAssociationMapping, (_state, assetId: string) => assetId],\n\t\t(associationMapping, assetId) => {\n\t\t\treturn Object.values(associationMapping).filter((assoc) => assoc.asset === assetId)\n\t\t},\n\t),\n)\n\nexport const issueAssociationReducer: Reducer<IssueAssociationSliceState> = issueAssociationSlice.reducer\n","// NOTE: Also update $full-asset-marker-size in src/theme/_variables.sass\nexport const fullAssetMarkerSize = 45 // px\n","import { IssuePriority, IssueStatus } from \"../enums\"\n\nexport const DEFAULT_ISSUE_STATUS = IssueStatus.BACKLOG\nexport const DEFAULT_ISSUE_PRIORITY = IssuePriority.MEDIUM\n","export const OUTBOX_RETRY_DELAY = 5000 // milliseconds\n","import { ToolkitStore } from \"@reduxjs/toolkit/dist/configureStore\"\nimport { BaseState } from \"../typings\"\nimport { BaseSDK } from \"./base\"\n\n/** The client store is the store passed to the SDKProvider\n * and is used where the SDKProvider is not available.\n */\nlet clientStore: ToolkitStore<BaseState> | undefined\n\nexport function setClientStore<TState extends BaseState>(store: ToolkitStore<TState>) {\n\tclientStore = store\n}\n\nexport function getClientStore(): ToolkitStore<BaseState> | undefined {\n\treturn clientStore\n}\n\nlet clientSDK: BaseSDK<BaseState> | undefined\n\nexport function setClientSDK<TState extends BaseState>(sdkCtor: BaseSDK<TState>) {\n\tclientSDK = sdkCtor\n}\n\nexport function getClientSDK(): BaseSDK<BaseState> | undefined {\n\treturn clientSDK\n}\n","import { AnyAction } from \"@reduxjs/toolkit\"\nimport type { BaseSDK } from \"../base\"\nimport { BaseState } from \"../../typings\"\nimport { SDKRequest } from \"../typings\"\n\nexport const CLASS_NAME_TO_SERVICE: Record<string, BaseService<BaseState, BaseSDK<BaseState>>> = {}\n\n/**\n * Abstract base class for building a service that can enqueue API requests\n */\nexport abstract class BaseService<TStore extends BaseState, TSDK extends BaseSDK<TStore>> {\n\tprotected readonly client: TSDK\n\tabstract readonly host: string\n\n\tprotected constructor(sdk: TSDK) {\n\t\tCLASS_NAME_TO_SERVICE[this.constructor.name] = this\n\t\tthis.client = sdk\n\t}\n\n\tprotected async enqueueRequest<TResult>(requestDetails: SDKRequest): Promise<TResult> {\n\t\t// enqueueRequest is a wrapper for _enqueueRequest that ensures the result is not an APIError unless\n\t\t// `.catch()` is triggered.\n\t\treturn this.client.enqueueRequest(requestDetails, this.host, this.constructor.name)\n\t}\n\n\tprotected dispatch(action: AnyAction) {\n\t\tthis.client.store.dispatch(action)\n\t}\n}\n","import { AnyAction, compose, Reducer } from \"redux\"\nimport { offline } from \"@redux-offline/redux-offline\"\nimport offlineConfig from \"@redux-offline/redux-offline/lib/defaults\"\nimport localforage from \"localforage\"\n\n// TODO: Fix\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-expect-error\nimport createMigration from \"redux-persist-migrate\"\n\nimport { combineReducers, createNextState } from \"@reduxjs/toolkit\"\nimport {\n\tConfig,\n\tOfflineAction,\n\tOfflineMetadata,\n\tOfflineState,\n\tResultAction,\n} from \"@redux-offline/redux-offline/lib/types\"\nimport request from \"superagent\"\nimport { HttpMethod } from \"../enums\"\nimport { manifest } from \"./migrations\"\n\n// There are two \"blobs\": The Blob type from the \"buffer\" package (part of node),\n// and the Blob type from the browser. For some reason, superagent uses the \"buffer\"\n// version after moving code from hemora-web to overmap-core. This overwrites the name\n// \"Blob\". There are minor differences between the two interfaces (remove the type casting\n// of the `file` argument to `req.field()` in performRequest() to see the error), but it's\n// unlikely that we'll run into any problems.\nimport { Blob } from \"buffer\"\nimport {\n\tAPIError,\n\tBaseApiService,\n\ttype BaseSDK,\n\ttype OfflineMetaEffect,\n\tOutboxCoordinator,\n\tRequestDetails,\n} from \"../sdk\"\nimport { ToastProps, unsafeShowToast } from \"@overmap-ai/blocks\"\nimport {\n\t_setLatestRetryTime,\n\tagentsReducer,\n\tAgentsState,\n\tassetAttachmentReducer,\n\tAssetAttachmentState,\n\tassetReducer,\n\tassetStageCompletionReducer,\n\tAssetStageCompletionState,\n\tassetStageReducer,\n\tAssetStageState,\n\tAssetState,\n\tassetTypeAttachmentReducer,\n\tAssetTypeAttachmentState,\n\tassetTypeReducer,\n\tAssetTypeState,\n\tauthReducer,\n\tAuthState,\n\tcategoryReducer,\n\tCategoryState,\n\tdocumentAttachmentReducer,\n\tDocumentAttachmentState,\n\tdocumentsReducer,\n\tDocumentState,\n\temailDomainsReducer,\n\tEmailDomainState,\n\tfileReducer,\n\tFileState,\n\tformReducer,\n\tformRevisionAttachmentReducer,\n\tFormRevisionAttachmentState,\n\tformRevisionReducer,\n\tFormRevisionState,\n\tFormState,\n\tformSubmissionAttachmentReducer,\n\tFormSubmissionAttachmentState,\n\tformSubmissionReducer,\n\tFormSubmissionState,\n\tgeoImageReducer,\n\tGeoImageSliceState,\n\tissueAssociationReducer,\n\tIssueAssociationSliceState,\n\tissueAttachmentReducer,\n\tIssueAttachmentState,\n\tissueCommentReducer,\n\tIssueCommentState,\n\tissueReducer,\n\tIssueState,\n\tissueTypeReducer,\n\tIssueTypeState,\n\tissueUpdateReducer,\n\tIssueUpdateState,\n\tlicenseReducer,\n\tLicenseState,\n\tmarkAsDeleted,\n\torganizationAccessReducer,\n\tOrganizationAccessState,\n\torganizationReducer,\n\tOrganizationState,\n\toutboxReducer,\n\tOutboxState,\n\tprojectAccessReducer,\n\tProjectAccessState,\n\tprojectAttachmentReducer,\n\tProjectAttachmentState,\n\tprojectFileReducer,\n\tProjectFileState,\n\tprojectReducer,\n\tProjectState,\n\trehydratedReducer,\n\tRehydratedState,\n\tselectCategoriesOfWorkspace,\n\tselectMainWorkspace,\n\tteamReducer,\n\tTeamState,\n\tuserReducer,\n\tUserState,\n\tversioningReducer,\n\tVersioningState,\n\tworkspaceReducer,\n\tWorkspaceState,\n} from \"./slices\"\nimport { OUTBOX_RETRY_DELAY } from \"../constants\"\nimport type { BaseState, OvermapRootState } from \"../typings\"\nimport { getClientSDK, getClientStore } from \"../sdk/globals\"\nimport { CLASS_NAME_TO_SERVICE } from \"../sdk/services/BaseService\"\n\n// NOTE: If changing, also change it in migrations.ts (avoid circular imports)\nexport const VERSION_REDUCER_KEY = \"versioning\"\n\nexport const overmapReducers = {\n\t// TODO: attachmentReducer,\n\t[VERSION_REDUCER_KEY]: versioningReducer,\n\tfileReducer,\n\tauthReducer,\n\tcategoryReducer,\n\tassetReducer,\n\tassetAttachmentReducer,\n\tassetStageCompletionReducer,\n\tassetStageReducer,\n\tassetTypeReducer,\n\tassetTypeAttachmentReducer,\n\tissueReducer,\n\tissueAttachmentReducer,\n\tissueTypeReducer,\n\torganizationReducer,\n\toutboxReducer,\n\tprojectReducer,\n\tprojectAttachmentReducer,\n\tprojectAccessReducer,\n\torganizationAccessReducer,\n\tprojectFileReducer,\n\trehydratedReducer,\n\tformReducer,\n\tformRevisionReducer,\n\tformRevisionAttachmentReducer,\n\tformSubmissionAttachmentReducer,\n\tformSubmissionReducer,\n\tuserReducer,\n\tworkspaceReducer,\n\temailDomainsReducer,\n\tlicenseReducer,\n\tdocumentsReducer,\n\tdocumentAttachmentReducer,\n\tteamReducer,\n\tagentsReducer,\n\tissueCommentReducer,\n\tissueUpdateReducer,\n\tgeoImageReducer,\n\tissueAssociationReducer,\n} as {\n\tversioning: Reducer<VersioningState>\n\tfileReducer: Reducer<FileState>\n\tauthReducer: Reducer<AuthState>\n\tcategoryReducer: Reducer<CategoryState>\n\tassetReducer: Reducer<AssetState>\n\tassetAttachmentReducer: Reducer<AssetAttachmentState>\n\tassetStageCompletionReducer: Reducer<AssetStageCompletionState>\n\tassetStageReducer: Reducer<AssetStageState>\n\tassetTypeReducer: Reducer<AssetTypeState>\n\tassetTypeAttachmentReducer: Reducer<AssetTypeAttachmentState>\n\tissueReducer: Reducer<IssueState>\n\tissueTypeReducer: Reducer<IssueTypeState>\n\torganizationReducer: Reducer<OrganizationState>\n\toutboxReducer: Reducer<OutboxState>\n\tprojectReducer: Reducer<ProjectState>\n\tprojectAttachmentReducer: Reducer<ProjectAttachmentState>\n\tprojectAccessReducer: Reducer<ProjectAccessState>\n\torganizationAccessReducer: Reducer<OrganizationAccessState>\n\tprojectFileReducer: Reducer<ProjectFileState>\n\trehydratedReducer: Reducer<RehydratedState>\n\tformReducer: Reducer<FormState>\n\tuserReducer: Reducer<UserState>\n\tformRevisionReducer: Reducer<FormRevisionState>\n\tformRevisionAttachmentReducer: Reducer<FormRevisionAttachmentState>\n\tformSubmissionAttachmentReducer: Reducer<FormSubmissionAttachmentState>\n\tformSubmissionReducer: Reducer<FormSubmissionState>\n\tworkspaceReducer: Reducer<WorkspaceState>\n\temailDomainsReducer: Reducer<EmailDomainState>\n\tlicenseReducer: Reducer<LicenseState>\n\tdocumentsReducer: Reducer<DocumentState>\n\tdocumentAttachmentReducer: Reducer<DocumentAttachmentState>\n\tteamReducer: Reducer<TeamState>\n\tagentsReducer: Reducer<AgentsState>\n\tissueCommentReducer: Reducer<IssueCommentState>\n\tissueUpdateReducer: Reducer<IssueUpdateState>\n\tissueAttachmentReducer: Reducer<IssueAttachmentState>\n\tgeoImageReducer: Reducer<GeoImageSliceState>\n\tissueAssociationReducer: Reducer<IssueAssociationSliceState>\n}\n\nconst overmapReducer = combineReducers(overmapReducers)\n\n// Special action to revert all slices to their initial state. A reducer for this is added to each slice using\n// `extraReducers` in the slice definition.\nexport const resetStore = \"RESET\"\n\nfunction handleWorkspaceRemoval(draft: OvermapRootState, action: AnyAction): void {\n\tconst workspaceId = (action as AnyAction & { payload: string }).payload\n\tconst issuesVisibleInWorkspace = Object.values(draft.issueReducer.instances).filter((issue) =>\n\t\tissue.visible_in_workspaces.includes(workspaceId),\n\t)\n\n\tconst mainWorkspace = selectMainWorkspace(draft)\n\tif (!mainWorkspace) {\n\t\tthrow new Error(\"Main workspace not found\")\n\t}\n\tif (action.payload === mainWorkspace.offline_id) {\n\t\tthrow new Error(\"Tried to delete main workspace\")\n\t}\n\n\t// Find categories about to be deleted. If the issue has this category, we will have to remove it.\n\tconst categoriesInThisWorkspace = new Set<string>(\n\t\tselectCategoriesOfWorkspace(workspaceId)(draft).map((category) => category.offline_id),\n\t)\n\tfor (const issue of issuesVisibleInWorkspace) {\n\t\tif (issue.category && categoriesInThisWorkspace.has(issue.category)) {\n\t\t\tissue.category = null\n\t\t}\n\t}\n\n\t// If the deleted workspace was the index_workspace, we need to update the index_workspace to be the\n\t// main workspace.\n\t// NOTE: Issues are always visible in the index_workspace, so we can expect to find the index_workspace\n\t// in visible_in_workspaces.\n\tconst issuesWithThisWorkspaceIndex = issuesVisibleInWorkspace.filter(\n\t\t(issue) => issue.index_workspace === action.payload,\n\t)\n\n\tfor (const issue of issuesWithThisWorkspaceIndex) {\n\t\t// NOTE: Indexes of WorkspaceIndexedModels are updated after a reload in the workspace service. For now,\n\t\t// we'll just update the index_workspace of indexed models (currently issues and forms).\n\t\tissue.index_workspace = mainWorkspace.offline_id\n\t\tif (!issue.visible_in_workspaces.includes(mainWorkspace.offline_id)) {\n\t\t\tissue.visible_in_workspaces.push(mainWorkspace.offline_id)\n\t\t}\n\t}\n\n\t// Remove the workspace from the visible_in_workspaces of all issues\n\tfor (const issue of issuesVisibleInWorkspace) {\n\t\tconst indexOfWorkspace = issue.visible_in_workspaces.indexOf(workspaceId)\n\t\tif (indexOfWorkspace === -1) {\n\t\t\t// This is unexpected because we already filtered by visible_in_workspaces.\n\t\t\tthrow new Error(\"Workspace not found in issue's visible_in_workspaces\")\n\t\t}\n\t\tissue.visible_in_workspaces.splice(indexOfWorkspace, 1)\n\t}\n\n\t// Lastly, some sanity checks to make sure we didn't miss anything.\n\tfor (const issue of issuesVisibleInWorkspace) {\n\t\tif (issue.visible_in_workspaces.length === 0) {\n\t\t\tthrow new Error(`Unexpected error: Issue ${issue.offline_id} has no visible_in_workspaces`)\n\t\t}\n\t\tif (issue.index_workspace === action.payload || !issue.index_workspace) {\n\t\t\tthrow new Error(`Failed to update index_workspace of issue ${issue.offline_id} to main workspace`)\n\t\t}\n\t}\n}\n\n// NOTE: Leaving this here for now until stories are removed from /core which requires a store to be set up.\n// not being used in /web\nexport const overmapRootReducer: Reducer<OvermapRootState> = (state, action): OvermapRootState => {\n\t// TODO: dont know if this is needed?\n\tif (action.type === \"auth/setLoggedIn\" && !action.payload) {\n\t\treturn overmapReducer(undefined, action) as OvermapRootState\n\t}\n\n\tlet mutatedState = state\n\n\tif (state && action.type === \"workspace/removeWorkspace\") {\n\t\tmutatedState = createNextState(state, (draft) => {\n\t\t\thandleWorkspaceRemoval(draft, action)\n\t\t})\n\t}\n\n\treturn overmapReducer(mutatedState, action) as OvermapRootState\n}\n\nexport interface FullOfflineMetadata extends OfflineMetadata {\n\teffect: OfflineMetaEffect\n}\n\nexport interface FullOfflineAction extends OfflineAction {\n\tmeta: { offline: FullOfflineMetadata }\n\t// Redundantly store request details in the unused `payload` property to make TypeScript happy\n\tpayload: RequestDetails\n}\n\nlet __OUTBOX_COORDINATOR: OutboxCoordinator | null = null\n\nexport function getOutboxCoordinator(): OutboxCoordinator | null {\n\tconst clientStore = getClientStore()\n\tif (!clientStore) {\n\t\tconsole.warn(\"Client store not set; cannot get outbox coordinator yet.\")\n\t\treturn null\n\t}\n\tif (__OUTBOX_COORDINATOR) {\n\t\treturn __OUTBOX_COORDINATOR\n\t}\n\tconst outbox = clientStore.getState().offline.outbox\n\tconst coordinator = OutboxCoordinator._fromOutbox(outbox)\n\t__OUTBOX_COORDINATOR = coordinator\n\treturn coordinator\n}\n\n// This callback is run when the Redux store has finished rehydrating itself from localForage\n// We signal to the rest of the app that hydration has finished\nconst persistCallback = (err: null | Error) => {\n\tif (err) throw err\n\tconst clientStore = getClientStore()\n\tif (clientStore) {\n\t\tclientStore.dispatch({ type: \"rehydrated/setRehydrated\", payload: true })\n\t} else {\n\t\tconsole.error(\"Client store not set\")\n\t}\n}\n\nexport const enqueue: Config[\"queue\"][\"enqueue\"] = (_array, item, _context) => {\n\tconst coordinator = getOutboxCoordinator()\n\tif (!coordinator) {\n\t\tconsole.warn(\"Outbox coordinator not set; cannot enqueue request yet.\")\n\t\treturn []\n\t}\n\tcoordinator.addRequest(item as FullOfflineAction)\n\treturn coordinator.getQueue()\n}\n\nexport const dequeue: Config[\"queue\"][\"dequeue\"] = (_array, item, _context) => {\n\tconst coordinator = getOutboxCoordinator()\n\tif (!coordinator) {\n\t\tconsole.warn(\"Outbox coordinator not set; cannot dequeue request yet.\")\n\t\treturn []\n\t}\n\t// The redux-offline type leaves out the \"offlineAction\" property\n\ttype BadMetaType = ResultAction[\"meta\"]\n\ttype CorrectedMetaType = BadMetaType & { offlineAction: FullOfflineAction }\n\tconst meta = item.meta as CorrectedMetaType\n\tconst uuid = meta.offlineAction.payload.uuid\n\tcoordinator.remove(uuid)\n\treturn coordinator.getQueue()\n}\n\n// This is called an \"effect reconciler\", and it turns an offline action into a real API request\nasync function effect(_effect: OfflineMetaEffect, action: FullOfflineAction) {\n\t// REASON: Handling of unexpected case\n\t// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n\tif (!action.payload) {\n\t\tthrow new Error(\"Received empty payload\")\n\t}\n\n\t// We pass the action through a chain of middleware, which can do some useful things and then perform the action.\n\t// `runMiddleware` returns a Promise<Response> if everything goes well.\n\treturn runMiddleware(action)\n}\n\nconst customConfig: Partial<Config> = {\n\t...offlineConfig,\n\teffect: effect as Config[\"effect\"],\n\t// Casting needed because we are saving FullOfflineAction objects, not just OfflineAction objects,\n\t// but redux-offline does not know this.\n\tdiscard: discard as Config[\"discard\"],\n\treturnPromises: true,\n\tpersistCallback,\n\tretry: retry as Config[\"retry\"],\n\t// Modify the configuration of the offline store to use localforage\n\t// which uses IndexedDB by default (persists even on mobile when installed as a PWA, unlike localStorage)\n\tpersistOptions: { storage: localforage },\n\t// TODO: custom enqueue implementation to take care of intelligently cancelling \"create/delete same issue\",\n\t// and custom dequeue for e.g. if user insists on removing a failed a \"create issue\", then remove the \"edit\n\t// that same issue\"\n\tqueue: {\n\t\t...offlineConfig.queue,\n\t\tenqueue,\n\t\tdequeue,\n\t\t// Bad typing, undefined is actually fine, and the action is a FullOfflineAction, not just an OfflineAction.\n\t\tpeek: (...args) => peek(...(args as Parameters<typeof peek>))!,\n\t} satisfies Config[\"queue\"],\n}\n\n// migration to compose into store\nconst migration = createMigration(manifest, VERSION_REDUCER_KEY) as (_: unknown) => unknown\n\n/**\n * Enhancer for the Redux store that adds offline support and needed middleware for overmap.\n * Add to your store's `enhancers` array.\n */\nexport const overmapEnhancer = compose(offline(customConfig), migration)\n\n/**\n * Makes a best-effort attempt to extract a request.Response from an error object.\n * @param error The error object\n */\nfunction extractResponseFromError(error: unknown): request.Response | undefined {\n\tfunction isResponse(response: unknown): response is request.Response {\n\t\t// Just some keys we know are on a request.Response\n\t\tconst knownKeys = [\"ok\", \"redirect\", \"clientError\", \"serverError\", \"error\"]\n\t\treturn typeof response === \"object\" && response !== null && knownKeys.every((key) => key in response)\n\t}\n\n\tif (isResponse(error)) return error\n\tif (typeof error === \"object\" && error !== null) {\n\t\tconst typedError = error as { response?: { response?: request.Response } }\n\t\tif (isResponse(typedError.response)) return typedError.response\n\t\tif (typedError.response && isResponse(typedError.response.response)) return typedError.response.response\n\t}\n\treturn undefined\n}\n\n// Executes an offline action by making the API request specified in the action's offline metadata\nexport async function performRequest(action: FullOfflineAction, client: BaseSDK<BaseState>): Promise<request.Response> {\n\tconst serviceOfRequest = CLASS_NAME_TO_SERVICE[action.meta.offline.effect.serviceName]\n\n\tif (!serviceOfRequest) {\n\t\tthrow new Error(`Service ${action.meta.offline.effect.serviceName} not found`)\n\t}\n\n\tconst isApiService = serviceOfRequest instanceof BaseApiService\n\n\tconst state = client.store.getState()\n\tif (state.outboxReducer.deletedRequests.includes(action.payload.uuid)) {\n\t\t// The request has been marked for deletion, so we don't want to perform it.\n\t\t// Instead, throw an error, so it will be retried and discarded in the `discard` function.\n\t\tthrow new Error(\"Request was marked for deletion\")\n\t}\n\n\tif (isApiService && action.payload.checkAuth !== false) {\n\t\tawait serviceOfRequest.auth.prepareAuth()\n\t}\n\n\tconst defaultSettings = {\n\t\tqueryParams: \"\",\n\t\tisAuthNeeded: true,\n\t}\n\n\tconst offlineEffect = action.meta.offline.effect\n\tconst { payload, headers, method, queryParams, attachmentHash, isExternalUrl, isAuthNeeded, isResponseBlob } = {\n\t\t...defaultSettings,\n\t\t...offlineEffect.request,\n\t}\n\tconst requestDetails = offlineEffect.request\n\tlet url = requestDetails.url\n\tconst file = attachmentHash ? await client.files.fetchCache(attachmentHash) : undefined\n\n\tif (attachmentHash && !file) {\n\t\tthrow new Error(`Cannot upload file ${attachmentHash} because it's not cached.`)\n\t}\n\n\tif ((!isExternalUrl || import.meta.env.DEV) && !url.startsWith(\"http\")) {\n\t\tif (!url.startsWith(\"/\") && !url.startsWith(\"blob:\")) {\n\t\t\turl = \"/\" + url\n\t\t\tif (import.meta.env.DEV) {\n\t\t\t\tconsole.trace(`You have passed a host-relative URL: ${url}`)\n\t\t\t}\n\t\t}\n\t\turl = action.meta.offline.effect.BASE_URL + url\n\t}\n\n\tconst addPayload = (req: request.SuperAgentRequest) => {\n\t\tif (attachmentHash) {\n\t\t\tconst s3url = requestDetails.s3url\n\t\t\tif (!s3url) throw new Error(`No S3 URL for file ${attachmentHash}`)\n\t\t\tif (\"warning\" in s3url) throw new Error(`S3 URL warning for file ${attachmentHash}`)\n\t\t\tif (!file) throw new Error(`No file for file ${attachmentHash}`)\n\t\t\tconst s3Sha1Checksum = s3url.fields[\"x-amz-checksum-sha1\"]\n\t\t\tif (!s3Sha1Checksum) throw new Error(`No checksum for file ${attachmentHash}`)\n\t\t\treturn req\n\t\t\t\t.set(\"x-amz-checksum-sha1\", s3Sha1Checksum)\n\t\t\t\t.field({ ...payload, ...s3url.fields })\n\t\t\t\t.attach(\"file\", file as unknown as Blob)\n\t\t}\n\t\treturn req.send(payload)\n\t}\n\n\tconst methodRequestMapping: Record<HttpMethod, () => request.SuperAgentRequest> = {\n\t\t[HttpMethod.GET]: () => {\n\t\t\tif (isResponseBlob) {\n\t\t\t\treturn request.get(url.toString()).responseType(\"blob\")\n\t\t\t}\n\t\t\treturn request.get(url.toString())\n\t\t},\n\t\t[HttpMethod.POST]: () => {\n\t\t\tconst ret = request.post(url.toString())\n\t\t\treturn addPayload(ret)\n\t\t},\n\t\t[HttpMethod.PATCH]: () => {\n\t\t\tconst ret = request.patch(url.toString())\n\t\t\treturn addPayload(ret)\n\t\t},\n\t\t[HttpMethod.PUT]: () => {\n\t\t\tconst ret = request.put(url.toString())\n\t\t\treturn addPayload(ret)\n\t\t},\n\t\t[HttpMethod.DELETE]: () => {\n\t\t\tconst ret = request.delete(url.toString())\n\t\t\treturn addPayload(ret)\n\t\t},\n\t}\n\n\tconst selectedRequest = methodRequestMapping[method]\n\n\tlet requestToSend = selectedRequest()\n\tif (isAuthNeeded && isApiService) {\n\t\tconst authHeader = serviceOfRequest.auth.getAuthHeader()\n\t\trequestToSend = requestToSend.set(\"Authorization\", authHeader)\n\t}\n\tif (headers) {\n\t\trequestToSend = requestToSend.set(headers)\n\t}\n\n\ttry {\n\t\treturn await requestToSend.query(queryParams)\n\t} catch (error) {\n\t\t// Observed error types: Error, request.Response\n\t\t// If it's an Error, it has a `response.response` property that is a request.Response.\n\t\tconst errorResponse = extractResponseFromError(error)\n\t\tconst status: number | undefined = errorResponse?.status\n\n\t\tif (isApiService && status === 401) {\n\t\t\tawait serviceOfRequest.auth.handleUnauthorized(requestToSend, errorResponse!)\n\t\t\treturn requestToSend.query(queryParams)\n\t\t}\n\n\t\t// TODO: Error codes for all APIErrors.\n\t\t// TODO: Constant for all messages.\n\t\tthrow new APIError({ response: errorResponse, innerError: error, discard: discardStatuses.includes(status!) })\n\t}\n}\n\ninterface MiddlewareChainer {\n\tthen: (next: OfflineMiddleware) => MiddlewareChainer\n\tcompile: () => OfflineMiddleware[]\n}\n\nclass MiddlewareChainerPrivate {\n\t_all: OfflineMiddleware[]\n\t_previous?: OfflineMiddleware\n\n\tconstructor(current: OfflineMiddleware) {\n\t\tthis._all = [current]\n\t\tthis._previous = current\n\t\tthis.then = this.then.bind(this)\n\t\tthis.compile = this.compile.bind(this)\n\t}\n\n\tthen(next: OfflineMiddleware): MiddlewareChainer {\n\t\tif (this._previous) this._previous.next = next // \"next\" is now \"current\"\n\t\tthis._all.push(next)\n\t\tthis._previous = next // \"next\" is now \"previous\"\n\n\t\treturn {\n\t\t\t// eslint-disable-next-line @typescript-eslint/unbound-method\n\t\t\tthen: this.then,\n\t\t\t// eslint-disable-next-line @typescript-eslint/unbound-method\n\t\t\tcompile: this.compile,\n\t\t}\n\t}\n\n\tcompile() {\n\t\treturn this._all\n\t}\n}\n\nabstract class OfflineMiddleware {\n\tnext: OfflineMiddleware | null\n\n\tconstructor() {\n\t\tthis.next = null\n\t}\n\n\tthen(next: OfflineMiddleware): MiddlewareChainer {\n\t\treturn new MiddlewareChainerPrivate(this).then(next)\n\t}\n\n\tasync run(action: FullOfflineAction): Promise<request.Response | null> {\n\t\tif (this.next) {\n\t\t\treturn this.next.run(action)\n\t\t} else {\n\t\t\tconsole.debug(\"Middleware finished. Performing request:\", action)\n\n\t\t\tconst clientStore = getClientStore()\n\t\t\tif (!clientStore) throw new Error(\"Client store not set\")\n\n\t\t\tconst clientSDK = getClientSDK()\n\t\t\tif (!clientSDK) throw new Error(\"Client SDK not set\")\n\n\t\t\t// At the end of the middleware chain, we want to perform the action\n\t\t\treturn performRequest(action, clientSDK)\n\t\t}\n\t}\n}\n\nclass OfflineAnalyticsMiddleware extends OfflineMiddleware {\n\tasync run(action: FullOfflineAction): Promise<request.Response | null> {\n\t\t// TODO: Store some statistics on which actions are called and enqueue reports periodically\n\t\treturn super.run(action)\n\t}\n}\n\nclass RateLimitingMiddleware extends OfflineMiddleware {\n\tasync run(action: FullOfflineAction): Promise<request.Response | null> {\n\t\t// TODO: Consider rate limits (enable offline mode programmatically to reduce rate)\n\t\treturn super.run(action)\n\t}\n}\n\nconst allMiddleware = new OfflineAnalyticsMiddleware().then(new RateLimitingMiddleware()).compile()\n\nfunction runMiddleware(action: FullOfflineAction) {\n\treturn allMiddleware[0]?.run(action)\n}\n\n// These status codes are due to a fundamental problem that can never be corrected except by manual intervention.\n// TODO: 400 (Bad Request) should result in the user being given a chance to amend their request to be valid.\nconst discardStatuses = [400, 409, 403, 404, 405, 500]\nconst statusMessages: Record<number, ToastProps | undefined> = {\n\t403: { title: \"Forbidden\", description: \"You are not authorized to perform this action.\", accentColor: \"red\" },\n\t404: { title: \"Not found\", description: \"The requested resource was not found.\", accentColor: \"red\" },\n\t405: {\n\t\ttitle: \"Not supported\",\n\t\tdescription: \"It's not you. It's us. Sorry for the inconvenience.\",\n\t\taccentColor: \"red\",\n\t},\n\t500: {\n\t\ttitle: \"Server error\",\n\t\tdescription:\n\t\t\t\"Our server seems to be experiencing problems at the moment. We have been alerted and will fix the \" +\n\t\t\t\"problem as soon as possible.\",\n\t\taccentColor: \"red\",\n\t},\n}\n\n// Discard function is used by Redux Offline to decide whether to discard an action or not, based on the error\n// that the effect reconciler threw and/or the action\nexport function discard(reason: unknown, action: FullOfflineAction, retries = 0): boolean {\n\t// TODO: If 401, renew auth and return false\n\t// TODO: If 400, set state to rescue mode, allowing the user to fix the request and retry (or discard)\n\n\tconsole.debug(\n\t\t\"Considering discarding request due to error:\",\n\t\treason,\n\t\t`(${typeof reason})`,\n\t\t\"\\nAction:\",\n\t\taction,\n\t\t\"\\nRetries:\",\n\t\tretries,\n\t)\n\n\tif (!(reason instanceof Error)) {\n\t\tconsole.error(\n\t\t\t\"ENCOUNTERED NON-ERROR ERROR:\",\n\t\t\treason,\n\t\t\t\"(throwing immediately, which may lead to unexpected behavior)\",\n\t\t)\n\t\tthrow reason\n\t}\n\n\tconst clientStore = getClientStore()\n\tconst state = clientStore!.getState()\n\tconst deletedRequests = state.outboxReducer.deletedRequests\n\tconst uuid = action.payload.uuid\n\n\t// NOTE: Doesn't really return true, but TypeScript doesn't need to know that.\n\t// Adding a `return true` would be meaningless since we are throwing the passed error.\n\tfunction rollbackAndThrow(): true {\n\t\tclientStore!.dispatch(markAsDeleted(uuid))\n\t\tconst coordinator = getOutboxCoordinator()\n\t\tif (!coordinator) {\n\t\t\tthrow new Error(\"Outbox coordinator not set\")\n\t\t}\n\t\tcoordinator.remove(action.payload.uuid)\n\t\tconst rollbackAction = action.meta.offline.rollback\n\t\tif (rollbackAction) {\n\t\t\tconsole.warn(\"Rolling back request due to SDK error:\", action)\n\t\t\tclientStore!.dispatch(rollbackAction)\n\t\t}\n\t\tthrow reason\n\t}\n\n\tif (reason instanceof APIError && reason.options.discard) {\n\t\tconsole.debug(\"Discarding request due to explicit discard:\", action)\n\t\treturn rollbackAndThrow()\n\t}\n\n\tif (deletedRequests.includes(uuid)) {\n\t\tconsole.debug(\"Discarding request due to deletion:\", action)\n\t\treturn rollbackAndThrow()\n\t}\n\n\tif (reason instanceof APIError) {\n\t\tconst status: number | undefined = reason.status || reason.response?.status\n\t\tif (!status) {\n\t\t\tconsole.warn(\"Error has no status code:\", reason)\n\t\t}\n\t\tif (status !== undefined && discardStatuses.includes(status)) {\n\t\t\tconsole.warn(\"Discarding request due to error:\", reason, \"\\nAction:\", action)\n\t\t\tconst message = statusMessages[status]\n\t\t\tif (message) {\n\t\t\t\tif (unsafeShowToast) {\n\t\t\t\t\tunsafeShowToast(message)\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error(`Could not display toast for status ${status} because there is no toast handle.`)\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst coordinator = getOutboxCoordinator()\n\t\t\tif (!coordinator) {\n\t\t\t\tthrow new Error(\"Outbox coordinator not set\")\n\t\t\t}\n\t\t\tcoordinator.remove(action.payload.uuid)\n\t\t\treason.options.discard = true\n\t\t\trollbackAndThrow()\n\t\t}\n\t}\n\n\tconsole.debug(\"Registering a retry for request:\", action.payload.uuid)\n\t// All failures due to any other reason should be retried indefinitely. It will not block the outbox thanks to\n\t// OutboxCoordinator.\n\tconst coordinator = getOutboxCoordinator()\n\tif (!coordinator) {\n\t\tthrow new Error(\"Outbox coordinator not set\")\n\t}\n\tcoordinator.registerRetry(action.payload.uuid)\n\treturn false\n}\n\n// Peek function is used by Redux Offline to determine the next action of the outbox to execute.\n// We are overriding the default implementation (return array[0]) with our own to support our graph-based outbox.\nfunction peek(\n\t_array: FullOfflineAction[],\n\t_item: unknown,\n\t_context: { offline: OfflineState },\n): OfflineAction | undefined {\n\treturn getOutboxCoordinator()?.peek()\n}\n\n// Retry function is used by Redux Offline to determine how long to retry an action, given number of retries\nfunction retry(_action: FullOfflineAction, _retries: number): number | undefined {\n\t// Always retry, but wait a few seconds after a failed request. We have our own custom discard/retry logic.\n\tgetClientStore()!.dispatch(_setLatestRetryTime(new Date().getTime()))\n\treturn OUTBOX_RETRY_DELAY\n}\n\n// export type AppThunk<ReturnType = void> = ThunkAction<ReturnType, RootState, unknown, Action<string>>\n","// The shape of an object that describes the details of an API request\nimport { FileService } from \"./services\"\nimport { ToolkitStore } from \"@reduxjs/toolkit/dist/configureStore\"\nimport request from \"superagent\"\nimport { v4 as uuidv4 } from \"uuid\"\nimport { OfflineMetaEffect, SDKRequest } from \"./typings\"\nimport { APIError } from \"./errors\"\nimport { DeferredPromise } from \"../utils/async/DeferredPromise\"\nimport { discard, enqueueRequest, FullOfflineAction, performRequest } from \"../store\"\nimport { BaseState } from \"../typings\"\n\n// This is a bundle of the services that our app uses. These can be used in tandem with the types\n// declared above in order to execute requests to the backend (queued or otherwise). To use it,\n// you can declare a \"PlaceholderName-Service.ts\" and have CRUD methods to send to the backend,\n// and call it by using `sdk.PlaceHolderName.CRUD_METHOD`\nexport abstract class BaseSDK<TState extends BaseState> {\n\treadonly store: ToolkitStore<TState>\n\tabstract readonly files: FileService<TState, BaseSDK<TState>>\n\n\tprotected constructor(store: ToolkitStore<TState>) {\n\t\tthis.store = store\n\t}\n\n\tpublic async enqueueRequest<TResult>(\n\t\trequestDetails: SDKRequest,\n\t\thost: string,\n\t\tserviceName: string,\n\t): Promise<TResult> {\n\t\t// enqueueRequest is a wrapper for _enqueueRequest that ensures the result is not an APIError unless\n\t\t// `.catch()` is triggered.\n\t\treturn this._enqueueRequest<TResult>(requestDetails, host, serviceName).then((result) => {\n\t\t\tif (result instanceof APIError) {\n\t\t\t\tthrow result\n\t\t\t}\n\t\t\treturn result\n\t\t})\n\t}\n\n\tprivate _enqueueRequest<TResult>(\n\t\trequestDetails: SDKRequest,\n\t\thost: string,\n\t\tserviceName: string,\n\t): DeferredPromise<TResult | APIError> {\n\t\t// We'll receive a Response object, but we want to return just the body of the response. This means\n\t\t// that we must inject a callback in the middle. We will use two promises:\n\t\tconst promise = new DeferredPromise<TResult | APIError>()\n\n\t\t// We dispatch an action that will eventually result in a request.\n\t\tconst requestDetailsWithBaseUrl = { ...requestDetails, BASE_URL: host, serviceName: serviceName }\n\n\t\tif (requestDetails.immediate) {\n\t\t\tconst requestWithUuid = {\n\t\t\t\t...requestDetailsWithBaseUrl,\n\t\t\t\tuuid: requestDetails.uuid ?? uuidv4(),\n\t\t\t}\n\t\t\t// TODO: Does this result in sending the request multiple times?\n\t\t\t// Should performRequest accept pure requestDetails?\n\t\t\t// (It shouldn't result in dupes because we're not dispatching an action.)\n\t\t\tconst fullOfflineAction: FullOfflineAction = {\n\t\t\t\tpayload: requestWithUuid,\n\t\t\t\ttype: \"\",\n\t\t\t\tmeta: {\n\t\t\t\t\toffline: {\n\t\t\t\t\t\teffect: {\n\t\t\t\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t\t\t\t\trequest: requestWithUuid,\n\t\t\t\t\t\t\tBASE_URL: host,\n\t\t\t\t\t\t\tserviceName: serviceName,\n\t\t\t\t\t\t} satisfies OfflineMetaEffect,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t\tperformRequest(fullOfflineAction, this)\n\t\t\t\t.then((result) => {\n\t\t\t\t\tpromise.resolve(result.body as TResult)\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tdiscard(error, fullOfflineAction)\n\t\t\t\t\tpromise.reject(error)\n\t\t\t\t})\n\t\t} else {\n\t\t\tconst innerPromise: Promise<request.Response> = this.store.dispatch(\n\t\t\t\tenqueueRequest(requestDetailsWithBaseUrl),\n\t\t\t) as unknown as Promise<request.Response>\n\n\t\t\tconst successOrUndefinedHandler = (response: request.Response | undefined) => {\n\t\t\t\tif (response) {\n\t\t\t\t\tpromise.resolve(response.body as TResult)\n\t\t\t\t} else {\n\t\t\t\t\tconst error = new APIError({\n\t\t\t\t\t\tmessage: \"Could not get a response from the server.\",\n\t\t\t\t\t\tresponse: response satisfies undefined,\n\t\t\t\t\t\tdiscard: true,\n\t\t\t\t\t})\n\t\t\t\t\tpromise.reject(error)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Handles errors from the inner promise (which performs the request) and rejects the outer promise, which has\n\t\t\t * been returned to the caller by the time this is triggered. This handler is only expected to be triggered if\n\t\t\t * the request has been discarded from the outbox.\n\t\t\t * @param error The error that caused the request to be discarded. Expected to be an APIError instance.\n\t\t\t */\n\t\t\tconst errorHandler = (error: unknown) => {\n\t\t\t\tif (error instanceof APIError) {\n\t\t\t\t\terror.options.discard = true\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t\"Received an unexpected error while processing a request:\",\n\t\t\t\t\t\terror,\n\t\t\t\t\t\t\"\\nConverting error to APIError and discarding.\",\n\t\t\t\t\t)\n\t\t\t\t\terror = new APIError({\n\t\t\t\t\t\tmessage: \"An error occurred while processing the request.\",\n\t\t\t\t\t\tinnerError: error,\n\t\t\t\t\t\tdiscard: true,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tpromise.reject(error)\n\t\t\t}\n\n\t\t\tinnerPromise.then(successOrUndefinedHandler, errorHandler)\n\t\t}\n\n\t\treturn promise\n\t}\n\n\t// NOTE: these are currently expected to be present in the base SDK, not sure if that is desired\n}\n","import { BaseSDK } from \"./base\"\nimport { ToolkitStore } from \"@reduxjs/toolkit/dist/configureStore\"\nimport { BaseState } from \"../typings\"\nimport { setClientSDK, setClientStore } from \"./globals\"\nimport { OvermapSDKConstructor } from \"./typings\"\n\nexport const initSDK = <TState extends BaseState, TSDK extends BaseSDK<TState>>(\n\tstore: ToolkitStore<TState>,\n\tsdk: OvermapSDKConstructor<TState, TSDK>,\n) => {\n\tconst sdkInstance = new sdk(store)\n\tsetClientSDK(sdkInstance)\n\tsetClientStore(store)\n\n\treturn sdkInstance\n}\n","import { Response, SuperAgentRequest } from \"superagent\"\nimport { BaseState } from \"../../typings\"\nimport type { BaseSDK } from \"../base\"\nimport { BaseService } from \"./BaseService\"\n\nexport abstract class BaseAuthService<TStore extends BaseState, TSDK extends BaseSDK<TStore>> extends BaseService<\n\tTStore,\n\tTSDK\n> {\n\tprotected constructor(sdk: TSDK) {\n\t\tsuper(sdk)\n\t}\n\n\tabstract initAuth(payload: object): Promise<void>\n\n\tabstract clearAuth(): void\n\n\tabstract prepareAuth(): Promise<void>\n\n\tabstract getAuthHeader(): string\n\n\tabstract handleUnauthorized(request: SuperAgentRequest, response: Response): Promise<void>\n}\n","import { markForDeletion, resetStore, setLoggedIn } from \"../../store\"\nimport { RESET_STATE } from \"@redux-offline/redux-offline/lib/constants\"\nimport request from \"superagent\"\nimport jwtDecode, { JwtPayload } from \"jwt-decode\"\nimport { BaseState } from \"../../typings\"\nimport { HttpMethod } from \"../../enums\"\nimport { v4 as uuidv4 } from \"uuid\"\nimport { APIError } from \"../errors\"\nimport type { BaseSDK } from \"../base\"\nimport { TokenPair } from \"../typings\"\nimport { BaseAuthService } from \"./BaseAuthService\"\n\n// Number of seconds until expiry that we consider as \"expiring soon\"\nconst EXPIRING_SOON_THRESHOLD = 1800\n\n// TODO: Rename `accessToken` and `refreshToken` to `access` and `refresh` respectively, then remove this function and\n// just return the response directly.\nfunction parseTokens(response: { access: string; refresh: string }): TokenPair {\n\tif (!response.access) throw new Error(\"Missing access token\")\n\tif (!response.refresh) throw new Error(\"Missing refresh token\")\n\treturn { accessToken: response.access, refreshToken: response.refresh }\n}\n\n/**\n * Handles login, logout and renewing tokens\n */\nexport abstract class JWTService<TState extends BaseState, TSDK extends BaseSDK<TState>> extends BaseAuthService<\n\tTState,\n\tTSDK\n> {\n\t// AUTH below\n\tprotected abstract initTokensUrl: string\n\tprotected abstract refreshTokensUrl: string\n\tprotected abstract setTokens: (tokens: TokenPair) => void\n\tprotected abstract clearTokens: () => void\n\tprotected abstract getAccessToken: () => string\n\tprotected abstract getRefreshToken: () => string\n\n\t// _getTokenPair and _getRenewedTokens don't need to use enqueueRequest from the BaseApiService because\n\t// they are very simple. However, if we need robust error handling or want these operations to queue in the Outbox,\n\t// we will use enqueueRequest.\n\n\t/**\n\t * Takes refresh token and gets a new token pair\n\t * @async\n\t * @param {string} refreshToken The refresh token used to get new tokens\n\t * @returns {Promise<TokenPair>} The new access and refresh tokens\n\t */\n\tprivate _getRenewedTokens = async (refreshToken: string): Promise<TokenPair | undefined> => {\n\t\tinterface MaybeTokenPair {\n\t\t\taccess?: string\n\t\t\trefresh?: string\n\t\t}\n\n\t\tconst promise = this.enqueueRequest<MaybeTokenPair>({\n\t\t\tdescription: \"Get renewed tokens\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: this.refreshTokensUrl,\n\t\t\tpayload: { refresh: refreshToken },\n\t\t\tisAuthNeeded: false,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t\t// Don't wait for an auth check since this is a refresh token request.\n\t\t\tcheckAuth: false,\n\t\t\t// Don't wait for other requests to finish, or we might end up in a deadlock.\n\t\t\timmediate: true,\n\t\t})\n\n\t\tlet response: MaybeTokenPair | undefined = undefined\n\t\ttry {\n\t\t\tresponse = await promise\n\t\t} catch (e) {\n\t\t\t// TODO: See TODOs in `renewTokens`\n\t\t\t// Log out if the request fails\n\t\t\tconsole.error(\"Could not renew tokens; clearing auth\", e)\n\t\t\tthis.clearAuth()\n\t\t\treturn undefined\n\t\t}\n\n\t\tif (!response.access) throw new Error(\"Missing access token\")\n\n\t\treturn { accessToken: response.access, refreshToken: response.refresh ?? this.getRefreshToken() }\n\t}\n\n\t/**\n\t * Logs the user out\n\t */\n\tclearAuth() {\n\t\t// This also sends an action to the store.ts rootReducer function, allowing\n\t\t// the store to be reset upon sending an undefined state to the other\n\t\t// reducers.\n\t\tconsole.debug(this.constructor.name, \"clearing auth;\")\n\n\t\tthis.dispatch(setLoggedIn(false))\n\t\tthis.clearTokens()\n\t\t// Clear the outbox\n\t\tthis.dispatch({ type: RESET_STATE })\n\t\t// TODO: Consider using only one of the two approaches\n\t\t// For good measure:\n\t\tthis.dispatch({ type: resetStore })\n\t}\n\n\t/**\n\t * Attempts to renew tokens\n\t */\n\tasync renewTokens() {\n\t\tconst dyingRefreshToken = this.getRefreshToken()\n\t\tif (!dyingRefreshToken) {\n\t\t\tthrow new Error(\"No refresh token found\")\n\t\t}\n\n\t\tconsole.debug(this.constructor.name, \"renewing tokens\")\n\n\t\ttry {\n\t\t\tconst tokens = await this._getRenewedTokens(dyingRefreshToken)\n\t\t\tif (!tokens) {\n\t\t\t\treturn undefined\n\t\t\t}\n\t\t\tconsole.log(\"Got renewed tokens\")\n\t\t\tthis.setTokens(tokens)\n\t\t} catch (e) {\n\t\t\t// TODO: Why is this not being triggered when the request fails inside _getRenewedTokens?\n\t\t\t// TODO: This is temporary behaviour, replace it with login button on outbox failed requests\n\t\t\t// that failed because of a 401 Unauthorized\n\t\t\tconsole.error(\"Could not renew tokens; clearing auth\", e)\n\t\t\tthis.clearAuth()\n\t\t\tthrow e\n\t\t}\n\t}\n\n\ttokenIsExpiringSoon(): boolean {\n\t\tconst accessToken = this.getAccessToken()\n\t\tif (!accessToken) {\n\t\t\t// If the access token doesn't exist, it's not expiring.\n\t\t\treturn false\n\t\t}\n\t\t// Convert the current date from milliseconds to seconds (divide by 1000)\n\t\tconst currentDate = Date.now() / 1000\n\t\t// Find the expiration date of access token (in seconds)\n\t\tlet expiryDate: number\n\t\t// jwtDecode may throw an error if the access token is an empty string (logged out)\n\t\ttry {\n\t\t\t// REASON: Bad types\n\t\t\t// eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error,@typescript-eslint/ban-ts-comment\n\t\t\t// @ts-ignore\n\n\t\t\texpiryDate = jwtDecode<JwtPayload>(accessToken).exp ?? currentDate\n\t\t} catch {\n\t\t\t// Enforce expiration if unable to decode token\n\t\t\texpiryDate = currentDate\n\t\t}\n\t\tconst secondsUntilExpiry = expiryDate - currentDate\n\t\treturn secondsUntilExpiry < EXPIRING_SOON_THRESHOLD\n\t}\n\n\tpublic getAuthHeader() {\n\t\tconst accessToken = this.getAccessToken()\n\t\treturn `Bearer ${accessToken}`\n\t}\n\n\tpublic async prepareAuth() {\n\t\tif (!this.tokenIsExpiringSoon()) return\n\n\t\tconsole.debug(this.constructor.name, \"preparing auth\")\n\t\ttry {\n\t\t\tawait this.renewTokens()\n\t\t} catch (e) {\n\t\t\tif (e instanceof APIError) {\n\t\t\t\t// Renewing tokens has failed; we should sign out the user.\n\t\t\t\tthis.clearAuth()\n\t\t\t}\n\t\t\treturn Promise.reject(e)\n\t\t}\n\t}\n\n\t/* if not successfull in gracefully handling an unauthorized response, throw and APIError */\n\tpublic async handleUnauthorized(request: request.SuperAgentRequest, response: request.Response) {\n\t\tconst state = this.client.store.getState()\n\t\t// Without this check, we end up in a loop:\n\t\t// client.auth.renewTokens() -> enqueue -> performRequest -> status === 401 -> client.auth.renewTokens()\n\t\t// See [1] below\n\t\tif (request.url.endsWith(\"/token/refresh/\")) {\n\t\t\t// If the refresh token has expired, we can't do anything.\n\t\t\tif (state.authReducer.isLoggedIn) {\n\t\t\t\t// This is only expected when signing in for the first time with invalid credentials.\n\t\t\t\tconsole.warn(\"No signed-in user to sign out.\")\n\t\t\t}\n\t\t\tthis.clearAuth()\n\t\t\tthrow new APIError({\n\t\t\t\tmessage: \"You have been signed out due to inactivity.\",\n\t\t\t\tresponse: response,\n\t\t\t\tdiscard: true,\n\t\t\t})\n\t\t}\n\t\tif (state.authReducer.isLoggedIn) {\n\t\t\tawait this.renewTokens()\n\t\t} else {\n\t\t\t// If the user is not logged in, we can't renew tokens.\n\t\t\t// Assume this is a login attempt with invalid credentials.\n\t\t\tconsole.debug(\"Forbidden; user is not logged in.\")\n\t\t\tthrow new APIError({\n\t\t\t\tmessage: \"Incorrect username or password.\",\n\t\t\t\tresponse: response,\n\t\t\t\tdiscard: true,\n\t\t\t})\n\t\t}\n\t}\n\n\tasync initAuth(payload: object): Promise<undefined> {\n\t\t// false: Don't log out on failure because we're not currently logged in. Instead, throw and show an error.\n\t\tconst uuid = uuidv4()\n\n\t\tconsole.debug(this.constructor.name, \"Initiating auth\")\n\t\tconst promise = this.enqueueRequest<{ access: string; refresh: string }>({\n\t\t\tuuid,\n\t\t\tdescription: \"Get token pair\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: this.initTokensUrl,\n\t\t\tpayload: payload,\n\t\t\tisAuthNeeded: false,\n\t\t\tcheckAuth: false,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t}).then(parseTokens)\n\n\t\t// The goal: Cancel the request if it takes too long\n\t\tconst timeout = 5 // seconds\n\t\tlet timedOut = false\n\n\t\tconst timeoutPromise = new Promise<undefined>((_, reject) => {\n\t\t\tsetTimeout(() => {\n\t\t\t\ttimedOut = true\n\t\t\t\tthis.dispatch(markForDeletion(uuid))\n\t\t\t\treject(new APIError({ message: `Request timed out after ${timeout} seconds` }))\n\t\t\t}, timeout * 1000)\n\t\t})\n\n\t\tconst successPromise: Promise<undefined> = promise.then((tokens) => {\n\t\t\tif (timedOut) {\n\t\t\t\treturn undefined\n\t\t\t}\n\t\t\tthis.setTokens(tokens)\n\t\t})\n\n\t\treturn Promise.race([timeoutPromise, successPromise])\n\t}\n}\n","import type { BaseSDK } from \"../base\"\nimport { BaseState } from \"../../typings\"\nimport { BaseAuthService } from \"./BaseAuthService\"\nimport { BaseService } from \"./BaseService\"\n\n/**\n * Abstract base class for building a service that can enqueue API requests\n */\nexport abstract class BaseApiService<TStore extends BaseState, TSDK extends BaseSDK<TStore>> extends BaseService<\n\tTStore,\n\tTSDK\n> {\n\treadonly auth: BaseAuthService<TStore, TSDK>\n\n\tconstructor(sdk: TSDK, auth: BaseAuthService<TStore, TSDK>) {\n\t\tsuper(sdk)\n\t\tthis.auth = auth\n\t}\n}\n","import { Category, Created, Offline, OvermapRootState, Payload, Stored } from \"../../typings\"\nimport { OptimisticModelResult } from \"../typings\"\nimport { offline } from \"../../utils\"\nimport { HttpMethod } from \"../../enums\"\nimport { addCategory, updateCategory, deleteCategory, initializeCategories, selectCategoryById } from \"../../store\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\n/**\n * Handles the creation of Category Service\n * TODO: Support editing and deleting categories\n */\nexport abstract class CategoryService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tadd(category: Omit<Payload<Category>, \"workspace\">, workspaceId: string): OptimisticModelResult<Category> {\n\t\tconst offlineCategory = offline(category)\n\t\tconst categoryWithWorkspace = { ...offlineCategory, workspace: workspaceId }\n\t\tthis.dispatch(addCategory(categoryWithWorkspace))\n\n\t\tconst promise = this.enqueueRequest<Category>({\n\t\t\tdescription: \"Create Category\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: \"/categories/\",\n\t\t\tqueryParams: {\n\t\t\t\tworkspace_id: workspaceId.toString(),\n\t\t\t},\n\t\t\tpayload: offlineCategory,\n\t\t\tblockers: [],\n\t\t\tblocks: [offlineCategory.offline_id],\n\t\t})\n\t\treturn [categoryWithWorkspace, promise]\n\t}\n\n\tupdate(category: Offline<Partial<Category>>, workspaceId: string): OptimisticModelResult<Category> {\n\t\tconst state = this.client.store.getState()\n\t\tconst existingCategory = selectCategoryById(category.offline_id)(state)\n\n\t\tif (!existingCategory) {\n\t\t\tthrow new Error(`Expected an existing category with offline_id ${category.offline_id}`)\n\t\t}\n\n\t\tconst optimisticCategory: Stored<Category> = { ...existingCategory, ...category }\n\t\tthis.dispatch(updateCategory(optimisticCategory))\n\n\t\tconst promise = this.enqueueRequest<Created<Category>>({\n\t\t\tdescription: \"Edit Category\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/categories/${category.offline_id}/`,\n\t\t\tqueryParams: {\n\t\t\t\tworkspace_id: workspaceId.toString(),\n\t\t\t},\n\t\t\tpayload: category,\n\t\t\tblockers: [category.offline_id],\n\t\t\tblocks: [category.offline_id],\n\t\t})\n\n\t\treturn [optimisticCategory, promise]\n\t}\n\n\tremove(category: Category, workspaceId: string): Promise<undefined> {\n\t\tthis.dispatch(deleteCategory(category.offline_id))\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Delete Category\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/categories/${category.offline_id}/`,\n\t\t\t// TODO: Shouldn't be necessary to specify workspace_id here\n\t\t\tqueryParams: {\n\t\t\t\tworkspace_id: workspaceId.toString(),\n\t\t\t},\n\t\t\tblockers: [category.offline_id],\n\t\t\tblocks: [],\n\t\t})\n\t}\n\n\tasync refreshStore(projectId: number): Promise<undefined> {\n\t\tconst result = await this.enqueueRequest<Category[]>({\n\t\t\tdescription: \"Get categories\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/categories/`,\n\t\t\tblocks: [],\n\t\t\tblockers: [],\n\t\t})\n\t\tthis.dispatch(initializeCategories(result))\n\t}\n}\n","export function chunkArray<T>(arr: T[], chunkSize: number) {\n\tconst chunks: T[][] = []\n\tlet index = 0\n\tconst arrLength = arr.length\n\n\twhile (index < arrLength) {\n\t\tchunks.push(arr.slice(index, (index += chunkSize)))\n\t}\n\n\treturn chunks\n}\n","import { v4 as uuidv4 } from \"uuid\"\nimport { Asset, Created, Payload, OvermapRootState, Submitted } from \"../../typings\"\nimport { OptimisticModelResult } from \"../typings\"\nimport { offline } from \"../../utils\"\nimport { HttpMethod } from \"../../enums\"\nimport {\n\taddAsset,\n\taddAssets,\n\taddAssetAttachments,\n\tdeleteAsset,\n\tselectAttachmentsOfAsset,\n\tselectAssetById,\n\tselectAssetsOfAssetType,\n\tupdateAsset,\n\tdeleteAssets,\n\tinitializeAssets,\n\tdeleteAssetAttachments,\n\tselectFormSubmissionsOfAsset,\n\tdeleteFormSubmissions,\n\taddFormSubmissions,\n\tselectIssueAssociationsOfAsset,\n\tdeleteIssueAssociations,\n\taddIssueAssociations,\n} from \"../../store\"\nimport { chunkArray } from \"../../utils/array\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class AssetService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\t// Basic CRUD functions\n\tadd(asset: Payload<Asset>, workspaceId: string): OptimisticModelResult<Asset> {\n\t\tif (!asset.canvas_marker && !asset.geo_marker) {\n\t\t\tthrow new Error(\"Asset must have either a canvas_marker or geo_marker\")\n\t\t}\n\n\t\tconst offlineAsset = offline(asset)\n\t\tthis.dispatch(addAsset(offlineAsset))\n\t\tconst promise = this.enqueueRequest<Asset>({\n\t\t\tdescription: \"Create asset\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/assets/types/${offlineAsset.asset_type}/add-assets/`,\n\t\t\tqueryParams: {\n\t\t\t\tworkspace_id: workspaceId.toString(),\n\t\t\t},\n\t\t\tpayload: { assets: [offlineAsset] },\n\t\t\tblockers: [],\n\t\t\tblocks: [offlineAsset.offline_id],\n\t\t})\n\t\treturn [offlineAsset, promise]\n\t}\n\n\tupdate(asset: Asset, workspaceId: string): OptimisticModelResult<Asset> {\n\t\tif (!asset.canvas_marker && !asset.geo_marker) {\n\t\t\tthrow new Error(\"Asset must have either a canvas_marker or geo_marker\")\n\t\t}\n\n\t\tthis.client.store.dispatch(updateAsset(asset))\n\t\tconst promise = this.enqueueRequest<Asset>({\n\t\t\tdescription: \"Edit asset\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/assets/${asset.offline_id}/`,\n\t\t\tqueryParams: {\n\t\t\t\tworkspace_id: workspaceId.toString(),\n\t\t\t},\n\t\t\tpayload: asset,\n\t\t\tblockers: [asset.offline_id],\n\t\t\tblocks: [asset.offline_id],\n\t\t})\n\t\treturn [asset, promise]\n\t}\n\tasync remove(assetId: string): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\t\tconst assetToBeDeleted = selectAssetById(assetId)(state)\n\n\t\tif (!assetToBeDeleted) throw new Error(`No asset with id ${assetId} found in the store`)\n\n\t\tconst attachmentsOfAssets = selectAttachmentsOfAsset(assetId)(state)\n\t\tconst formSubmissionsOfAssets = selectFormSubmissionsOfAsset(assetId)(state)\n\t\tconst issueAssociations = selectIssueAssociationsOfAsset(assetId)(state)\n\n\t\tthis.dispatch(deleteAsset(assetId))\n\n\t\t// remove any attachments of asset from the store\n\t\tif (attachmentsOfAssets.length > 0) {\n\t\t\tconst attachmentsOfAssetIds = attachmentsOfAssets.map(({ offline_id }) => offline_id)\n\t\t\tthis.dispatch(deleteAssetAttachments(attachmentsOfAssetIds))\n\t\t}\n\n\t\t// remove any form submissions of asset from the store\n\t\tif (formSubmissionsOfAssets.length > 0) {\n\t\t\tconst formSubmissionsOfAssetIds = formSubmissionsOfAssets.map(({ offline_id }) => offline_id)\n\t\t\tthis.dispatch(deleteFormSubmissions(formSubmissionsOfAssetIds))\n\t\t}\n\n\t\tif (issueAssociations.length > 0) {\n\t\t\tconst issueAssociationsIds = issueAssociations.map(({ offline_id }) => offline_id)\n\t\t\tthis.dispatch(deleteIssueAssociations(issueAssociationsIds))\n\t\t}\n\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Delete asset\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/assets/${assetId}/`,\n\t\t\tblockers: [assetId],\n\t\t\tblocks: [],\n\t\t}).catch((err) => {\n\t\t\tthis.dispatch(addAsset(assetToBeDeleted))\n\t\t\tthis.dispatch(addAssetAttachments(attachmentsOfAssets))\n\t\t\tthis.dispatch(addFormSubmissions(formSubmissionsOfAssets))\n\t\t\tthis.dispatch(addIssueAssociations(issueAssociations))\n\t\t\tthrow err\n\t\t})\n\t}\n\tasync deleteAllAssetsOfAssetType(assetTypeId: string): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst state: OvermapRootState = store.getState()\n\n\t\tconst allAssetsOfAssetType = selectAssetsOfAssetType(assetTypeId)(state)\n\t\tconst allAssetsOfAssetTypeIds = allAssetsOfAssetType.map((c) => c.offline_id)\n\t\tconst affectedOfflineIds = [assetTypeId, ...allAssetsOfAssetTypeIds]\n\n\t\tstore.dispatch(deleteAssets(allAssetsOfAssetTypeIds))\n\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Delete all assets of asset type\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/assets/types/${assetTypeId}/delete-all-of-type/`,\n\t\t\tblockers: affectedOfflineIds,\n\t\t\tblocks: affectedOfflineIds,\n\t\t}).catch((err) => {\n\t\t\t// If the request fails, we need to add the assets back to the store\n\t\t\tstore.dispatch(addAssets(allAssetsOfAssetType))\n\t\t\tthrow err\n\t\t})\n\t}\n\n\t// TODO: payload does not require asset_type\n\tbulkAdd(\n\t\tassetsToCreate: Payload<Asset>[],\n\t\tworkspaceId: string,\n\t\tassetTypeId: string,\n\t\t// TODO: should we validate this?\n\t\tbatchSize: number,\n\t): Promise<Created<Asset>[]>[] {\n\t\tconst { store } = this.client\n\n\t\tinterface BulkAddAssetPayload {\n\t\t\ttransaction_id: string\n\t\t\tassets: Submitted<Asset>[]\n\t\t\t// TODO: uncommnent when endpoint is refactored\n\t\t\t// submitted_at: string\n\t\t}\n\n\t\tinterface BulkAddAssetBatch {\n\t\t\tbatchId: string\n\t\t\tpayload: BulkAddAssetPayload\n\t\t}\n\n\t\tconst submittedAt = new Date().toISOString()\n\t\tconst transactionId = uuidv4()\n\n\t\tconst assetBatches: BulkAddAssetBatch[] = chunkArray(assetsToCreate, batchSize).map((assetBatch) => {\n\t\t\tconst assetPayloads: Submitted<Asset>[] = assetBatch.map((assetPayload) => {\n\t\t\t\treturn offline({\n\t\t\t\t\t...assetPayload,\n\t\t\t\t\tsubmitted_at: submittedAt,\n\t\t\t\t})\n\t\t\t})\n\n\t\t\treturn {\n\t\t\t\tbatchId: uuidv4(),\n\t\t\t\tpayload: {\n\t\t\t\t\ttransaction_id: transactionId,\n\t\t\t\t\tassets: assetPayloads,\n\t\t\t\t},\n\t\t\t}\n\t\t})\n\n\t\tconst batchPromises: Promise<Created<Asset>[]>[] = []\n\t\tlet prevBatchId: string | null = null\n\n\t\tfor (const assetBatch of assetBatches) {\n\t\t\tconst { batchId, payload } = assetBatch\n\n\t\t\tconst batchAssetOfflineIds = payload.assets.map((c) => c.offline_id)\n\n\t\t\tconst blockers = [assetTypeId]\n\t\t\tif (prevBatchId) blockers.push(prevBatchId)\n\n\t\t\tconst blocks = batchAssetOfflineIds\n\t\t\tblocks.push(batchId)\n\n\t\t\tconst promise = this.enqueueRequest<Created<Asset>[]>({\n\t\t\t\tdescription: \"Batch create assets\",\n\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\turl: `/assets/types/${assetTypeId}/add-assets/`,\n\t\t\t\tqueryParams: {\n\t\t\t\t\tworkspace_id: workspaceId.toString(),\n\t\t\t\t},\n\t\t\t\tpayload: payload,\n\t\t\t\tblockers: blockers,\n\t\t\t\tblocks: blocks,\n\t\t\t})\n\n\t\t\tprevBatchId = assetBatch.batchId\n\n\t\t\tbatchPromises.push(promise)\n\t\t}\n\n\t\tvoid Promise.all(batchPromises).then((result) => {\n\t\t\tconst allCreatedAssets = result.flat()\n\t\t\tstore.dispatch(addAssets(allCreatedAssets))\n\t\t})\n\n\t\treturn batchPromises\n\t}\n\n\tasync refreshStore(projectId: number): Promise<void> {\n\t\tconst result = await this.enqueueRequest<Asset[]>({\n\t\t\tdescription: \"Get assets\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/assets/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t\tthis.dispatch(initializeAssets(result))\n\t}\n}\n","import { addStageCompletion, addStageCompletions, removeStageCompletions, selectAssetById } from \"../../store\"\nimport { OptimisticModelResult } from \"../typings\"\nimport { offline } from \"../../utils\"\nimport { HttpMethod } from \"../../enums\"\nimport { AssetStageCompletion, CompletedStagesMapping, Created, OvermapRootState, Payload } from \"../../typings\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class AssetStageCompletionService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tadd(assetId: string, stageId: string): OptimisticModelResult<AssetStageCompletion> {\n\t\tconst { store } = this.client\n\t\tconst assetTypeId = selectAssetById(assetId)(store.getState())?.asset_type\n\n\t\tif (!assetTypeId) {\n\t\t\tthrow new Error(`Asset with offline_id ${assetId} not found`)\n\t\t}\n\n\t\tconst offlineStageCompletion = offline({\n\t\t\tasset: assetId,\n\t\t\tstage: stageId,\n\t\t})\n\n\t\tthis.dispatch(addStageCompletion(offlineStageCompletion))\n\n\t\tconst promise = this.enqueueRequest<Created<AssetStageCompletion>>({\n\t\t\tdescription: \"Complete stage\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/assets/types/${assetTypeId}/complete-stages/`,\n\t\t\t// TODO: Add submitted_at to model\n\t\t\tpayload: { completions: [{ ...offlineStageCompletion, submitted_at: new Date().getTime() / 1000 }] },\n\t\t\tblockers: [assetId, stageId],\n\t\t\tblocks: [offlineStageCompletion.offline_id],\n\t\t})\n\n\t\treturn [offlineStageCompletion, promise]\n\t}\n\tasync refreshStore(projectId: number): Promise<void> {\n\t\tconst result = await this.enqueueRequest<CompletedStagesMapping>({\n\t\t\tdescription: \"Get stage completions\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/asset-stage-completions/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t\tthis.dispatch(addStageCompletions(result))\n\t}\n\n\t/**\n\t * Creates a collection of AssetStageCompletions, marking the referenced stages as completed for the referenced\n\t * assets. It's REQUIRED that all assets referenced all have the SAME asset type.\n\t * @param assetTypeId The ID of the asset type for which we are completing stages (we can only complete\n\t * stages for one asset type at a time)\n\t * @param stageCompletions\n\t */\n\tasync bulkAdd(assetTypeId: string, stageCompletions: Payload<AssetStageCompletion>[]) {\n\t\tconst offlineStageCompletions = stageCompletions.map((completion) => {\n\t\t\treturn offline(completion)\n\t\t})\n\t\tconst asMapping: CompletedStagesMapping = {}\n\t\tfor (const completion of stageCompletions) {\n\t\t\tconst stageToCompletionDateMapping = asMapping[completion.asset] || {}\n\t\t\tstageToCompletionDateMapping[completion.stage] = new Date().toISOString()\n\t\t\tasMapping[completion.asset] = stageToCompletionDateMapping\n\t\t}\n\t\tthis.dispatch(addStageCompletions(asMapping))\n\t\tawait this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Bulk complete stages\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/assets/types/${assetTypeId}/complete-stages/`,\n\t\t\tpayload: {\n\t\t\t\tcompletions: offlineStageCompletions,\n\t\t\t},\n\t\t\tblockers: [assetTypeId, ...stageCompletions.map((c) => c.asset), ...stageCompletions.map((c) => c.stage)],\n\t\t\tblocks: offlineStageCompletions.map((c) => c.offline_id),\n\t\t})\n\t}\n\tbulkDelete(stageId: string, assetIds: string[]): Promise<undefined> {\n\t\tconst stageCompletionsToRemove: AssetStageCompletion[] = assetIds.map((assetId) => {\n\t\t\treturn {\n\t\t\t\tasset: assetId,\n\t\t\t\tstage: stageId,\n\t\t\t}\n\t\t})\n\t\tthis.dispatch(removeStageCompletions(stageCompletionsToRemove))\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: `Undo stage for ${assetIds.length} assets(s)`,\n\t\t\t// TODO: Rename to setCompletedStages\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/assets/stages/${stageId}/undo-stages/`,\n\t\t\tpayload: {\n\t\t\t\tassets: assetIds,\n\t\t\t},\n\t\t\tblockers: [stageId, ...assetIds],\n\t\t\tblocks: [],\n\t\t})\n\t}\n}\n","import { AssetStage, AssetStagePayload, OvermapRootState, Payload } from \"../../typings\"\nimport { offline } from \"../../utils\"\nimport { HttpMethod } from \"../../enums\"\nimport {\n\taddStages,\n\tremoveStages,\n\tselectAssetStagesByIds,\n\tupdateStages,\n\tupdateStage,\n\tsetStage,\n\tinitializeStages,\n} from \"../../store\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class AssetStageService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tasync bulkCreateStages(\n\t\tstagesToSubmit: Payload<AssetStagePayload>[],\n\t\tassetTypeId: string,\n\t\tworkspaceId: string,\n\t): Promise<AssetStage[]> {\n\t\tconst payload: AssetStagePayload[] = stagesToSubmit.map((stage) => {\n\t\t\treturn offline(stage)\n\t\t})\n\t\tconst fullStages: AssetStage[] = payload.map((stage) => {\n\t\t\treturn { ...stage, asset_type: assetTypeId }\n\t\t})\n\t\tthis.dispatch(addStages(fullStages))\n\t\treturn this.enqueueRequest<AssetStage[]>({\n\t\t\tdescription: \"Add asset stages\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/assets/types/${assetTypeId}/add-stages/`,\n\t\t\tpayload: {\n\t\t\t\tstages: payload,\n\t\t\t},\n\t\t\tqueryParams: {\n\t\t\t\tworkspace_id: workspaceId.toString(),\n\t\t\t},\n\t\t\tblockers: [assetTypeId, workspaceId],\n\t\t\tblocks: payload.map(({ offline_id }) => offline_id),\n\t\t})\n\t}\n\n\tasync bulkUpdateStages(stagesToUpdate: AssetStage[], assetTypeId: string): Promise<AssetStage[]> {\n\t\tconst store = this.client.store\n\t\tconst state = store.getState()\n\t\tconst prevStages = selectAssetStagesByIds(stagesToUpdate.map(({ offline_id }) => offline_id))(state)\n\n\t\tthis.dispatch(updateStages(stagesToUpdate))\n\n\t\treturn this.enqueueRequest<AssetStage[]>({\n\t\t\tdescription: \"Edit asset stages\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/assets/types/${assetTypeId}/bulk-update-stages/`,\n\t\t\tpayload: {\n\t\t\t\tstages: stagesToUpdate,\n\t\t\t},\n\t\t\tblockers: [assetTypeId],\n\t\t\tblocks: stagesToUpdate.map(({ offline_id }) => offline_id),\n\t\t}).catch((e) => {\n\t\t\t// restore stages in store if request fails\n\t\t\tstore.dispatch(updateStages(prevStages))\n\t\t\tthrow e\n\t\t})\n\t}\n\n\tasync bulkDelete(idsToDelete: string[]): Promise<undefined> {\n\t\tthis.dispatch(removeStages(idsToDelete))\n\t\treturn this.enqueueRequest({\n\t\t\tdescription: \"Delete asset stages\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: \"/assets/stages/bulk-delete/\",\n\t\t\tpayload: {\n\t\t\t\tstage_ids: idsToDelete,\n\t\t\t},\n\t\t\tblockers: idsToDelete,\n\t\t\tblocks: [],\n\t\t})\n\t}\n\n\tasync update(assetStage: AssetStage): Promise<undefined> {\n\t\tthis.dispatch(addStages([assetStage]))\n\t\treturn this.enqueueRequest({\n\t\t\tdescription: \"Update asset stage\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/assets/stages/${assetStage.offline_id}/`,\n\t\t\tpayload: assetStage,\n\t\t\tblockers: [assetStage.offline_id],\n\t\t\tblocks: [assetStage.offline_id],\n\t\t})\n\t}\n\n\tasync linkForm(stageId: string, formId: string): Promise<undefined> {\n\t\tconst { store } = this.client\n\n\t\tconst stage = store.getState().assetStageReducer.instances[stageId]\n\n\t\tif (!stage) {\n\t\t\tthrow new Error(`No asset stage with id ${stageId} found in the store`)\n\t\t}\n\n\t\tthis.dispatch(updateStage({ ...stage, form: formId }))\n\t\ttry {\n\t\t\tawait this.enqueueRequest({\n\t\t\t\tdescription: \"Link asset stage to form\",\n\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\turl: `/assets/stages/${stageId}/associate-with-form/`,\n\t\t\t\tpayload: { form: formId },\n\t\t\t\tblockers: [stageId, formId],\n\t\t\t\tblocks: [stageId],\n\t\t\t})\n\t\t} catch (e) {\n\t\t\tthis.dispatch(setStage(stage))\n\t\t\tthrow e\n\t\t}\n\t}\n\n\tasync unlinkForm(stageId: string, formId: string): Promise<undefined> {\n\t\tconst { store } = this.client\n\n\t\tconst stage = store.getState().assetStageReducer.instances[stageId]\n\n\t\tif (!stage) {\n\t\t\tthrow new Error(`No asset stage with id ${stageId} found in the store`)\n\t\t}\n\n\t\tthis.dispatch(updateStage({ ...stage, form: undefined }))\n\n\t\ttry {\n\t\t\tawait this.enqueueRequest({\n\t\t\t\tdescription: \"Unlink asset stage from form\",\n\t\t\t\tmethod: HttpMethod.DELETE,\n\t\t\t\turl: `/assets/stages/${stageId}/associate-with-form/`,\n\t\t\t\tblockers: [stageId, formId],\n\t\t\t\tblocks: [stageId],\n\t\t\t})\n\t\t} catch (e) {\n\t\t\tthis.dispatch(setStage(stage))\n\t\t\tthrow e\n\t\t}\n\t}\n\n\tasync refreshStore(projectId: number): Promise<undefined> {\n\t\tconst result = await this.enqueueRequest<AssetStage[]>({\n\t\t\tdescription: \"Get asset stages\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/asset-stages/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t\tthis.dispatch(initializeStages(result))\n\t}\n}\n","import { BaseApiService } from \"./BaseApiService\"\nimport { HttpMethod } from \"../../enums\"\nimport { PresignedUrlsResponse, SDKRequest } from \"../typings\"\nimport { OvermapRootState } from \"../../typings\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class BaseUploadService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tprotected getNumberOfAttachmentsWithSha1(sha1: string) {\n\t\tconst {\n\t\t\tissueAttachmentReducer,\n\t\t\tassetAttachmentReducer,\n\t\t\tassetTypeAttachmentReducer,\n\t\t\tdocumentAttachmentReducer,\n\t\t\tprojectAttachmentReducer,\n\t\t\tformRevisionAttachmentReducer,\n\t\t\tformSubmissionAttachmentReducer,\n\t\t\tgeoImageReducer,\n\t\t} = this.client.store.getState()\n\n\t\t// creating an array of objects with the file_sha1 property\n\t\t// TODO: @Audiopolis, probably makes sense to also include projectFiles in here?\n\t\tconst objectsWithSha1: { file_sha1: string }[] = ([] as { file_sha1: string }[]).concat(\n\t\t\tObject.values(issueAttachmentReducer.instances),\n\t\t\tObject.values(assetAttachmentReducer.instances),\n\t\t\tObject.values(assetTypeAttachmentReducer.instances),\n\t\t\tObject.values(documentAttachmentReducer.instances),\n\t\t\tObject.values(projectAttachmentReducer.instances),\n\t\t\tObject.values(formRevisionAttachmentReducer.instances),\n\t\t\tObject.values(formSubmissionAttachmentReducer.instances),\n\t\t\tObject.values(geoImageReducer.instances),\n\t\t)\n\n\t\treturn objectsWithSha1.filter((object) => object.file_sha1 === sha1).length\n\t}\n\n\tprotected processPresignedUrls(presignedUrls: PresignedUrlsResponse) {\n\t\tfor (const [sha1, presignedUrl] of Object.entries(presignedUrls)) {\n\t\t\tvoid this.enqueueRequest<undefined>({\n\t\t\t\turl: presignedUrl.url,\n\t\t\t\tdescription: \"Upload file to S3\",\n\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\tisExternalUrl: true,\n\t\t\t\tisAuthNeeded: false,\n\t\t\t\tattachmentHash: sha1,\n\t\t\t\t// TODO: can we use the sha1 as the blocker?\n\t\t\t\tblockers: [`s3-${presignedUrl.fields.key}`],\n\t\t\t\tblocks: [sha1],\n\t\t\t\ts3url: presignedUrl,\n\t\t\t} satisfies SDKRequest)\n\t\t}\n\t}\n}\n","import { ActionCreatorWithPayload } from \"@reduxjs/toolkit\"\nimport { OptimisticMultipleModelResult, PresignedUrlsResponse } from \"../typings\"\nimport { HttpMethod } from \"../../enums\"\nimport {\n\tAttachment,\n\tAttachmentModel,\n\tCreated,\n\tOfflineModel,\n\tOvermapRootState,\n\tOvermapSelectorWithArgs,\n\tStored,\n\tSubmitted,\n} from \"../../typings\"\nimport { hashFile } from \"../../utils\"\nimport type { BaseSDK } from \"../base\"\nimport { BaseUploadService } from \"./BaseUploadService\"\n\ninterface AttachmentPayload {\n\toffline_id: OfflineModel[\"offline_id\"]\n\tname: Attachment[\"file_name\"]\n\tsha1: Attachment[\"file_sha1\"]\n\tdescription: Attachment[\"description\"]\n}\n\nexport interface FilePayload {\n\tsha1: Attachment[\"file_sha1\"]\n\tfile_type: string\n\textension: string\n\tsize: number\n}\n\nexport interface BuildOfflineAttachmentData<TModelId> {\n\tfile: File\n\t// passing sha1 here so dont have to hash multiple times\n\tsha1: string\n\tsubmittedAt: string\n\tcreatedBy: number\n\tdescription?: string\n\t// this the offline_id passed in from the attachFiles method\n\tmodelId: TModelId\n}\n\nconst AttachmentModelMeta: Record<\n\tAttachmentModel,\n\t{ attachUrlPrefix: string; deleteUrlPrefix: string; name: string; fetchUrlPostfix: string }\n> = {\n\t[AttachmentModel.Issue]: {\n\t\tname: \"issue\",\n\t\tattachUrlPrefix: \"/issues\",\n\t\tdeleteUrlPrefix: \"/issues\",\n\t\tfetchUrlPostfix: \"/issue-attachments\",\n\t},\n\t[AttachmentModel.Asset]: {\n\t\tname: \"asset\",\n\t\tattachUrlPrefix: \"/assets\",\n\t\tdeleteUrlPrefix: \"/assets\",\n\t\tfetchUrlPostfix: \"/asset-attachments\",\n\t},\n\t[AttachmentModel.AssetType]: {\n\t\tname: \"asset type\",\n\t\tattachUrlPrefix: \"/assets/types\",\n\t\tdeleteUrlPrefix: \"/assets/types\",\n\t\tfetchUrlPostfix: \"/asset-type-attachments\",\n\t},\n\t[AttachmentModel.Project]: {\n\t\tname: \"project\",\n\t\tattachUrlPrefix: \"/projects\",\n\t\tdeleteUrlPrefix: \"/projects\",\n\t\tfetchUrlPostfix: \"/attachments\",\n\t},\n\t[AttachmentModel.Document]: {\n\t\tname: \"document\",\n\t\tattachUrlPrefix: \"/documents\",\n\t\tdeleteUrlPrefix: \"/documents\",\n\t\tfetchUrlPostfix: \"/document-attachments\",\n\t},\n}\n\nexport abstract class BaseAttachmentService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n\tTModelId extends string | number,\n\tTAttachment extends Attachment,\n> extends BaseUploadService<TState, TSDK> {\n\tabstract readonly attachmentModel: AttachmentModel\n\n\t// redux actions\n\tabstract readonly initializeAttachments: ActionCreatorWithPayload<Submitted<TAttachment>[]>\n\tabstract readonly addAttachments: ActionCreatorWithPayload<Submitted<TAttachment>[]>\n\tabstract readonly updateAttachments: ActionCreatorWithPayload<Submitted<TAttachment>[]>\n\tabstract readonly removeAttachments: ActionCreatorWithPayload<string[]>\n\tabstract readonly setAttachment: ActionCreatorWithPayload<Stored<TAttachment>>\n\tabstract readonly removeAttachment: ActionCreatorWithPayload<string>\n\n\t// redux selectors\n\tabstract readonly selectAttachment: OvermapSelectorWithArgs<string, Stored<TAttachment> | undefined>\n\n\tprotected async attachFiles(\n\t\tfiles: File[],\n\t\tmodelId: TModelId,\n\t\tbuildOfflineAttachment: (data: BuildOfflineAttachmentData<TModelId>) => Stored<TAttachment>,\n\t): Promise<OptimisticMultipleModelResult<TAttachment>> {\n\t\tconst { store } = this.client\n\n\t\tconst currentUser = store.getState().userReducer.currentUser\n\t\tconst submittedAt = new Date().toISOString()\n\n\t\tconst offlineAttachments: Stored<TAttachment>[] = []\n\t\tconst attachmentPayloads: AttachmentPayload[] = []\n\t\tconst filePayloads: Record<FilePayload[\"sha1\"], FilePayload> = {}\n\n\t\tfor (const file of files) {\n\t\t\t// has file once\n\t\t\tconst sha1 = await hashFile(file)\n\n\t\t\t// if the file is already being uploaded, skip it\n\t\t\tif (!(sha1 in filePayloads)) {\n\t\t\t\tfilePayloads[sha1] = {\n\t\t\t\t\tsha1,\n\t\t\t\t\tfile_type: file.type,\n\t\t\t\t\textension: file.name.split(\".\").pop()!,\n\t\t\t\t\tsize: file.size,\n\t\t\t\t}\n\t\t\t\tawait this.client.files.addCache(file, sha1)\n\t\t\t}\n\n\t\t\t// construct offline attachment\n\t\t\tconst offlineAttachment = buildOfflineAttachment({\n\t\t\t\tfile,\n\t\t\t\tsha1,\n\t\t\t\tsubmittedAt,\n\t\t\t\tcreatedBy: currentUser.id,\n\t\t\t\tdescription: \"\",\n\t\t\t\tmodelId: modelId,\n\t\t\t})\n\t\t\tofflineAttachments.push(offlineAttachment)\n\n\t\t\t// construct attachment payload\n\t\t\tattachmentPayloads.push({\n\t\t\t\toffline_id: offlineAttachment.offline_id,\n\t\t\t\tname: offlineAttachment.file_name,\n\t\t\t\tsha1: offlineAttachment.file_sha1,\n\t\t\t\tdescription: offlineAttachment.description,\n\t\t\t})\n\t\t}\n\n\t\tthis.dispatch(this.addAttachments(offlineAttachments))\n\n\t\tconst meta = AttachmentModelMeta[this.attachmentModel]\n\n\t\tconst promise = this.enqueueRequest<{\n\t\t\tattachments: Created<TAttachment>[]\n\t\t\tpresigned_urls: PresignedUrlsResponse\n\t\t}>({\n\t\t\tdescription: `Attach files to ${meta.name}`,\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `${meta.attachUrlPrefix}/${modelId}/attach/`,\n\t\t\tpayload: {\n\t\t\t\tsubmitted_at: submittedAt,\n\t\t\t\tattachments: attachmentPayloads,\n\t\t\t\tfiles: Object.values(filePayloads),\n\t\t\t},\n\t\t\tblocks: offlineAttachments.map((attachment) => attachment.offline_id),\n\t\t\tblockers: offlineAttachments.map((attachment) => attachment.file_sha1),\n\t\t})\n\n\t\tpromise\n\t\t\t.then(({ attachments, presigned_urls }) => {\n\t\t\t\tthis.dispatch(this.updateAttachments(attachments))\n\t\t\t\tthis.processPresignedUrls(presigned_urls)\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(this.removeAttachments(offlineAttachments.map((attachment) => attachment.offline_id)))\n\t\t\t})\n\n\t\treturn [offlineAttachments, promise.then(({ attachments }) => attachments)]\n\t}\n\n\tprotected async deleteAttachment(attachmendId: string): Promise<void> {\n\t\tconst { store } = this.client\n\t\tconst attachment = this.selectAttachment(attachmendId)(store.getState())\n\n\t\tif (!attachment) {\n\t\t\tthrow new Error(\n\t\t\t\t`Attempting to delete attachment with offline_id ${attachmendId} that does not exist in the store`,\n\t\t\t)\n\t\t}\n\n\t\tthis.dispatch(this.removeAttachment(attachment.offline_id))\n\n\t\tconst meta = AttachmentModelMeta[this.attachmentModel]\n\n\t\tconst promise = this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Delete attachment\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `${meta.deleteUrlPrefix}/attachments/${attachmendId}/`,\n\t\t\tblockers: [attachmendId],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tpromise\n\t\t\t.then(() => {\n\t\t\t\tif (this.getNumberOfAttachmentsWithSha1(attachment.file_sha1) === 0) {\n\t\t\t\t\tvoid this.client.files.removeCache(attachment.file_sha1)\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(this.setAttachment(attachment))\n\t\t\t})\n\n\t\treturn promise\n\t}\n\n\t// Note that currently the fetching of attachments for all models dependds on the active projectId. This may change in the future. And\n\t// so for some attachment model services, this method will have to be overridden.\n\tasync refreshStore(projectId: number, _organizationId?: number): Promise<void> {\n\t\tconst meta = AttachmentModelMeta[this.attachmentModel]\n\n\t\tconst result = await this.enqueueRequest<Created<TAttachment>[]>({\n\t\t\tdescription: `Get ${meta.name} attachments`,\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}${meta.fetchUrlPostfix}/`,\n\t\t\tblocks: [],\n\t\t\tblockers: [],\n\t\t})\n\n\t\tthis.dispatch(this.initializeAttachments(result))\n\t}\n}\n","import { BaseAttachmentService, BuildOfflineAttachmentData } from \"./BaseAttachmentService\"\nimport { AttachmentModel, AssetAttachment, Stored, OvermapRootState } from \"../../typings\"\nimport { offline } from \"../../utils\"\nimport { OptimisticMultipleModelResult } from \"../typings\"\nimport {\n\taddAssetAttachments,\n\tdeleteAssetAttachments,\n\tdeleteAssetAttachment,\n\tselectAssetAttachment,\n\tsetAssetAttachment,\n\tupdateAssetAttachments,\n\tinitializeAssetAttachments,\n} from \"../../store\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class AssetAttachmentService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseAttachmentService<TState, TSDK, string, AssetAttachment> {\n\tattachmentModel = AttachmentModel.Asset\n\n\tinitializeAttachments = initializeAssetAttachments\n\taddAttachments = addAssetAttachments\n\tupdateAttachments = updateAssetAttachments\n\tremoveAttachments = deleteAssetAttachments\n\tremoveAttachment = deleteAssetAttachment\n\tsetAttachment = setAssetAttachment\n\n\tselectAttachment = selectAssetAttachment\n\n\tprivate buildOfflineAttachment(data: BuildOfflineAttachmentData<string>) {\n\t\treturn offline({\n\t\t\tfile: URL.createObjectURL(data.file),\n\t\t\tfile_sha1: data.sha1,\n\t\t\tcreated_by: data.createdBy,\n\t\t\tfile_name: data.file.name,\n\t\t\tfile_type: data.file.type,\n\t\t\tsubmitted_at: data.submittedAt,\n\t\t\tdescription: data.description,\n\t\t\tasset: data.modelId,\n\t\t}) satisfies Stored<AssetAttachment>\n\t}\n\n\tasync attachFilesToAsset(files: File[], assetId: string): Promise<OptimisticMultipleModelResult<AssetAttachment>> {\n\t\treturn this.attachFiles(files, assetId, this.buildOfflineAttachment.bind(this))\n\t}\n\n\tasync deleteAssetAttachment(attachmentId: string): Promise<void> {\n\t\treturn this.deleteAttachment(attachmentId)\n\t}\n}\n","import { offline } from \"../../utils\"\nimport {\n\taddAssetType,\n\taddAssetTypeAttachments,\n\taddStages,\n\tdeleteAssetType,\n\tdeleteAssetTypeAttachments,\n\tinitializeAssetTypes,\n\tremoveStages,\n\tselectAssetTypeById,\n\tselectAttachmentsOfAssetType,\n\tselectStagesOfAssetType,\n} from \"../../store\"\nimport { AssetStage, AssetType, OvermapRootState, Payload } from \"../../typings\"\nimport { HttpMethod } from \"../../enums\"\nimport { OptimisticModelResult } from \"../typings\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class AssetTypeService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tadd(assetType: Payload<AssetType>): OptimisticModelResult<AssetType> {\n\t\tconst offlineAssetType = offline(assetType)\n\t\tconst { store } = this.client\n\t\tconst activeProjectId = store.getState().projectReducer.activeProjectId\n\n\t\tthis.dispatch(addAssetType(offlineAssetType))\n\t\tconst promise = this.enqueueRequest<AssetType>({\n\t\t\tdescription: \"Create asset type\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/projects/${activeProjectId}/asset-types/`,\n\t\t\tpayload: { ...offlineAssetType },\n\t\t\tblockers: [],\n\t\t\tblocks: [offlineAssetType.offline_id],\n\t\t})\n\t\treturn [offlineAssetType, promise]\n\t}\n\n\tupdate(assetType: AssetType): Promise<undefined> {\n\t\tthis.dispatch(addAssetType(assetType))\n\t\treturn this.enqueueRequest({\n\t\t\tdescription: \"Update asset type\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/assets/types/${assetType.offline_id}/`,\n\t\t\tpayload: assetType,\n\t\t\tblockers: [assetType.offline_id],\n\t\t\tblocks: [assetType.offline_id],\n\t\t})\n\t}\n\n\tasync delete(assetTypeId: string): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\t\t// Get asset Stages in state associated with asset type to be deleted\n\t\tconst assetType = selectAssetTypeById(assetTypeId)(state)\n\t\tif (!assetType) {\n\t\t\tthrow new Error(`Expected asset type with offline_id ${assetTypeId} to exist`)\n\t\t}\n\t\tconst stagesOfAssetType = selectStagesOfAssetType(assetTypeId)(state)\n\t\tconst attachmentsOfAssetType = selectAttachmentsOfAssetType(assetTypeId)(state)\n\n\t\tthis.dispatch(deleteAssetType(assetTypeId))\n\n\t\t// If any asset type stages, remove them from the store\n\t\tif (stagesOfAssetType.length > 0) {\n\t\t\tconst stagesOfAssetTypeIds = stagesOfAssetType.map((assetStage: AssetStage) => assetStage.offline_id)\n\t\t\tthis.dispatch(removeStages(stagesOfAssetTypeIds))\n\t\t}\n\n\t\t// If any attachments to the asset type, remove them from the store\n\t\tif (attachmentsOfAssetType.length > 0) {\n\t\t\t// TODO: Figure out when we actually delete these attachments from the database, not just removing them from the store\n\t\t\tconst attachmentsOfAssetTypeIds = attachmentsOfAssetType.map(({ offline_id }) => offline_id)\n\t\t\tthis.dispatch(deleteAssetTypeAttachments(attachmentsOfAssetTypeIds))\n\t\t}\n\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Delete asset type\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/assets/types/${assetTypeId}/`,\n\t\t\tblockers: [assetTypeId],\n\t\t\tblocks: [],\n\t\t}).catch((e) => {\n\t\t\tthis.dispatch(addAssetType(assetType))\n\t\t\tthis.dispatch(addStages(stagesOfAssetType))\n\t\t\tthis.dispatch(addAssetTypeAttachments(attachmentsOfAssetType))\n\t\t\tthrow e\n\t\t})\n\t}\n\n\tasync refreshStore(projectId: number): Promise<void> {\n\t\tconst result = await this.enqueueRequest<AssetType[]>({\n\t\t\tdescription: \"Get asset types\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/asset-types/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t\tthis.dispatch(initializeAssetTypes(result))\n\t}\n}\n","import { BaseAttachmentService, BuildOfflineAttachmentData } from \"./BaseAttachmentService\"\nimport {\n\taddAssetTypeAttachments,\n\tdeleteAssetTypeAttachments,\n\tdeleteAssetTypeAttachment,\n\tselectAssetTypeAttachment,\n\tsetAssetTypeAttachment,\n\tupdateAssetTypeAttachments,\n\tinitializeAssetTypeAttachments,\n} from \"../../store\"\nimport { AttachmentModel, AssetTypeAttachment, Stored, OvermapRootState } from \"../../typings\"\nimport { offline } from \"../../utils\"\nimport { OptimisticMultipleModelResult } from \"../typings\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class AssetTypeAttachmentService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseAttachmentService<TState, TSDK, string, AssetTypeAttachment> {\n\tattachmentModel = AttachmentModel.AssetType\n\n\tinitializeAttachments = initializeAssetTypeAttachments\n\taddAttachments = addAssetTypeAttachments\n\tupdateAttachments = updateAssetTypeAttachments\n\tremoveAttachments = deleteAssetTypeAttachments\n\tremoveAttachment = deleteAssetTypeAttachment\n\tsetAttachment = setAssetTypeAttachment\n\n\tselectAttachment = selectAssetTypeAttachment\n\n\tprivate buildOfflineAttachment(data: BuildOfflineAttachmentData<string>) {\n\t\treturn offline({\n\t\t\tfile: URL.createObjectURL(data.file),\n\t\t\tfile_sha1: data.sha1,\n\t\t\tcreated_by: data.createdBy,\n\t\t\tfile_name: data.file.name,\n\t\t\tfile_type: data.file.type,\n\t\t\tsubmitted_at: data.submittedAt,\n\t\t\tdescription: data.description,\n\t\t\tasset_type: data.modelId,\n\t\t}) satisfies Stored<AssetTypeAttachment>\n\t}\n\n\tasync attachFilesToAssetType(\n\t\tfiles: File[],\n\t\tassetTypeId: string,\n\t): Promise<OptimisticMultipleModelResult<AssetTypeAttachment>> {\n\t\treturn this.attachFiles(files, assetTypeId, this.buildOfflineAttachment.bind(this))\n\t}\n\n\tasync deleteAssetTypeAttachment(attachmentId: string): Promise<void> {\n\t\treturn this.deleteAttachment(attachmentId)\n\t}\n}\n","import { Created, IssueComment, OvermapRootState, Payload, Submitted } from \"../../typings\"\nimport { offline, truncate } from \"../../utils\"\nimport { HttpMethod } from \"../../enums\"\nimport { addIssueComment, deleteIssueComment, setIssueComment, setIssueComments } from \"../../store\"\nimport { OptimisticModelResult } from \"../typings\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class IssueCommentService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\t// Omit author and submitted_at since these will always be set internally\n\tadd(comment: Omit<Payload<IssueComment>, \"author\" | \"submitted_at\">): OptimisticModelResult<IssueComment> {\n\t\tconst { store } = this.client\n\n\t\tconst offlineComment: Submitted<IssueComment> = offline({\n\t\t\t...comment,\n\t\t\tauthor: store.getState().userReducer.currentUser.id,\n\t\t\tsubmitted_at: new Date().toISOString(),\n\t\t})\n\n\t\tthis.dispatch(addIssueComment(offlineComment))\n\n\t\tconst promise = this.enqueueRequest<Created<IssueComment>>({\n\t\t\tdescription: `${truncate(comment.content, 80)}`,\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/issues/${comment.issue}/comment/`,\n\t\t\tpayload: offlineComment,\n\t\t\tblockers: [comment.issue],\n\t\t\tblocks: [offlineComment.offline_id],\n\t\t})\n\n\t\tpromise.catch(() => {\n\t\t\tthis.dispatch(deleteIssueComment(offlineComment.offline_id))\n\t\t})\n\n\t\treturn [offlineComment, promise]\n\t}\n\n\tupdate(comment: Submitted<IssueComment>): OptimisticModelResult<IssueComment> {\n\t\tconst { store } = this.client\n\n\t\tconst commentToUpdate = store.getState().issueCommentReducer.instances[comment.offline_id]\n\t\tif (!commentToUpdate) {\n\t\t\tthrow new Error(`Comment with offline_id ${comment.offline_id} not found in store`)\n\t\t}\n\n\t\tthis.dispatch(setIssueComment(comment))\n\n\t\tconst promise = this.enqueueRequest<Created<IssueComment>>({\n\t\t\tdescription: `Edit comment: ${truncate(comment.content, 80)}`,\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/issues/comments/${comment.offline_id}/`,\n\t\t\tpayload: comment,\n\t\t\tblockers: [comment.issue],\n\t\t\tblocks: [comment.offline_id],\n\t\t})\n\n\t\tpromise.catch(() => {\n\t\t\tthis.dispatch(setIssueComment(commentToUpdate))\n\t\t})\n\n\t\treturn [comment, promise]\n\t}\n\n\tremove(offline_id: string): Promise<undefined> {\n\t\tconst commentToRemove = this.client.store.getState().issueCommentReducer.instances[offline_id]\n\t\tif (!commentToRemove) {\n\t\t\tthrow new Error(`Comment with offline_id ${offline_id} not found in store`)\n\t\t}\n\n\t\tthis.dispatch(deleteIssueComment(offline_id))\n\n\t\tconst promise = this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Delete comment\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/issues/comments/${offline_id}/`,\n\t\t\tblockers: [offline_id],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tpromise.catch(() => {\n\t\t\tthis.dispatch(addIssueComment(commentToRemove))\n\t\t})\n\n\t\treturn promise\n\t}\n\n\tasync refreshStore(projectId: number): Promise<void> {\n\t\tconst result = await this.enqueueRequest<Created<IssueComment>[]>({\n\t\t\tdescription: \"Get comments\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/comments/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t\tthis.dispatch(setIssueComments(result))\n\t}\n}\n","import { Created, IssueUpdate, OvermapRootState } from \"../../typings\"\nimport { onlyUniqueOfflineIds } from \"../../utils\"\nimport { HttpMethod } from \"../../enums\"\nimport { initializeIssueUpdates } from \"../../store\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class IssueUpdateService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tasync refreshStore(projectId: number): Promise<void> {\n\t\tconst result = await this.enqueueRequest<Created<IssueUpdate>[]>({\n\t\t\tdescription: \"Get issue updates\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/issues/updates/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tlet filteredResult = result.filter(onlyUniqueOfflineIds)\n\t\tfilteredResult = filteredResult.map((comment) => {\n\t\t\treturn { ...comment }\n\t\t})\n\t\tif (result.length !== filteredResult.length) {\n\t\t\tconsole.error(\n\t\t\t\t`Received duplicate comments from the API (new length ${filteredResult.length}); filtered in browser.`,\n\t\t\t)\n\t\t}\n\t\tthis.dispatch(initializeIssueUpdates(filteredResult))\n\t}\n}\n","import { BaseAttachmentService, BuildOfflineAttachmentData } from \"./BaseAttachmentService\"\nimport { OptimisticMultipleModelResult } from \"../typings\"\nimport { AttachmentModel, IssueAttachment, OvermapRootState, Stored } from \"../../typings\"\nimport {\n\taddIssueAttachments,\n\tdeleteIssueAttachments,\n\tdeleteIssueAttachment,\n\tselectIssueAttachmentById,\n\tsetIssueAttachment,\n\tupdateIssueAttachments,\n\tinitializeIssueAttachments,\n} from \"../../store\"\nimport { offline } from \"../../utils\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class IssueAttachmentService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseAttachmentService<TState, TSDK, string, IssueAttachment> {\n\tattachmentModel = AttachmentModel.Issue\n\n\tinitializeAttachments = initializeIssueAttachments\n\taddAttachments = addIssueAttachments\n\tupdateAttachments = updateIssueAttachments\n\tremoveAttachments = deleteIssueAttachments\n\tremoveAttachment = deleteIssueAttachment\n\tsetAttachment = setIssueAttachment\n\n\tselectAttachment = selectIssueAttachmentById\n\n\tprivate buildOfflineAttachment(data: BuildOfflineAttachmentData<string>) {\n\t\treturn offline({\n\t\t\tfile: URL.createObjectURL(data.file),\n\t\t\tfile_sha1: data.sha1,\n\t\t\tcreated_by: data.createdBy,\n\t\t\tfile_name: data.file.name,\n\t\t\tfile_type: data.file.type,\n\t\t\tsubmitted_at: data.submittedAt,\n\t\t\tdescription: data.description,\n\t\t\tissue: data.modelId,\n\t\t}) satisfies Stored<IssueAttachment>\n\t}\n\n\tasync attachFilesToIssue(files: File[], issueId: string): Promise<OptimisticMultipleModelResult<IssueAttachment>> {\n\t\treturn this.attachFiles(files, issueId, this.buildOfflineAttachment.bind(this))\n\t}\n\n\tasync deleteIssueAttachment(attachmentId: string): Promise<void> {\n\t\treturn this.deleteAttachment(attachmentId)\n\t}\n}\n","import { unsafeShowToast } from \"@overmap-ai/blocks\"\nimport { OptimisticModelResult } from \"../typings\"\nimport {\n\tCategory,\n\tCreated,\n\tIssue,\n\tIssueAssociation,\n\tIssueType,\n\tIssueUpdate,\n\tIssueUpdateChange,\n\tOvermapRootState,\n\tStored,\n\tSubmitted,\n\tUser,\n} from \"../../typings\"\nimport { offline, onlyUniqueOfflineIds } from \"../../utils\"\nimport {\n\taddActiveProjectIssuesCount,\n\taddFormSubmissions,\n\taddIssue,\n\taddIssueAssociations,\n\taddIssueAttachments,\n\taddIssueUpdate,\n\taddIssueUpdates,\n\taddToRecentIssues,\n\tdeleteFormSubmissions,\n\tdeleteIssue,\n\tdeleteIssueAssociations,\n\tdeleteIssueAttachments,\n\tdeleteIssueUpdate,\n\tdeleteIssueUpdates,\n\tinitializeIssues,\n\tselectAttachmentsOfIssue,\n\tselectFormSubmissionsOfIssue,\n\tselectIssueAssociationsOfIssue,\n\tselectIssueAssociationsToIssue,\n\tselectIssueById,\n\tselectIssueUpdatesOfIssue,\n\tupdateIssue,\n} from \"../../store\"\nimport { HttpMethod } from \"../../enums\"\nimport { DEFAULT_ISSUE_PRIORITY, DEFAULT_ISSUE_STATUS } from \"../../constants\"\nimport { APIError } from \"../errors\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\n/**\n * Handles CRUD operations on issues\n */\nexport abstract class IssueService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\t// Basic CRUD functions\n\t// TODO: Once all models are represented in `Created<TModel>`, use `Created` in `OptimisticModelResult`, so we don't\n\t// have to repeat it for all optimistic model results (all optimistic results are created).\n\tadd(\n\t\tissue: Issue,\n\t\tworkspaceId: string,\n\t\tissueType: IssueType[\"offline_id\"] | null = null,\n\t): OptimisticModelResult<Issue> {\n\t\tconst { store } = this.client\n\t\tconst dateWithoutMilliseconds = new Date()\n\t\tconst state = store.getState()\n\t\tconst currentUserId = state.userReducer.currentUser.id\n\t\tdateWithoutMilliseconds.setMilliseconds(0)\n\n\t\tif (!workspaceId) {\n\t\t\tthrow new Error(\"No active workspace ID while creating issue.\")\n\t\t}\n\n\t\tconst issuePayload: Submitted<Issue> = offline({\n\t\t\t...issue,\n\t\t\tsubmitted_at: dateWithoutMilliseconds.toISOString(),\n\t\t\tindex_workspace: workspaceId,\n\t\t\tcreated_by: currentUserId,\n\t\t\tstatus: issue.status ?? DEFAULT_ISSUE_STATUS,\n\t\t\tpriority: issue.priority ?? DEFAULT_ISSUE_PRIORITY,\n\t\t})\n\n\t\tthis.dispatch(addIssue(issuePayload))\n\t\tthis.dispatch(addToRecentIssues(issuePayload.offline_id))\n\t\tthis.dispatch(addActiveProjectIssuesCount(1))\n\n\t\tconst promise = this.enqueueRequest<Created<Issue>>({\n\t\t\tdescription: \"Create issue\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: \"/issues/\",\n\t\t\tqueryParams: {\n\t\t\t\tworkspace_id: workspaceId,\n\t\t\t\t...(issueType ? { issue_type: issueType } : {}),\n\t\t\t},\n\t\t\tpayload: issuePayload,\n\t\t\tblockers: [\n\t\t\t\t\"add-issue\",\n\t\t\t\t...(issuePayload.index_workspace ? [issuePayload.index_workspace] : []),\n\t\t\t\t...issuePayload.visible_in_workspaces,\n\t\t\t],\n\t\t\tblocks: [issuePayload.offline_id],\n\t\t})\n\t\tvoid promise\n\t\t\t.then((result: Created<Issue>) => {\n\t\t\t\tthis.dispatch(updateIssue(result)) // Updates the index in the store\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tconsole.error(error)\n\t\t\t\tif (error instanceof APIError) {\n\t\t\t\t\tunsafeShowToast?.({\n\t\t\t\t\t\ttitle: \"Could not create issue\",\n\t\t\t\t\t\tdescription: error.message,\n\t\t\t\t\t\taccentColor: \"red\",\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tthis.dispatch(deleteIssue(issuePayload.offline_id))\n\t\t\t\tthis.dispatch(addActiveProjectIssuesCount(-1))\n\t\t\t\tthrow error\n\t\t\t})\n\t\treturn [issuePayload, promise]\n\t}\n\n\tupdate(issue: Submitted<Partial<Issue>>): OptimisticModelResult<Issue> {\n\t\tconst state = this.client.store.getState()\n\t\tconst issueToBeUpdated = selectIssueById(issue.offline_id)(state)\n\n\t\tif (!issueToBeUpdated) {\n\t\t\tthrow new Error(\n\t\t\t\t`Attempting to update an issue with offline_id ${issue.offline_id} that doesn't exist in the store`,\n\t\t\t)\n\t\t}\n\n\t\tconst updatedIssue: Stored<Issue> = { ...issueToBeUpdated, ...issue }\n\n\t\tthis.dispatch(updateIssue(updatedIssue))\n\n\t\tconst changes: IssueUpdate[\"changes\"] = {}\n\t\t// NOTE: order here mirrors the backend order\n\t\tfor (const issueUpdateChange of [\n\t\t\tIssueUpdateChange.TITLE,\n\t\t\tIssueUpdateChange.DESCRIPTION,\n\t\t\tIssueUpdateChange.STATUS,\n\t\t\tIssueUpdateChange.CATEGORY,\n\t\t\tIssueUpdateChange.PRIORITY,\n\t\t\tIssueUpdateChange.ASSIGNED_TO,\n\t\t\tIssueUpdateChange.DUE_DATE,\n\t\t]) {\n\t\t\tif (issueUpdateChange in issue && issue[issueUpdateChange] !== issueToBeUpdated[issueUpdateChange]) {\n\t\t\t\tswitch (issueUpdateChange) {\n\t\t\t\t\tcase \"category\": {\n\t\t\t\t\t\tlet categoryOrNull: Category | null = null\n\t\t\t\t\t\tconst categoryIdOrNull = issue[issueUpdateChange]\n\t\t\t\t\t\tif (categoryIdOrNull) {\n\t\t\t\t\t\t\tcategoryOrNull = state.categoryReducer.instances[categoryIdOrNull] ?? null\n\n\t\t\t\t\t\t\tif (!categoryOrNull)\n\t\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t\t`Trying to update issue category to ${categoryIdOrNull} which does not exist in store`,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tchanges[issueUpdateChange] = categoryOrNull\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\tname: categoryOrNull.name,\n\t\t\t\t\t\t\t\t\tcolor: categoryOrNull.color,\n\t\t\t\t\t\t\t\t\toffline_id: categoryOrNull.offline_id,\n\t\t\t\t\t\t\t }\n\t\t\t\t\t\t\t: null\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcase \"assigned_to\": {\n\t\t\t\t\t\tlet userOrNull: User | null = null\n\t\t\t\t\t\tconst userIdOrNull = issue[issueUpdateChange]\n\t\t\t\t\t\tif (userIdOrNull) {\n\t\t\t\t\t\t\tuserOrNull = state.userReducer.users[userIdOrNull] ?? null\n\n\t\t\t\t\t\t\tif (!userOrNull)\n\t\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t\t`Trying to update issue assigned_to to ${userIdOrNull} which does not exist in store`,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tchanges[issueUpdateChange] = userOrNull\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\tfull_name: userOrNull.username,\n\t\t\t\t\t\t\t\t\tid: userOrNull.id,\n\t\t\t\t\t\t\t }\n\t\t\t\t\t\t\t: null\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcase \"description\":\n\t\t\t\t\t\tchanges[issueUpdateChange] = issue[issueUpdateChange] ?? null\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase \"title\":\n\t\t\t\t\t\tchanges[issueUpdateChange] = issue[issueUpdateChange] ?? null\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase \"priority\":\n\t\t\t\t\t\tchanges[issueUpdateChange] = issue[issueUpdateChange]!\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase \"status\":\n\t\t\t\t\t\tchanges[issueUpdateChange] = issue[issueUpdateChange]!\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase \"due_date\":\n\t\t\t\t\t\tchanges[issueUpdateChange] = issue[issueUpdateChange]\n\t\t\t\t\t\t\t? (issue[issueUpdateChange] as string)\n\t\t\t\t\t\t\t: null\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst offlineIssueUpdate: Submitted<IssueUpdate> = offline({\n\t\t\tcreated_by: state.userReducer.currentUser.id,\n\t\t\tsubmitted_at: new Date().toISOString(),\n\t\t\tissue: issueToBeUpdated.offline_id,\n\t\t\tchanges: changes,\n\t\t})\n\n\t\tthis.dispatch(addIssueUpdate(offlineIssueUpdate))\n\n\t\tconst promise = this.enqueueRequest<Created<Issue>>({\n\t\t\tdescription: \"Edit issue\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/issues/${issue.offline_id}/`,\n\t\t\tpayload: issue,\n\t\t\tblockers: [issue.offline_id],\n\t\t\tblocks: [issue.offline_id],\n\t\t})\n\n\t\tpromise.catch(() => {\n\t\t\t// the patch failed, revert issue back, remove offline issue update\n\t\t\tthis.dispatch(updateIssue(issueToBeUpdated))\n\t\t\tthis.dispatch(deleteIssueUpdate(offlineIssueUpdate.offline_id))\n\t\t})\n\n\t\treturn [updatedIssue, promise]\n\t}\n\n\tasync remove(id: string): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst backup = selectIssueById(id)(state)\n\n\t\tif (!backup) {\n\t\t\tthrow new Error(`No issue with id ${id} found in the store`)\n\t\t}\n\n\t\tconst attachmentsOfIssue = selectAttachmentsOfIssue(id)(state)\n\t\tconst updatesOfIssue = selectIssueUpdatesOfIssue(id)(state)\n\t\tconst formSubmissionsOfIssue = selectFormSubmissionsOfIssue(id)(state)\n\n\t\tconst issueAssociationsRecord: Record<string, Stored<IssueAssociation>> = {}\n\n\t\tfor (const issueAssociation of selectIssueAssociationsToIssue(id)(state))\n\t\t\tissueAssociationsRecord[issueAssociation.offline_id] = issueAssociation\n\t\tfor (const issueAssociation of selectIssueAssociationsOfIssue(id)(state))\n\t\t\tissueAssociationsRecord[issueAssociation.offline_id] = issueAssociation\n\n\t\tconst issueAssociations = Object.values(issueAssociationsRecord)\n\n\t\tthis.dispatch(deleteIssue(id))\n\t\tthis.dispatch(addActiveProjectIssuesCount(-1))\n\t\tif (attachmentsOfIssue.length > 0)\n\t\t\tthis.dispatch(deleteIssueAttachments(attachmentsOfIssue.map(({ offline_id }) => offline_id)))\n\t\tif (updatesOfIssue.length > 0)\n\t\t\tthis.dispatch(deleteIssueUpdates(updatesOfIssue.map(({ offline_id }) => offline_id)))\n\t\tif (formSubmissionsOfIssue.length > 0)\n\t\t\tthis.dispatch(deleteFormSubmissions(formSubmissionsOfIssue.map(({ offline_id }) => offline_id)))\n\t\tif (issueAssociations.length > 0)\n\t\t\tthis.dispatch(deleteIssueAssociations(issueAssociations.map(({ offline_id }) => offline_id)))\n\n\t\t// TODO: remove Issue comments in similar pattern above\n\n\t\ttry {\n\t\t\t// REASON: Need to await to trigger the catch block.\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-confusing-void-expression\n\t\t\treturn await this.enqueueRequest<undefined>({\n\t\t\t\tdescription: \"Delete issue\",\n\t\t\t\tmethod: HttpMethod.DELETE,\n\t\t\t\turl: `/issues/${id}/`,\n\t\t\t\tblockers: [id],\n\t\t\t\tblocks: [],\n\t\t\t})\n\t\t} catch (e) {\n\t\t\tthis.dispatch(addIssue(backup))\n\t\t\tthis.dispatch(addIssueAttachments(attachmentsOfIssue))\n\t\t\tthis.dispatch(addIssueUpdates(updatesOfIssue))\n\t\t\tthis.dispatch(addActiveProjectIssuesCount(1))\n\t\t\tthis.dispatch(addFormSubmissions(formSubmissionsOfIssue))\n\t\t\tthis.dispatch(addIssueAssociations(issueAssociations))\n\n\t\t\tthrow e\n\t\t}\n\t}\n\n\t// Special functions\n\tasync refreshStore(projectId: number): Promise<undefined> {\n\t\tconst result = await this.enqueueRequest<Created<Issue>[]>({\n\t\t\tdescription: \"Get issues\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/issues/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t}).then((result) => {\n\t\t\tconst filteredResult = result.filter(onlyUniqueOfflineIds)\n\t\t\tif (result.length !== filteredResult.length) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t`Received duplicate issues from the API (new length ${filteredResult.length});\n\t\t\t\t\t\t filtered in browser.`,\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn filteredResult\n\t\t})\n\n\t\tthis.dispatch(initializeIssues(result))\n\t}\n}\n","import { OptimisticModelResult } from \"../typings\"\nimport { Created, IssueType, IssueTypePayload, Offline, OvermapRootState, Stored } from \"../../typings\"\nimport { offline } from \"../../utils\"\nimport {\n\taddIssues,\n\taddIssueType,\n\tdeleteIssues,\n\tinitializeIssueTypes,\n\tremoveIssueType,\n\tselectIssuesOfIssueType,\n\tselectIssueTypeById,\n\tsetIssueType,\n\tupdateIssueType,\n} from \"../../store\"\nimport { HttpMethod } from \"../../enums\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class IssueTypeService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tadd(payload: IssueTypePayload, organizationId: number): OptimisticModelResult<IssueType> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst offlineIssueType: Stored<IssueType> = offline({\n\t\t\t...payload,\n\t\t\tsubmitted_at: new Date().toISOString(),\n\t\t\tcreated_by: state.userReducer.currentUser.id,\n\t\t\torganization: organizationId,\n\t\t})\n\n\t\tthis.dispatch(addIssueType(offlineIssueType))\n\n\t\tconst promise = this.enqueueRequest<Created<IssueType>>({\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/organizations/${organizationId}/issue-types/`,\n\t\t\t// Sending only whats needed here\n\t\t\tpayload: {\n\t\t\t\toffline_id: offlineIssueType.offline_id,\n\t\t\t\tsubmitted_at: offlineIssueType.submitted_at,\n\t\t\t\ticon: offlineIssueType.icon,\n\t\t\t\tcolor: offlineIssueType.color,\n\t\t\t\tname: offlineIssueType.name,\n\t\t\t\tdescription: offlineIssueType.description,\n\t\t\t},\n\t\t\tblockers: [],\n\t\t\tblocks: [offlineIssueType.offline_id],\n\t\t})\n\n\t\tpromise\n\t\t\t.then((createdIssueType) => {\n\t\t\t\tthis.dispatch(setIssueType(createdIssueType))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(removeIssueType(offlineIssueType.offline_id))\n\t\t\t})\n\n\t\treturn [offlineIssueType, promise]\n\t}\n\n\tupdate(payload: Offline<Partial<IssueType>>): OptimisticModelResult<IssueType> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst issueTypeToBeUpdated = selectIssueTypeById(payload.offline_id)(state)\n\n\t\tif (!issueTypeToBeUpdated) {\n\t\t\tthrow new Error(`IssueType with offline_id ${payload.offline_id} does not exist in the store.`)\n\t\t}\n\n\t\tconst offlineUpdatedIssueType: Stored<IssueType> = {\n\t\t\t...issueTypeToBeUpdated,\n\t\t\t...payload,\n\t\t}\n\n\t\tthis.dispatch(updateIssueType(offlineUpdatedIssueType))\n\n\t\tconst promise = this.enqueueRequest<Stored<IssueType>>({\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/issues/types/${payload.offline_id}/`,\n\t\t\tpayload: payload,\n\t\t\tblockers: [payload.offline_id],\n\t\t\tblocks: [payload.offline_id],\n\t\t})\n\n\t\tpromise\n\t\t\t.then((updatedIssueType) => {\n\t\t\t\tthis.dispatch(setIssueType(updatedIssueType))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(setIssueType(issueTypeToBeUpdated))\n\t\t\t})\n\n\t\treturn [offlineUpdatedIssueType, promise]\n\t}\n\n\tdelete(issueTypeId: string): Promise<void> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst issueTypeToDelete = selectIssueTypeById(issueTypeId)(state)\n\n\t\tif (!issueTypeToDelete) {\n\t\t\tthrow new Error(`IssueType with offline_id ${issueTypeId} does not exist in the store.`)\n\t\t}\n\n\t\tconst issuesOfIssueType = selectIssuesOfIssueType(issueTypeId)(state)\n\n\t\tthis.dispatch(removeIssueType(issueTypeId))\n\n\t\tthis.dispatch(deleteIssues(issuesOfIssueType.map((issue) => issue.offline_id)))\n\n\t\t// TODO: probably want to remove any forms, revisions and submissions associated with the issue type\n\n\t\tconst promise = this.enqueueRequest<undefined>({\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/issues/types/${issueTypeId}/`,\n\t\t\tblockers: [issueTypeId],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tpromise.catch(() => {\n\t\t\tthis.dispatch(setIssueType(issueTypeToDelete))\n\t\t\tthis.dispatch(addIssues(issuesOfIssueType))\n\t\t})\n\n\t\treturn promise\n\t}\n\n\tasync refreshStore(organizationId: number): Promise<void> {\n\t\t// TODO: fetch for projects too\n\n\t\tconst result = await this.enqueueRequest<Created<IssueType>[]>({\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/organizations/${organizationId}/issue-types/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tthis.dispatch(initializeIssueTypes(result))\n\t}\n}\n","import { HttpMethod } from \"../../enums\"\nimport { deleteProjectAccess, initializeProjectAccesses, updateProjectAccess } from \"../../store\"\nimport { OvermapRootState, ProjectAccess } from \"../../typings\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\n/**\n * Handles the creation of ProjectAccess Service\n */\nexport abstract class ProjectAccessService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tasync fetchAll(projectId: number): Promise<ProjectAccess[]> {\n\t\treturn this.enqueueRequest<ProjectAccess[]>({\n\t\t\tdescription: \"Get project accesses\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/access/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t}\n\n\tasync update(projectAccess: ProjectAccess): Promise<ProjectAccess> {\n\t\tthis.dispatch(updateProjectAccess(projectAccess))\n\t\treturn this.enqueueRequest<ProjectAccess>({\n\t\t\tdescription: \"Edit project access\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/access/${projectAccess.offline_id}/`,\n\t\t\tpayload: projectAccess,\n\t\t\tblockers: [projectAccess.offline_id, \"change-access-level\"],\n\t\t\tblocks: [projectAccess.offline_id],\n\t\t})\n\t}\n\t// TODO: Re-add user to project if removal fails\n\tasync remove(projectAccess: ProjectAccess): Promise<undefined> {\n\t\tthis.dispatch(deleteProjectAccess(projectAccess.offline_id))\n\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Delete project access\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/access/${projectAccess.offline_id}/`,\n\t\t\tblockers: [projectAccess.offline_id],\n\t\t\tblocks: [],\n\t\t})\n\t}\n\n\tasync refreshStore(projectId: number): Promise<undefined> {\n\t\tconst promise = this.fetchAll(projectId)\n\t\tconst result: ProjectAccess[] = await promise\n\t\tthis.dispatch(initializeProjectAccesses(result))\n\t}\n}\n","import { HttpMethod } from \"enums/api\"\nimport { ProjectFile } from \"typings/models/projects\"\nimport { OptimisticGenericResult, SDKRequest } from \"../typings\"\nimport {\n\taddOrReplaceProjectFile,\n\taddOrReplaceProjectFiles,\n\tremoveProjectFile,\n\tsaveActiveProjectFileBounds,\n\tsetActiveProjectFileId,\n\tsetIsImportingProjectFile,\n} from \"store/slices/projectFileSlice\"\nimport { OvermapRootState } from \"../../typings\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\n/**\n * Handles creation and caching of ProjectFiles\n */\nexport abstract class ProjectFileService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tasync refreshStore(projectId: number): Promise<void> {\n\t\tconst result = await this.enqueueRequest<ProjectFile[]>({\n\t\t\tdescription: \"Get project files\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/files/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t\tthis.dispatch(addOrReplaceProjectFiles([]))\n\t\tthis.dispatch(addOrReplaceProjectFiles(result))\n\t}\n\n\tasync saveExisting(file: ProjectFile): Promise<ProjectFile> {\n\t\tif (!file.offline_id) {\n\t\t\tthrow new Error(\n\t\t\t\t\"You can only use this method to save existing project files. The one provided has no offline_id.\",\n\t\t\t)\n\t\t}\n\t\tconst editableData: { file?: unknown } = { ...file }\n\t\tdelete editableData.file\n\t\tconst promise = this.enqueueRequest<ProjectFile>({\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/projects/files/${file.offline_id}/`,\n\t\t\tpayload: editableData,\n\t\t\tblockers: [file.offline_id],\n\t\t\tblocks: [file.offline_id],\n\t\t})\n\t\tvoid promise.then((result) => {\n\t\t\tthis.dispatch(addOrReplaceProjectFile(result))\n\t\t})\n\t\treturn promise\n\t}\n\n\t// TODO: This needs to be seperated into a update and create method\n\tsaveActive(): OptimisticGenericResult<ProjectFile> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\t\tconst activeProjectFileId = state.projectFileReducer.activeProjectFileId\n\t\tconst activeProjectId = state.projectReducer.activeProjectId\n\t\tif (!activeProjectFileId) {\n\t\t\tthrow new Error(\"No active project file\")\n\t\t}\n\t\tif (!activeProjectId) {\n\t\t\tthrow new Error(\"No active project\")\n\t\t}\n\t\tconst activeProjectFile = state.projectFileReducer.projectFiles[activeProjectFileId]\n\t\tif (!activeProjectFile) {\n\t\t\tthrow new Error(\"No active project file\")\n\t\t}\n\n\t\tif (!activeProjectFile.bounds && !activeProjectFile.canvas_bounds) {\n\t\t\tthrow new Error(\"Project file must either have bounds or canvas_bounds set\")\n\t\t}\n\n\t\tlet requestDetails: SDKRequest | Promise<SDKRequest>\n\t\tconst existing = typeof activeProjectFile.file === \"string\" && !activeProjectFile.file.startsWith(\"blob:\")\n\t\tif (existing) {\n\t\t\tconst editableData: { file?: unknown } = { ...activeProjectFile }\n\t\t\tdelete editableData.file\n\t\t\trequestDetails = {\n\t\t\t\tmethod: HttpMethod.PATCH,\n\t\t\t\turl: `/projects/files/${activeProjectFileId}/`,\n\t\t\t\tpayload: editableData,\n\t\t\t\tblockers: [activeProjectFileId],\n\t\t\t\tblocks: [activeProjectFileId],\n\t\t\t}\n\t\t} else {\n\t\t\trequestDetails = new Promise<SDKRequest>((resolve, reject) => {\n\t\t\t\tthis.client.files\n\t\t\t\t\t.uploadFileToS3(activeProjectFile.file_sha1)\n\t\t\t\t\t.then(([fileProps]) => {\n\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\t\t\t\turl: `/projects/${activeProjectId}/files/`,\n\t\t\t\t\t\t\tpayload: {\n\t\t\t\t\t\t\t\t...activeProjectFile,\n\t\t\t\t\t\t\t\t...fileProps,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tblockers: [activeProjectFileId],\n\t\t\t\t\t\t\tblocks: [activeProjectFileId],\n\t\t\t\t\t\t})\n\t\t\t\t\t})\n\t\t\t\t\t.catch(reject)\n\t\t\t})\n\t\t}\n\t\tconst promise = Promise.resolve(requestDetails).then((requestDetails) => {\n\t\t\treturn this.enqueueRequest<ProjectFile>(requestDetails)\n\t\t})\n\t\tvoid promise.then((result) => {\n\t\t\tthis.dispatch(addOrReplaceProjectFile(result))\n\t\t})\n\t\tthis.dispatch(saveActiveProjectFileBounds)\n\t\tthis.dispatch(setActiveProjectFileId(null))\n\t\tthis.dispatch(setIsImportingProjectFile(false))\n\t\treturn [activeProjectFile, promise]\n\t}\n\n\tdelete(projectFileId: string): Promise<undefined> {\n\t\tthis.dispatch(removeProjectFile(projectFileId))\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/projects/files/${projectFileId}`,\n\t\t\tblockers: [projectFileId],\n\t\t\tblocks: [],\n\t\t})\n\t}\n}\n","import { BaseAttachmentService, BuildOfflineAttachmentData } from \"./BaseAttachmentService\"\nimport { offline } from \"../../utils\"\nimport { AttachmentModel, OvermapRootState, ProjectAttachment, Stored } from \"../../typings\"\nimport { OptimisticMultipleModelResult } from \"../typings\"\nimport {\n\taddProjectAttachments,\n\tdeleteProjectAttachments,\n\tdeleteProjectAttachment,\n\tselectProjectAttachment,\n\tsetProjectAttachment,\n\tupdateProjectAttachments,\n\tinitializeProjectAttachments,\n} from \"../../store\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class ProjectAttachmentService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseAttachmentService<TState, TSDK, number, ProjectAttachment> {\n\tattachmentModel = AttachmentModel.Project\n\n\tinitializeAttachments = initializeProjectAttachments\n\taddAttachments = addProjectAttachments\n\tupdateAttachments = updateProjectAttachments\n\tremoveAttachments = deleteProjectAttachments\n\tremoveAttachment = deleteProjectAttachment\n\tsetAttachment = setProjectAttachment\n\n\tselectAttachment = selectProjectAttachment\n\n\tprivate buildOfflineAttachment(data: BuildOfflineAttachmentData<number>) {\n\t\treturn offline({\n\t\t\tfile: URL.createObjectURL(data.file),\n\t\t\tfile_sha1: data.sha1,\n\t\t\tcreated_by: data.createdBy,\n\t\t\tfile_name: data.file.name,\n\t\t\tfile_type: data.file.type,\n\t\t\tsubmitted_at: data.submittedAt,\n\t\t\tdescription: data.description,\n\t\t\tproject: data.modelId,\n\t\t}) satisfies Stored<ProjectAttachment>\n\t}\n\n\tasync attachFilesToProject(\n\t\tfiles: File[],\n\t\tprojectId: number,\n\t): Promise<OptimisticMultipleModelResult<ProjectAttachment>> {\n\t\treturn this.attachFiles(files, projectId, this.buildOfflineAttachment.bind(this))\n\t}\n\n\tasync deleteProjectAttachment(attachmentId: string): Promise<void> {\n\t\treturn this.deleteAttachment(attachmentId)\n\t}\n}\n","import { HttpMethod } from \"enums/api\"\nimport { Project } from \"typings/models/projects\"\nimport { v4 as uuidv4 } from \"uuid\"\nimport { Created, License, OvermapRootState, Payload } from \"../../typings\"\nimport {\n\tacceptProjectInvite,\n\taddOrReplaceProjectFiles,\n\tdeleteProject,\n\tdeleteProjectAccesses,\n\tdeleteProjectAttachments,\n\tinitializeProjectAccesses,\n\tremoveProjectFilesOfProject,\n\tselectAttachmentsOfProject,\n\tselectLicenseForProject,\n\tselectProjectAccesses,\n\tselectProjectFiles,\n\tselectProjectMapping,\n\tsetProjectAttachments,\n\tsetProjects,\n\tupdateLicense,\n\tupdateOrCreateProject,\n} from \"../../store\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\ninterface JoinProjectResponse {\n\tusername: string\n}\n\nexport abstract class ProjectService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\t/**\n\t * Creates a new project. Due to the nature of project creation,\n\t * @param project A Payload<Project> object containing project attributes.\n\t * @returns A promise that resolves to a Project.\n\t * @throws An APIError if the server returns an error, or any other error that may occur.\n\t */\n\tasync add(project: Payload<Project>): Promise<Project> {\n\t\tif (!project.organization_owner && !project.user_owner) {\n\t\t\tthrow new Error(\"Project type was not chosen when trying to create a project\")\n\t\t}\n\n\t\tif (!project.bounds && !project.canvas_bounds) {\n\t\t\tthrow new Error(\"Project must either have bounds or canvas_bounds set\")\n\t\t}\n\n\t\tconst isOrganizationProject = !!project.organization_owner\n\n\t\tconst url = isOrganizationProject ? `/organizations/${project.organization_owner}/projects/` : \"/projects/\"\n\t\tconst projectType = isOrganizationProject\n\t\t\t? { organization_owner: project.organization_owner }\n\t\t\t: { user_owner: project.user_owner }\n\n\t\treturn await this.enqueueRequest<Created<Project>>({\n\t\t\tdescription: \"Create project\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl,\n\t\t\tpayload: {\n\t\t\t\tname: project.name,\n\t\t\t\tbounds: project.bounds,\n\t\t\t\t...projectType,\n\t\t\t},\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t}\n\n\tasync update(project: Project): Promise<Project> {\n\t\tif (!project.bounds && !project.canvas_bounds) {\n\t\t\tthrow new Error(\"Project must either have bounds or canvas_bounds set\")\n\t\t}\n\n\t\tthis.dispatch(updateOrCreateProject(project))\n\t\treturn await this.enqueueRequest<Project>({\n\t\t\tdescription: \"Update project\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/projects/${project.id}/`,\n\t\t\tpayload: {\n\t\t\t\tname: project.name,\n\t\t\t\tbounds: project.bounds,\n\t\t\t},\n\t\t\tblockers: [project.id.toString()],\n\t\t\tblocks: [project.id.toString()],\n\t\t})\n\t}\n\n\tasync delete(projectId: number): Promise<void> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\t\tconst projects = selectProjectMapping(state)\n\t\tconst project = projects[projectId]\n\t\tif (!project) {\n\t\t\tthrow new Error(\"Expected project to exist\")\n\t\t}\n\n\t\t// TODO: this shouldnt be an optimistic result\n\t\t// Selector needed to restore if the request fails\n\t\tconst filesToDelete = selectProjectFiles(state).filter((file) => file.project === projectId)\n\t\tthis.dispatch(removeProjectFilesOfProject(project.id))\n\n\t\t// Selector needed to restore if the request fails\n\t\tconst attachmentsOfProject = selectAttachmentsOfProject(project.id)(state)\n\t\tthis.dispatch(deleteProjectAttachments(attachmentsOfProject.map(({ offline_id }) => offline_id)))\n\n\t\t// Selector needed to restore if the request fails\n\t\tconst projectAccesses = selectProjectAccesses(state)\n\t\tthis.dispatch(deleteProjectAccesses(projectAccesses.map(({ offline_id }) => offline_id)))\n\n\t\t// Necessary to prevent no projects view from showing when project is deleted\n\t\tthis.dispatch({ type: \"rehydrated/setRehydrated\", payload: false })\n\t\tthis.dispatch(deleteProject(project))\n\n\t\tconst license = selectLicenseForProject(project.id)(state)\n\t\t// Detach license from project\n\t\tif (license) {\n\t\t\tthis.dispatch(updateLicense({ ...license, project: null } as License))\n\t\t}\n\n\t\ttry {\n\t\t\tawait this.enqueueRequest<undefined>({\n\t\t\t\tdescription: \"Delete project\",\n\t\t\t\tmethod: HttpMethod.DELETE,\n\t\t\t\turl: `/projects/${projectId}/`,\n\t\t\t\tblockers: [projectId.toString()],\n\t\t\t\tblocks: [],\n\t\t\t})\n\t\t\tthis.dispatch({ type: \"rehydrated/setRehydrated\", payload: true })\n\t\t} catch (e) {\n\t\t\tthis.dispatch(setProjects(Object.values(projects)))\n\t\t\tthis.dispatch(initializeProjectAccesses(Object.values(projectAccesses)))\n\t\t\tthis.dispatch(addOrReplaceProjectFiles(filesToDelete))\n\t\t\tthis.dispatch(setProjectAttachments(attachmentsOfProject))\n\t\t\tthis.dispatch({ type: \"rehydrated/setRehydrated\", payload: true })\n\t\t\tif (license) {\n\t\t\t\tthis.dispatch(updateLicense({ ...license, project: project.id } as License))\n\t\t\t}\n\t\t\tthrow e\n\t\t}\n\t}\n\n\tinvite(projectId: number, email: string): Promise<undefined> {\n\t\tconst offline_id: string = uuidv4()\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Invite user to project\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/projects/${projectId}/invite/${email}/`,\n\t\t\tpayload: {\n\t\t\t\toffline_id,\n\t\t\t},\n\t\t\tblockers: [],\n\t\t\tblocks: [offline_id],\n\t\t})\n\t}\n\n\tjoinProject(projectId: number, userId: number, inviteCode: string): Promise<JoinProjectResponse> {\n\t\treturn this.enqueueRequest<JoinProjectResponse>({\n\t\t\tdescription: \"Join project\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/join-project/${userId}/${inviteCode}/`,\n\t\t\tisAuthNeeded: false,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t}\n\n\tasync acceptInvite(projectId: number): Promise<void> {\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Accept project invite\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/projects/${projectId}/accept-invite/`,\n\t\t\tblockers: [projectId.toString()],\n\t\t\tblocks: [projectId.toString()],\n\t\t}).then(() => {\n\t\t\tthis.dispatch(acceptProjectInvite(projectId))\n\t\t})\n\t}\n}\n","import { HttpMethod } from \"enums/api\"\nimport { addForm, deleteForm, initializeForms, selectFormById, updateForm } from \"store/slices/formSlice\"\nimport {\n\tForm,\n\tFormRevision,\n\tFormRevisionAttachment,\n\tFormRevisionPayload,\n\tISerializedField,\n\tISerializedOnlyField,\n} from \"typings/models/forms\"\nimport { OptimisticMultipleModelResult, PresignedUrlsResponse } from \"../typings\"\nimport { offline } from \"utils/offline\"\nimport { Created, OvermapRootState, Stored, Submitted } from \"../../typings\"\nimport { hashFile } from \"../../utils\"\nimport {\n\taddFormRevision,\n\taddFormRevisionAttachments,\n\taddFormRevisions,\n\taddFormSubmissions,\n\tdeleteFormRevision,\n\tdeleteFormRevisionAttachments,\n\tdeleteFormRevisions,\n\tdeleteFormSubmissions,\n\tinitializeFormRevisionAttachments,\n\tinitializeFormRevisions,\n\tselectFormRevisionsOfForm,\n\tselectFormSubmissionsOfForm,\n\tsetFormRevision,\n\tupdateFormRevisionAttachments,\n} from \"../../store\"\nimport type { BaseSDK } from \"../base\"\nimport { FilePayload } from \"./BaseAttachmentService\"\nimport { BaseUploadService } from \"./BaseUploadService\"\n\n/**\n * Finds and separates image files from form revision fields. The image attribute is deleted from the field objects and\n * is returned separately from the image files as they are stored in a different table.\n */\nconst separateImageFromFields = async (fields: ISerializedField[]) => {\n\tconst images: Record<string, File> = {} // key: field identifier, value: File\n\tconst newFields: ISerializedField[] = [] // fields without image attribute\n\tfor (const section of fields) {\n\t\tif (section.type !== \"section\") {\n\t\t\tthrow new Error(`Expected ISerializedField type to be a section. Got ${section.type} instead.`)\n\t\t}\n\n\t\tconst { fields: sectionFields } = section\n\t\tconst newSectionFields: ISerializedOnlyField[] = []\n\t\tfor (const field of sectionFields) {\n\t\t\tif (field.image) {\n\t\t\t\tif (field.image instanceof Promise) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\timages[field.identifier] = await field.image\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tconsole.error(\"Failed to get image from promise\", e)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\timages[field.identifier] = field.image\n\t\t\t\t}\n\t\t\t\tdelete field.image\n\t\t\t}\n\t\t\tnewSectionFields.push(field)\n\t\t}\n\t\tnewFields.push({ ...section, fields: newSectionFields })\n\t}\n\n\treturn { fields: newFields, images }\n}\n\nexport abstract class FormService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseUploadService<TState, TSDK> {\n\tprivate async bulkAddRevisionAttachments(\n\t\trevisionId: string,\n\t\tfiles: Record<string, File>,\n\t): Promise<OptimisticMultipleModelResult<FormRevisionAttachment>> {\n\t\tinterface AttachmentPayload {\n\t\t\toffline_id: string\n\t\t\tname: string\n\t\t\tsha1: string\n\t\t\tfield_identifier: string\n\t\t\tdesscription?: string\n\t\t}\n\n\t\tconst submittedAt = new Date().toISOString()\n\t\tconst createdBy = this.client.store.getState().userReducer.currentUser.id\n\n\t\tconst filePayloads: Record<FilePayload[\"sha1\"], FilePayload> = {}\n\t\tconst offlineFormRevisionAttachments: Stored<FormRevisionAttachment>[] = []\n\t\tconst attachmentPayloads: AttachmentPayload[] = []\n\n\t\tfor (const [fieldIdentifier, file] of Object.entries(files)) {\n\t\t\tconst sha1 = await hashFile(file)\n\n\t\t\tif (!(sha1 in filePayloads)) {\n\t\t\t\tfilePayloads[sha1] = {\n\t\t\t\t\tsha1,\n\t\t\t\t\tfile_type: file.type,\n\t\t\t\t\textension: file.name.split(\".\").pop()!,\n\t\t\t\t\tsize: file.size,\n\t\t\t\t}\n\t\t\t\tawait this.client.files.addCache(file, sha1)\n\t\t\t}\n\n\t\t\tconst offlineFormRevisionAttachment: Stored<FormRevisionAttachment> = offline({\n\t\t\t\tfile: URL.createObjectURL(file),\n\t\t\t\tfile_type: file.type,\n\t\t\t\tfile_name: file.name,\n\t\t\t\tfile_sha1: sha1,\n\t\t\t\tcreated_by: createdBy,\n\t\t\t\trevision: revisionId,\n\t\t\t\tsubmitted_at: submittedAt,\n\t\t\t\tfield_identifier: fieldIdentifier,\n\t\t\t})\n\t\t\tofflineFormRevisionAttachments.push(offlineFormRevisionAttachment)\n\n\t\t\tconst attachmentPayload: AttachmentPayload = {\n\t\t\t\toffline_id: offlineFormRevisionAttachment.offline_id,\n\t\t\t\tname: file.name,\n\t\t\t\tfield_identifier: fieldIdentifier,\n\t\t\t\tsha1,\n\t\t\t}\n\t\t\tattachmentPayloads.push(attachmentPayload)\n\t\t}\n\n\t\tthis.dispatch(addFormRevisionAttachments(offlineFormRevisionAttachments))\n\n\t\tconst promise = this.enqueueRequest<{\n\t\t\tattachments: Created<FormRevisionAttachment>[]\n\t\t\tpresigned_urls: PresignedUrlsResponse\n\t\t}>({\n\t\t\tdescription: \"Attach files to form revision\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/forms/revisions/${revisionId}/attachments/bulk/`,\n\t\t\tpayload: {\n\t\t\t\tsubmitted_at: submittedAt,\n\t\t\t\tattachments: attachmentPayloads,\n\t\t\t\tfiles: Object.values(filePayloads),\n\t\t\t},\n\t\t\tblockers: [revisionId],\n\t\t\tblocks: offlineFormRevisionAttachments.map((attachment) => attachment.offline_id),\n\t\t})\n\n\t\tpromise\n\t\t\t.then((result) => {\n\t\t\t\tthis.processPresignedUrls(result.presigned_urls)\n\t\t\t\tthis.dispatch(updateFormRevisionAttachments(result.attachments))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(\n\t\t\t\t\tdeleteFormRevisionAttachments(\n\t\t\t\t\t\tofflineFormRevisionAttachments.map((attachment) => attachment.offline_id),\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t})\n\n\t\treturn [offlineFormRevisionAttachments, promise.then(({ attachments }) => attachments)]\n\t}\n\n\tprivate async add(\n\t\townerId: string,\n\t\tform: Submitted<Form>,\n\t\tinitialRevision: FormRevisionPayload,\n\t\turlPrefix: string,\n\t): Promise<\n\t\t[\n\t\t\tStored<Form>,\n\t\t\tStored<FormRevision>,\n\t\t\tStored<FormRevisionAttachment>[],\n\t\t\tPromise<Created<FormRevision>>,\n\t\t\tPromise<Created<FormRevisionAttachment>[]>,\n\t\t]\n\t> {\n\t\tinterface CreateFormPayload {\n\t\t\toffline_id: string\n\t\t\tsubmitted_at: string\n\t\t\tinitial_revision: {\n\t\t\t\toffline_id: string\n\t\t\t\tsubmitted_at: string\n\t\t\t\ttitle: string\n\t\t\t\tdescription?: string\n\t\t\t\tfields: ISerializedField[]\n\t\t\t}\n\t\t}\n\n\t\tconst { fields, images } = await separateImageFromFields(initialRevision.fields)\n\n\t\tconst offlineFormRevision: Submitted<FormRevision> = offline({\n\t\t\t...initialRevision,\n\t\t\tfields: fields,\n\t\t\tcreated_by: form.created_by,\n\t\t\tform: form.offline_id,\n\t\t\tsubmitted_at: form.submitted_at,\n\t\t\trevision: \"Pending\",\n\t\t})\n\n\t\tthis.dispatch(addForm(form))\n\t\tthis.dispatch(addFormRevision(offlineFormRevision))\n\n\t\tconst formPromise = this.enqueueRequest<FormRevision>({\n\t\t\tdescription: \"Create form\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: urlPrefix,\n\t\t\tpayload: {\n\t\t\t\t// Sending exactly what is currently needed for the endpoint\n\t\t\t\toffline_id: form.offline_id,\n\t\t\t\tsubmitted_at: form.submitted_at,\n\t\t\t\tinitial_revision: {\n\t\t\t\t\toffline_id: offlineFormRevision.offline_id,\n\t\t\t\t\tsubmitted_at: offlineFormRevision.submitted_at,\n\t\t\t\t\ttitle: offlineFormRevision.title,\n\t\t\t\t\tdescription: offlineFormRevision.description,\n\t\t\t\t\tfields: offlineFormRevision.fields,\n\t\t\t\t},\n\t\t\t} satisfies CreateFormPayload,\n\t\t\tblockers: [ownerId],\n\t\t\tblocks: [form.offline_id, offlineFormRevision.offline_id],\n\t\t})\n\n\t\tconst [offlineFormRevisionAttachments, attachmentsPromise] = await this.bulkAddRevisionAttachments(\n\t\t\tofflineFormRevision.offline_id,\n\t\t\timages,\n\t\t)\n\n\t\tvoid formPromise.catch((e) => {\n\t\t\tthis.dispatch(deleteForm(form.offline_id))\n\t\t\tthis.dispatch(deleteFormRevision(offlineFormRevision.offline_id))\n\t\t\t// TODO: remove form revision attachments\n\t\t\tthrow e\n\t\t})\n\n\t\treturn [form, offlineFormRevision, offlineFormRevisionAttachments, formPromise, attachmentsPromise]\n\t}\n\n\taddForOrganization(organizationId: number, initialRevision: FormRevisionPayload) {\n\t\tconst state: OvermapRootState = this.client.store.getState()\n\n\t\tconst offlineForm: Submitted<Form> = offline({\n\t\t\tfavorite: false,\n\t\t\tcreated_by: state.userReducer.currentUser.id,\n\t\t\tsubmitted_at: new Date().toISOString(),\n\t\t\torganization: organizationId,\n\t\t})\n\n\t\treturn this.add(\n\t\t\torganizationId.toString(),\n\t\t\tofflineForm,\n\t\t\tinitialRevision,\n\t\t\t`/organizations/${organizationId}/create-form/`,\n\t\t)\n\t}\n\n\taddForProject(projectId: number, initialRevision: FormRevisionPayload) {\n\t\tconst state: OvermapRootState = this.client.store.getState()\n\n\t\tconst offlineForm: Submitted<Form> = offline({\n\t\t\tfavorite: false,\n\t\t\tcreated_by: state.userReducer.currentUser.id,\n\t\t\tsubmitted_at: new Date().toISOString(),\n\t\t\tproject: projectId,\n\t\t})\n\n\t\treturn this.add(projectId.toString(), offlineForm, initialRevision, `/projects/${projectId}/create-form/`)\n\t}\n\n\taddForIssueType(issueTypeId: string, initialRevision: FormRevisionPayload) {\n\t\tconst state: OvermapRootState = this.client.store.getState()\n\n\t\tconst offlineForm: Submitted<Form> = offline({\n\t\t\tfavorite: false,\n\t\t\tcreated_by: state.userReducer.currentUser.id,\n\t\t\tsubmitted_at: new Date().toISOString(),\n\t\t\tissue_type: issueTypeId,\n\t\t})\n\n\t\treturn this.add(issueTypeId, offlineForm, initialRevision, `/issues/types/${issueTypeId}/create-form/`)\n\t}\n\n\taddForAssetType(assetTypeId: string, initialRevision: FormRevisionPayload) {\n\t\tconst state: OvermapRootState = this.client.store.getState()\n\n\t\tconst offlineForm: Submitted<Form> = offline({\n\t\t\tfavorite: false,\n\t\t\tcreated_by: state.userReducer.currentUser.id,\n\t\t\tsubmitted_at: new Date().toISOString(),\n\t\t\tasset_type: assetTypeId,\n\t\t})\n\n\t\treturn this.add(assetTypeId, offlineForm, initialRevision, `/assets/types/${assetTypeId}/create-form/`)\n\t}\n\n\tasync createRevision(\n\t\tformId: string,\n\t\trevision: FormRevisionPayload,\n\t): Promise<\n\t\t[\n\t\t\tStored<FormRevision>,\n\t\t\tStored<FormRevisionAttachment>[],\n\t\t\tPromise<Created<FormRevision>>,\n\t\t\tPromise<Created<FormRevisionAttachment>[]>,\n\t\t]\n\t> {\n\t\tconst offlineRevision = offline(revision)\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst activeProjectId = state.projectReducer.activeProjectId\n\t\tif (!activeProjectId) {\n\t\t\tthrow new Error(\"Cannot create form revision when there is no active project.\")\n\t\t}\n\t\tconst currentUserId = state.userReducer.currentUser.id\n\n\t\tconst { fields, images } = await separateImageFromFields(offlineRevision.fields)\n\n\t\tconst fullRevision: Submitted<FormRevision> = {\n\t\t\t...offlineRevision,\n\t\t\tfields: fields,\n\t\t\tcreated_by: currentUserId,\n\t\t\trevision: \"Pending\",\n\t\t\tform: formId,\n\t\t\tsubmitted_at: new Date().toISOString(),\n\t\t}\n\n\t\tthis.dispatch(addFormRevision(fullRevision))\n\n\t\tconst promise = this.enqueueRequest<FormRevision>({\n\t\t\tdescription: \"Create form revision\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/forms/${formId}/`,\n\t\t\tpayload: {\n\t\t\t\tinitial_revision: {\n\t\t\t\t\toffline_id: fullRevision.offline_id,\n\t\t\t\t\tsubmitted_at: fullRevision.submitted_at,\n\t\t\t\t\ttitle: fullRevision.title,\n\t\t\t\t\tdescription: fullRevision.description,\n\t\t\t\t\tfields: fullRevision.fields,\n\t\t\t\t},\n\t\t\t},\n\t\t\tblockers: [formId],\n\t\t\tblocks: [offlineRevision.offline_id],\n\t\t})\n\n\t\tconst [offlineFormRevisionAttachments, attachmentsPromise] = await this.bulkAddRevisionAttachments(\n\t\t\tfullRevision.offline_id,\n\t\t\timages,\n\t\t)\n\n\t\tvoid promise\n\t\t\t.then((result) => {\n\t\t\t\tthis.dispatch(setFormRevision(result))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(deleteFormRevision(fullRevision.offline_id))\n\t\t\t})\n\n\t\treturn [fullRevision, offlineFormRevisionAttachments, promise, attachmentsPromise]\n\t}\n\n\tasync favorite(formId: string): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst activeProjectId = state.projectReducer.activeProjectId\n\t\tconst form = state.formReducer.instances[formId]\n\n\t\tif (!form) {\n\t\t\tthrow new Error(`Expected form to exist, got ${form}`)\n\t\t}\n\n\t\tthis.dispatch(updateForm({ ...form, favorite: true }))\n\n\t\ttry {\n\t\t\tawait this.enqueueRequest({\n\t\t\t\tdescription: \"Favorite form\",\n\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\turl: `/forms/${formId}/favorite/${activeProjectId}/`,\n\t\t\t\tblockers: [formId, `favorite-${formId}`],\n\t\t\t\tblocks: [`favorite-${formId}`],\n\t\t\t})\n\t\t} catch (e) {\n\t\t\tthis.dispatch(updateForm(form))\n\t\t\tthrow e\n\t\t}\n\t}\n\n\tasync unfavorite(formId: string): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst activeProjectId = state.projectReducer.activeProjectId\n\t\tconst form = state.formReducer.instances[formId]\n\n\t\tif (!form) {\n\t\t\tthrow new Error(`Expected form to exist, got ${form}`)\n\t\t}\n\n\t\tthis.dispatch(updateForm({ ...form, favorite: false }))\n\n\t\ttry {\n\t\t\t// REASON: Need to await to trigger the catch block.\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-confusing-void-expression\n\t\t\treturn await this.enqueueRequest<undefined>({\n\t\t\t\tdescription: \"Unfavorite form\",\n\t\t\t\tmethod: HttpMethod.DELETE,\n\t\t\t\turl: `/forms/${formId}/unfavorite/${activeProjectId}/`,\n\t\t\t\tblockers: [formId, `favorite-${formId}`],\n\t\t\t\tblocks: [`favorite-${formId}`],\n\t\t\t})\n\t\t} catch (e) {\n\t\t\tthis.dispatch(updateForm(form))\n\t\t\tthrow e\n\t\t}\n\t}\n\n\tasync delete(formId: string): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\t\tconst form = selectFormById(formId)(state)\n\t\tif (!form) {\n\t\t\tthrow new Error(\"Expected form to exist\")\n\t\t}\n\t\t// Delete all submissions for this form\n\t\tconst formSubmissions = selectFormSubmissionsOfForm(formId)(state)\n\t\tif (formSubmissions.length > 0) {\n\t\t\tthis.dispatch(deleteFormSubmissions(formSubmissions.map(({ offline_id }) => offline_id)))\n\t\t}\n\n\t\t// Delete all revisions for this form\n\t\tconst formRevisions = selectFormRevisionsOfForm(formId)(state)\n\t\tif (formRevisions.length > 0) {\n\t\t\tthis.dispatch(deleteFormRevisions(formRevisions.map(({ offline_id }) => offline_id)))\n\t\t}\n\n\t\t// Delete the form itself\n\t\tthis.dispatch(deleteForm(formId))\n\n\t\ttry {\n\t\t\t// REASON: Need to await to trigger the catch block.\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-confusing-void-expression\n\t\t\treturn await this.enqueueRequest<undefined>({\n\t\t\t\tdescription: \"Delete form\",\n\t\t\t\tmethod: HttpMethod.DELETE,\n\t\t\t\turl: `/forms/${formId}/`,\n\t\t\t\tblockers: [formId],\n\t\t\t\tblocks: [],\n\t\t\t})\n\t\t} catch (e) {\n\t\t\tthis.dispatch(addForm(form))\n\t\t\tif (formRevisions.length > 0) {\n\t\t\t\tthis.dispatch(addFormRevisions(formRevisions))\n\t\t\t}\n\t\t\tif (formSubmissions.length > 0) {\n\t\t\t\tthis.dispatch(addFormSubmissions(formSubmissions))\n\t\t\t}\n\t\t\tthrow e\n\t\t}\n\t}\n\n\tasync refreshStore(projectId: number): Promise<void> {\n\t\tinterface FormDataResponse {\n\t\t\tforms: Created<Form>[]\n\t\t\trevisions: Created<FormRevision>[]\n\t\t\tattachments: Created<FormRevisionAttachment>[]\n\t\t}\n\n\t\tconst forms: Created<Form>[] = []\n\t\tconst revisions: Created<FormRevision>[] = []\n\t\tconst attachments: Created<FormRevisionAttachment>[] = []\n\n\t\tconst projectFormsResult = await this.enqueueRequest<FormDataResponse>({\n\t\t\tdescription: \"Fetch project forms\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/forms/`,\n\t\t\tblockers: [projectId.toString()],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tfor (const form of projectFormsResult.forms) forms.push(form)\n\t\tfor (const revision of projectFormsResult.revisions) revisions.push(revision)\n\t\tfor (const attachment of projectFormsResult.attachments) attachments.push(attachment)\n\n\t\tconst organizationFormsResult = await this.enqueueRequest<FormDataResponse>({\n\t\t\tdescription: \"Fetch organization forms\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/organizations/forms/`,\n\t\t\tblockers: [projectId.toString()],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tfor (const form of organizationFormsResult.forms) forms.push(form)\n\t\tfor (const revision of organizationFormsResult.revisions) revisions.push(revision)\n\t\tfor (const attachment of organizationFormsResult.attachments) attachments.push(attachment)\n\n\t\tconst assetTypeFormsResult = await this.enqueueRequest<FormDataResponse>({\n\t\t\tdescription: \"Fetch asset type forms\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/asset-types/forms/`,\n\t\t\tblockers: [projectId.toString()],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tfor (const form of assetTypeFormsResult.forms) forms.push(form)\n\t\tfor (const revision of assetTypeFormsResult.revisions) revisions.push(revision)\n\t\tfor (const attachment of assetTypeFormsResult.attachments) attachments.push(attachment)\n\n\t\tconst issueTypeFormsResult = await this.enqueueRequest<FormDataResponse>({\n\t\t\tdescription: \"Fetch issue type forms\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/issue-types/forms/`,\n\t\t\tblockers: [projectId.toString()],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tfor (const form of issueTypeFormsResult.forms) forms.push(form)\n\t\tfor (const revision of issueTypeFormsResult.revisions) revisions.push(revision)\n\t\tfor (const attachment of issueTypeFormsResult.attachments) attachments.push(attachment)\n\n\t\tthis.dispatch(initializeForms(forms))\n\t\tthis.dispatch(initializeFormRevisions(revisions))\n\t\tthis.dispatch(initializeFormRevisionAttachments(attachments))\n\t}\n}\n","import { FieldValue, FormSubmission, FormSubmissionAttachment, FormSubmissionPayload } from \"typings/models/forms\"\nimport { OptimisticMultipleModelResult, PresignedUrlsResponse } from \"../typings\"\nimport { HttpMethod } from \"enums/api\"\nimport { hashFile, offline } from \"utils\"\nimport { v4 as uuidv4 } from \"uuid\"\nimport {\n\taddActiveProjectFormSubmissionsCount,\n\taddFormSubmission,\n\taddFormSubmissionAttachments,\n\taddFormSubmissions,\n\tdeleteFormSubmission,\n\tdeleteFormSubmissionAttachments,\n\tinitializeFormSubmissionAttachments,\n\tinitializeFormSubmissions,\n\tselectAttachmentsOfFormSubmission,\n\tselectFormSubmissionAttachemntsByIds,\n\tselectFormSubmissionById,\n\tsetFormSubmission,\n\tupdateFormSubmission,\n\tupdateFormSubmissionAttachments,\n} from \"../../store\"\nimport { Created, Offline, OvermapRootState, Payload, Stored, Submitted } from \"../../typings\"\nimport { chunkArray } from \"../../utils/array\"\nimport type { BaseSDK } from \"../base\"\nimport { BaseUploadService } from \"./BaseUploadService\"\nimport { FilePayload } from \"./BaseAttachmentService\"\n\nconst isArrayOfFiles = (value: unknown): value is File[] => {\n\treturn Array.isArray(value) && value[0] instanceof File\n}\n\n// returns a new object with the files separated from the values, files is a dictionary with the key being the\n// field identifier and the value being the list of files for that field\nconst separateFilesFromValues = (values: FormSubmissionPayload[\"values\"]) => {\n\tconst files: Record<string, File[]> = {}\n\tconst newValues: Record<string, FieldValue> = {}\n\tfor (const key in values) {\n\t\tconst value = values[key]\n\n\t\tif (value === undefined) throw new Error(\"Expected value to be defined\")\n\n\t\tif (value instanceof File) {\n\t\t\tfiles[key] = [value]\n\t\t} else if (isArrayOfFiles(value)) {\n\t\t\tfiles[key] = value\n\t\t} else {\n\t\t\tnewValues[key] = value\n\t\t}\n\t}\n\n\treturn { values: newValues, files }\n}\n\ninterface BulkAddRequestReturnValue {\n\tsubmissions: Created<FormSubmission>[]\n\tattachments: Created<FormSubmissionAttachment>[]\n\tpresigned_urls: PresignedUrlsResponse\n}\n\nexport abstract class FormSubmissionService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseUploadService<TState, TSDK> {\n\tprivate async bulkAddSubmissionAttachments(\n\t\tsubmissionId: string,\n\t\tfiles: Record<string, File[]>,\n\t): Promise<OptimisticMultipleModelResult<FormSubmissionAttachment>> {\n\t\tinterface AttachmentPayload {\n\t\t\toffline_id: string\n\t\t\tname: string\n\t\t\tsha1: string\n\t\t\tfield_identifier: string\n\t\t\tdesscription?: string\n\t\t}\n\n\t\tconst submittedAt = new Date().toISOString()\n\t\tconst createdBy = this.client.store.getState().userReducer.currentUser.id\n\n\t\tconst filePayloads: Record<FilePayload[\"sha1\"], FilePayload> = {}\n\t\tconst offlineFormSubmissionAttachments: Stored<FormSubmissionAttachment>[] = []\n\t\tconst attachmentPayloads: AttachmentPayload[] = []\n\n\t\tfor (const [fieldIdentifier, filesArray] of Object.entries(files)) {\n\t\t\tfor (const file of filesArray) {\n\t\t\t\tconst sha1 = await hashFile(file)\n\n\t\t\t\tif (!(sha1 in filePayloads)) {\n\t\t\t\t\tfilePayloads[sha1] = {\n\t\t\t\t\t\tsha1,\n\t\t\t\t\t\tfile_type: file.type,\n\t\t\t\t\t\textension: file.name.split(\".\").pop()!,\n\t\t\t\t\t\tsize: file.size,\n\t\t\t\t\t}\n\t\t\t\t\tawait this.client.files.addCache(file, sha1)\n\t\t\t\t}\n\n\t\t\t\tconst offlineFormSubmissionAttachment: Stored<FormSubmissionAttachment> = offline({\n\t\t\t\t\tfile: URL.createObjectURL(file),\n\t\t\t\t\tfile_type: file.type,\n\t\t\t\t\tfile_name: file.name,\n\t\t\t\t\tfile_sha1: sha1,\n\t\t\t\t\tcreated_by: createdBy,\n\t\t\t\t\tsubmission: submissionId,\n\t\t\t\t\tsubmitted_at: submittedAt,\n\t\t\t\t\tfield_identifier: fieldIdentifier,\n\t\t\t\t})\n\t\t\t\tofflineFormSubmissionAttachments.push(offlineFormSubmissionAttachment)\n\n\t\t\t\tconst attachmentPayload: AttachmentPayload = {\n\t\t\t\t\toffline_id: offlineFormSubmissionAttachment.offline_id,\n\t\t\t\t\tname: file.name,\n\t\t\t\t\tsha1,\n\t\t\t\t\tfield_identifier: fieldIdentifier,\n\t\t\t\t}\n\t\t\t\tattachmentPayloads.push(attachmentPayload)\n\t\t\t}\n\t\t}\n\n\t\tthis.dispatch(addFormSubmissionAttachments(offlineFormSubmissionAttachments))\n\n\t\tconst promise = this.enqueueRequest<{\n\t\t\tattachments: Created<FormSubmissionAttachment>[]\n\t\t\tpresigned_urls: PresignedUrlsResponse\n\t\t}>({\n\t\t\tdescription: \"Attach files to form submission\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/forms/submissions/${submissionId}/attachments/bulk/`,\n\t\t\tpayload: {\n\t\t\t\tsubmitted_at: submittedAt,\n\t\t\t\tattachments: attachmentPayloads,\n\t\t\t\tfiles: Object.values(filePayloads),\n\t\t\t},\n\t\t\tblockers: [submissionId],\n\t\t\tblocks: offlineFormSubmissionAttachments.map((attachment) => attachment.offline_id),\n\t\t})\n\n\t\tpromise\n\t\t\t.then((result) => {\n\t\t\t\tthis.processPresignedUrls(result.presigned_urls)\n\t\t\t\tthis.dispatch(updateFormSubmissionAttachments(result.attachments))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(\n\t\t\t\t\tdeleteFormSubmissionAttachments(\n\t\t\t\t\t\tofflineFormSubmissionAttachments.map((attachment) => attachment.offline_id),\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t})\n\n\t\treturn [offlineFormSubmissionAttachments, promise.then(({ attachments }) => attachments)]\n\t}\n\n\tprivate async bulkDeleteSubmissionAttachments(submissionId: string, attachmentsIds: string[]): Promise<void> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst formSubmissionAttachments = selectFormSubmissionAttachemntsByIds(attachmentsIds)(state)\n\n\t\tthis.dispatch(deleteFormSubmissionAttachments(attachmentsIds))\n\n\t\ttry {\n\t\t\tawait this.enqueueRequest<undefined>({\n\t\t\t\tdescription: \"Delete form submission attachments\",\n\t\t\t\tmethod: HttpMethod.DELETE,\n\t\t\t\turl: `/forms/submissions/${submissionId}/attachments/bulk/`,\n\t\t\t\tpayload: { attachments: attachmentsIds },\n\t\t\t\tblockers: [submissionId, ...attachmentsIds],\n\t\t\t\tblocks: [],\n\t\t\t})\n\t\t} catch (e) {\n\t\t\tthis.dispatch(addFormSubmissionAttachments(formSubmissionAttachments))\n\t\t\tthrow e\n\t\t}\n\t}\n\n\t// Outer promise is for hashing and caching files for submission attachments\n\tasync add(\n\t\tpayload: FormSubmissionPayload,\n\t): Promise<\n\t\t[\n\t\t\tStored<FormSubmission>,\n\t\t\tStored<FormSubmissionAttachment>[],\n\t\t\tPromise<Created<FormSubmission>>,\n\t\t\tPromise<Created<FormSubmissionAttachment>[]>,\n\t\t]\n\t> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\t\tconst activeProjectId = state.projectReducer.activeProjectId\n\n\t\tif (!activeProjectId) {\n\t\t\tthrow new Error(\"Expected an active project\")\n\t\t}\n\n\t\tconst { values, files } = separateFilesFromValues(payload.values)\n\n\t\tconst offlineSubmission: Submitted<FormSubmission> = offline({\n\t\t\t...payload,\n\t\t\tvalues: values,\n\t\t\tcreated_by: state.userReducer.currentUser.id,\n\t\t\tsubmitted_at: new Date().toISOString(),\n\t\t})\n\n\t\tconst promise = this.enqueueRequest<FormSubmission>({\n\t\t\tdescription: \"Respond to form\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/forms/revisions/${payload.form_revision}/respond/`,\n\t\t\tpayload: { ...offlineSubmission, project: activeProjectId },\n\t\t\tblockers: [payload.issue, payload.asset, payload.asset_stage, \"add-form-entry\"].filter(\n\t\t\t\t(x) => x !== undefined,\n\t\t\t) as string[],\n\t\t\tblocks: [offlineSubmission.offline_id],\n\t\t})\n\n\t\tthis.dispatch(addFormSubmission(offlineSubmission))\n\n\t\tconst [offlineFormSubmissionAttachments, attachmentsPromise] = await this.bulkAddSubmissionAttachments(\n\t\t\tofflineSubmission.offline_id,\n\t\t\tfiles,\n\t\t)\n\n\t\tpromise\n\t\t\t.then((result) => {\n\t\t\t\tthis.dispatch(addActiveProjectFormSubmissionsCount(1))\n\t\t\t\tthis.dispatch(setFormSubmission(result))\n\t\t\t\treturn result\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(deleteFormSubmission(offlineSubmission.offline_id))\n\t\t\t\tthis.dispatch(addActiveProjectFormSubmissionsCount(-1))\n\t\t\t})\n\n\t\treturn [offlineSubmission, offlineFormSubmissionAttachments, promise, attachmentsPromise]\n\t}\n\n\t// Note currently the bulkAdd method is specific to form submissions for assets\n\t// TODO: adapt the support bulk adding to any model type\n\tasync bulkAdd(\n\t\targs: {\n\t\t\tformRevision: string\n\t\t\tcommonFieldValues: Record<string, FieldValue>\n\t\t\tfieldValuesByAsset: Record<string, Record<string, FieldValue>>\n\t\t},\n\t\tbatchSize: number,\n\t): Promise<Promise<BulkAddRequestReturnValue>[]> {\n\t\tinterface SubmissionPayload {\n\t\t\toffline_id: string\n\t\t\tasset_id: string\n\t\t\tform_data: Record<string, FieldValue>\n\t\t}\n\n\t\tinterface AttachmenPayload {\n\t\t\toffline_id: string\n\t\t\tsubmission_id: string\n\t\t\tsha1: string\n\t\t\tname: string\n\t\t\tfield_identifier: string\n\t\t}\n\n\t\tinterface FilePayload {\n\t\t\tsha1: string\n\t\t\textension: string\n\t\t\tfile_type: string\n\t\t\tsize: number\n\t\t}\n\n\t\tinterface BulkAddPayload {\n\t\t\ttransaction_id: string\n\t\t\tform_data: Record<string, FieldValue>\n\t\t\tsubmitted_at: string\n\t\t\tsubmissions: SubmissionPayload[]\n\t\t\tattachments: AttachmenPayload[]\n\t\t\tfiles: FilePayload[]\n\t\t}\n\n\t\tinterface BulkAddBatch {\n\t\t\tbatchId: string\n\t\t\tpayload: BulkAddPayload\n\t\t}\n\t\t// Things we need to do:\n\t\t// 1. separate any files from the submitted form values\n\t\t// 2. create offline submissions\n\t\t// 3. create offline attachments\n\t\t// 4. deduplicate any files\n\t\tconst { formRevision, commonFieldValues, fieldValuesByAsset } = args\n\n\t\tconst allFilesRecord: Record<string, FilePayload> = {}\n\n\t\tconst { values: fileSeperatedCommonFieldValues, files: commonFiles } =\n\t\t\tseparateFilesFromValues(commonFieldValues)\n\n\t\tconst submittedAt = new Date().toISOString()\n\t\tconst transactionId = uuidv4()\n\n\t\tconst assetIdBatches = chunkArray(Object.keys(fieldValuesByAsset), batchSize)\n\n\t\tconst bulkAddBatches: BulkAddBatch[] = await Promise.all(\n\t\t\tassetIdBatches.map(async (assetIdBatch) => {\n\t\t\t\tconst batchId = uuidv4()\n\t\t\t\tconst submissionPayloads: SubmissionPayload[] = []\n\t\t\t\tconst attachmentPayloads: AttachmenPayload[] = []\n\t\t\t\tconst files: Record<string, File[]> = { ...commonFiles }\n\n\t\t\t\tfor (const assetId of assetIdBatch) {\n\t\t\t\t\tconst { values: fileSeperatedSubmissionSpecificValues, files: submissionSpecificFiles } =\n\t\t\t\t\t\tseparateFilesFromValues(fieldValuesByAsset[assetId] ?? {})\n\n\t\t\t\t\tObject.assign(files, submissionSpecificFiles)\n\n\t\t\t\t\tconst submissionPayload: SubmissionPayload = offline({\n\t\t\t\t\t\tasset_id: assetId,\n\t\t\t\t\t\tform_data: fileSeperatedSubmissionSpecificValues,\n\t\t\t\t\t})\n\n\t\t\t\t\tsubmissionPayloads.push(submissionPayload)\n\n\t\t\t\t\tfor (const [fieldIdentifier, fileArray] of Object.entries(files)) {\n\t\t\t\t\t\tfor (const file of fileArray) {\n\t\t\t\t\t\t\tconst sha1 = await hashFile(file)\n\t\t\t\t\t\t\tawait this.client.files.addCache(file, sha1)\n\n\t\t\t\t\t\t\tconst attachmentPayload: AttachmenPayload = offline({\n\t\t\t\t\t\t\t\tsubmission_id: submissionPayload.offline_id,\n\t\t\t\t\t\t\t\tsha1,\n\t\t\t\t\t\t\t\tname: file.name,\n\t\t\t\t\t\t\t\tfield_identifier: fieldIdentifier,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\tattachmentPayloads.push(attachmentPayload)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst filePaylods: FilePayload[] = []\n\n\t\t\t\tfor (const file of Object.values(files).flat()) {\n\t\t\t\t\tconst sha1 = await hashFile(file)\n\t\t\t\t\tconst filePayload: FilePayload = {\n\t\t\t\t\t\tsha1,\n\t\t\t\t\t\textension: file.name.split(\".\").pop() || \"\",\n\t\t\t\t\t\tfile_type: file.type,\n\t\t\t\t\t\tsize: file.size,\n\t\t\t\t\t}\n\t\t\t\t\tallFilesRecord[sha1] = filePayload\n\t\t\t\t\tfilePaylods.push(filePayload)\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tbatchId,\n\t\t\t\t\tpayload: {\n\t\t\t\t\t\ttransaction_id: transactionId,\n\t\t\t\t\t\tform_data: fileSeperatedCommonFieldValues,\n\t\t\t\t\t\tsubmitted_at: submittedAt,\n\t\t\t\t\t\tsubmissions: submissionPayloads,\n\t\t\t\t\t\tattachments: attachmentPayloads,\n\t\t\t\t\t\tfiles: filePaylods,\n\t\t\t\t\t},\n\t\t\t\t} satisfies BulkAddBatch\n\t\t\t}),\n\t\t)\n\n\t\tconst batchPromises: Promise<BulkAddRequestReturnValue>[] = []\n\t\tlet prevBatchId: string | null = null\n\n\t\tfor (const batch of bulkAddBatches) {\n\t\t\tconst { payload, batchId } = batch\n\n\t\t\tconst batchAssetIds = payload.submissions.map((x) => x.asset_id)\n\t\t\tconst batchSubmissionOfflineIds = payload.submissions.map((x) => x.offline_id)\n\t\t\tconst batchAttachmentsOfflineIds = payload.attachments.map((x) => x.offline_id)\n\n\t\t\tconst blockers = batchAssetIds\n\t\t\tif (prevBatchId) blockers.push(prevBatchId)\n\n\t\t\tconst blocks = [...batchSubmissionOfflineIds, ...batchAttachmentsOfflineIds, batchId]\n\n\t\t\tconst promise = this.enqueueRequest<{\n\t\t\t\tsubmissions: Created<FormSubmission>[]\n\t\t\t\tattachments: Created<FormSubmissionAttachment>[]\n\t\t\t\tpresigned_urls: PresignedUrlsResponse\n\t\t\t}>({\n\t\t\t\tdescription: \"Bulk add form submissions\",\n\t\t\t\tmethod: HttpMethod.POST,\n\t\t\t\turl: `/forms/revisions/${formRevision}/bulk-respond/`,\n\t\t\t\tpayload: payload,\n\t\t\t\tblockers: blockers,\n\t\t\t\tblocks: blocks,\n\t\t\t})\n\n\t\t\tvoid promise.then(({ presigned_urls }) => {\n\t\t\t\tthis.processPresignedUrls(presigned_urls)\n\t\t\t})\n\n\t\t\tprevBatchId = batchId\n\n\t\t\tbatchPromises.push(promise)\n\t\t}\n\n\t\t// Only on success of every batch request, add the submissions and attachments to the store\n\t\tvoid Promise.all(batchPromises).then((results) => {\n\t\t\tconst createdSubmissions: Created<FormSubmission>[] = []\n\t\t\tconst createdAttachments: Created<FormSubmissionAttachment>[] = []\n\n\t\t\tfor (const result of results) {\n\t\t\t\tfor (const createdSubmission of result.submissions) createdSubmissions.push(createdSubmission)\n\t\t\t\tfor (const createdAttachment of result.attachments) createdAttachments.push(createdAttachment)\n\t\t\t}\n\n\t\t\tthis.dispatch(addFormSubmissions(createdSubmissions))\n\t\t\tthis.dispatch(addFormSubmissionAttachments(createdAttachments))\n\t\t})\n\n\t\treturn batchPromises\n\t}\n\n\tasync update(\n\t\tpayload: Offline<Partial<Payload<FormSubmission>>>,\n\t): Promise<\n\t\t[\n\t\t\tStored<FormSubmission>,\n\t\t\tStored<FormSubmissionAttachment>[],\n\t\t\tPromise<Created<FormSubmission>>,\n\t\t\tPromise<Created<FormSubmissionAttachment>[]>,\n\t\t\tPromise<void>,\n\t\t]\n\t> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst submissionToBeUpdated = selectFormSubmissionById(payload.offline_id)(state)\n\n\t\tif (!submissionToBeUpdated) {\n\t\t\tthrow new Error(`Expected submission with offline_id ${payload.offline_id} to exist`)\n\t\t}\n\n\t\tconst { values, files } = separateFilesFromValues(payload.values ?? {})\n\n\t\tconst updatedSubmission: Stored<FormSubmission> = {\n\t\t\t...submissionToBeUpdated,\n\t\t\t...payload,\n\t\t\t// values could also have a partial update\n\t\t\tvalues: {\n\t\t\t\t...submissionToBeUpdated.values,\n\t\t\t\t...values,\n\t\t\t},\n\t\t}\n\n\t\tthis.dispatch(updateFormSubmission(updatedSubmission))\n\n\t\tconst promise = this.enqueueRequest<FormSubmission>({\n\t\t\tdescription: \"Delete user form submissions\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/forms/submissions/${updatedSubmission.offline_id}/`,\n\t\t\tpayload: updatedSubmission,\n\t\t\tblockers: [updatedSubmission.offline_id],\n\t\t\tblocks: [updatedSubmission.offline_id],\n\t\t})\n\n\t\tconst formSubmissionAttachments = selectAttachmentsOfFormSubmission(payload.offline_id)(state)!\n\t\tconst formSubmissionAttachmentIdsToBeDeleted: string[] = []\n\n\t\tfor (const attachment of formSubmissionAttachments) {\n\t\t\tif (attachment.field_identifier in files) {\n\t\t\t\tformSubmissionAttachmentIdsToBeDeleted.push(attachment.offline_id)\n\t\t\t}\n\t\t}\n\n\t\tconst [offlineFormSubmissionAttachments, attachmentsPromise] = await this.bulkAddSubmissionAttachments(\n\t\t\tpayload.offline_id,\n\t\t\tfiles,\n\t\t)\n\n\t\tconst deleteAttachmentsPromise = this.bulkDeleteSubmissionAttachments(\n\t\t\tpayload.offline_id,\n\t\t\tformSubmissionAttachmentIdsToBeDeleted,\n\t\t)\n\n\t\tpromise\n\t\t\t.then((result) => {\n\t\t\t\tthis.dispatch(setFormSubmission(result))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(setFormSubmission(submissionToBeUpdated))\n\t\t\t})\n\n\t\treturn [\n\t\t\tupdatedSubmission,\n\t\t\tofflineFormSubmissionAttachments,\n\t\t\tpromise,\n\t\t\tattachmentsPromise,\n\t\t\tdeleteAttachmentsPromise,\n\t\t]\n\t}\n\n\tasync delete(submissionId: string): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst submissionToBeDeleted = selectFormSubmissionById(submissionId)(state)\n\n\t\tif (!submissionToBeDeleted) {\n\t\t\tthrow new Error(`Expected submission with offline_id ${submissionId} to exist`)\n\t\t}\n\n\t\tconst submissionAttachments = selectAttachmentsOfFormSubmission(submissionId)(state)!\n\n\t\tthis.dispatch(deleteFormSubmission(submissionId))\n\t\tthis.dispatch(addActiveProjectFormSubmissionsCount(-1))\n\t\tthis.dispatch(deleteFormSubmissionAttachments(submissionAttachments.map((x) => x.offline_id)))\n\n\t\ttry {\n\t\t\t// REASON: Need to await to trigger the catch block.\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-confusing-void-expression\n\t\t\treturn await this.enqueueRequest<undefined>({\n\t\t\t\tdescription: \"Delete user form submissions\",\n\t\t\t\tmethod: HttpMethod.DELETE,\n\t\t\t\turl: `/forms/submissions/${submissionId}/`,\n\t\t\t\tblockers: [submissionId],\n\t\t\t\tblocks: [],\n\t\t\t})\n\t\t} catch (e) {\n\t\t\tthis.dispatch(addActiveProjectFormSubmissionsCount(1))\n\t\t\tthis.dispatch(addFormSubmission(submissionToBeDeleted))\n\t\t\tthis.dispatch(addFormSubmissionAttachments(submissionAttachments))\n\t\t\tthrow e\n\t\t}\n\t}\n\n\tasync refreshStore(projectId: number): Promise<void> {\n\t\tconst submissions = await this.enqueueRequest<FormSubmission[]>({\n\t\t\tdescription: \"Fetch form submissions\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/forms/in-project/${projectId}/submissions/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tthis.dispatch(initializeFormSubmissions(submissions))\n\n\t\tconst attachments = await this.enqueueRequest<FormSubmissionAttachment[]>({\n\t\t\tdescription: \"Fetch form attachments\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/forms/in-project/${projectId}/attachments/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tthis.dispatch(initializeFormSubmissionAttachments(attachments))\n\t}\n}\n","import { HttpMethod } from \"enums/api\"\nimport { addWorkspace, deleteWorkspace, initializeWorkspaces, updateWorkspace } from \"store/slices/workspaceSlice\"\nimport { Payload } from \"typings/models/base\"\nimport { Workspace } from \"typings/models/workspace\"\nimport { OptimisticModelResult } from \"../typings\"\nimport { offline } from \"utils/offline\"\nimport { OvermapRootState } from \"../../typings\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class WorkspaceService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tadd(workspace: Payload<Workspace>): OptimisticModelResult<Workspace> {\n\t\tconst { store } = this.client\n\t\tconst offlineWorkspace = offline(workspace)\n\t\tthis.dispatch(addWorkspace(offlineWorkspace))\n\t\tconst promise = this.enqueueRequest<Workspace>({\n\t\t\tdescription: \"Create Workspace\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/projects/${store.getState().projectReducer.activeProjectId}/workspaces/`,\n\t\t\tpayload: offlineWorkspace,\n\t\t\tblockers: [\"add-workspace\"],\n\t\t\tblocks: [offlineWorkspace.offline_id],\n\t\t})\n\n\t\tvoid promise\n\t\t\t.then((result) => {\n\t\t\t\tthis.dispatch(updateWorkspace(result))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(deleteWorkspace(offlineWorkspace.offline_id))\n\t\t\t})\n\n\t\treturn [offlineWorkspace, promise]\n\t}\n\n\tupdate(workspace: Workspace): OptimisticModelResult<Workspace> {\n\t\tthis.dispatch(addWorkspace(workspace))\n\t\tconst promise = this.enqueueRequest<Workspace>({\n\t\t\tdescription: \"Update Workspace\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/workspaces/${workspace.offline_id}/`,\n\t\t\tpayload: workspace,\n\t\t\tblockers: [workspace.offline_id],\n\t\t\tblocks: [workspace.offline_id],\n\t\t})\n\n\t\treturn [workspace, promise]\n\t}\n\n\tdelete(workspaceId: string): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst promise = this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Delete Workspace\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/workspaces/${workspaceId}/`,\n\t\t\tblockers: [workspaceId],\n\t\t\tblocks: [],\n\t\t})\n\t\tconst originalWorkspace = store.getState().workspaceReducer.instances[workspaceId]\n\t\tthis.dispatch(deleteWorkspace(workspaceId))\n\t\tvoid promise\n\t\t\t.then(() => {\n\t\t\t\t// After deleting a workspace, we need to fetch the initial data again because workspace indexes will have\n\t\t\t\t// changed.\n\t\t\t\t// TODO: void this.client.main.fetchInitialData(true).then()\n\t\t\t})\n\t\t\t.catch((reason) => {\n\t\t\t\tif (originalWorkspace) {\n\t\t\t\t\tthis.dispatch(addWorkspace(originalWorkspace))\n\t\t\t\t}\n\t\t\t\tthrow reason\n\t\t\t})\n\t\treturn promise\n\t}\n\n\tasync refreshStore(projectId: number): Promise<undefined> {\n\t\tconst result = await this.enqueueRequest<Workspace[]>({\n\t\t\tdescription: \"Get workspaces\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/workspaces/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t\tthis.dispatch(initializeWorkspaces(result))\n\t}\n}\n","import { HttpMethod } from \"../../enums\"\nimport { OrganizationAccess, Created, OvermapRootState } from \"../../typings\"\nimport {\n\tinitializeOrganizationAccesses,\n\tdeleteOrganizationAccess,\n\tremoveUser,\n\tupdateOrganizationAccess,\n} from \"../../store\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\n/**\n * Handles the creation of OrganizationAccess Service\n */\nexport abstract class OrganizationAccessService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tasync update(organizationAccess: OrganizationAccess): Promise<OrganizationAccess> {\n\t\tconst promise = this.enqueueRequest<Created<OrganizationAccess>>({\n\t\t\tdescription: \"Edit organization access\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/organizations/${organizationAccess.organization}/access/${organizationAccess.offline_id}/`,\n\t\t\tpayload: organizationAccess,\n\t\t\tblockers: [organizationAccess.offline_id],\n\t\t\tblocks: [organizationAccess.offline_id],\n\t\t})\n\n\t\tvoid promise.then(() => {\n\t\t\tthis.dispatch(updateOrganizationAccess(organizationAccess))\n\t\t})\n\n\t\treturn promise\n\t}\n\n\tasync remove(organizationAccess: OrganizationAccess): Promise<undefined> {\n\t\tthis.dispatch(deleteOrganizationAccess(organizationAccess.offline_id))\n\t\tthis.dispatch(removeUser(organizationAccess.user))\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Remove organization access\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/organizations/${organizationAccess.organization}/access/${organizationAccess.offline_id}/`,\n\t\t\tblockers: [organizationAccess.offline_id],\n\t\t\tblocks: [],\n\t\t})\n\t}\n\n\tasync refreshStore(organizationId: number): Promise<void> {\n\t\tconst result = await this.enqueueRequest<OrganizationAccess[]>({\n\t\t\tdescription: \"Get organization accesses\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/organizations/${organizationId}/access/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tthis.dispatch(initializeOrganizationAccesses(result))\n\t}\n}\n","import { BaseApiService } from \"./BaseApiService\"\n\n// TODO: add more methods, add error handling, add quota management etc, make it work for any Attachment\n// Goal is to not use more than 80% of quota, as full utilization would stop the Redux offline store from\n// functioning properly as well\nimport { DBSchema, IDBPDatabase, openDB } from \"idb\"\nimport { HttpMethod } from \"enums\"\nimport { fileToBlob, getFileS3Key, getRenamedFile, hashFile } from \"utils\"\nimport { selectUploadUrl, setUploadUrl } from \"store/slices/fileSlice\"\nimport { APIError } from \"../errors\"\nimport { SDKRequest } from \"../typings\"\nimport type { BaseSDK } from \"../base\"\nimport { BaseState } from \"../../typings\"\n\nexport interface GetS3UrlSuccessResponse {\n\turl: string\n\tfields: Record<string, string>\n}\n\ninterface GetS3UrlWarningResponse {\n\twarning: string\n}\n\nexport type GetS3UrlResponse = GetS3UrlSuccessResponse | GetS3UrlWarningResponse\n\ninterface DatabaseFileProperties {\n\tfile_name: string\n\tfile_sha1: string\n\t/** When uploading, this is the s3 key of the file.\n\t * When downloading, this is the s3 public url.\n\t */\n\tfile: string\n}\n\ninterface FileCacheDB extends DBSchema {\n\tfiles: {\n\t\tvalue: File\n\t\tkey: string\n\t}\n}\n\nconst cachedRequestPromises: Record<string, Promise<File> | undefined> = {}\n// Used to minimize writing to the cache.\nconst _cachedKeys = new Set<string>()\n\n// <ANALYTICS>\nlet _filePutCacheHits = 0\nlet _filePutCacheMisses = 0\nlet _totalCount = 0\nconst summarizeEvery = 20\n// </ANALYTICS>\n\nexport abstract class FileService<TState extends BaseState, TSDK extends BaseSDK<TState>> extends BaseApiService<\n\tTState,\n\tTSDK\n> {\n\thost = import.meta.env.REACT_APP_API_URL as string\n\t// NOTE: If you alter the schema (of the IndexedDB database) in any way, you must increment the version in order to\n\t// migrate the store. This allows idb to automatically migrate the user's existing data to the new schema.\n\tprivate _dbPromise = openDB<FileCacheDB>(\"fileCache\", 1, {\n\t\tupgrade(db) {\n\t\t\tdb.createObjectStore(\"files\")\n\t\t},\n\t})\n\n\tprivate async renewUploadUrl(sha1: string): Promise<GetS3UrlResponse> {\n\t\tconst file = await this.fetchCache(sha1)\n\t\tif (!file) throw new Error(`File with sha1 ${sha1} not found in cache`)\n\t\tconst key = await getFileS3Key(file, sha1)\n\n\t\tconst s3UploadUrl = await this.enqueueRequest<GetS3UrlResponse>({\n\t\t\tdescription: \"Get S3 URL\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: \"/authentication/files/presigned-upload-url/\",\n\t\t\tqueryParams: {\n\t\t\t\tsha1: await hashFile(file),\n\t\t\t\tfile_type: file.type,\n\t\t\t\textension: file.name.split(\".\").pop(),\n\t\t\t\tsize: file.size.toString(),\n\t\t\t},\n\t\t\tblockers: [],\n\t\t\tblocks: [`s3-${key}`],\n\t\t})\n\n\t\tif (\"url\" in s3UploadUrl) {\n\t\t\t// TODO: Why save it to the store?\n\t\t\tthis.dispatch(setUploadUrl({ sha1, ...s3UploadUrl }))\n\t\t}\n\t\treturn s3UploadUrl\n\t}\n\n\t/**\n\t * Adds a file to the cache using the sha1 hash as the key and returns the sha1 hash.\n\t * @param file The file to add to the cache\n\t * TODO: This should be removed once the bug described in [1] is fixed.\n\t * @param sha1 The sha1 hash of the file to cache.\n\t */\n\tasync addCache(file: File, sha1: string): Promise<void> {\n\t\tif (_cachedKeys.has(sha1)) {\n\t\t\treturn\n\t\t}\n\t\t// TODO: Check\n\t\tif (!file.type) {\n\t\t\tconst parts = file.name.split(\".\")\n\t\t\tconst extension = parts[parts.length - 1]\n\t\t\tfile = new File([file], file.name, { type: extension })\n\t\t}\n\t\tif (!file.name || !file.size || !file.type) {\n\t\t\tthrow new Error(\"Cannot add files to cache that do not have a name, size and type.\")\n\t\t}\n\t\tconst fileStorage: IDBPDatabase<FileCacheDB> = await this._dbPromise\n\t\t// TODO: Is this an improvement or not?\n\t\tconst alreadyCached = !!(await fileStorage.get(\"files\", sha1))\n\t\tif (!alreadyCached) {\n\t\t\tawait fileStorage.put(\"files\", file, sha1)\n\t\t\t_filePutCacheMisses++\n\t\t} else {\n\t\t\tconsole.error(\"File already cached (this is unexpected at this point):\", file.name, sha1)\n\t\t\t_filePutCacheHits++\n\t\t}\n\t\t_cachedKeys.add(sha1)\n\t\t_totalCount++\n\t\tif (_totalCount % summarizeEvery === 0) {\n\t\t\t// TODO: If this ends up hitting the console more often than not, they `alreadyCached` check might be more\n\t\t\t// performant than overwriting the identical file in the database. Because all file names saved are based\n\t\t\t// on the sha1 hash, we can guarantee that the files are identical, so there is no point in overwriting.\n\t\t\tconsole.debug(\n\t\t\t\t\"File cache summary: \" +\n\t\t\t\t\t`${_filePutCacheHits} hits and ${_filePutCacheMisses} misses, ` +\n\t\t\t\t\t`${(_filePutCacheHits / (_filePutCacheHits + _filePutCacheMisses)) * 100}% hit rate over ` +\n\t\t\t\t\t`${_totalCount} calls to addCache.`,\n\t\t\t)\n\t\t}\n\t}\n\n\tasync removeCache(sha1: string): Promise<void> {\n\t\tawait (await this._dbPromise).delete(\"files\", sha1)\n\t\t_cachedKeys.delete(sha1)\n\t}\n\n\tasync fetchCache(sha1: string): Promise<File | undefined> {\n\t\treturn (await this._dbPromise).get(\"files\", sha1)\n\t}\n\n\tasync getOrRenewUploadUrl(sha1: string): Promise<GetS3UrlResponse> {\n\t\tconst state = this.client.store.getState()\n\t\tconst uploadUrl = selectUploadUrl(sha1)(state)\n\n\t\treturn uploadUrl ?? (await this.renewUploadUrl(sha1))\n\t}\n\n\t/** Ensure the file has been added to the file cache before calling `uploadFileToS3()` */\n\tasync uploadFileToS3(sha1: string): Promise<[DatabaseFileProperties, Promise<undefined>]> {\n\t\tconst file = await this.fetchCache(sha1)\n\n\t\tif (!file) throw new Error(`File with sha1 ${sha1} not found in cache`)\n\n\t\tconst key = await getFileS3Key(file, sha1)\n\t\tconst dbFileProperties: DatabaseFileProperties = {\n\t\t\tfile_name: file.name,\n\t\t\tfile_sha1: sha1,\n\t\t\tfile: key,\n\t\t}\n\t\tconst fileUploadUrlResponse: GetS3UrlResponse = await this.getOrRenewUploadUrl(sha1)\n\n\t\tif (\"warning\" in fileUploadUrlResponse) {\n\t\t\tif (fileUploadUrlResponse.warning === \"already_uploaded\") {\n\t\t\t\treturn [dbFileProperties, Promise.resolve(undefined).then()]\n\t\t\t}\n\t\t\tthrow new Error(fileUploadUrlResponse.warning)\n\t\t}\n\n\t\tconst url = fileUploadUrlResponse.url\n\t\tconst promise = this.enqueueRequest<undefined>({\n\t\t\turl,\n\t\t\tdescription: \"Upload file\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\tisExternalUrl: true,\n\t\t\tisAuthNeeded: false,\n\t\t\tattachmentHash: sha1,\n\t\t\tblockers: [`s3-${key}`],\n\t\t\tblocks: [sha1],\n\t\t\ts3url: fileUploadUrlResponse,\n\t\t} satisfies SDKRequest)\n\n\t\treturn [dbFileProperties, promise]\n\t}\n\n\t/**\n\t * Fetches a file based on its URL and SHA1. SHA1 values should be known ahead of time because the SHA1 and URL of\n\t * any file is stored in a FileModelMixin (see backend). If the expected SHA1 doesn't match the actual SHA1 of the\n\t * file, an error will be thrown.\n\t * @param url The URL from which to get the file.\n\t * @param expectedSha1 The expected SHA1 of the file. If this doesn't match the actual SHA1 of the file, an error\n\t * will be thrown.\n\t * @param downloadedName (Optional) The name to give the file after download. Set to the name of an attachment, for\n\t * example.\n\t */\n\tasync fetchFileFromUrl(url: string, expectedSha1: string, downloadedName?: string | undefined): Promise<File> {\n\t\tconst requestCacheKey: string = url.split(\"?\")[0] ?? url\n\n\t\tconst cachedResult = await this.fetchCache(expectedSha1)\n\n\t\tif (cachedResult) {\n\t\t\tif (!cachedResult.name) {\n\t\t\t\tthrow new Error(\"Cached file unexpectedly has no name.\")\n\t\t\t}\n\t\t\treturn cachedResult\n\t\t}\n\n\t\tif (url.startsWith(\"blob:\")) {\n\t\t\tconst blob = await fileToBlob(url)\n\t\t\tconst file = new File([blob], downloadedName ?? expectedSha1, { type: blob.type })\n\t\t\tawait this.addCache(file, expectedSha1)\n\t\t\treturn file\n\t\t}\n\n\t\tlet promise = cachedRequestPromises[requestCacheKey]\n\t\tlet isFirstRequest = true\n\n\t\tif (!promise) {\n\t\t\tpromise = new Promise((resolve) => {\n\t\t\t\tvoid this.enqueueRequest<Blob>({\n\t\t\t\t\tdescription: \"Download file\",\n\t\t\t\t\tmethod: HttpMethod.GET,\n\t\t\t\t\turl,\n\t\t\t\t\t// If in development, we should assume the files are saved at localhost by the Django development server.\n\t\t\t\t\t// Setting this to true will lead to localhost:8000 being prepended to the URL.\n\t\t\t\t\tisExternalUrl: import.meta.env.PROD || url.startsWith(\"https://\"),\n\t\t\t\t\tisResponseBlob: true,\n\t\t\t\t\tisAuthNeeded: false,\n\t\t\t\t\tblockers: [expectedSha1],\n\t\t\t\t\tblocks: [expectedSha1],\n\t\t\t\t}).then((blob) => {\n\t\t\t\t\tconst blobToFile = new File([blob], downloadedName ?? expectedSha1, { type: blob.type })\n\t\t\t\t\tresolve(blobToFile)\n\t\t\t\t})\n\t\t\t})\n\t\t\tcachedRequestPromises[requestCacheKey] = promise\n\t\t} else {\n\t\t\tisFirstRequest = false\n\t\t}\n\n\t\tlet file: File\n\n\t\ttry {\n\t\t\tfile = await promise\n\t\t} catch (e) {\n\t\t\tif (isFirstRequest && e instanceof APIError) {\n\t\t\t\t// Don't cache failed promises\n\t\t\t\tdelete cachedRequestPromises[requestCacheKey]\n\t\t\t}\n\t\t\tthrow e\n\t\t}\n\n\t\tif (isFirstRequest) {\n\t\t\t// The first request for this image (in case there are concurrent ones) has the responsibility to cache the\n\t\t\t// file itself.\n\t\t\tconst actualSha1 = await hashFile(file)\n\t\t\tif (actualSha1 !== expectedSha1) {\n\t\t\t\tconst message = `The hash of the file returned from the server (${actualSha1}) does not match the \n\t\t\t\t\texpected hash (${expectedSha1}). This can happen if you're using a local development server and the \n\t\t\t\t\tisExternalUrl flag in the request details is set to true, because instead of requesting the local\n\t\t\t\t\tREST API, you will be requesting localhost:80 (where this app runs), resulting in a transformed blob\n\t\t\t\t\t(with an offline_id attached) being returned. Alternatively, you may be running with \n\t\t\t\t\timport.meta.env.PROD, which will result in some file requests being treated as\n\t\t\t\t\texternal URLs and therefore not prepended with VITE_API_URL.`\n\n\t\t\t\tthrow new Error(message)\n\t\t\t}\n\t\t\t// All files need a name. Otherwise, they might end up with duplicated keys in the PrimeReact FileUpload\n\t\t\t// asset (it uses the name, size and type as the key).\n\t\t\tconst extension = file.type.split(\"/\")[1]\n\t\t\tif (!extension) {\n\t\t\t\tthrow new Error(\"File has no extension\")\n\t\t\t}\n\t\t\tconst fileName = downloadedName ?? actualSha1 + \".\" + extension\n\n\t\t\tfile = getRenamedFile(file, fileName)\n\n\t\t\tif (!file.name) {\n\t\t\t\tthrow new Error(\"Failed to set file's name\")\n\t\t\t}\n\n\t\t\tawait this.addCache(file, actualSha1)\n\n\t\t\t// Overwrite the cached promise, so it returns the renamed file\n\t\t\tcachedRequestPromises[requestCacheKey] = new Promise((resolve) => {\n\t\t\t\tresolve(file)\n\t\t\t})\n\t\t}\n\n\t\treturn file\n\t}\n}\n","import { HttpMethod } from \"../../enums\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\nimport { EmailVerificationPayload, EmailVerificationReturn, OvermapRootState, VerificationCode } from \"../../typings\"\n\nexport abstract class EmailVerificationService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tasync getVerificationCode(verificationCode: string): Promise<VerificationCode> {\n\t\treturn this.enqueueRequest<VerificationCode>({\n\t\t\tdescription: \"Get verification code\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/verification/email-verification/${verificationCode}/`,\n\t\t\tisAuthNeeded: false,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t}\n\n\tvalidateVerificationCode(\n\t\tverificationCode: string,\n\t\tpayload: EmailVerificationPayload | undefined = undefined,\n\t): Promise<EmailVerificationReturn> {\n\t\treturn this.enqueueRequest<EmailVerificationReturn>({\n\t\t\tdescription: \"Validate verification code\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/verification/email-verification/${verificationCode}/`,\n\t\t\tisAuthNeeded: false,\n\t\t\tpayload,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t}\n}\n","import { HttpMethod } from \"../../enums\"\nimport { initializeEmailDomains, deleteEmailDomain, addEmailDomain } from \"../../store\"\nimport { EmailDomain, OvermapRootState } from \"../../typings\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class EmailDomainsService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tasync add(orgId: number, email: string): Promise<undefined> {\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Add email domain to organization\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/organizations/${orgId}/email-domains/`,\n\t\t\tpayload: { email },\n\t\t\tblockers: [orgId.toString(), \"create-org\"],\n\t\t\tblocks: [],\n\t\t})\n\t}\n\n\tasync remove(emailDomain: EmailDomain): Promise<undefined> {\n\t\tthis.dispatch(deleteEmailDomain(emailDomain.offline_id))\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Remove email domain from organization\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/organizations/${emailDomain.organization}/email-domains/${emailDomain.offline_id}/`,\n\t\t\tblockers: [emailDomain.domain],\n\t\t\tblocks: [],\n\t\t}).catch((e) => {\n\t\t\tthis.dispatch(addEmailDomain(emailDomain))\n\t\t\tthrow e\n\t\t})\n\t}\n\n\tasync refreshStore(organizationId: number): Promise<undefined> {\n\t\tconst result = await this.enqueueRequest<EmailDomain[]>({\n\t\t\tdescription: \"Fetch email domains for organization\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/organizations/${organizationId}/email-domains/`,\n\t\t\tblockers: [organizationId.toString()],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tthis.dispatch(initializeEmailDomains(result))\n\t}\n}\n","import { Organization, OvermapRootState } from \"../../typings\"\nimport { HttpMethod } from \"../../enums\"\nimport { setOrganizations } from \"../../store\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class OrganizationService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tcreate(name: string): Promise<Organization> {\n\t\treturn this.enqueueRequest<Organization>({\n\t\t\tdescription: \"Create organization\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: \"/organizations/\",\n\t\t\tpayload: { name },\n\t\t\tblockers: [],\n\t\t\tblocks: [`add-org-${name}`, \"create-org\"],\n\t\t})\n\t}\n\n\tasync update(organization: Organization): Promise<Organization> {\n\t\treturn this.enqueueRequest<Organization>({\n\t\t\tdescription: \"Edit organization\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/organizations/${organization.id}/`,\n\t\t\tpayload: organization,\n\t\t\tblockers: [`add-org-${organization.name}`, organization.id.toString()],\n\t\t\tblocks: [organization.id.toString()],\n\t\t})\n\t}\n\n\tasync invite(organizationId: number, email: string): Promise<undefined> {\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Invite user to organization\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/organizations/${organizationId}/invite/${email}/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\t}\n\n\tasync refreshStore(projectId: number, organizationId: number): Promise<void> {\n\t\tconst organizationsRecord: Record<number, Organization> = {}\n\n\t\tconst projectOrganizations = await this.enqueueRequest<Organization[]>({\n\t\t\tdescription: \"Get organizations\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/organizations/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tfor (const organization of projectOrganizations) {\n\t\t\torganizationsRecord[organization.id] = organization\n\t\t}\n\n\t\tconst organization = await this.enqueueRequest<Organization>({\n\t\t\tdescription: \"Get organization\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/organizations/${organizationId}/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\torganizationsRecord[organization.id] = organization\n\n\t\tthis.dispatch(setOrganizations(Object.values(organizationsRecord)))\n\t}\n}\n","import { License, OvermapRootState, Project, Transaction } from \"../../typings\"\nimport { HttpMethod } from \"../../enums\"\nimport { initializeLicences, updateLicense } from \"../../store\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class LicenseService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tasync getLicense(license: License): Promise<License> {\n\t\tconst result = await this.enqueueRequest<License>({\n\t\t\tdescription: \"Get license\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/billing/${license.offline_id}/`,\n\t\t\tisAuthNeeded: true,\n\t\t\tblockers: [\n\t\t\t\tlicense.organization_owner\n\t\t\t\t\t? license.organization_owner.toString()\n\t\t\t\t\t: license.user_owner\n\t\t\t\t\t? license.user_owner.toString()\n\t\t\t\t\t: \"\",\n\t\t\t],\n\t\t\tblocks: [],\n\t\t})\n\t\tthis.dispatch(updateLicense(result))\n\t\treturn result\n\t}\n\n\tasync pauseLicense(license: License): Promise<License> {\n\t\tconst result = await this.enqueueRequest<License>({\n\t\t\tdescription: \"Pause license\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/billing/${license.offline_id}/suspend/`,\n\t\t\tisAuthNeeded: true,\n\t\t\tblockers: [\n\t\t\t\tlicense.organization_owner\n\t\t\t\t\t? license.organization_owner.toString()\n\t\t\t\t\t: license.user_owner\n\t\t\t\t\t? license.user_owner.toString()\n\t\t\t\t\t: \"\",\n\t\t\t],\n\t\t\tblocks: [],\n\t\t})\n\t\tthis.dispatch(updateLicense(result))\n\t\treturn result\n\t}\n\tasync resumeLicense(license: License): Promise<License> {\n\t\tconst result = await this.enqueueRequest<License>({\n\t\t\tdescription: \"Resume license\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/billing/${license.offline_id}/suspend/`,\n\t\t\tisAuthNeeded: true,\n\t\t\tblockers: [\n\t\t\t\tlicense.organization_owner\n\t\t\t\t\t? license.organization_owner.toString()\n\t\t\t\t\t: license.user_owner\n\t\t\t\t\t? license.user_owner.toString()\n\t\t\t\t\t: \"\",\n\t\t\t],\n\t\t\tblocks: [],\n\t\t})\n\t\tthis.dispatch(updateLicense(result))\n\t\treturn result\n\t}\n\n\tasync cancelLicense(license: License): Promise<License> {\n\t\tconst result = await this.enqueueRequest<License>({\n\t\t\tdescription: \"Cancel license\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/billing/${license.offline_id}/`,\n\t\t\tisAuthNeeded: true,\n\t\t\tblockers: [\n\t\t\t\tlicense.organization_owner\n\t\t\t\t\t? license.organization_owner.toString()\n\t\t\t\t\t: license.user_owner\n\t\t\t\t\t? license.user_owner.toString()\n\t\t\t\t\t: \"\",\n\t\t\t],\n\t\t\tblocks: [],\n\t\t})\n\t\tthis.dispatch(updateLicense(result))\n\t\treturn result\n\t}\n\n\tasync attachLicenseToProject(license: License, project: Project): Promise<License> {\n\t\tconst result = await this.enqueueRequest<License>({\n\t\t\tdescription: \"Attach license\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/billing/${license.offline_id}/project/`,\n\t\t\tisAuthNeeded: true,\n\t\t\tpayload: { project: project.id },\n\t\t\tblockers: [\n\t\t\t\tlicense.organization_owner\n\t\t\t\t\t? license.organization_owner.toString()\n\t\t\t\t\t: license.user_owner\n\t\t\t\t\t? license.user_owner.toString()\n\t\t\t\t\t: \"\",\n\t\t\t\tproject.id ? project.id.toString() : \"\",\n\t\t\t],\n\t\t\tblocks: [\"add-issue\", \"add-form-entry\", \"change-access-level\", \"add-workspace\"],\n\t\t})\n\t\tthis.dispatch(updateLicense(result))\n\t\treturn result\n\t}\n\n\tasync detachLicenseFromProject(license: License): Promise<License> {\n\t\tconst result = await this.enqueueRequest<License>({\n\t\t\tdescription: \"Detach license\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/billing/${license.offline_id}/project/`,\n\t\t\tisAuthNeeded: true,\n\t\t\tblockers: [\n\t\t\t\tlicense.organization_owner\n\t\t\t\t\t? license.organization_owner.toString()\n\t\t\t\t\t: license.user_owner\n\t\t\t\t\t? license.user_owner.toString()\n\t\t\t\t\t: \"\",\n\t\t\t],\n\t\t\tblocks: [\"add-issue\", \"add-form-entry\", \"change-access-level\", \"add-workspace\"],\n\t\t})\n\t\tthis.dispatch(updateLicense(result))\n\t\treturn result\n\t}\n\n\tasync getLatestTransaction(license: License): Promise<Transaction> {\n\t\treturn await this.enqueueRequest<Transaction>({\n\t\t\tdescription: \"Get latest transaction\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/billing/${license.offline_id}/transaction/`,\n\t\t\tisAuthNeeded: true,\n\t\t\tblockers: [license.offline_id],\n\t\t\tblocks: [license.offline_id],\n\t\t})\n\t}\n\n\tasync refreshStore(projectId: number, organizationId: number): Promise<void> {\n\t\tconst licencesRecord: Record<string, License> = {}\n\n\t\tconst organizationLicences = await this.enqueueRequest<License[]>({\n\t\t\tdescription: \"Get licenses\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/organizations/${organizationId}/licenses/`,\n\t\t\tisAuthNeeded: true,\n\t\t\tblockers: [organizationId.toString()],\n\t\t\tblocks: [\"add-issue\", \"add-form-entry\", \"change-access-level\", \"add-workspace\"],\n\t\t})\n\n\t\tfor (const license of organizationLicences) {\n\t\t\tlicencesRecord[license.offline_id] = license\n\t\t}\n\n\t\tconst projectLicences = await this.enqueueRequest<License[]>({\n\t\t\tdescription: \"Get licenses\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/licenses/`,\n\t\t\tisAuthNeeded: true,\n\t\t\tblockers: [projectId.toString()],\n\t\t\tblocks: [\"add-issue\", \"add-form-entry\", \"change-access-level\", \"add-workspace\"],\n\t\t})\n\n\t\tfor (const license of projectLicences) {\n\t\t\tlicencesRecord[license.offline_id] = license\n\t\t}\n\n\t\tthis.dispatch(initializeLicences(Object.values(licencesRecord)))\n\t}\n}\n","import { HttpMethod } from \"../../enums\"\nimport {\n\taddDocuments,\n\tmoveDocument,\n\tremoveDocuments,\n\tselectDocumentsMapping,\n\tsetDocuments,\n\tupdateDocuments,\n} from \"../../store\"\nimport { Document, DocumentPayload, MovePosition, OvermapRootState, Stored, Submitted } from \"../../typings\"\nimport { OptimisticModelResult } from \"../typings\"\nimport { offline } from \"../../utils\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class DocumentService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tadd(payload: DocumentPayload): OptimisticModelResult<Document> {\n\t\tconst { store } = this.client\n\t\tconst currentUserId = store.getState().userReducer.currentUser.id\n\t\tconst submittedAt = new Date().toISOString()\n\n\t\tconst offlineDocument: Stored<Document> = offline({\n\t\t\t...payload,\n\t\t\tcreated_by: currentUserId,\n\t\t\tsubmitted_at: submittedAt,\n\t\t})\n\n\t\tthis.dispatch(addDocuments([offlineDocument]))\n\t\tconst promise = this.enqueueRequest<Document>({\n\t\t\tdescription: \"Create Document\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: \"/documents/\",\n\t\t\tpayload: offlineDocument,\n\t\t\tqueryParams: {\n\t\t\t\tparent_document: offlineDocument.parent_document ?? undefined,\n\t\t\t},\n\t\t\t// if adding as a child of another document, need that document to exist first\n\t\t\tblockers: offlineDocument.parent_document ? [offlineDocument.parent_document] : [],\n\t\t\tblocks: [offlineDocument.offline_id],\n\t\t})\n\n\t\tpromise.catch(() => {\n\t\t\tthis.dispatch(removeDocuments([offlineDocument.offline_id]))\n\t\t})\n\n\t\treturn [offlineDocument, promise]\n\t}\n\n\tupdate(document: Submitted<Partial<Document>>): OptimisticModelResult<Document> {\n\t\tconst { store } = this.client\n\t\tconst documentToBeUpdated = store.getState().documentsReducer.documents[document.offline_id]\n\t\tif (!documentToBeUpdated) {\n\t\t\tthrow new Error(\n\t\t\t\t`attempting to update a document with offline_id ${document.offline_id} that does not exist in store.documents`,\n\t\t\t)\n\t\t}\n\t\tthis.dispatch(updateDocuments([document]))\n\t\tconst promise = this.enqueueRequest<Document>({\n\t\t\tdescription: \"Update Document\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/documents/${document.offline_id}/`,\n\t\t\tpayload: document,\n\t\t\tblockers: [document.offline_id],\n\t\t\tblocks: [document.offline_id],\n\t\t})\n\n\t\tpromise.catch(() => {\n\t\t\tupdateDocuments([documentToBeUpdated])\n\t\t})\n\n\t\tconst fullDocument = store.getState().documentsReducer.documents[document.offline_id]!\n\n\t\treturn [fullDocument, promise]\n\t}\n\n\tmove(documentId: string, targetDocumentId: string | null, position: MovePosition): Promise<Document[]> {\n\t\tconst { store } = this.client\n\t\tconst documentsMapping = selectDocumentsMapping(store.getState())\n\t\t/** the documents that need to be reverted if the move operation fails are:\n\t\t * 1. the document itself (could have attempted to change parents, changing to parent_document property)\n\t\t * 2. the parent of the document (the document could have been moved to a different parent, changing the old parents children_documents property)\n\t\t * 3. the target document (could have been the desired new parent document, changing the children_documents property)\n\t\t * 4. the parent of the target document (could have been the desired new parent document, changing the children_documents property) */\n\t\tconst documentsToRevertIfMoveFails: Document[] = []\n\n\t\tconst documentBeingMoved = documentsMapping[documentId]\n\t\tif (!documentBeingMoved) {\n\t\t\tthrow new Error(\n\t\t\t\t`attempting to move a document with offline_id ${documentId} that does not exist in store.documents`,\n\t\t\t)\n\t\t}\n\t\tdocumentsToRevertIfMoveFails.push(documentBeingMoved)\n\n\t\tif (documentBeingMoved.parent_document) {\n\t\t\tdocumentsToRevertIfMoveFails.push(documentsMapping[documentBeingMoved.parent_document]!)\n\t\t}\n\n\t\tif (targetDocumentId) {\n\t\t\tconst targetDocument = documentsMapping[targetDocumentId]\n\t\t\tif (!targetDocument) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`attempting to move a document to target with offline_id ${targetDocumentId} that does not exist in store.documents`,\n\t\t\t\t)\n\t\t\t}\n\t\t\tdocumentsToRevertIfMoveFails.push(targetDocument)\n\n\t\t\tif (targetDocument.parent_document) {\n\t\t\t\tdocumentsToRevertIfMoveFails.push(documentsMapping[targetDocument.parent_document]!)\n\t\t\t}\n\t\t}\n\n\t\tthis.dispatch(moveDocument({ documentId, targetDocumentId, position }))\n\n\t\tconst promise = this.enqueueRequest<Document[]>({\n\t\t\tdescription: \"Move Document\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/documents/${documentId}/move/`,\n\t\t\tqueryParams: {\n\t\t\t\ttarget: targetDocumentId ?? undefined,\n\t\t\t\tposition,\n\t\t\t},\n\t\t\tblockers: [documentId],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tpromise\n\t\t\t.then((result) => {\n\t\t\t\tthis.dispatch(updateDocuments(result))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(updateDocuments(documentsToRevertIfMoveFails))\n\t\t\t})\n\n\t\treturn promise\n\t}\n\n\tdelete(documentId: string): Promise<Document[]> {\n\t\tconst { store } = this.client\n\t\tconst documentsMapping = selectDocumentsMapping(store.getState())\n\t\tconst documentToBeDeleted = documentsMapping[documentId]\n\t\tif (!documentToBeDeleted) {\n\t\t\tthrow new Error(\n\t\t\t\t`attempting to delete a document with offline_id ${documentId} that does not exist in store.documents`,\n\t\t\t)\n\t\t}\n\t\tconst parentDocument = documentToBeDeleted.parent_document\n\t\t\t? documentsMapping[documentToBeDeleted.parent_document]\n\t\t\t: undefined\n\n\t\tthis.dispatch(removeDocuments([documentId]))\n\t\tconst promise = this.enqueueRequest<Document[]>({\n\t\t\tdescription: \"Delete Document\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/documents/${documentId}/`,\n\t\t\tblockers: [documentId],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tpromise\n\t\t\t.then((documentsToUpdate) => {\n\t\t\t\tthis.dispatch(updateDocuments(documentsToUpdate))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(updateDocuments([documentToBeDeleted]))\n\t\t\t\tif (parentDocument) {\n\t\t\t\t\tthis.dispatch(updateDocuments([parentDocument]))\n\t\t\t\t}\n\t\t\t})\n\n\t\treturn promise\n\t}\n\n\tasync refreshStore(projectId: number, organizationId: number): Promise<void> {\n\t\t// NOTE: below fetches are guaranteed to not have any common documents between them since documents are owned exclusively by either a project or an organization\n\n\t\tconst projectDocumentsPromise = this.enqueueRequest<Document[]>({\n\t\t\tdescription: \"Get project documents\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/documents/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tconst organizationDocumentsPromise = this.enqueueRequest<Document[]>({\n\t\t\tdescription: \"Get organization documents\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/organizations/${organizationId}/documents/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\t// Load project documents first because they are more likely to be seen\n\t\tthis.dispatch(setDocuments(await projectDocumentsPromise))\n\n\t\t// Load organization documents\n\t\tthis.dispatch(addDocuments(await organizationDocumentsPromise))\n\t}\n}\n","import { BaseAttachmentService, BuildOfflineAttachmentData } from \"./BaseAttachmentService\"\nimport {\n\taddDocumentAttachments,\n\tdeleteDocumentAttachment,\n\tdeleteDocumentAttachments,\n\tinitializeDocumentAttachments,\n\tselectDocumentAttachment,\n\tsetDocumentAttachment,\n\tupdateDocumentAttachments,\n} from \"../../store\"\nimport { AttachmentModel, Created, DocumentAttachment, OvermapRootState, Stored } from \"../../typings\"\nimport { offline } from \"../../utils\"\nimport { OptimisticMultipleModelResult } from \"../typings\"\nimport type { BaseSDK } from \"../base\"\nimport { HttpMethod } from \"../../enums\"\n\nexport abstract class DocumentAttachmentService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseAttachmentService<TState, TSDK, string, DocumentAttachment> {\n\tattachmentModel = AttachmentModel.Document\n\n\tinitializeAttachments = initializeDocumentAttachments\n\taddAttachments = addDocumentAttachments\n\tupdateAttachments = updateDocumentAttachments\n\tremoveAttachments = deleteDocumentAttachments\n\tremoveAttachment = deleteDocumentAttachment\n\tsetAttachment = setDocumentAttachment\n\n\tselectAttachment = selectDocumentAttachment\n\n\tprivate buildOfflineAttachment(data: BuildOfflineAttachmentData<string>) {\n\t\treturn offline({\n\t\t\tfile: URL.createObjectURL(data.file),\n\t\t\tfile_sha1: data.sha1,\n\t\t\tcreated_by: data.createdBy,\n\t\t\tfile_name: data.file.name,\n\t\t\tfile_type: data.file.type,\n\t\t\tsubmitted_at: data.submittedAt,\n\t\t\tdescription: data.description,\n\t\t\tdocument: data.modelId,\n\t\t}) satisfies Stored<DocumentAttachment>\n\t}\n\n\tasync attachFilesToDocument(\n\t\tfiles: File[],\n\t\tdocumentId: string,\n\t): Promise<OptimisticMultipleModelResult<DocumentAttachment>> {\n\t\treturn this.attachFiles(files, documentId, this.buildOfflineAttachment.bind(this))\n\t}\n\n\tasync deleteDocumentAttachment(attachmentId: string): Promise<void> {\n\t\treturn this.deleteAttachment(attachmentId)\n\t}\n\n\toverride async refreshStore(projectId: number, organizationId: number): Promise<void> {\n\t\tconst projectDocumentAttachments = await this.enqueueRequest<Created<DocumentAttachment>[]>({\n\t\t\tdescription: \"Get document attachments\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/document-attachments/`,\n\t\t\tblocks: [],\n\t\t\tblockers: [],\n\t\t})\n\n\t\tthis.dispatch(this.initializeAttachments(projectDocumentAttachments))\n\n\t\tconst organizationDocumentAttachments = await this.enqueueRequest<Created<DocumentAttachment>[]>({\n\t\t\tdescription: \"Get document attachments\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/organizations/${organizationId}/document-attachments/`,\n\t\t\tblocks: [],\n\t\t\tblockers: [],\n\t\t})\n\n\t\tthis.dispatch(this.addAttachments(organizationDocumentAttachments))\n\t}\n}\n","import { AgentUserConversation, OvermapRootState } from \"../../typings\"\nimport { HttpMethod } from \"../../enums\"\nimport { addConversation, setConversation, initializeConversations, updateConversation } from \"../../store\"\nimport { JSONContent } from \"@tiptap/core\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class AgentService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseApiService<TState, TSDK> {\n\tasync startConversation(prompt: string): Promise<AgentUserConversation> {\n\t\tconst activeProjectId = this.client.store.getState().projectReducer.activeProjectId\n\t\treturn this.enqueueRequest<AgentUserConversation>({\n\t\t\tdescription: \"Start agent conversation\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: \"/agents/prompt/\",\n\t\t\tpayload: {\n\t\t\t\tprompt,\n\t\t\t\tactive_project: activeProjectId,\n\t\t\t},\n\t\t\tblockers: [\"prompt\"],\n\t\t\tblocks: [\"prompt\"],\n\t\t}).then((response) => {\n\t\t\tthis.dispatch(addConversation(response))\n\t\t\treturn response\n\t\t})\n\t}\n\n\t/**\n\t * Prompt the agent with a message.\n\t * @param prompt The message to prompt the agent with.\n\t * @param conversationId If continuing an existing message, the UUID of that conversation.\n\t */\n\tasync continueConversation(prompt: string, conversationId: AgentUserConversation[\"offline_id\"]): Promise<void> {\n\t\tconst { store } = this.client\n\t\tconst activeProjectId = store.getState().projectReducer.activeProjectId\n\n\t\treturn this.enqueueRequest<JSONContent[]>({\n\t\t\tdescription: \"Prompt agent\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: \"/agents/prompt/\",\n\t\t\tpayload: {\n\t\t\t\tprompt: prompt,\n\t\t\t\tactive_project: activeProjectId,\n\t\t\t},\n\t\t\tblockers: [\"prompt\"],\n\t\t\tblocks: [\"prompt\"],\n\t\t\tqueryParams: { conversation_id: conversationId },\n\t\t}).then((response) => {\n\t\t\tconst conversation = store.getState().agentsReducer.instances[conversationId]\n\t\t\tif (!conversation?.offline_id) {\n\t\t\t\tthrow new Error(\"Conversation not found\")\n\t\t\t}\n\t\t\tif (!Array.isArray(response)) {\n\t\t\t\tresponse = [response]\n\t\t\t}\n\t\t\tthis.dispatch(\n\t\t\t\tupdateConversation({\n\t\t\t\t\t...conversation,\n\t\t\t\t\ttiptap_content: [...(conversation.tiptap_content || []), ...response],\n\t\t\t\t}),\n\t\t\t)\n\t\t})\n\t}\n\n\tasync fetchDetails(conversationId: AgentUserConversation[\"offline_id\"]): Promise<void> {\n\t\treturn this.enqueueRequest<AgentUserConversation>({\n\t\t\tdescription: \"Get agent conversation\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/agents/conversations/${conversationId}/`,\n\t\t\tblockers: [\"conversation\"],\n\t\t\tblocks: [\"conversation\"],\n\t\t}).then((response) => {\n\t\t\tthis.dispatch(setConversation(response))\n\t\t})\n\t}\n\n\tasync rate(responseId: string, rating: 1 | 5): Promise<undefined> {\n\t\treturn this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Rate agent response\",\n\t\t\tmethod: HttpMethod.PUT,\n\t\t\turl: `/agents/responses/${responseId}/rate/`,\n\t\t\tpayload: { rating },\n\t\t\tblockers: [\"rate\"],\n\t\t\tblocks: [\"rate\"],\n\t\t})\n\t}\n\n\tasync refreshStore(projectId: number): Promise<void> {\n\t\tconst result = await this.enqueueRequest<AgentUserConversation[]>({\n\t\t\tdescription: \"Get agent conversation history\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/agent-conversations/`,\n\t\t\tblockers: [\"agent-conversations\"],\n\t\t\tblocks: [\"agent-conversations\"],\n\t\t})\n\t\tthis.dispatch(initializeConversations(result))\n\t}\n}\n","import { OvermapRootState, Stored, Submitted, Team, TeamPayload, User } from \"../../typings\"\nimport { OptimisticModelResult } from \"../typings\"\nimport { offline } from \"../../utils\"\nimport { addTeam, deleteTeam, selectTeamById, setTeam, initializeTeams, updateTeam } from \"../../store\"\nimport { HttpMethod } from \"../../enums\"\nimport { BaseApiService } from \"./BaseApiService\"\nimport type { BaseSDK } from \"../base\"\n\nexport abstract class TeamService<TState extends OvermapRootState, TSDK extends BaseSDK<TState>> extends BaseApiService<\n\tTState,\n\tTSDK\n> {\n\tadd(teamPayload: TeamPayload, organizationId: number): OptimisticModelResult<Team> {\n\t\tconst offlineTeam: Submitted<Team> = offline({\n\t\t\t...teamPayload,\n\t\t\torganization: organizationId,\n\t\t\tsubmitted_at: new Date().toISOString(),\n\t\t\t// TODO: uncomment once supported\n\t\t\t// created_by: state.userReducer.currentUser.id,\n\t\t})\n\n\t\tthis.dispatch(addTeam(offlineTeam))\n\n\t\tconst promise = this.enqueueRequest<Team>({\n\t\t\tdescription: \"Create team\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: `/organizations/${organizationId}/teams/`,\n\t\t\tpayload: offlineTeam,\n\t\t\t// No blocks since users and organizations are not offline\n\t\t\tblockers: [],\n\t\t\tblocks: [offlineTeam.offline_id],\n\t\t})\n\n\t\tpromise\n\t\t\t.then((createdTeam) => {\n\t\t\t\tthis.dispatch(setTeam(createdTeam))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(deleteTeam(offlineTeam.offline_id))\n\t\t\t})\n\n\t\treturn [offlineTeam, promise]\n\t}\n\n\t// TODO: @Audiopolis / Magnus - should we pass a offline_id as one arg and a UpdatedTeamProps as a second arg instead of this set up?\n\tupdate(team: Stored<Team>): OptimisticModelResult<Team> {\n\t\tconst { store } = this.client\n\n\t\tconst teamToBeUpdated = selectTeamById(team.offline_id)(store.getState())\n\n\t\tif (!teamToBeUpdated) {\n\t\t\tthrow new Error(`Expected team with offline_id ${team.offline_id} to exist`)\n\t\t}\n\n\t\tconst offlineUpdatedTeam: Submitted<Team> = {\n\t\t\t...teamToBeUpdated,\n\t\t\t...team,\n\t\t}\n\n\t\tthis.dispatch(updateTeam(offlineUpdatedTeam))\n\n\t\tconst promise = this.enqueueRequest<Team>({\n\t\t\tdescription: \"Update team\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/organizations/teams/${team.offline_id}/`,\n\t\t\tpayload: offlineUpdatedTeam,\n\t\t\tblockers: [team.offline_id],\n\t\t\tblocks: [team.offline_id],\n\t\t})\n\n\t\tpromise\n\t\t\t.then((updatedTeam) => {\n\t\t\t\t// sync the updated team with the store\n\t\t\t\tthis.dispatch(setTeam(updatedTeam))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(setTeam(teamToBeUpdated))\n\t\t\t})\n\n\t\treturn [offlineUpdatedTeam, promise]\n\t}\n\n\tasync delete(teamId: string): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst team = selectTeamById(teamId)(state)\n\n\t\tif (!team) {\n\t\t\tthrow new Error(`Expected team with id ${teamId} to exist`)\n\t\t}\n\n\t\tthis.dispatch(deleteTeam(teamId))\n\n\t\ttry {\n\t\t\t// REASON: Need to await to trigger the catch block.\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-confusing-void-expression\n\t\t\treturn await this.enqueueRequest<undefined>({\n\t\t\t\tdescription: \"Delete team\",\n\t\t\t\tmethod: HttpMethod.DELETE,\n\t\t\t\turl: `/organizations/teams/${teamId}/`,\n\t\t\t\tblockers: [teamId],\n\t\t\t\tblocks: [teamId],\n\t\t\t})\n\t\t} catch (e) {\n\t\t\tthis.dispatch(setTeam(team))\n\t\t\tthrow e\n\t\t}\n\t}\n\n\tasync setMembers(teamId: string, members: User[\"id\"][]): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst team = selectTeamById(teamId)(store.getState())\n\n\t\tif (!team) {\n\t\t\tthrow new Error(`Expected team with id ${teamId} to exist`)\n\t\t}\n\n\t\tif (members.length !== new Set(members).size) {\n\t\t\tthrow new Error(\"Duplicate members found in the list\")\n\t\t}\n\n\t\tthis.dispatch(updateTeam({ ...team, members }))\n\n\t\tconst promise = this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Set team members\",\n\t\t\tmethod: HttpMethod.PUT,\n\t\t\turl: `/organizations/teams/${teamId}/set-members/`,\n\t\t\tpayload: {\n\t\t\t\tusers: members,\n\t\t\t},\n\t\t\tblockers: [teamId],\n\t\t\tblocks: [teamId],\n\t\t})\n\n\t\tpromise.catch(() => {\n\t\t\tthis.dispatch(setTeam(team))\n\t\t})\n\n\t\treturn promise\n\t}\n\n\tasync addMembers(teamId: string, members: User[\"id\"][]): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst team = selectTeamById(teamId)(store.getState())\n\n\t\tif (!team) {\n\t\t\tthrow new Error(`Expected team with id ${teamId} to exist`)\n\t\t}\n\n\t\tconst newMembers = [...team.members, ...members]\n\n\t\treturn this.setMembers(teamId, newMembers)\n\t}\n\n\tasync removeMembers(teamId: string, members: User[\"id\"][]): Promise<undefined> {\n\t\tconst { store } = this.client\n\t\tconst team = selectTeamById(teamId)(store.getState())\n\n\t\tif (!team) {\n\t\t\tthrow new Error(`Expected team with id ${teamId} to exist`)\n\t\t}\n\n\t\tconst newMembers = team.members.filter((member) => !members.includes(member))\n\n\t\treturn this.setMembers(teamId, newMembers)\n\t}\n\n\tasync refreshStore(organizationId: number): Promise<void> {\n\t\t// TODO: fetch for project as well\n\n\t\tconst result = await this.enqueueRequest<Team[]>({\n\t\t\tdescription: \"Fetch teams\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/organizations/${organizationId}/teams/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tthis.dispatch(initializeTeams(result))\n\t}\n}\n","import { BaseApiService } from \"./BaseApiService\"\nimport { setUsers } from \"../../store\"\nimport { OvermapRootState, User } from \"../../typings\"\nimport { BaseSDK } from \"../base\"\nimport { HttpMethod } from \"../../enums\"\n\nexport abstract class UserService<TState extends OvermapRootState, TSDK extends BaseSDK<TState>> extends BaseApiService<\n\tTState,\n\tTSDK\n> {\n\tasync refreshStore(projectId: number, organizationId: number): Promise<void> {\n\t\tconst usersRecord: Record<number, User> = {}\n\n\t\tconst organizationUsers = await this.enqueueRequest<User[]>({\n\t\t\tdescription: \"Fetch organization users\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/organizations/${organizationId}/users/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tfor (const user of organizationUsers) {\n\t\t\tusersRecord[user.id] = user\n\t\t}\n\n\t\tconst projectUsers = await this.enqueueRequest<User[]>({\n\t\t\tdescription: \"Fetch project users\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/users/`,\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tfor (const user of projectUsers) {\n\t\t\tusersRecord[user.id] = user\n\t\t}\n\n\t\tthis.dispatch(setUsers(Object.values(usersRecord)))\n\t}\n}\n","import { HttpMethod } from \"../../enums\"\nimport {\n\tBulkGeoImagePayload,\n\tCreated,\n\tGeoImage,\n\tGeoImagePayload,\n\tOffline,\n\tOvermapRootState,\n\tPointGeometry,\n\tStored,\n\tSubmitted,\n} from \"../../typings\"\n\nimport { OptimisticModelResult, OptimisticMultipleModelResult, PresignedUrlsResponse } from \"../typings\"\nimport { hashFile, offline } from \"../../utils\"\nimport { FilePayload } from \"./BaseAttachmentService\"\nimport type { BaseSDK } from \"../base\"\nimport { BaseUploadService } from \"./BaseUploadService\"\nimport {\n\taddGeoImage,\n\taddGeoImages,\n\tdeleteGeoImage,\n\tdeleteGeoImages,\n\tinitializeGeoImages,\n\tselectGeoImageById,\n\tsetGeoImage,\n\tsetGeoImages,\n\tupdateGeoImage,\n} from \"../../store\"\n\ninterface BulkCreateGeoImagesPayload {\n\tsubmitted_at: string\n\tproject: number\n\tgeo_images: {\n\t\t// requireds\n\t\toffline_id: string\n\t\tsha1: string\n\t\tfile_name: string\n\t\t// optionals\n\t\ttitle?: string\n\t\tdescription?: string\n\t\tgeo_marker?: PointGeometry\n\t\tcanvas_marker?: PointGeometry\n\n\t\tdirection?: number\n\t\toriginal_date?: string\n\t}[]\n\tfiles: FilePayload[]\n}\n\ninterface CreateGeoImageResult {\n\tgeo_image: Created<GeoImage>\n\tpresigned_urls: PresignedUrlsResponse\n}\n\ninterface BulkCreateMapImagesResult {\n\tgeo_images: Created<GeoImage>[]\n\tpresigned_urls: PresignedUrlsResponse\n}\n\nexport abstract class GeoImageService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseUploadService<TState, TSDK> {\n\tasync add(payload: GeoImagePayload): Promise<OptimisticModelResult<GeoImage>> {\n\t\tconst { store } = this.client\n\n\t\tconst { file, ...payloadWithoutFile } = payload\n\n\t\tconst submittedAt = new Date().toISOString()\n\t\tconst currentUser = store.getState().userReducer.currentUser\n\t\tconst projectId = payloadWithoutFile.project\n\n\t\tconst sha1 = await hashFile(file)\n\n\t\tconst filePayload: FilePayload = {\n\t\t\tsha1,\n\t\t\tfile_type: file.type,\n\t\t\textension: file.name.split(\".\").pop()!,\n\t\t\tsize: file.size,\n\t\t}\n\n\t\tconst offlineMapImage: Stored<GeoImage> = offline({\n\t\t\t...payloadWithoutFile,\n\t\t\tfile_name: file.name,\n\t\t\tfile_sha1: sha1,\n\t\t\tfile: URL.createObjectURL(file),\n\t\t\tsubmitted_at: submittedAt,\n\t\t\tcreated_by: currentUser.id,\n\t\t})\n\n\t\tstore.dispatch(addGeoImage(offlineMapImage))\n\n\t\tconst promise = this.enqueueRequest<CreateGeoImageResult>({\n\t\t\tdescription: \"Add geo image\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: \"/geo-images/\",\n\t\t\tpayload: {\n\t\t\t\toffline_id: offlineMapImage.offline_id,\n\t\t\t\tsubmitted_at: submittedAt,\n\t\t\t\ttitle: offlineMapImage.title,\n\t\t\t\tdescription: offlineMapImage.description,\n\t\t\t\tgeo_marker: offlineMapImage.geo_marker,\n\t\t\t\tcanvas_marker: offlineMapImage.canvas_marker,\n\t\t\t\tsha1: offlineMapImage.file_sha1,\n\t\t\t\tproject: offlineMapImage.project,\n\t\t\t\tfile_name: offlineMapImage.file_name,\n\t\t\t\tdirection: offlineMapImage.direction,\n\t\t\t\toriginal_date: offlineMapImage.original_date,\n\t\t\t\tfile: filePayload,\n\t\t\t},\n\t\t\tblocks: [projectId.toString()],\n\t\t\tblockers: [projectId.toString()],\n\t\t})\n\n\t\tpromise\n\t\t\t.then((result) => {\n\t\t\t\tthis.processPresignedUrls(result.presigned_urls)\n\t\t\t\tstore.dispatch(setGeoImage(result.geo_image))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tstore.dispatch(deleteGeoImage(offlineMapImage.offline_id))\n\t\t\t})\n\n\t\treturn [offlineMapImage, promise.then((result) => result.geo_image)]\n\t}\n\n\tasync bulkAdd(\n\t\tpayloads: BulkGeoImagePayload[],\n\t\tprojectId: number,\n\t): Promise<OptimisticMultipleModelResult<GeoImage>> {\n\t\tconst { store } = this.client\n\n\t\tconst submittedAt = new Date().toISOString()\n\t\tconst currentUser = store.getState().userReducer.currentUser\n\n\t\tconst offlineGeoImages: Submitted<GeoImage>[] = []\n\t\tconst offlineIds: string[] = []\n\t\tconst geoImagePayloads: BulkCreateGeoImagesPayload[\"geo_images\"] = []\n\t\tconst filePayloadRecord: Record<string, FilePayload> = {}\n\n\t\tfor (const payloadAndFile of payloads) {\n\t\t\tconst { file, ...payload } = payloadAndFile\n\n\t\t\tconst sha1 = await hashFile(file)\n\t\t\tif (!(sha1 in filePayloadRecord)) {\n\t\t\t\tfilePayloadRecord[sha1] = {\n\t\t\t\t\tsha1,\n\t\t\t\t\tfile_type: file.type,\n\t\t\t\t\textension: file.name.split(\".\").pop()!,\n\t\t\t\t\tsize: file.size,\n\t\t\t\t}\n\t\t\t\tawait this.client.files.addCache(file, sha1)\n\t\t\t}\n\n\t\t\tconst offlineMapImage: Stored<GeoImage> = offline({\n\t\t\t\t...payload,\n\t\t\t\tfile_name: file.name,\n\t\t\t\tfile_sha1: sha1,\n\t\t\t\tfile: URL.createObjectURL(file),\n\t\t\t\tsubmitted_at: submittedAt,\n\t\t\t\tcreated_by: currentUser.id,\n\t\t\t\tproject: projectId,\n\t\t\t})\n\t\t\tofflineGeoImages.push(offlineMapImage)\n\n\t\t\tofflineIds.push(offlineMapImage.offline_id)\n\n\t\t\tgeoImagePayloads.push({\n\t\t\t\toffline_id: offlineMapImage.offline_id,\n\t\t\t\tsha1: offlineMapImage.file_sha1,\n\t\t\t\tfile_name: offlineMapImage.file_name,\n\n\t\t\t\ttitle: offlineMapImage.title,\n\t\t\t\tdescription: offlineMapImage.description,\n\t\t\t\tgeo_marker: offlineMapImage.geo_marker,\n\t\t\t\tcanvas_marker: offlineMapImage.canvas_marker,\n\t\t\t\tdirection: offlineMapImage.direction,\n\t\t\t\toriginal_date: offlineMapImage.original_date,\n\t\t\t})\n\t\t}\n\n\t\tstore.dispatch(addGeoImages(offlineGeoImages))\n\n\t\tconst promise = this.enqueueRequest<BulkCreateMapImagesResult>({\n\t\t\tdescription: \"Bulk add geo images\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: \"/geo-images/bulk/\",\n\t\t\tpayload: {\n\t\t\t\tsubmitted_at: submittedAt,\n\t\t\t\tproject: projectId,\n\t\t\t\tgeo_images: geoImagePayloads,\n\t\t\t\tfiles: Object.values(filePayloadRecord),\n\t\t\t} satisfies BulkCreateGeoImagesPayload,\n\t\t\tblocks: [projectId.toString()],\n\t\t\tblockers: offlineIds,\n\t\t})\n\n\t\tpromise\n\t\t\t.then((result) => {\n\t\t\t\tthis.processPresignedUrls(result.presigned_urls)\n\t\t\t\tstore.dispatch(setGeoImages(result.geo_images))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tstore.dispatch(deleteGeoImages(offlineIds))\n\t\t\t})\n\n\t\treturn [offlineGeoImages, promise.then((result) => result.geo_images)]\n\t}\n\n\tupdate(payload: Offline<Partial<Pick<GeoImagePayload, \"title\" | \"description\">>>): OptimisticModelResult<GeoImage> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst geoImageToUpdate = selectGeoImageById(payload.offline_id)(state)\n\n\t\tif (!geoImageToUpdate) {\n\t\t\tthrow new Error(`Map image with offline_id ${payload.offline_id} does not exist in the store`)\n\t\t}\n\n\t\tconst updatedGeoImage: Stored<GeoImage> = { ...geoImageToUpdate, ...payload }\n\n\t\tstore.dispatch(updateGeoImage(updatedGeoImage))\n\n\t\tconst promise = this.enqueueRequest<Created<GeoImage>>({\n\t\t\tdescription: \"Update geo image\",\n\t\t\tmethod: HttpMethod.PATCH,\n\t\t\turl: `/geo-images/${payload.offline_id}/`,\n\t\t\tpayload: payload,\n\t\t\tblocks: [payload.offline_id],\n\t\t\tblockers: [payload.offline_id],\n\t\t})\n\n\t\tpromise\n\t\t\t.then((result) => {\n\t\t\t\tstore.dispatch(setGeoImage(result))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tstore.dispatch(setGeoImage(geoImageToUpdate))\n\t\t\t})\n\n\t\treturn [updatedGeoImage, promise]\n\t}\n\n\tasync delete(geoImageId: string): Promise<void> {\n\t\tconst { store } = this.client\n\t\tconst state = store.getState()\n\n\t\tconst geoImageToDelete = selectGeoImageById(geoImageId)(state)\n\n\t\tif (!geoImageToDelete) {\n\t\t\tthrow new Error(`Map image with offline_id ${geoImageId} does not exist in the store`)\n\t\t}\n\n\t\tstore.dispatch(deleteGeoImage(geoImageId))\n\n\t\tconst promise = this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Delete geo image\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/geo-images/${geoImageId}/`,\n\t\t\tblocks: [geoImageId],\n\t\t\tblockers: [geoImageId],\n\t\t})\n\n\t\tpromise.catch(() => {\n\t\t\tstore.dispatch(setGeoImage(geoImageToDelete))\n\t\t})\n\n\t\treturn promise\n\t}\n\n\tasync refreshStore(projectId: number): Promise<void> {\n\t\tconst { store } = this.client\n\n\t\tconst result = await this.enqueueRequest<Created<GeoImage>[]>({\n\t\t\tdescription: \"Get geo images\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: `/projects/${projectId}/geo-images/`,\n\t\t\tblocks: [projectId.toString()],\n\t\t\tblockers: [],\n\t\t})\n\n\t\tstore.dispatch(initializeGeoImages(result))\n\t}\n}\n","import type { IssueAssociation, OvermapRootState, Payload, Stored } from \"../../typings\"\n\nimport type { OptimisticModelResult } from \"../typings\"\nimport type { BaseSDK } from \"../base\"\nimport { BaseUploadService } from \"./BaseUploadService\"\nimport { offline } from \"../../utils\"\nimport {\n\taddIssueAssociation,\n\tdeleteIssueAssociation,\n\tinitializeIssueAssociations,\n\tselectIssueAssociationById,\n\tupdateIssueAssociation,\n} from \"../../store\"\nimport { HttpMethod } from \"../../enums\"\n\nexport abstract class IssueAssociationService<\n\tTState extends OvermapRootState,\n\tTSDK extends BaseSDK<TState>,\n> extends BaseUploadService<TState, TSDK> {\n\tadd(payload: Payload<IssueAssociation>): OptimisticModelResult<IssueAssociation> {\n\t\tconst { store } = this.client\n\n\t\tconst submittedAt = new Date().toISOString()\n\t\tconst createdBy = store.getState().userReducer.currentUser.id\n\n\t\tconst offlineIssueAssociation = offline({\n\t\t\t...payload,\n\t\t\tsubmitted_at: submittedAt,\n\t\t\tcreated_by: createdBy,\n\t\t}) satisfies Stored<IssueAssociation>\n\n\t\tthis.dispatch(addIssueAssociation(offlineIssueAssociation))\n\n\t\tconst promise = this.enqueueRequest<IssueAssociation>({\n\t\t\tdescription: \"Add issue association\",\n\t\t\tmethod: HttpMethod.POST,\n\t\t\turl: \"/issues/associations/\",\n\t\t\tpayload: {\n\t\t\t\toffline_id: offlineIssueAssociation.offline_id,\n\t\t\t\tsubmitted_at: submittedAt,\n\t\t\t\tcreated_by: createdBy,\n\t\t\t\t...payload,\n\t\t\t},\n\t\t\tblockers: [\n\t\t\t\tpayload.associated_issue,\n\t\t\t\t...(payload.issue ? [payload.issue] : []),\n\t\t\t\t...(payload.asset ? [payload.asset] : []),\n\t\t\t],\n\t\t\tblocks: [offlineIssueAssociation.offline_id],\n\t\t})\n\n\t\tpromise\n\t\t\t.then((issueAssociation) => {\n\t\t\t\tthis.dispatch(updateIssueAssociation(issueAssociation))\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tthis.dispatch(deleteIssueAssociation(offlineIssueAssociation.offline_id))\n\t\t\t})\n\n\t\treturn [offlineIssueAssociation, promise]\n\t}\n\n\tasync delete(id: string): Promise<void> {\n\t\tconst { store } = this.client\n\n\t\tconst issueAssociation = selectIssueAssociationById(id)(store.getState())\n\n\t\tif (!issueAssociation) {\n\t\t\tthrow new Error(`Issue association with id ${id} not found in store.`)\n\t\t}\n\n\t\tthis.dispatch(deleteIssueAssociation(id))\n\n\t\tconst promise = this.enqueueRequest<undefined>({\n\t\t\tdescription: \"Delete issue association\",\n\t\t\tmethod: HttpMethod.DELETE,\n\t\t\turl: `/issues/associations/${id}/`,\n\t\t\tblockers: [id],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tpromise.catch(() => {\n\t\t\tthis.dispatch(addIssueAssociation(issueAssociation))\n\t\t})\n\n\t\treturn promise\n\t}\n\n\tasync refreshStore(projectId: number): Promise<void> {\n\t\tconst issueAssociations = await this.enqueueRequest<IssueAssociation[]>({\n\t\t\tdescription: \"Fetch issue associations\",\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: \"/issues/associations/\",\n\t\t\tqueryParams: { project_id: projectId.toString() },\n\t\t\tblockers: [],\n\t\t\tblocks: [],\n\t\t})\n\n\t\tthis.dispatch(initializeIssueAssociations(issueAssociations))\n\t}\n}\n"],"names":["HttpMethod","IssuePriority","IssueStatus","DepGraph","request","uuid","randomString","VERSION_REDUCER_KEY","_a","migration","initialState","createSlice","saveAs","uuidv4","self","useRef","useEffect","gray","gold","brown","yellow","amber","orange","red","crimson","pink","plum","purple","violet","iris","indigo","blue","cyan","jade","grass","lime","mint","sky","createSelector","today","ProjectAccessLevel","OrganizationAccessLevel","AttachmentModel","IssueUpdateChange","VerificationCodeType","PaddleCheckoutEvent","LicenseLevel","LicenseStatus","document","combineReducers","createNextState","clientStore","offline","clientSDK","coordinator","unsafeShowToast","RESET_STATE","blocks","issueAttachmentReducer","assetAttachmentReducer","assetTypeAttachmentReducer","documentAttachmentReducer","projectAttachmentReducer","formRevisionAttachmentReducer","formSubmissionAttachmentReducer","geoImageReducer","result","requestDetails","openDB","file","organization"],"mappings":"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","x_google_ignoreList":[5]}