nsarrazin HF staff victor HF staff commited on
Commit
3109a5e
1 Parent(s): 7b7114b

Ask for a reason when reporting assistants (#825)

Browse files

* Show modal asking for assistant report reason

* fix disabled button styling

* parse with zod

* Update src/routes/settings/assistants/[assistantId]/ReportModal.svelte

Co-authored-by: Victor Muštar <victor.mustar@gmail.com>

* use a text area with max-w

---------

Co-authored-by: Victor Muštar <victor.mustar@gmail.com>

src/lib/components/Modal.svelte CHANGED
@@ -46,7 +46,7 @@
46
  role="presentation"
47
  tabindex="-1"
48
  bind:this={backdropEl}
49
- on:click={handleBackdropClick}
50
  transition:fade|global={{ easing: cubicOut, duration: 300 }}
51
  class="fixed inset-0 z-40 flex items-center justify-center bg-black/80 p-8 backdrop-blur-sm dark:bg-black/50"
52
  >
 
46
  role="presentation"
47
  tabindex="-1"
48
  bind:this={backdropEl}
49
+ on:click|stopPropagation={handleBackdropClick}
50
  transition:fade|global={{ easing: cubicOut, duration: 300 }}
51
  class="fixed inset-0 z-40 flex items-center justify-center bg-black/80 p-8 backdrop-blur-sm dark:bg-black/50"
52
  >
src/lib/types/Report.ts CHANGED
@@ -7,4 +7,5 @@ export interface Report extends Timestamps {
7
  _id: ObjectId;
8
  createdBy: User["_id"] | string;
9
  assistantId: Assistant["_id"];
 
10
  }
 
7
  _id: ObjectId;
8
  createdBy: User["_id"] | string;
9
  assistantId: Assistant["_id"];
10
+ reason?: string;
11
  }
src/routes/settings/assistants/[assistantId]/+page.server.ts CHANGED
@@ -5,7 +5,7 @@ import { authCondition } from "$lib/server/auth";
5
  import { base } from "$app/paths";
6
  import { PUBLIC_ORIGIN, PUBLIC_SHARE_PREFIX } from "$env/static/public";
7
  import { WEBHOOK_URL_REPORT_ASSISTANT } from "$env/static/private";
