Files
catalog/ts_web/elements/upl-statuspage-footer.demo.ts
2025-06-29 19:55:58 +00:00

744 lines
29 KiB
TypeScript

import { html } from '@design.estate/dees-element';
import type { IStatusPageConfig } from '../interfaces/index.js';
export const demoFunc = () => html`
<style>
.demo-container {
display: flex;
flex-direction: column;
gap: 20px;
}
.demo-section {
border: 1px solid #ddd;
border-radius: 8px;
padding: 20px;
background: #f5f5f5;
}
.demo-title {
font-size: 14px;
font-weight: 600;
margin-bottom: 16px;
color: #333;
}
.demo-controls {
display: flex;
gap: 10px;
margin-top: 16px;
flex-wrap: wrap;
}
.demo-button {
padding: 6px 12px;
border: 1px solid #ddd;
background: white;
border-radius: 4px;
cursor: pointer;
font-size: 13px;
}
.demo-button:hover {
background: #f0f0f0;
}
.demo-button.active {
background: #2196F3;
color: white;
border-color: #2196F3;
}
.demo-info {
margin-top: 12px;
padding: 12px;
background: white;
border-radius: 4px;
font-size: 13px;
line-height: 1.6;
}
.event-log {
margin-top: 12px;
padding: 12px;
background: #f9f9f9;
border-radius: 4px;
font-size: 12px;
max-height: 150px;
overflow-y: auto;
font-family: monospace;
}
.config-display {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 12px;
margin-top: 12px;
}
.config-item {
background: white;
padding: 12px;
border-radius: 4px;
font-size: 12px;
}
.config-label {
font-weight: 600;
color: #666;
margin-bottom: 4px;
}
.config-value {
word-break: break-word;
}
</style>
<div class="demo-container">
<!-- Different Configuration Scenarios -->
<div class="demo-section">
<div class="demo-title">Different Footer Configurations</div>
<dees-demowrapper
.runAfterRender=${async (wrapperElement: any) => {
const footer = wrapperElement.querySelector('upl-statuspage-footer') as any;
// Configuration presets
const configPresets = {
minimal: {
name: 'Minimal',
config: {
companyName: 'SimpleStatus',
whitelabel: true,
lastUpdated: Date.now()
}
},
standard: {
name: 'Standard',
config: {
companyName: 'TechCorp Solutions',
legalUrl: 'https://example.com/legal',
supportEmail: 'support@techcorp.com',
statusPageUrl: 'https://status.techcorp.com',
whitelabel: false,
lastUpdated: Date.now(),
currentYear: new Date().getFullYear()
}
},
fullFeatured: {
name: 'Full Featured',
config: {
companyName: 'Enterprise Cloud Platform',
legalUrl: 'https://enterprise.com/legal',
supportEmail: 'support@enterprise.com',
statusPageUrl: 'https://status.enterprise.com',
whitelabel: false,
socialLinks: [
{ platform: 'twitter', url: 'https://twitter.com/enterprise' },
{ platform: 'github', url: 'https://github.com/enterprise' },
{ platform: 'linkedin', url: 'https://linkedin.com/company/enterprise' },
{ platform: 'facebook', url: 'https://facebook.com/enterprise' },
{ platform: 'youtube', url: 'https://youtube.com/enterprise' }
],
rssFeedUrl: 'https://status.enterprise.com/rss',
apiStatusUrl: 'https://api.enterprise.com/v1/status',
lastUpdated: Date.now(),
currentYear: new Date().getFullYear(),
language: 'en',
additionalLinks: [
{ label: 'API Docs', url: 'https://docs.enterprise.com' },
{ label: 'Service SLA', url: 'https://enterprise.com/sla' },
{ label: 'Security', url: 'https://enterprise.com/security' }
]
}
},
international: {
name: 'International',
config: {
companyName: 'Global Services GmbH',
legalUrl: 'https://global.eu/legal',
supportEmail: 'support@global.eu',
statusPageUrl: 'https://status.global.eu',
whitelabel: false,
language: 'de',
currentYear: new Date().getFullYear(),
lastUpdated: Date.now(),
languageOptions: [
{ code: 'en', label: 'English' },
{ code: 'de', label: 'Deutsch' },
{ code: 'fr', label: 'Français' },
{ code: 'es', label: 'Español' },
{ code: 'ja', label: '日本語' }
],
socialLinks: [
{ platform: 'twitter', url: 'https://twitter.com/global_eu' },
{ platform: 'linkedin', url: 'https://linkedin.com/company/global-eu' }
]
}
},
whitelabel: {
name: 'Whitelabel',
config: {
companyName: 'Custom Brand Status',
whitelabel: true,
customBranding: {
primaryColor: '#FF5722',
logoUrl: 'https://example.com/custom-logo.png',
footerText: 'Powered by Custom Infrastructure'
},
lastUpdated: Date.now(),
currentYear: new Date().getFullYear()
}
}
};
// Initial setup
let currentPreset = 'standard';
const applyPreset = (preset: any) => {
Object.keys(preset.config).forEach(key => {
footer[key] = preset.config[key];
});
updateConfigDisplay(preset.config);
};
applyPreset(configPresets[currentPreset]);
// Create controls
const controls = document.createElement('div');
controls.className = 'demo-controls';
Object.entries(configPresets).forEach(([key, preset]) => {
const button = document.createElement('button');
button.className = 'demo-button' + (key === currentPreset ? ' active' : '');
button.textContent = preset.name;
button.onclick = () => {
controls.querySelectorAll('.demo-button').forEach(btn => btn.classList.remove('active'));
button.classList.add('active');
currentPreset = key;
footer.loading = true;
setTimeout(() => {
applyPreset(preset);
footer.loading = false;
}, 500);
};
controls.appendChild(button);
});
wrapperElement.appendChild(controls);
// Add configuration display
const configDisplay = document.createElement('div');
configDisplay.className = 'config-display';
wrapperElement.appendChild(configDisplay);
const updateConfigDisplay = (config: any) => {
configDisplay.innerHTML = Object.entries(config)
.filter(([key]) => key !== 'socialLinks' && key !== 'additionalLinks' && key !== 'languageOptions')
.map(([key, value]) => `
<div class="config-item">
<div class="config-label">${key}</div>
<div class="config-value">${value}</div>
</div>
`).join('');
};
// Handle events
footer.addEventListener('footerLinkClick', (event: CustomEvent) => {
console.log('Footer link clicked:', event.detail);
alert(`Link clicked: ${event.detail.type} - ${event.detail.url}`);
});
footer.addEventListener('subscribeClick', () => {
alert('Subscribe feature would open here');
});
footer.addEventListener('reportIncidentClick', () => {
alert('Report incident form would open here');
});
footer.addEventListener('languageChange', (event: CustomEvent) => {
alert(`Language changed to: ${event.detail.language}`);
});
}}
>
<upl-statuspage-footer></upl-statuspage-footer>
</dees-demowrapper>
</div>
<!-- Loading and Error States -->
<div class="demo-section">
<div class="demo-title">Loading and Error States</div>
<dees-demowrapper
.runAfterRender=${async (wrapperElement: any) => {
const footer = wrapperElement.querySelector('upl-statuspage-footer') as any;
// Start with loading
footer.loading = true;
footer.companyName = 'LoadingCorp';
const controls = document.createElement('div');
controls.className = 'demo-controls';
controls.innerHTML = `
<button class="demo-button" id="toggleLoading">Toggle Loading</button>
<button class="demo-button" id="loadSuccess">Load Successfully</button>
<button class="demo-button" id="simulateError">Simulate Error</button>
<button class="demo-button" id="simulateOffline">Simulate Offline</button>
<button class="demo-button" id="brokenLinks">Broken Links</button>
`;
wrapperElement.appendChild(controls);
controls.querySelector('#toggleLoading')?.addEventListener('click', () => {
footer.loading = !footer.loading;
});
controls.querySelector('#loadSuccess')?.addEventListener('click', () => {
footer.loading = true;
setTimeout(() => {
footer.companyName = 'Successfully Loaded Inc';
footer.legalUrl = 'https://example.com/legal';
footer.supportEmail = 'support@loaded.com';
footer.statusPageUrl = 'https://status.loaded.com';
footer.lastUpdated = Date.now();
footer.socialLinks = [
{ platform: 'twitter', url: 'https://twitter.com/loaded' },
{ platform: 'github', url: 'https://github.com/loaded' }
];
footer.loading = false;
footer.errorMessage = null;
}, 1000);
});
controls.querySelector('#simulateError')?.addEventListener('click', () => {
footer.loading = true;
setTimeout(() => {
footer.loading = false;
footer.errorMessage = 'Failed to load footer configuration';
footer.companyName = 'Error Loading';
footer.socialLinks = [];
}, 1500);
});
controls.querySelector('#simulateOffline')?.addEventListener('click', () => {
footer.offline = true;
footer.errorMessage = 'You are currently offline';
footer.lastUpdated = null;
});
controls.querySelector('#brokenLinks')?.addEventListener('click', () => {
footer.companyName = 'Broken Links Demo';
footer.legalUrl = 'https://broken.invalid/legal';
footer.supportEmail = 'invalid-email';
footer.socialLinks = [
{ platform: 'twitter', url: '' },
{ platform: 'github', url: 'not-a-url' }
];
footer.rssFeedUrl = 'https://broken.invalid/rss';
footer.apiStatusUrl = null;
});
// Add info display
const info = document.createElement('div');
info.className = 'demo-info';
info.innerHTML = 'Test different loading states and error scenarios using the controls above.';
wrapperElement.appendChild(info);
}}
>
<upl-statuspage-footer></upl-statuspage-footer>
</dees-demowrapper>
</div>
<!-- Dynamic Updates and Real-time Features -->
<div class="demo-section">
<div class="demo-title">Dynamic Updates and Real-time Features</div>
<dees-demowrapper
.runAfterRender=${async (wrapperElement: any) => {
const footer = wrapperElement.querySelector('upl-statuspage-footer') as any;
// Initial configuration
footer.companyName = 'RealTime Systems';
footer.legalUrl = 'https://realtime.com/legal';
footer.supportEmail = 'support@realtime.com';
footer.statusPageUrl = 'https://status.realtime.com';
footer.lastUpdated = Date.now();
footer.currentYear = new Date().getFullYear();
// Dynamic social links
const allSocialPlatforms = [
{ platform: 'twitter', url: 'https://twitter.com/realtime' },
{ platform: 'github', url: 'https://github.com/realtime' },
{ platform: 'linkedin', url: 'https://linkedin.com/company/realtime' },
{ platform: 'facebook', url: 'https://facebook.com/realtime' },
{ platform: 'youtube', url: 'https://youtube.com/realtime' },
{ platform: 'instagram', url: 'https://instagram.com/realtime' },
{ platform: 'slack', url: 'https://realtime.slack.com' },
{ platform: 'discord', url: 'https://discord.gg/realtime' }
];
footer.socialLinks = allSocialPlatforms.slice(0, 3);
// Real-time status feed
footer.rssFeedUrl = 'https://status.realtime.com/rss';
footer.apiStatusUrl = 'https://api.realtime.com/v1/status';
// Status feed simulation
const statusUpdates = [
'All systems operational',
'Investigating API latency',
'Maintenance scheduled for tonight',
'Performance improvements deployed',
'New datacenter online',
'Security patch applied'
];
let updateIndex = 0;
footer.latestStatusUpdate = statusUpdates[0];
// Auto-update last updated time
const updateInterval = setInterval(() => {
footer.lastUpdated = Date.now();
}, 5000);
// Rotate status updates
const statusInterval = setInterval(() => {
updateIndex = (updateIndex + 1) % statusUpdates.length;
footer.latestStatusUpdate = statusUpdates[updateIndex];
logEvent(`Status update: ${statusUpdates[updateIndex]}`);
}, 8000);
// Create controls
const controls = document.createElement('div');
controls.className = 'demo-controls';
controls.innerHTML = `
<button class="demo-button" id="addSocial">Add Social Link</button>
<button class="demo-button" id="removeSocial">Remove Social Link</button>
<button class="demo-button" id="updateStatus">Force Status Update</button>
<button class="demo-button" id="changeYear">Change Year</button>
`;
wrapperElement.appendChild(controls);
controls.querySelector('#addSocial')?.addEventListener('click', () => {
if (footer.socialLinks.length < allSocialPlatforms.length) {
footer.socialLinks = [...footer.socialLinks, allSocialPlatforms[footer.socialLinks.length]];
logEvent(`Added ${allSocialPlatforms[footer.socialLinks.length - 1].platform} link`);
}
});
controls.querySelector('#removeSocial')?.addEventListener('click', () => {
if (footer.socialLinks.length > 0) {
const removed = footer.socialLinks[footer.socialLinks.length - 1];
footer.socialLinks = footer.socialLinks.slice(0, -1);
logEvent(`Removed ${removed.platform} link`);
}
});
controls.querySelector('#updateStatus')?.addEventListener('click', () => {
const customStatus = prompt('Enter custom status update:');
if (customStatus) {
footer.latestStatusUpdate = customStatus;
footer.lastUpdated = Date.now();
logEvent(`Custom status: ${customStatus}`);
}
});
controls.querySelector('#changeYear')?.addEventListener('click', () => {
footer.currentYear = footer.currentYear + 1;
logEvent(`Year changed to ${footer.currentYear}`);
});
// Event log
const eventLog = document.createElement('div');
eventLog.className = 'event-log';
eventLog.innerHTML = '<strong>Event Log:</strong><br>';
wrapperElement.appendChild(eventLog);
const logEvent = (message: string) => {
const time = new Date().toLocaleTimeString();
eventLog.innerHTML += `[${time}] ${message}<br>`;
eventLog.scrollTop = eventLog.scrollHeight;
};
logEvent('Real-time updates started');
// Cleanup
wrapperElement.addEventListener('remove', () => {
clearInterval(updateInterval);
clearInterval(statusInterval);
});
}}
>
<upl-statuspage-footer></upl-statuspage-footer>
</dees-demowrapper>
</div>
<!-- Interactive Features -->
<div class="demo-section">
<div class="demo-title">Interactive Features and Actions</div>
<dees-demowrapper
.runAfterRender=${async (wrapperElement: any) => {
const footer = wrapperElement.querySelector('upl-statuspage-footer') as any;
// Setup interactive footer
footer.companyName = 'Interactive Corp';
footer.legalUrl = 'https://interactive.com/legal';
footer.supportEmail = 'help@interactive.com';
footer.statusPageUrl = 'https://status.interactive.com';
footer.whitelabel = false;
footer.lastUpdated = Date.now();
footer.currentYear = new Date().getFullYear();
// Interactive features
footer.enableSubscribe = true;
footer.enableReportIssue = true;
footer.enableLanguageSelector = true;
footer.enableThemeToggle = true;
footer.languageOptions = [
{ code: 'en', label: 'English' },
{ code: 'es', label: 'Español' },
{ code: 'fr', label: 'Français' },
{ code: 'de', label: 'Deutsch' },
{ code: 'ja', label: '日本語' },
{ code: 'zh', label: '中文' }
];
footer.socialLinks = [
{ platform: 'twitter', url: 'https://twitter.com/interactive' },
{ platform: 'github', url: 'https://github.com/interactive' },
{ platform: 'discord', url: 'https://discord.gg/interactive' }
];
footer.additionalLinks = [
{ label: 'API Documentation', url: 'https://docs.interactive.com' },
{ label: 'Service Level Agreement', url: 'https://interactive.com/sla' },
{ label: 'Privacy Policy', url: 'https://interactive.com/privacy' },
{ label: 'Terms of Service', url: 'https://interactive.com/terms' }
];
// Subscribe functionality
let subscriberCount = 1234;
footer.subscriberCount = subscriberCount;
footer.addEventListener('subscribeClick', (event: CustomEvent) => {
const email = prompt('Enter your email to subscribe:');
if (email && email.includes('@')) {
subscriberCount++;
footer.subscriberCount = subscriberCount;
logAction(`New subscriber: ${email} (Total: ${subscriberCount})`);
alert(`Successfully subscribed! You are subscriber #${subscriberCount}`);
}
});
// Report issue functionality
footer.addEventListener('reportIncidentClick', (event: CustomEvent) => {
const issue = prompt('Describe the issue you are experiencing:');
if (issue) {
const ticketId = `INC-${Date.now().toString().slice(-6)}`;
logAction(`Issue reported: ${ticketId} - ${issue.substring(0, 50)}...`);
alert(`Thank you! Your issue has been logged.\nTicket ID: ${ticketId}\nWe will investigate and update you at the provided email.`);
}
});
// Language change
footer.addEventListener('languageChange', (event: CustomEvent) => {
const newLang = event.detail.language;
footer.currentLanguage = newLang;
logAction(`Language changed to: ${newLang}`);
// Simulate translation
const translations = {
en: 'Interactive Corp',
es: 'Corporación Interactiva',
fr: 'Corp Interactif',
de: 'Interaktive GmbH',
ja: 'インタラクティブ株式会社',
zh: '互动公司'
};
footer.companyName = translations[newLang] || translations.en;
});
// Theme toggle
footer.addEventListener('themeToggle', (event: CustomEvent) => {
const theme = event.detail.theme;
logAction(`Theme changed to: ${theme}`);
footer.currentTheme = theme;
});
// Click tracking
footer.addEventListener('footerLinkClick', (event: CustomEvent) => {
logAction(`Link clicked: ${event.detail.type} - ${event.detail.label || event.detail.url}`);
});
// Action log
const actionLog = document.createElement('div');
actionLog.className = 'event-log';
actionLog.innerHTML = '<strong>User Actions:</strong><br>';
wrapperElement.appendChild(actionLog);
const logAction = (message: string) => {
const time = new Date().toLocaleTimeString();
actionLog.innerHTML += `[${time}] ${message}<br>`;
actionLog.scrollTop = actionLog.scrollHeight;
};
logAction('Interactive footer ready');
// Add info
const info = document.createElement('div');
info.className = 'demo-info';
info.innerHTML = 'Try clicking on various footer elements to see the interactive features in action.';
wrapperElement.appendChild(info);
}}
>
<upl-statuspage-footer></upl-statuspage-footer>
</dees-demowrapper>
</div>
<!-- Edge Cases -->
<div class="demo-section">
<div class="demo-title">Edge Cases and Special Scenarios</div>
<dees-demowrapper
.runAfterRender=${async (wrapperElement: any) => {
const footer = wrapperElement.querySelector('upl-statuspage-footer') as any;
const edgeCases = {
empty: {
name: 'Empty/Minimal',
config: {
companyName: '',
whitelabel: true,
lastUpdated: null
}
},
veryLong: {
name: 'Very Long Content',
config: {
companyName: 'International Mega Corporation with an Extremely Long Company Name That Tests Layout Limits Inc.',
legalUrl: 'https://very-long-domain-name-that-might-break-layouts.international-corporation.com/legal/terms-and-conditions/privacy-policy/cookie-policy',
supportEmail: 'customer.support.team@very-long-domain-name.international-corporation.com',
socialLinks: Array.from({ length: 15 }, (_, i) => ({
platform: ['twitter', 'github', 'linkedin', 'facebook', 'youtube'][i % 5],
url: `https://social-${i}.com/long-username-handle-that-tests-limits`
})),
additionalLinks: Array.from({ length: 10 }, (_, i) => ({
label: `Very Long Link Label That Might Cause Layout Issues #${i + 1}`,
url: `https://example.com/very/long/path/structure/that/goes/on/and/on/page-${i}`
}))
}
},
unicode: {
name: 'Unicode/International',
config: {
companyName: '🌍 全球服务 • グローバル • العالمية • Глобальный 🌏',
legalUrl: 'https://unicode.test/法律',
supportEmail: 'support@日本.jp',
currentYear: new Date().getFullYear(),
socialLinks: [
{ platform: 'twitter', url: 'https://twitter.com/🌐' },
{ platform: 'github', url: 'https://github.com/世界' }
],
additionalLinks: [
{ label: '📋 Terms & Conditions', url: '#' },
{ label: '🔒 Privacy Policy', url: '#' },
{ label: '🛡️ Security', url: '#' }
]
}
},
brokenData: {
name: 'Broken/Invalid Data',
config: {
companyName: null,
legalUrl: 'not-a-valid-url',
supportEmail: 'not-an-email',
currentYear: 'not-a-year',
lastUpdated: 'invalid-timestamp',
socialLinks: [
{ platform: null, url: null },
{ platform: 'unknown-platform', url: '' },
{ url: 'https://missing-platform.com' },
{ platform: 'twitter' }
],
rssFeedUrl: '',
apiStatusUrl: undefined
}
},
maxData: {
name: 'Maximum Data',
config: {
companyName: 'Maximum Configuration Demo',
legalUrl: 'https://max.demo/legal',
supportEmail: 'all@max.demo',
statusPageUrl: 'https://status.max.demo',
whitelabel: false,
currentYear: new Date().getFullYear(),
lastUpdated: Date.now(),
language: 'en',
theme: 'dark',
socialLinks: Array.from({ length: 20 }, (_, i) => ({
platform: 'generic',
url: `https://social${i}.com`
})),
additionalLinks: Array.from({ length: 15 }, (_, i) => ({
label: `Link ${i + 1}`,
url: `#link${i + 1}`
})),
rssFeedUrl: 'https://status.max.demo/rss',
apiStatusUrl: 'https://api.max.demo/status',
subscriberCount: 999999,
enableSubscribe: true,
enableReportIssue: true,
enableLanguageSelector: true,
enableThemeToggle: true,
languageOptions: Array.from({ length: 50 }, (_, i) => ({
code: `lang${i}`,
label: `Language ${i}`
}))
}
}
};
// Initial setup
let currentCase = 'empty';
const applyCase = (edgeCase: any) => {
// Clear all properties first
Object.keys(footer).forEach(key => {
if (typeof footer[key] !== 'function') {
footer[key] = undefined;
}
});
// Apply new config
Object.keys(edgeCase.config).forEach(key => {
footer[key] = edgeCase.config[key];
});
};
applyCase(edgeCases[currentCase]);
// Create controls
const controls = document.createElement('div');
controls.className = 'demo-controls';
Object.entries(edgeCases).forEach(([key, edgeCase]) => {
const button = document.createElement('button');
button.className = 'demo-button' + (key === currentCase ? ' active' : '');
button.textContent = edgeCase.name;
button.onclick = () => {
controls.querySelectorAll('.demo-button').forEach(btn => btn.classList.remove('active'));
button.classList.add('active');
currentCase = key;
applyCase(edgeCase);
};
controls.appendChild(button);
});
wrapperElement.appendChild(controls);
// Add description
const info = document.createElement('div');
info.className = 'demo-info';
info.innerHTML = `
<strong>Edge Case Descriptions:</strong><br>
<strong>Empty:</strong> Minimal configuration with missing data<br>
<strong>Very Long:</strong> Tests layout with extremely long content<br>
<strong>Unicode:</strong> International characters and emojis<br>
<strong>Broken Data:</strong> Invalid or malformed configuration<br>
<strong>Maximum Data:</strong> All features with maximum content
`;
wrapperElement.appendChild(info);
}}
>
<upl-statuspage-footer></upl-statuspage-footer>
</dees-demowrapper>
</div>
</div>
`;