This commit is contained in:
2025-06-29 23:43:17 +00:00
parent bcddd4dbee
commit a20d46f561

View File

@@ -51,6 +51,12 @@ export class UplStatuspageIncidents extends DeesElement {
})
public daysToShow = 90;
@property({
type: Object,
state: true,
})
private expandedIncidents: Set<string> = new Set();
constructor() {
super();
}
@@ -91,12 +97,10 @@ export class UplStatuspageIncidents extends DeesElement {
box-shadow: ${unsafeCSS(shadows.sm)};
border: 1px solid ${colors.border.default};
transition: all 0.2s ease;
cursor: pointer;
}
.incident-card:hover {
.incident-card.expanded {
box-shadow: ${unsafeCSS(shadows.md)};
transform: translateY(-2px);
}
.incident-header {
@@ -106,6 +110,12 @@ export class UplStatuspageIncidents extends DeesElement {
align-items: start;
justify-content: space-between;
gap: ${unsafeCSS(spacing.md)};
cursor: pointer;
transition: background-color 0.2s ease;
}
.incident-header:hover {
background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.02)', 'rgba(255, 255, 255, 0.02)')};
}
.incident-header.critical {
@@ -303,15 +313,21 @@ export class UplStatuspageIncidents extends DeesElement {
transform: translateY(0);
}
.collapsed-hint {
font-size: 12px;
color: ${colors.text.secondary};
text-align: center;
margin-top: ${unsafeCSS(spacing.md)};
opacity: 0.8;
}
@media (max-width: 640px) {
.container {
padding: 0 ${unsafeCSS(spacing.md)} ${unsafeCSS(spacing.md)} ${unsafeCSS(spacing.md)};
}
.incident-header {
flex-direction: column;
align-items: start;
gap: ${unsafeCSS(spacing.sm)};
padding: ${unsafeCSS(spacing.md)};
}
.incident-meta {
@@ -328,8 +344,9 @@ export class UplStatuspageIncidents extends DeesElement {
<uplinternal-miniheading>Current Incidents</uplinternal-miniheading>
${this.loading ? html`
<div class="loading-skeleton"></div>
` : this.currentIncidents.length ?
this.currentIncidents.map(incident => this.renderIncident(incident, true)) :
` : this.currentIncidents.length ? html`
${this.currentIncidents.map(incident => this.renderIncident(incident, true))}
` :
html`<div class="noIncidentBox">No incidents ongoing.</div>`
}
@@ -360,8 +377,8 @@ export class UplStatuspageIncidents extends DeesElement {
this.formatDuration(Date.now() - incident.startTime);
return html`
<div class="incident-card" @click=${() => this.handleIncidentClick(incident)}>
<div class="incident-header ${incident.severity}">
<div class="incident-card ${this.expandedIncidents.has(incident.id) ? 'expanded' : ''}">
<div class="incident-header ${incident.severity}" @click=${() => this.toggleIncident(incident.id)}>
<div>
<h3 class="incident-title">${incident.title}</h3>
<div class="incident-meta">
@@ -371,13 +388,56 @@ export class UplStatuspageIncidents extends DeesElement {
<span>Ended: ${this.formatDate(incident.endTime)}</span>
` : ''}
</div>
${!this.expandedIncidents.has(incident.id) ? html`
<div style="
margin-top: ${unsafeCSS(spacing.sm)};
font-size: 13px;
color: ${colors.text.secondary};
display: flex;
align-items: center;
gap: ${unsafeCSS(spacing.md)};
">
${incident.impact ? html`
<span style="
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 500px;
">${incident.impact}</span>
` : ''}
<span style="
font-size: 12px;
color: ${cssManager.bdTheme('#9ca3af', '#71717a')};
">
${incident.updates.length} update${incident.updates.length !== 1 ? 's' : ''}
</span>
</div>
` : ''}
</div>
<div class="incident-status ${latestUpdate.status}">
${this.getStatusIcon(latestUpdate.status)}
${latestUpdate.status.replace(/_/g, ' ')}
<div style="display: flex; align-items: center; gap: ${unsafeCSS(spacing.md)};">
<div class="incident-status ${latestUpdate.status}">
${this.getStatusIcon(latestUpdate.status)}
${latestUpdate.status.replace(/_/g, ' ')}
</div>
<div class="expand-icon" style="
font-size: 10px;
color: ${cssManager.bdTheme('#6b7280', '#a1a1aa')};
transition: transform 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
border-radius: 4px;
background: ${cssManager.bdTheme('#f3f4f6', '#27272a')};
${this.expandedIncidents.has(incident.id) ? 'transform: rotate(180deg);' : ''}
">
</div>
</div>
</div>
${this.expandedIncidents.has(incident.id) ? html`
<div class="incident-body">
<div class="incident-impact">
<strong>Impact:</strong> ${incident.impact}
@@ -411,6 +471,7 @@ export class UplStatuspageIncidents extends DeesElement {
</div>
` : ''}
</div>
` : ''}
</div>
`;
}
@@ -427,15 +488,18 @@ export class UplStatuspageIncidents extends DeesElement {
`;
}
private getStatusIcon(status: string): string {
const icons: Record<string, string> = {
investigating: '🔍',
identified: '🎯',
monitoring: '👁️',
resolved: '✅',
postmortem: '📋'
};
return icons[status] || '•';
private getStatusIcon(status: string): TemplateResult {
return html`<span style="
display: inline-block;
width: 6px;
height: 6px;
border-radius: 50%;
margin-right: 4px;
background: ${status === 'resolved' ? colors.status.operational :
status === 'monitoring' ? colors.status.maintenance :
status === 'identified' ? colors.status.degraded :
colors.status.partial};
"></span>`;
}
private formatDate(timestamp: number): string {
@@ -483,6 +547,16 @@ export class UplStatuspageIncidents extends DeesElement {
}
}
private toggleIncident(incidentId: string) {
const newExpanded = new Set(this.expandedIncidents);
if (newExpanded.has(incidentId)) {
newExpanded.delete(incidentId);
} else {
newExpanded.add(incidentId);
}
this.expandedIncidents = newExpanded;
}
private handleIncidentClick(incident: IIncidentDetails) {
this.dispatchEvent(new CustomEvent('incidentClick', {
detail: { incident },