feat: add names/pronouns/field entries on enter

This commit is contained in:
Sam 2023-03-31 00:11:28 +02:00
parent b1e267cb29
commit ba48ba0eb2
Signed by: sam
GPG key ID: B4EF20DDE721CAA1
5 changed files with 97 additions and 49 deletions

View file

@ -6,6 +6,7 @@
export let tooltip: string; export let tooltip: string;
export let active: boolean = false; export let active: boolean = false;
export let disabled: boolean = false; export let disabled: boolean = false;
export let type: string | undefined = undefined;
export let click: ((e: MouseEvent) => void) | undefined = undefined; export let click: ((e: MouseEvent) => void) | undefined = undefined;
export let href: string | undefined = undefined; export let href: string | undefined = undefined;
@ -14,6 +15,6 @@
</script> </script>
<Tooltip target={button} placement="top">{tooltip}</Tooltip> <Tooltip target={button} placement="top">{tooltip}</Tooltip>
<Button {color} {active} {disabled} {href} on:click={click} bind:inner={button}> <Button {type} {color} {active} {disabled} {href} on:click={click} bind:inner={button}>
<Icon name={icon} /> <Icon name={icon} />
</Button> </Button>

View file

@ -10,7 +10,9 @@
let newEntry: string = ""; let newEntry: string = "";
const addEntry = () => { const addEntry = (event: Event) => {
event.preventDefault();
field.entries = [...field.entries, { value: newEntry, status: WordStatus.Okay }]; field.entries = [...field.entries, { value: newEntry, status: WordStatus.Okay }];
newEntry = ""; newEntry = "";
}; };
@ -61,8 +63,8 @@
/> />
{/each} {/each}
<div class="input-group m-1"> <form class="input-group m-1" on:submit={addEntry}>
<input type="text" class="form-control" placeholder="New entry" bind:value={newEntry} /> <input type="text" class="form-control" placeholder="New entry" bind:value={newEntry} />
<IconButton color="success" icon="plus" tooltip="Add entry" click={() => addEntry()} /> <IconButton color="success" icon="plus" tooltip="Add entry" />
</div> </form>
</div> </div>

View file

