mirror of
https://github.com/ivabus/gui
synced 2025-04-23 14:07:14 +03:00
show packages list filter and sorting buttons (#269)
* #267 #262 show packages list filter and sorting buttons * #262 toggle installed vs all packages filter * #267 show more packages --------- Co-authored-by: neil <neil@neils-MacBook-Pro.local>
This commit is contained in:
parent
3c17dd97f9
commit
78a6887374
4 changed files with 100 additions and 41 deletions
|
@ -9,42 +9,83 @@
|
|||
|
||||
import { installPackage } from '@native';
|
||||
import { trackInstall, trackInstallFailed } from '$libs/analytics';
|
||||
|
||||
import SortingButtons from '$components/search-packages/sorting-buttons.svelte';
|
||||
export let title = 'Packages';
|
||||
export let category = ''; // filter
|
||||
|
||||
let installedOnly = false;
|
||||
|
||||
let sortBy = 'popularity';
|
||||
let sortDirection: 'asc' | 'desc' = 'desc';
|
||||
let limit = 9;
|
||||
|
||||
let packages: GUIPackage[] = [];
|
||||
|
||||
packagesStore.subscribe((ps) => {
|
||||
packages = category ?
|
||||
ps.filter((p) => (p.categories || []).includes(category)) :
|
||||
ps;
|
||||
});
|
||||
const setPackages = (pkgs: GUIPackage[]) => {
|
||||
const sortedPackages = pkgs.sort((a, b) => {
|
||||
if (sortBy === 'popularity') {
|
||||
const aPop = +a.dl_count + a.installs;
|
||||
const bPop = +b.dl_count + b.installs;
|
||||
return sortDirection === 'asc' ? aPop - bPop : bPop - aPop;
|
||||
} else {
|
||||
// most recent
|
||||
const aDate = new Date(a.last_modified);
|
||||
const bDate = new Date(b.last_modified);
|
||||
return sortDirection === 'asc' ? +aDate - +bDate : +bDate - +aDate;
|
||||
}
|
||||
});
|
||||
|
||||
packages = sortedPackages.filter((p) => installedOnly ? [PackageStates.INSTALLED, PackageStates.NEEDS_UPDATE].includes(p.state!) : true);
|
||||
};
|
||||
|
||||
packagesStore.subscribe(setPackages);
|
||||
|
||||
const onSort = (opt: string, dir: 'asc' | 'desc') => {
|
||||
sortBy = opt;
|
||||
sortDirection = dir;
|
||||
setPackages(packages);
|
||||
};
|
||||
|
||||
const toggleInstalledFilter = (installed: boolean) => {
|
||||
installedOnly = installed;
|
||||
setPackages($packagesStore);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<header class="border-gray text-primary flex items-center justify-between border bg-black p-4">
|
||||
<span>{title}</span>
|
||||
<header class="flex items-center justify-between my-4">
|
||||
<h1 class="text-primary text-4xl font-bold">{title}</h1>
|
||||
<div class="flex">
|
||||
<section class="border border-gray mr-2 rounded-sm h-10 text-gray font-thin flex">
|
||||
<button on:click={() => toggleInstalledFilter(false)} class={`px-2 ${installedOnly ? "":"active"}`}>All packages</button>
|
||||
<button on:click={() => toggleInstalledFilter(true)} class={`px-2 ${installedOnly ? "active":""}`}>installed only</button>
|
||||
</section>
|
||||
<section class="border-gray h-10 w-48 border rounded-sm">
|
||||
<SortingButtons {onSort} />
|
||||
</section>
|
||||
</div>
|
||||
</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' : ''}>
|
||||
<Package
|
||||
{pkg}
|
||||
onClick={async () => {
|
||||
try {
|
||||
pkg.state = PackageStates.INSTALLING;
|
||||
await installPackage(pkg);
|
||||
trackInstall(pkg.full_name);
|
||||
pkg.state = PackageStates.INSTALLED;
|
||||
} catch (error) {
|
||||
let message = 'Unknown Error'
|
||||
if (error instanceof Error) message = error.message
|
||||
trackInstallFailed(pkg.full_name, message || "unknown");
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{#each packages as pkg, index}
|
||||
{#if index < limit}
|
||||
<div class={pkg.state === PackageStates.INSTALLING ? 'animate-pulse' : ''}>
|
||||
<Package
|
||||
{pkg}
|
||||
onClick={async () => {
|
||||
try {
|
||||
pkg.state = PackageStates.INSTALLING;
|
||||
await installPackage(pkg);
|
||||
trackInstall(pkg.full_name);
|
||||
pkg.state = PackageStates.INSTALLED;
|
||||
} catch (error) {
|
||||
let message = 'Unknown Error'
|
||||
if (error instanceof Error) message = error.message
|
||||
trackInstallFailed(pkg.full_name, message || "unknown");
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
{:else}
|
||||
{#each Array(9) as _}
|
||||
|
@ -54,3 +95,24 @@
|
|||
{/each}
|
||||
{/if}
|
||||
</ul>
|
||||
{#if limit < packages.length }
|
||||
<footer class="w-full flex border border-gray h-16">
|
||||
<button class="flex-grow h-16" on:click={() => limit += 9 }>show more</button>
|
||||
</footer>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
button {
|
||||
height: 100%;
|
||||
text-decoration: none;
|
||||
min-width: 120px;
|
||||
transition: 0.1s linear;
|
||||
}
|
||||
|
||||
button:hover, button.active {
|
||||
color: white;
|
||||
background-color: #8000ff;
|
||||
box-shadow: inset 0vw 0vw 0vw 0.223vw #1a1a1a !important;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
|
@ -26,14 +26,14 @@
|
|||
};
|
||||
</script>
|
||||
|
||||
<section class="sorting-container font-machina bg-black text-white">
|
||||
<section class="sorting-container font-machina bg-black text-gray">
|
||||
<div class="dropdown">
|
||||
<div class="dropdown-title">{$t("sorting.label")}</div>
|
||||
<ul class="dropdown-content column flex">
|
||||
{#each sortOptions as option}
|
||||
<li class="flex items-center">
|
||||
<button
|
||||
class={`sort-btn uppercase ${sortBy === option ? 'active' : ''}`}
|
||||
class={`sort-btn ${sortBy === option ? 'active' : ''}`}
|
||||
on:click={() => setSortBy(option)}
|
||||
>
|
||||
{optionLabels[option]}
|
||||
|
@ -67,13 +67,11 @@
|
|||
|
||||
.sorting-container {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
max-width: 240px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 34px;
|
||||
min-height: 30px;
|
||||
transition: 0.1s linear;
|
||||
}
|
||||
|
||||
|
@ -100,9 +98,9 @@
|
|||
.dropdown-content li {
|
||||
position: relative;
|
||||
padding: 0px 10px;
|
||||
height: 40px;
|
||||
height: 32px;
|
||||
width: 100%;
|
||||
line-height: 40px;
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
.dropdown-content li .sort-btn {
|
||||
|
@ -131,8 +129,8 @@
|
|||
}
|
||||
|
||||
.dropdown-title {
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -62,9 +62,9 @@
|
|||
},
|
||||
"view-all": "view all",
|
||||
"sorting": {
|
||||
"label": "sort order",
|
||||
"popularity": "popularity",
|
||||
"most-recent": "most recent"
|
||||
"label": "Filters",
|
||||
"popularity": "Most popular",
|
||||
"most-recent": "Most recent"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,9 +9,8 @@
|
|||
</script>
|
||||
|
||||
<div>
|
||||
<PageHeader coverUrl="/images/headers/header_bg_1.png">{$t("home.discover-title")}</PageHeader>
|
||||
<section class="mt-8 mb-8">
|
||||
<Packages title={$t("package.foundation-essentials-title")} category="foundation_essentials" />
|
||||
<Packages title={$t("home.discover-title")}/>
|
||||
</section>
|
||||
<PageHeader coverUrl="/images/headers/header_bg_1.png">{$t("home.tutorials-title")}</PageHeader>
|
||||
<section class="mt-8 mb-8">
|
||||
|
|
Loading…
Reference in a new issue