version creating dependency configuration

This commit is contained in:
Jake Potrebic 2021-03-11 00:03:55 -08:00
parent c4570a7dbc
commit ff8899272c
No known key found for this signature in database
GPG Key ID: 7C58557EC9C421F8
26 changed files with 606 additions and 218 deletions

View File

@ -1,3 +1,13 @@
@import '~vuetify/src/styles/styles.sass';
.text-transform-unset {
text-transform: unset;
}
}
.platform-logo {
fill: map-deep-get($material-dark, 'tabs');
}
.v-tab--active .platform-logo {
fill: map-get($blue, 'base')
}

View File

@ -1,7 +1,7 @@
<template>
<div class="markdown-editor">
<div v-show="isEditing && !preview" class="ml-4">
<v-textarea v-model="rawEdited" outlined :rows="rawEdited.split(/\r\n|\r|\n/g).length + 3" />
<v-textarea v-model="rawEdited" outlined :rows="rawEdited.split(/\r\n|\r|\n/g).length + 3" :rules="rules" />
</div>
<Markdown v-show="!isEditing" :raw="raw" class="ml-4" />
<Markdown v-if="preview" :raw="rawEdited" class="ml-4" inner-class="pl-5" />
@ -54,6 +54,7 @@
<script lang="ts">
import { Component, Prop, PropSync, Vue, Watch } from 'nuxt-property-decorator';
import { PropType } from 'vue';
import Markdown from '~/components/Markdown.vue';
import DeletePageModal from '~/components/modals/pages/DeletePageModal.vue';
@ -86,6 +87,9 @@ export default class MarkdownEditor extends Vue {
@Prop({ default: true, type: Boolean })
saveable!: boolean;
@Prop({ default: () => [], type: Array as PropType<Function[]> })
rules!: Function[];
created() {
this.rawEdited = this.raw || '';
}

View File

@ -2,7 +2,7 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1" width="72" height="72" viewBox="0 0 2000 2000">
<title>Paper</title>
<path
fill="#FFF"
class="platform-logo"
d="M1625.4 316.8c16.8 12 24.8 31.2 21.6 51.1l-204.5 1227.2c-2.4 15.2-12 28-25.6 36-7.2 4-16 6.4-24.8 6.4-6.4 0-12.8-1.6-19.2-4L1011 1485.6l-193.3 235.7c-9.6 12-24 18.4-39.2 18.4-5.6 0-12-.8-17.6-3.2-20-7.2-33.6-26.4-33.6-47.9v-278.8l690.3-846.1-854.1 739L248 1173.2c-18.4-7.2-30.4-24-32-43.9-.8-19.2 8.8-37.6 25.6-47.1l1329.4-767c8-4.8 16.8-7.2 25.6-7.2 10.4 0 20.8 3.2 28.8 8.8z"
/>
</svg>

View File

@ -1,7 +1,7 @@
<template>
<svg viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg">
<title>Velocity</title>
<g fill="#fff">
<g class="platform-logo">
<path
d="M236.25 232.55l-54.08-73.79a11.86 11.86 0 00-11.91-4.62L84 171.57a11.88 11.88 0 00-8 5.88l-42.64 77.07a11.84 11.84 0 00.81 12.75l54.21 74a11.86 11.86 0 0011.91 4.62l86-17.37a11.85 11.85 0 008-5.89l42.78-77.3a11.86 11.86 0 00-.82-12.78zm-59.45 74.21a9.57 9.57 0 01-13.39-2.06l-31-42.24a16 16 0 00-16-6.21l-52.58 10.63a9.58 9.58 0 01-11.29-7.49A9.58 9.58 0 0160 248.1l57-11.52a16 16 0 0010.81-7.92L156.42 177a9.58 9.58 0 0113-3.75 9.58 9.58 0 013.75 13L146.81 234a16 16 0 001.09 17.16l31 42.23a9.58 9.58 0 01-2.1 13.37z"
/>

View File

@ -2,18 +2,15 @@
<template>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
<title>Waterfall</title>
<g>
<g class="platform-logo">
<g transform="translate(0.000000,512.000000) scale(0.100000,-0.100000)">
<path
fill="#FFF"
d="M3180.5,5009.8c-162.9-72.8-182-272.1-34.5-350.7c28.7-15.3,205-28.7,484.8-38.3c427.3-13.4,701.3-46,938.9-105.4c206.9-53.6,469.5-143.7,469.5-161c0-9.6-55.6-80.5-122.6-157.1c-900.6-1023.2-1456.3-2103.9-1783.9-3474c-61.3-251-174.4-833.5-185.9-956.2c-5.7-53.7-9.6-55.6-293.2-128.4c-866.1-218.4-1559.8-557.6-2017.7-984.9C101.2-1844.3-40.6-2447.9,243-3013.1c151.4-298.9,471.4-618.9,869.9-866.1c1030.9-643.8,2780.4-988.7,4487.7-887.2c1716.9,103.5,3146.3,599.8,3847.6,1333.6c216.5,229.9,316.2,387.1,404.3,651.5c86.2,258.7,49.8,651.5-84.3,917.9C9381.2-1102.7,8227.7-483.8,6715.8-225.1c-136,23-260.6,46-274,49.8c-24.9,7.7-26.8-7.6,26.8,505.9c145.6,1435.2,515.4,2812.9,963.8,3590.9c176.3,306.6,212.7,344.9,412,419.6c515.4,197.4,831.6,258.7,1458.2,279.8c243.4,9.6,465.6,26.8,494.4,38.3c65.2,24.9,116.9,136,99.6,212.7c-5.8,28.7-32.6,72.8-59.4,97.7c-47.9,46-53.7,46-425.4,44.1c-720.5-5.7-1124.8-78.6-1732.2-316.2c-274-109.2-298.9-128.4-500.1-438.8c-576.8-891-1000.2-2521.7-1155.4-4451.2c-30.7-400.5-59.4-1906.6-38.3-2050.3c21.1-132.2,82.4-195.5,191.6-195.5c69,0,97.7,11.5,139.9,53.7l53.6,53.7v314.3c0,174.4,5.8,316.2,13.4,316.2c44.1,0,492.5-161,615.1-220.4c249.1-120.7,383.2-270.2,341.1-377.5c-42.1-115-293.2-279.8-594-392.8c-251-93.9-768.4-216.5-1121-264.4c-51.7-7.7-231.8-23-400.5-36.4l-306.6-24.9l-57.5-63.2c-47.9-53.6-55.6-72.8-46-141.8c7.7-51.7,28.7-93.9,61.3-120.7c46-40.2,69-44.1,256.8-44.1c224.2,0,666.8,53.7,973.4,115c869.9,180.1,1406.5,444.6,1580.8,785.6c34.5,69,44.1,116.9,44.1,239.5c0,134.1-7.7,166.7-57.5,254.8c-153.3,279.8-576.8,513.5-1211,674.5l-82.4,21.1v151.4c0,84.3,5.8,153.3,15.3,153.3c7.7,0,130.3-28.8,272.1-65.2c643.8-164.8,1117.1-396.6,1410.3-689.8c184-185.8,247.2-316.2,245.3-509.7c0-118.8-9.6-162.9-57.5-258.7c-67.1-138-272.1-352.6-448.4-467.6c-492.5-321.9-1295.3-557.6-2165.3-636.1c-308.5-26.8-994.5-26.8-1303,0c-869.9,78.6-1672.8,314.2-2165.3,636.1c-176.3,115-381.3,329.6-448.4,467.6c-80.5,162.9-82.4,354.5-5.8,511.6c115,233.8,379.4,456,766.5,645.7c128.4,63.2,258.7,120.7,289.3,128.4c55.6,13.4,55.6,13.4,44.1-61.3c-7.7-40.3-13.4-101.6-13.4-136.1c0-55.6-11.5-67.1-147.5-141.8c-394.7-216.5-567.2-423.5-569.1-687.9c-3.8-389,415.8-718.6,965.7-760.7c216.5-15.3,306.6,40.3,306.6,193.5c0,111.1-61.3,162.9-220.4,185.8c-329.6,49.8-530.8,134.1-617,264.4c-70.9,105.4-59.4,166.7,49.8,272.1c51.7,49.8,120.7,105.4,153.3,120.7l57.5,30.6l-1.9-93.9c0-160.9,101.6-249.1,243.4-210.8c115,32.6,138,93.9,151.4,406.2c76.6,1632.6,346.8,2908.7,845,4000.9c279.8,615.1,707.1,1257,1237.8,1856.8c298.9,337.2,304.7,344.9,304.7,425.4c0,116.9-67.1,168.6-358.3,281.7c-291.3,111.1-607.4,199.3-868,239.5C4002.5,5011.7,3259.1,5044.3,3180.5,5009.8z M6700.5-617.9c1312.6-243.3,2322.4-753,2673-1352.8c105.4-178.2,136-298.9,126.5-509.7c-5.7-159-15.3-189.7-88.1-337.2c-321.9-649.6-1385.4-1195.7-2801.4-1439c-605.5-105.4-1293.4-147.5-1989-122.6c-1950.7,67.1-3610.1,710.9-4033.5,1563.6L507.5-2651v220.4v222.3l86.2,172.5c70.9,143.7,116.9,203.1,268.3,354.5c99.6,101.6,247.2,228,327.7,281.7c369.8,252.9,952.3,503.9,1477.4,638.1c80.5,21.1,161,44.1,178.2,49.8c24.9,9.6,30.7,3.8,24.9-30.6c-3.8-34.5-38.3-53.7-183.9-105.4c-701.3-251-1230.2-684.1-1366.2-1119C1180-2421,1390.8-2894.3,1889-3250.8c1469.7-1046.2,4754-1046.2,6223.7,0c823.9,588.3,812.4,1418-30.7,2015.8c-346.8,245.3-938.9,482.9-1490.8,597.8c-90.1,19.2-170.5,42.2-180.1,49.8C6382.4-562.4,6407.3-564.3,6700.5-617.9z"
/>
<path
fill="#FFF"
d="M6666,4578.7c-53.7-46-182-220.4-333.4-454.1c-908.3-1406.5-1303-2989.2-1446.7-5806c-9.6-205-19.2-473.3-19.2-595.9c0-195.4,5.7-228,38.3-272.1c86.2-109.2,283.6-76.6,323.8,51.7c11.5,32.6,28.7,279.8,40.3,548c126.5,3021.8,549.9,4685,1561.7,6108.7c124.6,174.4,143.7,212.7,143.7,283.6c0,67.1-9.6,90.1-59.4,130.3C6840.4,4636.2,6735,4640,6666,4578.7z"
/>
<path
fill="#FFF"
d="M5958.9,4534.6c-26.8-17.2-105.4-101.6-176.3-187.8C4933.8,3308.3,4381.9,2053.2,4073.4,455.1c-138-718.6-256.8-1820.3-266.3-2494.8c-3.8-281.7-1.9-291.3,42.2-339.2c67.1-70.9,157.1-82.4,237.6-32.6c93.9,57.5,88.1,30.7,128.4,749.2c76.6,1356.6,310.4,2623.2,661.1,3594.7c289.3,793.3,687.9,1521.4,1140.1,2077.1c214.6,262.5,229.9,287.4,229.9,367.9C6246.4,4526.9,6085.4,4613.2,5958.9,4534.6z"
/>
</g>

View File

@ -235,6 +235,7 @@ const msgs: LocaleMessageObject = {
fileName: 'File name',
fileSize: 'File size',
externalUrl: 'External URL',
hangarProject: 'Hangar Project',
channel: 'Channel',
addChannel: 'Add Channel',
unstable: 'Unstable',
@ -244,6 +245,8 @@ const msgs: LocaleMessageObject = {
bulletin: 'Release Bulletin',
desc: "What's new in this release?",
},
platforms: 'Platforms',
dependencies: 'Plugin Dependencies',
},
error: {
metaNotFound: 'Could not load metadata from uploaded file',
@ -262,6 +265,7 @@ const msgs: LocaleMessageObject = {
unknown: 'An unknown error has occurred',
incomplete: 'Plugin file missing {0}',
noDescription: 'Must have a description',
invalidPluginDependencyNamespace: 'Declared plugin dependency has an invalid project namespace',
channel: {
noName: 'Must have a channel name specified',
noColor: 'Must have a channel color specified',

View File

@ -1,7 +1,13 @@
<template>
<div>
<v-tabs>
<v-tab v-for="version in versionPlatforms" :key="`platform-${version}`" nuxt :to="version.toLowerCase()">
<v-tab
v-for="version in versionPlatforms"
:key="`platform-${version}`"
nuxt
:to="{ name: `author-slug-versions-version-platform`, params: { ...$route.params, platform: version.toLowerCase() } }"
>
<v-icon left v-text="`$vuetify.icons.${version.toLowerCase()}`"></v-icon>
{{ version }}
</v-tab>
</v-tabs>

View File

@ -4,8 +4,8 @@
<v-col>{{ $t('reviews.headline', [version.author, $util.prettyDate(version.createdAt)]) }}</v-col>
<v-col>
<v-btn color="secondary" @click="removeFromQueue">{{ $t('reviews.removeFromQueue') }}</v-btn>
<v-btn color="secondary" :to="'/' + $route.params.author + '/' + $route.params.slug">{{ $t('reviews.projectPage') }}</v-btn>
<v-btn color="secondary" :to="'/' + $route.params.author + '/' + $route.params.slug + '/versions/' + $route.params.version + '/jar'">
<v-btn color="secondary" :to="{ name: 'author-slug', params: $route.params }" nuxt exact>{{ $t('reviews.projectPage') }}</v-btn>
<v-btn color="secondary" :to="'/' + $route.params.author + '/' + $route.params.slug + '/versions/' + $route.params.version + '/jar'" nuxt>
{{ $t('reviews.downloadFile') }}
</v-btn>
<v-btn v-if="!hasReviewStarted" color="primary" @click="startReview">{{ $t('reviews.startReview') }}</v-btn>
@ -22,8 +22,8 @@
v-model="message"
:label="$t('reviews.reviewMessage')"
append-outer-icon="mdi-clipboard"
@click:append-outer="sendMessage"
></v-text-field>
@click="sendMessage"
/>
<h2>{{ $t('reviews.title') }}</h2>

View File

@ -15,7 +15,7 @@
</v-row>
</v-card-text>
<v-card-text v-else>
<v-form v-model="validForm">
<v-form ref="newVersionForm" v-model="validForm">
<v-row justify="space-around">
<v-col cols="12">
<v-btn color="warning" block @click="reset">{{ $t('general.reset') }}</v-btn>
@ -26,6 +26,7 @@
:hide-details="isFile"
:label="$t('version.new.form.versionString')"
:disabled="isFile"
:autofocus="!isFile"
filled
:rules="[$util.$vc.require('Version string')]"
/>
@ -79,7 +80,7 @@
</NewChannelModal>
</v-col>
</v-row>
<v-sheet color="accent" elevation="1" rounded class="mt-2">
<v-sheet color="accent darken-1" elevation="1" rounded class="mt-2">
<v-row justify="space-around">
<v-col md="3" sm="4" cols="12">
<v-checkbox v-model="pendingVersion.unstable" :label="$t('version.new.form.unstable')" />
@ -92,13 +93,105 @@
</v-col>
</v-row>
</v-sheet>
<v-card color="accent darken-1" elevation="1" class="mt-6">
<v-card-title class="pb-0">{{ $t('version.new.form.platforms') }}</v-card-title>
<v-card-text>
<v-row justify="space-around">
<v-select
v-model="selectedPlatforms"
style="display: none"
multiple
:items="Array.from($store.state.platforms.keys())"
:rules="[(v) => !!v.length || 'Error']"
/>
<v-col v-for="platform in platforms" :key="platform.name" class="flex-grow-0">
<div :class="{ platformError: !selectedPlatforms.length }" class="platform-version-label text-center">
{{ platform.name }}
</div>
<v-checkbox
v-for="version in platform.possibleVersions"
:key="`${platform.name}-${version}`"
v-model="pendingVersion.platformDependencies[platform.name.toUpperCase()]"
:rules="platformVersionRules"
class="platform-version-checkbox"
dense
hide-details
:label="version"
:value="version"
@change="togglePlatformVersion($event, platform.name.toUpperCase())"
/>
</v-col>
</v-row>
</v-card-text>
</v-card>
<v-card v-if="platformsForPluginDeps.length" color="accent darken-1" elevation="1" class="mt-2 pb-1">
<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>
<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>
</template>
</v-card>
<v-row class="mt-3">
<v-col cols="12" class="pb-0 ml-6">
<h2>{{ $t('version.new.form.release.bulletin') }}</h2>
{{ $t('version.new.form.release.desc') }}
</v-col>
<v-col cols="12">
<MarkdownEditor ref="editor" :deletable="false" :cancellable="false" :saveable="false" editing :raw="pendingVersion.description" />
<MarkdownEditor
ref="editor"
:deletable="false"
:cancellable="false"
:saveable="false"
editing
:raw="pendingVersion.description"
:rules="[$util.$vc.require($t('version.new.form.release.bulletin'))]"
/>
</v-col>
</v-row>
</v-form>
@ -115,12 +208,14 @@
<script lang="ts">
import { Component } from 'nuxt-property-decorator';
import remove from 'lodash-es/remove';
import { PendingVersion, ProjectChannel } from 'hangar-internal';
import { IPlatform, PendingVersion, ProjectChannel } from 'hangar-internal';
import { PaginatedResult, Project, 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';
// TODO implement setting up dependencies
@Component({
@ -133,6 +228,9 @@ export default class ProjectVersionsNewPage extends HangarProjectMixin {
pendingVersion: PendingVersion | null = null;
validForm: boolean = false;
channels: ProjectChannel[] = [];
selectedPlatforms: string[] = [];
hangarProjectSearchResults: ProjectNamespace[] = [];
loading = {
create: false,
submit: false,
@ -144,6 +242,19 @@ 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);
}
@ -152,6 +263,35 @@ export default class ProjectVersionsNewPage extends HangarProjectMixin {
return this.channels.find((c) => c.name === this.pendingVersion?.channelName);
}
get platforms(): IPlatform[] {
if (this.pendingVersion?.isFile) {
const platforms: IPlatform[] = [];
for (const platformDependenciesKey in this.pendingVersion.platformDependencies) {
platforms.push((this.$store.state as RootState).platforms.get(platformDependenciesKey as Platform)!);
}
return platforms;
}
return Array.from((this.$store.state as RootState).platforms.values());
}
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);
}
}
return platforms;
}
get platformVersionRules(): Function[] {
if (!this.pendingVersion?.isFile) {
return [];
} else {
return [(v: string[]) => !!v.length || 'Error'];
}
}
addChannel(channel: ProjectChannel) {
if (this.pendingVersion) {
remove(this.channels, (c) => c.temp);
@ -162,17 +302,21 @@ export default class ProjectVersionsNewPage extends HangarProjectMixin {
$refs!: {
editor: MarkdownEditor;
newVersionForm: any;
};
getNamespace(namespace: ProjectNamespace) {
return `${namespace.owner}/${namespace.slug}`;
}
createVersion() {
if (this.pendingVersion) {
if (!this.$refs.newVersionForm.validate()) {
return;
}
this.pendingVersion.description = this.$refs.editor.rawEdited;
this.pendingVersion.channelColor = this.currentChannel!.color;
this.pendingVersion.channelNonReviewed = this.currentChannel!.nonReviewed;
// TODO remove debug values
this.pendingVersion.platformDependencies.PAPER = ['1.13', '1.14', '1.15'];
this.pendingVersion.platformDependencies.VELOCITY = ['1.0'];
this.pendingVersion.platformDependencies.WATERFALL = ['1.13', '1.14', '1.15'];
// played around trying to get this to happen in jackson's deserialization, but couldn't figure it out.
for (const platform in this.pendingVersion.platformDependencies) {
if (this.pendingVersion.platformDependencies[platform as Platform].length < 1) {
@ -188,12 +332,20 @@ export default class ProjectVersionsNewPage extends HangarProjectMixin {
this.$api
.requestInternal(`versions/version/${this.project.id}/create`, true, 'post', this.pendingVersion)
.then(() => {
this.$router.push(`/${this.$route.params.author}/${this.$route.params.slug}/versions`);
// this.$router.push(`/${this.$route.params.author}/${this.$route.params.slug}/versions`);
})
.catch(this.$util.handleRequestError);
}
}
togglePlatformVersion(value: string[], platform: string) {
if (value.length === 0 && this.selectedPlatforms.includes(platform)) {
this.$delete(this.selectedPlatforms, this.selectedPlatforms.indexOf(platform));
} else if (!this.selectedPlatforms.includes(platform)) {
this.selectedPlatforms.push(platform);
}
}
// todo handle errors better, for example "version.new.error.duplicateNameAndPlatform"
// TODO should have a set of validate name endpoints to provide this check while the user is changing the name (Project name, Version name, page name, channel name, etc)
async createPendingVersion() {
@ -213,7 +365,11 @@ export default class ProjectVersionsNewPage extends HangarProjectMixin {
this.pendingVersion = await this.$api
.requestInternal<PendingVersion>(`versions/version/${this.project.id}/upload`, true, 'post', data)
.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.loading.create = false;
}
@ -228,3 +384,19 @@ export default class ProjectVersionsNewPage extends HangarProjectMixin {
}
}
</script>
<style lang="scss" scoped>
@import '~vuetify/src/styles/styles.sass';
.platform-version-checkbox.v-input--selection-controls {
margin-top: 0;
padding-top: 0;
}
.platform-version-label {
color: map-deep-get($material-dark, 'text', 'secondary');
&.platformError {
color: var(--v-error-base);
}
}
</style>

View File

@ -23,7 +23,9 @@ export default {
default: 'dark',
dark: true,
disable: false,
options: {},
options: {
customProperties: true,
},
themes: {
dark: {
anchor: colors.blue.lighten3,

View File

@ -1,11 +1,11 @@
declare module 'hangar-internal' {
import { FileInfo, Named, Version } from 'hangar-api';
import { FileInfo, Named, ProjectNamespace, Version } from 'hangar-api';
import { Platform } from '~/types/enums';
interface PlatformDependency {
name: string;
required: boolean;
projectId: number | null;
namespace: ProjectNamespace | null;
externalUrl: string | null;
}

View File

@ -10189,9 +10189,9 @@ vuetify-loader@^1.6.0:
loader-utils "^1.2.0"
vuetify@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/vuetify/-/vuetify-2.4.2.tgz#d37d160c1fc6b241fc166a32980b34590a017d6e"
integrity sha512-8W1928Fv6GKwLiOThutYf2wtD5C9+vcCavlI8NT0YxNOVvluoL8xrep8mGGwDsCkay+4LzaAX92owKeNi3kpWg==
version "2.4.6"
resolved "https://registry.yarnpkg.com/vuetify/-/vuetify-2.4.6.tgz#127b37bd36c7a63f61615e0cd6f97e8b203e7a07"
integrity sha512-oqAWKAin07ip/QuT/p4bL1LegE3MYPbfojrOcj80RATZDSnJyco2PZD8QuIzd0RhYfdAuSTkY8elvHsLu90RuQ==
vuex-class@^0.3.2:
version "0.3.2"

View File

@ -1,135 +1,83 @@
package io.papermc.hangar.db.dao.internal;
import io.papermc.hangar.db.dao.v1.VersionsApiDAO.VersionReducer;
import io.papermc.hangar.model.api.project.version.PluginDependency;
import io.papermc.hangar.model.common.Platform;
import io.papermc.hangar.model.internal.versions.HangarVersion;
import org.jdbi.v3.core.enums.EnumByOrdinal;
import org.jdbi.v3.core.enums.EnumStrategy;
import org.jdbi.v3.core.result.LinkedHashMapRowReducer;
import org.jdbi.v3.core.result.RowView;
import org.jdbi.v3.sqlobject.config.RegisterConstructorMapper;
import org.jdbi.v3.sqlobject.config.UseEnumStrategy;
import org.jdbi.v3.sqlobject.customizer.Define;
import org.jdbi.v3.sqlobject.statement.SqlQuery;
import org.jdbi.v3.sqlobject.statement.UseRowReducer;
import org.jdbi.v3.stringtemplate4.UseStringTemplateEngine;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@Repository
@UseStringTemplateEngine
@UseEnumStrategy(EnumStrategy.BY_ORDINAL)
@RegisterConstructorMapper(HangarVersion.class)
public interface HangarVersionsDAO {
@UseEnumStrategy(EnumStrategy.BY_ORDINAL)
@UseRowReducer(HangarVersionReducer.class)
@RegisterConstructorMapper(value = PluginDependency.class, prefix = "pd_")
@UseStringTemplateEngine
@SqlQuery("SELECT pv.id," +
" pv.created_at," +
" pv.version_string," +
" pv.visibility," +
" pv.description," +
" coalesce((SELECT sum(pvd.downloads) FROM project_versions_downloads pvd WHERE p.id = pvd.project_id AND pv.id = pvd.version_id), 0) vs_downloads," +
" pv.file_name fi_name," +
" pv.file_size fi_size_bytes," +
" pv.hash fi_md5_hash," +
" pv.external_url," +
" u.name author," +
" pv.review_state," +
" pvt.name AS tag_name," +
" pvt.data AS tag_data," +
" pvt.color AS tag_color," +
" 'Channel' AS ch_tag_name," +
" pc.name AS ch_tag_data," +
" pc.color AS ch_tag_color," +
" d.platform pd_platform," +
" d.name pd_name," +
" d.required pd_required," +
" d.project_id pd_project_id," +
" d.external_url pd_external_url," +
" plv.platform p_platform," +
" plv.version p_version," +
" exists(SELECT 1 FROM recommended_project_versions rpv WHERE rpv.version_id = pv.id) as recommended," +
" ru.name approved_by" +
" pv.created_at," +
" pv.version_string," +
" pv.visibility," +
" pv.description," +
" coalesce((SELECT sum(pvd.downloads) FROM project_versions_downloads pvd WHERE p.id = pvd.project_id AND pv.id = pvd.version_id), 0) vs_downloads," +
" pv.file_name fi_name," +
" pv.file_size fi_size_bytes," +
" pv.hash fi_md5_hash," +
" pv.external_url," +
" u.name author," +
" pv.review_state," +
" exists(SELECT 1 FROM recommended_project_versions rpv WHERE rpv.version_id = pv.id) as recommended," +
" ru.name approved_by" +
" FROM project_versions pv" +
" JOIN projects p ON pv.project_id = p.id" +
" LEFT JOIN users u ON pv.author_id = u.id" +
" LEFT JOIN project_version_tags pvt ON pv.id = pvt.version_id" +
" LEFT JOIN project_channels pc ON pv.channel_id = pc.id " +
" JOIN project_version_platform_dependencies pvpd ON pv.id = pvpd.version_id" +
" JOIN platform_versions plv ON pvpd.platform_version_id = plv.id" +
" LEFT JOIN project_version_dependencies d ON pv.id = d.version_id" +
" LEFT JOIN users ru ON pv.reviewer_id = ru.id" +
" WHERE <if(!canSeeHidden)>(pv.visibility = 0 " +
" <if(userId)>OR (<userId> IN (SELECT pm.user_id FROM project_members_all pm WHERE pm.id = p.id) AND pv.visibility != 4) <endif>) AND <endif> " +
" plv.platform = :platform AND" +
" pvt.name IS NOT NULL AND" +
" lower(p.owner_name) = lower(:author) AND" +
" lower(p.slug) = lower(:slug) AND" +
" lower(pv.version_string) = lower(:versionString)" +
" GROUP BY p.id, pv.id, u.id, pc.id, d.id, plv.id, pvt.id, ru.id " +
" ORDER BY pv.created_at DESC")
Optional<HangarVersion> getVersion(String author, String slug, String versionString, @EnumByOrdinal Platform platform, @Define boolean canSeeHidden, @Define Long userId);
" WHERE " +
" <if(!canSeeHidden)>" +
" (pv.visibility = 0 " +
" <if(userId)>" +
" OR (<userId> IN (SELECT pm.user_id FROM project_members_all pm WHERE pm.id = p.id) AND pv.visibility != 4) " +
" <endif>)" +
" AND" +
" <endif>" +
" pv.id = :versionId" +
" ORDERED BY pv.created_at DESC"
)
HangarVersion getVersion(long versionId, @Define boolean canSeeHidden, @Define Long userId);
@UseEnumStrategy(EnumStrategy.BY_ORDINAL)
@UseRowReducer(HangarVersionReducer.class)
@RegisterConstructorMapper(value = PluginDependency.class, prefix = "pd_")
@UseStringTemplateEngine
@SqlQuery("SELECT pv.id," +
" pv.created_at," +
" pv.version_string," +
" pv.visibility," +
" pv.description," +
" coalesce((SELECT sum(pvd.downloads) FROM project_versions_downloads pvd WHERE p.id = pvd.project_id AND pv.id = pvd.version_id), 0) vs_downloads," +
" pv.file_name fi_name," +
" pv.file_size fi_size_bytes," +
" pv.hash fi_md5_hash," +
" pv.external_url," +
" u.name author," +
" pv.review_state," +
" pvt.name AS tag_name," +
" pvt.data AS tag_data," +
" pvt.color AS tag_color," +
" 'Channel' AS ch_tag_name," +
" pc.name AS ch_tag_data," +
" pc.color AS ch_tag_color," +
" d.platform pd_platform," +
" d.name pd_name," +
" d.required pd_required," +
" d.project_id pd_project_id," +
" d.external_url pd_external_url," +
" plv.platform p_platform," +
" plv.version p_version," +
" exists(SELECT 1 FROM recommended_project_versions rpv WHERE rpv.version_id = pv.id) as recommended," +
" ru.name approved_by" +
" pv.created_at," +
" pv.version_string," +
" pv.visibility," +
" pv.description," +
" coalesce((SELECT sum(pvd.downloads) FROM project_versions_downloads pvd WHERE p.id = pvd.project_id AND pv.id = pvd.version_id), 0) vs_downloads," +
" pv.file_name fi_name," +
" pv.file_size fi_size_bytes," +
" pv.hash fi_md5_hash," +
" pv.external_url," +
" u.name author," +
" pv.review_state," +
" exists(SELECT 1 FROM recommended_project_versions rpv WHERE rpv.version_id = pv.id) as recommended," +
" ru.name approved_by" +
" FROM project_versions pv" +
" JOIN projects p ON pv.project_id = p.id" +
" JOIN projects p ON pv.project_id = p.id" +
" LEFT JOIN users u ON pv.author_id = u.id" +
" LEFT JOIN project_version_tags pvt ON pv.id = pvt.version_id" +
" LEFT JOIN project_channels pc ON pv.channel_id = pc.id " +
" JOIN project_version_platform_dependencies pvpd ON pv.id = pvpd.version_id" +
" JOIN platform_versions plv ON pvpd.platform_version_id = plv.id" +
" LEFT JOIN project_version_dependencies d ON pv.id = d.version_id" +
" LEFT JOIN users ru ON pv.reviewer_id = ru.id" +
" WHERE <if(!canSeeHidden)>(pv.visibility = 0 " +
" <if(userId)>OR (<userId> IN (SELECT pm.user_id FROM project_members_all pm WHERE pm.id = p.id) AND pv.visibility != 4) <endif>) AND <endif> " +
" pvt.name IS NOT NULL AND" +
" WHERE " +
" <if(!canSeeHidden)>" +
" (pv.visibility = 0 " +
" <if(userId)>" +
" OR (<userId> IN (SELECT pm.user_id FROM project_members_all pm WHERE pm.id = p.id) AND pv.visibility != 4) " +
" <endif>)" +
" AND" +
" <endif>" +
" lower(p.owner_name) = lower(:author) AND" +
" lower(p.slug) = lower(:slug) AND" +
" lower(pv.version_string) = lower(:versionString)" +
" GROUP BY p.id, pv.id, u.id, pc.id, d.id, plv.id, pvt.id, ru.id" +
" ORDER BY pv.created_at DESC")
List<HangarVersion> getVersions(String author, String slug, String versionString, @Define boolean canSeeHidden, @Define Long userId);
class HangarVersionReducer implements LinkedHashMapRowReducer<Long, HangarVersion> {
@Override
public void accumulate(Map<Long, HangarVersion> container, RowView rowView) {
final HangarVersion version = container.computeIfAbsent(rowView.getColumn("id", Long.class), id -> rowView.getRow(HangarVersion.class));
VersionReducer._accumulateVersion(rowView, version.getPluginDependencies(), version.getPlatformDependencies(), version.getTags(), version);
}
}
" pv.version_string = :versionString" +
" ORDER BY pv.created_at DESC"
)
List<HangarVersion> getVersionsWithVersionString(String author, String slug, String versionString, @Define boolean canSeeHidden, @Define Long userId);
}

View File

@ -28,6 +28,9 @@ public interface ProjectChannelsDAO {
@SqlQuery("SELECT * FROM project_channels WHERE project_id = :projectId AND name = :name AND color = :color")
ProjectChannelTable getProjectChannel(long projectId, String name, @EnumByOrdinal Color color);
@SqlQuery("SELECT pc.* FROM project_channels pc JOIN project_versions pv ON pc.id = pv.channel_id WHERE pv.id = :versionId")
ProjectChannelTable getProjectChannelForVersion(long versionId);
@SqlQuery("SELECT * FROM project_channels WHERE project_id = :projectId ORDER BY created_at LIMIT 1")
ProjectChannelTable getFirstChannel(long projectId);
}

View File

@ -1,44 +1,171 @@
package io.papermc.hangar.db.dao.v1;
import io.papermc.hangar.model.api.color.TagColor;
import io.papermc.hangar.db.mappers.TagMapper;
import io.papermc.hangar.model.api.project.version.PluginDependency;
import io.papermc.hangar.model.api.project.version.Tag;
import io.papermc.hangar.model.api.project.version.Version;
import io.papermc.hangar.model.api.project.version.VersionStats;
import io.papermc.hangar.model.common.Color;
import io.papermc.hangar.model.common.Platform;
import io.papermc.hangar.util.StringUtils;
import org.jdbi.v3.core.enums.EnumByOrdinal;
import org.jdbi.v3.core.enums.EnumStrategy;
import org.jdbi.v3.core.result.LinkedHashMapRowReducer;
import org.jdbi.v3.core.result.RowView;
import org.jdbi.v3.sqlobject.config.KeyColumn;
import org.jdbi.v3.sqlobject.config.RegisterConstructorMapper;
import org.jdbi.v3.sqlobject.config.RegisterRowMapper;
import org.jdbi.v3.sqlobject.config.UseEnumStrategy;
import org.jdbi.v3.sqlobject.config.ValueColumn;
import org.jdbi.v3.sqlobject.customizer.BindList;
import org.jdbi.v3.sqlobject.customizer.Define;
import org.jdbi.v3.sqlobject.statement.SqlQuery;
import org.jdbi.v3.sqlobject.statement.UseRowReducer;
import org.jdbi.v3.stringtemplate4.UseStringTemplateEngine;
import org.springframework.stereotype.Repository;
import java.time.OffsetDateTime;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
@Repository
@UseStringTemplateEngine
@UseEnumStrategy(EnumStrategy.BY_ORDINAL)
@RegisterConstructorMapper(Version.class)
public interface VersionsApiDAO {
@UseEnumStrategy(EnumStrategy.BY_ORDINAL)
@UseRowReducer(VersionReducer.class)
@RegisterConstructorMapper(value = PluginDependency.class, prefix = "pd_")
@KeyColumn("id")
@SqlQuery("SELECT pv.id," +
" pv.created_at," +
" pv.created_at," +
" pv.version_string," +
" pv.visibility," +
" pv.description," +
" coalesce((SELECT sum(pvd.downloads) FROM project_versions_downloads pvd WHERE p.id = pvd.project_id AND pv.id = pvd.version_id), 0) vs_downloads," +
" pv.file_name fi_name," +
" pv.file_size fi_size_bytes," +
" pv.hash fi_md5_hash," +
" pv.external_url," +
" u.name author," +
" pv.review_state," +
" exists(SELECT 1 FROM recommended_project_versions rpv WHERE rpv.version_id = pv.id) as recommended" +
" FROM project_versions pv" +
" JOIN projects p ON pv.project_id = p.id" +
" LEFT JOIN users u ON pv.author_id = u.id" +
" WHERE " +
" <if(!canSeeHidden)>" +
" (pv.visibility = 0 " +
" <if(userId)>" +
" OR (<userId> IN (SELECT pm.user_id FROM project_members_all pm WHERE pm.id = p.id) AND pv.visibility != 4) " +
" <endif>)" +
" AND" +
" <endif>" +
" pv.id = :versionId" +
" ORDERED BY pv.created_at DESC"
)
Entry<Long, Version> getVersion(long versionId, @Define boolean canSeeHidden, @Define Long userId);
@KeyColumn("id")
@SqlQuery("SELECT pv.id," +
" pv.created_at," +
" pv.version_string," +
" pv.visibility," +
" pv.description," +
" coalesce((SELECT sum(pvd.downloads) FROM project_versions_downloads pvd WHERE p.id = pvd.project_id AND pv.id = pvd.version_id), 0) vs_downloads," +
" pv.file_name fi_name," +
" pv.file_size fi_size_bytes," +
" pv.hash fi_md5_hash," +
" pv.external_url," +
" u.name author," +
" pv.review_state," +
" exists(SELECT 1 FROM recommended_project_versions rpv WHERE rpv.version_id = pv.id) as recommended" +
" FROM project_versions pv" +
" JOIN projects p ON pv.project_id = p.id" +
" LEFT JOIN users u ON pv.author_id = u.id" +
" WHERE " +
" <if(!canSeeHidden)>" +
" (pv.visibility = 0 " +
" <if(userId)>" +
" OR (<userId> IN (SELECT pm.user_id FROM project_members_all pm WHERE pm.id = p.id) AND pv.visibility != 4) " +
" <endif>)" +
" AND" +
" <endif>" +
" lower(p.owner_name) = lower(:author) AND" +
" lower(p.slug) = lower(:slug) AND" +
" pv.version_string = :versionString" +
" ORDER BY pv.created_at DESC"
)
SortedMap<Long, Version> getVersionsWithVersionString(String author, String slug, String versionString, @Define boolean canSeeHidden, @Define Long userId);
@KeyColumn("id")
@SqlQuery("SELECT pv.id," +
" pv.created_at," +
" pv.version_string," +
" pv.visibility," +
" pv.description," +
" coalesce((SELECT sum(pvd.downloads) FROM project_versions_downloads pvd WHERE p.id = pvd.project_id AND pv.id = pvd.version_id), 0) vs_downloads," +
" pv.file_name fi_name," +
" pv.file_size fi_size_bytes," +
" pv.hash fi_md5_hash," +
" pv.external_url," +
" u.name author," +
" pv.review_state," +
" exists(SELECT 1 FROM recommended_project_versions rpv WHERE rpv.version_id = pv.id) as recommended" +
" FROM project_versions pv" +
" JOIN projects p ON pv.project_id = p.id" +
" LEFT JOIN users u ON pv.author_id = u.id" +
" WHERE " +
" <if(!canSeeHidden)>" +
" (pv.visibility = 0 " +
" <if(userId)>" +
" OR (<userId> IN (SELECT pm.user_id FROM project_members_all pm WHERE pm.id = p.id) AND pv.visibility != 4) " +
" <endif>)" +
" AND" +
" <endif>" +
" lower(p.owner_name) = lower(:author) AND" +
" lower(p.slug) = lower(:slug) " +
// TODO tags
/*" <if(tags)> AND (" +
" pvt.name || ':' || pvt.data IN (<tags>) OR " +
" pvt.name IN (<tags>) OR " +
" 'Channel:' || pc.name IN (<tags>) OR " +
" 'Channel' IN (<tags>)" +
" )" +
" <endif> " +*/
" ORDER BY pv.created_at DESC LIMIT :limit OFFSET :offset"
)
SortedMap<Long, Version> getVersions(String author, String slug, @BindList(onEmpty = BindList.EmptyHandling.NULL_VALUE) List<String> tags, @Define boolean canSeeHidden, @Define Long userId, long limit, long offset);
@KeyColumn("platform")
@SqlQuery("SELECT " +
" pvd.name," +
" pvd.required," +
" pvd.external_url," +
" p.owner_name pn_owner," +
" p.slug pn_slug" +
" FROM project_version_dependencies pvd" +
" LEFT JOIN projects p ON pvd.project_id = p.id" +
" WHERE pvd.version_id = :versionId AND pvd.platform = :platform")
@RegisterConstructorMapper(PluginDependency.class)
Set<PluginDependency> getPluginDependencies(long versionId, @EnumByOrdinal Platform platform);
@KeyColumn("platform")
@ValueColumn("versions")
@SqlQuery("SELECT" +
" pv.platform," +
" array_agg(pv.version ORDER BY pv.created_at) versions" +
" FROM project_version_platform_dependencies pvpd " +
" JOIN platform_versions pv ON pvpd.platform_version_id = pv.id" +
" WHERE pvpd.version_id = :versionId" +
" GROUP BY pv.platform")
Map<Platform, SortedSet<String>> getPlatformDependencies(long versionId);
@SqlQuery("SELECT pvt.name, pvt.data, pvt.color FROM project_version_tags pvt WHERE pvt.version_id = :versionId")
@RegisterRowMapper(TagMapper.class)
Set<Tag> getVersionTags(long versionId);
/*@UseRowReducer(VersionReducer.class)
@RegisterConstructorMapper(value = PluginDependency.class, prefix = "pd_")
@UseStringTemplateEngine
@SqlQuery("SELECT pv.created_at," +
" pv.version_string," +
" pv.visibility," +
" pv.description," +
@ -58,7 +185,8 @@ public interface VersionsApiDAO {
" d.platform pd_platform," +
" d.name pd_name," +
" d.required pd_required," +
" d.project_id pd_project_id," +
" pdp.owner_name pd_owner," +
" pdp.slug pd_slug," +
" d.external_url pd_external_url," +
" plv.platform p_platform," +
" plv.version p_version," +
@ -71,6 +199,7 @@ public interface VersionsApiDAO {
" JOIN project_version_platform_dependencies pvpd ON pv.id = pvpd.version_id" +
" JOIN platform_versions plv ON pvpd.platform_version_id = plv.id" +
" LEFT JOIN project_version_dependencies d ON pv.id = d.version_id" +
" LEFT JOIN projects pdp ON d.project_id = pdp.id" +
" WHERE <if(!canSeeHidden)>(pv.visibility = 0 " +
" <if(userId)>OR (<userId> IN (SELECT pm.user_id FROM project_members_all pm WHERE pm.id = p.id) AND pv.visibility != 4) <endif>) AND <endif> " +
" plv.platform = :platform AND" +
@ -78,13 +207,14 @@ public interface VersionsApiDAO {
" lower(p.owner_name) = lower(:author) AND" +
" lower(p.slug) = lower(:slug) AND" +
" lower(pv.version_string) = lower(:versionString)" +
" GROUP BY p.id, pv.id, u.id, pc.id, d.id, plv.id, pvt.id" +
" GROUP BY p.id, pv.id, u.id, pc.id, d.id, plv.id, pvt.id, pdp.id" +
" ORDER BY pv.created_at DESC")
Version getVersion(String author, String slug, String versionString, @EnumByOrdinal Platform platform, @Define boolean canSeeHidden, @Define Long userId);
@UseEnumStrategy(EnumStrategy.BY_ORDINAL)
@UseRowReducer(VersionReducer.class)
@RegisterConstructorMapper(value = PluginDependency.class, prefix = "pd_")
@UseStringTemplateEngine
@SqlQuery("SELECT pv.id," +
" pv.created_at," +
" pv.version_string," +
@ -106,7 +236,8 @@ public interface VersionsApiDAO {
" d.platform pd_platform," +
" d.name pd_name," +
" d.required pd_required," +
" d.project_id pd_project_id," +
" pdp.owner_name pd_owner," +
" pdp.slug pd_slug," +
" d.external_url pd_external_url," +
" plv.platform p_platform," +
" plv.version p_version," +
@ -119,51 +250,23 @@ public interface VersionsApiDAO {
" JOIN project_version_platform_dependencies pvpd ON pv.id = pvpd.version_id" +
" JOIN platform_versions plv ON pvpd.platform_version_id = plv.id" +
" LEFT JOIN project_version_dependencies d ON pv.id = d.version_id" +
" LEFT JOIN projects pdp ON d.project_id = pdp.id" +
" WHERE <if(!canSeeHidden)>(pv.visibility = 0 " +
" <if(userId)>OR (<userId> IN (SELECT pm.user_id FROM project_members_all pm WHERE pm.id = p.id) AND pv.visibility != 4) <endif>) AND <endif> " +
" pvt.name IS NOT NULL AND" +
" lower(p.owner_name) = lower(:author) AND" +
" lower(p.slug) = lower(:slug) AND" +
" lower(pv.version_string) = lower(:versionString)" +
" GROUP BY p.id, pv.id, u.id, pc.id, d.id, plv.id, pvt.id" +
" GROUP BY p.id, pv.id, u.id, pc.id, d.id, plv.id, pvt.id, pdp.id" +
" ORDER BY pv.created_at DESC")
List<Version> getVersions(String author, String slug, String versionString, @Define boolean canSeeHidden, @Define Long userId);
class VersionReducer implements LinkedHashMapRowReducer<Long, Version> {
@Override
public void accumulate(Map<Long, Version> container, RowView rowView) {
final Version version = container.computeIfAbsent(rowView.getColumn("id", Long.class), id -> rowView.getRow(Version.class));
VersionReducer._accumulateVersion(rowView, version.getPluginDependencies(), version.getPlatformDependencies(), version.getTags(), version);
}
public static <T extends Version> void _accumulateVersion(RowView rowView, Map<Platform, Set<PluginDependency>> pluginDependencies, Map<Platform, Set<String>> platformDependencies, Set<Tag> tags, T version) { // What a mess really
Platform pluginPlatform = rowView.getColumn("pd_platform", Platform.class);
if (pluginPlatform != null) {
pluginDependencies.computeIfAbsent(pluginPlatform, _pl -> new HashSet<>());
pluginDependencies.get(pluginPlatform).add(rowView.getRow(PluginDependency.class));
}
Platform platformPlatform = rowView.getColumn("p_platform", Platform.class);
platformDependencies.computeIfAbsent(platformPlatform, _pl -> new HashSet<>());
platformDependencies.get(platformPlatform).add(rowView.getColumn("p_version", String.class));
if (rowView.getColumn("ch_tag_name", String.class) != null) {
tags.add(new Tag(rowView.getColumn("ch_tag_name", String.class), rowView.getColumn("ch_tag_data", String.class), new TagColor(null, rowView.getColumn("ch_tag_color", Color.class).getHex())));
}
if (rowView.getColumn("tag_name", String.class) != null) {
tags.add(new Tag(
rowView.getColumn("tag_name", String.class),
StringUtils.formatVersionNumbers(Arrays.asList(rowView.getColumn("tag_data", String[].class))),
rowView.getColumn("tag_color", io.papermc.hangar.model.common.TagColor.class).toTagColor()
));
}
}
}
@UseEnumStrategy(EnumStrategy.BY_ORDINAL)
@UseRowReducer(VersionReducer.class)
@RegisterConstructorMapper(value = PluginDependency.class, prefix = "pd_")
@UseStringTemplateEngine
@SqlQuery("SELECT pv.id," +
" pv.created_at," +
" pv.version_string," +
@ -185,11 +288,13 @@ public interface VersionsApiDAO {
" d.platform pd_platform," +
" d.name pd_name," +
" d.required pd_required," +
" d.project_id pd_project_id," +
" pdp.owner_name pd_owner," +
" pdp.slug pd_slug," +
" d.external_url pd_external_url," +
" plv.platform p_platform," +
" plv.version p_version," +
" exists(SELECT 1 FROM recommended_project_versions rpv WHERE rpv.version_id = pv.id) as recommended" +
" exists(SELECT 1 FROM recommended_project_versions rpv WHERE rpv.version_id = pv.id) as recommended," +
" ru.name approved_by" +
" FROM project_versions pv" +
" JOIN projects p ON pv.project_id = p.id" +
" LEFT JOIN users u ON pv.author_id = u.id" +
@ -198,32 +303,35 @@ public interface VersionsApiDAO {
" JOIN project_version_platform_dependencies pvpd ON pv.id = pvpd.version_id" +
" JOIN platform_versions plv ON pvpd.platform_version_id = plv.id" +
" LEFT JOIN project_version_dependencies d ON pv.id = d.version_id" +
" LEFT JOIN projects pdp ON d.project_id = pdp.id" +
" LEFT JOIN users ru ON pv.reviewer_id = ru.id" +
" WHERE <if(!canSeeHidden)>(pv.visibility = 0 " +
" <if(userId)>OR (<userId> IN (SELECT pm.user_id FROM project_members_all pm WHERE pm.id = p.id) AND pv.visibility != 4) <endif>) AND <endif> " +
" pvt.name IS NOT NULL AND" +
" lower(p.owner_name) = lower(:author) AND" +
" lower(p.slug) = lower(:slug)" +
" GROUP BY p.id, pv.id, u.id, pc.id, d.id, plv.id, pvt.id" +
" GROUP BY p.id, pv.id, u.id, pc.id, d.id, plv.id, pvt.id, pdp.id, ru.id" +
" ORDER BY pv.created_at DESC LIMIT :limit OFFSET :offset")
List<Version> getVersions(String author, String slug, @BindList(onEmpty = BindList.EmptyHandling.NULL_VALUE) List<String> tags, @Define boolean canSeeHidden, @Define Long userId, long limit, long offset);
List<Version> getVersions(String author, String slug, @BindList(onEmpty = BindList.EmptyHandling.NULL_VALUE) List<String> tags, @Define boolean canSeeHidden, @Define Long userId, long limit, long offset);*/
@SqlQuery("SELECT COUNT(*) " +
"FROM projects p" +
" JOIN project_versions pv ON p.id = pv.project_id" +
" LEFT JOIN users u ON pv.author_id = u.id" +
" LEFT JOIN project_version_tags pvt ON pv.id = pvt.version_id" +
" LEFT JOIN project_channels pc ON pv.channel_id = pc.id " +
" LEFT JOIN users u ON pv.author_id = u.id " +
// " LEFT JOIN project_version_tags pvt ON pv.id = pvt.version_id" +
// " LEFT JOIN project_channels pc ON pv.channel_id = pc.id " +
"WHERE <if(!canSeeHidden)>(pv.visibility = 0 " +
"<if(userId)>OR (<userId> IN (SELECT pm.user_id FROM project_members_all pm WHERE pm.id = p.id) AND pv.visibility != 4) <endif>) AND <endif> " +
"p.slug = :slug AND " +
"p.owner_name = :author <if(tags)> AND " +
"lower(p.slug) = lower(:slug) AND " +
"lower(p.owner_name) = lower(:author)" + /* <if(tags)> AND " +
// TODO tags
"(" +
" pvt.name || ':' || pvt.data IN (<tags>) OR " +
" pvt.name IN (<tags>) OR " +
" 'Channel:' || pc.name IN (<tags>) OR " +
" 'Channel' IN (<tags>)" +
" )<endif> " +
"GROUP BY p.id, pv.id, u.id, pc.id")
" )<endif> " + */
"GROUP BY p.id, pv.id, u.id")
Long getVersionCount(String author, String slug, @BindList(onEmpty = BindList.EmptyHandling.NULL_VALUE) List<String> tags, @Define boolean canSeeHidden, @Define Long userId);
// TODO this might be totally screwed up by adding the platform check
@ -242,4 +350,36 @@ public interface VersionsApiDAO {
" AND plv.platform = :platform" +
" AND (pvd IS NULL OR (pvd.project_id = p.id AND pvd.version_id = pv.id));")
Map<String, VersionStats> getVersionStats(String author, String slug, String versionString, @EnumByOrdinal Platform platform, OffsetDateTime fromDate, OffsetDateTime toDate);
/*class VersionReducer implements LinkedHashMapRowReducer<Long, Version> {
@Override
public void accumulate(Map<Long, Version> container, RowView rowView) {
final Version version = container.computeIfAbsent(rowView.getColumn("id", Long.class), id -> rowView.getRow(Version.class));
VersionReducer._accumulateVersion(rowView, version);
}
public static <T extends Version> void _accumulateVersion(RowView rowView, T version) { // What a mess really
Platform pluginPlatform = rowView.getColumn("pd_platform", Platform.class);
if (pluginPlatform != null) {
version.getPluginDependencies().computeIfAbsent(pluginPlatform, _pl -> new HashSet<>());
version.getPluginDependencies().get(pluginPlatform).add(rowView.getRow(PluginDependency.class));
}
Platform platformPlatform = rowView.getColumn("p_platform", Platform.class);
version.getPlatformDependencies().computeIfAbsent(platformPlatform, _pl -> new HashSet<>());
version.getPlatformDependencies().get(platformPlatform).add(rowView.getColumn("p_version", String.class));
if (rowView.getColumn("ch_tag_name", String.class) != null) {
version.getTags().add(new Tag(rowView.getColumn("ch_tag_name", String.class), rowView.getColumn("ch_tag_data", String.class), new TagColor(null, rowView.getColumn("ch_tag_color", Color.class).getHex())));
}
if (rowView.getColumn("tag_name", String.class) != null) {
version.getTags().add(new Tag(
rowView.getColumn("tag_name", String.class),
StringUtils.formatVersionNumbers(Arrays.asList(rowView.getColumn("tag_data", String[].class))),
rowView.getColumn("tag_color", io.papermc.hangar.model.common.TagColor.class).toTagColor()
));
}
}
}*/
}

View File

@ -0,0 +1,22 @@
package io.papermc.hangar.db.mappers;
import io.papermc.hangar.model.api.color.TagColor;
import io.papermc.hangar.model.api.project.version.Tag;
import io.papermc.hangar.util.StringUtils;
import org.jdbi.v3.core.mapper.RowMapper;
import org.jdbi.v3.core.statement.StatementContext;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
public class TagMapper implements RowMapper<Tag> {
@Override
public Tag map(ResultSet rs, StatementContext ctx) throws SQLException {
String name = rs.getString("name");
String[] data = (String[]) rs.getArray("data").getArray();
TagColor tagColor = io.papermc.hangar.model.common.TagColor.getValues()[rs.getInt("color")].toTagColor();
return new Tag(name, data != null ? StringUtils.formatVersionNumbers(Arrays.asList(data)) : null, tagColor);
}
}

View File

@ -1,11 +1,15 @@
package io.papermc.hangar.model.api.project;
import org.jdbi.v3.core.mapper.PropagateNull;
import java.util.Objects;
public class ProjectNamespace {
private final String owner;
private final String slug;
public ProjectNamespace(String owner, String slug) {
public ProjectNamespace(@PropagateNull String owner, String slug) {
this.owner = owner;
this.slug = slug;
}
@ -25,5 +29,18 @@ public class ProjectNamespace {
", slug='" + slug + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ProjectNamespace that = (ProjectNamespace) o;
return owner.equals(that.owner) && slug.equals(that.slug);
}
@Override
public int hashCode() {
return Objects.hash(owner, slug);
}
}

View File

@ -2,6 +2,9 @@ package io.papermc.hangar.model.api.project.version;
import io.papermc.hangar.controller.validations.AtLeastOneNotNull;
import io.papermc.hangar.model.Named;
import io.papermc.hangar.model.api.project.ProjectNamespace;
import org.jdbi.v3.core.mapper.Nested;
import org.jetbrains.annotations.Nullable;
import javax.validation.constraints.NotBlank;
import java.util.Objects;
@ -12,13 +15,13 @@ public class PluginDependency implements Named {
@NotBlank(message = "Must have a dependency name")
private final String name;
private final boolean required;
private final Long projectId;
private final ProjectNamespace namespace;
private final String externalUrl;
public PluginDependency(String name, boolean required, Long projectId, String externalUrl) {
public PluginDependency(String name, boolean required, @Nested("pn") @Nullable ProjectNamespace namespace, String externalUrl) {
this.name = name;
this.required = required;
this.projectId = projectId;
this.namespace = namespace;
this.externalUrl = externalUrl;
}
@ -31,8 +34,9 @@ public class PluginDependency implements Named {
return required;
}
public Long getProjectId() {
return projectId;
@Nullable
public ProjectNamespace getNamespace() {
return namespace;
}
public String getExternalUrl() {
@ -44,7 +48,7 @@ public class PluginDependency implements Named {
return "PluginDependency{" +
"name='" + name + '\'' +
", required=" + required +
", projectId=" + projectId +
", namespace=" + namespace +
", externalUrl='" + externalUrl + '\'' +
'}';
}
@ -54,11 +58,11 @@ public class PluginDependency implements Named {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PluginDependency that = (PluginDependency) o;
return required == that.required && name.equals(that.name) && Objects.equals(projectId, that.projectId) && Objects.equals(externalUrl, that.externalUrl);
return required == that.required && name.equals(that.name) && Objects.equals(namespace, that.namespace) && Objects.equals(externalUrl, that.externalUrl);
}
@Override
public int hashCode() {
return Objects.hash(name, required, projectId, externalUrl);
return Objects.hash(name, required, namespace, externalUrl);
}
}

View File

@ -16,6 +16,7 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
// TODO CompactVersion w/o dependencies for the version list page
public class Version extends Model implements Named, Visible {
private final String name;

View File

@ -11,6 +11,7 @@ import io.papermc.hangar.model.common.Platform;
import io.papermc.hangar.model.db.projects.ProjectChannelTable;
import org.jetbrains.annotations.Nullable;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
@ -24,9 +25,8 @@ public class PendingVersion {
@NotBlank(message = "version.new.error.invalidVersionString")
@Validate(SpEL = "#root matches @hangarConfig.projects.versionNameRegex", message = "version.new.error.invalidVersionString")
private final String versionString;
// TODO validate below by uncommenting the @Valid annotation
private final Map<Platform, Set</*@Valid */PluginDependency>> pluginDependencies;
@Validate(SpEL = "#root.size lt 1 or #root.size gt T(io.papermc.hangar.model.common.Platform).getValues().length", message = "version.new.error.invalidNumOfPlatforms")
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 = "Empty platform version list") Set<@NotBlank(message = "version.new.error.invalidPlatformVersion") String>> platformDependencies;
@NotBlank(message = "version.new.error.noDescription")
private final String description;
@ -64,7 +64,7 @@ public class PendingVersion {
this.versionString = versionString;
this.pluginDependencies = pluginDependencies;
this.platformDependencies = platformDependencies;
this.description = "## " + this.versionString + "\n\n" + description;
this.description = "## " + this.versionString + (description != null ? "\n\n" + description : "");
this.fileInfo = fileInfo;
this.forumSync = forumSync;
this.externalUrl = null;

View File

@ -10,7 +10,10 @@ import io.papermc.hangar.model.api.project.version.VersionStats;
import io.papermc.hangar.model.api.requests.RequestPagination;
import io.papermc.hangar.model.common.Permission;
import io.papermc.hangar.model.common.Platform;
import io.papermc.hangar.model.db.versions.ProjectVersionTable;
import io.papermc.hangar.service.HangarService;
import io.papermc.hangar.service.internal.versions.VersionDependencyService;
import io.papermc.hangar.service.internal.versions.VersionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
@ -18,23 +21,33 @@ import org.springframework.stereotype.Service;
import java.time.OffsetDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
public class VersionsApiService extends HangarService {
private final VersionsApiDAO versionsApiDAO;
private final VersionService versionService;
private final VersionDependencyService versionDependencyService;
@Autowired
public VersionsApiService(HangarDao<VersionsApiDAO> versionsApiDAO) {
public VersionsApiService(HangarDao<VersionsApiDAO> versionsApiDAO, VersionService versionService, VersionDependencyService versionDependencyService) {
this.versionsApiDAO = versionsApiDAO.get();
this.versionService = versionService;
this.versionDependencyService = versionDependencyService;
}
public Version getVersion(String author, String slug, String versionString, Platform platform) {
return versionsApiDAO.getVersion(author, slug, versionString, platform, getGlobalPermissions().has(Permission.SeeHidden), getHangarUserId());
ProjectVersionTable projectVersionTable = versionService.getProjectVersionTable(author, slug, versionString, platform);
if (projectVersionTable == null) {
throw new HangarApiException(HttpStatus.NOT_FOUND);
}
var entry = versionsApiDAO.getVersion(projectVersionTable.getId(), getGlobalPermissions().has(Permission.SeeHidden), getHangarUserId());
return versionDependencyService.addDependenciesAndTags(entry.getKey(), entry.getValue());
}
public List<Version> getVersions(String author, String slug, String versionString) {
List<Version> versions = versionsApiDAO.getVersions(author, slug, versionString, getGlobalPermissions().has(Permission.SeeHidden), getHangarUserId());
List<Version> versions = versionsApiDAO.getVersionsWithVersionString(author, slug, versionString, getGlobalPermissions().has(Permission.SeeHidden), getHangarUserId()).entrySet().stream().map(entry -> versionDependencyService.addDependenciesAndTags(entry.getKey(), entry.getValue())).collect(Collectors.toList());
if (versions.isEmpty()) {
throw new HangarApiException(HttpStatus.NOT_FOUND);
}
@ -42,7 +55,7 @@ public class VersionsApiService extends HangarService {
}
public PaginatedResult<Version> getVersions(String author, String slug, List<String> tags, RequestPagination pagination) {
List<Version> versions = versionsApiDAO.getVersions(author, slug, tags, getGlobalPermissions().has(Permission.SeeHidden), getHangarUserId(), pagination.getLimit(), pagination.getOffset());
List<Version> versions = versionsApiDAO.getVersions(author, slug, tags, getGlobalPermissions().has(Permission.SeeHidden), getHangarUserId(), pagination.getLimit(), pagination.getOffset()).entrySet().stream().map(entry -> versionDependencyService.addDependenciesAndTags(entry.getKey(), entry.getValue())).collect(Collectors.toList());
Long versionCount = versionsApiDAO.getVersionCount(author, slug, tags, getGlobalPermissions().has(Permission.SeeHidden), getHangarUserId());
return new PaginatedResult<>(new Pagination(versionCount == null ? 0 : versionCount, pagination), versions);
}

View File

@ -49,6 +49,10 @@ public class ChannelService extends HangarService {
return projectChannelsDAO.getProjectChannel(projectId, name, color);
}
public ProjectChannelTable getProjectChannelForVersion(long versionId) {
return projectChannelsDAO.getProjectChannelForVersion(versionId);
}
public ProjectChannelTable getFirstChannel(long projectId) {
return projectChannelsDAO.getFirstChannel(projectId);
}

View File

@ -1,27 +1,37 @@
package io.papermc.hangar.service.internal.versions;
import io.papermc.hangar.db.dao.HangarDao;
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.v1.VersionsApiDAO;
import io.papermc.hangar.model.api.color.TagColor;
import io.papermc.hangar.model.api.project.version.PluginDependency;
import io.papermc.hangar.model.api.project.version.Tag;
import io.papermc.hangar.model.api.project.version.Version;
import io.papermc.hangar.model.common.Platform;
import io.papermc.hangar.model.db.projects.ProjectChannelTable;
import io.papermc.hangar.model.db.versions.ProjectVersionDependencyTable;
import io.papermc.hangar.model.db.versions.ProjectVersionPlatformDependencyTable;
import io.papermc.hangar.service.HangarService;
import io.papermc.hangar.service.internal.projects.ChannelService;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Set;
@Service
public class VersionDependencyService extends HangarService {
private final ProjectVersionDependenciesDAO projectVersionDependenciesDAO;
private final VersionsApiDAO versionsApiDAO;
private final ProjectVersionPlatformDependenciesDAO projectVersionPlatformDependenciesDAO;
private final PlatformVersionDAO platformVersionDAO;
private final ChannelService channelService;
public VersionDependencyService(HangarDao<ProjectVersionDependenciesDAO> projectVersionDependencyDAO, HangarDao<ProjectVersionPlatformDependenciesDAO> projectVersionPlatformDependencyDAO, HangarDao<PlatformVersionDAO> platformVersionDAO) {
public VersionDependencyService(HangarDao<ProjectVersionDependenciesDAO> projectVersionDependencyDAO, HangarDao<VersionsApiDAO> versionsApiDAO, HangarDao<ProjectVersionPlatformDependenciesDAO> projectVersionPlatformDependencyDAO, ChannelService channelService) {
this.projectVersionDependenciesDAO = projectVersionDependencyDAO.get();
this.versionsApiDAO = versionsApiDAO.get();
this.projectVersionPlatformDependenciesDAO = projectVersionPlatformDependencyDAO.get();
this.platformVersionDAO = platformVersionDAO.get();
this.channelService = channelService;
}
public List<ProjectVersionDependencyTable> getProjectVersionDependencyTables(long versionId) {
@ -32,4 +42,18 @@ public class VersionDependencyService extends HangarService {
return projectVersionPlatformDependenciesDAO.getForVersion(versionId);
}
public <T extends Version> T addDependenciesAndTags(Long versionId, T version) {
version.getPlatformDependencies().putAll(versionsApiDAO.getPlatformDependencies(versionId));
for (Platform platform : Platform.getValues()) {
Set<PluginDependency> pluginDependencySet = versionsApiDAO.getPluginDependencies(versionId, platform);
if (!pluginDependencySet.isEmpty()) {
version.getPluginDependencies().put(platform, pluginDependencySet);
}
}
version.getTags().addAll(versionsApiDAO.getVersionTags(versionId));
ProjectChannelTable projectChannelTable = channelService.getProjectChannelForVersion(versionId);
version.getTags().add(new Tag("Channel", projectChannelTable.getName(), new TagColor(null, projectChannelTable.getColor().getHex())));
return version;
}
}

View File

@ -44,6 +44,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
@Service
public class VersionFactory extends HangarService {
@ -205,7 +206,15 @@ public class VersionFactory extends HangarService {
List<ProjectVersionDependencyTable> pluginDependencyTables = new ArrayList<>();
for (var platformListEntry : pendingVersion.getPluginDependencies().entrySet()) {
for (PluginDependency pluginDependency : platformListEntry.getValue()) {
pluginDependencyTables.add(new ProjectVersionDependencyTable(projectVersionTable.getId(), platformListEntry.getKey(), pluginDependency.getName(), pluginDependency.isRequired(), pluginDependency.getProjectId(), pluginDependency.getExternalUrl()));
Long depProjectId = null;
if (pluginDependency.getNamespace() != null) {
Optional<ProjectTable> depProjectTable = Optional.ofNullable(projectService.getProjectTable(pluginDependency.getNamespace().getOwner(), pluginDependency.getNamespace().getSlug()));
if (depProjectTable.isEmpty()) {
throw new HangarApiException(HttpStatus.BAD_REQUEST, "version.new.error.invalidPluginDependencyNamespace");
}
depProjectId = depProjectTable.get().getProjectId();
}
pluginDependencyTables.add(new ProjectVersionDependencyTable(projectVersionTable.getId(), platformListEntry.getKey(), pluginDependency.getName(), pluginDependency.isRequired(), depProjectId, pluginDependency.getExternalUrl()));
}
}
projectVersionDependenciesDAO.insertAll(pluginDependencyTables);

View File

@ -19,6 +19,7 @@ import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@Service
public class VersionService extends HangarService {
@ -26,12 +27,14 @@ public class VersionService extends HangarService {
private final ProjectVersionsDAO projectVersionsDAO;
private final HangarVersionsDAO hangarVersionsDAO;
private final ProjectVersionVisibilityService projectVersionVisibilityService;
private final VersionDependencyService versionDependencyService;
@Autowired
public VersionService(HangarDao<ProjectVersionsDAO> projectVersionDAO, HangarDao<HangarVersionsDAO> hangarProjectsDAO, ProjectVersionVisibilityService projectVersionVisibilityService) {
public VersionService(HangarDao<ProjectVersionsDAO> projectVersionDAO, HangarDao<HangarVersionsDAO> hangarProjectsDAO, ProjectVersionVisibilityService projectVersionVisibilityService, VersionDependencyService versionDependencyService) {
this.projectVersionsDAO = projectVersionDAO.get();
this.hangarVersionsDAO = hangarProjectsDAO.get();
this.projectVersionVisibilityService = projectVersionVisibilityService;
this.versionDependencyService = versionDependencyService;
}
@Nullable
@ -52,15 +55,20 @@ public class VersionService extends HangarService {
}
public HangarVersion getHangarVersion(String author, String slug, String versionString, Platform platform) {
return hangarVersionsDAO.getVersion(author, slug, versionString, platform, getGlobalPermissions().has(Permission.SeeHidden), getHangarUserId()).orElseThrow(() -> new HangarApiException(HttpStatus.NOT_FOUND));
ProjectVersionTable projectVersionTable = getProjectVersionTable(author, slug, versionString, platform);
if (projectVersionTable == null) {
throw new HangarApiException(HttpStatus.NOT_FOUND);
}
HangarVersion hangarVersion = hangarVersionsDAO.getVersion(projectVersionTable.getId(), getGlobalPermissions().has(Permission.SeeHidden), getHangarUserId());
return versionDependencyService.addDependenciesAndTags(hangarVersion.getId(), hangarVersion);
}
public List<HangarVersion> getHangarVersions(String author, String slug, String versionString) {
List<HangarVersion> versions = hangarVersionsDAO.getVersions(author, slug, versionString, getGlobalPermissions().has(Permission.SeeHidden), getHangarUserId());
List<HangarVersion> versions = hangarVersionsDAO.getVersionsWithVersionString(author, slug, versionString, getGlobalPermissions().has(Permission.SeeHidden), getHangarUserId());
if (versions.isEmpty()) {
throw new HangarApiException(HttpStatus.NOT_FOUND);
}
return versions;
return versions.stream().map(v -> versionDependencyService.addDependenciesAndTags(v.getId(), v)).collect(Collectors.toList());
}
public void addUnstableTag(long versionId) {

View File

@ -187,7 +187,7 @@ public class VersionService extends HangarService {
} else {
path = null;
}
dependencies.get(pvdt.getPlatform()).put(new PluginDependency(pvdt.getName(), pvdt.isRequired(), pvdt.getProjectId(), pvdt.getExternalUrl()), path);
// dependencies.get(pvdt.getPlatform()).put(new PluginDependency(pvdt.getName(), pvdt.isRequired(), pvdt.getProjectId(), pvdt.getExternalUrl()), path);
});
if (true) throw new NotImplementedException();
return new VersionData(