import * as plugins from '../../../plugins.js'; import * as appstate from '../../../appstate.js'; import { viewHostCss } from '../../shared/index.js'; import { DeesElement, customElement, html, state, css, cssManager, type TemplateResult, } from '@design.estate/dees-element'; @customElement('gitops-view-buildlog') export class GitopsViewBuildlog extends DeesElement { @state() accessor connectionsState: appstate.IConnectionsState = { connections: [], activeConnectionId: null, }; @state() accessor dataState: appstate.IDataState = { projects: [], groups: [], secrets: [], pipelines: [], pipelineJobs: [], currentJobLog: '', }; @state() accessor selectedConnectionId: string = ''; @state() accessor selectedProjectId: string = ''; @state() accessor selectedJobId: string = ''; constructor() { super(); const connSub = appstate.connectionsStatePart .select((s) => s) .subscribe((s) => { this.connectionsState = s; }); this.rxSubscriptions.push(connSub); const dataSub = appstate.dataStatePart .select((s) => s) .subscribe((s) => { this.dataState = s; }); this.rxSubscriptions.push(dataSub); } public static styles = [ cssManager.defaultStyles, viewHostCss, css` .log-container { background: #0d0d0d; border: 1px solid #333; border-radius: 8px; padding: 16px; font-family: 'Fira Code', 'Courier New', monospace; font-size: 13px; line-height: 1.6; color: #ccc; max-height: 600px; overflow-y: auto; white-space: pre-wrap; word-break: break-all; } .log-empty { color: #666; text-align: center; padding: 40px; } .job-meta { display: flex; gap: 16px; margin-bottom: 16px; padding: 12px; background: #1a1a2e; border-radius: 8px; font-size: 14px; } .job-meta-item { color: #999; } .job-meta-item strong { color: #fff; } `, ]; public render(): TemplateResult { const connectionOptions = this.connectionsState.connections.map((c) => ({ option: `${c.name} (${c.providerType})`, key: c.id, })); const projectOptions = this.dataState.projects.map((p) => ({ option: p.fullPath || p.name, key: p.id, })); const jobOptions = this.dataState.pipelineJobs.map((j) => ({ option: `${j.name} (${j.status})`, key: j.id, })); return html`
Build Log
View raw build logs for CI/CD jobs
o.key === this.selectedConnectionId) || connectionOptions[0]} @selectedOption=${(e: CustomEvent) => { this.selectedConnectionId = e.detail.key; this.loadProjects(); }} > o.key === this.selectedProjectId) || projectOptions[0]} @selectedOption=${(e: CustomEvent) => { this.selectedProjectId = e.detail.key; }} > o.key === this.selectedJobId) || jobOptions[0]} @selectedOption=${(e: CustomEvent) => { this.selectedJobId = e.detail.key; }} > this.fetchLog()}>Fetch Log this.fetchLog()}>Refresh
${this.selectedJobId ? html`
Job: ${this.selectedJobId} Project: ${this.selectedProjectId}
` : ''}
${this.dataState.currentJobLog ? this.dataState.currentJobLog : html`
Select a connection, project, and job, then click "Fetch Log" to view build output.
` }
`; } async firstUpdated() { await appstate.connectionsStatePart.dispatchAction(appstate.fetchConnectionsAction, null); const conns = appstate.connectionsStatePart.getState().connections; if (conns.length > 0 && !this.selectedConnectionId) { this.selectedConnectionId = conns[0].id; await this.loadProjects(); } } private async loadProjects() { if (!this.selectedConnectionId) return; await appstate.dataStatePart.dispatchAction(appstate.fetchProjectsAction, { connectionId: this.selectedConnectionId, }); } private async fetchLog() { if (!this.selectedConnectionId || !this.selectedProjectId || !this.selectedJobId) return; await appstate.dataStatePart.dispatchAction(appstate.fetchJobLogAction, { connectionId: this.selectedConnectionId, projectId: this.selectedProjectId, jobId: this.selectedJobId, }); } }