mirror of
https://github.com/ivabus/gui
synced 2025-06-08 00:00:27 +03:00
parent
44d59a3cc5
commit
4ac357a4db
8 changed files with 126 additions and 5 deletions
60
packages/gui/src/components/TopPackages/TopPackages.svelte
Normal file
60
packages/gui/src/components/TopPackages/TopPackages.svelte
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import '$appcss';
|
||||||
|
import type { GUIPackage } from '$libs/types';
|
||||||
|
import { PackageStates } from '$libs/types';
|
||||||
|
import Preloader from '@tea/ui/Preloader/Preloader.svelte';
|
||||||
|
import PackageCard from '@tea/ui/PackageCard/PackageCard.svelte';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import { getTopPackages } from '$libs/api/mock';
|
||||||
|
import { installPackage } from '@api';
|
||||||
|
|
||||||
|
let packages: GUIPackage[] = [];
|
||||||
|
|
||||||
|
const getCTALabel = (state: PackageStates): string => {
|
||||||
|
return {
|
||||||
|
[PackageStates.AVAILABLE]: 'INSTALL',
|
||||||
|
[PackageStates.INSTALLED]: 'INSTALLED',
|
||||||
|
[PackageStates.INSTALLING]: 'INSTALLING',
|
||||||
|
[PackageStates.UNINSTALLED]: 'RE-INSTALL'
|
||||||
|
}[state];
|
||||||
|
};
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
if (!packages.length) {
|
||||||
|
packages = await getTopPackages();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<header class="flex items-center justify-between border border-gray bg-black p-4 text-primary">
|
||||||
|
<span>TOP PACKAGES</span>
|
||||||
|
<a href="/packages" class="font-sono text-sm underline">View all packages</a>
|
||||||
|
</header>
|
||||||
|
<ul class="grid grid-cols-3 bg-black">
|
||||||
|
{#if packages.length > 0}
|
||||||
|
{#each packages as pkg}
|
||||||
|
<div class={pkg.state === PackageStates.INSTALLING ? 'animate-pulse' : ''}>
|
||||||
|
<PackageCard
|
||||||
|
{pkg}
|
||||||
|
link={`/packages/${pkg.slug}`}
|
||||||
|
ctaLabel={getCTALabel(pkg.state)}
|
||||||
|
onClickCTA={async () => {
|
||||||
|
try {
|
||||||
|
pkg.state = PackageStates.INSTALLING;
|
||||||
|
await installPackage(pkg.full_name);
|
||||||
|
pkg.state = PackageStates.INSTALLED;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
{:else}
|
||||||
|
{#each Array(9) as _}
|
||||||
|
<section class="h-50 border border-gray p-4">
|
||||||
|
<Preloader />
|
||||||
|
</section>
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
|
</ul>
|
|
@ -241,3 +241,13 @@ export async function getFeaturedCourses(): Promise<Course[]> {
|
||||||
|
|
||||||
return mockCourses;
|
return mockCourses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getTopPackages(): Promise<GUIPackage[]> {
|
||||||
|
await delay(500);
|
||||||
|
return packages.slice(0, 9).map((pkg) => {
|
||||||
|
return {
|
||||||
|
...pkg,
|
||||||
|
state: PackageStates.AVAILABLE
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -142,3 +142,8 @@ export async function getFeaturedCourses(): Promise<Course[]> {
|
||||||
const courses = await mock.getFeaturedCourses();
|
const courses = await mock.getFeaturedCourses();
|
||||||
return courses;
|
return courses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getTopPackages(): Promise<GUIPackage[]> {
|
||||||
|
const packages = await mock.getTopPackages();
|
||||||
|
return packages;
|
||||||
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<nav class="border border-t-0 border-l-0 border-b-0 border-gray">
|
<nav class="border border-t-0 border-l-0 border-b-0 border-gray">
|
||||||
<NavBar />
|
<NavBar />
|
||||||
</nav>
|
</nav>
|
||||||
<section class="px-16 pt-24">
|
<section class="px-16 pt-24 pb-24">
|
||||||
{#if backLink}
|
{#if backLink}
|
||||||
<header class="px-16 py-2 text-3xl text-gray hover:text-primary">
|
<header class="px-16 py-2 text-3xl text-gray hover:text-primary">
|
||||||
<a href={backLink}>←</a>
|
<a href={backLink}>←</a>
|
||||||
|
@ -46,10 +46,10 @@
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
figure {
|
figure {
|
||||||
position: absolute;
|
position: fixed;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
top: 220px;
|
top: 220px;
|
||||||
left: 0px;
|
left: 240px;
|
||||||
right: 0px;
|
right: 0px;
|
||||||
bottom: 0px;
|
bottom: 0px;
|
||||||
background-image: url('/images/footer-grid-element.svg');
|
background-image: url('/images/footer-grid-element.svg');
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
import PageHeader from '$components/PageHeader/PageHeader.svelte';
|
import PageHeader from '$components/PageHeader/PageHeader.svelte';
|
||||||
import FeaturedPackages from '$components/FeaturedPackages/FeaturedPackages.svelte';
|
import FeaturedPackages from '$components/FeaturedPackages/FeaturedPackages.svelte';
|
||||||
import GettingStarted from '$components/GettingStarted/GettingStarted.svelte';
|
import GettingStarted from '$components/GettingStarted/GettingStarted.svelte';
|
||||||
|
import TopPackages from '$components/TopPackages/TopPackages.svelte';
|
||||||
backLink.set('');
|
backLink.set('');
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -16,6 +17,9 @@
|
||||||
<section class="mt-8">
|
<section class="mt-8">
|
||||||
<GettingStarted />
|
<GettingStarted />
|
||||||
</section>
|
</section>
|
||||||
|
<section class="mt-8">
|
||||||
|
<TopPackages />
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
42
packages/ui/src/Gallery/Gallery.stories.ts
Normal file
42
packages/ui/src/Gallery/Gallery.stories.ts
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
import Gallery from './Gallery.svelte';
|
||||||
|
|
||||||
|
// More on how to set up stories at: https://storybook.js.org/docs/7.0/svelte/writing-stories/introduction
|
||||||
|
export default {
|
||||||
|
title: 'Example/Gallery',
|
||||||
|
component: Gallery,
|
||||||
|
tags: ['docsPage'],
|
||||||
|
render: (args) => ({
|
||||||
|
Component: Gallery,
|
||||||
|
props: args
|
||||||
|
}),
|
||||||
|
argTypes: {
|
||||||
|
onClick: () => console.log('does nothing')
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// More on writing stories with args: https://storybook.js.org/docs/7.0/svelte/writing-stories/args
|
||||||
|
export const Example = {
|
||||||
|
args: {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
imageUrl:
|
||||||
|
'https://upload.wikimedia.org/wikipedia/commons/thumb/8/85/%22_Shot_From_The_Sky%22_Army_Show_1945_Oak_Ridge_%2824971013612%29.jpg/2732px-%22_Shot_From_The_Sky%22_Army_Show_1945_Oak_Ridge_%2824971013612%29.jpg',
|
||||||
|
title: 'Item 1',
|
||||||
|
subTitle: 'sub-title',
|
||||||
|
link: '#'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
imageUrl: 'https://tea.xyz/Images/packages/sqlite_org.jpg',
|
||||||
|
title: 'Item 2',
|
||||||
|
subTitle: 'sub-title 2',
|
||||||
|
link: '#'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
imageUrl: 'https://tea.xyz/Images/packages/gnu_org_libtool.jpg',
|
||||||
|
title: 'Item 3',
|
||||||
|
subTitle: 'sub-title 3',
|
||||||
|
link: '#'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import '$appcss';
|
import '../app.css';
|
||||||
import { onDestroy, onMount } from 'svelte';
|
import { onDestroy, onMount } from 'svelte';
|
||||||
import { watchResize } from 'svelte-watch-resize';
|
import { watchResize } from 'svelte-watch-resize';
|
||||||
import Preloader from '../Preloader/Preloader.svelte';
|
import Preloader from '../Preloader/Preloader.svelte';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import '$appcss';
|
import '../app.css';
|
||||||
import ImgLoader from '../ImgLoader/ImgLoader.svelte';
|
import ImgLoader from '../ImgLoader/ImgLoader.svelte';
|
||||||
|
|
||||||
export let width = 0;
|
export let width = 0;
|
||||||
|
|
Loading…
Reference in a new issue