@c8y/ngx-components 1023.78.7 → 1023.80.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/ai/agent-chat/index.d.ts +22 -11
  2. package/ai/agent-chat/index.d.ts.map +1 -1
  3. package/ai/ai-chat/index.d.ts +31 -10
  4. package/ai/ai-chat/index.d.ts.map +1 -1
  5. package/ai/index.d.ts +64 -49
  6. package/ai/index.d.ts.map +1 -1
  7. package/ecosystem/index.d.ts +34 -4
  8. package/ecosystem/index.d.ts.map +1 -1
  9. package/ecosystem/shared/index.d.ts +1 -1
  10. package/ecosystem/shared/index.d.ts.map +1 -1
  11. package/fesm2022/c8y-ngx-components-ai-agent-chat.mjs +237 -129
  12. package/fesm2022/c8y-ngx-components-ai-agent-chat.mjs.map +1 -1
  13. package/fesm2022/c8y-ngx-components-ai-ai-chat.mjs +112 -51
  14. package/fesm2022/c8y-ngx-components-ai-ai-chat.mjs.map +1 -1
  15. package/fesm2022/c8y-ngx-components-ai.mjs +92 -61
  16. package/fesm2022/c8y-ngx-components-ai.mjs.map +1 -1
  17. package/fesm2022/{c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-DFytXNdc.mjs → c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-C8QX6xlf.mjs} +3 -3
  18. package/fesm2022/c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-C8QX6xlf.mjs.map +1 -0
  19. package/fesm2022/c8y-ngx-components-dashboard-details-advanced-tab.mjs +2 -2
  20. package/fesm2022/c8y-ngx-components-datapoints-export-selector.mjs +7 -7
  21. package/fesm2022/c8y-ngx-components-datapoints-export-selector.mjs.map +1 -1
  22. package/fesm2022/c8y-ngx-components-device-enrolment-modal.mjs +3 -3
  23. package/fesm2022/c8y-ngx-components-device-enrolment-modal.mjs.map +1 -1
  24. package/fesm2022/c8y-ngx-components-device-grid.mjs +1 -1
  25. package/fesm2022/c8y-ngx-components-device-grid.mjs.map +1 -1
  26. package/fesm2022/c8y-ngx-components-device-list.mjs +2 -2
  27. package/fesm2022/c8y-ngx-components-device-list.mjs.map +1 -1
  28. package/fesm2022/c8y-ngx-components-ecosystem-shared.mjs +4 -1
  29. package/fesm2022/c8y-ngx-components-ecosystem-shared.mjs.map +1 -1
  30. package/fesm2022/c8y-ngx-components-ecosystem.mjs +151 -53
  31. package/fesm2022/c8y-ngx-components-ecosystem.mjs.map +1 -1
  32. package/fesm2022/c8y-ngx-components-feature-toggles-list.mjs +3 -3
  33. package/fesm2022/c8y-ngx-components-feature-toggles-list.mjs.map +1 -1
  34. package/fesm2022/c8y-ngx-components-search.mjs +2 -2
  35. package/fesm2022/c8y-ngx-components-search.mjs.map +1 -1
  36. package/fesm2022/c8y-ngx-components-widgets-definitions-html-widget-ai-config.mjs +31 -29
  37. package/fesm2022/c8y-ngx-components-widgets-definitions-html-widget-ai-config.mjs.map +1 -1
  38. package/fesm2022/c8y-ngx-components-widgets-implementations-asset-table.mjs +4 -4
  39. package/fesm2022/c8y-ngx-components-widgets-implementations-asset-table.mjs.map +1 -1
  40. package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-graph.mjs +5 -5
  41. package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-graph.mjs.map +1 -1
  42. package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-list.mjs +2 -2
  43. package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-list.mjs.map +1 -1
  44. package/fesm2022/c8y-ngx-components-widgets-implementations-pie-chart.mjs +2 -2
  45. package/fesm2022/c8y-ngx-components-widgets-implementations-pie-chart.mjs.map +1 -1
  46. package/fesm2022/c8y-ngx-components.mjs +5 -5
  47. package/fesm2022/c8y-ngx-components.mjs.map +1 -1
  48. package/index.d.ts +1 -0
  49. package/index.d.ts.map +1 -1
  50. package/locales/de.po +152 -198
  51. package/locales/es.po +126 -123
  52. package/locales/fr.po +151 -197
  53. package/locales/ja_JP.po +102 -113
  54. package/locales/ko.po +128 -127
  55. package/locales/locales.pot +101 -92
  56. package/locales/nl.po +129 -128
  57. package/locales/pl.po +126 -127
  58. package/locales/pt_BR.po +125 -126
  59. package/locales/zh_CN.po +126 -128
  60. package/locales/zh_TW.po +128 -129
  61. package/package.json +1 -1
  62. package/search/index.d.ts.map +1 -1
  63. package/widgets/implementations/asset-table/index.d.ts +1 -1
  64. package/fesm2022/c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-DFytXNdc.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"c8y-ngx-components-ai.mjs","sources":["../../ai/ai.service.ts","../../ai/c8y-ngx-components-ai.ts"],"sourcesContent":["import { inject, Injectable } from '@angular/core';\nimport { FetchClient } from '@c8y/client';\nimport { Observable, Subscriber } from 'rxjs';\nimport {\n AgentDefinition,\n AgentHealthCheckResponse,\n AgentStep,\n AIMessage,\n AIStreamResponse,\n ClientAgentDefinition,\n ToolCallPart\n} from './ai.model';\n\n// Internal implementation detail; maybe we don't even need this enum since\nexport enum DataStreamType {\n TEXT_DELTA = 'text-delta',\n TOOL_CALL = 'tool-call',\n TOOL_INPUT_START = 'tool-input-start',\n TOOL_INPUT_DELTA = 'tool-input-delta',\n TOOL_CALL_STREAMING = 'tool-call-streaming',\n TOOL_CALL_DELTA = 'tool-call-delta',\n TOOL_RESULT = 'tool-result',\n REASONING = 'reasoning',\n REASONING_DELTA = 'reasoning-delta',\n REDACTED_REASONING = 'redacted-reasoning',\n REASONING_SIGNATURE = 'reasoning-signature',\n FINISH_REASONING = 'finish-reasoning',\n FINISH = 'finish',\n FINISH_STEP = 'finish-step',\n ERROR = 'error',\n DATA = 'data',\n MESSAGE_ANNOTATIONS = 'message-annotations',\n SOURCE = 'source',\n FILE = 'file',\n STEP_START = 'start-step',\n STEP_FINISH = 'finish-step'\n}\n\n/** This service manages communication with the AI Agent Manager microservice, supporting\n * management of agents, and sending requests to the agents.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class AIService {\n private baseUrl = '/service/ai';\n private client: FetchClient;\n\n // nb: allowing the client to be passed in the constructor allows efficient unit testing without setting up the Angular TestBed\n constructor(client?: FetchClient) {\n this.client = client ?? inject(FetchClient);\n }\n\n /**\n * Creates or updates an agent.\n * @param def The agent definition\n */\n async createOrUpdateAgent(def: AgentDefinition): Promise<void> {\n const health = await this.getAgentHealth(def.name);\n let resource = `${this.baseUrl}/agent/${def.type}`;\n let method = 'POST';\n if (health.exists) {\n resource = `${this.baseUrl}/agent/${def.type}/${def.name}`;\n method = 'PUT';\n }\n const response = await this.client.fetch(resource, {\n body: JSON.stringify(def),\n method,\n headers: { 'Content-Type': 'application/json' }\n });\n\n if (!response.ok) {\n throw new Error(`Failed to create agent: ${response.statusText}`);\n }\n }\n\n /**\n * Check if an agent exists and is ready for use.\n * @param name Agent name (optional)\n * @param fromApp The app context path to check for an agent. This can be used, if the agent should get distributed by the plugin (optional).\n * @returns Agent health check response.\n */\n async getAgentHealth(name = '', fromApp?: string): Promise<AgentHealthCheckResponse> {\n const response = await this.client.fetch(\n `${this.baseUrl}/agent/test/${name || crypto.randomUUID()}${fromApp ? `?fromApp=${fromApp}` : ''}`,\n {\n method: 'GET',\n headers: { 'Content-Type': 'application/json' }\n }\n );\n\n if (!response.ok) {\n return {\n status: response.status === 403 ? 'missing-permissions' : 'missing-microservice',\n exists: false,\n canCreate: false,\n isProviderConfigured: false,\n messages: response.status === 403 ? [] : [response.statusText]\n };\n }\n const json: AgentHealthCheckResponse = await response.json();\n if (!json.isProviderConfigured) {\n json.status = 'missing-provider';\n } else if (!json.exists) {\n json.status = 'missing-agent';\n } else {\n json.status = 'ready';\n }\n return json;\n }\n\n /**\n * Send a text message to the agent.\n * @param name Agent name\n * @param messages The message to send, including any previous message history.\n * Typically you should use `defaultPruneMessagesForAgent` or a custom function to prepare the message history\n * by removing unnecessary content such as large/old tool inputs/outputs.\n * @param variables Variables to include\n * @param fromApp The app context path to check for an agent. This can be used, if the agent should get distributed by the plugin (optional).\n * @returns Text response from the agent.\n */\n async text(\n name: string,\n messages: AIMessage[],\n variables: { [key: string]: any },\n fromApp?: string\n ): Promise<string> {\n const parsedMessages = this.convertToAgentMessageFormat(messages);\n\n const data = this.client.fetch(\n `${this.baseUrl}/agent/text/${name}${fromApp ? `?fromApp=${fromApp}` : ''}`,\n {\n body: JSON.stringify({ messages: parsedMessages, variables }),\n method: 'POST',\n headers: { 'Content-Type': 'application/json' }\n }\n );\n\n const response = await data;\n if (!response.ok) {\n throw new Error(`Failed to talk with agent: ${response.statusText}`);\n }\n const text = await response.text();\n return text;\n }\n\n /**\n * Stream a text message to the agent.\n * @param agent Agent name or an agent definition.\n * @param messages The message to send, including any previous message history.\n * Typically you should use `defaultPruneMessagesForAgent` or a custom function to prepare the message history\n * by removing unnecessary content such as large/old tool inputs/outputs.\n * @param variables Variables to include\n * @param abortController An AbortController to cancel the request.\n * @param fromApp The app context path to check for an agent. This can be used, if the agent should get distributed by the plugin (optional).\n * @returns An observable that emits AIStreamResponse including partial `AIMessage` objects as they are received.\n * When additional useful metadata is available, this will be streamed with type indicating it is metadata.\n * The observable can be cancelled using the provided AbortController.\n * The observable will emit an error if the request fails or is aborted.\n * The observable will complete when the stream is finished.\n *\n * The messages sent to the agent can include special options:\n * - `hiddenContent`: If set, this content will be sent to the agent instead of the `content` field.\n * - `skipToLLM`: If set to true, this message will be skipped when sending to the agent.\n *\n * Example usage:\n * ```typescript\n * const abortController = new AbortController();\n * const messages: AIMessage[] = [\n * { role: 'user', content: 'Hello' },\n * { role: 'assistant', content: 'Hi there!' },\n * { role: 'user', content: 'Tell me a joke.', options: { hiddenContent: 'Tell me a joke about cats.' } }\n * ];\n * const observable = aiService.stream$('my-agent', messages, {}, abortController);\n * const subscription = observable.subscribe({\n * next: (response) => { console.log('Received message update:', response.message); },\n * error: (err) => console.error('Error:', err),\n * complete: () => console.log('Stream complete')\n * });\n *\n * // To cancel the request:\n * abortController.abort();\n * subscription.unsubscribe();\n * ```\n */\n async stream$(\n agent: string | ClientAgentDefinition,\n messages: AIMessage[],\n variables: { [key: string]: any },\n abortController: AbortController,\n fromApp?: string\n ): Promise<Observable<AIStreamResponse>> {\n const parsedMessages = this.convertToAgentMessageFormat(messages);\n\n const agentName = typeof agent === 'string' ? agent : agent.definition.name;\n const useTest = typeof agent !== 'string' && agent.snapshot;\n const baseUrl = useTest\n ? `${this.baseUrl}/agent/test/text`\n : `${this.baseUrl}/agent/text/${agentName}`;\n let body = JSON.stringify({ messages: parsedMessages, variables });\n if (useTest) {\n const agentCopy = {\n ...agent.definition\n };\n agentCopy.agent['messages'] = parsedMessages;\n agentCopy.agent['variables'] = variables;\n body = JSON.stringify(agentCopy);\n }\n\n const response = await this.client.fetch(\n `${baseUrl}?fullResponse=true${fromApp ? `&fromApp=${fromApp}` : ''}`,\n {\n method: 'POST',\n body,\n headers: {\n ...this.client.defaultHeaders,\n 'content-type': 'application/json',\n accept: 'text/event-stream'\n },\n signal: abortController.signal\n }\n );\n\n const stream = response.body;\n const decoder = new TextDecoder();\n\n return new Observable<AIStreamResponse>(observer => {\n if (response.status > 300) {\n response\n .json()\n .then(data => {\n observer.error(`Error communicating with server: ${JSON.stringify(data, null, 2)}`);\n })\n .catch(err => {\n observer.error(\n `Error communicating with server: HTTP ${response.status}: ${response.statusText}; ${err}`\n );\n });\n return;\n }\n\n if (!stream) {\n observer.error('Server error - no response body');\n return;\n }\n\n const reader = stream.getReader();\n const message: AIMessage = {\n role: 'assistant',\n content: '',\n steps: []\n };\n\n const abortHandler = () => {\n reader.cancel();\n observer.error(new DOMException('Aborted', 'AbortError'));\n };\n\n abortController.signal.addEventListener('abort', abortHandler);\n\n let buffer = '';\n\n const read = () => {\n reader.read().then(({ done, value }) => {\n if (done) {\n if (buffer.trim()) this.processLine(buffer, observer, message); // process any remaining data\n observer.complete();\n return;\n }\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n\\n');\n buffer = lines.pop() || '';\n for (const line of lines) {\n if (line.trim()) this.processLine(line, observer, message);\n }\n read();\n });\n };\n\n read();\n return () => {\n abortController.signal.removeEventListener('abort', abortHandler);\n reader.cancel();\n };\n });\n }\n\n protected convertToAgentMessageFormat(messages: AIMessage[]): object[] {\n // We will need to rewrite this to include tool outputs soon (effectively this means targetting LanguageModelV*ToolResultOutput).\n // Once we have more fields than just role and content, we will need to convert between our format and\n // the Vercel format expected by the agent manager (e.g. steps->content parts)\n return messages\n .filter(m => m)\n .map(m => ({\n role: m.role,\n content: m.content\n }));\n }\n\n /**\n * Convert a tool output from the wire format (which is different/more compact than LanguageModelV3ToolResultOutput)\n * into our own standard representation.\n */\n protected convertStreamingToolOutputToToolCallPart(output: any, target: ToolCallPart) {\n // So far we just pass the data through unchanged from the streaming API but that's pretty hard to work with since it's neither\n // in the format returned by the tool nor in the LanguageModelV3ToolResultOutput format that we have to use\n // when passing it back for the next request\n target.output = output;\n\n if (output?.type?.startsWith('error-') || output?.isError) target.error = true;\n }\n\n /** Add the specified tool call info to the current step. If this toolCallId is already known,\n * updates it rather than adding a new one, since for UI rendering and compactness of data it's\n * easiest to just have one item per tool call.\n */\n private addToolCallInfo(\n type: ToolCallPart['type'],\n rawInfo: any,\n addTo: AgentStep\n ): ToolCallPart {\n // Vercel v4 seems to set this to \"id\" not \"toolCallId\" in some places despite doc to the contrary, so normalize it here\n if (!rawInfo.toolCallId) rawInfo.toolCallId = rawInfo.id;\n\n // We can simplify this logic once we have AIMessage as a list of parts instead of separate lists for these\n let existing: ToolCallPart | undefined = addTo.toolCalls?.find(\n tc => tc.toolCallId === rawInfo.toolCallId\n );\n if (!existing) existing = addTo.toolResults?.find(tc => tc.toolCallId === rawInfo.toolCallId);\n\n // Move from toolCalls to toolResults when transitioning to tool-result\n if (existing && type === 'tool-result' && existing.type !== 'tool-result') {\n addTo.toolCalls = addTo.toolCalls?.filter(tc => tc.toolCallId !== existing?.toolCallId);\n existing.type = type;\n addTo.toolResults = [...(addTo.toolResults || []), existing];\n } else if (existing && existing.type !== type) {\n // Just update the type in place for other transitions\n existing.type = type;\n }\n\n if (!existing) {\n existing = { type: type, toolName: rawInfo.toolName, toolCallId: rawInfo.toolCallId };\n if (type !== 'tool-result') addTo.toolCalls = [...(addTo.toolCalls || []), existing];\n else addTo.toolResults = [...(addTo.toolResults || []), existing];\n }\n if (rawInfo?.input) existing.input = rawInfo.input;\n if (rawInfo?.output) this.convertStreamingToolOutputToToolCallPart(rawInfo.output, existing);\n\n return existing;\n }\n\n /** Unpacks data from the Vercel Data Stream Protocol (sent by the Agent Manager over SSE) to update the message\n *\n * See streamText().fullStream() from https://ai-sdk.dev/docs/ai-sdk-ui/stream-protocol#data-stream-protocol\n *\n * This is similar to what the Vercel `toUIMessageStreamResponse` API does (though it'd need the agent manager to publish the\n * UIMessageStream which has a bit more - useful - data than what is included here).\n *\n * We always use the same steps (or in future, parts) object, to make it easier for consumers (eg. agent-chat)\n * to add items to the list and have them still there on the next update from this service.\n */\n private processLine(line: string, observer: Subscriber<AIStreamResponse>, message: AIMessage) {\n if (!line.trim()) {\n return;\n }\n\n try {\n let data: any = {};\n let type = '';\n try {\n data = JSON.parse(line.replace('data: ', ''));\n type = data.type;\n } catch (e) {\n console.error('Error parsing line from AI response: ', line, e);\n return;\n }\n\n // Ensure there's a step into which we can store everything\n if (!message.steps || message.steps.length === 0) {\n message.steps = [{ type: 'text', text: '' }];\n }\n const lastStep = message.steps[message.steps.length - 1];\n\n switch (type) {\n case DataStreamType.STEP_START:\n if (data.request && data.request.body) {\n observer.next({\n message: message,\n changedPart: {\n type: 'response-metadata',\n model: data.request.body.model,\n systemPrompt: data.request.body.systemPrompt\n }\n });\n }\n\n // Create a step, unless we already have an empty one from the initialization section above\n if (lastStep.text || lastStep.reasoning || lastStep.toolCalls || lastStep.toolResults) {\n message.steps.push({\n type: 'text',\n text: ''\n });\n }\n return;\n\n case DataStreamType.REASONING:\n if (lastStep.reasoning === undefined) {\n lastStep!.reasoning = '';\n }\n lastStep.reasoning += data.text || data.textDelta;\n observer.next({ message, changedPart: undefined });\n return;\n\n case DataStreamType.TEXT_DELTA:\n lastStep.text += data.text || data.textDelta;\n\n // FUTURE: this setting the same value to message.content is probably not correct;\n // duplicating the same text wastes space so not necessary given it's already in steps, and\n // the Vercel SDK sets message.content to the text of the LAST step only (the summarizing step)\n message.content += data.text || data.textDelta;\n\n observer.next({ message, changedPart: undefined });\n return;\n\n case DataStreamType.TOOL_INPUT_START:\n observer.next({\n message,\n changedPart: this.addToolCallInfo('tool-input-streaming', data, lastStep)\n });\n return;\n\n case DataStreamType.TOOL_CALL:\n observer.next({\n message,\n changedPart: this.addToolCallInfo('tool-executing', data, lastStep)\n });\n return;\n\n case DataStreamType.TOOL_RESULT:\n observer.next({\n message,\n changedPart: this.addToolCallInfo('tool-result', data, lastStep)\n });\n return;\n\n case DataStreamType.FINISH:\n message.finishReason = data.finishReason; // FUTURE could be anything, may not match the options in AIMessage\n observer.next({ message, changedPart: undefined });\n observer.complete();\n return;\n\n case DataStreamType.ERROR:\n message.finishReason = 'error';\n observer.next({ message, changedPart: undefined });\n observer.error(data?.message || data?.errorText || data);\n // Error is instead of completing the stream\n return;\n\n // Should we also handle other types such as \"abort\"?\n }\n } catch (e) {\n observer.error(e);\n }\n }\n}\n\n/**\n * The default method for reducing the size of the message history so it is ready to be sent to the LLM agent.\n *\n * This is important since old tool inputs and outputs can be very large and fill up the agent's context window.\n *\n * When sending an AI request you can provide your own function instead of using this one,\n * or you can write your own function that calls this and adds extra logic,\n * for example to suppress specific tools from the AIMessage, or\n * retain only the final step text in multi-step responses, etc.\n *\n * The current default implementation preserves text content, but does not include any tool calls.\n * This may change in future releases.\n */\nexport function defaultPruneMessagesForAgent(messages: AIMessage[]): AIMessage[] {\n // When we change this to include tool calls, we should remove large inputs and truncate large and/or old outputs\n // to avoid too many tokens and context window consumption.\n // Some applications will want to entirely remove specific tool calls that have only transient use,\n // which can be done by providing their own pruneMessagesForAgent function.\n return messages.map(m => ({\n role: m.role,\n content: m.content\n }));\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"c8y-ngx-components-ai.mjs","sources":["../../ai/ai.service.ts","../../ai/c8y-ngx-components-ai.ts"],"sourcesContent":["import { inject, Injectable } from '@angular/core';\nimport { FetchClient } from '@c8y/client';\nimport { Observable, Subscriber } from 'rxjs';\nimport {\n AgentDefinition,\n AgentHealthCheckResponse,\n AIAssistantMessage,\n AIMessage,\n AIMessagePart,\n AIStreamResponse,\n ClientAgentDefinition,\n ToolCallPart\n} from './ai.model';\n\n// Internal implementation detail; maybe we don't even need this enum since\nexport enum DataStreamType {\n TEXT_DELTA = 'text-delta',\n TOOL_CALL = 'tool-call',\n TOOL_INPUT_START = 'tool-input-start',\n TOOL_INPUT_DELTA = 'tool-input-delta',\n TOOL_CALL_STREAMING = 'tool-call-streaming',\n TOOL_CALL_DELTA = 'tool-call-delta',\n TOOL_RESULT = 'tool-result',\n REASONING = 'reasoning',\n REASONING_DELTA = 'reasoning-delta',\n REDACTED_REASONING = 'redacted-reasoning',\n REASONING_SIGNATURE = 'reasoning-signature',\n FINISH_REASONING = 'finish-reasoning',\n FINISH = 'finish',\n FINISH_STEP = 'finish-step',\n ERROR = 'error',\n DATA = 'data',\n MESSAGE_ANNOTATIONS = 'message-annotations',\n SOURCE = 'source',\n FILE = 'file',\n STEP_START = 'start-step',\n STEP_FINISH = 'finish-step'\n}\n\n/** This service manages communication with the AI Agent Manager microservice, supporting\n * management of agents, and sending requests to the agents.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class AIService {\n private baseUrl = '/service/ai';\n private client: FetchClient;\n\n // nb: allowing the client to be passed in the constructor allows efficient unit testing without setting up the Angular TestBed\n constructor(client?: FetchClient) {\n this.client = client ?? inject(FetchClient);\n }\n\n /**\n * Creates or updates an agent.\n * @param def The agent definition\n */\n async createOrUpdateAgent(def: AgentDefinition): Promise<void> {\n const health = await this.getAgentHealth(def.name);\n let resource = `${this.baseUrl}/agent/${def.type}`;\n let method = 'POST';\n if (health.exists) {\n resource = `${this.baseUrl}/agent/${def.type}/${def.name}`;\n method = 'PUT';\n }\n const response = await this.client.fetch(resource, {\n body: JSON.stringify(def),\n method,\n headers: { 'Content-Type': 'application/json' }\n });\n\n if (!response.ok) {\n throw new Error(`Failed to create agent: ${response.statusText}`);\n }\n }\n\n /**\n * Check if an agent exists and is ready for use.\n * @param name Agent name (optional)\n * @param fromApp The app context path to check for an agent. This can be used, if the agent should get distributed by the plugin (optional).\n * @returns Agent health check response.\n */\n async getAgentHealth(name = '', fromApp?: string): Promise<AgentHealthCheckResponse> {\n const response = await this.client.fetch(\n `${this.baseUrl}/agent/test/${name || crypto.randomUUID()}${fromApp ? `?fromApp=${fromApp}` : ''}`,\n {\n method: 'GET',\n headers: { 'Content-Type': 'application/json' }\n }\n );\n\n if (!response.ok) {\n return {\n status: response.status === 403 ? 'missing-permissions' : 'missing-microservice',\n exists: false,\n canCreate: false,\n isProviderConfigured: false,\n messages: response.status === 403 ? [] : [response.statusText]\n };\n }\n const json: AgentHealthCheckResponse = await response.json();\n if (!json.isProviderConfigured) {\n json.status = 'missing-provider';\n } else if (!json.exists) {\n json.status = 'missing-agent';\n } else {\n json.status = 'ready';\n }\n return json;\n }\n\n /**\n * Send a text message to the agent.\n * @param name Agent name\n * @param messages The message to send, including any previous message history.\n * Typically you should use `defaultPruneMessagesForAgent` or a custom function to prepare the message history\n * by removing unnecessary content such as large/old tool inputs/outputs.\n * @param variables Variables to include\n * @param fromApp The app context path to check for an agent. This can be used, if the agent should get distributed by the plugin (optional).\n * @returns Text response from the agent.\n */\n async text(\n name: string,\n messages: AIMessage[],\n variables: { [key: string]: any },\n fromApp?: string\n ): Promise<string> {\n const parsedMessages = this.convertToAgentMessageFormat(messages);\n\n const data = this.client.fetch(\n `${this.baseUrl}/agent/text/${name}${fromApp ? `?fromApp=${fromApp}` : ''}`,\n {\n body: JSON.stringify({ messages: parsedMessages, variables }),\n method: 'POST',\n headers: { 'Content-Type': 'application/json' }\n }\n );\n\n const response = await data;\n if (!response.ok) {\n throw new Error(`Failed to talk with agent: ${response.statusText}`);\n }\n const text = await response.text();\n return text;\n }\n\n /**\n * Stream a text message to the agent.\n * @param agent Agent name or an agent definition.\n * @param messages The message to send, including any previous message history.\n * Typically you should use `defaultPruneMessagesForAgent` or a custom function to prepare the message history\n * by removing unnecessary content such as large/old tool inputs/outputs.\n * @param variables Variables to include\n * @param abortController An AbortController to cancel the request.\n * @param fromApp The app context path to check for an agent. This can be used, if the agent should get distributed by the plugin (optional).\n * @returns An observable that emits AIStreamResponse including partial `AIMessage` objects as they are received.\n * When additional useful metadata is available, this will be streamed with type indicating it is metadata.\n * The observable can be cancelled using the provided AbortController.\n * The observable will emit an error if the request fails or is aborted.\n * The observable will complete when the stream is finished.\n *\n * The messages sent to the agent can include special options:\n * - `hiddenContent`: If set, this content will be sent to the agent instead of the `content` field.\n * - `skipToLLM`: If set to true, this message will be skipped when sending to the agent.\n *\n * Example usage:\n * ```typescript\n * const abortController = new AbortController();\n * const messages: AIMessage[] = [\n * { role: 'user', content: 'Hello' },\n * { role: 'assistant', content: 'Hi there!' },\n * { role: 'user', content: 'Tell me a joke.', options: { hiddenContent: 'Tell me a joke about cats.' } }\n * ];\n * const observable = aiService.stream$('my-agent', messages, {}, abortController);\n * const subscription = observable.subscribe({\n * next: (response) => { console.log('Received message update:', response.message); },\n * error: (err) => console.error('Error:', err),\n * complete: () => console.log('Stream complete')\n * });\n *\n * // To cancel the request:\n * abortController.abort();\n * subscription.unsubscribe();\n * ```\n */\n async stream$(\n agent: string | ClientAgentDefinition,\n messages: AIMessage[],\n variables: { [key: string]: any },\n abortController: AbortController,\n fromApp?: string\n ): Promise<Observable<AIStreamResponse>> {\n const parsedMessages = this.convertToAgentMessageFormat(messages);\n\n const agentName = typeof agent === 'string' ? agent : agent.definition.name;\n const useTest = typeof agent !== 'string' && agent.snapshot;\n const baseUrl = useTest\n ? `${this.baseUrl}/agent/test/text`\n : `${this.baseUrl}/agent/text/${agentName}`;\n let body = JSON.stringify({ messages: parsedMessages, variables });\n if (useTest) {\n const agentCopy = {\n ...agent.definition\n };\n agentCopy.agent['messages'] = parsedMessages;\n agentCopy.agent['variables'] = variables;\n body = JSON.stringify(agentCopy);\n }\n\n const response = await this.client.fetch(\n `${baseUrl}?fullResponse=true${fromApp ? `&fromApp=${fromApp}` : ''}`,\n {\n method: 'POST',\n body,\n headers: {\n ...this.client.defaultHeaders,\n 'content-type': 'application/json',\n accept: 'text/event-stream'\n },\n signal: abortController.signal\n }\n );\n\n const stream = response.body;\n const decoder = new TextDecoder();\n\n return new Observable<AIStreamResponse>(observer => {\n if (response.status > 300) {\n response\n .json()\n .then(data => {\n observer.error(`Error communicating with server: ${JSON.stringify(data, null, 2)}`);\n })\n .catch(err => {\n observer.error(\n `Error communicating with server: HTTP ${response.status}: ${response.statusText}; ${err}`\n );\n });\n return;\n }\n\n if (!stream) {\n observer.error('Server error - no response body');\n return;\n }\n\n const reader = stream.getReader();\n const message: AIAssistantMessage = {\n role: 'assistant',\n content: []\n };\n\n const abortHandler = () => {\n reader.cancel();\n observer.error(new DOMException('Aborted', 'AbortError'));\n };\n\n abortController.signal.addEventListener('abort', abortHandler);\n\n let buffer = '';\n\n const read = () => {\n reader.read().then(({ done, value }) => {\n if (done) {\n if (buffer.trim()) this.processLine(buffer, observer, message); // process any remaining data\n observer.complete();\n return;\n }\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n\\n');\n buffer = lines.pop() || '';\n for (const line of lines) {\n if (line.trim()) this.processLine(line, observer, message);\n }\n read();\n });\n };\n\n read();\n return () => {\n abortController.signal.removeEventListener('abort', abortHandler);\n reader.cancel();\n };\n });\n }\n\n protected convertToAgentMessageFormat(messages: AIMessage[]): object[] {\n // We will need to rewrite this to include tool outputs soon (effectively this means targetting LanguageModelV*ToolResultOutput).\n // Once we have more fields than just role and content, we will need to convert between our format and\n // the Vercel format expected by the agent manager (e.g. steps->content parts)\n return messages.map(m => ({\n role: m.role,\n content:\n m.role === 'assistant'\n ? m.content\n .filter((part): part is { type: 'text'; text: string } => part.type === 'text')\n .map(part => part.text)\n .join('\\n\\n')\n : m.content\n }));\n }\n\n /**\n * Convert a tool output from the MCP/wire format (which is different/more compact than LanguageModelV3ToolResultOutput)\n * into our own standard representation, which can be roundtripped to the format we need to provide when making future requests.\n *\n * Handles different data types from Vercel's streaming API:\n * - Text: stored as simple string in output field\n * - JSON objects: stored as-is in output field\n * - Content arrays: stored in output field with outputType=\"content\" to enable roundtripping\n * - Single text in content array: unwrapped to simple string for simpler handling (and easier truncation)\n * - Errors: error flag set to true\n */\n protected convertStreamingToolOutputToToolCallPart(output: any, target: ToolCallPart) {\n if (!output) {\n return;\n }\n\n if (output.isError || output.type === 'error-text' || output.type === 'error-json')\n target.error = true;\n\n // Handle content array format from streaming API\n if (output.content && Array.isArray(output.content)) {\n // Single text element - unwrap to simple string for simplicity\n if (output.content.length === 1 && output.content[0].type === 'text') {\n target.output = output.content[0].text;\n return;\n }\n\n // Multiple elements or mixed types - preserve as content array\n target.output = output.content;\n target.outputType = 'content'; // Mark as content to enable roundtripping\n return;\n }\n\n // Plain string or structured (JSON-serializable) object - store as-is\n target.output = output;\n }\n\n /** Add the specified tool call info to the current step. If this toolCallId is already known,\n * updates it rather than adding a new one, since for UI rendering and compactness of data it's\n * easiest to just have one item per tool call.\n *\n * Returns the changed item.\n */\n private addToolCallInfo(\n type: ToolCallPart['type'],\n rawInfo: any,\n addTo: AIMessagePart[]\n ): ToolCallPart {\n // Vercel v4 seems to set this to \"id\" not \"toolCallId\" in some places despite doc to the contrary, so normalize it here\n if (!rawInfo.toolCallId) rawInfo.toolCallId = rawInfo.id;\n\n let existing: ToolCallPart | undefined = addTo.find(\n (tc): tc is ToolCallPart =>\n tc.type.startsWith('tool-') && (tc as ToolCallPart).toolCallId === rawInfo.toolCallId\n );\n\n if (existing) {\n existing.type = type;\n } else if (!existing) {\n existing = { type: type, toolName: rawInfo.toolName, toolCallId: rawInfo.toolCallId };\n addTo.push(existing);\n }\n if (rawInfo?.input) existing.input = rawInfo.input;\n if (rawInfo?.output) this.convertStreamingToolOutputToToolCallPart(rawInfo.output, existing);\n\n return existing;\n }\n\n /** Unpacks data from the Vercel Data Stream Protocol (sent by the Agent Manager over SSE) to update the message\n *\n * See streamText().fullStream() from https://ai-sdk.dev/docs/ai-sdk-ui/stream-protocol#data-stream-protocol\n *\n * This is similar to what the Vercel `toUIMessageStreamResponse` API does (though it'd need the agent manager to publish the\n * UIMessageStream which has a bit more - useful - data than what is included here).\n *\n * We always use the same parts object, to make it easier for consumers (eg. agent-chat)\n * to add items to the list and have them still there on the next update from this service.\n */\n private processLine(\n line: string,\n observer: Subscriber<AIStreamResponse>,\n message: AIAssistantMessage\n ) {\n if (!line.trim()) {\n return;\n }\n\n try {\n let data: any = {};\n let type = '';\n try {\n data = JSON.parse(line.replace('data: ', ''));\n type = data.type;\n } catch (e) {\n console.error('Error parsing line from AI response: ', line, e);\n return;\n }\n\n let lastPart = !message.content ? undefined : message.content[message.content.length - 1];\n\n switch (type) {\n case DataStreamType.STEP_START:\n if (data.request && data.request.body) {\n observer.next({\n message: message,\n changedPart: {\n type: 'response-metadata',\n model: data.request.body.model,\n systemPrompt: data.request.body.systemPrompt\n }\n });\n }\n // Don't add consecutive duplicate step bounaries\n if (!lastPart || lastPart.type !== 'step-start') {\n message.content.push({ type: 'step-start' });\n observer.next({ message, changedPart: message.content[message.content.length - 1] });\n }\n\n return;\n\n case DataStreamType.REASONING_DELTA:\n const reasoning = data.text;\n if (!reasoning) return;\n if (lastPart?.type === 'reasoning') {\n lastPart.text += reasoning;\n } else {\n lastPart = { type: 'reasoning', text: reasoning };\n message.content.push(lastPart);\n }\n observer.next({ message, changedPart: lastPart });\n return;\n\n case DataStreamType.TEXT_DELTA:\n const text = data.textDelta || data.text;\n if (!text) return;\n if (lastPart?.type === 'text') {\n lastPart.text += text;\n } else {\n lastPart = { type: 'text', text: text };\n message.content.push(lastPart);\n }\n observer.next({ message, changedPart: lastPart });\n return;\n\n case DataStreamType.TOOL_INPUT_START:\n observer.next({\n message,\n changedPart: this.addToolCallInfo('tool-input-streaming', data, message.content)\n });\n return;\n\n case DataStreamType.TOOL_CALL:\n observer.next({\n message,\n changedPart: this.addToolCallInfo('tool-executing', data, message.content)\n });\n return;\n\n case DataStreamType.TOOL_RESULT:\n observer.next({\n message,\n changedPart: this.addToolCallInfo('tool-result', data, message.content)\n });\n return;\n\n case DataStreamType.FINISH:\n message.finishReason = data.finishReason; // FUTURE could be anything, may not match the options in AIMessage\n observer.next({ message, changedPart: undefined });\n observer.complete();\n return;\n\n case DataStreamType.ERROR:\n message.finishReason = 'error';\n observer.next({ message, changedPart: undefined });\n observer.error(data?.message || data?.errorText || data);\n // Error is instead of completing the stream\n return;\n\n // Should we also handle other types such as \"abort\"?\n }\n } catch (e) {\n observer.error(e);\n }\n }\n}\n\n/**\n * The default implementation of for reducing the size of the message history so it is ready to be sent to the LLM agent.\n *\n * This is important since old tool inputs and outputs can be very large and fill up the agent's context window.\n *\n * Implements `pruneMessagesFunction`.\n *\n * When sending an AI request you can provide your own function instead of using this one,\n * or you can write your own function that calls this and adds extra logic,\n * for example to suppress specific tools from the AIMessage, or\n * retain only the final step text in multi-step responses, etc.\n *\n * The current default implementation preserves text content, but does not include any tool calls.\n * This may change in future releases.\n */\nexport function defaultPruneMessagesForAgent(messages: AIMessage[]): AIMessage[] {\n // When we change this to include tool calls, we should remove large inputs and truncate large and/or old outputs\n // to avoid too many tokens and context window consumption.\n // Some applications will want to entirely remove specific tool calls that have only transient use,\n // which can be done by providing their own pruneMessagesForAgent function.\n return messages.map(m =>\n m.role !== 'assistant'\n ? {\n role: m.role,\n content: m.content\n }\n : {\n role: m.role,\n content: [\n {\n type: 'text',\n text: m.content\n .filter((part): part is { type: 'text'; text: string } => part.type === 'text')\n .map(part => part.text)\n .join('\\n\\n')\n }\n ]\n }\n );\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -257,11 +257,11 @@ class AssignWidgetAssetModalComponent {
257
257
  widgetAsset.selectedAsset = $event.change.item;
258
258
  }
