generated from wessel/boilerplate
167 lines
7.0 KiB
Svelte
167 lines
7.0 KiB
Svelte
<script lang="ts">
|
||
import { onMount } from 'svelte';
|
||
import services, { type Service } from './services';
|
||
|
||
let selectedService: Service | null = null;
|
||
let currentTime = '';
|
||
|
||
// Group services by category
|
||
const groupedServices: Record<string, Service[]> = services.reduce((acc, service) => {
|
||
if (!acc[service.category]) {
|
||
acc[service.category] = [];
|
||
}
|
||
acc[service.category].push(service);
|
||
return acc;
|
||
}, {} as Record<string, Service[]>);
|
||
|
||
function selectService(service: Service) {
|
||
selectedService = service;
|
||
}
|
||
|
||
function updateTime() {
|
||
const now = new Date();
|
||
currentTime = now.toLocaleTimeString('en-US', {
|
||
hour12: false,
|
||
hour: '2-digit',
|
||
minute: '2-digit',
|
||
second: '2-digit'
|
||
});
|
||
}
|
||
|
||
onMount(() => {
|
||
updateTime();
|
||
const interval = setInterval(updateTime, 1000);
|
||
return () => clearInterval(interval);
|
||
});
|
||
</script>
|
||
|
||
<!-- Terminal-style homepage layout -->
|
||
<div class="terminal">
|
||
<!-- Header -->
|
||
<header class="terminal-header">
|
||
<div class="header-left">
|
||
<span class="terminal-title">NOVA</span>
|
||
<span class="terminal-path">/home/root/services</span>
|
||
</div>
|
||
<div class="header-right">
|
||
<span class="terminal-time">{currentTime}</span>
|
||
<div class="terminal-controls">
|
||
<span class="control minimize">─</span>
|
||
<span class="control maximize">□</span>
|
||
<span class="control close">×</span>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- Main content area -->
|
||
<div class="terminal-body">
|
||
<!-- Left sidebar with services -->
|
||
<aside class="services-sidebar">
|
||
<div class="prompt-line">
|
||
<span class="prompt-prefix">
|
||
<span class="prompt-bracket">[</span><span class="prompt-user">user</span><span class="prompt-at">@</span><span class="prompt-host">nova</span><span class="prompt-bracket">]</span><span class="prompt-path">~/services</span><span class="prompt-dollar">$ </span>
|
||
</span>
|
||
<span class="command">ls -la services/</span>
|
||
</div>
|
||
|
||
{#each Object.entries(groupedServices) as [category, categoryServices]}
|
||
<div class="service-category">
|
||
<div class="category-header">
|
||
<span class="folder-icon">📁</span>
|
||
<span class="category-name">{category.toLowerCase()}/</span>
|
||
</div>
|
||
|
||
{#each categoryServices as service}
|
||
<button
|
||
class="service-item {selectedService?.name === service.name ? 'selected' : ''}"
|
||
on:click={() => selectService(service)}
|
||
>
|
||
<span class="service-icon">{service.icon}</span>
|
||
<span class="service-name">{service.name}</span>
|
||
<span class="service-ext">.service</span>
|
||
</button>
|
||
{/each}
|
||
</div>
|
||
{/each}
|
||
|
||
{#if selectedService}
|
||
<div class="service-info">
|
||
<div class="prompt-line">
|
||
<span class="prompt-prefix">
|
||
<span class="prompt-bracket">[</span><span class="prompt-user">user</span><span class="prompt-at">@</span><span class="prompt-host">nova</span><span class="prompt-bracket">]</span><span class="prompt-path">~/services</span><span class="prompt-dollar">$ </span>
|
||
</span>
|
||
<span class="command">systemctl status {selectedService.name.toLowerCase()}</span>
|
||
</div>
|
||
<div class="status-output">
|
||
<div class="status-line">● {selectedService.name.toLowerCase()}.service - {selectedService.name}</div>
|
||
<div class="status-line"> Loaded: loaded (/etc/systemd/system/{selectedService.name.toLowerCase()}.service; enabled)</div>
|
||
<div class="status-line active"> Active: <span class="status-active">active (running)</span> since $(date)</div>
|
||
<div class="status-line"> Main PID: $(echo $RANDOM)</div>
|
||
</div>
|
||
</div>
|
||
{/if}
|
||
</aside>
|
||
|
||
<!-- Right content area with iframe -->
|
||
<main class="content-area">
|
||
{#if selectedService}
|
||
<div class="iframe-header">
|
||
<div class="iframe-controls">
|
||
<span class="iframe-title">{selectedService.name} - {selectedService.url}</span>
|
||
<button class="external-link" on:click={() => selectedService && window.open(selectedService.url, '_blank')}>
|
||
↗ Open External
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="iframe-container">
|
||
<iframe
|
||
src={selectedService.url}
|
||
title={selectedService.name}
|
||
frameborder="0"
|
||
></iframe>
|
||
</div>
|
||
{:else}
|
||
<div class="placeholder">
|
||
<div class="placeholder-content">
|
||
<div class="ascii-art">
|
||
<pre>{`
|
||
███╗ ██╗ ██████╗ ██╗ ██╗ █████╗
|
||
████╗ ██║██╔═══██╗██║ ██║██╔══██╗
|
||
██╔██╗ ██║██║ ██║██║ ██║███████║
|
||
██║╚██╗██║██║ ██║╚██╗ ██╔╝██╔══██║
|
||
██║ ╚████║╚██████╔╝ ╚████╔╝ ██║ ██║
|
||
╚═╝ ╚═══╝ ╚═════╝ ╚═══╝ ╚═╝ ╚═╝
|
||
`}</pre>
|
||
</div>
|
||
<div class="welcome-text">
|
||
<p class="prompt-line">
|
||
<span class="prompt-prefix">
|
||
<span class="prompt-bracket">[</span><span class="prompt-user">user</span><span class="prompt-at">@</span><span class="prompt-host">nova</span><span class="prompt-bracket">]</span><span class="prompt-path">~</span><span class="prompt-dollar">$ </span>
|
||
</span>
|
||
<span class="command">echo "Welcome to Nova Terminal Dashboard"</span>
|
||
</p>
|
||
<p class="output">Welcome to Nova Terminal Dashboard</p>
|
||
<p class="prompt-line">
|
||
<span class="prompt-prefix">
|
||
<span class="prompt-bracket">[</span><span class="prompt-user">user</span><span class="prompt-at">@</span><span class="prompt-host">nova</span><span class="prompt-bracket">]</span><span class="prompt-path">~</span><span class="prompt-dollar">$ </span>
|
||
</span>
|
||
<span class="command">echo "Select a service from the left panel to view"</span>
|
||
</p>
|
||
<p class="output">Select a service from the left panel to view</p>
|
||
<p class="prompt-line">
|
||
<span class="prompt-prefix">
|
||
<span class="prompt-bracket">[</span><span class="prompt-user">user</span><span class="prompt-at">@</span><span class="prompt-host">nova</span><span class="prompt-bracket">]</span><span class="prompt-path">~</span><span class="prompt-dollar">$ </span>
|
||
</span>
|
||
<span class="typing-cursor">█</span>
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{/if}
|
||
</main>
|
||
</div>
|
||
</div>
|
||
|
||
<style lang="scss">
|
||
@use './main.scss'
|
||
</style> |