You've already forked AstralRinth
forked from didirus/AstralRinth
Project pages (#65)
* Initial impl of project pages
* Finalize project styling
* Revert browse page changes
* Fix lint
* Addressed some comments
* 😄
* Run lint
* Addressed issues
* fixed dist
* addressed changes
* Address changes
* I am speed
* Howd you get there
This commit is contained in:
385
theseus_gui/src/pages/project/Version.vue
Normal file
385
theseus_gui/src/pages/project/Version.vue
Normal file
@@ -0,0 +1,385 @@
|
||||
<template>
|
||||
<div>
|
||||
<Card>
|
||||
<div class="version-title">
|
||||
<h2>{{ version.name }}</h2>
|
||||
<span v-if="version.featured">Auto-Featured</span>
|
||||
</div>
|
||||
<div class="button-group">
|
||||
<Button color="primary">
|
||||
<DownloadIcon />
|
||||
Install
|
||||
</Button>
|
||||
<Button :link="`/project/${route.params.id}/versions`">
|
||||
<LeftArrowIcon />
|
||||
Back to list
|
||||
</Button>
|
||||
<Button>
|
||||
<ReportIcon />
|
||||
Report
|
||||
</Button>
|
||||
<a
|
||||
:href="`https://modrinth.com/mod/${route.params.id}/version/${route.params.version}`"
|
||||
rel="external"
|
||||
target="_blank"
|
||||
class="btn"
|
||||
>
|
||||
<ExternalIcon />
|
||||
Modrinth Website
|
||||
</a>
|
||||
</div>
|
||||
</Card>
|
||||
<div class="version-container">
|
||||
<div class="description-cards">
|
||||
<Card>
|
||||
<h3 class="card-title">Changelog</h3>
|
||||
<div class="markdown-body" v-html="renderString(version.changelog ?? '')" />
|
||||
</Card>
|
||||
<Card>
|
||||
<h3 class="card-title">Files</h3>
|
||||
<Card
|
||||
v-for="file in version.files"
|
||||
:key="file.id"
|
||||
:class="{ primary: file.primary }"
|
||||
class="file"
|
||||
>
|
||||
<span class="label">
|
||||
<FileIcon />
|
||||
<span>
|
||||
<span class="title">
|
||||
{{ file.filename }}
|
||||
</span>
|
||||
({{ formatBytes(file.size) }})
|
||||
<span v-if="file.primary" class="primary-label"> Primary </span>
|
||||
</span>
|
||||
</span>
|
||||
<Button class="download">
|
||||
<DownloadIcon />
|
||||
Install
|
||||
</Button>
|
||||
</Card>
|
||||
</Card>
|
||||
<Card v-if="displayDependencies[0]">
|
||||
<h2>Dependencies</h2>
|
||||
<div v-for="dependency in displayDependencies" :key="dependency.title">
|
||||
<router-link v-if="dependency.link" class="btn dependency" :to="dependency.link">
|
||||
<Avatar size="sm" :src="dependency.icon" />
|
||||
<div>
|
||||
<span class="title"> {{ dependency.title }} </span> <br />
|
||||
<span> {{ dependency.subtitle }} </span>
|
||||
</div>
|
||||
</router-link>
|
||||
<div v-else class="dependency disabled" disabled="">
|
||||
<Avatar size="sm" :src="dependency.icon" />
|
||||
<div class="text">
|
||||
<div class="title">{{ dependency.title }}</div>
|
||||
<div>{{ dependency.subtitle }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
<Card class="metadata-card">
|
||||
<h3 class="card-title">Metadata</h3>
|
||||
<div class="metadata">
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-label">Release Channel</span>
|
||||
<span class="metadata-value"
|
||||
><Badge
|
||||
:color="releaseColor(version.version_type)"
|
||||
:type="
|
||||
version.version_type.charAt(0).toUpperCase() + version.version_type.slice(1)
|
||||
"
|
||||
/></span>
|
||||
</div>
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-label">Version Number</span>
|
||||
<span class="metadata-value">{{ version.version_number }}</span>
|
||||
</div>
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-label">Loaders</span>
|
||||
<span class="metadata-value">{{
|
||||
version.loaders
|
||||
.map((loader) => loader.charAt(0).toUpperCase() + loader.slice(1))
|
||||
.join(', ')
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-label">Game Versions</span>
|
||||
<span class="metadata-value"> {{ version.game_versions.join(', ') }} </span>
|
||||
</div>
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-label">Downloads</span>
|
||||
<span class="metadata-value">{{ version.downloads }}</span>
|
||||
</div>
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-label">Publication Date</span>
|
||||
<span class="metadata-value">
|
||||
{{
|
||||
new Date(version.date_published).toLocaleString('en-US', {
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
year: 'numeric',
|
||||
})
|
||||
}}
|
||||
at
|
||||
{{
|
||||
new Date(version.date_published).toLocaleString('en-US', {
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
second: 'numeric',
|
||||
hour12: true,
|
||||
})
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="author" class="metadata-item">
|
||||
<span class="metadata-label">Author</span>
|
||||
<a
|
||||
:href="`https://modrinth.com/user/${author.user.username}`"
|
||||
rel="external"
|
||||
target="_blank"
|
||||
class="metadata-value btn author"
|
||||
>
|
||||
<Avatar size="sm" :src="author.user.avatar_url" circle />
|
||||
<span>
|
||||
<strong>
|
||||
{{ author.user.username }}
|
||||
</strong>
|
||||
<br />
|
||||
{{ author.role }}
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-label">Version ID</span>
|
||||
<span class="metadata-value"><CopyCode class="copycode" :text="version.id" /></span>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
Card,
|
||||
Button,
|
||||
DownloadIcon,
|
||||
FileIcon,
|
||||
Avatar,
|
||||
LeftArrowIcon,
|
||||
ReportIcon,
|
||||
Badge,
|
||||
ExternalIcon,
|
||||
CopyCode,
|
||||
formatBytes,
|
||||
renderString,
|
||||
} from 'omorphia'
|
||||
import { releaseColor } from '@/helpers/utils'
|
||||
import { ref, defineProps } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const props = defineProps({
|
||||
versions: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
dependencies: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
members: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const version = ref(props.versions.find((version) => version.id === route.params.version))
|
||||
const author = ref(props.members.find((member) => member.user.id === version.value.author_id))
|
||||
const displayDependencies = ref(
|
||||
version.value.dependencies.map((dependency) => {
|
||||
const version = props.dependencies.versions.find((obj) => obj.id === dependency.version_id)
|
||||
if (version) {
|
||||
const project = props.dependencies.projects.find(
|
||||
(obj) => obj.id === version.project_id || obj.id === dependency.project_id
|
||||
)
|
||||
return {
|
||||
icon: project?.icon_url,
|
||||
title: project?.title || project?.name,
|
||||
subtitle: `Version ${version.version_number} is ${dependency.dependency_type}`,
|
||||
link: `/project/${project.slug}/version/${version.id}`,
|
||||
}
|
||||
} else
|
||||
return {
|
||||
icon: null,
|
||||
title: dependency.file_name,
|
||||
subtitle: `Added via overrides`,
|
||||
link: null,
|
||||
}
|
||||
})
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.version-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.version-title {
|
||||
margin-bottom: 1rem;
|
||||
h2 {
|
||||
font-size: var(--font-size-2xl);
|
||||
font-weight: 700;
|
||||
color: var(--color-contrast);
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.dependency {
|
||||
display: flex;
|
||||
padding: 0.5rem 1rem 0.5rem 0.5rem;
|
||||
gap: 0.5rem;
|
||||
background: var(--color-raised-bg);
|
||||
color: var(--color-base);
|
||||
width: 100%;
|
||||
|
||||
.title {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
:deep(svg) {
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.file {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 0.5rem;
|
||||
background: var(--color-button-bg);
|
||||
color: var(--color-base);
|
||||
padding: 0.5rem 1rem;
|
||||
|
||||
.download {
|
||||
margin-left: auto;
|
||||
background-color: var(--color-raised-bg);
|
||||
}
|
||||
|
||||
.label {
|
||||
display: flex;
|
||||
margin: auto 0 auto;
|
||||
gap: 0.5rem;
|
||||
|
||||
.title {
|
||||
font-weight: bolder;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
svg {
|
||||
min-width: 1.1rem;
|
||||
min-height: 1.1rem;
|
||||
width: 1.1rem;
|
||||
height: 1.1rem;
|
||||
margin: auto 0;
|
||||
}
|
||||
|
||||
.primary-label {
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.primary {
|
||||
background: var(--color-brand-highlight);
|
||||
color: var(--color-contrast);
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: var(--font-size-lg);
|
||||
color: var(--color-contrast);
|
||||
margin: 0 0 0.5rem;
|
||||
}
|
||||
|
||||
.description-cards {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.metadata-card {
|
||||
width: 20rem;
|
||||
height: min-content;
|
||||
}
|
||||
|
||||
.metadata {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
|
||||
.metadata-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
|
||||
.metadata-label {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.author {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 0.5rem;
|
||||
align-items: center;
|
||||
text-decoration: none;
|
||||
color: var(--color-base);
|
||||
background: var(--color-raised-bg);
|
||||
padding: 0.5rem;
|
||||
width: 100%;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.markdown-body {
|
||||
:deep(hr),
|
||||
:deep(h1),
|
||||
:deep(h2),
|
||||
img {
|
||||
max-width: max(60rem, 90%) !important;
|
||||
}
|
||||
|
||||
:deep(ul),
|
||||
:deep(ol) {
|
||||
margin-left: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.copycode {
|
||||
border: 0;
|
||||
color: var(--color-contrast);
|
||||
}
|
||||
|
||||
.disabled {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
vertical-align: center;
|
||||
align-items: center;
|
||||
cursor: not-allowed;
|
||||
border-radius: var(--radius-lg);
|
||||
|
||||
.text {
|
||||
filter: brightness(0.5);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user