version dependencies mgmt improvements

This commit is contained in:
Jake Potrebic 2021-03-16 22:05:27 -07:00
parent d8bbc9e865
commit dfe3ba6a37
No known key found for this signature in database
GPG Key ID: 7C58557EC9C421F8
13 changed files with 199 additions and 239 deletions

View File

@ -6,111 +6,119 @@
<th>{{ $t('general.name') }}</th>
<th>{{ $t('general.required') }}</th>
<th>{{ $t('general.link') }}</th>
<th>{{ $t('general.delete') }}</th>
<th v-if="!noEditing">{{ $t('general.delete') }}</th>
</tr>
</thead>
<tbody>
<tr v-for="dep in version.pluginDependencies[platform]" :key="`${platform}-${dep.name}`">
<td>{{ dep.name }}</td>
<!--TODO having ripple here produces console errors?-->
<td><v-simple-checkbox v-model="dep.required" :ripple="false" /></td>
<td>
<v-text-field
v-model.trim="dep.externalUrl"
dense
hide-details
:placeholder="$t('version.new.form.externalUrl')"
:disabled="dep.namespace !== null && Object.keys(dep.namespace).length !== 0"
:rules="
dep.namespace !== null && Object.keys(dep.namespace).length !== 0 ? [] : [$util.$vc.require('version.new.form.externalUrl')]
"
clearable
/>
<v-autocomplete
v-model="dep.namespace"
dense
hide-details
hide-no-data
:placeholder="$t('version.new.form.hangarProject')"
class="mb-2"
:items="results[dep.name]"
:item-text="getNamespace"
:item-value="getNamespace"
return-object
clearable
auto-select-first
:disabled="!!dep.externalUrl"
:rules="!!dep.externalUrl ? [] : [$util.$vc.require('version.new.form.hangarProject')]"
@update:search-input="onSearch($event, dep.name)"
/>
</td>
<td>
<v-btn icon color="error" @click="deleteDep(dep.name)">
<v-icon>mdi-delete</v-icon>
</v-btn>
</td>
</tr>
<tr v-for="(newDep, index) in newDeps" :key="`newDep-${index}`">
<td>
<v-text-field
v-model.trim="newDep.name"
dense
hide-details
flat
:label="$t('general.name')"
:rules="[$util.$vc.require($t('general.name'))]"
/>
</td>
<td><v-simple-checkbox v-model="newDep.required" :ripple="false" /></td>
<td>
<v-text-field
v-model.trim="newDep.externalUrl"
dense
hide-details
:placeholder="$t('version.new.form.externalUrl')"
:disabled="newDep.namespace !== null && Object.keys(newDep.namespace).length !== 0"
:rules="
newDep.namespace !== null && Object.keys(newDep.namespace).length !== 0
? []
: [$util.$vc.require('version.new.form.externalUrl')]
"
clearable
/>
<v-autocomplete
v-model="newDep.namespace"
dense
hide-details
hide-no-data
:placeholder="$t('version.new.form.hangarProject')"
class="mb-2"
:items="newDepResults[index]"
:item-text="getNamespace"
:item-value="getNamespace"
return-object
clearable
auto-select-first
:disabled="!!newDep.externalUrl"
:rules="!!newDep.externalUrl ? [] : [$util.$vc.require('version.new.form.hangarProject')]"
@update:search-input="onNewDepSearch($event, index)"
/>
</td>
<td>
<v-btn icon color="error" @click="deleteNewDep(index)">
<v-icon>mdi-delete</v-icon>
</v-btn>
</td>
</tr>
<template v-if="!isNew">
<tr v-for="dep in version.pluginDependencies[platform]" :key="`${platform}-${dep.name}`">
<td>{{ dep.name }}</td>
<!--TODO having ripple here produces console errors?-->
<td><v-simple-checkbox v-model="dep.required" :ripple="false" /></td>
<td>
<v-text-field
v-model.trim="dep.externalUrl"
dense
hide-details
:placeholder="$t('version.new.form.externalUrl')"
:disabled="dep.namespace !== null && Object.keys(dep.namespace).length !== 0"
:rules="
dep.namespace !== null && Object.keys(dep.namespace).length !== 0 ? [] : [$util.$vc.require('version.new.form.externalUrl')]
"
clearable
/>
<v-autocomplete
v-model="dep.namespace"
dense
hide-details
hide-no-data
:placeholder="$t('version.new.form.hangarProject')"
class="mb-2"
:items="results[dep.name]"
:item-text="getNamespace"
:item-value="getNamespace"
return-object
clearable
auto-select-first
:disabled="!!dep.externalUrl"
:rules="!!dep.externalUrl ? [] : [$util.$vc.require('version.new.form.hangarProject')]"
@update:search-input="onSearch($event, dep.name)"
/>
</td>
<td v-if="!noEditing">
<v-btn icon color="error" @click="deleteDep(dep.name)">
<v-icon>mdi-delete</v-icon>
</v-btn>
</td>
</tr>
</template>
<template v-if="!noEditing || isNew">
<tr v-for="(newDep, index) in newDeps" :key="`newDep-${index}`">
<td>
<v-text-field
v-model.trim="newDep.name"
dense
hide-details
flat
:label="$t('general.name')"
:rules="[$util.$vc.require($t('general.name'))]"
:disabled="noEditing"
/>
</td>
<td><v-simple-checkbox v-model="newDep.required" :ripple="false" /></td>
<td>
<v-text-field
v-model.trim="newDep.externalUrl"
dense
hide-details
:placeholder="$t('version.new.form.externalUrl')"
:disabled="newDep.namespace !== null && Object.keys(newDep.namespace).length !== 0"
:rules="
newDep.namespace !== null && Object.keys(newDep.namespace).length !== 0
? []
: [$util.$vc.require('version.new.form.externalUrl')]
"
clearable
/>
<v-autocomplete
v-model="newDep.namespace"
dense
hide-details
hide-no-data
:placeholder="$t('version.new.form.hangarProject')"
class="mb-2"
:items="newDepResults[index]"
:item-text="getNamespace"
:item-value="getNamespace"
return-object
clearable
auto-select-first
:disabled="!!newDep.externalUrl"
:rules="!!newDep.externalUrl ? [] : [$util.$vc.require('version.new.form.hangarProject')]"
@update:search-input="onNewDepSearch($event, index)"
/>
</td>
<td v-if="!noEditing">
<v-btn icon color="error" @click="deleteNewDep(index)">
<v-icon>mdi-delete</v-icon>
</v-btn>
</td>
</tr>
</template>
</tbody>
</v-simple-table>
<v-btn block color="primary" @click="addNewDep">
<v-icon left>mdi-plus</v-icon>
{{ $t('general.add') }}
</v-btn>
<div v-if="!noEditing" class="ma-2">
<v-btn color="primary" block @click="addNewDep">
<v-icon left>mdi-plus</v-icon>
{{ $t('general.add') }}
</v-btn>
</div>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue, Watch } from 'nuxt-property-decorator';
import { Component, Prop, PropSync, Vue, Watch } from 'nuxt-property-decorator';
import { PropType } from 'vue';
import { DependencyVersion, PaginatedResult, PluginDependency, Project, ProjectNamespace } from 'hangar-api';
import { Platform } from '~/types/enums';
@ -119,7 +127,6 @@ import { Platform } from '~/types/enums';
export default class DependencyTable extends Vue {
results: Record<string, ProjectNamespace[]> = {};
newDepResults: ProjectNamespace[][] = [];
newDeps: Partial<PluginDependency>[] = [];
@Prop({ type: Object as PropType<DependencyVersion>, required: true })
version!: DependencyVersion;
@ -127,6 +134,15 @@ export default class DependencyTable extends Vue {
@Prop({ type: String as PropType<Platform>, required: true })
platform!: Platform;
@Prop({ type: Boolean, default: false })
noEditing!: boolean;
@Prop({ type: Boolean, default: false })
isNew!: boolean;
@PropSync('newDepsProp', { type: Array as PropType<Partial<PluginDependency>[]>, default: () => [] })
newDeps!: Partial<PluginDependency>[];
addNewDep() {
this.newDeps.push({
name: undefined,
@ -146,7 +162,14 @@ export default class DependencyTable extends Vue {
this.$api
.request<PaginatedResult<Project>>(`projects?relevance=true&limit=25&offset=0&q=${val}`)
.then((projects) => {
this.results[name].push(...projects.result.map((p) => p.namespace));
if (!this.results[name]) {
this.$set(this.results, name, []);
}
this.results[name].push(
...projects.result
.filter((p) => p.namespace.owner !== this.$route.params.author || p.namespace.slug !== this.$route.params.slug)
.map((p) => p.namespace)
);
})
.catch(console.error);
}

View File

@ -111,14 +111,14 @@
<v-checkbox
v-for="version in platform.possibleVersions"
:key="`${platform.name}-${version}`"
v-model="pendingVersion.platformDependencies[platform.name.toUpperCase()]"
v-model="pendingVersion.platformDependencies[platform.enumName]"
:rules="platformVersionRules"
class="platform-version-checkbox"
dense
hide-details
:label="version"
:value="version"
@change="togglePlatformVersion($event, platform.name.toUpperCase())"
@change="togglePlatformVersion($event, platform.enumName)"
/>
</v-col>
</v-row>
@ -128,54 +128,14 @@
<v-card-title class="pb-0">{{ $t('version.new.form.dependencies') }}</v-card-title>
<template v-for="platform in platformsForPluginDeps">
<v-card-subtitle :key="`${platform}-deps`" class="mt-3 pb-0">{{ $store.state.platforms.get(platform).name }}</v-card-subtitle>
<!--TODO figure out how to make this work with the DependencyTable component-->
<v-simple-table :key="`${platform}-deps-table`" class="ma-2">
<thead>
<tr>
<th>Name</th>
<th>Required?</th>
<th>Link</th>
</tr>
</thead>
<tbody>
<tr v-for="dep in pendingVersion.pluginDependencies[platform]" :key="`${platform}-${dep.name}`">
<td>{{ dep.name }}</td>
<!--TODO having ripple here produces console errors?-->
<td><v-simple-checkbox v-model="dep.required" :ripple="false" /></td>
<td>
<v-text-field
v-model="dep.externalUrl"
dense
hide-details
placeholder="External Link"
:disabled="dep.namespace !== null && Object.keys(dep.namespace).length !== 0"
:rules="
dep.namespace !== null && Object.keys(dep.namespace).length !== 0
? []
: [$util.$vc.require('version.new.form.externalUrl')]
"
clearable
/>
<v-autocomplete
v-model="dep.namespace"
dense
hide-details
hide-no-data
placeholder="Hangar Project"
class="mb-2"
:items="hangarProjectSearchResults"
:item-text="getNamespace"
return-object
clearable
auto-select-first
:disabled="!!dep.externalUrl"
:rules="!!dep.externalUrl ? [] : [$util.$vc.require('version.new.form.hangarProject')]"
@update:search-input="onSearch"
/>
</td>
</tr>
</tbody>
</v-simple-table>
<DependencyTable
:key="`${platform}-deps-table`"
:platform="platform"
:version="pendingVersion"
:no-editing="pendingVersion.isFile"
:new-deps-prop="pendingVersion.pluginDependencies[platform]"
:is-new="!pendingVersion.isFile"
/>
</template>
</v-card>
<v-row class="mt-3">
@ -210,17 +170,18 @@
import { Component } from 'nuxt-property-decorator';
import remove from 'lodash-es/remove';
import { IPlatform, PendingVersion, ProjectChannel } from 'hangar-internal';
import { PaginatedResult, Project, ProjectNamespace } from 'hangar-api';
import { ProjectNamespace } from 'hangar-api';
import { HangarProjectMixin } from '~/components/mixins';
import { ProjectPermission } from '~/utils/perms';
import { NamedPermission, Platform } from '~/types/enums';
import MarkdownEditor from '~/components/MarkdownEditor.vue';
import NewChannelModal from '~/components/modals/NewChannelModal.vue';
import { RootState } from '~/store';
import DependencyTable from '~/components/modals/versions/DependencyTable.vue';
// TODO implement setting up dependencies
@Component({
components: { NewChannelModal, MarkdownEditor },
components: { DependencyTable, NewChannelModal, MarkdownEditor },
})
@ProjectPermission(NamedPermission.CREATE_VERSION)
export default class ProjectVersionsNewPage extends HangarProjectMixin {
@ -229,8 +190,7 @@ export default class ProjectVersionsNewPage extends HangarProjectMixin {
pendingVersion: PendingVersion | null = null;
validForm: boolean = false;
channels: ProjectChannel[] = [];
selectedPlatforms: string[] = [];
hangarProjectSearchResults: ProjectNamespace[] = [];
selectedPlatforms: Platform[] = [];
loading = {
create: false,
submit: false,
@ -242,19 +202,6 @@ export default class ProjectVersionsNewPage extends HangarProjectMixin {
};
}
onSearch(val: string) {
if (val) {
console.log(val);
this.$api
.request<PaginatedResult<Project>>(`projects?relevance=true&limit=25&offset=0&q=${val}`)
.then((projects) => {
// console.log(projects.result);
this.hangarProjectSearchResults = projects.result.map((p) => p.namespace);
})
.catch(console.error);
}
}
get canCreate(): boolean {
return (!!this.file || !!this.url) && !(!!this.file && !!this.url);
}
@ -276,10 +223,14 @@ export default class ProjectVersionsNewPage extends HangarProjectMixin {
get platformsForPluginDeps(): Platform[] {
const platforms: Platform[] = [];
for (const key of Object.keys(this.pendingVersion!.pluginDependencies)) {
if (this.pendingVersion?.pluginDependencies[key as Platform].length) {
platforms.push(key as Platform);
if (this.pendingVersion?.isFile) {
for (const key of Object.keys(this.pendingVersion!.pluginDependencies)) {
if (this.pendingVersion?.pluginDependencies[key as Platform].length) {
platforms.push(key as Platform);
}
}
} else {
platforms.push(...this.selectedPlatforms);
}
return platforms;
}
@ -342,7 +293,7 @@ export default class ProjectVersionsNewPage extends HangarProjectMixin {
}
}
togglePlatformVersion(value: string[], platform: string) {
togglePlatformVersion(value: string[], platform: Platform) {
if (value.length === 0 && this.selectedPlatforms.includes(platform)) {
this.$delete(this.selectedPlatforms, this.selectedPlatforms.indexOf(platform));
} else if (!this.selectedPlatforms.includes(platform)) {
@ -371,7 +322,7 @@ export default class ProjectVersionsNewPage extends HangarProjectMixin {
.catch<any>(this.$util.handlePageRequestError);
for (const platformDependenciesKey in this.pendingVersion?.platformDependencies) {
if (this.pendingVersion?.platformDependencies[platformDependenciesKey as Platform].length) {
this.selectedPlatforms.push(platformDependenciesKey);
this.selectedPlatforms.push(platformDependenciesKey as Platform);
}
}
this.loading.create = false;

View File

@ -1,6 +1,6 @@
declare module 'hangar-internal' {
import { Model, TagColor } from 'hangar-api';
import { ProjectCategory } from '~/types/enums';
import { Platform, ProjectCategory } from '~/types/enums';
interface Table extends Model {
id: number;
@ -25,6 +25,7 @@ declare module 'hangar-internal' {
interface IPlatform {
name: string;
enumName: Platform;
category: 'Server' | 'Proxy';
url: string;
tagColor: TagColor;

View File

@ -7,12 +7,12 @@ import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.papermc.hangar.config.hangar.HangarConfig;
import io.papermc.hangar.model.Announcement;
import io.papermc.hangar.model.common.Color;
import io.papermc.hangar.model.common.NamedPermission;
import io.papermc.hangar.model.common.Platform;
import io.papermc.hangar.model.common.projects.Category;
import io.papermc.hangar.model.common.projects.FlagReason;
import io.papermc.hangar.model.Announcement;
import io.papermc.hangar.security.annotations.Anyone;
import io.papermc.hangar.service.internal.projects.PlatformService;
import org.springframework.beans.factory.annotation.Autowired;
@ -72,12 +72,12 @@ public class BackendDataController {
}
@GetMapping("/platforms")
// TODO include valid versions (equivalent of PlatformInfo)
public ResponseEntity<ArrayNode> getPlatforms() {
ArrayNode arrayNode = mapper.createArrayNode();
for (Platform platform : Platform.getValues()) {
ObjectNode objectNode = mapper.createObjectNode()
.put("name", platform.getName())
.put("enumName", platform.name())
.put("category", platform.getCategory().getTagName())
.put("url", platform.getUrl());
objectNode.set("tagColor", mapper.valueToTree(platform.getTagColor()));

View File

@ -34,6 +34,13 @@ public interface ProjectVersionsDAO {
@SqlQuery("SELECT * FROM project_versions pv WHERE pv.id = :versionId")
ProjectVersionTable getProjectVersionTable(long versionId);
@SqlQuery("SELECT pv.*" +
" FROM project_versions pv" +
" JOIN project_channels pc ON pv.channel_id = pc.id" +
" WHERE pc.id = :channelId" +
" ORDER BY pv.created_at DESC")
ProjectVersionTable getLastVersionOnChannel(long channelId);
@SqlQuery("SELECT pv.* FROM project_versions pv" +
" JOIN projects p ON pv.project_id = p.id" +
" JOIN project_version_platform_dependencies pvpd ON pv.id = pvpd.version_id" +

View File

@ -1,46 +0,0 @@
package io.papermc.hangar.db.dao.session;
import io.papermc.hangar.controller.extras.HangarApiRequest;
import io.papermc.hangar.db.mappers.PermissionMapper;
import org.jdbi.v3.sqlobject.config.RegisterColumnMapper;
import org.jdbi.v3.sqlobject.config.RegisterConstructorMapper;
import org.jdbi.v3.sqlobject.statement.SqlQuery;
import org.springframework.stereotype.Repository;
@Repository
@RegisterConstructorMapper(HangarApiRequest.class)
@RegisterColumnMapper(PermissionMapper.class)
@Deprecated
public interface HangarRequestDAO {
@SqlQuery("SELECT u.id u_id," +
" u.created_at u_created_at," +
" u.full_name u_full_name," +
" u.name u_name," +
" u.email u_email," +
" u.tagline u_tagline," +
" u.join_date u_join_date," +
" u.read_prompts u_read_prompts," +
" u.is_locked u_is_locked," +
" u.language u_language," +
" ak.id ak_id," +
" ak.created_at ak_created_at," +
" ak.name ak_name," +
" ak.owner_id ak_owner_id," +
" ak.token_identifier ak_token_identifier," +
" ak.token ak_token," +
" ak.raw_key_permissions::BIGINT ak_permissions," +
" aks.token \"session\"," +
" aks.expires," +
" CASE" +
" WHEN u.id IS NULL THEN 1::BIT(64)::BIGINT" +
" ELSE ((coalesce(gt.permission, B'0'::BIT(64)) | 1::BIT(64) | (1::BIT(64) << 1) | (1::BIT(64) << 2)) &" +
" coalesce(ak.raw_key_permissions, (-1)::BIT(64)))::BIGINT" +
" END AS global_permissions" +
" FROM api_sessions aks" +
" LEFT JOIN api_keys ak ON aks.key_id = ak.id" +
" LEFT JOIN users u ON aks.user_id = u.id" +
" LEFT JOIN global_trust gt ON gt.user_id = u.id" +
" WHERE aks.token = :token")
HangarApiRequest createHangarRequest(String token);
}

View File

@ -19,6 +19,8 @@ import java.util.EnumMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
public class PendingVersion {
@ -27,7 +29,7 @@ public class PendingVersion {
private final String versionString;
private final Map<Platform, Set<@Valid PluginDependency>> pluginDependencies;
@Size(min = 1, max = 3, message = "version.new.error.invalidNumOfPlatforms")
private final Map<Platform, @Size(min = 1, message = "version.edit.error.noPlatformVersions") Set<@NotBlank(message = "version.new.error.invalidPlatformVersion") String>> platformDependencies;
private final Map<Platform, @Size(min = 1, message = "version.edit.error.noPlatformVersions") SortedSet<@NotBlank(message = "version.new.error.invalidPlatformVersion") String>> platformDependencies;
@NotBlank(message = "version.new.error.noDescription")
private final String description;
private final FileInfo fileInfo;
@ -44,7 +46,7 @@ public class PendingVersion {
private final boolean isFile;
@JsonCreator(mode = Mode.PROPERTIES)
public PendingVersion(String versionString, Map<Platform, Set<PluginDependency>> pluginDependencies, EnumMap<Platform, Set<String>> platformDependencies, String description, FileInfo fileInfo, String externalUrl, String channelName, Color channelColor, boolean channelNonReviewed, boolean forumSync, boolean unstable, boolean recommended, boolean isFile) {
public PendingVersion(String versionString, Map<Platform, Set<PluginDependency>> pluginDependencies, EnumMap<Platform, SortedSet<String>> platformDependencies, String description, FileInfo fileInfo, String externalUrl, String channelName, Color channelColor, boolean channelNonReviewed, boolean forumSync, boolean unstable, boolean recommended, boolean isFile) {
this.versionString = versionString;
this.pluginDependencies = pluginDependencies;
this.platformDependencies = platformDependencies;
@ -60,7 +62,7 @@ public class PendingVersion {
this.isFile = isFile;
}
public PendingVersion(String versionString, Map<Platform, Set<PluginDependency>> pluginDependencies, Map<Platform, Set<String>> platformDependencies, String description, FileInfo fileInfo, ProjectChannelTable projectChannelTable, boolean forumSync) {
public PendingVersion(String versionString, Map<Platform, Set<PluginDependency>> pluginDependencies, Map<Platform, SortedSet<String>> platformDependencies, String description, FileInfo fileInfo, ProjectChannelTable projectChannelTable, boolean forumSync) {
this.versionString = versionString;
this.pluginDependencies = pluginDependencies;
this.platformDependencies = platformDependencies;
@ -76,14 +78,14 @@ public class PendingVersion {
this.isFile = true;
}
public PendingVersion(String externalUrl, ProjectChannelTable projectChannelTable, boolean forumSync) {
public PendingVersion(Map<Platform, Set<PluginDependency>> pluginDependencies, Map<Platform, SortedSet<String>> platformDependencies, String externalUrl, ProjectChannelTable projectChannelTable, boolean forumSync) {
this.forumSync = forumSync;
this.versionString = null;
this.pluginDependencies = new EnumMap<>(Platform.class);
this.platformDependencies = new EnumMap<>(Platform.class);
this.pluginDependencies = pluginDependencies;
this.platformDependencies = platformDependencies;
for (Platform platform : Platform.getValues()) {
this.pluginDependencies.put(platform, new HashSet<>());
this.platformDependencies.put(platform, new HashSet<>());
this.platformDependencies.put(platform, new TreeSet<>());
}
this.description = null;
this.fileInfo = null;
@ -104,7 +106,7 @@ public class PendingVersion {
return pluginDependencies;
}
public Map<Platform, Set<String>> getPlatformDependencies() {
public Map<Platform, SortedSet<String>> getPlatformDependencies() {
return platformDependencies;
}

View File

@ -7,6 +7,7 @@ import io.papermc.hangar.db.dao.internal.table.PlatformVersionDAO;
import io.papermc.hangar.db.dao.internal.table.versions.ProjectVersionDependenciesDAO;
import io.papermc.hangar.db.dao.internal.table.versions.ProjectVersionPlatformDependenciesDAO;
import io.papermc.hangar.db.dao.internal.table.versions.ProjectVersionsDAO;
import io.papermc.hangar.db.dao.v1.VersionsApiDAO;
import io.papermc.hangar.exceptions.HangarApiException;
import io.papermc.hangar.model.api.project.version.FileInfo;
import io.papermc.hangar.model.api.project.version.PluginDependency;
@ -42,9 +43,13 @@ import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.SortedSet;
@Service
public class VersionFactory extends HangarService {
@ -53,6 +58,7 @@ public class VersionFactory extends HangarService {
private final ProjectVersionDependenciesDAO projectVersionDependenciesDAO;
private final PlatformVersionDAO platformVersionDAO;
private final ProjectVersionsDAO projectVersionsDAO;
private final VersionsApiDAO versionsApiDAO;
private final ProjectFiles projectFiles;
private final PluginDataService pluginDataService;
private final ChannelService channelService;
@ -60,17 +66,17 @@ public class VersionFactory extends HangarService {
private final RecommendedVersionService recommendedVersionService;
private final ProjectService projectService;
private final NotificationService notificationService;
private final VersionService versionService;
private final VersionTagService versionTagService;
private final PlatformService platformService;
private final UsersApiService usersApiService;
@Autowired
public VersionFactory(HangarDao<ProjectVersionPlatformDependenciesDAO> projectVersionPlatformDependencyDAO, HangarDao<ProjectVersionDependenciesDAO> projectVersionDependencyDAO, HangarDao<PlatformVersionDAO> platformVersionDAO, HangarDao<ProjectVersionsDAO> projectVersionDAO, ProjectFiles projectFiles, PluginDataService pluginDataService, ChannelService channelService, ProjectVisibilityService projectVisibilityService, RecommendedVersionService recommendedVersionService, ProjectService projectService, NotificationService notificationService, VersionService versionService, VersionTagService versionTagService, PlatformService platformService, UsersApiService usersApiService) {
public VersionFactory(HangarDao<ProjectVersionPlatformDependenciesDAO> projectVersionPlatformDependencyDAO, HangarDao<ProjectVersionDependenciesDAO> projectVersionDependencyDAO, HangarDao<PlatformVersionDAO> platformVersionDAO, HangarDao<ProjectVersionsDAO> projectVersionDAO, HangarDao<VersionsApiDAO> versionsApiDAO, ProjectFiles projectFiles, PluginDataService pluginDataService, ChannelService channelService, ProjectVisibilityService projectVisibilityService, RecommendedVersionService recommendedVersionService, ProjectService projectService, NotificationService notificationService, VersionTagService versionTagService, PlatformService platformService, UsersApiService usersApiService) {
this.projectVersionPlatformDependenciesDAO = projectVersionPlatformDependencyDAO.get();
this.projectVersionDependenciesDAO = projectVersionDependencyDAO.get();
this.platformVersionDAO = platformVersionDAO.get();
this.projectVersionsDAO = projectVersionDAO.get();
this.versionsApiDAO = versionsApiDAO.get();
this.projectFiles = projectFiles;
this.pluginDataService = pluginDataService;
this.channelService = channelService;
@ -78,7 +84,6 @@ public class VersionFactory extends HangarService {
this.recommendedVersionService = recommendedVersionService;
this.projectService = projectService;
this.notificationService = notificationService;
this.versionService = versionService;
this.versionTagService = versionTagService;
this.platformService = platformService;
this.usersApiService = usersApiService;
@ -137,7 +142,18 @@ public class VersionFactory extends HangarService {
ProjectTable projectTable = projectService.getProjectTable(projectId);
assert projectTable != null;
ProjectChannelTable projectChannelTable = channelService.getFirstChannel(projectId);
return new PendingVersion(url, projectChannelTable, projectTable.isForumSync());
ProjectVersionTable lastVersionOnChannel = projectVersionsDAO.getProjectVersionTable(projectChannelTable.getId());
Map<Platform, Set<PluginDependency>> pluginDependencies = new EnumMap<>(Platform.class);
Map<Platform, SortedSet<String>> platformDependencies;
if (lastVersionOnChannel == null) {
platformDependencies = new EnumMap<>(Platform.class);
} else {
for (Platform platform : Platform.getValues()) {
pluginDependencies.put(platform, versionsApiDAO.getPluginDependencies(lastVersionOnChannel.getId(), platform));
}
platformDependencies = versionsApiDAO.getPlatformDependencies(lastVersionOnChannel.getId());
}
return new PendingVersion(pluginDependencies, platformDependencies, url, projectChannelTable, projectTable.isForumSync());
}
public void publishPendingVersion(long projectId, final PendingVersion pendingVersion) {

View File

@ -7,6 +7,7 @@ import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
public abstract class DataValue {
@ -64,19 +65,19 @@ public abstract class DataValue {
public static class PlatformDependencyDataValue extends DataValue {
private final Map<Platform, Set<String>> value;
private final Map<Platform, SortedSet<String>> value;
public PlatformDependencyDataValue(String key, Platform platform, Set<String> versions) {
public PlatformDependencyDataValue(String key, Platform platform, SortedSet<String> versions) {
super(key);
this.value = Map.of(platform, versions);
}
public PlatformDependencyDataValue(String key, Map<Platform, Set<String>> map) {
public PlatformDependencyDataValue(String key, Map<Platform, SortedSet<String>> map) {
super(key);
this.value = map;
}
public Map<Platform, Set<String>> getValue() {
public Map<Platform, SortedSet<String>> getValue() {
return value;
}
}

View File

@ -14,6 +14,7 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedSet;
import java.util.stream.Collectors;
import static io.papermc.hangar.service.internal.versions.plugindata.DataValue.DependencyDataValue;
@ -93,7 +94,7 @@ public class PluginFileData {
return ((DependencyDataValue) dependencies).getValue();
}
public Map<Platform, Set<String>> getPlatformDependencies() {
public Map<Platform, SortedSet<String>> getPlatformDependencies() {
DataValue platformDependencies = dataValues.get(FileTypeHandler.PLATFORM_DEPENDENCY);
return platformDependencies != null ? ((PlatformDependencyDataValue) platformDependencies).getValue() : null;
}

View File

@ -12,6 +12,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.stream.Collectors;
@Component
@ -76,7 +78,7 @@ public class PaperPluginFileHandler extends FileTypeHandler {
result.add(new DataValue.DependencyDataValue(FileTypeHandler.DEPENDENCIES, getPlatform(), dependencies));
}
Set<String> versions = new HashSet<>();
SortedSet<String> versions = new TreeSet<>();
if (data.containsKey("api-version")) {
versions.add(data.get("api-version").toString());
}

View File

@ -12,6 +12,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;
@Component
@ -71,7 +72,7 @@ public class VelocityFileHandler extends FileTypeHandler {
result.add(new DataValue.DependencyDataValue(FileTypeHandler.DEPENDENCIES, getPlatform(), dependencies));
}
result.add(new DataValue.PlatformDependencyDataValue(FileTypeHandler.PLATFORM_DEPENDENCY, getPlatform(), new HashSet<>()));
result.add(new DataValue.PlatformDependencyDataValue(FileTypeHandler.PLATFORM_DEPENDENCY, getPlatform(), new TreeSet<>()));
return result;
}

View File

@ -12,6 +12,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;
@Component
@ -76,7 +77,7 @@ public class WaterfallPluginFileHandler extends FileTypeHandler {
result.add(new DataValue.DependencyDataValue(FileTypeHandler.DEPENDENCIES, getPlatform(), dependencies));
}
result.add(new DataValue.PlatformDependencyDataValue(FileTypeHandler.PLATFORM_DEPENDENCY, getPlatform(), new HashSet<>()));
result.add(new DataValue.PlatformDependencyDataValue(FileTypeHandler.PLATFORM_DEPENDENCY, getPlatform(), new TreeSet<>()));
return result;
}