259
259
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AssignWidgetAssetModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
260
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: AssignWidgetAssetModalComponent, isStandalone: true, selector: "c8y-assign-widget-asset-modal", inputs: { assetsToAlign: "assetsToAlign", contextAsset: "contextAsset", notSupportedWidgets: "notSupportedWidgets" }, ngImport: i0, template: "<div class=\"viewport-modal has-asset-selector\">\n <div class=\"modal-header dialog-header\">\n <i [c8yIcon]=\"'th-large'\"></i>\n <div\n class=\"modal-title\"\n id=\"modal-title\"\n translate\n >\n Select and confirm widget assets mapping\n </div>\n </div>\n <div\n class=\"inner-scroll\"\n id=\"modal-body\"\n >\n <div class=\"p-16\">\n <p class=\"text-center text-balance\">\n {{ modalTitle | translate }}\n </p>\n </div>\n @if (notSupportedWidgets.length) {\n <div class=\"d-flex fit-w j-c-center p-16 p-t-0\">\n <div class=\"alert alert-warning\">\n {{ 'Widgets not supported for asset mapping: {{ notSupportedWidgets }}' | translate: {\n notSupportedWidgets: notSupportedWidgets.join(', ') } }}\n </div>\n </div>\n }\n @if (!assetsToAlign.length) {\n <div class=\"p-16 d-flex j-c-center\">\n <c8y-ui-empty-state\n class=\"\"\n [icon]=\"'empty-box'\"\n [title]=\"'No assets to assign' | translate\"\n ></c8y-ui-empty-state>\n </div>\n }\n @if (assetsToAlign.length) {\n <div>\n <c8y-list-group class=\"separator-top no-border-last\">\n <c8y-li class=\"sticky-top bg-level-1 hidden-sm hidden-xs\">\n <c8y-li-icon></c8y-li-icon>\n <div class=\"d-flex\">\n <div class=\"col-md-2\">\n <!-- title -->\n <p\n class=\"text-truncate text-medium\"\n translate\n >\n Widget\n </p>\n </div>\n <div class=\"col-md-10\">\n <div class=\"row\">\n <div class=\"col-md-4 p-r-0\">\n <p\n class=\"text-medium\"\n translate\n >\n Original source\n </p>\n </div>\n <div class=\"col-md-1 text-center\">\n <button\n class=\"btn btn-default btn-sm\"\n [attr.aria-label]=\"'Accept all suggested' | translate\"\n [tooltip]=\"'Accept all suggested' | translate\"\n placement=\"right\"\n (click)=\"acceptAllSuggested()\"\n [disabled]=\"!hasSuggestedAssets\"\n >\n <i [c8yIcon]=\"'check'\"></i>\n </button>\n </div>\n <div class=\"col-md-7 p-l-8\">\n <p\n class=\"text-medium\"\n translate\n >\n Selected source\n </p>\n </div>\n </div>\n </div>\n </div>\n </c8y-li>\n @for (widgetAsset of updatedWidgetAssets; track widgetAsset; let i = $index) {\n <c8y-li class=\"c8y-list__item--overflow-visible\">\n <c8y-li-icon\n class=\"p-r-0 p-t-16\"\n icon=\"th-large\"\n ></c8y-li-icon>\n <div class=\"d-flex-md\">\n <div class=\"col-md-2\">\n <!-- title -->\n <p\n class=\"text-truncate text-medium boxed-label p-l-0\"\n title=\"{{ widgetAsset.title }}\"\n >\n {{ widgetAsset.title }}\n </p>\n </div>\n <div class=\"col-md-10\">\n <div class=\"row\">\n <div class=\"col-md-4 p-l-md-0 p-r-0\">\n <!-- origin device -->\n <p class=\"visible-sm visible-xs text-label-small\">\n {{ 'Original source' | translate }}\n </p>\n <div class=\"d-flex gap-4 boxed-label\">\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.deviceRef.value }\n \"\n ></ng-container>\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.deviceRef.value.name }}\"\n >\n {{ widgetAsset.deviceRef.value.name }}\n </span>\n <small class=\"text-muted\">\n {{\n assetIdInfo | translate: { assetId: widgetAsset.deviceRef.value.id }\n }}\n </small>\n </span>\n </div>\n </div>\n <div\n class=\"col-md-1 col-xs-1 p-l-xs-0 p-l-sm-0 p-r-sm-0 p-r-xs-0 text-center p-t-16\"\n >\n <i\n class=\"icon-20\"\n [c8yIcon]=\"\n widgetAsset.selectedAsset !== undefined ? 'ok' : 'inactive-state'\n \"\n [title]=\"\n widgetAsset.selectedAsset !== undefined\n ? (assetSelectedLabel | translate)\n : (assetNotSelectedLabel | translate)\n \"\n [ngClass]=\"{\n 'text-success': widgetAsset.selectedAsset !== undefined,\n 'text-muted': widgetAsset.selectedAsset === undefined\n }\"\n ></i>\n @if (\n widgetAsset.selectedAsset === undefined && userClickedAcceptAllSuggested\n ) {\n <span\n class=\"c8y-icon-badge\"\n [tooltip]=\"\n 'No suggestion available- widget will not be imported' | translate\n \"\n placement=\"right\"\n >\n <i\n class=\"status major stroked-icon\"\n c8yIcon=\"warning\"\n ></i>\n </span>\n }\n </div>\n <div class=\"col-md-4 col-xs-11 p-l-md-0\">\n <!-- Suggested/Selected source -->\n <p class=\"visible-sm visible-xs text-label-small m-t-16 m-b-8\">\n {{ 'Selected source' | translate }}\n </p>\n @if (\n widgetAsset.deviceRef.value.suggestedDevice && !widgetAsset.selectedAsset\n ) {\n <div\n class=\"d-flex gap-4 text-muted boxed-label\"\n [attr.data-label]=\"'Suggested' | translate\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.deviceRef.value.suggestedDevice }\n \"\n ></ng-container>\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.deviceRef.value.suggestedDevice?.name }}\"\n >\n {{ widgetAsset.deviceRef.value.suggestedDevice?.name }}\n </span>\n <small class=\"text-muted\">\n {{\n assetIdInfo\n | translate\n : { assetId: widgetAsset.deviceRef.value.suggestedDevice?.id }\n }}\n </small>\n </span>\n </div>\n }\n @if (widgetAsset.selectedAsset) {\n <div class=\"d-flex gap-4 boxed-label\">\n <!-- selectedAsset icon -->\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.selectedAsset }\n \"\n ></ng-container>\n <!-- selectedAsset Name and ID -->\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.selectedAsset?.name }}\"\n >\n {{ widgetAsset.selectedAsset?.name }}\n </span>\n <small class=\"text-muted\">\n {{\n assetIdInfo | translate: { assetId: widgetAsset.selectedAsset.id }\n }}\n </small>\n </span>\n </div>\n }\n @if (\n !widgetAsset.deviceRef.value.suggestedDevice && !widgetAsset.selectedAsset\n ) {\n <div class=\"text-muted boxed-label\">\n <em>{{ 'No suggestion available' | translate }}</em>\n </div>\n }\n </div>\n <div class=\"col-md-3 p-0 flex-grow\">\n <div class=\"d-flex a-i-center j-c-end-md gap-8 boxed-label p-l-md-0 p-r-0\">\n <div class=\"input-group max-width-fit\">\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"\n (widgetAsset.deviceRef.value.suggestedDevice\n ? acceptSuggestedLabel\n : noSuggestedAssetLabel\n ) | translate\n \"\n [tooltip]=\"\n (widgetAsset.deviceRef.value.suggestedDevice\n ? acceptSuggestedLabel\n : noSuggestedAssetLabel\n ) | translate\n \"\n placement=\"top\"\n container=\"body\"\n [ngClass]=\"{\n active:\n widgetAsset.selectedAsset &&\n widgetAsset.selectedAsset ===\n widgetAsset.deviceRef.value.suggestedDevice\n }\"\n [disabled]=\"!widgetAsset.deviceRef.value.suggestedDevice\"\n (click)=\"\n widgetAsset.selectedAsset =\n widgetAsset.deviceRef.value.suggestedDevice\n \"\n >\n <i [c8yIcon]=\"'check'\"></i>\n </button>\n </div>\n <div\n class=\"dropdown input-group-btn\"\n container=\"body\"\n dropdown\n [insideClick]=\"true\"\n #dropdown=\"bs-dropdown\"\n >\n <button\n class=\"btn btn-default dropdown-toggle c8y-dropdown\"\n [attr.aria-label]=\"'Select asset' | translate\"\n tooltip=\"{{ 'Select asset' | translate }}\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n dropdownToggle\n [ngClass]=\"{\n active:\n widgetAsset.selectedAsset &&\n widgetAsset.selectedAsset !==\n widgetAsset.deviceRef.value.suggestedDevice\n }\"\n >\n <i [c8yIcon]=\"'card-exchange'\"></i>\n </button>\n <div\n class=\"dropdown-menu dropdown-menu-right--md\"\n style=\"width: 300px\"\n *dropdownMenu\n >\n @if (dropdown.isOpen) {\n <c8y-asset-selector-miller\n (onSelected)=\"\n selectionChange($event, widgetAsset); dropdown.hide()\n \"\n [asset]=\"contextAsset\"\n [config]=\"{\n groupsSelectable: true,\n showChildDevices: true,\n showFilter: true,\n showSelected: false,\n columnHeaders: true,\n singleColumn: true,\n preventInitialSelect: true\n }\"\n ></c8y-asset-selector-miller>\n }\n </div>\n </div>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Configure later' | translate\"\n tooltip=\"{{ 'Configure later' | translate }}\"\n placement=\"top\"\n container=\"body\"\n [ngClass]=\"{ active: widgetAsset.selectedAsset === null }\"\n (click)=\"widgetAsset.selectedAsset = null\"\n >\n <i [c8yIcon]=\"'link-off'\"></i>\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </c8y-li>\n }\n </c8y-list-group>\n </div>\n }\n </div>\n <div class=\"modal-footer\">\n <button\n class=\"btn btn-default\"\n [title]=\"'Cancel' | translate\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n [title]=\"'Apply' | translate\"\n type=\"button\"\n (click)=\"apply()\"\n >\n {{ 'Apply' | translate }}\n </button>\n </div>\n</div>\n\n<ng-template\n #assetIcon\n let-device\n>\n @if (device.c8y_IsDevice) {\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"'data-transfer'\"\n ></i>\n }\n @if (device.c8y_IsDeviceGroup && !device.c8y_IsAsset) {\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"'c8y-group'\"\n ></i>\n }\n @if (device.c8y_IsAsset) {\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"device.icon?.name || 'c8y-group'\"\n ></i>\n }\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: CoreModule }, { kind: "component", type: i1.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: i1.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i1.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i1.ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: i1.ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: i1.ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "ngmodule", type: AssetSelectorModule }, { kind: "component", type: i3.MillerViewComponent, selector: "c8y-asset-selector-miller", inputs: ["config", "asset", "selectedDevice", "rootNode", "container"], outputs: ["onSelected", "onClearSelected"] }, { kind: "ngmodule", type: BsDropdownModule }, { kind: "directive", type: i4.BsDropdownMenuDirective, selector: "[bsDropdownMenu],[dropdownMenu]", exportAs: ["bs-dropdown-menu"] }, { kind: "directive", type: i4.BsDropdownToggleDirective, selector: "[bsDropdownToggle],[dropdownToggle]", exportAs: ["bs-dropdown-toggle"] }, { kind: "directive", type: i4.BsDropdownDirective, selector: "[bsDropdown], [dropdown]", inputs: ["placement", "triggers", "container", "dropup", "autoClose", "isAnimated", "insideClick", "isDisabled", "isOpen"], outputs: ["isOpenChange", "onShown", "onHidden"], exportAs: ["bs-dropdown"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i5.TooltipDirective, selector: "[tooltip], [tooltipHtml]", inputs: ["adaptivePosition", "tooltip", "placement", "triggers", "container", "containerClass", "boundariesElement", "isOpen", "isDisabled", "delay", "tooltipHtml", "tooltipPlacement", "tooltipIsOpen", "tooltipEnable", "tooltipAppendToBody", "tooltipAnimation", "tooltipClass", "tooltipContext", "tooltipPopupDelay", "tooltipFadeDuration", "tooltipTrigger"], outputs: ["tooltipChange", "onShown", "onHidden", "tooltipStateChanged"], exportAs: ["bs-tooltip"] }, { kind: "pipe", type: i1.C8yTranslatePipe, name: "translate" }] }); }
260
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: AssignWidgetAssetModalComponent, isStandalone: true, selector: "c8y-assign-widget-asset-modal", inputs: { assetsToAlign: "assetsToAlign", contextAsset: "contextAsset", notSupportedWidgets: "notSupportedWidgets" }, ngImport: i0, template: "<div class=\"viewport-modal has-asset-selector\">\n <div class=\"modal-header dialog-header\">\n <i [c8yIcon]=\"'th-large'\"></i>\n <div\n class=\"modal-title\"\n id=\"modal-title\"\n translate\n >\n Select and confirm widget assets mapping\n </div>\n </div>\n <div\n class=\"inner-scroll\"\n id=\"modal-body\"\n >\n <div class=\"p-16\">\n <p class=\"text-center text-balance\">\n {{ modalTitle | translate }}\n </p>\n </div>\n @if (notSupportedWidgets.length) {\n <div class=\"d-flex fit-w j-c-center p-16 p-t-0\">\n <div class=\"alert alert-warning\">\n {{ 'Widgets not supported for asset mapping: {{ notSupportedWidgets }}' | translate: {\n notSupportedWidgets: notSupportedWidgets.join(', ') } }}\n </div>\n </div>\n }\n @if (!assetsToAlign.length) {\n <div class=\"p-16 d-flex j-c-center\">\n <c8y-ui-empty-state\n class=\"\"\n [icon]=\"'empty-box'\"\n [title]=\"'No assets to assign' | translate\"\n ></c8y-ui-empty-state>\n </div>\n }\n @if (assetsToAlign.length) {\n <div>\n <c8y-list-group class=\"separator-top no-border-last\">\n <c8y-li class=\"sticky-top bg-level-1 hidden-sm hidden-xs\">\n <c8y-li-icon></c8y-li-icon>\n <div class=\"d-flex\">\n <div class=\"col-md-2\">\n <!-- title -->\n <p\n class=\"text-truncate text-medium\"\n translate\n >\n Widget\n </p>\n </div>\n <div class=\"col-md-10\">\n <div class=\"row\">\n <div class=\"col-md-4 p-r-0\">\n <p\n class=\"text-medium\"\n translate\n >\n Original source\n </p>\n </div>\n <div class=\"col-md-1 text-center\">\n <button\n class=\"btn btn-default btn-sm\"\n [attr.aria-label]=\"'Accept all suggested' | translate\"\n [tooltip]=\"'Accept all suggested' | translate\"\n placement=\"right\"\n (click)=\"acceptAllSuggested()\"\n [disabled]=\"!hasSuggestedAssets\"\n >\n <i [c8yIcon]=\"'check'\"></i>\n </button>\n </div>\n <div class=\"col-md-7 p-l-8\">\n <p\n class=\"text-medium\"\n translate\n >\n Selected source\n </p>\n </div>\n </div>\n </div>\n </div>\n </c8y-li>\n @for (widgetAsset of updatedWidgetAssets; track widgetAsset; let i = $index) {\n <c8y-li class=\"c8y-list__item--overflow-visible\">\n <c8y-li-icon\n class=\"p-r-0 p-t-16\"\n icon=\"th-large\"\n ></c8y-li-icon>\n <div class=\"d-flex-md\">\n <div class=\"col-md-2\">\n <!-- title -->\n <p\n class=\"text-truncate text-medium boxed-label p-l-0\"\n title=\"{{ widgetAsset.title }}\"\n >\n {{ widgetAsset.title }}\n </p>\n </div>\n <div class=\"col-md-10\">\n <div class=\"row\">\n <div class=\"col-md-4 p-l-md-0 p-r-0\">\n <!-- origin device -->\n <p class=\"visible-sm visible-xs text-label-small\">\n {{ 'Original source' | translate }}\n </p>\n <div class=\"d-flex gap-4 boxed-label\">\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.deviceRef.value }\n \"\n ></ng-container>\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.deviceRef.value.name }}\"\n >\n {{ widgetAsset.deviceRef.value.name }}\n </span>\n <small class=\"text-muted\">\n {{\n assetIdInfo | translate: { assetId: widgetAsset.deviceRef.value.id }\n }}\n </small>\n </span>\n </div>\n </div>\n <div\n class=\"col-md-1 col-xs-1 p-l-xs-0 p-l-sm-0 p-r-sm-0 p-r-xs-0 text-center p-t-16\"\n >\n <i\n class=\"icon-20\"\n [c8yIcon]=\"\n widgetAsset.selectedAsset !== undefined ? 'ok' : 'inactive-state'\n \"\n [title]=\"\n widgetAsset.selectedAsset !== undefined\n ? (assetSelectedLabel | translate)\n : (assetNotSelectedLabel | translate)\n \"\n [ngClass]=\"{\n 'text-success': widgetAsset.selectedAsset !== undefined,\n 'text-muted': widgetAsset.selectedAsset === undefined\n }\"\n ></i>\n @if (\n widgetAsset.selectedAsset === undefined && userClickedAcceptAllSuggested\n ) {\n <span\n class=\"c8y-icon-badge\"\n [tooltip]=\"\n 'No suggestion available - widget will not be imported' | translate\n \"\n placement=\"right\"\n >\n <i\n class=\"status major stroked-icon\"\n c8yIcon=\"warning\"\n ></i>\n </span>\n }\n </div>\n <div class=\"col-md-4 col-xs-11 p-l-md-0\">\n <!-- Suggested/Selected source -->\n <p class=\"visible-sm visible-xs text-label-small m-t-16 m-b-8\">\n {{ 'Selected source' | translate }}\n </p>\n @if (\n widgetAsset.deviceRef.value.suggestedDevice && !widgetAsset.selectedAsset\n ) {\n <div\n class=\"d-flex gap-4 text-muted boxed-label\"\n [attr.data-label]=\"'Suggested' | translate\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.deviceRef.value.suggestedDevice }\n \"\n ></ng-container>\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.deviceRef.value.suggestedDevice?.name }}\"\n >\n {{ widgetAsset.deviceRef.value.suggestedDevice?.name }}\n </span>\n <small class=\"text-muted\">\n {{\n assetIdInfo\n | translate\n : { assetId: widgetAsset.deviceRef.value.suggestedDevice?.id }\n }}\n </small>\n </span>\n </div>\n }\n @if (widgetAsset.selectedAsset) {\n <div class=\"d-flex gap-4 boxed-label\">\n <!-- selectedAsset icon -->\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.selectedAsset }\n \"\n ></ng-container>\n <!-- selectedAsset Name and ID -->\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.selectedAsset?.name }}\"\n >\n {{ widgetAsset.selectedAsset?.name }}\n </span>\n <small class=\"text-muted\">\n {{\n assetIdInfo | translate: { assetId: widgetAsset.selectedAsset.id }\n }}\n </small>\n </span>\n </div>\n }\n @if (\n !widgetAsset.deviceRef.value.suggestedDevice && !widgetAsset.selectedAsset\n ) {\n <div class=\"text-muted boxed-label\">\n <em>{{ 'No suggestion available' | translate }}</em>\n </div>\n }\n </div>\n <div class=\"col-md-3 p-0 flex-grow\">\n <div class=\"d-flex a-i-center j-c-end-md gap-8 boxed-label p-l-md-0 p-r-0\">\n <div class=\"input-group max-width-fit\">\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"\n (widgetAsset.deviceRef.value.suggestedDevice\n ? acceptSuggestedLabel\n : noSuggestedAssetLabel\n ) | translate\n \"\n [tooltip]=\"\n (widgetAsset.deviceRef.value.suggestedDevice\n ? acceptSuggestedLabel\n : noSuggestedAssetLabel\n ) | translate\n \"\n placement=\"top\"\n container=\"body\"\n [ngClass]=\"{\n active:\n widgetAsset.selectedAsset &&\n widgetAsset.selectedAsset ===\n widgetAsset.deviceRef.value.suggestedDevice\n }\"\n [disabled]=\"!widgetAsset.deviceRef.value.suggestedDevice\"\n (click)=\"\n widgetAsset.selectedAsset =\n widgetAsset.deviceRef.value.suggestedDevice\n \"\n >\n <i [c8yIcon]=\"'check'\"></i>\n </button>\n </div>\n <div\n class=\"dropdown input-group-btn\"\n container=\"body\"\n dropdown\n [insideClick]=\"true\"\n #dropdown=\"bs-dropdown\"\n >\n <button\n class=\"btn btn-default dropdown-toggle c8y-dropdown\"\n [attr.aria-label]=\"'Select asset' | translate\"\n tooltip=\"{{ 'Select asset' | translate }}\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n dropdownToggle\n [ngClass]=\"{\n active:\n widgetAsset.selectedAsset &&\n widgetAsset.selectedAsset !==\n widgetAsset.deviceRef.value.suggestedDevice\n }\"\n >\n <i [c8yIcon]=\"'card-exchange'\"></i>\n </button>\n <div\n class=\"dropdown-menu dropdown-menu-right--md\"\n style=\"width: 300px\"\n *dropdownMenu\n >\n @if (dropdown.isOpen) {\n <c8y-asset-selector-miller\n (onSelected)=\"\n selectionChange($event, widgetAsset); dropdown.hide()\n \"\n [asset]=\"contextAsset\"\n [config]=\"{\n groupsSelectable: true,\n showChildDevices: true,\n showFilter: true,\n showSelected: false,\n columnHeaders: true,\n singleColumn: true,\n preventInitialSelect: true\n }\"\n ></c8y-asset-selector-miller>\n }\n </div>\n </div>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Configure later' | translate\"\n tooltip=\"{{ 'Configure later' | translate }}\"\n placement=\"top\"\n container=\"body\"\n [ngClass]=\"{ active: widgetAsset.selectedAsset === null }\"\n (click)=\"widgetAsset.selectedAsset = null\"\n >\n <i [c8yIcon]=\"'link-off'\"></i>\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </c8y-li>\n }\n </c8y-list-group>\n </div>\n }\n </div>\n <div class=\"modal-footer\">\n <button\n class=\"btn btn-default\"\n [title]=\"'Cancel' | translate\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n [title]=\"'Apply' | translate\"\n type=\"button\"\n (click)=\"apply()\"\n >\n {{ 'Apply' | translate }}\n </button>\n </div>\n</div>\n\n<ng-template\n #assetIcon\n let-device\n>\n @if (device.c8y_IsDevice) {\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"'data-transfer'\"\n ></i>\n }\n @if (device.c8y_IsDeviceGroup && !device.c8y_IsAsset) {\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"'c8y-group'\"\n ></i>\n }\n @if (device.c8y_IsAsset) {\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"device.icon?.name || 'c8y-group'\"\n ></i>\n }\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: CoreModule }, { kind: "component", type: i1.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: i1.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i1.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i1.ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: i1.ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: i1.ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "ngmodule", type: AssetSelectorModule }, { kind: "component", type: i3.MillerViewComponent, selector: "c8y-asset-selector-miller", inputs: ["config", "asset", "selectedDevice", "rootNode", "container"], outputs: ["onSelected", "onClearSelected"] }, { kind: "ngmodule", type: BsDropdownModule }, { kind: "directive", type: i4.BsDropdownMenuDirective, selector: "[bsDropdownMenu],[dropdownMenu]", exportAs: ["bs-dropdown-menu"] }, { kind: "directive", type: i4.BsDropdownToggleDirective, selector: "[bsDropdownToggle],[dropdownToggle]", exportAs: ["bs-dropdown-toggle"] }, { kind: "directive", type: i4.BsDropdownDirective, selector: "[bsDropdown], [dropdown]", inputs: ["placement", "triggers", "container", "dropup", "autoClose", "isAnimated", "insideClick", "isDisabled", "isOpen"], outputs: ["isOpenChange", "onShown", "onHidden"], exportAs: ["bs-dropdown"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i5.TooltipDirective, selector: "[tooltip], [tooltipHtml]", inputs: ["adaptivePosition", "tooltip", "placement", "triggers", "container", "containerClass", "boundariesElement", "isOpen", "isDisabled", "delay", "tooltipHtml", "tooltipPlacement", "tooltipIsOpen", "tooltipEnable", "tooltipAppendToBody", "tooltipAnimation", "tooltipClass", "tooltipContext", "tooltipPopupDelay", "tooltipFadeDuration", "tooltipTrigger"], outputs: ["tooltipChange", "onShown", "onHidden", "tooltipStateChanged"], exportAs: ["bs-tooltip"] }, { kind: "pipe", type: i1.C8yTranslatePipe, name: "translate" }] }); }
261
261
  }
