update
This commit is contained in:
105
test-footer-subscribe.html
Normal file
105
test-footer-subscribe.html
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Footer Subscribe Button Test</title>
|
||||||
|
<script type="module" src="./dist_bundle/bundle.js"></script>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-family: 'Geist Sans', -apple-system, BlinkMacSystemFont, sans-serif;
|
||||||
|
background: #fafafa;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
body {
|
||||||
|
background: #09090b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
main {
|
||||||
|
flex: 1;
|
||||||
|
padding: 40px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
color: #0a0a0a;
|
||||||
|
}
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
h1 {
|
||||||
|
color: #fafafa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.demo-section {
|
||||||
|
margin-top: auto;
|
||||||
|
}
|
||||||
|
.comparison {
|
||||||
|
display: flex;
|
||||||
|
gap: 40px;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 40px 0;
|
||||||
|
}
|
||||||
|
.example {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.example h3 {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.example h3 {
|
||||||
|
color: #a1a1aa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main>
|
||||||
|
<h1>Footer Subscribe Button - Fixed Layout</h1>
|
||||||
|
<p>The subscriber count is now displayed below the button instead of inside it:</p>
|
||||||
|
|
||||||
|
<div class="comparison">
|
||||||
|
<div class="example">
|
||||||
|
<h3>Without Subscribers</h3>
|
||||||
|
<p>Button appears alone when subscriber count is 0</p>
|
||||||
|
</div>
|
||||||
|
<div class="example">
|
||||||
|
<h3>With Subscribers</h3>
|
||||||
|
<p>Count appears below the button as secondary text</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<div class="demo-section">
|
||||||
|
<upl-statuspage-footer
|
||||||
|
id="footer1"
|
||||||
|
company-name="Example Corp"
|
||||||
|
enable-subscribe="true"
|
||||||
|
subscriber-count="1234"
|
||||||
|
></upl-statuspage-footer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
const footer = document.getElementById('footer1');
|
||||||
|
|
||||||
|
footer.addEventListener('subscribeClick', () => {
|
||||||
|
alert('Subscribe button clicked! The subscriber count is displayed separately below the button.');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Demonstrate different subscriber counts
|
||||||
|
let counts = [0, 42, 1234, 50000];
|
||||||
|
let currentIndex = 0;
|
||||||
|
|
||||||
|
setInterval(() => {
|
||||||
|
currentIndex = (currentIndex + 1) % counts.length;
|
||||||
|
footer.subscriberCount = counts[currentIndex];
|
||||||
|
}, 3000);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
286
test-incident-subscriptions.html
Normal file
286
test-incident-subscriptions.html
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Incident Subscription Test</title>
|
||||||
|
<script type="module" src="./dist_bundle/bundle.js"></script>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
font-family: 'Geist Sans', -apple-system, BlinkMacSystemFont, sans-serif;
|
||||||
|
background: #fafafa;
|
||||||
|
}
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
body {
|
||||||
|
background: #09090b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
color: #0a0a0a;
|
||||||
|
}
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
h1 {
|
||||||
|
color: #fafafa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.info-panel {
|
||||||
|
background: #f0f9ff;
|
||||||
|
border: 1px solid #bae6fd;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.info-panel {
|
||||||
|
background: #0c4a6e;
|
||||||
|
border-color: #0284c7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.subscription-log {
|
||||||
|
background: #f3f4f6;
|
||||||
|
border: 1px solid #e5e7eb;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 20px;
|
||||||
|
margin-top: 30px;
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 13px;
|
||||||
|
max-height: 200px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.subscription-log {
|
||||||
|
background: #1f2937;
|
||||||
|
border-color: #374151;
|
||||||
|
color: #e5e7eb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.notification {
|
||||||
|
position: fixed;
|
||||||
|
top: 20px;
|
||||||
|
right: 20px;
|
||||||
|
padding: 16px 24px;
|
||||||
|
background: #10b981;
|
||||||
|
color: white;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
animation: slideIn 0.3s ease;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
@keyframes slideIn {
|
||||||
|
from {
|
||||||
|
transform: translateX(100%);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: translateX(0);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.notification.unsubscribe {
|
||||||
|
background: #6b7280;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>Incident Subscription Feature Demo</h1>
|
||||||
|
|
||||||
|
<div class="info-panel">
|
||||||
|
<h3>How Incident Subscriptions Work:</h3>
|
||||||
|
<ul>
|
||||||
|
<li>Each incident can be individually subscribed to</li>
|
||||||
|
<li>Click on an incident to expand it and see the "Subscribe to updates" button</li>
|
||||||
|
<li>Subscribed incidents show a checkmark and "Subscribed to updates" text</li>
|
||||||
|
<li>Click again to unsubscribe</li>
|
||||||
|
<li>The component emits events for subscribe/unsubscribe actions</li>
|
||||||
|
<li>You can pre-set subscribed incidents using the <code>subscribedIncidentIds</code> property</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<upl-statuspage-incidents id="incidents"></upl-statuspage-incidents>
|
||||||
|
|
||||||
|
<div class="subscription-log" id="log">
|
||||||
|
<strong>Event Log:</strong><br>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
const incidents = document.getElementById('incidents');
|
||||||
|
const log = document.getElementById('log');
|
||||||
|
|
||||||
|
// Helper function to add log entries
|
||||||
|
function addLog(message) {
|
||||||
|
const timestamp = new Date().toLocaleTimeString();
|
||||||
|
log.innerHTML += `[${timestamp}] ${message}<br>`;
|
||||||
|
log.scrollTop = log.scrollHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to show notifications
|
||||||
|
function showNotification(message, type = 'subscribe') {
|
||||||
|
const notification = document.createElement('div');
|
||||||
|
notification.className = `notification ${type === 'unsubscribe' ? 'unsubscribe' : ''}`;
|
||||||
|
notification.textContent = message;
|
||||||
|
document.body.appendChild(notification);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
notification.style.opacity = '0';
|
||||||
|
notification.style.transform = 'translateX(100%)';
|
||||||
|
setTimeout(() => notification.remove(), 300);
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up some test incidents
|
||||||
|
const currentIncidents = [
|
||||||
|
{
|
||||||
|
id: 'inc-001',
|
||||||
|
title: 'Database Connection Pool Exhaustion',
|
||||||
|
status: 'monitoring',
|
||||||
|
severity: 'major',
|
||||||
|
affectedServices: ['API Gateway', 'User Service', 'Order Service'],
|
||||||
|
startTime: Date.now() - 2 * 60 * 60 * 1000,
|
||||||
|
impact: 'API response times are elevated. Some requests may timeout.',
|
||||||
|
updates: [
|
||||||
|
{
|
||||||
|
id: 'upd-1',
|
||||||
|
timestamp: Date.now() - 2 * 60 * 60 * 1000,
|
||||||
|
status: 'investigating',
|
||||||
|
message: 'We are investigating reports of slow API responses',
|
||||||
|
author: 'Operations Team'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'upd-2',
|
||||||
|
timestamp: Date.now() - 90 * 60 * 1000,
|
||||||
|
status: 'identified',
|
||||||
|
message: 'Database connection pool is at capacity due to increased traffic',
|
||||||
|
author: 'Database Team'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'upd-3',
|
||||||
|
timestamp: Date.now() - 30 * 60 * 1000,
|
||||||
|
status: 'monitoring',
|
||||||
|
message: 'Connection pool size has been increased. Monitoring for stability.',
|
||||||
|
author: 'Operations Team'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'inc-002',
|
||||||
|
title: 'CDN Configuration Update',
|
||||||
|
status: 'identified',
|
||||||
|
severity: 'minor',
|
||||||
|
affectedServices: ['CDN', 'Static Assets'],
|
||||||
|
startTime: Date.now() - 45 * 60 * 1000,
|
||||||
|
impact: 'Some static assets may load slowly in certain regions',
|
||||||
|
updates: [
|
||||||
|
{
|
||||||
|
id: 'upd-4',
|
||||||
|
timestamp: Date.now() - 45 * 60 * 1000,
|
||||||
|
status: 'investigating',
|
||||||
|
message: 'Investigating reports of slow asset loading',
|
||||||
|
author: 'Network Team'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'upd-5',
|
||||||
|
timestamp: Date.now() - 20 * 60 * 1000,
|
||||||
|
status: 'identified',
|
||||||
|
message: 'CDN configuration needs optimization for new edge locations',
|
||||||
|
author: 'Network Team'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const pastIncidents = [
|
||||||
|
{
|
||||||
|
id: 'inc-003',
|
||||||
|
title: 'Authentication Service Outage',
|
||||||
|
status: 'resolved',
|
||||||
|
severity: 'critical',
|
||||||
|
affectedServices: ['Authentication', 'All Services'],
|
||||||
|
startTime: Date.now() - 7 * 24 * 60 * 60 * 1000,
|
||||||
|
endTime: Date.now() - 7 * 24 * 60 * 60 * 1000 + 2 * 60 * 60 * 1000,
|
||||||
|
impact: 'Users were unable to log in',
|
||||||
|
rootCause: 'Certificate expiration in auth service',
|
||||||
|
resolution: 'Certificate renewed and monitoring alerts added',
|
||||||
|
updates: [
|
||||||
|
{
|
||||||
|
id: 'upd-6',
|
||||||
|
timestamp: Date.now() - 7 * 24 * 60 * 60 * 1000,
|
||||||
|
status: 'investigating',
|
||||||
|
message: 'Multiple reports of login failures',
|
||||||
|
author: 'On-call Engineer'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'upd-7',
|
||||||
|
timestamp: Date.now() - 7 * 24 * 60 * 60 * 1000 + 30 * 60 * 1000,
|
||||||
|
status: 'identified',
|
||||||
|
message: 'SSL certificate has expired',
|
||||||
|
author: 'Security Team'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'upd-8',
|
||||||
|
timestamp: Date.now() - 7 * 24 * 60 * 60 * 1000 + 2 * 60 * 60 * 1000,
|
||||||
|
status: 'resolved',
|
||||||
|
message: 'Certificate renewed and service restored',
|
||||||
|
author: 'Security Team'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// Set the incidents
|
||||||
|
incidents.currentIncidents = currentIncidents;
|
||||||
|
incidents.pastIncidents = pastIncidents;
|
||||||
|
|
||||||
|
// Pre-subscribe to the first incident
|
||||||
|
incidents.subscribedIncidentIds = ['inc-001'];
|
||||||
|
addLog('Pre-subscribed to incident: "Database Connection Pool Exhaustion"');
|
||||||
|
|
||||||
|
// Handle subscription events
|
||||||
|
incidents.addEventListener('incidentSubscribe', (event) => {
|
||||||
|
const { incidentId, incidentTitle, affectedServices } = event.detail;
|
||||||
|
addLog(`SUBSCRIBED to incident: "${incidentTitle}" (ID: ${incidentId})`);
|
||||||
|
addLog(` Affected services: ${affectedServices.join(', ')}`);
|
||||||
|
showNotification(`✓ Subscribed to: ${incidentTitle}`, 'subscribe');
|
||||||
|
|
||||||
|
// In a real application, you would send this to your backend
|
||||||
|
console.log('Subscribe API call would be made here:', {
|
||||||
|
incidentId,
|
||||||
|
userEmail: 'user@example.com',
|
||||||
|
notificationPreferences: ['email', 'sms']
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
incidents.addEventListener('incidentUnsubscribe', (event) => {
|
||||||
|
const { incident } = event.detail;
|
||||||
|
addLog(`UNSUBSCRIBED from incident: "${incident.title}" (ID: ${incident.id})`);
|
||||||
|
showNotification(`Unsubscribed from: ${incident.title}`, 'unsubscribe');
|
||||||
|
|
||||||
|
// In a real application, you would send this to your backend
|
||||||
|
console.log('Unsubscribe API call would be made here:', {
|
||||||
|
incidentId: incident.id,
|
||||||
|
userEmail: 'user@example.com'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Simulate receiving a new update for a subscribed incident
|
||||||
|
setTimeout(() => {
|
||||||
|
if (incidents.subscribedIncidents && incidents.subscribedIncidents.has('inc-001')) {
|
||||||
|
addLog('📬 NEW UPDATE for subscribed incident "Database Connection Pool Exhaustion"');
|
||||||
|
showNotification('New update: Connection pool stable, incident will be resolved soon');
|
||||||
|
}
|
||||||
|
}, 5000);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -298,10 +298,16 @@ export class UplStatuspageFooter extends DeesElement {
|
|||||||
border-color: ${colors.border.muted};
|
border-color: ${colors.border.muted};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.subscribe-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: ${unsafeCSS(spacing.xs)};
|
||||||
|
}
|
||||||
|
|
||||||
.subscriber-count {
|
.subscriber-count {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: ${colors.text.muted};
|
color: ${cssManager.bdTheme('#6b7280', '#a1a1aa')};
|
||||||
margin-top: ${unsafeCSS(spacing.xs)};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.error-message {
|
.error-message {
|
||||||
@@ -468,12 +474,14 @@ export class UplStatuspageFooter extends DeesElement {
|
|||||||
|
|
||||||
<div class="footer-actions">
|
<div class="footer-actions">
|
||||||
${this.enableSubscribe ? html`
|
${this.enableSubscribe ? html`
|
||||||
|
<div class="subscribe-wrapper">
|
||||||
<button class="action-button" @click=${this.handleSubscribeClick}>
|
<button class="action-button" @click=${this.handleSubscribeClick}>
|
||||||
Subscribe to Updates
|
Subscribe to Updates
|
||||||
|
</button>
|
||||||
${this.subscriberCount > 0 ? html`
|
${this.subscriberCount > 0 ? html`
|
||||||
<div class="subscriber-count">${this.subscriberCount.toLocaleString()} subscribers</div>
|
<div class="subscriber-count">${this.subscriberCount.toLocaleString()} subscribers</div>
|
||||||
` : ''}
|
` : ''}
|
||||||
</button>
|
</div>
|
||||||
` : ''}
|
` : ''}
|
||||||
|
|
||||||
${this.enableReportIssue ? html`
|
${this.enableReportIssue ? html`
|
||||||
|
|||||||
@@ -521,6 +521,17 @@ export const demoFunc = () => html`
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Handle incident subscriptions
|
||||||
|
incidents.addEventListener('incidentSubscribe', (event: CustomEvent) => {
|
||||||
|
console.log('Subscribed to incident:', event.detail);
|
||||||
|
logUpdate(`[SUBSCRIBED] User subscribed to incident "${event.detail.incidentTitle}"`);
|
||||||
|
});
|
||||||
|
|
||||||
|
incidents.addEventListener('incidentUnsubscribe', (event: CustomEvent) => {
|
||||||
|
console.log('Unsubscribed from incident:', event.detail);
|
||||||
|
logUpdate(`[UNSUBSCRIBED] User unsubscribed from incident "${event.detail.incident.title}"`);
|
||||||
|
});
|
||||||
|
|
||||||
// Add update log
|
// Add update log
|
||||||
const logDiv = document.createElement('div');
|
const logDiv = document.createElement('div');
|
||||||
logDiv.className = 'incident-log';
|
logDiv.className = 'incident-log';
|
||||||
@@ -1027,5 +1038,179 @@ export const demoFunc = () => html`
|
|||||||
<upl-statuspage-incidents></upl-statuspage-incidents>
|
<upl-statuspage-incidents></upl-statuspage-incidents>
|
||||||
</dees-demowrapper>
|
</dees-demowrapper>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Incident Subscription Demo -->
|
||||||
|
<div class="demo-section">
|
||||||
|
<div class="demo-title">Incident Subscription Management</div>
|
||||||
|
<dees-demowrapper
|
||||||
|
.runAfterRender=${async (wrapperElement: any) => {
|
||||||
|
const incidents = wrapperElement.querySelector('upl-statuspage-incidents') as any;
|
||||||
|
|
||||||
|
// Sample incidents with subscription
|
||||||
|
const currentIncidents: IIncidentDetails[] = [
|
||||||
|
{
|
||||||
|
id: 'sub-001',
|
||||||
|
title: 'Payment Gateway Intermittent Failures',
|
||||||
|
status: 'monitoring',
|
||||||
|
severity: 'major',
|
||||||
|
affectedServices: ['payment-gateway', 'checkout'],
|
||||||
|
startTime: Date.now() - 2 * 60 * 60 * 1000,
|
||||||
|
impact: 'Some customers may experience payment failures during checkout',
|
||||||
|
updates: [
|
||||||
|
{
|
||||||
|
id: 'sub-u1',
|
||||||
|
timestamp: Date.now() - 2 * 60 * 60 * 1000,
|
||||||
|
status: 'investigating',
|
||||||
|
message: 'We are investigating reports of payment failures',
|
||||||
|
author: 'Payment Team'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'sub-u2',
|
||||||
|
timestamp: Date.now() - 1 * 60 * 60 * 1000,
|
||||||
|
status: 'identified',
|
||||||
|
message: 'Issue identified with payment processor API rate limits',
|
||||||
|
author: 'Payment Team'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'sub-u3',
|
||||||
|
timestamp: Date.now() - 30 * 60 * 1000,
|
||||||
|
status: 'monitoring',
|
||||||
|
message: 'Temporary fix applied, monitoring for stability',
|
||||||
|
author: 'Payment Team'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'sub-002',
|
||||||
|
title: 'Email Delivery Delays',
|
||||||
|
status: 'identified',
|
||||||
|
severity: 'minor',
|
||||||
|
affectedServices: ['email-service'],
|
||||||
|
startTime: Date.now() - 45 * 60 * 1000,
|
||||||
|
impact: 'Transactional emails may be delayed by 5-10 minutes',
|
||||||
|
updates: [
|
||||||
|
{
|
||||||
|
id: 'sub-u4',
|
||||||
|
timestamp: Date.now() - 45 * 60 * 1000,
|
||||||
|
status: 'investigating',
|
||||||
|
message: 'Investigating email queue backlog',
|
||||||
|
author: 'Infrastructure Team'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'sub-u5',
|
||||||
|
timestamp: Date.now() - 20 * 60 * 1000,
|
||||||
|
status: 'identified',
|
||||||
|
message: 'High volume causing queue delays, scaling up workers',
|
||||||
|
author: 'Infrastructure Team'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
incidents.currentIncidents = currentIncidents;
|
||||||
|
incidents.pastIncidents = [];
|
||||||
|
|
||||||
|
// Pre-subscribe to first incident
|
||||||
|
incidents.subscribedIncidentIds = ['sub-001'];
|
||||||
|
|
||||||
|
// Create subscription status display
|
||||||
|
const statusDiv = document.createElement('div');
|
||||||
|
statusDiv.className = 'subscription-status';
|
||||||
|
statusDiv.style.cssText = `
|
||||||
|
margin-top: 16px;
|
||||||
|
padding: 16px;
|
||||||
|
background: #f0f9ff;
|
||||||
|
border: 1px solid #bae6fd;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 14px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const updateStatus = () => {
|
||||||
|
const subscribed = Array.from(incidents.subscribedIncidents || []);
|
||||||
|
statusDiv.innerHTML = `
|
||||||
|
<strong>Subscription Status:</strong><br>
|
||||||
|
${subscribed.length === 0 ?
|
||||||
|
'Not subscribed to any incidents' :
|
||||||
|
`Subscribed to ${subscribed.length} incident(s):<br>` +
|
||||||
|
subscribed.map(id => {
|
||||||
|
const incident = currentIncidents.find(i => i.id === id);
|
||||||
|
return incident ? `• ${incident.title}` : '';
|
||||||
|
}).filter(Boolean).join('<br>')}
|
||||||
|
`;
|
||||||
|
};
|
||||||
|
|
||||||
|
updateStatus();
|
||||||
|
wrapperElement.appendChild(statusDiv);
|
||||||
|
|
||||||
|
// Handle subscription events
|
||||||
|
incidents.addEventListener('incidentSubscribe', (event: CustomEvent) => {
|
||||||
|
console.log('Subscribed:', event.detail);
|
||||||
|
updateStatus();
|
||||||
|
|
||||||
|
// Show notification
|
||||||
|
const notification = document.createElement('div');
|
||||||
|
notification.style.cssText = `
|
||||||
|
position: fixed;
|
||||||
|
top: 20px;
|
||||||
|
right: 20px;
|
||||||
|
padding: 16px;
|
||||||
|
background: #10b981;
|
||||||
|
color: white;
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
||||||
|
z-index: 1000;
|
||||||
|
animation: slideIn 0.3s ease;
|
||||||
|
`;
|
||||||
|
notification.textContent = `✓ Subscribed to: ${event.detail.incidentTitle}`;
|
||||||
|
document.body.appendChild(notification);
|
||||||
|
setTimeout(() => notification.remove(), 3000);
|
||||||
|
});
|
||||||
|
|
||||||
|
incidents.addEventListener('incidentUnsubscribe', (event: CustomEvent) => {
|
||||||
|
console.log('Unsubscribed:', event.detail);
|
||||||
|
updateStatus();
|
||||||
|
|
||||||
|
// Show notification
|
||||||
|
const notification = document.createElement('div');
|
||||||
|
notification.style.cssText = `
|
||||||
|
position: fixed;
|
||||||
|
top: 20px;
|
||||||
|
right: 20px;
|
||||||
|
padding: 16px;
|
||||||
|
background: #6b7280;
|
||||||
|
color: white;
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
||||||
|
z-index: 1000;
|
||||||
|
animation: slideIn 0.3s ease;
|
||||||
|
`;
|
||||||
|
notification.textContent = `Unsubscribed from: ${event.detail.incident.title}`;
|
||||||
|
document.body.appendChild(notification);
|
||||||
|
setTimeout(() => notification.remove(), 3000);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add info text
|
||||||
|
const infoDiv = document.createElement('div');
|
||||||
|
infoDiv.style.cssText = `
|
||||||
|
margin-top: 12px;
|
||||||
|
padding: 12px;
|
||||||
|
background: #f3f4f6;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #6b7280;
|
||||||
|
`;
|
||||||
|
infoDiv.innerHTML = `
|
||||||
|
<strong>How it works:</strong><br>
|
||||||
|
• Click on an incident to expand it<br>
|
||||||
|
• Click "Subscribe to updates" to get notifications<br>
|
||||||
|
• Subscribed incidents show a checkmark<br>
|
||||||
|
• Click again to unsubscribe
|
||||||
|
`;
|
||||||
|
wrapperElement.appendChild(infoDiv);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<upl-statuspage-incidents></upl-statuspage-incidents>
|
||||||
|
</dees-demowrapper>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
@@ -51,16 +51,42 @@ export class UplStatuspageIncidents extends DeesElement {
|
|||||||
})
|
})
|
||||||
public daysToShow = 90;
|
public daysToShow = 90;
|
||||||
|
|
||||||
|
@property({
|
||||||
|
type: Array,
|
||||||
|
})
|
||||||
|
public subscribedIncidentIds: string[] = [];
|
||||||
|
|
||||||
@property({
|
@property({
|
||||||
type: Object,
|
type: Object,
|
||||||
state: true,
|
state: true,
|
||||||
})
|
})
|
||||||
private expandedIncidents: Set<string> = new Set();
|
private expandedIncidents: Set<string> = new Set();
|
||||||
|
|
||||||
|
@property({
|
||||||
|
type: Object,
|
||||||
|
state: true,
|
||||||
|
})
|
||||||
|
private subscribedIncidents: Set<string> = new Set();
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async connectedCallback() {
|
||||||
|
await super.connectedCallback();
|
||||||
|
// Initialize subscribed incidents from the property
|
||||||
|
if (this.subscribedIncidentIds.length > 0) {
|
||||||
|
this.subscribedIncidents = new Set(this.subscribedIncidentIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updated(changedProperties: Map<string, any>) {
|
||||||
|
super.updated(changedProperties);
|
||||||
|
if (changedProperties.has('subscribedIncidentIds')) {
|
||||||
|
this.subscribedIncidents = new Set(this.subscribedIncidentIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
plugins.domtools.elementBasic.staticStyles,
|
plugins.domtools.elementBasic.staticStyles,
|
||||||
commonStyles,
|
commonStyles,
|
||||||
@@ -313,6 +339,46 @@ export class UplStatuspageIncidents extends DeesElement {
|
|||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.incident-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: ${unsafeCSS(spacing.md)};
|
||||||
|
align-items: center;
|
||||||
|
margin-top: ${unsafeCSS(spacing.lg)};
|
||||||
|
padding-top: ${unsafeCSS(spacing.lg)};
|
||||||
|
border-top: 1px solid ${colors.border.default};
|
||||||
|
}
|
||||||
|
|
||||||
|
.subscribe-button {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: ${unsafeCSS(spacing.xs)};
|
||||||
|
padding: ${unsafeCSS(spacing.xs)} ${unsafeCSS(spacing.md)};
|
||||||
|
background: transparent;
|
||||||
|
border: 1px solid ${colors.border.default};
|
||||||
|
border-radius: ${unsafeCSS(borderRadius.base)};
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 400;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
color: ${colors.text.primary};
|
||||||
|
font-family: ${unsafeCSS(fonts.base)};
|
||||||
|
}
|
||||||
|
|
||||||
|
.subscribe-button:hover {
|
||||||
|
background: ${colors.background.secondary};
|
||||||
|
border-color: ${colors.border.muted};
|
||||||
|
}
|
||||||
|
|
||||||
|
.subscribe-button.subscribed {
|
||||||
|
background: ${cssManager.bdTheme('#f0fdf4', '#064e3b')};
|
||||||
|
border-color: ${cssManager.bdTheme('#86efac', '#047857')};
|
||||||
|
color: ${cssManager.bdTheme('#047857', '#86efac')};
|
||||||
|
}
|
||||||
|
|
||||||
|
.subscribe-button.subscribed:hover {
|
||||||
|
background: ${cssManager.bdTheme('#dcfce7', '#065f46')};
|
||||||
|
}
|
||||||
|
|
||||||
.collapsed-hint {
|
.collapsed-hint {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: ${colors.text.secondary};
|
color: ${colors.text.secondary};
|
||||||
@@ -470,6 +536,35 @@ export class UplStatuspageIncidents extends DeesElement {
|
|||||||
<strong>Resolution:</strong> ${incident.resolution}
|
<strong>Resolution:</strong> ${incident.resolution}
|
||||||
</div>
|
</div>
|
||||||
` : ''}
|
` : ''}
|
||||||
|
|
||||||
|
<div class="incident-actions">
|
||||||
|
<button
|
||||||
|
class="subscribe-button ${this.isSubscribedToIncident(incident.id) ? 'subscribed' : ''}"
|
||||||
|
@click=${(e: Event) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
this.handleIncidentSubscribe(incident);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
${this.isSubscribedToIncident(incident.id) ? html`
|
||||||
|
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M11.6667 3.5L5.25 9.91667L2.33334 7" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
Subscribed to updates
|
||||||
|
` : html`
|
||||||
|
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M10.5 5.25V8.75C10.5 9.34674 10.2629 9.91903 9.84099 10.341C9.41903 10.7629 8.84674 11 8.25 11L3.75 11C3.15326 11 2.58097 10.7629 2.15901 10.341C1.73705 9.91903 1.5 9.34674 1.5 8.75V4.25C1.5 3.65326 1.73705 3.08097 2.15901 2.65901C2.58097 2.23705 3.15326 2 3.75 2H7.25" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M9 1.5H12.5M12.5 1.5V5M12.5 1.5L6 8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
Subscribe to updates
|
||||||
|
`}
|
||||||
|
</button>
|
||||||
|
${isCurrent ? html`
|
||||||
|
<span style="
|
||||||
|
font-size: 12px;
|
||||||
|
color: ${cssManager.bdTheme('#6b7280', '#a1a1aa')};
|
||||||
|
">Get notified when this incident is updated or resolved</span>
|
||||||
|
` : ''}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
` : ''}
|
` : ''}
|
||||||
</div>
|
</div>
|
||||||
@@ -570,6 +665,38 @@ export class UplStatuspageIncidents extends DeesElement {
|
|||||||
console.log('Show more incidents');
|
console.log('Show more incidents');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private isSubscribedToIncident(incidentId: string): boolean {
|
||||||
|
return this.subscribedIncidents.has(incidentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleIncidentSubscribe(incident: IIncidentDetails) {
|
||||||
|
const newSubscribed = new Set(this.subscribedIncidents);
|
||||||
|
if (newSubscribed.has(incident.id)) {
|
||||||
|
newSubscribed.delete(incident.id);
|
||||||
|
this.dispatchEvent(new CustomEvent('incidentUnsubscribe', {
|
||||||
|
detail: {
|
||||||
|
incident,
|
||||||
|
incidentId: incident.id
|
||||||
|
},
|
||||||
|
bubbles: true,
|
||||||
|
composed: true
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
newSubscribed.add(incident.id);
|
||||||
|
this.dispatchEvent(new CustomEvent('incidentSubscribe', {
|
||||||
|
detail: {
|
||||||
|
incident,
|
||||||
|
incidentId: incident.id,
|
||||||
|
incidentTitle: incident.title,
|
||||||
|
affectedServices: incident.affectedServices
|
||||||
|
},
|
||||||
|
bubbles: true,
|
||||||
|
composed: true
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
this.subscribedIncidents = newSubscribed;
|
||||||
|
}
|
||||||
|
|
||||||
public dispatchReportNewIncident() {
|
public dispatchReportNewIncident() {
|
||||||
this.dispatchEvent(new CustomEvent('reportNewIncident', {
|
this.dispatchEvent(new CustomEvent('reportNewIncident', {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user