Files
modrinth/packages/ui/src/components/project/ProjectPageHeader.vue
T
755825b09a project disclosures frontend (#6955)
* begin project disclosures

* new project settings header

* begin disclosure settings, edit content rules

* togglecards

* update phrasing of the rules, prepr

* more disclosure settings structuring

* add functionality toggle

* implement functionality with staging api

* improve project settings head titles

* feat(labrinth): project disclosures model

* feat(labrinth): project disclosures database model

* feat(labrinth): project disclosures get endpoint

* feat(labrinth): censor user ids if set by moderator

* feat(labrinth): wrap disclosures in struct

* feat(labrinth): edit project disclosures endpoint

* style(labrinth): cargo fmt

* style(labrinth): fix typo

* feat(labrinth): add fields for ai content disclosure

* fix(labrinth): field typo

* chore(labrinth): update query cache

* feat(labrinth): index disclosures in search

* refactor(labrinth): use enum instead of bools

* feat(labrinth): trigger incremental index on disclosure change

* feat(labrinth): change archived status to disclosure

* feat(labrinth): use disclosure for archival status

* fix(labrinth): error type for deserialization

* fix(labrinth): migration timestamp

* fix(labrinth): add disclosures to elasticsearch schema

* disclosures in search

* update photosensitivity warning copy

* update archiving, move general project settings to v3 (start redesign there), use project id lookups for stable cache keys, advanced in server search

* blue archive banner

* display AI use types

* improve labels

* add modrinth to link

* add placeholder missing disclosure report type

* add AI metadata checking to block image uploads with notice

* update copy

* update section 4 of rules

* Update rule 6 layout

* fix(labrinth): don't remove archival disclosure when changing status via v3 api

* feat(labrinth): derive str for ai usages and telemtry consent

* feat(labrinth): include ai usages and telemetry consent in disclosure types

* Update moderation checklist (#7056)

* fix: missing delphi severity (#7054)

* Utils nav, new disclosures stage, ai button in rules

* add prefix to collect

* Finish up new disclosures stage

* update r4 messages

* new r4 msg, update showcase clarity message

* fix: version upload failing to detect mrpack loader (#7063)

* fix: mrpack exporting with zip64 (#7064)

* fix: action bar max width (#7048)

* fix: action bar max width

* fix: width

* changelog

* Rule placeholders with subsections & anchors, update messages.

* update new messages to account for new rule and placeholder layout

* Add nag for content disclosures

---------

Co-authored-by: ThatGravyBoat <gravy@thatgravyboat.tech>
Co-authored-by: chyzman <chyzalt@gmail.com>
Co-authored-by: Truman Gao <106889354+tdgao@users.noreply.github.com>
Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>

* prepr

* refactor(labrinth): move disclosure parsing to document creation

* fix(labrinth): prevent removing moderator added archival disclosures

* fix(labrinth): dedupe ai usages

* fix(labrinth): auth logic on archived disclosure removal

* feat(labrinth): add interactions field

* style(labrinth): cargo fmt

* feat(labrinth): granular disclosure locking

* add 5.8, move 5.9, update messages and placeholders accordingly.

* move disclosures stage earlier

* include consent model info in telemetry disclosure msgs

* prepr + update date

* typo

* qa pass

* search suboptions

* add empty state

* checkboxes in column

* persistent advanced filters

* blog draft

* prepr

* support soft deletion

* reload instead of optimistically updating

* update blog

* TOS update + minor verbiage adjustment

* 45 day grace

---------

Co-authored-by: sychic <47618543+Sychic@users.noreply.github.com>
Co-authored-by: coolbot <76798835+coolbot100s@users.noreply.github.com>
Co-authored-by: ThatGravyBoat <gravy@thatgravyboat.tech>
Co-authored-by: chyzman <chyzalt@gmail.com>
Co-authored-by: Truman Gao <106889354+tdgao@users.noreply.github.com>
2026-08-13 09:01:18 -07:00

118 lines
3.6 KiB
Vue

<template>
<PageHeader
:title="project.title"
:summary="project.description"
@contextmenu="emit('contextmenu', $event)"
>
<template #leading>
<Avatar :src="project.icon_url" :alt="project.title" :tint-by="project.id" size="96px" />
</template>
<template v-if="showStatusBadge" #badges>
<ProjectStatusBadge :status="projectV3.status" />
</template>
<template #metadata>
<PageHeaderMetadata>
<template v-if="projectV3?.minecraft_server != null">
<ServerDetails
v-if="projectV3?.status !== 'draft'"
:online-players="projectV3?.minecraft_java_server?.ping?.data?.players_online ?? 0"
:status-online="!!projectV3?.minecraft_java_server?.ping?.data"
:recent-plays="projectV3?.minecraft_java_server?.verified_plays_2w ?? 0"
/>
</template>
<template v-else>
<PageHeaderMetadataNumberItem
:icon="DownloadIcon"
:value="project.downloads"
:label="formatMessage(messages.downloadsStat, { count: project.downloads })"
:tooltip="formatNumber(project.downloads)"
/>
<PageHeaderMetadataNumberItem
:icon="HeartIcon"
:value="project.followers"
:label="formatMessage(messages.followersStat, { count: project.followers })"
:tooltip="formatNumber(project.followers)"
/>
</template>
<PageHeaderMetadataTagsItem v-if="project.categories.length > 0" class="hidden md:flex">
<TagItem
v-for="category in project.categories"
:key="category"
:action="() => emit('category', category)"
>
<FormattedTag :tag="category" />
</TagItem>
</PageHeaderMetadataTagsItem>
</PageHeaderMetadata>
</template>
<template #actions>
<PageHeaderActions>
<slot name="actions" />
</PageHeaderActions>
</template>
</PageHeader>
</template>
<script setup lang="ts">
import type { Labrinth } from '@modrinth/api-client'
import { DownloadIcon, HeartIcon } from '@modrinth/assets'
import { defineMessages, useFormatNumber, useVIntl } from '../../composables'
import Avatar from '../base/Avatar.vue'
import FormattedTag from '../base/FormattedTag.vue'
import PageHeader from '../base/page-header/index.vue'
import PageHeaderMetadata from '../base/page-header/metadata/index.vue'
import PageHeaderMetadataNumberItem from '../base/page-header/metadata/page-header-metadata-number-item.vue'
import PageHeaderMetadataTagsItem from '../base/page-header/metadata/page-header-metadata-tags-item.vue'
import PageHeaderActions from '../base/page-header/page-header-actions.vue'
import TagItem from '../base/TagItem.vue'
import ProjectStatusBadge from './ProjectStatusBadge.vue'
import ServerDetails from './server/ServerDetails.vue'
type HeaderProject = Pick<
Labrinth.Projects.v2.Project,
'id' | 'title' | 'description' | 'status' | 'downloads' | 'followers' | 'categories'
> & {
icon_url?: string | null
}
type HeaderProjectV3 = Pick<
Labrinth.Projects.v3.Project,
'status' | 'minecraft_server' | 'minecraft_java_server'
>
withDefaults(
defineProps<{
project: HeaderProject
projectV3?: HeaderProjectV3 | null
showStatusBadge?: boolean
}>(),
{
projectV3: null,
showStatusBadge: false,
},
)
const emit = defineEmits<{
category: [category: string]
contextmenu: [event: MouseEvent]
}>()
const messages = defineMessages({
downloadsStat: {
id: 'project.stats.downloads-label',
defaultMessage: '{count, plural, one {download} other {downloads}}',
},
followersStat: {
id: 'project.stats.followers-label',
defaultMessage: '{count, plural, one {follower} other {followers}}',
},
})
const { formatMessage } = useVIntl()
const formatNumber = useFormatNumber()
</script>