262
262
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AssignWidgetAssetModalComponent, decorators: [{
263
263
  type: Component,
264
- args: [{ selector: 'c8y-assign-widget-asset-modal', standalone: true, imports: [CoreModule, AssetSelectorModule, BsDropdownModule, TooltipModule], template: "<div class=\"viewport-modal has-asset-selector\">\n <div class=\"modal-header dialog-header\">\n <i [c8yIcon]=\"'th-large'\"></i>\n <div\n class=\"modal-title\"\n id=\"modal-title\"\n translate\n >\n Select and confirm widget assets mapping\n </div>\n </div>\n <div\n class=\"inner-scroll\"\n id=\"modal-body\"\n >\n <div class=\"p-16\">\n <p class=\"text-center text-balance\">\n {{ modalTitle | translate }}\n </p>\n </div>\n @if (notSupportedWidgets.length) {\n <div class=\"d-flex fit-w j-c-center p-16 p-t-0\">\n <div class=\"alert alert-warning\">\n {{ 'Widgets not supported for asset mapping: {{ notSupportedWidgets }}' | translate: {\n notSupportedWidgets: notSupportedWidgets.join(', ') } }}\n </div>\n </div>\n }\n @if (!assetsToAlign.length) {\n <div class=\"p-16 d-flex j-c-center\">\n <c8y-ui-empty-state\n class=\"\"\n [icon]=\"'empty-box'\"\n [title]=\"'No assets to assign' | translate\"\n ></c8y-ui-empty-state>\n </div>\n }\n @if (assetsToAlign.length) {\n <div>\n <c8y-list-group class=\"separator-top no-border-last\">\n <c8y-li class=\"sticky-top bg-level-1 hidden-sm hidden-xs\">\n <c8y-li-icon></c8y-li-icon>\n <div class=\"d-flex\">\n <div class=\"col-md-2\">\n <!-- title -->\n <p\n class=\"text-truncate text-medium\"\n translate\n >\n Widget\n </p>\n </div>\n <div class=\"col-md-10\">\n <div class=\"row\">\n <div class=\"col-md-4 p-r-0\">\n <p\n class=\"text-medium\"\n translate\n >\n Original source\n </p>\n </div>\n <div class=\"col-md-1 text-center\">\n <button\n class=\"btn btn-default btn-sm\"\n [attr.aria-label]=\"'Accept all suggested' | translate\"\n [tooltip]=\"'Accept all suggested' | translate\"\n placement=\"right\"\n (click)=\"acceptAllSuggested()\"\n [disabled]=\"!hasSuggestedAssets\"\n >\n <i [c8yIcon]=\"'check'\"></i>\n </button>\n </div>\n <div class=\"col-md-7 p-l-8\">\n <p\n class=\"text-medium\"\n translate\n >\n Selected source\n </p>\n </div>\n </div>\n </div>\n </div>\n </c8y-li>\n @for (widgetAsset of updatedWidgetAssets; track widgetAsset; let i = $index) {\n <c8y-li class=\"c8y-list__item--overflow-visible\">\n <c8y-li-icon\n class=\"p-r-0 p-t-16\"\n icon=\"th-large\"\n ></c8y-li-icon>\n <div class=\"d-flex-md\">\n <div class=\"col-md-2\">\n <!-- title -->\n <p\n class=\"text-truncate text-medium boxed-label p-l-0\"\n title=\"{{ widgetAsset.title }}\"\n >\n {{ widgetAsset.title }}\n </p>\n </div>\n <div class=\"col-md-10\">\n <div class=\"row\">\n <div class=\"col-md-4 p-l-md-0 p-r-0\">\n <!-- origin device -->\n <p class=\"visible-sm visible-xs text-label-small\">\n {{ 'Original source' | translate }}\n </p>\n <div class=\"d-flex gap-4 boxed-label\">\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.deviceRef.value }\n \"\n ></ng-container>\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.deviceRef.value.name }}\"\n >\n {{ widgetAsset.deviceRef.value.name }}\n </span>\n <small class=\"text-muted\">\n {{\n assetIdInfo | translate: { assetId: widgetAsset.deviceRef.value.id }\n }}\n </small>\n </span>\n </div>\n </div>\n <div\n class=\"col-md-1 col-xs-1 p-l-xs-0 p-l-sm-0 p-r-sm-0 p-r-xs-0 text-center p-t-16\"\n >\n <i\n class=\"icon-20\"\n [c8yIcon]=\"\n widgetAsset.selectedAsset !== undefined ? 'ok' : 'inactive-state'\n \"\n [title]=\"\n widgetAsset.selectedAsset !== undefined\n ? (assetSelectedLabel | translate)\n : (assetNotSelectedLabel | translate)\n \"\n [ngClass]=\"{\n 'text-success': widgetAsset.selectedAsset !== undefined,\n 'text-muted': widgetAsset.selectedAsset === undefined\n }\"\n ></i>\n @if (\n widgetAsset.selectedAsset === undefined && userClickedAcceptAllSuggested\n ) {\n <span\n class=\"c8y-icon-badge\"\n [tooltip]=\"\n 'No suggestion available- widget will not be imported' | translate\n \"\n placement=\"right\"\n >\n <i\n class=\"status major stroked-icon\"\n c8yIcon=\"warning\"\n ></i>\n </span>\n }\n </div>\n <div class=\"col-md-4 col-xs-11 p-l-md-0\">\n <!-- Suggested/Selected source -->\n <p class=\"visible-sm visible-xs text-label-small m-t-16 m-b-8\">\n {{ 'Selected source' | translate }}\n </p>\n @if (\n widgetAsset.deviceRef.value.suggestedDevice && !widgetAsset.selectedAsset\n ) {\n <div\n class=\"d-flex gap-4 text-muted boxed-label\"\n [attr.data-label]=\"'Suggested' | translate\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.deviceRef.value.suggestedDevice }\n \"\n ></ng-container>\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.deviceRef.value.suggestedDevice?.name }}\"\n >\n {{ widgetAsset.deviceRef.value.suggestedDevice?.name }}\n </span>\n <small class=\"text-muted\">\n {{\n assetIdInfo\n | translate\n : { assetId: widgetAsset.deviceRef.value.suggestedDevice?.id }\n }}\n </small>\n </span>\n </div>\n }\n @if (widgetAsset.selectedAsset) {\n <div class=\"d-flex gap-4 boxed-label\">\n <!-- selectedAsset icon -->\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.selectedAsset }\n \"\n ></ng-container>\n <!-- selectedAsset Name and ID -->\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.selectedAsset?.name }}\"\n >\n {{ widgetAsset.selectedAsset?.name }}\n </span>\n <small class=\"text-muted\">\n {{\n assetIdInfo | translate: { assetId: widgetAsset.selectedAsset.id }\n }}\n </small>\n </span>\n </div>\n }\n @if (\n !widgetAsset.deviceRef.value.suggestedDevice && !widgetAsset.selectedAsset\n ) {\n <div class=\"text-muted boxed-label\">\n <em>{{ 'No suggestion available' | translate }}</em>\n </div>\n }\n </div>\n <div class=\"col-md-3 p-0 flex-grow\">\n <div class=\"d-flex a-i-center j-c-end-md gap-8 boxed-label p-l-md-0 p-r-0\">\n <div class=\"input-group max-width-fit\">\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"\n (widgetAsset.deviceRef.value.suggestedDevice\n ? acceptSuggestedLabel\n : noSuggestedAssetLabel\n ) | translate\n \"\n [tooltip]=\"\n (widgetAsset.deviceRef.value.suggestedDevice\n ? acceptSuggestedLabel\n : noSuggestedAssetLabel\n ) | translate\n \"\n placement=\"top\"\n container=\"body\"\n [ngClass]=\"{\n active:\n widgetAsset.selectedAsset &&\n widgetAsset.selectedAsset ===\n widgetAsset.deviceRef.value.suggestedDevice\n }\"\n [disabled]=\"!widgetAsset.deviceRef.value.suggestedDevice\"\n (click)=\"\n widgetAsset.selectedAsset =\n widgetAsset.deviceRef.value.suggestedDevice\n \"\n >\n <i [c8yIcon]=\"'check'\"></i>\n </button>\n </div>\n <div\n class=\"dropdown input-group-btn\"\n container=\"body\"\n dropdown\n [insideClick]=\"true\"\n #dropdown=\"bs-dropdown\"\n >\n <button\n class=\"btn btn-default dropdown-toggle c8y-dropdown\"\n [attr.aria-label]=\"'Select asset' | translate\"\n tooltip=\"{{ 'Select asset' | translate }}\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n dropdownToggle\n [ngClass]=\"{\n active:\n widgetAsset.selectedAsset &&\n widgetAsset.selectedAsset !==\n widgetAsset.deviceRef.value.suggestedDevice\n }\"\n >\n <i [c8yIcon]=\"'card-exchange'\"></i>\n </button>\n <div\n class=\"dropdown-menu dropdown-menu-right--md\"\n style=\"width: 300px\"\n *dropdownMenu\n >\n @if (dropdown.isOpen) {\n <c8y-asset-selector-miller\n (onSelected)=\"\n selectionChange($event, widgetAsset); dropdown.hide()\n \"\n [asset]=\"contextAsset\"\n [config]=\"{\n groupsSelectable: true,\n showChildDevices: true,\n showFilter: true,\n showSelected: false,\n columnHeaders: true,\n singleColumn: true,\n preventInitialSelect: true\n }\"\n ></c8y-asset-selector-miller>\n }\n </div>\n </div>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Configure later' | translate\"\n tooltip=\"{{ 'Configure later' | translate }}\"\n placement=\"top\"\n container=\"body\"\n [ngClass]=\"{ active: widgetAsset.selectedAsset === null }\"\n (click)=\"widgetAsset.selectedAsset = null\"\n >\n <i [c8yIcon]=\"'link-off'\"></i>\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </c8y-li>\n }\n </c8y-list-group>\n </div>\n }\n </div>\n <div class=\"modal-footer\">\n <button\n class=\"btn btn-default\"\n [title]=\"'Cancel' | translate\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n [title]=\"'Apply' | translate\"\n type=\"button\"\n (click)=\"apply()\"\n >\n {{ 'Apply' | translate }}\n </button>\n </div>\n</div>\n\n<ng-template\n #assetIcon\n let-device\n>\n @if (device.c8y_IsDevice) {\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"'data-transfer'\"\n ></i>\n }\n @if (device.c8y_IsDeviceGroup && !device.c8y_IsAsset) {\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"'c8y-group'\"\n ></i>\n }\n @if (device.c8y_IsAsset) {\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"device.icon?.name || 'c8y-group'\"\n ></i>\n }\n</ng-template>\n" }]
264
+ args: [{ selector: 'c8y-assign-widget-asset-modal', standalone: true, imports: [CoreModule, AssetSelectorModule, BsDropdownModule, TooltipModule], template: "<div class=\"viewport-modal has-asset-selector\">\n <div class=\"modal-header dialog-header\">\n <i [c8yIcon]=\"'th-large'\"></i>\n <div\n class=\"modal-title\"\n id=\"modal-title\"\n translate\n >\n Select and confirm widget assets mapping\n </div>\n </div>\n <div\n class=\"inner-scroll\"\n id=\"modal-body\"\n >\n <div class=\"p-16\">\n <p class=\"text-center text-balance\">\n {{ modalTitle | translate }}\n </p>\n </div>\n @if (notSupportedWidgets.length) {\n <div class=\"d-flex fit-w j-c-center p-16 p-t-0\">\n <div class=\"alert alert-warning\">\n {{ 'Widgets not supported for asset mapping: {{ notSupportedWidgets }}' | translate: {\n notSupportedWidgets: notSupportedWidgets.join(', ') } }}\n </div>\n </div>\n }\n @if (!assetsToAlign.length) {\n <div class=\"p-16 d-flex j-c-center\">\n <c8y-ui-empty-state\n class=\"\"\n [icon]=\"'empty-box'\"\n [title]=\"'No assets to assign' | translate\"\n ></c8y-ui-empty-state>\n </div>\n }\n @if (assetsToAlign.length) {\n <div>\n <c8y-list-group class=\"separator-top no-border-last\">\n <c8y-li class=\"sticky-top bg-level-1 hidden-sm hidden-xs\">\n <c8y-li-icon></c8y-li-icon>\n <div class=\"d-flex\">\n <div class=\"col-md-2\">\n <!-- title -->\n <p\n class=\"text-truncate text-medium\"\n translate\n >\n Widget\n </p>\n </div>\n <div class=\"col-md-10\">\n <div class=\"row\">\n <div class=\"col-md-4 p-r-0\">\n <p\n class=\"text-medium\"\n translate\n >\n Original source\n </p>\n </div>\n <div class=\"col-md-1 text-center\">\n <button\n class=\"btn btn-default btn-sm\"\n [attr.aria-label]=\"'Accept all suggested' | translate\"\n [tooltip]=\"'Accept all suggested' | translate\"\n placement=\"right\"\n (click)=\"acceptAllSuggested()\"\n [disabled]=\"!hasSuggestedAssets\"\n >\n <i [c8yIcon]=\"'check'\"></i>\n </button>\n </div>\n <div class=\"col-md-7 p-l-8\">\n <p\n class=\"text-medium\"\n translate\n >\n Selected source\n </p>\n </div>\n </div>\n </div>\n </div>\n </c8y-li>\n @for (widgetAsset of updatedWidgetAssets; track widgetAsset; let i = $index) {\n <c8y-li class=\"c8y-list__item--overflow-visible\">\n <c8y-li-icon\n class=\"p-r-0 p-t-16\"\n icon=\"th-large\"\n ></c8y-li-icon>\n <div class=\"d-flex-md\">\n <div class=\"col-md-2\">\n <!-- title -->\n <p\n class=\"text-truncate text-medium boxed-label p-l-0\"\n title=\"{{ widgetAsset.title }}\"\n >\n {{ widgetAsset.title }}\n </p>\n </div>\n <div class=\"col-md-10\">\n <div class=\"row\">\n <div class=\"col-md-4 p-l-md-0 p-r-0\">\n <!-- origin device -->\n <p class=\"visible-sm visible-xs text-label-small\">\n {{ 'Original source' | translate }}\n </p>\n <div class=\"d-flex gap-4 boxed-label\">\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.deviceRef.value }\n \"\n ></ng-container>\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.deviceRef.value.name }}\"\n >\n {{ widgetAsset.deviceRef.value.name }}\n </span>\n <small class=\"text-muted\">\n {{\n assetIdInfo | translate: { assetId: widgetAsset.deviceRef.value.id }\n }}\n </small>\n </span>\n </div>\n </div>\n <div\n class=\"col-md-1 col-xs-1 p-l-xs-0 p-l-sm-0 p-r-sm-0 p-r-xs-0 text-center p-t-16\"\n >\n <i\n class=\"icon-20\"\n [c8yIcon]=\"\n widgetAsset.selectedAsset !== undefined ? 'ok' : 'inactive-state'\n \"\n [title]=\"\n widgetAsset.selectedAsset !== undefined\n ? (assetSelectedLabel | translate)\n : (assetNotSelectedLabel | translate)\n \"\n [ngClass]=\"{\n 'text-success': widgetAsset.selectedAsset !== undefined,\n 'text-muted': widgetAsset.selectedAsset === undefined\n }\"\n ></i>\n @if (\n widgetAsset.selectedAsset === undefined && userClickedAcceptAllSuggested\n ) {\n <span\n class=\"c8y-icon-badge\"\n [tooltip]=\"\n 'No suggestion available - widget will not be imported' | translate\n \"\n placement=\"right\"\n >\n <i\n class=\"status major stroked-icon\"\n c8yIcon=\"warning\"\n ></i>\n </span>\n }\n </div>\n <div class=\"col-md-4 col-xs-11 p-l-md-0\">\n <!-- Suggested/Selected source -->\n <p class=\"visible-sm visible-xs text-label-small m-t-16 m-b-8\">\n {{ 'Selected source' | translate }}\n </p>\n @if (\n widgetAsset.deviceRef.value.suggestedDevice && !widgetAsset.selectedAsset\n ) {\n <div\n class=\"d-flex gap-4 text-muted boxed-label\"\n [attr.data-label]=\"'Suggested' | translate\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.deviceRef.value.suggestedDevice }\n \"\n ></ng-container>\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.deviceRef.value.suggestedDevice?.name }}\"\n >\n {{ widgetAsset.deviceRef.value.suggestedDevice?.name }}\n </span>\n <small class=\"text-muted\">\n {{\n assetIdInfo\n | translate\n : { assetId: widgetAsset.deviceRef.value.suggestedDevice?.id }\n }}\n </small>\n </span>\n </div>\n }\n @if (widgetAsset.selectedAsset) {\n <div class=\"d-flex gap-4 boxed-label\">\n <!-- selectedAsset icon -->\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.selectedAsset }\n \"\n ></ng-container>\n <!-- selectedAsset Name and ID -->\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.selectedAsset?.name }}\"\n >\n {{ widgetAsset.selectedAsset?.name }}\n </span>\n <small class=\"text-muted\">\n {{\n assetIdInfo | translate: { assetId: widgetAsset.selectedAsset.id }\n }}\n </small>\n </span>\n </div>\n }\n @if (\n !widgetAsset.deviceRef.value.suggestedDevice && !widgetAsset.selectedAsset\n ) {\n <div class=\"text-muted boxed-label\">\n <em>{{ 'No suggestion available' | translate }}</em>\n </div>\n }\n </div>\n <div class=\"col-md-3 p-0 flex-grow\">\n <div class=\"d-flex a-i-center j-c-end-md gap-8 boxed-label p-l-md-0 p-r-0\">\n <div class=\"input-group max-width-fit\">\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"\n (widgetAsset.deviceRef.value.suggestedDevice\n ? acceptSuggestedLabel\n : noSuggestedAssetLabel\n ) | translate\n \"\n [tooltip]=\"\n (widgetAsset.deviceRef.value.suggestedDevice\n ? acceptSuggestedLabel\n : noSuggestedAssetLabel\n ) | translate\n \"\n placement=\"top\"\n container=\"body\"\n [ngClass]=\"{\n active:\n widgetAsset.selectedAsset &&\n widgetAsset.selectedAsset ===\n widgetAsset.deviceRef.value.suggestedDevice\n }\"\n [disabled]=\"!widgetAsset.deviceRef.value.suggestedDevice\"\n (click)=\"\n widgetAsset.selectedAsset =\n widgetAsset.deviceRef.value.suggestedDevice\n \"\n >\n <i [c8yIcon]=\"'check'\"></i>\n </button>\n </div>\n <div\n class=\"dropdown input-group-btn\"\n container=\"body\"\n dropdown\n [insideClick]=\"true\"\n #dropdown=\"bs-dropdown\"\n >\n <button\n class=\"btn btn-default dropdown-toggle c8y-dropdown\"\n [attr.aria-label]=\"'Select asset' | translate\"\n tooltip=\"{{ 'Select asset' | translate }}\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n dropdownToggle\n [ngClass]=\"{\n active:\n widgetAsset.selectedAsset &&\n widgetAsset.selectedAsset !==\n widgetAsset.deviceRef.value.suggestedDevice\n }\"\n >\n <i [c8yIcon]=\"'card-exchange'\"></i>\n </button>\n <div\n class=\"dropdown-menu dropdown-menu-right--md\"\n style=\"width: 300px\"\n *dropdownMenu\n >\n @if (dropdown.isOpen) {\n <c8y-asset-selector-miller\n (onSelected)=\"\n selectionChange($event, widgetAsset); dropdown.hide()\n \"\n [asset]=\"contextAsset\"\n [config]=\"{\n groupsSelectable: true,\n showChildDevices: true,\n showFilter: true,\n showSelected: false,\n columnHeaders: true,\n singleColumn: true,\n preventInitialSelect: true\n }\"\n ></c8y-asset-selector-miller>\n }\n </div>\n </div>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Configure later' | translate\"\n tooltip=\"{{ 'Configure later' | translate }}\"\n placement=\"top\"\n container=\"body\"\n [ngClass]=\"{ active: widgetAsset.selectedAsset === null }\"\n (click)=\"widgetAsset.selectedAsset = null\"\n >\n <i [c8yIcon]=\"'link-off'\"></i>\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </c8y-li>\n }\n </c8y-list-group>\n </div>\n }\n </div>\n <div class=\"modal-footer\">\n <button\n class=\"btn btn-default\"\n [title]=\"'Cancel' | translate\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n [title]=\"'Apply' | translate\"\n type=\"button\"\n (click)=\"apply()\"\n >\n {{ 'Apply' | translate }}\n </button>\n </div>\n</div>\n\n<ng-template\n #assetIcon\n let-device\n>\n @if (device.c8y_IsDevice) {\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"'data-transfer'\"\n ></i>\n }\n @if (device.c8y_IsDeviceGroup && !device.c8y_IsAsset) {\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"'c8y-group'\"\n ></i>\n }\n @if (device.c8y_IsAsset) {\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"device.icon?.name || 'c8y-group'\"\n ></i>\n }\n</ng-template>\n" }]
265
265
  }], propDecorators: { assetsToAlign: [{
266
266
  type: Input
267
267
  }], contextAsset: [{
@@ -587,4 +587,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
587
587
  }] });
