error notifications (#456)

This commit is contained in:
ABevier 2023-04-13 20:01:37 -04:00 committed by GitHub
parent 328c6e2bf6
commit af59c02cae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 86 additions and 54 deletions

View file

@ -5,7 +5,7 @@
import Button from "@tea/ui/button/button.svelte";
import semverCompare from "semver/functions/compare";
import { PackageStates, type GUIPackage } from "$libs/types";
import type { GUIPackage } from "$libs/types";
import { packagesStore } from "$libs/stores";
import { shellOpenExternal } from "@native";
import InstallButton from "$components/install-button/install-button.svelte";
@ -20,9 +20,6 @@
installing = true;
await packagesStore.installPkg(pkg, version);
installing = false;
packagesStore.updatePackage(pkg.full_name, {
state: PackageStates.INSTALLED
});
};
const prune = async () => {

View file

@ -2,21 +2,13 @@
import "$appcss";
import type { GUIPackage } from "$libs/types";
import { packagesStore, notificationStore } from "$libs/stores";
import { packagesStore } from "$libs/stores";
import { onMount } from "svelte";
import PackageCard from "$components/package-card/package-card.svelte";
import { findAvailableVersions } from "$libs/packages/pkg-utils";
export let tab = "all";
export let pkg: GUIPackage;
export let onClick: (version: string) => void;
const onClickCTA = async (version: string) => {
await onClick(version);
notificationStore.add({
message: `Package ${pkg.full_name} v${version || pkg.version} has been installed.`
});
};
onMount(() => {
packagesStore.fetchPackageBottles(pkg.full_name);
@ -28,7 +20,7 @@
availableVersions={findAvailableVersions(pkg)}
link="/packages/{pkg.slug}?tab={tab}"
progessLoading={pkg.install_progress_percentage}
{onClickCTA}
onClickCTA={(version) => packagesStore.installPkg(pkg, version)}
onUninstall={async () => {
packagesStore.uninstallPkg(pkg);
}}

View file

@ -87,11 +87,7 @@
{#each packages as pkg, index}
{#if index < limit}
<div class="card z-1 p-1" class:animate-puls={pkg.state === PackageStates.INSTALLING}>
<Package
tab={packageFilter}
{pkg}
onClick={(version) => packagesStore.installPkg(pkg, version)}
/>
<Package tab={packageFilter} {pkg} />
</div>
{/if}
{/each}

View file

@ -85,14 +85,10 @@ export async function getPackageReviews(full_name: string): Promise<Review[]> {
}
export async function installPackage(pkg: GUIPackage, version?: string) {
try {
const latestVersion = pkg.version;
const specificVersion = version || latestVersion;
log.info(`installing package: ${pkg.name} version: ${specificVersion}`);
await installPackageCommand(pkg.full_name + (specificVersion ? `@${specificVersion}` : ""));
} catch (error) {
log.error("installPackage:", error);
}
const latestVersion = pkg.version;
const specificVersion = version || latestVersion;
log.info(`installing package: ${pkg.name} version: ${specificVersion}`);
await installPackageCommand(pkg.full_name + (specificVersion ? `@${specificVersion}` : ""));
}
export async function getTopPackages(): Promise<GUIPackage[]> {

View file

@ -2,5 +2,7 @@ const { ipcRenderer } = window.require("electron");
export async function installPackageCommand(full_name: string) {
const res = await ipcRenderer.invoke("install-package", { full_name });
console.log("install:", res);
if (res instanceof Error) {
throw res;
}
}

View file

@ -15,11 +15,12 @@ import {
} from "@native";
import { getReadme, getContributors, getRepoAsPackage } from "$libs/github";
import type { Package } from "@tea/ui/types";
import { NotificationType, type Package } from "@tea/ui/types";
import { trackInstall, trackInstallFailed } from "$libs/analytics";
import { addInstalledVersion } from "$libs/packages/pkg-utils";
import withDebounce from "$libs/utils/debounce";
import { trimGithubSlug } from "$libs/github";
import { notificationStore } from "$libs/stores";
const log = window.require("electron-log");
@ -136,6 +137,9 @@ To read more about this package go to [${guiPkg.homepage}](${guiPkg.homepage}).
const installPkg = async (pkg: GUIPackage, version?: string) => {
let fakeTimer: NodeJS.Timer | null = null;
const originalState = pkg.state;
const versionToInstall = version || pkg.version;
try {
const state: PackageStates =
pkg.state === PackageStates.NEEDS_UPDATE
@ -148,7 +152,6 @@ To read more about this package go to [${guiPkg.homepage}](${guiPkg.homepage}).
updatePackage(pkg.full_name, { install_progress_percentage: progress });
});
const versionToInstall = version || pkg.version;
await installPackage(pkg, versionToInstall);
trackInstall(pkg.full_name);
@ -156,10 +159,22 @@ To read more about this package go to [${guiPkg.homepage}](${guiPkg.homepage}).
state: PackageStates.INSTALLED,
installed_versions: addInstalledVersion(pkg.installed_versions, versionToInstall)
});
notificationStore.add({
message: `Package ${pkg.full_name} v${versionToInstall} has been installed.`
});
} catch (error) {
let message = "Unknown Error";
if (error instanceof Error) message = error.message;
trackInstallFailed(pkg.full_name, message || "unknown");
//FIXME: probably need a refresh package state function instead of this
updatePackage(pkg.full_name, { state: originalState });
notificationStore.add({
message: `Package ${pkg.full_name} v${versionToInstall} failed to install.`,
type: NotificationType.ERROR
});
} finally {
fakeTimer && clearTimeout(fakeTimer);
updatePackage(pkg.full_name, { install_progress_percentage: 100 });

View file

@ -1,24 +1,25 @@
<script lang="ts">
import '$appcss';
import { t } from '$libs/translations';
import "$appcss";
import { t } from "$libs/translations";
import { page } from '$app/stores';
import { page } from "$app/stores";
// import PageHeader from '$components/page-header/page-header.svelte';
import PackageBanner from '$components/package-banner/package-banner.svelte';
import PackageBanner from "$components/package-banner/package-banner.svelte";
// import SuggestedPackages from '$components/suggested-packages/suggested-packages.svelte';
import Tabs from '@tea/ui/tabs/tabs.svelte';
import type { Tab } from '@tea/ui/types';
import Bottles from '@tea/ui/bottles/bottles.svelte';
import PackageMetas from '@tea/ui/package-metas/package-metas.svelte';
import Markdown from '@tea/ui/markdown/markdown.svelte';
import Tabs from "@tea/ui/tabs/tabs.svelte";
import type { Tab } from "@tea/ui/types";
import Bottles from "@tea/ui/bottles/bottles.svelte";
import PackageMetas from "@tea/ui/package-metas/package-metas.svelte";
import Markdown from "@tea/ui/markdown/markdown.svelte";
// import PackageSnippets from '@tea/ui/package-snippets/package-snippets.svelte';
import Preloader from '@tea/ui/Preloader/Preloader.svelte';
import Preloader from "@tea/ui/Preloader/Preloader.svelte";
/** @type {import('./$types').PageData} */
export let data: { slug:string, content:string, title:string };
export let data: { slug: string; content: string; title: string };
import { packagesStore } from '$libs/stores';
import { onMount } from 'svelte';
import { packagesStore } from "$libs/stores";
import { onMount } from "svelte";
import NotificationBar from "$components/notification-bar/notification-bar.svelte";
const { packageList } = packagesStore;
@ -27,10 +28,10 @@
// let reviews: Review[];
$: bottles = pkg?.bottles || [];
$: versions = [...new Set(bottles.map((b) => b.version))];
$: readme = pkg?.readme_md || '';
$: readme = pkg?.readme_md || "";
$: tabs = [
readme !== '' && {
readme !== "" && {
label: $t("common.details"),
component: Markdown,
props: { pkg, source: readme }
@ -50,17 +51,23 @@
onMount(() => {
packagesStore.syncPackageData(pkg);
})
});
</script>
<header class="mx-16 py-5 mb-10 text-gray border border-x-0 border-t-0">
<header class="text-gray mx-16 mb-4 border border-x-0 border-t-0 py-5">
<a class="hover:text-white hover:opacity-80" href="/">{$t("common.home")}</a>
>
{#if tab !== "all"}
<a class="hover:text-white hover:opacity-80" href="/?tab={tab || "all"}">{$t(`tags.${tab}`) || "all"}</a>
<a class="hover:text-white hover:opacity-80" href="/?tab={tab || 'all'}"
>{$t(`tags.${tab}`) || "all"}</a
>
>
{/if}
<span class="text-white">{pkg?.full_name}</span>
</header>
<div class="mx-16 mb-4">
<NotificationBar />
</div>
{#if pkg}
<div class="px-16">
<section>
@ -94,5 +101,5 @@
{/if} -->
</div>
{:else}
<Preloader/>
<Preloader />
{/if}

View file

@ -1,20 +1,28 @@
<script lang="ts">
import "../app.css";
// import { NotificationType } from "../types";
import { NotificationType } from "../types";
import type { Notification } from "../types";
export let notification: Notification;
export let onClose: () => void;
const styles = {
[NotificationType.MESSAGE]: "message-notification",
[NotificationType.ERROR]: "error-notification",
[NotificationType.ACTION_BANNER]: "action-banner-notification"
};
const notificationClass = styles[notification.type];
</script>
<div class=" flex w-full items-center justify-between bg-accent px-4 py-2">
<div class="text-white">{notification.message}</div>
<div class="flex w-full items-center justify-between px-4 py-2 {notificationClass}">
<div>{notification.message}</div>
<div class="flex items-center gap-4">
{#if notification.callback}
<button
class="h-10 w-32 rounded-sm bg-white text-accent"
class="h-10 w-32 rounded-sm bg-white"
on:click={() => {
if (notification.callback) {
notification.callback();
@ -25,3 +33,21 @@
<button class="icon-tea-x-btn mt-1 text-xs" on:click={onClose} />
</div>
</div>
<style>
/* FIXME: is there a better way to integrate this with tailwind? */
.error-notification {
background-color: #ff4100;
color: #ffffff;
}
.message-notification {
background-color: #8000ff;
color: #ffffff;
}
.alert-notification {
background-color: #8000ff;
color: #ffffff;
}
</style>

View file

@ -117,7 +117,8 @@ export interface ListActionItem {
export enum NotificationType {
MESSAGE,
ACTION_BANNER
ACTION_BANNER,
ERROR
}
export interface Notification {
id: string;