import { customElement, query, state } from "lit/decorators.js"; import { ClientConsumer } from "../ClientConsumer"; import { ServerInfo } from "@labir/server"; import { css, CSSResultGroup, html, nothing } from "lit"; import { TimeFormat } from "@labir/core"; import { t } from "i18next"; import { T } from "../../../translations/Languages"; type HistoryItem = { timestamp: number; success: boolean; code: boolean; message: boolean; method: string; }; @customElement("server-info") export class ServerBar extends ClientConsumer { @state() protected history: HistoryItem[] = []; @state() protected logExpanded: boolean = false; connectedCallback(): void { super.connectedCallback(); this.client?.onResult.set(this.UUID, (timestamp, success, code, message, method) => { this.history.push({ timestamp, success, code, message, method }); this.requestUpdate(); }); } static styles?: CSSResultGroup | undefined = css` :host { display: flex; align-items: flex-start; gap: 0.5em; } .icon { font-size: 1em; width: 1em; height: 1em; } .spinner { width: 1em; height: 1em; display: inline-block; vertical-align: middle; animation: spin 1s linear infinite; color: var(--thermal-primary); } @keyframes spin { 100% { transform: rotate(360deg); } } .dialog-trigger { color: var( --thermal-primary ); cursor: pointer; &:hover, &:focus { text-decoration: underline; } } .history { flex-grow: 1; table { width: 100%; border-collapse: collapse; } td { padding: 0.1em 0.1em; box-sizing: border-box; vertical-align: center; &.time {width: 55px;} &.method, &.code { width: 40px; } &.success, &.error {width: 1em;} &.method, &.code, &.success, &.error { text-align: center; } i { display: inline-block; width: .5em; height: .5em; line-height: 0; border-radius: 50%; margin-bottom: 0.15em; } &.success i { background: var( --thermal-primary ); } &.error i { background: red; } } } .history.collapsed { .history-header { display: none; } transition: all .2s ease-in-out; cursor: pointer; &:hover { color: var( --thermal-foreground ); } } .history.expanded { border: 1px solid var( --thermal-slate ); border-radius: var( --thermal-radius ); overflow: hidden; .history-header { } .history-content { max-height: 150px; overflow-y: scroll; } } .history-header { display: flex; gap: 0.5em; align-items: center; justify-content: space-between; padding: 0.2em 0.5em; background: var( --thermal-slate-dark ); color: var( --thermal-background ); cursor: pointer; transition: all .3s ease-in-out; svg { transition: transform .3s ease-in-out; } &:hover, &:focus { color: var( --thermal-primary-light ); background: var( --thermal-foreground ); svg { transform: scale(1.2); } } h2 { padding: 0; margin: 0; font-size: calc( var( --thermal-fs ) * 0.7 ); text-transform: uppercase; letter-spacing: 0.05em; } } `; protected renderIcon(): unknown { // Pokud probíhá načítání, zobraz spinner if (this.isClientLoading) { // Spinner: oblouk 270°, 90° mezera return html` `; } let col = this.isClientConnecting ? "var(--thermal-primary)" : this.client?.isConnected() ? "var(--thermal-primary)" : "red"; return html` `; } protected renderLoading(): unknown { return html`
Connecting to server...
`; } protected renderServerDialog(info: ServerInfo): unknown { const name = info.name ?? info.url; return html` ${name}
${info.url} ${info.name ?? "-"} ${info.description ?? "-"}
`; } protected renderServerInfo(): unknown { if (this.isConnected === true && this.serverInfo) { return html`${this.renderServerDialog(this.serverInfo)} ${this.renderLog()}`; } else { return html`
Failed to connect to the remote server
`; } } protected renderLogItem( item: HistoryItem ): unknown { return html` ${TimeFormat.humanTime(item.timestamp, true)} ${item.success ? html` ` : html` `} ${item.method} ${item.code} ${item.message} `; } @query('.history-content') protected historyContent?: HTMLDivElement; updated(changedProps: Map) { super.updated?.(changedProps); if (this.logExpanded && this.historyContent) { this.historyContent.scrollTop = this.historyContent.scrollHeight; } } protected renderLog(): unknown { const items = this.logExpanded ? this.history : this.history.slice(this.history.length - 1); const stateClass = this.logExpanded ? "expanded" : "collapsed"; const tableCallback = this.logExpanded ? undefined : () => { this.logExpanded = true; } const closeCallback = (event: Event) => { event.stopPropagation(); this.logExpanded = false; this.requestUpdate(); } return html`

${t(T.networklog)}

${items.map(item => this.renderLogItem(item))}
`; } protected render(): unknown { const content = this.isClientConnecting ? this.renderLoading() : this.renderServerInfo(); return html` ${this.renderIcon()} ${content} ` } }