mirror of
https://github.com/HangarMC/Hangar.git
synced 2024-11-21 01:21:54 +08:00
Update version page to show all platforms at once
This commit is contained in:
parent
029d53441a
commit
b9f9471f1f
@ -1,6 +1,6 @@
|
||||
<script lang="ts" setup>
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { HangarProject, HangarVersion } from "hangar-internal";
|
||||
import { HangarProject, HangarVersion, IPlatform } from "hangar-internal";
|
||||
import { computed, onMounted, ref, watch } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { DependencyVersion, PluginDependency } from "hangar-api";
|
||||
@ -9,7 +9,6 @@ import { hasPerms } from "~/composables/usePerm";
|
||||
import Button from "~/lib/components/design/Button.vue";
|
||||
import Modal from "~/lib/components/modals/Modal.vue";
|
||||
import { NamedPermission, Platform } from "~/types/enums";
|
||||
import { useBackendData } from "~/store/backendData";
|
||||
import { handleRequestError } from "~/composables/useErrorHandling";
|
||||
import { useInternalApi } from "~/composables/useApi";
|
||||
import DependencyTable from "~/components/projects/DependencyTable.vue";
|
||||
@ -17,15 +16,13 @@ import DependencyTable from "~/components/projects/DependencyTable.vue";
|
||||
const props = defineProps<{
|
||||
project: HangarProject;
|
||||
version: HangarVersion;
|
||||
platform: IPlatform;
|
||||
}>();
|
||||
|
||||
const i18n = useI18n();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const platform = computed(() => {
|
||||
return useBackendData.platforms.get((route.params.platform as string).toUpperCase() as Platform);
|
||||
});
|
||||
const projectVersion = computed(() => {
|
||||
return props.version;
|
||||
});
|
||||
@ -64,7 +61,7 @@ async function save() {
|
||||
loading.value = true;
|
||||
try {
|
||||
await useInternalApi(`versions/version/${props.project.id}/${projectVersion.value?.id}/savePluginDependencies`, "post", {
|
||||
platform: platform.value?.name?.toUpperCase(),
|
||||
platform: props.platform.enumName,
|
||||
pluginDependencies: depTable.value.dependencies,
|
||||
});
|
||||
await router.go(0);
|
||||
@ -89,8 +86,8 @@ onMounted(() =>
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal ref="modal" :title="i18n.t('version.edit.platformVersions', [platform?.name])" window-classes="w-200">
|
||||
<DependencyTable ref="depTable" :platform="platform?.enumName" :version="formVersion" />
|
||||
<Modal ref="modal" :title="i18n.t('version.edit.platformVersions', [platform.name])" window-classes="w-200">
|
||||
<DependencyTable ref="depTable" :platform="platform.enumName" :version="formVersion" />
|
||||
|
||||
<Button button-type="primary" class="mt-3" :disabled="loading || !validInput" @click="save">{{ i18n.t("general.save") }}</Button>
|
||||
<template #activator="{ on }">
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script lang="ts" setup>
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { HangarProject, HangarVersion } from "hangar-internal";
|
||||
import { HangarProject, HangarVersion, IPlatform } from "hangar-internal";
|
||||
import { computed, ref } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import Button from "~/lib/components/design/Button.vue";
|
||||
@ -14,26 +14,24 @@ import InputTag from "~/lib/components/ui/InputTag.vue";
|
||||
const props = defineProps<{
|
||||
project: HangarProject;
|
||||
version: HangarVersion;
|
||||
platform: IPlatform;
|
||||
}>();
|
||||
|
||||
const i18n = useI18n();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const platform = computed(() => {
|
||||
return useBackendData.platforms?.get((route.params.platform as string).toUpperCase() as Platform);
|
||||
});
|
||||
const projectVersion = computed(() => {
|
||||
return props.version;
|
||||
});
|
||||
|
||||
const loading = ref(false);
|
||||
const selectedVersions = ref(projectVersion.value?.platformDependencies[platform.value?.name.toUpperCase() as Platform]);
|
||||
const selectedVersions = ref(projectVersion.value?.platformDependencies[props.platform.name.toUpperCase() as Platform]);
|
||||
|
||||
function save() {
|
||||
loading.value = true;
|
||||
useInternalApi(`versions/version/${props.project.id}/${projectVersion.value?.id}/savePlatformVersions`, "post", {
|
||||
platform: platform.value?.name?.toUpperCase(),
|
||||
platform: props.platform.name.toUpperCase(),
|
||||
versions: selectedVersions.value,
|
||||
})
|
||||
.catch((e) => handleRequestError(e))
|
||||
@ -47,8 +45,8 @@ function save() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal :title="i18n.t('version.edit.platformVersions', [platform?.name])" window-classes="w-200">
|
||||
<InputTag v-model="selectedVersions" :options="platform?.possibleVersions" />
|
||||
<Modal :title="i18n.t('version.edit.platformVersions', [platform.name])" window-classes="w-200">
|
||||
<InputTag v-model="selectedVersions" :options="platform.possibleVersions" />
|
||||
|
||||
<Button class="mt-3" :disabled="loading" @click="save">{{ i18n.t("general.save") }}</Button>
|
||||
<template #activator="{ on }">
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 98c38c8a0e4af622538756dca7af769c73d70577
|
||||
Subproject commit e71d470e4a3a34c709c945ce75178acbec8fa2db
|
@ -501,7 +501,7 @@
|
||||
"page": {
|
||||
"subheader": "{0} released this version: {1}",
|
||||
"dependencies": "Dependencies",
|
||||
"platform": "Platform",
|
||||
"platforms": "Platforms",
|
||||
"required": "(required)",
|
||||
"adminMsg": "Approved by {0} {1}",
|
||||
"reviewLogs": "Review logs",
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script lang="ts" setup>
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { useRoute } from "vue-router";
|
||||
import { HangarProject } from "hangar-internal";
|
||||
import { useProjectVersionsInternal } from "~/composables/useApiHelper";
|
||||
import { useErrorRedirect } from "~/lib/composables/useErrorRedirect";
|
||||
@ -24,18 +24,6 @@ if (version && version.value) {
|
||||
versionPlatforms.add(platformKey as Platform);
|
||||
}
|
||||
}
|
||||
|
||||
if (!route.params.platform) {
|
||||
let path = route.path;
|
||||
if (path.endsWith("/")) {
|
||||
path = path.substring(0, path.length - 1);
|
||||
}
|
||||
const [entry] = versionPlatforms;
|
||||
if (!entry) {
|
||||
throw useErrorRedirect(route, 404, "Not found");
|
||||
}
|
||||
await useRouter().replace({ path: `${path}/${entry.toLowerCase()}` });
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -1,12 +1,11 @@
|
||||
<script lang="ts" setup>
|
||||
import { HangarProject, HangarVersion, IPlatform } from "hangar-internal";
|
||||
import { HangarProject, HangarVersion } from "hangar-internal";
|
||||
import { computed, ref } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { User } from "hangar-api";
|
||||
import { useHead } from "@vueuse/head";
|
||||
import { AxiosError } from "axios";
|
||||
import { filesize } from "filesize";
|
||||
import { NamedPermission, Platform, ReviewState, Visibility, PinnedStatus } from "~/types/enums";
|
||||
import { useBackendData } from "~/store/backendData";
|
||||
import { lastUpdated } from "~/lib/composables/useTime";
|
||||
@ -23,15 +22,13 @@ import Link from "~/lib/components/design/Link.vue";
|
||||
import { useSeo } from "~/composables/useSeo";
|
||||
import { projectIconUrl } from "~/composables/useUrlHelper";
|
||||
import { useNotificationStore } from "~/lib/store/notification";
|
||||
import DropdownButton from "~/lib/components/design/DropdownButton.vue";
|
||||
import DropdownItem from "~/lib/components/design/DropdownItem.vue";
|
||||
import PlatformVersionEditModal from "~/components/modals/PlatformVersionEditModal.vue";
|
||||
import Tooltip from "~/lib/components/design/Tooltip.vue";
|
||||
import DownloadButton from "~/components/projects/DownloadButton.vue";
|
||||
import PlatformLogo from "~/components/logos/platforms/PlatformLogo.vue";
|
||||
import TextAreaModal from "~/lib/components/modals/TextAreaModal.vue";
|
||||
import DependencyEditModal from "~/components/modals/DependencyEditModal.vue";
|
||||
import ComingSoon from "~/lib/components/design/ComingSoon.vue";
|
||||
import Spoiler from "~/lib/components/design/Spoiler.vue";
|
||||
|
||||
const route = useRoute();
|
||||
const i18n = useI18n();
|
||||
@ -45,12 +42,10 @@ const props = defineProps<{
|
||||
user: User;
|
||||
}>();
|
||||
|
||||
const p = ref<Platform>(((route.params.platform as string) || "").toUpperCase() as Platform);
|
||||
const projectVersion = computed<HangarVersion | undefined>(() => props.version);
|
||||
if (!projectVersion.value) {
|
||||
throw useErrorRedirect(route, 404, "Not found");
|
||||
}
|
||||
const platform = ref<IPlatform | undefined>(useBackendData.platforms.get(p.value));
|
||||
const isReviewStateChecked = computed<boolean>(
|
||||
() => projectVersion.value?.reviewState === ReviewState.PARTIALLY_REVIEWED || projectVersion.value?.reviewState === ReviewState.REVIEWED
|
||||
);
|
||||
@ -69,12 +64,22 @@ const requiresConfirmation = computed<boolean>(() => {
|
||||
return false;
|
||||
});
|
||||
|
||||
const sortedDependencies = computed(() => {
|
||||
if (platform.value && projectVersion.value && projectVersion.value.pluginDependencies[p.value]) {
|
||||
return [...projectVersion.value.pluginDependencies[p.value]].sort((a, b) => Number(b.required) - Number(a.required));
|
||||
const platformsWithDependencies = computed(() => {
|
||||
const platforms = [];
|
||||
for (const platform of props.versionPlatforms) {
|
||||
if ((projectVersion.value && projectVersion.value.pluginDependencies[platform]) || hasPerms(NamedPermission.EDIT_VERSION)) {
|
||||
platforms.push(platform);
|
||||
}
|
||||
}
|
||||
return platforms;
|
||||
});
|
||||
|
||||
function sortedDependencies(platform: Platform) {
|
||||
if (projectVersion.value && projectVersion.value.pluginDependencies[platform]) {
|
||||
return [...projectVersion.value.pluginDependencies[platform]].sort((a, b) => Number(b.required) - Number(a.required));
|
||||
}
|
||||
return [];
|
||||
});
|
||||
}
|
||||
|
||||
useHead(
|
||||
useSeo(
|
||||
@ -85,11 +90,6 @@ useHead(
|
||||
)
|
||||
);
|
||||
|
||||
function setPlatform(plat: Platform) {
|
||||
p.value = plat;
|
||||
platform.value = useBackendData.platforms.get(plat);
|
||||
}
|
||||
|
||||
async function savePage(content: string) {
|
||||
try {
|
||||
await useInternalApi(`versions/version/${props.project.id}/${projectVersion.value?.id}/saveDescription`, "post", {
|
||||
@ -155,8 +155,8 @@ async function restoreVersion() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="projectVersion && platform" class="flex <sm:flex-col flex-wrap md:flex-nowrap gap-4">
|
||||
<section class="basis-full md:basis-9/12 flex-grow overflow-auto">
|
||||
<div v-if="projectVersion" class="flex <sm:flex-col flex-wrap md:flex-nowrap gap-4">
|
||||
<section class="basis-full md:basis-11/15 flex-grow">
|
||||
<div class="flex flex-wrap gap-2 justify-between">
|
||||
<div>
|
||||
<h2 class="text-3xl sm:inline-flex items-center gap-x-1">
|
||||
@ -166,10 +166,10 @@ async function restoreVersion() {
|
||||
<h3>
|
||||
<span class="inline-flex <sm:flex-wrap ml-1">
|
||||
{{ i18n.t("version.page.subheader", [projectVersion.author, lastUpdated(new Date(projectVersion.createdAt))]) }}
|
||||
<span v-if="projectVersion.downloads[platform?.enumName]?.fileInfo?.sizeBytes" class="inline-flex items-center sm:ml-3">
|
||||
<!--<span v-if="projectVersion.downloads[platform?.enumName]?.fileInfo?.sizeBytes" class="inline-flex items-center sm:ml-3">
|
||||
<IconMdiFile class="mr-1" />
|
||||
{{ filesize(projectVersion.downloads[platform.enumName].fileInfo.sizeBytes) }}
|
||||
</span>
|
||||
</span>-->
|
||||
</span>
|
||||
</h3>
|
||||
<em v-if="hasPerms(NamedPermission.REVIEWER) && projectVersion.approvedBy" class="text-lg ml-1">
|
||||
@ -181,19 +181,7 @@ async function restoreVersion() {
|
||||
<Tooltip v-if="requiresConfirmation" :content="i18n.t('version.page.unsafeWarning')">
|
||||
<IconMdiAlertCircleOutline class="text-2xl" />
|
||||
</Tooltip>
|
||||
<DropdownButton v-if="versionPlatforms.size > 1" class="inline" button-size="large">
|
||||
<template #button-label>
|
||||
<PlatformLogo :platform="platform?.enumName" :size="24" class="mr-1 flex-shrink-0" />
|
||||
{{ platform?.name }}
|
||||
</template>
|
||||
<template #default="{ close }">
|
||||
<DropdownItem v-for="plat in versionPlatforms" :key="plat" :to="plat.toLowerCase()" class="inline-flex" @click="setPlatform(plat) || close()">
|
||||
<PlatformLogo :platform="plat" :size="24" class="mr-1 flex-shrink-0" />
|
||||
{{ useBackendData.platforms?.get(plat)?.name }}
|
||||
</DropdownItem>
|
||||
</template>
|
||||
</DropdownButton>
|
||||
<DownloadButton :version="projectVersion" :project="project" :platform="p" :show-single-platform="false" />
|
||||
<DownloadButton :version="projectVersion" :project="project" :show-single-platform="false" :show-versions="false" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -211,7 +199,7 @@ async function restoreVersion() {
|
||||
<Markdown v-else :raw="projectVersion.description" />
|
||||
</Card>
|
||||
</section>
|
||||
<section class="basis-full md:basis-3/12 flex-grow space-y-4">
|
||||
<section class="basis-full md:basis-4/15 flex-grow space-y-4">
|
||||
<Card v-if="hasPerms(NamedPermission.DELETE_VERSION) || hasPerms(NamedPermission.VIEW_LOGS) || hasPerms(NamedPermission.REVIEWER)">
|
||||
<template #header>
|
||||
<h3>{{ i18n.t("version.page.manage") }}</h3>
|
||||
@ -328,38 +316,51 @@ async function restoreVersion() {
|
||||
<Card>
|
||||
<template #header>
|
||||
<div class="inline-flex w-full">
|
||||
<h3 class="flex-grow">{{ i18n.t("version.page.platform") }}</h3>
|
||||
<PlatformVersionEditModal v-if="hasPerms(NamedPermission.EDIT_VERSION)" :project="project" :version="version" />
|
||||
<h3 class="flex-grow">{{ i18n.t("version.page.platforms") }}</h3>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="flex items-center">
|
||||
<PlatformLogo :platform="platform?.enumName" :size="24" class="mr-1" />
|
||||
{{ platform?.name }}
|
||||
{{ projectVersion?.platformDependenciesFormatted[platform?.enumName] }}
|
||||
<div v-for="platform in versionPlatforms" :key="platform" class="flex items-center">
|
||||
<PlatformLogo :platform="platform" :size="24" class="mr-1" />
|
||||
{{ useBackendData.platforms.get(platform).name }}
|
||||
({{ projectVersion?.platformDependenciesFormatted[platform] }})
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<Card v-if="(platform?.name && projectVersion?.pluginDependencies[platform.enumName]) || hasPerms(NamedPermission.EDIT_VERSION)">
|
||||
<Card>
|
||||
<template #header>
|
||||
<div class="inline-flex w-full">
|
||||
<h3 class="flex-grow">{{ i18n.t("version.page.dependencies") }}</h3>
|
||||
<DependencyEditModal :project="project" :version="version" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<ul>
|
||||
<li v-for="dep in sortedDependencies" :key="dep.name">
|
||||
<Link
|
||||
:href="dep.externalUrl || undefined"
|
||||
:target="dep.externalUrl ? '_blank' : undefined"
|
||||
:to="!!dep.namespace ? { name: 'user-project', params: { user: dep.namespace.owner, project: dep.namespace.slug } } : undefined"
|
||||
>
|
||||
{{ dep.name }}
|
||||
<small v-if="!dep.required">({{ i18n.t("general.optional") }})</small>
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
<div v-for="platform in platformsWithDependencies" :key="platform" class="py-1">
|
||||
<Spoiler :with-line="projectVersion?.pluginDependencies[platform] !== undefined">
|
||||
<template #title>
|
||||
<div class="flex inline-flex items-center gap-1">
|
||||
<PlatformLogo :platform="platform" :size="24" />
|
||||
{{ useBackendData.platforms.get(platform).name }}
|
||||
<DependencyEditModal :project="project" :version="version" :platform="useBackendData.platforms.get(platform)" />
|
||||
</div>
|
||||
</template>
|
||||
<template #content>
|
||||
<div>
|
||||
<ul>
|
||||
<li v-for="dep in sortedDependencies(platform)" :key="dep.name">
|
||||
<Link
|
||||
:href="dep.externalUrl || undefined"
|
||||
:target="dep.externalUrl ? '_blank' : undefined"
|
||||
:to="!!dep.namespace ? { name: 'user-project', params: { user: dep.namespace.owner, project: dep.namespace.slug } } : undefined"
|
||||
>
|
||||
{{ dep.name }}
|
||||
<small v-if="!dep.required">({{ i18n.t("general.optional") }})</small>
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
</Spoiler>
|
||||
</div>
|
||||
</Card>
|
||||
</section>
|
||||
</div>
|
Loading…
Reference in New Issue
Block a user