import '@material/web/icon/icon.js' import '@material/web/fab/fab.js' import gql from 'graphql-tag' import { css, html, LitElement, nothing } from 'lit' import { customElement, property, query } from 'lit/decorators.js' import { subscribe } from '@operato/graphql' import { i18next } from '@operato/i18n' import { ScrollbarStyles } from '@operato/styles' @customElement('scenario-instance-log-view') export class ScenarioInstanceLogView extends LitElement { static styles = [ ScrollbarStyles, css` :host { display: flex; flex-direction: column; background-color: var(--md-sys-color-surface); padding: var(--spacing-large); } :host([active]) { padding: 0; } [content] { flex: 1; display: flex; flex-direction: column; overflow: auto; font-size: var(--fontsize-small); } div.error { color: #8b0000; } div.warn { color: #ff6b6b; } span { color: var(--md-sys-color-primary); } #start { position: absolute; bottom: 15px; right: 16px; text-decoration: auto; display: flex; flex-direction: column-reverse; gap: 10px; align-items: center; } #start [draft] { --md-fab-container-color: var(--md-sys-color-secondary-container); --md-fab-icon-color: var(--md-sys-color-on-secondary-container); } ` ] @property({ type: String }) scenarioName?: string @property({ type: String }) instanceName?: string @property({ type: Array }) logs: any @property({ type: Boolean }) startable: boolean = false subscription: any firstUpdated() { this.logs = [] this.startSubscribe() } disconnectedCallback() { super.disconnectedCallback() this.stopSubscribe() } render() { const logs = this.logs || [] return html`
${logs.map( ({ timestamp, message, level }) => html`
${new Date(timestamp).toLocaleString()} ${level} ${message}
` )}
${this.startable ? html`
this.dispatchEvent(new CustomEvent('start', { detail: { mode: 'released' } }))} > play_arrow this.dispatchEvent(new CustomEvent('start', { detail: { mode: 'draft' } }))} > bug_report
` : nothing} ` } async startSubscribe() { this.subscription = await subscribe( { query: gql` subscription ($instanceName: String, $scenarioName: String, $level: String) { log: scenarioInstanceLog(instanceName: $instanceName, scenarioName: $scenarioName, level: $level) { level message timestamp } } `, variables: { instanceName: this.instanceName, scenarioName: this.scenarioName } }, { next: async ({ data }) => { var wasBottom = this.scrollHeight - this.scrollTop === this.clientHeight this.logs.push(data.log) this.logs.length > 100 && this.logs.shift() this.requestUpdate() if (wasBottom) { /* this is not proved yet - to keep bottom scroll position */ await this.updateComplete this.scrollTop = this.scrollHeight - this.clientHeight } } } ) } async stopSubscribe() { await this.subscription?.unsubscribe() delete this.subscription } }