Add platform versions to download dropdown

This commit is contained in:
Nassim Jahnke 2022-07-02 14:25:32 +02:00
parent 0cc6d06c4c
commit f9c4d652df
No known key found for this signature in database
GPG Key ID: 6BE3B555EBC5982B
11 changed files with 100 additions and 39 deletions

View File

@ -1,7 +1,2 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
cd frontend
pnpm prettier --write src/types/generated/**.*
pnpm lint-staged

View File

@ -1,10 +1,11 @@
<script lang="ts" setup>
import Button from "~/lib/components/design/Button.vue";
import { useI18n } from "vue-i18n";
import { HangarProject, HangarVersion, PinnedVersion } from "hangar-internal";
import { computed, ref } from "vue";
import { HangarProject, PinnedVersion } from "hangar-internal";
import { computed } from "vue";
import { Platform } from "~/types/enums";
import DropdownButton from "~/lib/components/design/DropdownButton.vue";
import { formatVersionNumbers } from "~/composables/useVersionHelper";
import { useBackendDataStore } from "~/store/backendData";
import DropdownItem from "~/lib/components/design/DropdownItem.vue";
import PlatformLogo from "~/components/logos/PlatformLogo.vue";
@ -54,7 +55,7 @@ const external = computed(() => false);
</span>
</template>
<DropdownItem
v-for="platform in pinnedVersion.platforms"
v-for="(v, platform) in pinnedVersion.platformDependencies"
:key="platform"
class="flex items-center"
:href="downloadLink(platform, pinnedVersion)"
@ -63,6 +64,7 @@ const external = computed(() => false);
>
<PlatformLogo :platform="platform" :size="24" class="mr-1" />
{{ backendData.platforms?.get(platform).name }}
<span class="ml-1">({{ formatVersionNumbers(v) }})</span>
</DropdownItem>
</DropdownButton>
@ -90,6 +92,7 @@ const external = computed(() => false);
>
<PlatformLogo :platform="p" :size="24" class="mr-1" />
{{ backendData.platforms?.get(p).name }}
<span v-if="v.platformDependencies" class="ml-1">({{ formatVersionNumbers(v.platformDependencies[p]) }})</span>
</DropdownItem>
</DropdownButton>
</div>

@ -1 +1 @@
Subproject commit 7480c33fa1aac6127a2f55ac9cac4d3b9e5327f5
Subproject commit c9e053c9e6af57301b514520876bd72ad3e97632

View File

@ -105,7 +105,7 @@ useHead(useSeo(props.project.name, props.project.description, route, projectIcon
<br />
<div class="inline-flex items-center">
<Tag :name="version.channel.name" :color="{ background: version.channel.color }" />
<PlatformLogo v-for="(platform, idx) in version.platforms" :key="`${idx}-${platform}`" :platform="platform" :size="24" class="ml-1" />
<PlatformLogo v-for="(v, p) in version.platformDependencies" :key="p" :platform="p" :size="24" class="ml-1" />
</div>
</router-link>
</div>

View File

@ -54,7 +54,7 @@ useHead(useSeo(i18n.t("userActionLog.title"), null, route, null));
</template>
<template v-else-if="item.version">
<Link :to="'/' + item.project.owner + '/' + item.project.slug + '/versions/' + item.version.versionString">
{{ `${item.project.owner}/${item.project.slug}/${item.version.versionString}/${item.version.platforms[0].toLowerCase()}` }}
{{ `${item.project.owner}/${item.project.slug}/${item.version.versionString}` }}
</Link>
</template>
<template v-else-if="item.project && item.project.owner">

View File

@ -14,34 +14,23 @@ declare module '@vue/runtime-core' {
IconMdiCalendar: typeof import('~icons/mdi/calendar')['default']
IconMdiCheck: typeof import('~icons/mdi/check')['default']
IconMdiCheckBold: typeof import('~icons/mdi/check-bold')['default']
IconMdiCheckboxMarkedCircle: typeof import('~icons/mdi/checkbox-marked-circle')['default']
IconMdiCheckCircleOutline: typeof import('~icons/mdi/check-circle-outline')['default']
IconMdiCircle: typeof import('~icons/mdi/circle')['default']
IconMdiClipboardOutline: typeof import('~icons/mdi/clipboard-outline')['default']
IconMdiClose: typeof import('~icons/mdi/close')['default']
IconMdiCloseCircle: typeof import('~icons/mdi/close-circle')['default']
IconMdiContentCopy: typeof import('~icons/mdi/content-copy')['default']
IconMdiContentSave: typeof import('~icons/mdi/content-save')['default']
IconMdiDelete: typeof import('~icons/mdi/delete')['default']
IconMdiDiamond: typeof import('~icons/mdi/diamond')['default']
IconMdiDiamondStone: typeof import('~icons/mdi/diamond-stone')['default']
IconMdiDownload: typeof import('~icons/mdi/download')['default']
IconMdiDownloadOutline: typeof import('~icons/mdi/download-outline')['default']
IconMdiEye: typeof import('~icons/mdi/eye')['default']
IconMdiEyeOff: typeof import('~icons/mdi/eye-off')['default']
IconMdiFile: typeof import('~icons/mdi/file')['default']
IconMdiFlag: typeof import('~icons/mdi/flag')['default']
IconMdiHome: typeof import('~icons/mdi/home')['default']
IconMdiInformation: typeof import('~icons/mdi/information')['default']
IconMdiKeyOutline: typeof import('~icons/mdi/key-outline')['default']
IconMdiListStatus: typeof import('~icons/mdi/list-status')['default']
IconMdiMenu: typeof import('~icons/mdi/menu')['default']
IconMdiMenuDown: typeof import('~icons/mdi/menu-down')['default']
IconMdiOpenInNew: typeof import('~icons/mdi/open-in-new')['default']
IconMdiPencil: typeof import('~icons/mdi/pencil')['default']
IconMdiPin: typeof import('~icons/mdi/pin')['default']
IconMdiPinOff: typeof import('~icons/mdi/pin-off')['default']
IconMdiPlay: typeof import('~icons/mdi/play')['default']
IconMdiPlus: typeof import('~icons/mdi/plus')['default']
IconMdiSortVariant: typeof import('~icons/mdi/sort-variant')['default']
IconMdiStar: typeof import('~icons/mdi/star')['default']

View File

@ -1,8 +1,8 @@
declare module "hangar-internal" {
import type { Joinable, Table } from "hangar-internal";
import type { Project, ProjectNamespace } from "hangar-api";
import type { ProjectCategory, Visibility } from "~/types/enums";
import { Platform } from "~/types/enums";
import type {Joinable, Table} from "hangar-internal";
import type {Project, ProjectNamespace} from "hangar-api";
import type {ProjectCategory, Visibility} from "~/types/enums";
import {Platform} from "~/types/enums";
interface ProjectOwner {
id: number;
@ -30,7 +30,7 @@ declare module "hangar-internal" {
interface PinnedVersion {
type: 'channel' | 'version';
name: string;
platforms: Platform[];
platformDependencies: Record<Platform, string[]>;
channel: ProjectChannel;
fileInfo: FileInfo | null;
externalUrl: string | null;

View File

@ -103,9 +103,9 @@ public interface HangarVersionsDAO {
List<HangarVersion> getVersionsWithVersionString(String author, String slug, String versionString, @Define boolean canSeeHidden, @Define Long userId);
@SqlQuery("""
SELECT pv."type",
SELECT pv.version_id,
pv."type",
pv.version_string AS name,
pv.platforms,
pc.name pc_name,
pc.created_at pc_created_at,
pc.color pc_color,

View File

@ -14,15 +14,17 @@ import io.papermc.hangar.model.identified.ProjectIdentified;
import io.papermc.hangar.model.internal.Joinable;
import io.papermc.hangar.model.internal.user.JoinableMember;
import io.papermc.hangar.model.internal.versions.HangarVersion;
import org.jdbi.v3.core.enums.EnumByName;
import org.jdbi.v3.core.mapper.Nested;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jdbi.v3.core.enums.EnumByName;
import org.jdbi.v3.core.mapper.Nested;
import org.jetbrains.annotations.Nullable;
public class HangarProject extends Project implements Joinable<ProjectRoleTable>, ProjectIdentified {
private final long id;
@ -118,7 +120,7 @@ public class HangarProject extends Project implements Joinable<ProjectRoleTable>
private final long starCount;
private final long watcherCount;
public HangarProjectInfo(int publicVersions, int flagCount, int noteCount, long starCount, long watcherCount) {
public HangarProjectInfo(final int publicVersions, final int flagCount, final int noteCount, final long starCount, final long watcherCount) {
this.publicVersions = publicVersions;
this.flagCount = flagCount;
this.noteCount = noteCount;
@ -161,8 +163,66 @@ public class HangarProject extends Project implements Joinable<ProjectRoleTable>
}
public record PinnedVersion(Type type, String name, Set<Platform> platforms, @Nested("pc") ProjectChannel channel,
@Nested("fi") @Nullable FileInfo fileInfo, @Nullable String externalUrl) {
public static class PinnedVersion {
private final long versionId;
private final Type type;
private final String name;
private final ProjectChannel channel;
private final FileInfo fileInfo;
private final String externalUrl;
private final Map<Platform, Set<String>> platformDependencies;
public PinnedVersion(long versionId, Type type, String name, @Nested("pc") ProjectChannel channel,
@Nested("fi") @Nullable FileInfo fileInfo, @Nullable String externalUrl) {
this.versionId = versionId;
this.type = type;
this.name = name;
this.channel = channel;
this.fileInfo = fileInfo;
this.externalUrl = externalUrl;
this.platformDependencies = new EnumMap<>(Platform.class);
}
public long getVersionId() {
return versionId;
}
public Type getType() {
return type;
}
public String getName() {
return name;
}
public Map<Platform, Set<String>> getPlatformDependencies() {
return platformDependencies;
}
public ProjectChannel getChannel() {
return channel;
}
public FileInfo getFileInfo() {
return fileInfo;
}
public String getExternalUrl() {
return externalUrl;
}
@Override
public String toString() {
return "PinnedVersion[" +
"versionId=" + versionId + ", " +
"type=" + type + ", " +
"name=" + name + ", " +
"platforms=" + platformDependencies + ", " +
"channel=" + channel + ", " +
"fileInfo=" + fileInfo + ", " +
"externalUrl=" + externalUrl + ']';
}
@EnumByName
@JsonFormat(shape = JsonFormat.Shape.STRING)

View File

@ -10,6 +10,7 @@ import io.papermc.hangar.db.dao.internal.versions.HangarVersionsDAO;
import io.papermc.hangar.db.dao.v1.VersionsApiDAO;
import io.papermc.hangar.exceptions.HangarApiException;
import io.papermc.hangar.model.api.project.Project;
import io.papermc.hangar.model.api.project.version.PluginDependency;
import io.papermc.hangar.model.api.requests.RequestPagination;
import io.papermc.hangar.model.common.Permission;
import io.papermc.hangar.model.common.Platform;
@ -42,6 +43,7 @@ import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;
import org.apache.commons.lang3.StringUtils;
@ -128,8 +130,12 @@ public class ProjectService extends HangarComponent {
final Map<Platform, HangarVersion> mainChannelVersions = new EnumMap<>(Platform.class);
for (final Platform platform : Platform.getValues()) {
final HangarVersion version = getLastVersion(author, slug, platform, config.channels.getNameDefault());
final HangarVersion version = getLastVersion(author, slug, platform, config.channels.getNameDefault());
if (version != null) {
if (version.getPlatformDependencies().isEmpty()) {
version.getPlatformDependencies().putAll(versionsApiDAO.getPlatformDependencies(version.getId()));
}
mainChannelVersions.put(platform, version);
}
}

View File

@ -3,23 +3,27 @@ package io.papermc.hangar.service.internal.versions;
import io.papermc.hangar.HangarComponent;
import io.papermc.hangar.db.dao.internal.table.versions.PinnedProjectVersionsDAO;
import io.papermc.hangar.db.dao.internal.versions.HangarVersionsDAO;
import io.papermc.hangar.db.dao.v1.VersionsApiDAO;
import io.papermc.hangar.model.db.versions.PinnedProjectVersionTable;
import io.papermc.hangar.model.internal.projects.HangarProject;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
@Transactional
public class PinnedVersionService extends HangarComponent {
private final HangarVersionsDAO hangarVersionsDAO;
private final VersionsApiDAO versionsApiDAO;
private final PinnedProjectVersionsDAO pinnedProjectVersionsDAO;
@Autowired
public PinnedVersionService(final HangarVersionsDAO hangarVersionsDAO, final PinnedProjectVersionsDAO pinnedProjectVersionsDAO) {
public PinnedVersionService(final HangarVersionsDAO hangarVersionsDAO, final VersionsApiDAO versionsApiDAO, final PinnedProjectVersionsDAO pinnedProjectVersionsDAO) {
this.hangarVersionsDAO = hangarVersionsDAO;
this.versionsApiDAO = versionsApiDAO;
this.pinnedProjectVersionsDAO = pinnedProjectVersionsDAO;
}
@ -33,6 +37,10 @@ public class PinnedVersionService extends HangarComponent {
}
public List<HangarProject.PinnedVersion> getPinnedVersions(final long projectId) {
return this.hangarVersionsDAO.getPinnedVersions(projectId);
final List<HangarProject.PinnedVersion> versions = this.hangarVersionsDAO.getPinnedVersions(projectId);
for (final HangarProject.PinnedVersion version : versions) {
version.getPlatformDependencies().putAll(versionsApiDAO.getPlatformDependencies(version.getVersionId()));
}
return versions;
}
}