Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 88 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ members = [
"packages/app-lib",
"packages/ariadne",
"packages/daedalus",
"packages/delphi-cel-experiment",
"packages/labrinth-derive",
"packages/modrinth-content-management",
"packages/modrinth-log",
Expand Down Expand Up @@ -55,6 +56,7 @@ bon = "3.9.3"
bytemuck = "1.24.0"
bytes = "1.10.1"
censor = "0.3.0"
cel = { version = "0.14.0", default-features = false, features = ["json"] }
chardetng = "0.1.17"
chrono = "0.4.42"
cidre = { version = "0.15.0", default-features = false, features = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,8 @@
<p class="m-0 break-words font-semibold text-contrast">
{{ trace.project_name }}
</p>
<p class="m-0 mt-1 flex flex-wrap items-center gap-1 text-sm text-secondary">
<span class="break-all">{{ trace.version_number }}</span>
<ChevronRightIcon class="size-4 shrink-0" aria-hidden="true" />
<span class="break-all">{{ decodeTracePath(trace.file_name) }}</span>
<template v-if="trace.jar">
<ChevronRightIcon class="size-4 shrink-0" aria-hidden="true" />
<span class="break-all">{{ decodeTracePath(trace.jar) }}</span>
</template>
<p class="m-0 mt-1 text-sm text-secondary">
<IssueDetailPath :segments="[trace.version_number, trace.file_name, trace.jar]" />
</p>
</div>
<div class="flex flex-wrap items-center gap-2">
Expand All @@ -33,9 +27,11 @@

<script setup lang="ts">
import type { Labrinth } from '@modrinth/api-client'
import { ChevronRightIcon, ExternalIcon } from '@modrinth/assets'
import { ExternalIcon } from '@modrinth/assets'
import { Badge, ButtonStyled } from '@modrinth/ui'

import IssueDetailPath from '~/components/ui/moderation/IssueDetailPath.vue'

const props = defineProps<{
trace: Labrinth.TechReview.Internal.GlobalIssueDetailTrace
}>()
Expand All @@ -46,12 +42,4 @@ const localTraceLink = computed(
props.trace.detail_id,
)}`,
)

function decodeTracePath(path: string): string {
try {
return decodeURIComponent(path)
} catch {
return path
}
}
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
</p>
<p class="m-0 break-all text-secondary">
<span class="font-semibold text-contrast">Path</span>
{{ decodeTracePath(getLatestLocalTrace(trace)?.file_path ?? '') }}
<IssueDetailPath :segments="[getLatestLocalTrace(trace)?.file_path]" />
</p>
</div>
</div>
Expand Down Expand Up @@ -133,6 +133,7 @@ import {
} from '@modrinth/ui'

import GlobalDetailLocalTraceCard from '~/components/ui/moderation/GlobalDetailLocalTraceCard.vue'
import IssueDetailPath from '~/components/ui/moderation/IssueDetailPath.vue'

const client = injectModrinthClient()
const { addNotification } = injectNotificationManager()
Expand Down Expand Up @@ -165,14 +166,6 @@ function getLatestLocalTrace(trace: Labrinth.TechReview.Internal.GlobalIssueDeta
return trace.local_traces.at(-1)
}

function decodeTracePath(path: string): string {
try {
return decodeURIComponent(path)
} catch {
return path
}
}

function getSeverityBadgeColor(
severity: Labrinth.TechReview.Internal.DelphiSeverity | undefined,
): string {
Expand Down
74 changes: 74 additions & 0 deletions apps/frontend/src/components/ui/moderation/IssueDetailPath.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<template>
<span class="inline-flex min-w-0 flex-wrap items-center gap-1">
<template v-for="(segment, index) in decodedSegments" :key="`${segment}-${index}`">
<ChevronRightIcon v-if="index > 0" class="size-4 shrink-0" aria-hidden="true" />
<span
v-tooltip="isTruncated(segment) ? segment : undefined"
class="break-all"
:class="{
'font-semibold text-contrast': emphasizeLast && index === decodedSegments.length - 1,
'text-secondary': emphasizeLast && index < decodedSegments.length - 1,
}"
>
{{ formatSegment(segment) }}
</span>
</template>
</span>
</template>

<script setup lang="ts">
import { ChevronRightIcon } from '@modrinth/assets'

const props = withDefaults(
defineProps<{
segments: readonly (string | null | undefined)[]
truncate?: boolean
maxLength?: number
emphasizeLast?: boolean
decode?: boolean
hideBaseMrpack?: boolean
}>(),
{
truncate: false,
maxLength: 120,
emphasizeLast: false,
decode: true,
hideBaseMrpack: false,
},
)

const decodedSegments = computed(() => {
const segments = props.segments
.flatMap((segment) => segment?.split('#') ?? [])
.filter((segment) => segment.length > 0)
.map((segment) => (props.decode ? decodePath(segment) : segment))

if (props.hideBaseMrpack && segments[0]?.toLowerCase().endsWith('.mrpack')) {
return segments.slice(1)
}

return segments
})

function decodePath(path: string): string {
try {
return decodeURIComponent(path)
} catch {
return path
}
}

function isTruncated(segment: string): boolean {
return props.truncate && segment.length > props.maxLength
}

function formatSegment(segment: string): string {
if (!isTruncated(segment)) return segment

const separator = '...'
const charsToShow = props.maxLength - separator.length
const frontChars = Math.ceil(charsToShow / 3)
const backChars = Math.floor((charsToShow * 2) / 3)
return segment.slice(0, frontChars) + separator + segment.slice(-backChars)
}
</script>
Loading
Loading