Skip to content

Commit d560b75

Browse files
committed
ask for name (optional) in submission form
1 parent 774c43b commit d560b75

4 files changed

Lines changed: 52 additions & 16 deletions

File tree

src/components/SuggestionForm.svelte

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
<script lang="ts">
2+
import { browser } from '$app/environment'
23
import { page } from '$app/state'
34
import { resize_textarea } from '$lib/client/utils'
45
import { faCheckCircle, faWarning } from '@fortawesome/free-solid-svg-icons'
56
import { tick } from 'svelte'
67
import Fa from 'svelte-fa'
78
9+
const saved_name = browser ? (window.localStorage.getItem('name') ?? '') : ''
10+
811
let title = $state('')
912
let body = $state('')
13+
let name = $state(saved_name)
14+
1015
let error = $state('')
1116
let url = $state('')
1217
let sending = $state(false)
@@ -18,10 +23,16 @@
1823
error = ''
1924
url = ''
2025
26+
if (name) {
27+
window.localStorage.setItem('name', name)
28+
} else {
29+
window.localStorage.removeItem('name')
30+
}
31+
2132
try {
2233
const res = await fetch('/api/issue', {
2334
method: 'POST',
24-
body: JSON.stringify({ title, body, url: page.url.href }),
35+
body: JSON.stringify({ title, body, url: page.url.href, name }),
2536
})
2637
2738
const res_json = await res.json()
@@ -57,15 +68,31 @@
5768
<form onsubmit={create_issue}>
5869
<div class="form-group">
5970
<label for="title">Short summary</label>
60-
<input type="text" id="title" bind:value={title} required />
71+
<input
72+
type="text"
73+
id="title"
74+
class="full-width"
75+
bind:value={title}
76+
required
77+
/>
6178
</div>
6279

6380
<div class="form-group">
6481
<label for="body">Details</label>
65-
<textarea id="body" {@attach resize_textarea} bind:value={body} required
82+
<textarea
83+
id="body"
84+
{@attach resize_textarea}
85+
bind:value={body}
86+
required
87+
class="full-width"
6688
></textarea>
6789
</div>
6890

91+
<div class="form-group">
92+
<label for="name">Your name (optional)</label>
93+
<input type="text" id="name" bind:value={name} />
94+
</div>
95+
6996
<button class="button" disabled={sending}>
7097
{#if sending}
7198
Submitting...
@@ -102,11 +129,6 @@
102129
color: var(--error-color);
103130
}
104131
105-
input,
106-
textarea {
107-
width: 100%;
108-
}
109-
110132
.form-group {
111133
margin-bottom: 1rem;
112134
}

src/routes/api/issue/+server.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
GITHUB_OWNER,
1010
GITHUB_REPO,
1111
TITLE_MAX_LENGTH,
12+
NAME_MAX_LENGTH,
1213
} from './config'
1314
import { flag_violation, is_blocked, has_profanity, rate_limit } from '$lib/server/redis'
1415

@@ -36,17 +37,18 @@ export const POST = async (event) => {
3637

3738
if ('error' in data) return json({ error: data.error }, { status: 400 })
3839

39-
const { title, body, url } = data
40+
const { title, body, url, name } = data
4041

4142
if (has_profanity(title, body)) {
4243
await flag_violation(ip, 'profanity')
4344
return json({ error: 'Profanity detected' }, { status: 400 })
4445
}
4546

46-
const full_body =
47-
body +
48-
'\n\n---\n' +
49-
`This issue has been created via the submission form on ${url}`
47+
const footer = name
48+
? `This issue has been created by **${name}** via the submission form on ${url}`
49+
: `This issue has been created via the submission form on ${url}`
50+
51+
const full_body = `${body}\n\n---\n${footer}`
5052

5153
try {
5254
const octokit = await app.getInstallationOctokit(Number(GITHUB_INSTALLATION_ID))
@@ -67,15 +69,17 @@ export const POST = async (event) => {
6769

6870
async function parse_data(
6971
request: Request,
70-
): Promise<{ error: string } | { title: string; body: string; url: string }> {
72+
): Promise<
73+
{ error: string } | { title: string; body: string; url: string; name: string }
74+
> {
7175
let data
7276
try {
7377
data = await request.json()
7478
} catch (_) {
7579
return { error: 'Invalid request body' }
7680
}
7781

78-
const { title, body, url } = data
82+
const { title, body, url, name = '' } = data
7983

8084
if (!title) return { error: 'Title required' }
8185
if (!body) return { error: 'Body required' }
@@ -84,6 +88,7 @@ async function parse_data(
8488
if (typeof title !== 'string') return { error: 'Title must be a string' }
8589
if (typeof body !== 'string') return { error: 'Body must be a string' }
8690
if (typeof url !== 'string') return { error: 'URL must be a string' }
91+
if (typeof name !== 'string') return { error: 'Name must be a string' }
8792

8893
if (title.length > TITLE_MAX_LENGTH) {
8994
return { error: `Title must have at most ${TITLE_MAX_LENGTH} characters` }
@@ -96,5 +101,9 @@ async function parse_data(
96101
return { error: 'URL must be a valid URL' }
97102
}
98103

99-
return { title, body, url }
104+
if (name.length > NAME_MAX_LENGTH) {
105+
return { error: `Name must have at most ${NAME_MAX_LENGTH} characters` }
106+
}
107+
108+
return { title, body, url, name }
100109
}

src/routes/api/issue/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ export const GITHUB_OWNER = 'ScriptRaccoon'
44
export const GITHUB_REPO = 'CatDat'
55
export const TITLE_MAX_LENGTH = 50
66
export const BODY_MAX_LENGTH = 10000
7+
export const NAME_MAX_LENGTH = 50

src/routes/app.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,10 @@ button:focus-visible {
202202
white-space: nowrap;
203203
}
204204

205+
.full-width {
206+
width: 100%;
207+
}
208+
205209
summary {
206210
cursor: pointer;
207211
width: fit-content;

0 commit comments

Comments
 (0)