Refactor internal error page

- copies most things from `ProblemLoadingRepo`
- `maybeGetContext` function now necessary for project selector
- throw expected error in layout.ts if loading project fails
This commit is contained in:
Mattias Granlund 2024-04-03 21:50:02 +02:00
parent ea9cf23997
commit d021eb51a4
5 changed files with 76 additions and 23 deletions

View File

@ -3,11 +3,11 @@
import Select from './Select.svelte';
import SelectItem from './SelectItem.svelte';
import { ProjectService, Project } from '$lib/backend/projects';
import { getContext } from '$lib/utils/context';
import { getContext, maybeGetContext } from '$lib/utils/context';
import { goto } from '$app/navigation';
const projectService = getContext(ProjectService);
const project = getContext(Project);
const project = maybeGetContext(Project);
const projects = projectService.projects;

View File

@ -0,0 +1,54 @@
<script lang="ts">
import DecorativeSplitView from './DecorativeSplitView.svelte';
import ProjectSwitcher from './ProjectSwitcher.svelte';
import loadErrorSvg from '$lib/assets/illustrations/load-error.svg?raw';
import Icon from '$lib/components/Icon.svelte';
export let error: any = undefined;
</script>
<DecorativeSplitView img={loadErrorSvg}>
<div class="problem" data-tauri-drag-region>
<p class="problem__title text-base-body-18 text-bold" data-tauri-drag-region>
There was a problem loading the app
</p>
<div class="problem__error text-base-body-12">
<Icon name="error" color="error" />
{error ? error : 'An unknown error occurred'}
</div>
<div class="problem__switcher">
<ProjectSwitcher />
</div>
</div>
</DecorativeSplitView>
<style lang="postcss">
.problem__title {
color: var(--clr-scale-ntrl-30);
margin-bottom: var(--size-12);
}
.problem__switcher {
text-align: right;
margin-top: var(--size-24);
}
.problem__error {
display: flex;
color: var(--clr-scale-ntrl-0);
gap: var(--size-12);
padding: var(--size-20);
background-color: var(--clr-theme-err-container);
border-radius: var(--radius-m);
margin-bottom: var(--size-12);
}
.remove-project-btn {
display: flex;
justify-content: flex-end;
padding-bottom: var(--size-24);
border-bottom: 1px dashed var(--clr-scale-ntrl-60);
}
</style>

View File

@ -19,6 +19,13 @@ export function getContext<T extends Class>(key: T): InstanceType<T> {
return instance;
}
/**
* Optional getter that returns an instance of the parameter type
*/
export function maybeGetContext<T extends Class>(key: T): InstanceType<T> | undefined {
return svelteGetContext<InstanceType<T> | undefined>(key);
}
/**
* Getter that returns an readable store of the parameter type
*/

View File

@ -1,29 +1,12 @@
<script lang="ts">
import SomethingWentWrong from '$lib/components/SomethingWentWrong.svelte';
import { page } from '$app/stores';
$: if ($page.error) {
console.error($page.url.toString(), $page.error);
} else {
console.log($page.url.toString(), $page.status.toString());
}
$: message = $page.error
? $page.error.message
: $page.status === 404
? 'Page not found'
: 'Something went wrong';
: 'Unknown error';
</script>
<div class="wrapper">
<h1 class="text-base-18 text-semibold">
{message}
</h1>
</div>
<style>
.wrapper {
display: flex;
flex: 1 1 0%;
height: 100%;
}
</style>
<SomethingWentWrong error={message} />

View File

@ -4,7 +4,9 @@ import { getHeads } from '$lib/stores/head';
import { RemoteBranchService } from '$lib/stores/remoteBranches';
import { BranchController } from '$lib/vbranches/branchController';
import { BaseBranchService, VirtualBranchService } from '$lib/vbranches/branchStoresCache';
import { error } from '@sveltejs/kit';
import { map } from 'rxjs';
import type { Project } from '$lib/backend/projects';
export const prerender = false;
@ -21,7 +23,14 @@ export async function load({ params, parent }) {
// Getting the project should be one of few, if not the only await expression in
// this function. It delays drawing the page, but currently the benefit from having this
// synchronously available are much greater than the cost.
const project = await projectService.getProject(projectId);
let project: Project | undefined = undefined;
try {
project = await projectService.getProject(projectId);
} catch (err: any) {
throw error(400, {
message: err.message
});
}
const fetches$ = getFetchNotifications(projectId);
const heads$ = getHeads(projectId);