ai/ai-chat/ai-chat-message.component.ts
A container for content and actions that should be rendered for each chat message.
Project content into this component to display the message, for example add an <ai-chat-assistant-message>
for assistant messages, and a simple markdownToHtml | async rendering of the content for user messages.
| changeDetection | ChangeDetectionStrategy.OnPush |
| selector | c8y-ai-chat-message |
| standalone | true |
| imports |
TooltipModule
C8yTranslatePipe
|
| styleUrls | ./ai-chat-message.component.scss |
| templateUrl | ./ai-chat-message.component.html |
| styleUrl | ./ai-chat-message.component.scss |
<div
class="d-col p-t-16"
[attr.aria-label]="ariaLabel()"
role="article"
>
<div
class="chat-message text-break-word"
[ngClass]="{
'user-message': message()?.role === 'user' || role() === 'user',
'agent-message': message()?.role === 'assistant' || role() === 'assistant'
}"
>
<!-- Visually hidden label included when users copy-paste from the chat, e.g. to report issues -->
<span
class="hidden-copy-label"
aria-hidden="true"
>
{{ `====== ${messageContentAriaLabel()} ======` }}</span
>
<!-- Apply the class and aria-label to both the main content and whatever is projected, so we get the same styling by default -->
<div
class="message-content"
[attr.aria-label]="messageContentAriaLabel()"
>
<div style="display: contents">
<ng-content select=":not(c8y-ai-chat-message-action)"></ng-content>
</div>
</div>
@if (message()?.timestamp) {
<div class="message-timestamp">
<span [tooltip]="message()?.timestamp | c8yDate">
{{ message()?.timestamp | c8yDate: 'adaptiveDate' }}
</span>
</div>
}
</div>
<div
class="message-action"
[attr.aria-label]="'Message actions' | translate"
role="toolbar"
[ngClass]="{
'user-action showOnHover': message()?.role === 'user' || role() === 'user',
'agent-action p-l-16': message()?.role === 'assistant' || role() === 'assistant'
}"
>
<ng-content select="c8y-ai-chat-message-action"></ng-content>
</div>
</div>