@ -20,6 +20,7 @@
Modal, Modal,
ModalBody, ModalBody,
ModalFooter, ModalFooter,
Popover,
} from "sveltestrap"; } from "sveltestrap";
import { encode } from "base64-arraybuffer"; import { encode } from "base64-arraybuffer";
import { apiFetchClient, fastFetchClient } from "$lib/api/fetch"; import { apiFetchClient, fastFetchClient } from "$lib/api/fetch";
@ -59,7 +60,6 @@
let newName = ""; let newName = "";
let newPronouns = ""; let newPronouns = "";
let newPronounsDisplay = "";
let newLink = ""; let newLink = "";
let modified = false; let modified = false;
@ -169,21 +169,38 @@
fields[newIndex] = temp; fields[newIndex] = temp;
}; };
const addName = () => { const addName = (event: Event) => {
event.preventDefault();
names = [...names, { value: newName, status: WordStatus.Okay }]; names = [...names, { value: newName, status: WordStatus.Okay }];
newName = ""; newName = "";
}; };
const addPronouns = () => { const addPronouns = (event: Event) => {
pronouns = [ event.preventDefault();
...pronouns,
{ pronouns: newPronouns, display_text: newPronounsDisplay || null, status: WordStatus.Okay }, if (newPronouns in data.pronouns) {
]; const fullSet = data.pronouns[newPronouns];
pronouns = [
...pronouns,
{
pronouns: fullSet.pronouns.join("/"),
display_text: fullSet.display || null,
status: WordStatus.Okay,
},
];
} else {
pronouns = [
...pronouns,
{ pronouns: newPronouns, display_text: null, status: WordStatus.Okay },
];
}
newPronouns = ""; newPronouns = "";
newPronounsDisplay = "";
}; };
const addLink = () => { const addLink = (event: Event) => {
event.preventDefault();
links = [...links, newLink]; links = [...links, newLink];
newLink = ""; newLink = "";
}; };
@ -375,9 +392,10 @@
</FormGroup> </FormGroup>
</div> </div>
<div> <div>
<FormGroup floating label="Bio ({bio.length}/{MAX_DESCRIPTION_LENGTH})"> <div class="form">
<textarea style="min-height: 100px;" class="form-control" bind:value={bio} /> <label for="bio"><strong>Bio ({bio.length}/{MAX_DESCRIPTION_LENGTH})</strong></label>
</FormGroup> <textarea class="form-control" style="height: 200px;" id="bio" bind:value={bio} />
</div>
<p class="text-muted mt-3"> <p class="text-muted mt-3">
<Icon name="info-circle-fill" aria-hidden /> Your bio supports limited <Icon name="info-circle-fill" aria-hidden /> Your bio supports limited
<a <a
@ -402,10 +420,10 @@
remove={() => removeName(index)} remove={() => removeName(index)}
/> />
{/each} {/each}
<div class="input-group m-1"> <form class="input-group m-1" on:submit={addName}>
<input type="text" class="form-control" bind:value={newName} /> <input type="text" class="form-control" bind:value={newName} />
<IconButton color="success" icon="plus" tooltip="Add name" click={() => addName()} /> <IconButton type="submit" color="success" icon="plus" tooltip="Add name" />
</div> </form>
</div> </div>
<div class="col-md"> <div class="col-md">
<h4>Links</h4> <h4>Links</h4>
@ -420,10 +438,10 @@
/> />
</div> </div>
{/each} {/each}
<div class="input-group m-1"> <form class="input-group m-1" on:submit={addLink}>
<input type="text" class="form-control" bind:value={newLink} /> <input type="text" class="form-control" bind:value={newLink} />
<IconButton color="success" icon="plus" tooltip="Add link" click={() => addLink()} /> <IconButton type="submit" color="success" icon="plus" tooltip="Add link" />
</div> </form>
</div> </div>
</div> </div>
<div class="row m-1"> <div class="row m-1">
@ -437,27 +455,43 @@
remove={() => removePronoun(index)} remove={() => removePronoun(index)}
/> />
{/each} {/each}
<div class="input-group m-1"> <form class="input-group m-1" on:submit={addPronouns}>
<input <input
type="text" type="text"
class="form-control" class="form-control"
placeholder="Full set (e.g. it/it/its/its/itself)" placeholder="New pronouns"
bind:value={newPronouns} bind:value={newPronouns}
required required
/> />
<input
type="text"
class="form-control"
placeholder="Optional display text (e.g. it/its)"
bind:value={newPronounsDisplay}
/>
<IconButton <IconButton
type="submit"
color="success" color="success"
icon="plus" icon="plus"
tooltip="Add pronouns" tooltip="Add pronouns"
click={() => addPronouns()} disabled={newPronouns === ""}
/> />
</div> <form class="input-group m-1" on:submit={addPronouns}>
<input
type="text"
class="form-control"
placeholder="New pronouns"
bind:value={newPronouns}
required
/>
<IconButton
type="submit"
color="success"
icon="plus"
tooltip="Add pronouns"
disabled={newPronouns === ""}
/>
<Button id="pronouns-help" color="secondary"><Icon name="question" /></Button>
<Popover target="pronouns-help" placement="bottom">
For common pronouns, the short form (e.g. "she/her" or "he/him") is enough; for less
common pronouns, you will have to use all five forms (e.g. "ce/cir/cir/cirs/cirself").
</Popover>
</form>
</form>
</div> </div>
</div> </div>
<hr /> <hr />

View file