588
588
 
589
589
  export { DashboardDetailsAdvancedTabComponent };
590
- //# sourceMappingURL=c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-DFytXNdc.mjs.map
590
+ //# sourceMappingURL=c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-C8QX6xlf.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-C8QX6xlf.mjs","sources":["../../dashboard-details-advanced-tab/dashboard-json-editor/json-validation.service.ts","../../dashboard-details-advanced-tab/assign-widget-assets/assign-widget-asset-modal.component.ts","../../dashboard-details-advanced-tab/assign-widget-assets/assign-widget-asset-modal.component.html","../../dashboard-details-advanced-tab/dashboard-json-editor/import-export-widgets.service.ts","../../dashboard-details-advanced-tab/dashboard-json-editor/dashboard-json-editor.component.ts","../../dashboard-details-advanced-tab/dashboard-json-editor/dashboard-json-editor.component.html","../../dashboard-details-advanced-tab/dashboard-details-advanced-tab.component.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { ContextDashboard } from '@c8y/ngx-components/context-dashboard';\nimport { DynamicComponentService } from '@c8y/ngx-components';\nimport Ajv from 'ajv';\nimport addFormats from 'ajv-formats';\nimport { JSONSchema7 } from 'json-schema';\n\nexport type JSONValidationError = {\n message: string;\n path: string;\n};\n\n@Injectable()\nexport class JsonValidationService {\n ajv: Ajv;\n private OMIT_ERRORS = ['must NOT be valid', 'must match exactly one schema in oneOf'];\n\n constructor(private dynamicComponentService: DynamicComponentService) {\n this.ajv = new Ajv({ verbose: true, allErrors: true });\n addFormats(this.ajv as any);\n }\n\n async validateDashboard(dashboardJson: string, schemas?: any[]): Promise<JSONValidationError[]> {\n try {\n // Parse JSON string to object\n const dashboard: ContextDashboard = JSON.parse(dashboardJson);\n\n // Get or use provided schemas\n const validationSchemas = schemas || (await this.getJsonSchemas(dashboard));\n\n // Create a new Ajv instance\n const validator = new Ajv({\n verbose: true,\n allErrors: true\n });\n\n addFormats(validator as any);\n\n // Add all component schemas individually\n validationSchemas.forEach(({ uri, schema }) => {\n validator.addSchema(schema, uri);\n });\n\n const errorsMap = new Map<string, JSONValidationError>();\n\n // Validate main dashboard structure first (without children)\n const mainSchema = validationSchemas.find(\n s => s.uri === 'context-dashboard.c8y-schema-loader'\n )?.schema;\n\n if (!mainSchema) {\n throw new Error('Dashboard schema not found');\n }\n\n // Create a copy without children for main validation\n const dashboardWithoutChildren = { ...dashboard };\n delete dashboardWithoutChildren.children;\n\n const mainValidate = validator.compile(mainSchema);\n mainValidate(dashboardWithoutChildren);\n\n // Now validate each widget with its specific schema\n if (dashboard.children) {\n Object.entries(dashboard.children).forEach(([widgetId, widget]) => {\n const componentId = widget.componentId;\n // Find the correct schema for this widget type\n const widgetSchema = validationSchemas.find(s => s.uri === componentId)?.schema;\n\n if (widgetSchema) {\n // Validate this widget's config against its specific schema\n const validateWidgetConfig = validator.compile(widgetSchema);\n const isValid = validateWidgetConfig(widget.config);\n\n if (!isValid && validateWidgetConfig.errors) {\n validateWidgetConfig.errors.forEach(error => {\n const message = error.message || 'Unknown error';\n const basePath = `/children/${widgetId}/config`;\n const relativePath = error.instancePath;\n const fullPath = basePath + relativePath;\n\n if (!this.OMIT_ERRORS.includes(message)) {\n errorsMap.set(`${message}::${fullPath}`, {\n message,\n path: fullPath\n });\n }\n });\n }\n }\n });\n }\n\n // Process any errors from main validation\n if (mainValidate.errors) {\n mainValidate.errors.forEach(error => {\n const message = error.message || 'Unknown error';\n const path = error.instancePath;\n\n // Skip children validation errors as we handled them separately\n if (!path.includes('/children/') && !this.OMIT_ERRORS.includes(message)) {\n errorsMap.set(`${message}::${path}`, { message, path });\n }\n });\n }\n\n return Array.from(errorsMap.values());\n } catch (error) {\n if (error instanceof SyntaxError) {\n return [{ message: 'Invalid JSON syntax', path: '' }];\n }\n throw error;\n }\n }\n\n /**\n * Returns JSON schema for dashboard and all its children.\n * Children are referenced by their componentId. Dashboard schema is enriched with references to children schemas.\n * @param dashboard Context dashboard object.\n */\n async getJsonSchemas(dashboard: ContextDashboard) {\n try {\n const dashboardChildrenIds = [\n ...new Set(Object.entries(dashboard.children || {}).map(([_, value]) => value.componentId))\n ];\n\n const widgetSchemasPromises = dashboardChildrenIds.map(id => this.getSchemaForWidget(id));\n const widgetSchemasResults = await Promise.allSettled(widgetSchemasPromises);\n\n // Filter out failed or null schemas\n const validWidgetSchemas = widgetSchemasResults\n .filter(\n (result): result is PromiseFulfilledResult<{ id: string; schema: any }> =>\n result.status === 'fulfilled' && result.value !== null\n )\n .map(result => result.value);\n\n const { schema: dashboardSchemaOriginal }: { schema: JSONSchema7 } = await import(\n 'c8y-schema-loader?interfaceName=ContextDashboard&type=dashboarding!@c8y/ngx-components/context-dashboard'\n );\n const dashboardSchema = JSON.parse(JSON.stringify(dashboardSchemaOriginal));\n\n // Modify Widget definition with proper schema structure\n if (validWidgetSchemas.length > 0) {\n // Remove any existing allOf or oneOf conditions that might interfere\n if (dashboardSchema.definitions.Widget.allOf) {\n delete dashboardSchema.definitions.Widget.allOf;\n }\n\n // Set up the oneOf condition\n dashboardSchema.definitions.Widget.oneOf = this.getWidgetSchemasReferences(\n validWidgetSchemas.map(({ id }) => id)\n );\n }\n\n return [\n {\n uri: 'context-dashboard.c8y-schema-loader',\n fileMatch: ['*'],\n schema: dashboardSchema\n },\n ...validWidgetSchemas.map(({ id, schema }) => ({\n uri: id,\n schema: schema\n }))\n ];\n } catch (error) {\n console.error('Error processing dashboard schemas:', error);\n throw error;\n }\n }\n\n private async getSchemaForWidget(id: string) {\n try {\n const def = await this.dynamicComponentService.getById(id);\n if (def?.data?.schema && typeof def.data.schema === 'function') {\n const { schema }: { schema: JSONSchema7 } = await def.data.schema();\n return { id, schema };\n }\n return null;\n } catch (error) {\n console.warn(`Failed to fetch schema for widget ${id}:`, error);\n return null;\n }\n }\n\n private getWidgetSchemasReferences(widgetIds: string[]) {\n // provide references to all children schemas\n const schemasPart = widgetIds.map(id => {\n return {\n properties: {\n componentId: { const: id },\n config: { $ref: `${id}#` } // Ensure proper URI reference format\n },\n required: ['componentId'] // Only require componentId\n };\n });\n\n // provide default schema for object if component has no schema definition\n const defaultPart = {\n not: {\n properties: {\n componentId: {\n enum: widgetIds\n }\n }\n },\n properties: {\n config: {\n type: 'object',\n additionalProperties: true\n }\n }\n };\n\n return [...schemasPart, defaultPart];\n }\n}\n","import { Component, inject, Input, OnInit } from '@angular/core';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport { CoreModule } from '@c8y/ngx-components';\nimport { BsModalRef } from 'ngx-bootstrap/modal';\nimport { IManagedObject } from '@c8y/client';\nimport {\n AssetSelectionChangeEvent,\n AssetSelectorModule\n} from '@c8y/ngx-components/assets-navigator';\nimport { WidgetAssetToAlign } from '../advanced-tab.model';\nimport { BsDropdownModule } from 'ngx-bootstrap/dropdown';\nimport { TooltipModule } from 'ngx-bootstrap/tooltip';\n\n@Component({\n selector: 'c8y-assign-widget-asset-modal',\n templateUrl: './assign-widget-asset-modal.component.html',\n standalone: true,\n imports: [CoreModule, AssetSelectorModule, BsDropdownModule, TooltipModule]\n})\nexport class AssignWidgetAssetModalComponent implements OnInit {\n @Input() assetsToAlign: WidgetAssetToAlign[];\n @Input() contextAsset: IManagedObject;\n @Input() notSupportedWidgets: string[] = [];\n\n modalTitle = gettext(`\n For each asset in the widgets, we suggest a source based on the original configuration. \n You can accept it, choose another asset, or configure it later. If you don’t choose any option,\n the widget will not be imported.\n `);\n assetIdInfo = gettext('id: {{ assetId }}');\n acceptSuggestedLabel = gettext('Accept suggested asset');\n noSuggestedAssetLabel = gettext('No suggestion available');\n updatedWidgetAssets: (WidgetAssetToAlign & { selectedAsset?: IManagedObject | null })[] = [];\n hasSuggestedAssets: boolean;\n userClickedAcceptAllSuggested = false;\n assetSelectedLabel = gettext('Asset selected');\n assetNotSelectedLabel = gettext('Asset not selected');\n result: Promise<WidgetAssetToAlign[]> = new Promise((resolve, reject) => {\n this._close = resolve;\n this._cancel = reject;\n });\n private _close: (value: WidgetAssetToAlign[]) => void;\n private _cancel: (reason?: any) => void;\n private bsModalRef = inject(BsModalRef);\n\n ngOnInit() {\n this.updatedWidgetAssets = this.assetsToAlign.map(asset => ({\n ...asset\n }));\n this.hasSuggestedAssets = this.updatedWidgetAssets.some(\n asset => !!asset.deviceRef.value.suggestedDevice\n );\n }\n\n apply(): void {\n const alignedAssets: WidgetAssetToAlign[] = this.updatedWidgetAssets.map(asset => {\n return {\n widgetId: asset.widgetId,\n title: asset.title,\n deviceRef: {\n path: asset.deviceRef.path,\n value:\n asset.selectedAsset == null\n ? asset.selectedAsset\n : { ...asset.selectedAsset, suggestedDevice: null }\n }\n };\n });\n this._close(alignedAssets);\n this.bsModalRef.hide();\n }\n\n acceptAllSuggested() {\n this.userClickedAcceptAllSuggested = true;\n this.updatedWidgetAssets.forEach(asset => {\n if (asset.deviceRef.value.suggestedDevice) {\n asset.selectedAsset = asset.deviceRef.value.suggestedDevice;\n }\n });\n }\n\n cancel() {\n this.bsModalRef.hide();\n this._cancel();\n }\n\n selectionChange(\n $event: AssetSelectionChangeEvent,\n widgetAsset: WidgetAssetToAlign & { selectedAsset?: IManagedObject | null }\n ) {\n widgetAsset.selectedAsset = $event.change.item;\n }\n}\n","<div class=\"viewport-modal has-asset-selector\">\n <div class=\"modal-header dialog-header\">\n <i [c8yIcon]=\"'th-large'\"></i>\n <div\n class=\"modal-title\"\n id=\"modal-title\"\n translate\n >\n Select and confirm widget assets mapping\n </div>\n </div>\n <div\n class=\"inner-scroll\"\n id=\"modal-body\"\n >\n <div class=\"p-16\">\n <p class=\"text-center text-balance\">\n {{ modalTitle | translate }}\n </p>\n </div>\n @if (notSupportedWidgets.length) {\n <div class=\"d-flex fit-w j-c-center p-16 p-t-0\">\n <div class=\"alert alert-warning\">\n {{ 'Widgets not supported for asset mapping: {{ notSupportedWidgets }}' | translate: {\n notSupportedWidgets: notSupportedWidgets.join(', ') } }}\n </div>\n </div>\n }\n @if (!assetsToAlign.length) {\n <div class=\"p-16 d-flex j-c-center\">\n <c8y-ui-empty-state\n class=\"\"\n [icon]=\"'empty-box'\"\n [title]=\"'No assets to assign' | translate\"\n ></c8y-ui-empty-state>\n </div>\n }\n @if (assetsToAlign.length) {\n <div>\n <c8y-list-group class=\"separator-top no-border-last\">\n <c8y-li class=\"sticky-top bg-level-1 hidden-sm hidden-xs\">\n <c8y-li-icon></c8y-li-icon>\n <div class=\"d-flex\">\n <div class=\"col-md-2\">\n <!-- title -->\n <p\n class=\"text-truncate text-medium\"\n translate\n >\n Widget\n </p>\n </div>\n <div class=\"col-md-10\">\n <div class=\"row\">\n <div class=\"col-md-4 p-r-0\">\n <p\n class=\"text-medium\"\n translate\n >\n Original source\n </p>\n </div>\n <div class=\"col-md-1 text-center\">\n <button\n class=\"btn btn-default btn-sm\"\n [attr.aria-label]=\"'Accept all suggested' | translate\"\n [tooltip]=\"'Accept all suggested' | translate\"\n placement=\"right\"\n (click)=\"acceptAllSuggested()\"\n [disabled]=\"!hasSuggestedAssets\"\n >\n <i [c8yIcon]=\"'check'\"></i>\n </button>\n </div>\n <div class=\"col-md-7 p-l-8\">\n <p\n class=\"text-medium\"\n translate\n >\n Selected source\n </p>\n </div>\n </div>\n </div>\n </div>\n </c8y-li>\n @for (widgetAsset of updatedWidgetAssets; track widgetAsset; let i = $index) {\n <c8y-li class=\"c8y-list__item--overflow-visible\">\n <c8y-li-icon\n class=\"p-r-0 p-t-16\"\n icon=\"th-large\"\n ></c8y-li-icon>\n <div class=\"d-flex-md\">\n <div class=\"col-md-2\">\n <!-- title -->\n <p\n class=\"text-truncate text-medium boxed-label p-l-0\"\n title=\"{{ widgetAsset.title }}\"\n >\n {{ widgetAsset.title }}\n </p>\n </div>\n <div class=\"col-md-10\">\n <div class=\"row\">\n <div class=\"col-md-4 p-l-md-0 p-r-0\">\n <!-- origin device -->\n <p class=\"visible-sm visible-xs text-label-small\">\n {{ 'Original source' | translate }}\n </p>\n <div class=\"d-flex gap-4 boxed-label\">\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.deviceRef.value }\n \"\n ></ng-container>\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.deviceRef.value.name }}\"\n >\n {{ widgetAsset.deviceRef.value.name }}\n </span>\n <small class=\"text-muted\">\n {{\n assetIdInfo | translate: { assetId: widgetAsset.deviceRef.value.id }\n }}\n </small>\n </span>\n </div>\n </div>\n <div\n class=\"col-md-1 col-xs-1 p-l-xs-0 p-l-sm-0 p-r-sm-0 p-r-xs-0 text-center p-t-16\"\n >\n <i\n class=\"icon-20\"\n [c8yIcon]=\"\n widgetAsset.selectedAsset !== undefined ? 'ok' : 'inactive-state'\n \"\n [title]=\"\n widgetAsset.selectedAsset !== undefined\n ? (assetSelectedLabel | translate)\n : (assetNotSelectedLabel | translate)\n \"\n [ngClass]=\"{\n 'text-success': widgetAsset.selectedAsset !== undefined,\n 'text-muted': widgetAsset.selectedAsset === undefined\n }\"\n ></i>\n @if (\n widgetAsset.selectedAsset === undefined && userClickedAcceptAllSuggested\n ) {\n <span\n class=\"c8y-icon-badge\"\n [tooltip]=\"\n 'No suggestion available - widget will not be imported' | translate\n \"\n placement=\"right\"\n >\n <i\n class=\"status major stroked-icon\"\n c8yIcon=\"warning\"\n ></i>\n </span>\n }\n </div>\n <div class=\"col-md-4 col-xs-11 p-l-md-0\">\n <!-- Suggested/Selected source -->\n <p class=\"visible-sm visible-xs text-label-small m-t-16 m-b-8\">\n {{ 'Selected source' | translate }}\n </p>\n @if (\n widgetAsset.deviceRef.value.suggestedDevice && !widgetAsset.selectedAsset\n ) {\n <div\n class=\"d-flex gap-4 text-muted boxed-label\"\n [attr.data-label]=\"'Suggested' | translate\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.deviceRef.value.suggestedDevice }\n \"\n ></ng-container>\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.deviceRef.value.suggestedDevice?.name }}\"\n >\n {{ widgetAsset.deviceRef.value.suggestedDevice?.name }}\n </span>\n <small class=\"text-muted\">\n {{\n assetIdInfo\n | translate\n : { assetId: widgetAsset.deviceRef.value.suggestedDevice?.id }\n }}\n </small>\n </span>\n </div>\n }\n @if (widgetAsset.selectedAsset) {\n <div class=\"d-flex gap-4 boxed-label\">\n <!-- selectedAsset icon -->\n <ng-container\n *ngTemplateOutlet=\"\n assetIcon;\n context: { $implicit: widgetAsset.selectedAsset }\n \"\n ></ng-container>\n <!-- selectedAsset Name and ID -->\n <span class=\"text-truncate\">\n <span\n class=\"text-truncate\"\n title=\"{{ widgetAsset.selectedAsset?.name }}\"\n >\n {{ widgetAsset.selectedAsset?.name }}\n </span>\n <small class=\"text-muted\">\n {{\n assetIdInfo | translate: { assetId: widgetAsset.selectedAsset.id }\n }}\n </small>\n </span>\n </div>\n }\n @if (\n !widgetAsset.deviceRef.value.suggestedDevice && !widgetAsset.selectedAsset\n ) {\n <div class=\"text-muted boxed-label\">\n <em>{{ 'No suggestion available' | translate }}</em>\n </div>\n }\n </div>\n <div class=\"col-md-3 p-0 flex-grow\">\n <div class=\"d-flex a-i-center j-c-end-md gap-8 boxed-label p-l-md-0 p-r-0\">\n <div class=\"input-group max-width-fit\">\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"\n (widgetAsset.deviceRef.value.suggestedDevice\n ? acceptSuggestedLabel\n : noSuggestedAssetLabel\n ) | translate\n \"\n [tooltip]=\"\n (widgetAsset.deviceRef.value.suggestedDevice\n ? acceptSuggestedLabel\n : noSuggestedAssetLabel\n ) | translate\n \"\n placement=\"top\"\n container=\"body\"\n [ngClass]=\"{\n active:\n widgetAsset.selectedAsset &&\n widgetAsset.selectedAsset ===\n widgetAsset.deviceRef.value.suggestedDevice\n }\"\n [disabled]=\"!widgetAsset.deviceRef.value.suggestedDevice\"\n (click)=\"\n widgetAsset.selectedAsset =\n widgetAsset.deviceRef.value.suggestedDevice\n \"\n >\n <i [c8yIcon]=\"'check'\"></i>\n </button>\n </div>\n <div\n class=\"dropdown input-group-btn\"\n container=\"body\"\n dropdown\n [insideClick]=\"true\"\n #dropdown=\"bs-dropdown\"\n >\n <button\n class=\"btn btn-default dropdown-toggle c8y-dropdown\"\n [attr.aria-label]=\"'Select asset' | translate\"\n tooltip=\"{{ 'Select asset' | translate }}\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n dropdownToggle\n [ngClass]=\"{\n active:\n widgetAsset.selectedAsset &&\n widgetAsset.selectedAsset !==\n widgetAsset.deviceRef.value.suggestedDevice\n }\"\n >\n <i [c8yIcon]=\"'card-exchange'\"></i>\n </button>\n <div\n class=\"dropdown-menu dropdown-menu-right--md\"\n style=\"width: 300px\"\n *dropdownMenu\n >\n @if (dropdown.isOpen) {\n <c8y-asset-selector-miller\n (onSelected)=\"\n selectionChange($event, widgetAsset); dropdown.hide()\n \"\n [asset]=\"contextAsset\"\n [config]=\"{\n groupsSelectable: true,\n showChildDevices: true,\n showFilter: true,\n showSelected: false,\n columnHeaders: true,\n singleColumn: true,\n preventInitialSelect: true\n }\"\n ></c8y-asset-selector-miller>\n }\n </div>\n </div>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Configure later' | translate\"\n tooltip=\"{{ 'Configure later' | translate }}\"\n placement=\"top\"\n container=\"body\"\n [ngClass]=\"{ active: widgetAsset.selectedAsset === null }\"\n (click)=\"widgetAsset.selectedAsset = null\"\n >\n <i [c8yIcon]=\"'link-off'\"></i>\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </c8y-li>\n }\n </c8y-list-group>\n </div>\n }\n </div>\n <div class=\"modal-footer\">\n <button\n class=\"btn btn-default\"\n [title]=\"'Cancel' | translate\"\n type=\"button\"\n (click)=\"cancel()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n [title]=\"'Apply' | translate\"\n type=\"button\"\n (click)=\"apply()\"\n >\n {{ 'Apply' | translate }}\n </button>\n </div>\n</div>\n\n<ng-template\n #assetIcon\n let-device\n>\n @if (device.c8y_IsDevice) {\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"'data-transfer'\"\n ></i>\n }\n @if (device.c8y_IsDeviceGroup && !device.c8y_IsAsset) {\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"'c8y-group'\"\n ></i>\n }\n @if (device.c8y_IsAsset) {\n <i\n class=\"l-h-inherit\"\n [c8yIcon]=\"device.icon?.name || 'c8y-group'\"\n ></i>\n }\n</ng-template>\n","import { inject, Injectable, Injector, runInInjectionContext } from '@angular/core';\nimport { ContextDashboard, DashboardDetailService } from '@c8y/ngx-components/context-dashboard';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport { cloneDeep } from 'lodash-es';\nimport { saveAs } from 'file-saver';\nimport {\n AlertService,\n DroppedFile,\n DynamicComponentService,\n Widget,\n WidgetDataType\n} from '@c8y/ngx-components';\nimport { IManagedObject } from '@c8y/client';\nimport { BsModalService } from 'ngx-bootstrap/modal';\nimport { AssignWidgetAssetModalComponent } from '../assign-widget-assets/assign-widget-asset-modal.component';\nimport { WidgetAssetToAlign } from '../advanced-tab.model';\n\n@Injectable()\nexport class ImportExportWidgetsService {\n private dynamicComponentService = inject(DynamicComponentService);\n private injector = inject(Injector);\n private alertService = inject(AlertService);\n private dashboardDetailService = inject(DashboardDetailService);\n private modal = inject(BsModalService);\n\n /**\n * Export the dashboard to a JSON file. If the widget has an export method, it will be called to export\n * the widget's configuration.\n * @param dashboard Context dashboard to be exported\n */\n async export(dashboard: ContextDashboard) {\n const copiedDashboard: ContextDashboard = cloneDeep(dashboard);\n\n for (const [id, child] of Object.entries(copiedDashboard.children || {})) {\n try {\n const definition = await this.dynamicComponentService.getById(child.componentId);\n\n if (definition && typeof definition.data.export === 'function') {\n const widgetData: WidgetDataType = definition.data;\n const pluginInjector = definition.injector || this.injector;\n await runInInjectionContext(pluginInjector, async () => {\n const exportedConfig = await widgetData.export(\n child.config,\n this.dashboardDetailService.details,\n { pluginInjector, injector: this.injector }\n );\n copiedDashboard.children[id].config = exportedConfig;\n });\n }\n } catch (error) {\n this.alertService.addServerFailure(error);\n }\n }\n const dateStr = new Date().toISOString().replace(/[:.]/g, '-');\n const filename = `dashboard_${dateStr}.json`;\n const blob = new Blob([JSON.stringify(copiedDashboard)], { type: 'application/json' });\n saveAs(blob, filename);\n this.alertService.success(gettext('Dashboard exported.'));\n }\n\n /**\n * Import the dashboard from a JSON file. If the widget has an import method, it will be called to import\n * widget's configuration.\n * @param file JSON file with context dashboard configuration\n */\n async import(file: DroppedFile[]) {\n if (!file || file.length === 0) {\n return;\n }\n const dashboard: ContextDashboard = await file[0].readAsJson();\n const notSupportedWidgets: string[] = [];\n\n for (const [id, child] of Object.entries(dashboard.children)) {\n try {\n const definition = await this.dynamicComponentService.getById(child.componentId);\n\n if (definition && typeof definition.data.import === 'function') {\n const widgetData: WidgetDataType = definition.data;\n const pluginInjector = definition.injector || this.injector;\n await runInInjectionContext(pluginInjector, async () => {\n const importedConfig = await widgetData.import(\n child.config,\n this.dashboardDetailService.details,\n { pluginInjector, injector: this.injector }\n );\n dashboard.children[id].config = importedConfig;\n });\n } else {\n notSupportedWidgets.push(child.title);\n }\n } catch (error) {\n console.error(`Error importing widget with id ${id}:`, error);\n }\n }\n if (Object.entries(dashboard.children).length) {\n dashboard.children = await this.assignWidgetAssets(dashboard.children, notSupportedWidgets);\n if (!dashboard.children) {\n return;\n }\n }\n\n return JSON.stringify(dashboard, null, 2);\n }\n\n private async assignWidgetAssets(\n widgets: {\n [id: string]: Widget;\n },\n notSupportedWidgets: string[]\n ): Promise<{ [id: string]: Widget }> {\n const assetsToAlign = this.findWidgetsWithSuggestedDevice(widgets);\n const contextAsset = this.dashboardDetailService.details.context;\n\n try {\n const modalRef = this.modal.show(AssignWidgetAssetModalComponent, {\n class: 'modal-lg',\n ariaDescribedby: 'modal-body',\n ariaLabelledBy: 'modal-title',\n ignoreBackdropClick: true,\n keyboard: false,\n initialState: { assetsToAlign, contextAsset, notSupportedWidgets }\n }).content;\n const result = await modalRef.result;\n\n return this.updateWidgets(widgets, result);\n } catch (_) {\n // cancel clicked\n return null;\n }\n }\n\n private findWidgetsWithSuggestedDevice(widgets: Record<string, Widget>): WidgetAssetToAlign[] {\n const results: WidgetAssetToAlign[] = [];\n\n const searchObject = (obj: any, path: string[] = []): void => {\n if (!obj || typeof obj !== 'object') return;\n\n for (const [key, value] of Object.entries(obj)) {\n const currentPath = [...path, key];\n\n if (key === 'suggestedDevice') {\n // Find the nearest device/__target reference\n let deviceRef: (IManagedObject & { suggestedDevice: IManagedObject }) | null = null;\n let devicePath: string[] = [];\n\n // Search for __target or device in parent objects\n let currentObj = obj;\n const currentSearchPath = [...path];\n while (currentObj && !deviceRef) {\n if (currentObj.__target) {\n deviceRef = currentObj.__target;\n devicePath = [...currentSearchPath, '__target'];\n break;\n }\n if (currentObj.device) {\n deviceRef = currentObj.device;\n devicePath = [...currentSearchPath, 'device'];\n break;\n }\n // Move up one level\n currentSearchPath.pop();\n currentObj = this.getObjectByPath(widgets, currentSearchPath);\n }\n\n if (deviceRef) {\n const widgetId = path[0]; // First element in path should be widget ID\n results.push({\n widgetId,\n title: widgets[widgetId].title,\n deviceRef: { path: devicePath, value: deviceRef }\n });\n }\n } else if (typeof value === 'object') {\n searchObject(value, currentPath);\n }\n }\n };\n\n searchObject(widgets);\n return results;\n }\n\n private getObjectByPath(obj: any, path: string[]): any {\n return path.reduce((curr, key) => curr && curr[key], obj);\n }\n\n private updateWidgets(\n originalWidgets: Record<string, Widget>,\n processedReferences: Array<{\n widgetId: string;\n deviceRef: { path: string[]; value: IManagedObject };\n }>\n ): Record<string, Widget> {\n const result = JSON.parse(JSON.stringify(originalWidgets));\n\n // remove widgets that were no aligned\n processedReferences.forEach(ref => {\n if (ref.deviceRef.value === undefined) {\n delete result[ref.widgetId];\n return;\n }\n\n // apply selected assets to widgets\n const obj = this.getObjectByPath(result, ref.deviceRef.path.slice(0, -1));\n const lastKey = ref.deviceRef.path[ref.deviceRef.path.length - 1];\n if (obj && lastKey) {\n obj[lastKey] = ref.deviceRef.value;\n delete obj[lastKey]?.suggestedDevice;\n }\n });\n\n return result;\n }\n}\n","import { ContextDashboard, DashboardDetailService } from '@c8y/ngx-components/context-dashboard';\nimport { Component, inject, OnInit, signal, ViewChild } from '@angular/core';\nimport { PopoverModule } from 'ngx-bootstrap/popover';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport {\n CommonModule,\n CoreModule,\n DroppedFile,\n FormsModule,\n ThemeOptions\n} from '@c8y/ngx-components';\nimport { EditorComponent } from '@c8y/ngx-components/editor';\nimport { JSONValidationError, JsonValidationService } from './json-validation.service';\nimport { debounceTime, Subject, takeUntil } from 'rxjs';\nimport { ReactiveFormsModule } from '@angular/forms';\nimport { ImportExportWidgetsService } from './import-export-widgets.service';\n\n@Component({\n selector: 'c8y-dashboard-json-editor',\n templateUrl: 'dashboard-json-editor.component.html',\n standalone: true,\n imports: [\n CommonModule,\n FormsModule,\n ReactiveFormsModule,\n CoreModule,\n PopoverModule,\n EditorComponent\n ],\n providers: [JsonValidationService, ImportExportWidgetsService]\n})\nexport class DashboardJsonEditorComponent implements OnInit {\n infoText = gettext(\n \"Import / Export allows copying dashboard configurations between assets using JSON files. You can export a dashboard's setup and import it to another asset.\\n\\nNote: Basic knowledge of dashboard JSON structure is required.\"\n );\n @ViewChild(EditorComponent) editorComponent!: EditorComponent;\n dashboard: ContextDashboard;\n\n valueString = '';\n errors = signal<JSONValidationError[]>([]);\n editorDirty: boolean;\n editorTheme: ThemeOptions;\n isExporting = false;\n isImporting = false;\n editorOptions: EditorComponent['editorOptions'] = {\n hover: {\n above: false\n }\n };\n\n private dashboardDetailService = inject(DashboardDetailService);\n private jsonValidationService = inject(JsonValidationService);\n private importExportWidgetsService = inject(ImportExportWidgetsService);\n\n private valueChange = new Subject<void>();\n private destroy$ = new Subject<void>();\n private currentSchemas: any[] | null = null;\n\n ngOnInit() {\n this.dashboard = this.dashboardDetailService.details.dashboard;\n this.editorTheme = this.getEditorTheme();\n\n this.valueString = JSON.stringify(this.dashboard, null, 2);\n this.valueChange.pipe(debounceTime(500), takeUntil(this.destroy$)).subscribe(() => {\n this.applyChanges();\n this.validate();\n });\n }\n\n ngOnDestroy() {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n dashboardJSONChange(value: string) {\n this.valueString = value;\n this.valueChange.next();\n }\n\n async assignSchema() {\n this.currentSchemas = await this.jsonValidationService.getJsonSchemas(this.dashboard);\n this.editorComponent.monaco.languages.json.jsonDefaults.setDiagnosticsOptions({\n validate: true,\n schemas: this.currentSchemas,\n enableSchemaRequest: false,\n allowComments: false\n });\n this.validate();\n }\n\n async validate() {\n this.editorDirty = this.valueString !== JSON.stringify(this.dashboard, null, 2);\n try {\n const validationResult = await this.jsonValidationService.validateDashboard(\n this.valueString,\n this.currentSchemas\n );\n this.errors.set(validationResult);\n } catch (error) {\n console.error('Validation error:', error);\n this.errors.set([\n {\n message: 'An error occurred during validation',\n path: ''\n }\n ]);\n }\n }\n\n applyChanges() {\n try {\n const newDashboard = JSON.parse(this.valueString);\n this.dashboardDetailService.details.dashboard = newDashboard;\n this.dashboardDetailService.generalSettingsForm.patchValue(newDashboard);\n this.dashboardDetailService.appearanceSettingsForm.patchValue(newDashboard);\n this.dashboardDetailService.widgetsForm.patchValue(newDashboard);\n this.dashboardDetailService.previewChangedFn({\n classes: newDashboard.classes,\n widgetClasses: newDashboard.widgetClasses\n });\n this.dashboardDetailService.dashboardDetailsForm.markAsDirty();\n this.dashboardDetailService.saveButtonDisabled = false;\n } catch (error) {\n // disable save button if JSON is invalid and don't apply value to form\n this.dashboardDetailService.saveButtonDisabled = true;\n }\n }\n\n async export() {\n this.isExporting = true;\n try {\n await this.importExportWidgetsService.export(this.dashboard);\n } finally {\n this.isExporting = false;\n }\n }\n\n async import(file: DroppedFile[]) {\n this.isImporting = true;\n try {\n if (file && file.length !== 0) {\n const importedValue = await this.importExportWidgetsService.import(file);\n if (importedValue) {\n this.valueString = importedValue;\n this.valueChange.next();\n }\n }\n } finally {\n this.isImporting = false;\n }\n }\n\n private getEditorTheme(): ThemeOptions | null {\n const dashboardClasses =\n this.dashboardDetailService.appearanceSettingsForm.get('classes').value;\n\n if (dashboardClasses['dashboard-theme-dark']) {\n return 'dark';\n } else if (dashboardClasses['dashboard-theme-white']) {\n return 'light';\n }\n return null;\n }\n}\n","<div class=\"card-block\">\n<div\n class=\"d-flex d-col\"\n [ngStyle]=\"{ height: '410px' }\"\n>\n <ng-container *ngIf=\"!isExporting && !isImporting; else loading\">\n <div class=\"d-flex gap-16 flex-grow min-height-0\">\n <div class=\"d-col col-md-8 col-xs-6\">\n <label class=\"d-flex a-i-center\">{{ 'Dashboard configuration' | translate }} \n <button \n type=\"button\"\n [attr.aria-label]=\"'Help' | translate\"\n class=\"btn-help \" \n placement=\"right\"\n triggers=\"focus\"\n containerClass=\"text-pre-wrap\"\n [popover]=\"infoText | translate\"\n ></button>\n </label>\n <c8y-editor\n class=\"flex-grow min-height-0\"\n [ngModel]=\"valueString\"\n (ngModelChange)=\"dashboardJSONChange($event)\"\n (editorInit)=\"assignSchema()\"\n [theme]=\"editorTheme\"\n monacoEditorMarkerValidator\n [editorOptions]=\"editorOptions\"\n ></c8y-editor>\n </div>\n <div class=\"col-md-4 d-col col-xs-6\">\n <label translate>Validation</label>\n <div\n class=\"c8y-messages has-error m-b-24 inner-scroll flex-grow\"\n *ngIf=\"errors().length > 0\"\n >\n <div\n class=\"form-control-feedback-message\"\n *ngFor=\"let error of errors()\"\n >\n <span\n class=\"error-path\"\n *ngIf=\"error.path\"\n >\n {{ error.path }}:\n </span>\n <span class=\"error-message\">{{ error.message }}</span>\n </div>\n </div>\n <div\n class=\"c8y-messages has-success m-b-24\"\n *ngIf=\"errors().length === 0\"\n >\n <div\n class=\"form-control-feedback-message\"\n >\n <span class=\"error-message\">{{ 'No errors found' | translate }}</span>\n </div>\n </div>\n <div class=\"d-flex gap-16 a-i-center flex-no-shrink min-height-0 m-t-auto\">\n <c8y-drop-area\n class=\"drop-area-sm min-width-0\"\n [icon]=\"'upload'\"\n *ngIf=\"!isExporting\"\n [accept]=\"'.json'\"\n [maxAllowedFiles]=\"1\"\n [message]=\"'Import JSON' | translate\"\n (dropped)=\"import($event)\"\n [loading]=\"isImporting\"\n ></c8y-drop-area>\n <button\n class=\"btn btn-primary\"\n (click)=\"export()\"\n [disabled]=\"isExporting || isImporting\"\n [ngClass]=\"{\n 'btn-pending': isExporting\n }\"\n >\n {{'Export JSON' | translate}}\n </button>\n </div>\n </div>\n </div>\n </ng-container>\n\n</div>\n\n<ng-template #loading>\n <c8y-loading></c8y-loading>\n</ng-template>\n","import { Component } from '@angular/core';\nimport { DashboardJsonEditorComponent } from './dashboard-json-editor/dashboard-json-editor.component';\n\n@Component({\n selector: 'app-dashboard-details-advanced-tab',\n template: `<c8y-dashboard-json-editor></c8y-dashboard-json-editor>`,\n standalone: true,\n imports: [DashboardJsonEditorComponent]\n})\nexport class DashboardDetailsAdvancedTabComponent {}\n"],"names":["i3","i4"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;MAaa,qBAAqB,CAAA;AAIhC,IAAA,WAAA,CAAoB,uBAAgD,EAAA;QAAhD,IAAA,CAAA,uBAAuB,GAAvB,uBAAuB;AAFnC,QAAA,IAAA,CAAA,WAAW,GAAG,CAAC,mBAAmB,EAAE,wCAAwC,CAAC;AAGnF,QAAA,IAAI,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AACtD,QAAA,UAAU,CAAC,IAAI,CAAC,GAAU,CAAC;IAC7B;AAEA,IAAA,MAAM,iBAAiB,CAAC,aAAqB,EAAE,OAAe,EAAA;AAC5D,QAAA,IAAI;;YAEF,MAAM,SAAS,GAAqB,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC;;AAG7D,YAAA,MAAM,iBAAiB,GAAG,OAAO,KAAK,MAAM,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;;AAG3E,YAAA,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC;AACxB,gBAAA,OAAO,EAAE,IAAI;AACb,gBAAA,SAAS,EAAE;AACZ,aAAA,CAAC;YAEF,UAAU,CAAC,SAAgB,CAAC;;YAG5B,iBAAiB,CAAC,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAI;AAC5C,gBAAA,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,GAAG,CAAC;AAClC,YAAA,CAAC,CAAC;AAEF,YAAA,MAAM,SAAS,GAAG,IAAI,GAAG,EAA+B;;AAGxD,YAAA,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CACvC,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,qCAAqC,CACrD,EAAE,MAAM;YAET,IAAI,CAAC,UAAU,EAAE;AACf,gBAAA,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC;YAC/C;;AAGA,YAAA,MAAM,wBAAwB,GAAG,EAAE,GAAG,SAAS,EAAE;YACjD,OAAO,wBAAwB,CAAC,QAAQ;YAExC,MAAM,YAAY,GAAG,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC;YAClD,YAAY,CAAC,wBAAwB,CAAC;;AAGtC,YAAA,IAAI,SAAS,CAAC,QAAQ,EAAE;AACtB,gBAAA,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAI;AAChE,oBAAA,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW;;AAEtC,oBAAA,MAAM,YAAY,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,WAAW,CAAC,EAAE,MAAM;oBAE/E,IAAI,YAAY,EAAE;;wBAEhB,MAAM,oBAAoB,GAAG,SAAS,CAAC,OAAO,CAAC,YAAY,CAAC;wBAC5D,MAAM,OAAO,GAAG,oBAAoB,CAAC,MAAM,CAAC,MAAM,CAAC;AAEnD,wBAAA,IAAI,CAAC,OAAO,IAAI,oBAAoB,CAAC,MAAM,EAAE;AAC3C,4BAAA,oBAAoB,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,IAAG;AAC1C,gCAAA,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,eAAe;AAChD,gCAAA,MAAM,QAAQ,GAAG,CAAA,UAAA,EAAa,QAAQ,SAAS;AAC/C,gCAAA,MAAM,YAAY,GAAG,KAAK,CAAC,YAAY;AACvC,gCAAA,MAAM,QAAQ,GAAG,QAAQ,GAAG,YAAY;gCAExC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE;oCACvC,SAAS,CAAC,GAAG,CAAC,CAAA,EAAG,OAAO,CAAA,EAAA,EAAK,QAAQ,EAAE,EAAE;wCACvC,OAAO;AACP,wCAAA,IAAI,EAAE;AACP,qCAAA,CAAC;gCACJ;AACF,4BAAA,CAAC,CAAC;wBACJ;oBACF;AACF,gBAAA,CAAC,CAAC;YACJ;;AAGA,YAAA,IAAI,YAAY,CAAC,MAAM,EAAE;AACvB,gBAAA,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,IAAG;AAClC,oBAAA,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,eAAe;AAChD,oBAAA,MAAM,IAAI,GAAG,KAAK,CAAC,YAAY;;AAG/B,oBAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE;AACvE,wBAAA,SAAS,CAAC,GAAG,CAAC,CAAA,EAAG,OAAO,CAAA,EAAA,EAAK,IAAI,CAAA,CAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;oBACzD;AACF,gBAAA,CAAC,CAAC;YACJ;YAEA,OAAO,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;QACvC;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,IAAI,KAAK,YAAY,WAAW,EAAE;gBAChC,OAAO,CAAC,EAAE,OAAO,EAAE,qBAAqB,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;YACvD;AACA,YAAA,MAAM,KAAK;QACb;IACF;AAEA;;;;AAIG;IACH,MAAM,cAAc,CAAC,SAA2B,EAAA;AAC9C,QAAA,IAAI;AACF,YAAA,MAAM,oBAAoB,GAAG;AAC3B,gBAAA,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,KAAK,CAAC,WAAW,CAAC;aAC3F;AAED,YAAA,MAAM,qBAAqB,GAAG,oBAAoB,CAAC,GAAG,CAAC,EAAE,IAAI,IAAI,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC;YACzF,MAAM,oBAAoB,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,qBAAqB,CAAC;;YAG5E,MAAM,kBAAkB,GAAG;AACxB,iBAAA,MAAM,CACL,CAAC,MAAM,KACL,MAAM,CAAC,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI;iBAEzD,GAAG,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,CAAC;YAE9B,MAAM,EAAE,MAAM,EAAE,uBAAuB,EAAE,GAA4B,MAAM,OACzE,0GAA0G,CAC3G;AACD,YAAA,MAAM,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;;AAG3E,YAAA,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE;;gBAEjC,IAAI,eAAe,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,EAAE;AAC5C,oBAAA,OAAO,eAAe,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK;gBACjD;;gBAGA,eAAe,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,0BAA0B,CACxE,kBAAkB,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CACvC;YACH;YAEA,OAAO;AACL,gBAAA;AACE,oBAAA,GAAG,EAAE,qCAAqC;oBAC1C,SAAS,EAAE,CAAC,GAAG,CAAC;AAChB,oBAAA,MAAM,EAAE;AACT,iBAAA;AACD,gBAAA,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM;AAC7C,oBAAA,GAAG,EAAE,EAAE;AACP,oBAAA,MAAM,EAAE;AACT,iBAAA,CAAC;aACH;QACH;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,KAAK,CAAC;AAC3D,YAAA,MAAM,KAAK;QACb;IACF;IAEQ,MAAM,kBAAkB,CAAC,EAAU,EAAA;AACzC,QAAA,IAAI;YACF,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,OAAO,CAAC,EAAE,CAAC;AAC1D,YAAA,IAAI,GAAG,EAAE,IAAI,EAAE,MAAM,IAAI,OAAO,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,UAAU,EAAE;gBAC9D,MAAM,EAAE,MAAM,EAAE,GAA4B,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE;AACnE,gBAAA,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE;YACvB;AACA,YAAA,OAAO,IAAI;QACb;QAAE,OAAO,KAAK,EAAE;YACd,OAAO,CAAC,IAAI,CAAC,CAAA,kCAAA,EAAqC,EAAE,CAAA,CAAA,CAAG,EAAE,KAAK,CAAC;AAC/D,YAAA,OAAO,IAAI;QACb;IACF;AAEQ,IAAA,0BAA0B,CAAC,SAAmB,EAAA;;QAEpD,MAAM,WAAW,GAAG,SAAS,CAAC,GAAG,CAAC,EAAE,IAAG;YACrC,OAAO;AACL,gBAAA,UAAU,EAAE;AACV,oBAAA,WAAW,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;oBAC1B,MAAM,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAA,CAAA,CAAG,EAAE;AAC3B,iBAAA;AACD,gBAAA,QAAQ,EAAE,CAAC,aAAa,CAAC;aAC1B;AACH,QAAA,CAAC,CAAC;;AAGF,QAAA,MAAM,WAAW,GAAG;AAClB,YAAA,GAAG,EAAE;AACH,gBAAA,UAAU,EAAE;AACV,oBAAA,WAAW,EAAE;AACX,wBAAA,IAAI,EAAE;AACP;AACF;AACF,aAAA;AACD,YAAA,UAAU,EAAE;AACV,gBAAA,MAAM,EAAE;AACN,oBAAA,IAAI,EAAE,QAAQ;AACd,oBAAA,oBAAoB,EAAE;AACvB;AACF;SACF;AAED,QAAA,OAAO,CAAC,GAAG,WAAW,EAAE,WAAW,CAAC;IACtC;+GA1MW,qBAAqB,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,uBAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;mHAArB,qBAAqB,EAAA,CAAA,CAAA;;4FAArB,qBAAqB,EAAA,UAAA,EAAA,CAAA;kBADjC;;;MCOY,+BAA+B,CAAA;AAN5C,IAAA,WAAA,GAAA;QASW,IAAA,CAAA,mBAAmB,GAAa,EAAE;QAE3C,IAAA,CAAA,UAAU,GAAG,OAAO,CAAC;;;;AAIhB,MAAA,CAAA,CAAC;AACN,QAAA,IAAA,CAAA,WAAW,GAAG,OAAO,CAAC,mBAAmB,CAAC;AAC1C,QAAA,IAAA,CAAA,oBAAoB,GAAG,OAAO,CAAC,wBAAwB,CAAC;AACxD,QAAA,IAAA,CAAA,qBAAqB,GAAG,OAAO,CAAC,yBAAyB,CAAC;QAC1D,IAAA,CAAA,mBAAmB,GAAuE,EAAE;QAE5F,IAAA,CAAA,6BAA6B,GAAG,KAAK;AACrC,QAAA,IAAA,CAAA,kBAAkB,GAAG,OAAO,CAAC,gBAAgB,CAAC;AAC9C,QAAA,IAAA,CAAA,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,CAAC;QACrD,IAAA,CAAA,MAAM,GAAkC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,KAAI;AACtE,YAAA,IAAI,CAAC,MAAM,GAAG,OAAO;AACrB,YAAA,IAAI,CAAC,OAAO,GAAG,MAAM;AACvB,QAAA,CAAC,CAAC;AAGM,QAAA,IAAA,CAAA,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;AAiDxC,IAAA;IA/CC,QAAQ,GAAA;AACN,QAAA,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,KAAK;AAC1D,YAAA,GAAG;AACJ,SAAA,CAAC,CAAC;QACH,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,mBAAmB,CAAC,IAAI,CACrD,KAAK,IAAI,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,eAAe,CACjD;IACH;IAEA,KAAK,GAAA;QACH,MAAM,aAAa,GAAyB,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,KAAK,IAAG;YAC/E,OAAO;gBACL,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,KAAK,EAAE,KAAK,CAAC,KAAK;AAClB,gBAAA,SAAS,EAAE;AACT,oBAAA,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC,IAAI;AAC1B,oBAAA,KAAK,EACH,KAAK,CAAC,aAAa,IAAI;0BACnB,KAAK,CAAC;0BACN,EAAE,GAAG,KAAK,CAAC,aAAa,EAAE,eAAe,EAAE,IAAI;AACtD;aACF;AACH,QAAA,CAAC,CAAC;AACF,QAAA,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC;AAC1B,QAAA,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;IACxB;IAEA,kBAAkB,GAAA;AAChB,QAAA,IAAI,CAAC,6BAA6B,GAAG,IAAI;AACzC,QAAA,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,KAAK,IAAG;YACvC,IAAI,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,eAAe,EAAE;gBACzC,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,eAAe;YAC7D;AACF,QAAA,CAAC,CAAC;IACJ;IAEA,MAAM,GAAA;AACJ,QAAA,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;QACtB,IAAI,CAAC,OAAO,EAAE;IAChB;IAEA,eAAe,CACb,MAAiC,EACjC,WAA2E,EAAA;QAE3E,WAAW,CAAC,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI;IAChD;+GAxEW,+BAA+B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;mGAA/B,+BAA+B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,+BAAA,EAAA,MAAA,EAAA,EAAA,aAAA,EAAA,eAAA,EAAA,YAAA,EAAA,cAAA,EAAA,mBAAA,EAAA,qBAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECnB5C,ikgBAiYA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EDhXY,UAAU,mgCAAE,mBAAmB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,mBAAA,EAAA,QAAA,EAAA,2BAAA,EAAA,MAAA,EAAA,CAAA,QAAA,EAAA,OAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,WAAA,CAAA,EAAA,OAAA,EAAA,CAAA,YAAA,EAAA,iBAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAE,gBAAgB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,uBAAA,EAAA,QAAA,EAAA,iCAAA,EAAA,QAAA,EAAA,CAAA,kBAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,yBAAA,EAAA,QAAA,EAAA,qCAAA,EAAA,QAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,mBAAA,EAAA,QAAA,EAAA,0BAAA,EAAA,MAAA,EAAA,CAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,WAAA,EAAA,YAAA,EAAA,aAAA,EAAA,YAAA,EAAA,QAAA,CAAA,EAAA,OAAA,EAAA,CAAA,cAAA,EAAA,SAAA,EAAA,UAAA,CAAA,EAAA,QAAA,EAAA,CAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAE,aAAa,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,gBAAA,EAAA,QAAA,EAAA,0BAAA,EAAA,MAAA,EAAA,CAAA,kBAAA,EAAA,SAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,gBAAA,EAAA,mBAAA,EAAA,QAAA,EAAA,YAAA,EAAA,OAAA,EAAA,aAAA,EAAA,kBAAA,EAAA,eAAA,EAAA,eAAA,EAAA,qBAAA,EAAA,kBAAA,EAAA,cAAA,EAAA,gBAAA,EAAA,mBAAA,EAAA,qBAAA,EAAA,gBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,EAAA,SAAA,EAAA,UAAA,EAAA,qBAAA,CAAA,EAAA,QAAA,EAAA,CAAA,YAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,MAAA,EAAA,IAAA,EAAA,EAAA,CAAA,gBAAA,EAAA,IAAA,EAAA,WAAA,EAAA,CAAA,EAAA,CAAA,CAAA;;4FAE/D,+BAA+B,EAAA,UAAA,EAAA,CAAA;kBAN3C,SAAS;+BACE,+BAA+B,EAAA,UAAA,EAE7B,IAAI,EAAA,OAAA,EACP,CAAC,UAAU,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,aAAa,CAAC,EAAA,QAAA,EAAA,ikgBAAA,EAAA;;sBAG1E;;sBACA;;sBACA;;;MEJU,0BAA0B,CAAA;AADvC,IAAA,WAAA,GAAA;AAEU,QAAA,IAAA,CAAA,uBAAuB,GAAG,MAAM,CAAC,uBAAuB,CAAC;AACzD,QAAA,IAAA,CAAA,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;AAC3B,QAAA,IAAA,CAAA,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;AACnC,QAAA,IAAA,CAAA,sBAAsB,GAAG,MAAM,CAAC,sBAAsB,CAAC;AACvD,QAAA,IAAA,CAAA,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC;AA8LvC,IAAA;AA5LC;;;;AAIG;IACH,MAAM,MAAM,CAAC,SAA2B,EAAA;AACtC,QAAA,MAAM,eAAe,GAAqB,SAAS,CAAC,SAAS,CAAC;AAE9D,QAAA,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE;AACxE,YAAA,IAAI;AACF,gBAAA,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC;gBAEhF,IAAI,UAAU,IAAI,OAAO,UAAU,CAAC,IAAI,CAAC,MAAM,KAAK,UAAU,EAAE;AAC9D,oBAAA,MAAM,UAAU,GAAmB,UAAU,CAAC,IAAI;oBAClD,MAAM,cAAc,GAAG,UAAU,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ;AAC3D,oBAAA,MAAM,qBAAqB,CAAC,cAAc,EAAE,YAAW;wBACrD,MAAM,cAAc,GAAG,MAAM,UAAU,CAAC,MAAM,CAC5C,KAAK,CAAC,MAAM,EACZ,IAAI,CAAC,sBAAsB,CAAC,OAAO,EACnC,EAAE,cAAc,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAC5C;wBACD,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,MAAM,GAAG,cAAc;AACtD,oBAAA,CAAC,CAAC;gBACJ;YACF;YAAE,OAAO,KAAK,EAAE;AACd,gBAAA,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,KAAK,CAAC;YAC3C;QACF;AACA,QAAA,MAAM,OAAO,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;AAC9D,QAAA,MAAM,QAAQ,GAAG,CAAA,UAAA,EAAa,OAAO,OAAO;QAC5C,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC;AACtF,QAAA,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC;QACtB,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAC3D;AAEA;;;;AAIG;IACH,MAAM,MAAM,CAAC,IAAmB,EAAA;QAC9B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE;YAC9B;QACF;QACA,MAAM,SAAS,GAAqB,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE;QAC9D,MAAM,mBAAmB,GAAa,EAAE;AAExC,QAAA,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE;AAC5D,YAAA,IAAI;AACF,gBAAA,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC;gBAEhF,IAAI,UAAU,IAAI,OAAO,UAAU,CAAC,IAAI,CAAC,MAAM,KAAK,UAAU,EAAE;AAC9D,oBAAA,MAAM,UAAU,GAAmB,UAAU,CAAC,IAAI;oBAClD,MAAM,cAAc,GAAG,UAAU,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ;AAC3D,oBAAA,MAAM,qBAAqB,CAAC,cAAc,EAAE,YAAW;wBACrD,MAAM,cAAc,GAAG,MAAM,UAAU,CAAC,MAAM,CAC5C,KAAK,CAAC,MAAM,EACZ,IAAI,CAAC,sBAAsB,CAAC,OAAO,EACnC,EAAE,cAAc,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAC5C;wBACD,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,MAAM,GAAG,cAAc;AAChD,oBAAA,CAAC,CAAC;gBACJ;qBAAO;AACL,oBAAA,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;gBACvC;YACF;YAAE,OAAO,KAAK,EAAE;gBACd,OAAO,CAAC,KAAK,CAAC,CAAA,+BAAA,EAAkC,EAAE,CAAA,CAAA,CAAG,EAAE,KAAK,CAAC;YAC/D;QACF;QACA,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE;AAC7C,YAAA,SAAS,CAAC,QAAQ,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,SAAS,CAAC,QAAQ,EAAE,mBAAmB,CAAC;AAC3F,YAAA,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE;gBACvB;YACF;QACF;QAEA,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C;AAEQ,IAAA,MAAM,kBAAkB,CAC9B,OAEC,EACD,mBAA6B,EAAA;QAE7B,MAAM,aAAa,GAAG,IAAI,CAAC,8BAA8B,CAAC,OAAO,CAAC;QAClE,MAAM,YAAY,GAAG,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,OAAO;AAEhE,QAAA,IAAI;YACF,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,+BAA+B,EAAE;AAChE,gBAAA,KAAK,EAAE,UAAU;AACjB,gBAAA,eAAe,EAAE,YAAY;AAC7B,gBAAA,cAAc,EAAE,aAAa;AAC7B,gBAAA,mBAAmB,EAAE,IAAI;AACzB,gBAAA,QAAQ,EAAE,KAAK;AACf,gBAAA,YAAY,EAAE,EAAE,aAAa,EAAE,YAAY,EAAE,mBAAmB;aACjE,CAAC,CAAC,OAAO;AACV,YAAA,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM;YAEpC,OAAO,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC;QAC5C;QAAE,OAAO,CAAC,EAAE;;AAEV,YAAA,OAAO,IAAI;QACb;IACF;AAEQ,IAAA,8BAA8B,CAAC,OAA+B,EAAA;QACpE,MAAM,OAAO,GAAyB,EAAE;QAExC,MAAM,YAAY,GAAG,CAAC,GAAQ,EAAE,IAAA,GAAiB,EAAE,KAAU;AAC3D,YAAA,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;gBAAE;AAErC,YAAA,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;gBAC9C,MAAM,WAAW,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC;AAElC,gBAAA,IAAI,GAAG,KAAK,iBAAiB,EAAE;;oBAE7B,IAAI,SAAS,GAAkE,IAAI;oBACnF,IAAI,UAAU,GAAa,EAAE;;oBAG7B,IAAI,UAAU,GAAG,GAAG;AACpB,oBAAA,MAAM,iBAAiB,GAAG,CAAC,GAAG,IAAI,CAAC;AACnC,oBAAA,OAAO,UAAU,IAAI,CAAC,SAAS,EAAE;AAC/B,wBAAA,IAAI,UAAU,CAAC,QAAQ,EAAE;AACvB,4BAAA,SAAS,GAAG,UAAU,CAAC,QAAQ;AAC/B,4BAAA,UAAU,GAAG,CAAC,GAAG,iBAAiB,EAAE,UAAU,CAAC;4BAC/C;wBACF;AACA,wBAAA,IAAI,UAAU,CAAC,MAAM,EAAE;AACrB,4BAAA,SAAS,GAAG,UAAU,CAAC,MAAM;AAC7B,4BAAA,UAAU,GAAG,CAAC,GAAG,iBAAiB,EAAE,QAAQ,CAAC;4BAC7C;wBACF;;wBAEA,iBAAiB,CAAC,GAAG,EAAE;wBACvB,UAAU,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,iBAAiB,CAAC;oBAC/D;oBAEA,IAAI,SAAS,EAAE;wBACb,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;wBACzB,OAAO,CAAC,IAAI,CAAC;4BACX,QAAQ;AACR,4BAAA,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,KAAK;4BAC9B,SAAS,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS;AAChD,yBAAA,CAAC;oBACJ;gBACF;AAAO,qBAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;AACpC,oBAAA,YAAY,CAAC,KAAK,EAAE,WAAW,CAAC;gBAClC;YACF;AACF,QAAA,CAAC;QAED,YAAY,CAAC,OAAO,CAAC;AACrB,QAAA,OAAO,OAAO;IAChB;IAEQ,eAAe,CAAC,GAAQ,EAAE,IAAc,EAAA;QAC9C,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC;IAC3D;IAEQ,aAAa,CACnB,eAAuC,EACvC,mBAGE,EAAA;AAEF,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;;AAG1D,QAAA,mBAAmB,CAAC,OAAO,CAAC,GAAG,IAAG;YAChC,IAAI,GAAG,CAAC,SAAS,CAAC,KAAK,KAAK,SAAS,EAAE;AACrC,gBAAA,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAC3B;YACF;;YAGA,MAAM,GAAG,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACzE,YAAA,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;AACjE,YAAA,IAAI,GAAG,IAAI,OAAO,EAAE;gBAClB,GAAG,CAAC,OAAO,CAAC,GAAG,GAAG,CAAC,SAAS,CAAC,KAAK;AAClC,gBAAA,OAAO,GAAG,CAAC,OAAO,CAAC,EAAE,eAAe;YACtC;AACF,QAAA,CAAC,CAAC;AAEF,QAAA,OAAO,MAAM;IACf;+GAlMW,0BAA0B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;mHAA1B,0BAA0B,EAAA,CAAA,CAAA;;4FAA1B,0BAA0B,EAAA,UAAA,EAAA,CAAA;kBADtC;;;MCcY,4BAA4B,CAAA;AAdzC,IAAA,WAAA,GAAA;AAeE,QAAA,IAAA,CAAA,QAAQ,GAAG,OAAO,CAChB,+NAA+N,CAChO;QAID,IAAA,CAAA,WAAW,GAAG,EAAE;AAChB,QAAA,IAAA,CAAA,MAAM,GAAG,MAAM,CAAwB,EAAE,kDAAC;QAG1C,IAAA,CAAA,WAAW,GAAG,KAAK;QACnB,IAAA,CAAA,WAAW,GAAG,KAAK;AACnB,QAAA,IAAA,CAAA,aAAa,GAAqC;AAChD,YAAA,KAAK,EAAE;AACL,gBAAA,KAAK,EAAE;AACR;SACF;AAEO,QAAA,IAAA,CAAA,sBAAsB,GAAG,MAAM,CAAC,sBAAsB,CAAC;AACvD,QAAA,IAAA,CAAA,qBAAqB,GAAG,MAAM,CAAC,qBAAqB,CAAC;AACrD,QAAA,IAAA,CAAA,0BAA0B,GAAG,MAAM,CAAC,0BAA0B,CAAC;AAE/D,QAAA,IAAA,CAAA,WAAW,GAAG,IAAI,OAAO,EAAQ;AACjC,QAAA,IAAA,CAAA,QAAQ,GAAG,IAAI,OAAO,EAAQ;QAC9B,IAAA,CAAA,cAAc,GAAiB,IAAI;AA2G5C,IAAA;IAzGC,QAAQ,GAAA;QACN,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,SAAS;AAC9D,QAAA,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,cAAc,EAAE;AAExC,QAAA,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,MAAK;YAChF,IAAI,CAAC,YAAY,EAAE;YACnB,IAAI,CAAC,QAAQ,EAAE;AACjB,QAAA,CAAC,CAAC;IACJ;IAEA,WAAW,GAAA;AACT,QAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE;AACpB,QAAA,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE;IAC1B;AAEA,IAAA,mBAAmB,CAAC,KAAa,EAAA;AAC/B,QAAA,IAAI,CAAC,WAAW,GAAG,KAAK;AACxB,QAAA,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE;IACzB;AAEA,IAAA,MAAM,YAAY,GAAA;AAChB,QAAA,IAAI,CAAC,cAAc,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC;AACrF,QAAA,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,qBAAqB,CAAC;AAC5E,YAAA,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,IAAI,CAAC,cAAc;AAC5B,YAAA,mBAAmB,EAAE,KAAK;AAC1B,YAAA,aAAa,EAAE;AAChB,SAAA,CAAC;QACF,IAAI,CAAC,QAAQ,EAAE;IACjB;AAEA,IAAA,MAAM,QAAQ,GAAA;AACZ,QAAA,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC/E,QAAA,IAAI;AACF,YAAA,MAAM,gBAAgB,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,iBAAiB,CACzE,IAAI,CAAC,WAAW,EAChB,IAAI,CAAC,cAAc,CACpB;AACD,YAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC;QACnC;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,KAAK,CAAC;AACzC,YAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;AACd,gBAAA;AACE,oBAAA,OAAO,EAAE,qCAAqC;AAC9C,oBAAA,IAAI,EAAE;AACP;AACF,aAAA,CAAC;QACJ;IACF;IAEA,YAAY,GAAA;AACV,QAAA,IAAI;YACF,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC;YACjD,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,SAAS,GAAG,YAAY;YAC5D,IAAI,CAAC,sBAAsB,CAAC,mBAAmB,CAAC,UAAU,CAAC,YAAY,CAAC;YACxE,IAAI,CAAC,sBAAsB,CAAC,sBAAsB,CAAC,UAAU,CAAC,YAAY,CAAC;YAC3E,IAAI,CAAC,sBAAsB,CAAC,WAAW,CAAC,UAAU,CAAC,YAAY,CAAC;AAChE,YAAA,IAAI,CAAC,sBAAsB,CAAC,gBAAgB,CAAC;gBAC3C,OAAO,EAAE,YAAY,CAAC,OAAO;gBAC7B,aAAa,EAAE,YAAY,CAAC;AAC7B,aAAA,CAAC;AACF,YAAA,IAAI,CAAC,sBAAsB,CAAC,oBAAoB,CAAC,WAAW,EAAE;AAC9D,YAAA,IAAI,CAAC,sBAAsB,CAAC,kBAAkB,GAAG,KAAK;QACxD;QAAE,OAAO,KAAK,EAAE;;AAEd,YAAA,IAAI,CAAC,sBAAsB,CAAC,kBAAkB,GAAG,IAAI;QACvD;IACF;AAEA,IAAA,MAAM,MAAM,GAAA;AACV,QAAA,IAAI,CAAC,WAAW,GAAG,IAAI;AACvB,QAAA,IAAI;YACF,MAAM,IAAI,CAAC,0BAA0B,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;QAC9D;gBAAU;AACR,YAAA,IAAI,CAAC,WAAW,GAAG,KAAK;QAC1B;IACF;IAEA,MAAM,MAAM,CAAC,IAAmB,EAAA;AAC9B,QAAA,IAAI,CAAC,WAAW,GAAG,IAAI;AACvB,QAAA,IAAI;YACF,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE;gBAC7B,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,0BAA0B,CAAC,MAAM,CAAC,IAAI,CAAC;gBACxE,IAAI,aAAa,EAAE;AACjB,oBAAA,IAAI,CAAC,WAAW,GAAG,aAAa;AAChC,oBAAA,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE;gBACzB;YACF;QACF;gBAAU;AACR,YAAA,IAAI,CAAC,WAAW,GAAG,KAAK;QAC1B;IACF;IAEQ,cAAc,GAAA;AACpB,QAAA,MAAM,gBAAgB,GACpB,IAAI,CAAC,sBAAsB,CAAC,sBAAsB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,KAAK;AAEzE,QAAA,IAAI,gBAAgB,CAAC,sBAAsB,CAAC,EAAE;AAC5C,YAAA,OAAO,MAAM;QACf;AAAO,aAAA,IAAI,gBAAgB,CAAC,uBAAuB,CAAC,EAAE;AACpD,YAAA,OAAO,OAAO;QAChB;AACA,QAAA,OAAO,IAAI;IACb;+GAnIW,4BAA4B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;mGAA5B,4BAA4B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,2BAAA,EAAA,SAAA,EAF5B,CAAC,qBAAqB,EAAE,0BAA0B,CAAC,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,iBAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAMnD,eAAe,EAAA,WAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECnC5B,i3FAyFA,2CDnEI,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,qBAAA,EAAA,QAAA,EAAA,6BAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,OAAA,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,OAAA,EAAA,QAAA,EAAA,kBAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,cAAA,EAAA,eAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,IAAA,EAAA,QAAA,EAAA,QAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,UAAA,EAAA,UAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,OAAA,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,gBAAA,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,QAAA,EAAA,UAAA,EAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EACZ,WAAW,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,IAAA,CAAA,OAAA,EAAA,QAAA,EAAA,qDAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,gBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EACX,mBAAmB,8BACnB,UAAU,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,iBAAA,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,OAAA,EAAA,SAAA,EAAA,MAAA,EAAA,gBAAA,EAAA,eAAA,EAAA,YAAA,EAAA,aAAA,EAAA,SAAA,EAAA,UAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,wBAAA,EAAA,QAAA,CAAA,EAAA,OAAA,EAAA,CAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EACV,aAAa,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAC,IAAA,CAAA,gBAAA,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,kBAAA,EAAA,mBAAA,EAAA,SAAA,EAAA,gBAAA,EAAA,cAAA,EAAA,WAAA,EAAA,cAAA,EAAA,UAAA,EAAA,WAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,CAAA,SAAA,EAAA,UAAA,CAAA,EAAA,QAAA,EAAA,CAAA,YAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACb,eAAe,EAAA,QAAA,EAAA,YAAA,EAAA,MAAA,EAAA,CAAA,eAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,CAAA,YAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,MAAA,EAAA,IAAA,EAAA,EAAA,CAAA,gBAAA,EAAA,IAAA,EAAA,WAAA,EAAA,CAAA,EAAA,CAAA,CAAA;;4FAIN,4BAA4B,EAAA,UAAA,EAAA,CAAA;kBAdxC,SAAS;+BACE,2BAA2B,EAAA,UAAA,EAEzB,IAAI,EAAA,OAAA,EACP;wBACP,YAAY;wBACZ,WAAW;wBACX,mBAAmB;wBACnB,UAAU;wBACV,aAAa;wBACb;AACD,qBAAA,EAAA,SAAA,EACU,CAAC,qBAAqB,EAAE,0BAA0B,CAAC,EAAA,QAAA,EAAA,i3FAAA,EAAA;;sBAM7D,SAAS;uBAAC,eAAe;;;ME1Bf,oCAAoC,CAAA;+GAApC,oCAAoC,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;mGAApC,oCAAoC,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,oCAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAJrC,CAAA,uDAAA,CAAyD,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAEzD,4BAA4B,EAAA,QAAA,EAAA,2BAAA,EAAA,CAAA,EAAA,CAAA,CAAA;;4FAE3B,oCAAoC,EAAA,UAAA,EAAA,CAAA;kBANhD,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,oCAAoC;AAC9C,oBAAA,QAAQ,EAAE,CAAA,uDAAA,CAAyD;AACnE,oBAAA,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,4BAA4B;AACvC,iBAAA;;;;;"}
@@ -64,7 +64,7 @@ class DashboardDetailsAdvancedTabModule {
64
64
  hookRoute([
65
65
  {
66
66
  path: TAB_ID,
67
- loadComponent: () => import('./c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-DFytXNdc.mjs').then(m => m.DashboardDetailsAdvancedTabComponent),
67
+ loadComponent: () => import('./c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-C8QX6xlf.mjs').then(m => m.DashboardDetailsAdvancedTabComponent),
68
68
  outlet: DASHBOARD_DETAILS_OUTLET,
69
69
  context: ViewContext.Dashboard,
70
70
  canActivate: [AdvancedTabRouteGuard]
@@ -86,7 +86,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
86
86
  hookRoute([
87
87
  {
88
88
  path: TAB_ID,
89
- loadComponent: () => import('./c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-DFytXNdc.mjs').then(m => m.DashboardDetailsAdvancedTabComponent),
89
+ loadComponent: () => import('./c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-C8QX6xlf.mjs').then(m => m.DashboardDetailsAdvancedTabComponent),
90
90
  outlet: DASHBOARD_DETAILS_OUTLET,
91
91
  context: ViewContext.Dashboard,
92
92
  canActivate: [AdvancedTabRouteGuard]