Skip to content

Commit f5da7ee

Browse files
committed
fix: lint & severity
1 parent 7892e4a commit f5da7ee

File tree

7 files changed

+139
-852
lines changed

7 files changed

+139
-852
lines changed

apps/frontend/src/components/ui/moderation/ModerationReportCard.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@
117117
</div>
118118
</div>
119119
</div>
120-
<div class="border-1 bg-surface-2 rounded-b-3xl border-solid border-bg-raised p-4 pt-2">
120+
<div class="border-1 rounded-b-3xl border-solid border-bg-raised bg-surface-2 p-4 pt-2">
121121
<ThreadView
122122
v-if="report.thread"
123123
ref="reportThread"

apps/frontend/src/components/ui/moderation/ModerationTechRevCard.vue

Lines changed: 109 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,11 @@ import {
44
CheckIcon,
55
ChevronDownIcon,
66
ClipboardCopyIcon,
7+
CodeIcon,
78
CopyIcon,
8-
DownloadIcon,
99
EllipsisVerticalIcon,
1010
LinkIcon,
1111
LoaderCircleIcon,
12-
ShieldCheckIcon,
13-
TriangleAlertIcon,
1412
} from '@modrinth/assets'
1513
import {
1614
Avatar,
@@ -21,7 +19,12 @@ import {
2119
OverflowMenu,
2220
type OverflowMenuOption,
2321
} from '@modrinth/ui'
24-
import { capitalizeString, formatProjectType, highlightCodeLines, type Thread } from '@modrinth/utils'
22+
import {
23+
capitalizeString,
24+
formatProjectType,
25+
highlightCodeLines,
26+
type Thread,
27+
} from '@modrinth/utils'
2528
import { computed, ref } from 'vue'
2629
2730
import ThreadView from '~/components/ui/thread/ThreadView.vue'
@@ -43,34 +46,52 @@ const emit = defineEmits<{
4346
loadSource: [issueId: string]
4447
}>()
4548
46-
const quickActions: OverflowMenuOption[] = [
47-
{
48-
id: 'copy-link',
49-
action: () => {
50-
const base = window.location.origin
51-
const reportUrl = `${base}/moderation/technical-review/${props.item.project.id}`
52-
navigator.clipboard.writeText(reportUrl).then(() => {
53-
addNotification({
54-
type: 'success',
55-
title: 'Technical Report link copied',
56-
text: 'The link to this report has been copied to your clipboard.',
49+
const quickActions = computed<OverflowMenuOption[]>(() => {
50+
const actions: OverflowMenuOption[] = []
51+
52+
// Add view source if URL exists
53+
const sourceUrl = props.item.project.link_urls?.['source']?.url
54+
if (sourceUrl) {
55+
actions.push({
56+
id: 'view-source',
57+
action: () => {
58+
window.open(sourceUrl, '_blank', 'noopener,noreferrer')
59+
},
60+
})
61+
}
62+
63+
// Always add these actions
64+
actions.push(
65+
{
66+
id: 'copy-link',
67+
action: () => {
68+
const base = window.location.origin
69+
const reportUrl = `${base}/moderation/technical-review/${props.item.project.id}`
70+
navigator.clipboard.writeText(reportUrl).then(() => {
71+
addNotification({
72+
type: 'success',
73+
title: 'Technical Report link copied',
74+
text: 'The link to this report has been copied to your clipboard.',
75+
})
5776
})
58-
})
77+
},
5978
},
60-
},
61-
{
62-
id: 'copy-id',
63-
action: () => {
64-
navigator.clipboard.writeText(props.item.project.id).then(() => {
65-
addNotification({
66-
type: 'success',
67-
title: 'Technical Report ID copied',
68-
text: 'The ID of this report has been copied to your clipboard.',
79+
{
80+
id: 'copy-id',
81+
action: () => {
82+
navigator.clipboard.writeText(props.item.project.id).then(() => {
83+
addNotification({
84+
type: 'success',
85+
title: 'Technical Report ID copied',
86+
text: 'The ID of this report has been copied to your clipboard.',
87+
})
6988
})
70-
})
89+
},
7190
},
72-
},
73-
]
91+
)
92+
93+
return actions
94+
})
7495
7596
type Tab = 'Thread' | 'Files'
7697
const tabs: readonly Tab[] = ['Thread', 'Files']
@@ -91,19 +112,32 @@ const highestSeverity = computed(() => {
91112
.flatMap((i) => i.details)
92113
.map((d) => d.severity)
93114
94-
const order = { SEVERE: 3, HIGH: 2, MEDIUM: 1, LOW: 0 } as Record<string, number>
95-
return severities.sort((a, b) => (order[b] ?? 0) - (order[a] ?? 0))[0] || 'LOW'
115+
const order = { severe: 3, high: 2, medium: 1, low: 0 } as Record<string, number>
116+
return severities.sort((a, b) => (order[b] ?? 0) - (order[a] ?? 0))[0] || 'low'
96117
})
97118
119+
function getSeverityBadgeColor(severity: Labrinth.TechReview.Internal.DelphiSeverity): string {
120+
switch (severity) {
121+
case 'severe':
122+
return 'border-red/60 border bg-highlight-red text-red'
123+
case 'high':
124+
case 'medium':
125+
return 'border-orange/60 border bg-highlight-orange text-orange'
126+
case 'low':
127+
default:
128+
return 'border-green/60 border bg-highlight-green text-green'
129+
}
130+
}
131+
98132
const severityColor = computed(() => {
99133
switch (highestSeverity.value) {
100-
case 'SEVERE':
134+
case 'severe':
101135
return 'text-red bg-highlight-red border-solid border-[1px] border-red'
102-
case 'HIGH':
136+
case 'high':
103137
return 'text-orange bg-highlight-orange border-solid border-[1px] border-orange'
104-
case 'MEDIUM':
138+
case 'medium':
105139
return 'text-blue bg-highlight-blue border-solid border-[1px] border-blue'
106-
case 'LOW':
140+
case 'low':
107141
default:
108142
return 'text-green bg-highlight-green border-solid border-[1px] border-green'
109143
}
@@ -216,7 +250,13 @@ function handleThreadUpdate() {
216250

217251
<div class="flex flex-col gap-1.5">
218252
<div class="flex items-center gap-2">
219-
<span class="text-lg font-semibold text-contrast">{{ item.project.name }}</span>
253+
<NuxtLink
254+
:to="`/${item.project.project_types[0]}/${item.project.slug ?? item.project.id}`"
255+
target="_blank"
256+
class="text-lg font-semibold text-contrast hover:underline"
257+
>
258+
{{ item.project.name }}
259+
</NuxtLink>
220260

221261
<div
222262
class="flex items-center gap-1 rounded-full border border-solid border-surface-5 bg-surface-4 px-2.5 py-1"
@@ -254,24 +294,22 @@ function handleThreadUpdate() {
254294
size="1.5rem"
255295
circle
256296
/>
257-
<span class="text-sm font-medium text-secondary">{{ item.project_owner.name }}</span>
297+
<NuxtLink
298+
:to="`/${item.project_owner.kind}/${item.project_owner.id}`"
299+
target="_blank"
300+
class="text-sm font-medium text-secondary hover:underline"
301+
>
302+
{{ item.project_owner.name }}
303+
</NuxtLink>
258304
</div>
259305
</div>
260306
</div>
261307

262308
<div class="flex items-center gap-3">
263309
<span class="text-base text-secondary">{{ formattedDate }}</span>
264310
<div class="flex items-center gap-2">
265-
<ButtonStyled color="green">
266-
<button><ShieldCheckIcon /> Safe</button>
267-
</ButtonStyled>
268-
269-
<ButtonStyled color="red">
270-
<button><TriangleAlertIcon /> Malware</button>
271-
</ButtonStyled>
272-
273-
<ButtonStyled circular>
274-
<OverflowMenu :options="quickActions">
311+
<ButtonStyled circular type="outlined">
312+
<OverflowMenu :options="quickActions" class="!border-px !border-surface-4">
275313
<template #default>
276314
<EllipsisVerticalIcon class="size-4" />
277315
</template>
@@ -283,6 +321,10 @@ function handleThreadUpdate() {
283321
<LinkIcon />
284322
<span class="hidden sm:inline">Copy link</span>
285323
</template>
324+
<template #view-source>
325+
<CodeIcon />
326+
<span class="hidden sm:inline">View source</span>
327+
</template>
286328
</OverflowMenu>
287329
</ButtonStyled>
288330
</div>
@@ -322,10 +364,7 @@ function handleThreadUpdate() {
322364

323365
<div class="border-t border-surface-3 bg-surface-2">
324366
<div v-if="currentTab === 'Thread'" class="p-4">
325-
<ThreadView
326-
:thread="item.thread as Thread"
327-
@update-thread="handleThreadUpdate"
328-
/>
367+
<ThreadView :thread="item.thread as Thread" @update-thread="handleThreadUpdate" />
329368
</div>
330369

331370
<div v-else-if="currentTab === 'Files' && !selectedFile" class="flex flex-col">
@@ -371,9 +410,17 @@ function handleThreadUpdate() {
371410
<button @click="viewFileFlags(file)">Flags</button>
372411
</ButtonStyled>
373412

374-
<ButtonStyled outline>
375-
<button><DownloadIcon /> Download</button>
376-
</ButtonStyled>
413+
<!-- TODO: Impl when backend supports it -->
414+
<!-- <ButtonStyled type="outlined">
415+
<a
416+
:href="`https://api.modrinth.com/v2/version_file/${file.file_id}/download`"
417+
:title="`Download ${file.file_name}`"
418+
class="!border-px !border-surface-4"
419+
tabindex="0"
420+
>
421+
<DownloadIcon /> Download
422+
</a>
423+
</ButtonStyled> -->
377424
</div>
378425
</div>
379426
</div>
@@ -391,7 +438,10 @@ function handleThreadUpdate() {
391438
>
392439
<div class="my-auto flex items-center gap-2">
393440
<ButtonStyled type="transparent" circular>
394-
<button class="transition-transform" :class="{ 'rotate-180': expandedIssues.has(issue.id) }">
441+
<button
442+
class="transition-transform"
443+
:class="{ 'rotate-180': expandedIssues.has(issue.id) }"
444+
>
395445
<ChevronDownIcon class="h-5 w-5 text-contrast" />
396446
</button>
397447
</ButtonStyled>
@@ -403,18 +453,10 @@ function handleThreadUpdate() {
403453
<div
404454
v-if="issue.details.length > 0"
405455
class="rounded-full px-2.5 py-1"
406-
:class="{
407-
'border-red/60 border bg-highlight-red text-red':
408-
issue.details[0].severity === 'SEVERE',
409-
'border-orange/60 border bg-highlight-orange text-orange':
410-
issue.details[0].severity === 'HIGH' || issue.details[0].severity === 'MEDIUM',
411-
'border-green/60 border bg-highlight-green text-green':
412-
issue.details[0].severity === 'LOW',
413-
}"
456+
:class="getSeverityBadgeColor(issue.details[0].severity)"
414457
>
415458
<span class="text-sm font-medium">{{
416-
issue.details[0].severity.charAt(0) +
417-
issue.details[0].severity.slice(1).toLowerCase()
459+
capitalizeString(issue.details[0].severity)
418460
}}</span>
419461
</div>
420462

@@ -424,8 +466,9 @@ function handleThreadUpdate() {
424466
class="rounded-full border border-solid border-surface-5 bg-surface-3 px-2.5 py-1"
425467
>
426468
<span class="text-sm font-medium text-secondary">
427-
<LoaderCircleIcon class="animate-spin size-5" />
428-
Loading source...</span>
469+
<LoaderCircleIcon class="size-5 animate-spin" />
470+
Loading source...</span
471+
>
429472
</div>
430473
</Transition>
431474
</div>

apps/frontend/src/components/ui/thread/ThreadView.vue

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,7 @@
2626
<template v-if="reportClosed">
2727
<p class="text-secondary">This thread is closed and new messages cannot be sent to it.</p>
2828
<ButtonStyled v-if="isStaff(auth.user)" color="green" class="mt-2">
29-
<button
30-
class="w-full gap-2 sm:w-auto"
31-
@click="reopenReport()"
32-
>
29+
<button class="w-full gap-2 sm:w-auto" @click="reopenReport()">
3330
<CheckCircleIcon class="size-4" />
3431
Reopen Thread
3532
</button>
@@ -50,31 +47,19 @@
5047
>
5148
<div class="flex flex-col items-stretch gap-2 sm:flex-row sm:items-center">
5249
<ButtonStyled v-if="sortedMessages.length > 0" color="brand">
53-
<button
54-
:disabled="!replyBody"
55-
class="w-full gap-2 sm:w-auto"
56-
@click="sendReply()"
57-
>
50+
<button :disabled="!replyBody" class="w-full gap-2 sm:w-auto" @click="sendReply()">
5851
<ReplyIcon class="size-4" />
5952
Reply
6053
</button>
6154
</ButtonStyled>
6255
<ButtonStyled v-else color="brand">
63-
<button
64-
:disabled="!replyBody"
65-
class="w-full gap-2 sm:w-auto"
66-
@click="sendReply()"
67-
>
56+
<button :disabled="!replyBody" class="w-full gap-2 sm:w-auto" @click="sendReply()">
6857
<SendIcon class="size-4" />
6958
Send
7059
</button>
7160
</ButtonStyled>
7261
<ButtonStyled v-if="isStaff(auth.user)">
73-
<button
74-
:disabled="!replyBody"
75-
class="w-full sm:w-auto"
76-
@click="sendReply(true)"
77-
>
62+
<button :disabled="!replyBody" class="w-full sm:w-auto" @click="sendReply(true)">
7863
Add note
7964
</button>
8065
</ButtonStyled>
@@ -89,19 +74,13 @@
8974
<div class="flex flex-col items-stretch gap-2 sm:flex-row sm:items-center">
9075
<template v-if="isStaff(auth.user)">
9176
<ButtonStyled v-if="replyBody" color="red">
92-
<button
93-
class="w-full gap-2 sm:w-auto"
94-
@click="closeReport(true)"
95-
>
77+
<button class="w-full gap-2 sm:w-auto" @click="closeReport(true)">
9678
<CheckCircleIcon class="size-4" />
9779
Reply and close
9880
</button>
9981
</ButtonStyled>
10082
<ButtonStyled v-else color="red">
101-
<button
102-
class="w-full gap-2 sm:w-auto"
103-
@click="closeReport()"
104-
>
83+
<button class="w-full gap-2 sm:w-auto" @click="closeReport()">
10584
<CheckCircleIcon class="size-4" />
10685
Close report
10786
</button>
@@ -175,7 +154,9 @@ async function handleQuickReply(reply: ReportQuickReply) {
175154
if (!props.report) return
176155
177156
const message =
178-
typeof reply.message === 'function' ? await reply.message(props.report as ExtendedReport) : reply.message
157+
typeof reply.message === 'function'
158+
? await reply.message(props.report as ExtendedReport)
159+
: reply.message
179160
180161
await nextTick()
181162
setReplyContent(message)

0 commit comments

Comments
 (0)