8
-
9
  async function assistantOnlyIfAuthor(locals: App.Locals, assistantId?: string) {
10
  const assistant = await collections.assistants.findOne({ _id: new ObjectId(assistantId) });
11
 
@@ -53,7 +53,7 @@ export const actions: Actions = {
53
 
54
  throw redirect(302, `${base}/settings`);
55
  },
56
- report: async ({ params, locals, url }) => {
57
  // is there already a report from this user for this model ?
58
  const report = await collections.reports.findOne({
59
  assistantId: new ObjectId(params.assistantId),
@@ -64,12 +64,20 @@ export const actions: Actions = {
64
  return fail(400, { error: true, message: "Already reported" });
65
  }
66
 
 
 
 
 
 
 
 
67
  const { acknowledged } = await collections.reports.insertOne({
68
  _id: new ObjectId(),
69
  assistantId: new ObjectId(params.assistantId),
70
  createdBy: locals.user?._id ?? locals.sessionId,
71
  createdAt: new Date(),
72
  updatedAt: new Date(),
 
73
  });
74
 
75
  if (!acknowledged) {
@@ -91,7 +99,7 @@ export const actions: Actions = {
91
  "Content-type": "application/json",
92
  },
93
  body: JSON.stringify({
94
- text: `Assistant <${assistantUrl}|${assistant?.name}> reported by <http://hf.co/${locals.user?.username}|${locals.user?.username}>`,
95
  }),
96
  });
97
 
 
5
  import { base } from "$app/paths";
6
  import { PUBLIC_ORIGIN, PUBLIC_SHARE_PREFIX } from "$env/static/public";
7
  import { WEBHOOK_URL_REPORT_ASSISTANT } from "$env/static/private";
8
+ import { z } from "zod";
9
  async function assistantOnlyIfAuthor(locals: App.Locals, assistantId?: string) {
10
  const assistant = await collections.assistants.findOne({ _id: new ObjectId(assistantId) });
11
 
 
53
 
54
  throw redirect(302, `${base}/settings`);
55
  },
56
+ report: async ({ request, params, locals, url }) => {
57
  // is there already a report from this user for this model ?
58
  const report = await collections.reports.findOne({
59
  assistantId: new ObjectId(params.assistantId),
 
64
  return fail(400, { error: true, message: "Already reported" });
65
  }
66
 
67
+ const formData = await request.formData();
68
+ const result = z.string().min(1).max(128).safeParse(formData?.get("reportReason"));
69
+
70
+ if (!result.success) {
71
+ return fail(400, { error: true, message: "Invalid report reason" });
72
+ }
73
+
74
  const { acknowledged } = await collections.reports.insertOne({
75
  _id: new ObjectId(),
76
  assistantId: new ObjectId(params.assistantId),
77
  createdBy: locals.user?._id ?? locals.sessionId,
78
  createdAt: new Date(),
79
  updatedAt: new Date(),
80
+ reason: result.data,
81
  });
82
 
83
  if (!acknowledged) {
 
99
  "Content-type": "application/json",
100
  },
101
  body: JSON.stringify({
102
+ text: `Assistant <${assistantUrl}|${assistant?.name}> reported by <http://hf.co/${locals.user?.username}|${locals.user?.username}>. The following reason was given \n\n> ${result.data}`,
103
  }),
104
  });
105
 
src/routes/settings/assistants/[assistantId]/+page.svelte CHANGED
@@ -12,6 +12,7 @@
12
  import CarbonFlag from "~icons/carbon/flag";
13
  import CarbonLink from "~icons/carbon/link";
14
  import CopyToClipBoardBtn from "$lib/components/CopyToClipBoardBtn.svelte";
 
15
 
16
  export let data: PageData;
17
 
@@ -24,8 +25,13 @@
24
  const prefix = PUBLIC_SHARE_PREFIX || `${PUBLIC_ORIGIN || $page.url.origin}${base}`;
25
 
26
  $: shareUrl = `${prefix}/assistant/${assistant?._id}`;
 
 
27
  </script>
28
 
 
 
 
29
  <div class="flex h-full flex-col gap-2">
30
  <div class="flex gap-6">
31
  {#if assistant?.avatar}
@@ -102,11 +108,15 @@
102
  >
103
  </form>
104
  {#if !assistant?.reported}
105
- <form method="POST" action="?/report" use:enhance>
106
- <button type="submit" class="underline">
107
- <CarbonFlag class="mr-1.5 inline text-xs" />Report</button
108
- >
109
- </form>
 
 
 
 
110
  {:else}
111
  <button type="button" disabled class="text-gray-700">
112
  <CarbonFlag class="mr-1.5 inline text-xs" />Reported</button
 
12
  import CarbonFlag from "~icons/carbon/flag";
13
  import CarbonLink from "~icons/carbon/link";
14
  import CopyToClipBoardBtn from "$lib/components/CopyToClipBoardBtn.svelte";
15
+ import ReportModal from "./ReportModal.svelte";
16
 
17
  export let data: PageData;
18
 
 
25
  const prefix = PUBLIC_SHARE_PREFIX || `${PUBLIC_ORIGIN || $page.url.origin}${base}`;
26
 
27
  $: shareUrl = `${prefix}/assistant/${assistant?._id}`;
28
+
29
+ let displayReportModal = false;
30
  </script>
31
 
32
+ {#if displayReportModal}
33
+ <ReportModal on:close={() => (displayReportModal = false)} />
34
+ {/if}
35
  <div class="flex h-full flex-col gap-2">
36
  <div class="flex gap-6">
37
  {#if assistant?.avatar}
 
108
  >
109
  </form>
110
  {#if !assistant?.reported}
111
+ <button
112
+ type="button"
113
+ on:click={() => {
114
+ displayReportModal = true;
115
+ }}
116
+ class="underline"
117
+ >
118
+ <CarbonFlag class="mr-1.5 inline text-xs" />Report
119
+ </button>
120
  {:else}
121
  <button type="button" disabled class="text-gray-700">
122
  <CarbonFlag class="mr-1.5 inline text-xs" />Reported</button
src/routes/settings/assistants/[assistantId]/ReportModal.svelte ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import { applyAction, enhance } from "$app/forms";
3
+ import { invalidateAll } from "$app/navigation";
4
+ import Modal from "$lib/components/Modal.svelte";
5
+ import { createEventDispatcher } from "svelte";
6
+
7
+ const dispatch = createEventDispatcher<{ close: void }>();
8
+
9
+ let reason = "";
10
+ </script>
11
+
12
+ <Modal on:close>
13
+ <form
14
+ method="POST"
15
+ action="?/report"
16
+ use:enhance={() => {
17
+ return async ({ result }) => {
18
+ await applyAction(result);
19
+ dispatch("close");
20
+ invalidateAll();
21
+ };
22
+ }}
23
+ class="w-full min-w-64 p-4"
24
+ >
25
+ <span class="mb-1 text-sm font-semibold">Report an assistant</span>
26
+
27
+ <p class="text-sm text-gray-500">
28
+ Please provide a brief description of why you are reporting this assistant.
29
+ </p>
30
+
31
+ <textarea
32
+ name="reportReason"
33
+ class="mt-6 max-h-48 w-full resize-y rounded-lg border-2 border-gray-200 bg-gray-100 p-2 text-smd"
34
+ placeholder="Reason(s) for the report"
35
+ maxlength="128"
36
+ bind:value={reason}
37
+ />
38
+
39
+ <div class="flex w-full flex-row justify-between px-2 pt-4">
40
+ <button
41
+ type="button"
42
+ class="text-sm text-gray-700 hover:underline"
43
+ on:click={() => dispatch("close")}>Cancel</button
44
+ >
45
+
46
+ <button
47
+ type="submit"
48
+ class="rounded-full bg-black px-4 py-2 text-sm font-semibold text-white md:px-8"
49
+ disabled={!reason}
50
+ class:bg-gray-200={!reason}
51
+ class:!text-gray-400={!reason}
52
+ >
53
+ Submit report
54
+ </button>
55
+ </div>
56
+ </form>
57
+ </Modal>