feat(internal/launchpad): add iframe viewer for prototypes and update links loader This commit introduces an iframe viewer in the launchpad to display prototypes directly within the application. It also updates the links loader to handle prototype links differently, opening them in the iframe instead of a new tab. The contributing guide has been updated to include a list of required development tools and recommended IDE setup, ensuring that contributors have the necessary tools to work on the project.
94 lines
4.4 KiB
JavaScript
94 lines
4.4 KiB
JavaScript
async function loadLinks() {
|
|
const container = document.getElementById('links-container');
|
|
if (!container) return;
|
|
|
|
try {
|
|
const response = await fetch('./assets/data/links.json');
|
|
if (!response.ok) {
|
|
throw new Error(`Failed to load links: ${response.status}`);
|
|
}
|
|
|
|
const groups = await response.json();
|
|
|
|
// Helper function to fetch SVG content
|
|
const fetchSvg = async (path) => {
|
|
if (!path) return '';
|
|
try {
|
|
const res = await fetch(path);
|
|
if (!res.ok) return '';
|
|
return await res.text();
|
|
} catch (e) {
|
|
console.error(`Failed to load SVG: ${path}`, e);
|
|
return '';
|
|
}
|
|
};
|
|
|
|
// Process groups and fetch SVGs in parallel
|
|
const groupsWithSvgs = await Promise.all(groups.map(async (group) => {
|
|
const groupIconSvg = await fetchSvg(group.iconPath);
|
|
|
|
const linksWithSvgs = await Promise.all(group.links.map(async (link) => {
|
|
const linkIconSvg = link.iconPath ? await fetchSvg(link.iconPath) : '';
|
|
return { ...link, iconSvg: linkIconSvg };
|
|
}));
|
|
|
|
return { ...group, iconSvg: groupIconSvg, links: linksWithSvgs };
|
|
}));
|
|
|
|
container.innerHTML = groupsWithSvgs.map(group => `
|
|
<!-- ${group.title} Card -->
|
|
<div class="card-hover bg-white rounded-2xl shadow-lg p-6 border border-gray-100">
|
|
<div class="flex items-center space-x-3 mb-6">
|
|
<div class="w-10 h-10 ${group.iconColorClass} rounded-lg flex items-center justify-center">
|
|
${group.iconSvg}
|
|
</div>
|
|
<h3 class="text-xl font-bold text-gray-900">${group.title}</h3>
|
|
</div>
|
|
|
|
<div class="space-y-3">
|
|
${group.links.map(link => {
|
|
const isPrototype = link.url.startsWith('/prototypes/');
|
|
const hrefAttr = isPrototype ? 'href="#"' : `href="${link.url}" target="_blank"`;
|
|
const onclickAttr = isPrototype ? `onclick="event.preventDefault(); showView('iframe', this, '${link.url}', '${link.title}')"` : '';
|
|
|
|
return `
|
|
<a ${hrefAttr} ${onclickAttr}
|
|
class="flex items-center justify-between p-4 ${link.containerClass} rounded-xl transition-all group">
|
|
<div class="flex items-center space-x-3">
|
|
${link.iconClass ? `<div class="${link.iconClass}"></div>` : link.iconSvg}
|
|
${link.subtitle ? `
|
|
<div>
|
|
<div class="font-medium text-gray-900 ${link.textHoverClass}">${link.title}</div>
|
|
<div class="text-xs text-gray-500">${link.subtitle}</div>
|
|
</div>
|
|
` : `
|
|
<span class="font-medium text-gray-900 ${link.textHoverClass}">${link.title}</span>
|
|
`}
|
|
</div>
|
|
${link.badge ? `
|
|
<span class="px-3 py-1 ${link.badgeColorClass} text-white text-xs font-semibold rounded-full">${link.badge}</span>
|
|
` : ''}
|
|
${link.arrowIcon ? `
|
|
<svg class="w-5 h-5 text-gray-400 group-hover:translate-x-1 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
|
|
</svg>
|
|
` : ''}
|
|
</a>
|
|
`}).join('')}
|
|
</div>
|
|
</div>
|
|
`).join('');
|
|
|
|
} catch (error) {
|
|
console.error('Error loading links:', error);
|
|
container.innerHTML = `
|
|
<div class="col-span-full p-4 bg-red-50 text-red-600 rounded-xl border border-red-200">
|
|
Failed to load application links. Please try refreshing the page.
|
|
</div>
|
|
`;
|
|
}
|
|
}
|
|
|
|
// Load links when the DOM is loaded
|
|
document.addEventListener('DOMContentLoaded', loadLinks);
|