From 8f1d1fc87cfbaa129c995f12965c31749dabb4a0 Mon Sep 17 00:00:00 2001 From: Sam Date: Mon, 29 May 2023 02:56:31 +0200 Subject: [PATCH] feat: add flags to edit member page --- .../src/routes/edit/member/[id]/+page.svelte | 110 ++++++++++++++++++ frontend/src/routes/edit/member/[id]/+page.ts | 4 +- 2 files changed, 113 insertions(+), 1 deletion(-) diff --git a/frontend/src/routes/edit/member/[id]/+page.svelte b/frontend/src/routes/edit/member/[id]/+page.svelte index 34fc26d..7ba9080 100644 --- a/frontend/src/routes/edit/member/[id]/+page.svelte +++ b/frontend/src/routes/edit/member/[id]/+page.svelte @@ -8,6 +8,7 @@ type FieldEntry, type Member, type Pronoun, + type PrideFlag, } from "$lib/api/entities"; import FallbackImage from "$lib/components/FallbackImage.svelte"; import { @@ -40,6 +41,7 @@ import { memberNameRegex } from "$lib/api/regex"; import { charCount, renderMarkdown } from "$lib/utils"; import MarkdownHelp from "../../MarkdownHelp.svelte"; + import FlagButton from "../../FlagButton.svelte"; const MAX_AVATAR_BYTES = 1_000_000; @@ -59,6 +61,7 @@ let names: FieldEntry[] = window.structuredClone(data.member.names); let pronouns: Pronoun[] = window.structuredClone(data.member.pronouns); let fields: Field[] = window.structuredClone(data.member.fields); + let flags: PrideFlag[] = window.structuredClone(data.member.flags); let unlisted: boolean = data.member.unlisted || false; let memberNameValid = true; @@ -71,6 +74,18 @@ let newPronouns = ""; let newLink = ""; + let flagSearch = ""; + let filteredFlags: PrideFlag[]; + $: filteredFlags = filterFlags(flagSearch, data.flags); + + const filterFlags = (search: string, flags: PrideFlag[]) => { + return ( + search + ? flags.filter((flag) => flag.name.toLocaleLowerCase().includes(search.toLocaleLowerCase())) + : flags + ).slice(0, 25); + }; + let modified = false; $: modified = isModified( @@ -82,6 +97,7 @@ names, pronouns, fields, + flags, avatar, unlisted, ); @@ -96,6 +112,7 @@ names: FieldEntry[], pronouns: Pronoun[], fields: Field[], + flags: PrideFlag[], avatar: string | null, unlisted: boolean, ) => { @@ -104,6 +121,7 @@ if (display_name !== member.display_name) return true; if (!linksEqual(links, member.links)) return true; if (!fieldsEqual(fields, member.fields)) return true; + if (!flagsEqual(flags, member.flags)) return true; if (!namesEqual(names, member.names)) return true; if (!pronounsEqual(pronouns, member.pronouns)) return true; if (avatar !== null) return true; @@ -147,6 +165,11 @@ return arr1.every((_, i) => arr1[i] === arr2[i]); }; + const flagsEqual = (arr1: PrideFlag[], arr2: PrideFlag[]) => { + if (arr1.length !== arr2.length) return false; + return arr1.every((_, i) => arr1[i].id === arr2[i].id); + }; + const getAvatar = async (list: FileList | null) => { if (!list || list.length === 0) return null; if (list[0].size > MAX_AVATAR_BYTES) { @@ -211,6 +234,26 @@ links[newIndex] = temp; }; + const moveFlag = (index: number, up: boolean) => { + if (up && index == 0) return; + if (!up && index == flags.length - 1) return; + + const newIndex = up ? index - 1 : index + 1; + + const temp = flags[index]; + flags[index] = flags[newIndex]; + flags[newIndex] = temp; + }; + + const addFlag = (flag: PrideFlag) => { + flags = [...flags, flag]; + }; + + const removeFlag = (index: number) => { + flags.splice(index, 1); + flags = [...flags]; + }; + const addName = (event: Event) => { event.preventDefault(); @@ -281,6 +324,7 @@ names, pronouns, fields, + flags: flags.map((flag) => flag.id), unlisted, }); @@ -541,6 +585,72 @@ + +
+ {#each flags as _, index} + + moveFlag(index, true)} + /> + moveFlag(index, false)} + /> + removeFlag(index)} + /> + + {/each} +
+
+
+
+ +
+ {#each filteredFlags as flag (flag.id)} + addFlag(flag)} + /> + {:else} + {#if data.flags.length === 0} + You haven't uploaded any flags yet. + {:else} + There are no flags matching your search {flagSearch}. + {/if} + {/each} +
+
+
+ + {#if data.flags.length === 0} +

Why can't I see any flags?

+

+ There are thousands of pride flags, and it would be impossible to bundle all of them + by default. Many labels also have multiple different flags that are favoured by + different people. Because of this, there are no flags available by default--instead, + you can upload flags in your settings. Your main profile + and your member profiles can all have different flags. +

+ {:else} + To upload and delete flags, go to your settings. + {/if} +
+
+
+
{#each links as _, index} diff --git a/frontend/src/routes/edit/member/[id]/+page.ts b/frontend/src/routes/edit/member/[id]/+page.ts index b695c60..a84b94d 100644 --- a/frontend/src/routes/edit/member/[id]/+page.ts +++ b/frontend/src/routes/edit/member/[id]/+page.ts @@ -1,4 +1,4 @@ -import type { MeUser, APIError, Member, PronounsJson } from "$lib/api/entities"; +import type { PrideFlag, MeUser, APIError, Member, PronounsJson } from "$lib/api/entities"; import { apiFetchClient } from "$lib/api/fetch"; import { error } from "@sveltejs/kit"; @@ -11,11 +11,13 @@ export const load = async ({ params }) => { try { const user = await apiFetchClient(`/users/@me`); const member = await apiFetchClient(`/members/${params.id}`); + const flags = await apiFetchClient("/users/@me/flags"); return { user, member, pronouns: pronouns.autocomplete, + flags, }; } catch (e) { throw error((e as APIError).code, (e as APIError).message);