Переглянути джерело

Starts working on template page

Alicia Sykes 2 роки тому
батько
коміт
93b9dcb68a
2 змінених файлів з 235 додано та 0 видалено
  1. 19 0
      src/routes/[slug]/+page.server.ts
  2. 216 0
      src/routes/[slug]/+page.svelte

+ 19 - 0
src/routes/[slug]/+page.server.ts

@@ -0,0 +1,19 @@
+import { get } from 'svelte/store';
+
+import { templatesUrl } from '$src/constants';
+import { templates } from '$src/store';
+
+export const load = async () => {
+  if (get(templates) && get(templates).length > 0) {
+    return {
+      templates: get(templates),
+    }
+  } else {
+    const data = await fetch(templatesUrl).then((res) => res.json());
+    templates.set(data.templates);
+    
+    return {
+      templates: data.templates,
+    }
+  }
+};

+ 216 - 0
src/routes/[slug]/+page.svelte

@@ -0,0 +1,216 @@
+<script lang="ts">
+  import { page } from '$app/stores';
+  import TemplateNotFound from '$lib/TemplateNotFound.svelte';
+  import type { Template } from '$src/Types';
+
+  const templates = $page.data.templates as Template[];
+  const templateSlug = $page.params.slug as string;
+  
+  const template = templates.find((temp: Template) =>
+    temp.title.toLowerCase().replace(/[^a-zA-Z ]/g, "").replaceAll(' ', '-') === templateSlug
+  );
+
+  console.log(template);
+</script>
+
+<header>
+  <a class="title" href="/">
+    <img src="https://i.ibb.co/hMymwH0/portainer-templates-small.png" />
+    <h2>Portainer Templates</h2>
+  </a>
+  <nav>
+    <a href="/">Home</a>
+    <a href="https://github.com/lissy93/portainer-templates">View on GitHub</a>
+  </nav>
+</header>
+
+{#if template}
+  <section class="summary-section">
+    <h1><img src={template.logo} alt={template.title} />{template.title}</h1>
+    {#if template.categories}
+      <p class="tags">
+        {#each (template.categories) as tag}
+          <span>{tag}</span>
+        {/each}
+      </p>
+    {/if}
+    <div class="content">
+      <p class="description">{template.description}</p>
+      <div class="stats">
+        {#if template.type}
+          <div class="row">
+            <span class="lbl">Type</span>
+            {#if template.type === 1}
+              <span>Container</span>
+            {:else if template.type === 2}
+              <span>Swarm</span>
+            {:else if template.type === 3}
+              <span>Kubernetes</span>
+            {:else}
+              <span>Unknown</span>
+            {/if}
+          </div>
+        {/if}
+        {#if template.platform}
+          <div class="row">
+            <span class="lbl">Platform</span>
+            <code>{template.platform}</code>
+          </div>
+        {/if}
+        {#if template.image}
+          <div class="row">
+            <span class="lbl">Image</span>
+            <code>{template.image}</code>
+          </div>
+        {/if}
+        {#if template.command}
+          <div class="row">
+            <span class="lbl">Command</span>
+            <code>{template.command}</code>
+          </div>
+        {/if}
+        {#if typeof template.interactive === 'boolean'}
+          <div class="row">
+            <span class="lbl">Interactive</span>
+            <code>{template.interactive ? 'Yes' : 'No'}</code>
+          </div>
+        {/if}
+        {#if template.ports}
+        <div class="row">
+          <span class="lbl">Ports</span>
+          <p>
+            {#each template.ports as port}<code>{port}</code>{/each}
+          </p>
+        </div>
+      {/if}
+        {#if template.volumes}
+        <div class="row">
+          <span class="lbl">Volumes</span>
+          <p>
+            {#each template.volumes as volume}<code>{volume.container}</code>{/each}
+          </p>
+        </div>
+      {/if}
+      </div>
+    </div>
+  </section>
+{:else}
+  <TemplateNotFound />
+{/if}
+
+<style lang="scss">
+  header {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    background: var(--card);
+    padding: 0.25rem 1rem;
+    a.title {
+      display: flex;
+      justify-content: center;
+      gap: 1rem;
+      color: var(--foreground);
+      text-decoration: none;
+      h2 {
+        margin: 0;
+        font-size: 1.5rem;
+        font-weight: 600;
+      }
+      img {
+        width: 40px;
+        transition: all 0.3s ease-in-out;
+      }
+      &:hover {
+        img { transform: rotate(-5deg) scale(1.1); }
+      }
+    }
+
+    nav {
+      display: flex;
+      gap: 1rem;
+      a {
+        color: var(--foreground);
+        text-decoration: none;
+        padding: 0.25rem 0.5rem;
+        border-radius: 6px;
+        transition: all 250ms ease-in-out;
+        &:hover {
+          background: var(--gradient);
+          transform: scale(1.05);
+        }
+      }
+    }
+  }
+  .summary-section {
+    background: var(--card);
+    border-radius: 6px;
+    padding: 1rem;
+    margin: 1rem;
+    display: flex;
+    flex-direction: column;
+    h1 {
+      font-size: 4rem;
+      margin: 0;
+      display: flex;
+      align-items: center;
+      gap: 1rem;
+    }
+    img {
+      width: 64px;
+      max-height: 64px;
+    }
+    .tags {
+      display: flex;
+      margin: 0;
+      span {
+        &:before {
+          content: '#';
+          opacity: 0.5;
+        }
+        &:not(:last-child)::after {
+          content: ',';
+          margin-right: 0.5rem;
+        }
+      }
+    }
+  }
+
+  .content {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 1rem;
+    justify-content: space-between;
+    p.description {
+      max-width: 60%;
+    }
+    .stats {
+      min-width: 15rem;
+      border: 2px solid var(--background);
+      border-radius: 6px;
+      .row {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        flex-wrap: wrap;
+        padding: 0.5rem;
+        gap: 0.5rem;
+        &:not(:last-child) {
+          border-bottom: 2px dotted var(--background);
+        }
+        span {
+          font-style: italic;
+        }
+        p {
+          margin: 0;
+          display: flex;
+          flex-direction: column;
+        }
+        .lbl {
+          font-weight: 400;
+          font-style: normal;
+          min-width: 5rem;
+        }
+      }
+    }
+  }
+</style>