Add colours and Sentry feedback form

This commit is contained in:
Jade Ellis 2024-09-10 04:11:45 +01:00
parent 3ff04eba7e
commit d6da36314d
No known key found for this signature in database
GPG key ID: 8705A2A3EBF77BD2
10 changed files with 294 additions and 147 deletions

View file

@ -1,5 +1,5 @@
import { SENTRY_DSN } from '$lib/config';
import { init as initSentry, handleErrorWithSentry, makeBrowserOfflineTransport, makeFetchTransport } from '@sentry/sveltekit';
import { init as initSentry, handleErrorWithSentry, makeBrowserOfflineTransport, makeFetchTransport, feedbackIntegration } from '@sentry/sveltekit';
initSentry({
dsn: SENTRY_DSN,
@ -14,8 +14,9 @@ initSentry({
// sessions when an error occurs.
replaysOnErrorSampleRate: 1.0,
// If you don't want to use Session Replay, just remove the line below:
// integrations: [replayIntegration()],
integrations: [feedbackIntegration({
autoInject: false,
})],
// To enable offline events caching, use makeBrowserOfflineTransport to wrap
// existing transports and queue events using the browsers' IndexedDB storage

View file

@ -33,6 +33,11 @@
--code-background-color: #0d1117;
--code-color: #fff;
--color-primary: hsl(230, 50%, 90%);
--color-secondary: hsl(230, 50%, 10%);
--color-tertiary: hsl(290, 80%, 20%);
--color-accent: hsl(227, 80%, 20%);
--color-red: #e93147;
--color-orange: #ec7500;
--color-yellow: #e0ac00;
@ -60,6 +65,11 @@
--font-color: rgba(255, 255, 255, .87);
--font-color-contrast: rgba(0, 0, 0, .87);
--font-color-secondary: rgba(255, 255, 255, .6);
--color-primary: hsl(230, 50%, 10%);
--color-secondary: hsl(230, 50%, 90%);
--color-tertiary: hsl(290, 80%, 80%);
--color-accent: hsl(195, 80%, 80%);
--color-red: #fb464c;
--color-orange: #e9973f;
@ -109,7 +119,8 @@ html {
body {
padding: 0;
margin: 0
margin: 0;
min-height: 100vh;
}
iframe,
@ -125,6 +136,13 @@ svg {
display: block;
}
a {
color: var(--color-accent);
}
a:visited {
color: var(--color-tertiary);
}
.container {
--container-max-width: var(--page-width);
--padding-x: var(--spacing);
@ -176,3 +194,18 @@ svg {
}
button {
display: inline-block;
color: var(--color-primary);
background: var(--color-accent);
border-radius: 4px;
margin: 8px 8px 8px 0px;
padding: 12px 24px;
border: solid 2px var(--color-accent);
}
.secondary {
border: solid 2px var(--color-accent);
color: var(--color-accent);
background: transparent;
}

View file

@ -5,7 +5,7 @@
import { bookmarkify, parseMeta } from "./bookmarklets";
import type { Config } from "./config";
import { init } from "$lib/workers/terser";
import { SITE_URL } from '$lib/metadata';
import { SITE_URL } from "$lib/metadata";
/** @type {import('./$types').Snapshot<string>} */
export const snapshot = {
@ -13,7 +13,7 @@
restore: (v: string) => (value = v),
};
let minify = init().minify
let minify = init().minify;
let value = "";
let output = "";
@ -26,7 +26,7 @@
}
}
let contentAttributes = {"aria-label": "Bookmarklet editor"}
let contentAttributes = { "aria-label": "Bookmarklet editor" };
$: progress = process(value);
</script>
@ -36,34 +36,45 @@
description="Make booklets in your browser with this tool. Make handy shortcuts to save time."
canonical={SITE_URL + "/bookmarklets"}
/>
<h1>Bookmarklet Maker</h1>
<Editor
{value}
on:change={(e) => (value = e.detail)}
lang={javascript()}
{contentAttributes}
>
<div slot="header" class="code-header">Input</div>
</Editor>
<h2>Output</h2>
{#await progress}
<p>...waiting</p>
{:catch error}
<p style="color: red">{error.message}</p>
{/await}
<label for="output">Bookmarklet code</label>
<textarea name="output" id="output" class="output card" rows="1" value={output} readonly
></textarea>
<main class="main container" id="page-content">
<h1>Bookmarklet Maker</h1>
<Editor
{value}
on:change={(e) => (value = e.detail)}
lang={javascript()}
{contentAttributes}
>
<div slot="header" class="code-header">Input</div>
</Editor>
<!-- <Editor readonly={true} /> -->
<p>
Bookmark this link: <a href={output}>{options.name || "My Bookmarklet"}</a>
</p>
<p>
Either drag the link to your bookmarlets bar or, on FireFox, right click and
select "Bookmark Link".
</p>
<h2>Output</h2>
{#await progress}
<p>...waiting</p>
{:catch error}
<p style="color: red">{error.message}</p>
{/await}
<label for="output">Bookmarklet code</label>
<textarea
name="output"
id="output"
class="output card"
rows="1"
value={output}
readonly
></textarea>
<!-- <Editor readonly={true} /> -->
<p>
Bookmark this link: <a href={output}
>{options.name || "My Bookmarklet"}</a
>
</p>
<p>
Either drag the link to your bookmarlets bar or, on FireFox, right click
and select "Bookmark Link".
</p>
</main>
<style>
.code-header {

View file

@ -3,7 +3,7 @@
import { javascript } from "@codemirror/lang-javascript";
import SvelteSeo from "svelte-seo";
import { init } from "$lib/workers/terser";
import { SITE_URL } from '$lib/metadata';
import { SITE_URL } from "$lib/metadata";
/** @type {import('./$types').Snapshot<string>} */
export const snapshot = {
@ -11,24 +11,24 @@
restore: (v: string) => (value = v),
};
let minify = init().minify
let minify = init().minify;
let value = "";
let output = "";
async function process(str: string) {
if (value === "") {
output = "";
return
return;
}
let result = await minify(str)
let result = await minify(str);
if (typeof result.code == "string") {
output = result.code
output = result.code;
} else {
console.error(result)
console.error(result);
}
}
let contentAttributes = {"aria-label": "Javascript editor"}
let contentAttributes = { "aria-label": "Javascript editor" };
$: progress = process(value);
</script>
@ -38,26 +38,34 @@
description="Reduce JavaScript code size with this handy online tool. It's easy to minify your JavaScript code."
canonical={SITE_URL + "/javascript-minifier"}
/>
<h1>Javascript Minifier</h1>
<Editor
{value}
on:change={(e) => (value = e.detail)}
lang={javascript()}
{contentAttributes}
>
<div slot="header" class="code-header">Input</div>
</Editor>
<h2>Output</h2>
{#await progress}
<p>...waiting</p>
{:catch error}
<p style="color: red">{error.message}</p>
{/await}
<label for="output">Minified code</label>
<textarea name="output" id="output" class="output card" rows="1" value={output} readonly
></textarea>
<main class="main container" id="page-content">
<h1>Javascript Minifier</h1>
<Editor
{value}
on:change={(e) => (value = e.detail)}
lang={javascript()}
{contentAttributes}
>
<div slot="header" class="code-header">Input</div>
</Editor>
<h2>Output</h2>
{#await progress}
<p>...waiting</p>
{:catch error}
<p style="color: red">{error.message}</p>
{/await}
<label for="output">Minified code</label>
<textarea
name="output"
id="output"
class="output card"
rows="1"
value={output}
readonly
></textarea>
</main>
<style>
.code-header {

View file

@ -0,0 +1,78 @@
<script lang="ts">
import { page } from "$app/stores";
import * as Sentry from "@sentry/sveltekit";
import { onMount } from "svelte";
import SvelteSeo from "svelte-seo";
const { status, error } = $page;
const message = error?.message || "Hmm";
const title = `${status}: ${message}`;
let sentryElement: HTMLDivElement;
let openForm = () => {};
onMount(async () => {
const feedback = Sentry.getFeedback({
el: sentryElement,
});
if (!feedback) {
return;
}
// console.log("feedback", feedback);
const form = await feedback.createForm({});
form.appendToDom();
form.open();
openForm = async () => {
form.open();
};
});
</script>
<SvelteSeo {title} />
<main class="main container" id="page-content">
<div class="wrapper">
<h1>{title}</h1>
<div bind:this={sentryElement} class="feedback"></div>
<button on:click={openForm}>Send Feedback</button>
<button class="secondary" on:click={()=> window.location.reload()}>Reload</button>
<!-- <div role="doc-subtitle">{status}</div> -->
</div>
</main>
<style>
main {
display: grid;
place-items: center;
}
.wrapper {
flex-grow: 2;
width: 40vw;
max-width: 500px;
margin: 0 auto;
/* display: flex;
flex-direction: column;
align-items: center;
gap: var(--spacing);
margin: 48px auto;
max-width: 320px;
padding: 3rem 0.5rem; */
}
h1 {
margin: 0;
font-size: 4em;
/* font-weight: 100; */
}
/* [role="doc-subtitle"] {
padding-block-start: 0;
font-size: 2em;
font-weight: 600;
} */
:global(#sentry-feedback) {
--dialog-inset: auto auto 0;
}
p {
width: 95%;
font-size: 1.5em;
line-height: 1.4;
}
</style>

View file

@ -11,7 +11,4 @@
<meta property="og:site_name" content={SITE_TITLE}>
</svelte:head>
<Nav />
<main class="main container" id="page-content">
<slot />
</main>
<slot />

View file

@ -6,15 +6,27 @@
</script>
<svelte:head>
<link rel="alternate" type="application/rss+xml" title={SITE_TITLE} href={SITE_URL + "/blog/rss.xml"}>
<link rel="alternate" type="application/feed+json" title={SITE_TITLE} href={SITE_URL + "/blog/feed.json"}>
<link
rel="alternate"
type="application/rss+xml"
title={SITE_TITLE}
href={SITE_URL + "/blog/rss.xml"}
/>
<link
rel="alternate"
type="application/feed+json"
title={SITE_TITLE}
href={SITE_URL + "/blog/feed.json"}
/>
</svelte:head>
<SvelteSeo
title="Jade Ellis"
description="Student, Creative & Computer Scientist. See what I'm doing."
canonical="https://jade.ellis.link"
title="Jade Ellis"
description="Student, Creative & Computer Scientist. See what I'm doing."
canonical="https://jade.ellis.link"
/>
<Hero />
<Homepage />
<main class="main container" id="page-content">
<Hero />
<Homepage />
</main>

View file

@ -53,44 +53,46 @@
<SvelteSeo title="Jade's Blog - Posts" canonical={SITE_URL + "/blog"} />
<section role="feed" class="h-feed" id="feed">
<h1 class="p-name">
<a
aria-hidden="true"
tabindex="-1"
class="u-url permalink"
href={SITE_URL + "/blog#feed"}>#</a
>Jade's Blog - Posts
</h1>
{#each pages as post, index}
<article
aria-posinset={index + 1}
aria-setsize={pages.length}
class="h-entry"
>
<div class="content" data-sveltekit-preload-data="hover">
<h2>
<a class="u-url p-name" href="/blog/{post.canonical}">
{post.title}
</a>
</h2>
<span class="quiet"
><time class="dt-published" datetime={post.date}
>{new Date(post.date).toLocaleDateString()}</time
></span
>
{#if post.description}
<p class="p-summary">{post.description}</p>
{/if}
</div>
</article>
{:else}
<p>No posts yet!</p>
{/each}
<!-- {#if showPosts < postCount}
<main class="main container" id="page-content">
<section role="feed" class="h-feed" id="feed">
<h1 class="p-name">
<a
aria-hidden="true"
tabindex="-1"
class="u-url permalink"
href={SITE_URL + "/blog#feed"}>#</a
>Jade's Blog - Posts
</h1>
{#each pages as post, index}
<article
aria-posinset={index + 1}
aria-setsize={pages.length}
class="h-entry"
>
<div class="content" data-sveltekit-preload-data="hover">
<h2>
<a class="u-url p-name" href="/blog/{post.canonical}">
{post.title}
</a>
</h2>
<span class="quiet"
><time class="dt-published" datetime={post.date}
>{new Date(post.date).toLocaleDateString()}</time
></span
>
{#if post.description}
<p class="p-summary">{post.description}</p>
{/if}
</div>
</article>
{:else}
<p>No posts yet!</p>
{/each}
<!-- {#if showPosts < postCount}
<button type="submit" on:click={handleClick}>See more {H_ELLIPSIS_ENTITY}</button>
{/if} -->
</section>
</section>
</main>
<style>
.permalink {

View file

@ -48,11 +48,11 @@
});
gtag("event", "share", {
"share_url": url.href,
"share_title": data.post.title,
"share_button": "article_top",
"method": "navigator_share",
"content_type": "article",
share_url: url.href,
share_title: data.post.title,
share_button: "article_top",
method: "navigator_share",
content_type: "article",
});
} catch (error: any) {
if (error.toString().includes("AbortError")) {
@ -176,42 +176,44 @@
}}
/>
<article class="h-entry">
<h1 id="title" class="p-name">{data.post.title}</h1>
<aside>
<a class="u-url ib" href={canonical}
>Published on <time
class="dt-published ib"
datetime={data.post.date}
>{new Date(data.post.date).toLocaleDateString()}</time
></a
>
<span class="author p-author h-card vcard ib">
by <img
loading="lazy"
style="display: none;"
src={defaultAuthor.image}
class="avatar avatar-96 photo u-photo"
/><a class="u-url url fn n p-name" href={defaultAuthor.url}
>{defaultAuthor.name}</a
></span
>
· <span class="reading-time ib">{data.post.readingTime.text}</span>
{#if webShareAPISupported}
· <button class="link" on:click={handleWebShare}>Share</button>
{/if}
</aside>
<Toc headings={data.post.headings} />
<!-- {#await GhReleasesDownload}
<main class="main container" id="page-content">
<article class="h-entry">
<h1 id="title" class="p-name">{data.post.title}</h1>
<aside>
<a class="u-url ib" href={canonical}
>Published on <time
class="dt-published ib"
datetime={data.post.date}
>{new Date(data.post.date).toLocaleDateString()}</time
></a
>
<span class="author p-author h-card vcard ib">
by <img
loading="lazy"
style="display: none;"
src={defaultAuthor.image}
class="avatar avatar-96 photo u-photo"
/><a class="u-url url fn n p-name" href={defaultAuthor.url}
>{defaultAuthor.name}</a
></span
>
· <span class="reading-time ib">{data.post.readingTime.text}</span>
{#if webShareAPISupported}
· <button class="link" on:click={handleWebShare}>Share</button>
{/if}
</aside>
<Toc headings={data.post.headings} />
<!-- {#await GhReleasesDownload}
{:then component}
<svelte:component this={component} releaseData={data.ghReleaseData} />
{/await} -->
<div class="e-content">
<svelte:component this={data.component} />
</div>
</article>
<div class="e-content">
<svelte:component this={data.component} />
</div>
</article>
</main>
<style>
aside {

View file

@ -18,15 +18,18 @@
description={data.post.description}
canonical={SITE_URL + "/projects/" + data.post.slug}
/>
<h1>{data.post.title}</h1>
<!-- {#await GhReleasesDownload}
<main class="main container" id="page-content">
<h1>{data.post.title}</h1>
<!-- {#await GhReleasesDownload}
{:then component}
<svelte:component this={component} releaseData={data.ghReleaseData} />
{/await} -->
{#if data.ghReleaseData}
<GhReleasesDownload releaseData={data.ghReleaseData} />
{/if}
{#if data.ghReleaseData}
<GhReleasesDownload releaseData={data.ghReleaseData} />
{/if}
<svelte:component this={data.component} />
<svelte:component this={data.component} />
</main>