@ -1,7 +1,10 @@
import type { MeUser, APIError, Member } from "$lib/api/entities"; import type { MeUser, APIError, Member, PronounsJson } from "$lib/api/entities";
import { apiFetchClient } from "$lib/api/fetch"; import { apiFetchClient } from "$lib/api/fetch";
import { error } from "@sveltejs/kit"; import { error } from "@sveltejs/kit";
import pronounsRaw from "$lib/pronouns.json";
const pronouns = pronounsRaw as PronounsJson;
export const ssr = false; export const ssr = false;
export const load = async ({ params }) => { export const load = async ({ params }) => {
@ -12,6 +15,7 @@ export const load = async ({ params }) => {
return { return {
user, user,
member, member,
pronouns: pronouns.autocomplete,
}; };
} catch (e) { } catch (e) {
throw error((e as APIError).code, (e as APIError).message); throw error((e as APIError).code, (e as APIError).message);

View file

@ -148,12 +148,16 @@
fields[newIndex] = temp; fields[newIndex] = temp;
}; };
const addName = () => { const addName = (event: Event) => {
event.preventDefault();
names = [...names, { value: newName, status: WordStatus.Okay }]; names = [...names, { value: newName, status: WordStatus.Okay }];
newName = ""; newName = "";
}; };
const addPronouns = () => { const addPronouns = (event: Event) => {
event.preventDefault();
if (newPronouns in data.pronouns) { if (newPronouns in data.pronouns) {
const fullSet = data.pronouns[newPronouns]; const fullSet = data.pronouns[newPronouns];
pronouns = [ pronouns = [
@ -173,7 +177,9 @@
newPronouns = ""; newPronouns = "";
}; };
const addLink = () => { const addLink = (event: Event) => {
event.preventDefault();
links = [...links, newLink]; links = [...links, newLink];
newLink = ""; newLink = "";
}; };
@ -297,9 +303,10 @@
<Input bind:value={display_name} /> <Input bind:value={display_name} />
</FormGroup> </FormGroup>
<div> <div>
<FormGroup floating label="Bio ({bio.length}/{MAX_DESCRIPTION_LENGTH})"> <div class="form">
<textarea style="min-height: 100px;" class="form-control" bind:value={bio} /> <label for="bio"><strong>Bio ({bio.length}/{MAX_DESCRIPTION_LENGTH})</strong></label>
</FormGroup> <textarea class="form-control" style="height: 200px;" id="bio" bind:value={bio} />
</div>
<p class="text-muted mt-3"> <p class="text-muted mt-3">
<Icon name="info-circle-fill" aria-hidden /> Your bio supports limited <Icon name="info-circle-fill" aria-hidden /> Your bio supports limited
<a <a
@ -324,10 +331,10 @@
remove={() => removeName(index)} remove={() => removeName(index)}
/> />
{/each} {/each}
<div class="input-group m-1"> <form class="input-group m-1" on:submit={addName}>
<input type="text" class="form-control" bind:value={newName} /> <input type="text" class="form-control" bind:value={newName} />
<IconButton color="success" icon="plus" tooltip="Add name" click={() => addName()} /> <IconButton type="submit" color="success" icon="plus" tooltip="Add name" />
</div> </form>
</div> </div>
<div class="col-md"> <div class="col-md">
<h4>Links</h4> <h4>Links</h4>
@ -342,10 +349,10 @@
/> />
</div> </div>
{/each} {/each}
<div class="input-group m-1"> <form class="input-group m-1" on:submit={addLink}>
<input type="text" class="form-control" bind:value={newLink} /> <input type="text" class="form-control" bind:value={newLink} />
<IconButton color="success" icon="plus" tooltip="Add link" click={() => addLink()} /> <IconButton type="submit" color="success" icon="plus" tooltip="Add link" />
</div> </form>
</div> </div>
</div> </div>
<div class="row m-1"> <div class="row m-1">
@ -359,7 +366,7 @@
remove={() => removePronoun(index)} remove={() => removePronoun(index)}
/> />
{/each} {/each}
<div class="input-group m-1"> <form class="input-group m-1" on:submit={addPronouns}>
<input <input
type="text" type="text"
class="form-control" class="form-control"
@ -368,18 +375,18 @@
required required
/> />
<IconButton <IconButton
type="submit"
color="success" color="success"
icon="plus" icon="plus"
tooltip="Add pronouns" tooltip="Add pronouns"
disabled={newPronouns === ""} disabled={newPronouns === ""}
click={() => addPronouns()}
/> />
<Button id="pronouns-help" color="secondary"><Icon name="question" /></Button> <Button id="pronouns-help" color="secondary"><Icon name="question" /></Button>
<Popover target="pronouns-help" placement="bottom"> <Popover target="pronouns-help" placement="bottom">
For common pronouns, the short form (e.g. "she/her" or "he/him") is enough; for less For common pronouns, the short form (e.g. "she/her" or "he/him") is enough; for less
common pronouns, you will have to use all five forms (e.g. "ce/cir/cir/cirs/cirself"). common pronouns, you will have to use all five forms (e.g. "ce/cir/cir/cirs/cirself").
</Popover> </Popover>
</div> </form>
</div> </div>
</div> </div>
<hr /> <hr />