whole bunch of random stuff

This commit is contained in:
Jake Potrebic 2021-04-09 17:19:16 -07:00
parent 1964e5a470
commit 0b58c92390
No known key found for this signature in database
GPG Key ID: 7C58557EC9C421F8
16 changed files with 94 additions and 96 deletions

View File

@ -29,13 +29,13 @@
<template #activator="{ on }">
<v-btn icon to="/authors" nuxt class="mr-1" v-on="on"><v-icon>mdi-account-group</v-icon></v-btn>
</template>
<span>{{ $t('pages.authors') }}</span>
<span>{{ $t('pages.authorsTitle') }}</span>
</v-tooltip>
<v-tooltip bottom>
<template #activator="{ on }">
<v-btn icon to="/staff" nuxt class="mr-1" v-on="on"><v-icon>mdi-account-tie</v-icon></v-btn>
</template>
<span>{{ $t('pages.staff') }}</span>
<span>{{ $t('pages.staffTitle') }}</span>
</v-tooltip>
<v-menu v-if="isLoggedIn" bottom offset-y transition="slide-y-transition" close-delay="100">

View File

@ -38,8 +38,14 @@ const msgs: LocaleMessageObject = {
sponsoredBy: 'Sponsored by',
},
pages: {
authors: 'Authors',
staff: 'Staff',
staffTitle: 'Staff',
authorsTitle: 'Authors',
headers: {
username: 'Username',
roles: 'Roles',
joined: 'Joined',
projects: 'Projects',
},
},
nav: {
login: 'Login',

View File

@ -24,11 +24,11 @@
</v-btn>
</v-card-title>
<v-card-text>
<v-tabs v-model="selectedTab" vertical>
<v-tab href="#general">{{ $t('project.settings.tabs.general') }}</v-tab>
<v-tab href="#optional">{{ $t('project.settings.tabs.optional') }}</v-tab>
<v-tab href="#management">{{ $t('project.settings.tabs.management') }}</v-tab>
<v-tab href="#donation">{{ $t('project.settings.tabs.donation') }}</v-tab>
<v-tabs vertical>
<v-tab to="#general" replace nuxt>{{ $t('project.settings.tabs.general') }}</v-tab>
<v-tab to="#optional" replace nuxt>{{ $t('project.settings.tabs.optional') }}</v-tab>
<v-tab to="#management" replace nuxt>{{ $t('project.settings.tabs.management') }}</v-tab>
<v-tab to="#donation" replace nuxt>{{ $t('project.settings.tabs.donation') }}</v-tab>
<v-tab-item id="general">
<v-form v-model="validForm.settings">
@ -132,6 +132,7 @@
:rules="[$util.$vc.maxLength(validations.project.keywords.max)]"
:delimiters="[' ', ',', '.']"
:label="$t('project.new.step3.keywords')"
append-icon=""
prepend-inner-icon="mdi-file-word-box"
/>
</div>
@ -420,20 +421,12 @@ export default class ProjectManagePage extends HangarProjectMixin {
rename: false,
};
selectedTab: string = '';
@Watch('$route.hash')
onRouteTabChange(newVal: string) {
this.selectedTab = newVal;
}
@Watch('selectedTab')
onSelectedTabChange(newVal: string) {
history.pushState({}, '', this.$route.path + '#' + newVal);
}
mounted() {
this.selectedTab = this.$route.hash.substr(1) || 'general';
if (!this.$route.hash) {
this.$router.replace({
hash: '#general',
});
}
}
get settingsEqual() {
@ -597,15 +590,12 @@ export default class ProjectManagePage extends HangarProjectMixin {
}
}
</script>
<style lang="scss">
.settings-card {
.v-text-field .v-text-field__details {
margin-bottom: 0;
}
}
</style>
<style lang="scss" scoped>
@import '~vuetify/src/styles/styles';
.settings-card .v-text-field::v-deep .v-text-field__details {
margin-bottom: 0;
}
hr {
margin-top: 6px;
margin-bottom: 5px;
@ -629,7 +619,7 @@ h2 {
.theme--dark {
.sticky {
background-color: #1e1e1e;
background-color: map-get($material-dark, 'cards');
}
}

View File

@ -4,10 +4,6 @@
<ProjectList :projects="projects" />
</v-col>
<v-col cols="12" md="4">
<!-- TODO project manager (for organizations) (so what this is, is accepting invites to other projects AS the organization, I don't think we really need to have that. You couldn't be able to invite organizations to other projects/organizations) -->
<v-card v-if="user.isOrganization && $perms.canEditSubjectSettings">
<v-card-title>Project Manager</v-card-title>
</v-card>
<template v-if="!user.isOrganization">
<v-card>
<v-card-title>{{ $t('author.orgs') }}</v-card-title>

View File

@ -37,18 +37,17 @@ import { UserListPage } from '~/components/mixins';
components: { UserAvatar },
})
export default class AuthorsPage extends UserListPage {
// TODO i18n for headers
headers: DataTableHeader[] = [
{ text: '', value: 'pic', sortable: false },
{ text: 'Username', value: 'username' },
{ text: 'Roles', value: 'roles', sortable: false },
{ text: 'Joined', value: 'joinDate' },
{ text: 'Projects', value: 'projectCount' },
{ text: this.$t('pages.headers.username') as string, value: 'username' },
{ text: this.$t('pages.headers.roles') as string, value: 'roles', sortable: false },
{ text: this.$t('pages.headers.joined') as string, value: 'joinDate' },
{ text: this.$t('pages.headers.projects') as string, value: 'projectCount' },
];
head() {
return {
title: this.$t('pages.authors'),
title: this.$t('pages.authorsTitle'),
};
}

View File

@ -49,7 +49,6 @@
/>
</v-col>
<v-col cols="12" md="6">
<!-- todo custom rule to check if a name exist already -->
<v-text-field
v-model.trim="form.name"
autofocus
@ -203,7 +202,6 @@
</v-container>
</v-card>
</StepperStepContent>
<!-- TODO donation settings as a step as well -->
<StepperStepContent
:step="4"
@back="step = 3"
@ -273,6 +271,7 @@ export default class NewProjectPage extends HangarComponent {
projectLoading = true;
projectError = false;
projectOwners!: ProjectOwner[];
licences!: string[];
error = null as string | null;
form: NewProjectForm = {
category: ProjectCategory.ADMIN_TOOLS,
@ -305,14 +304,14 @@ export default class NewProjectPage extends HangarComponent {
return this.step !== 2 || this.forms.step2;
}
// TODO do we want to get those from the server? Jake: I think so, it'd be nice to admins to be able to configure default licenses, but not needed for MVP
get licences() {
return ['MIT', 'Apache 2.0', 'GPL', 'LGPL', '(custom)'];
}
async asyncData({ $api }: Context) {
async asyncData({ $api, $util }: Context) {
const data = await Promise.all([$api.requestInternal('data/possibleOwners'), $api.requestInternal('data/licenses', false)]).catch(
$util.handlePageRequestError
);
if (typeof data === 'undefined') return;
return {
projectOwners: await $api.requestInternal<ProjectOwner[]>('projects/possibleOwners'),
licenses: data[0],
projectOwners: data[1],
};
}
@ -321,7 +320,6 @@ export default class NewProjectPage extends HangarComponent {
}
createProject() {
console.log(this.form);
this.$api
.requestInternal<string>('projects/create', true, 'post', this.form)
.then((url) => {
@ -342,7 +340,6 @@ export default class NewProjectPage extends HangarComponent {
this.projectError = false;
}
// This is very useful. Prob should have a generalization of this that works elsewhere. I didn't make it a rule because it relies on other input (the ownerId)
@Watch('form.name')
onProjectNameChange(val: string) {
if (!val) {

View File

@ -3,33 +3,39 @@
<v-card>
<v-card-title v-text="$t('organization.new.title')" />
<v-card-subtitle>{{ $t('organization.new.text') }}</v-card-subtitle>
<!--TODO error message if already at max orgs-->
<v-card-text>
<v-form v-model="validForm">
<v-text-field
v-model="form.name"
class="mt-2"
filled
:loading="validateLoading"
:label="$t('organization.new.name')"
:rules="[
$util.$vc.require($t('organization.new.name')),
$util.$vc.regex($t('organization.new.name'), validations.org.regex),
$util.$vc.minLength(validations.org.min),
$util.$vc.maxLength(validations.org.max),
]"
:error-messages="nameErrorMessages"
/>
<v-divider />
<MemberList ref="memberList" class="mt-7 elevation-5" no-save-btn :roles="roles" always-editing :search-filter="searchFilter" />
</v-form>
<template v-if="currentUser.headerData.organizationCount < 1">
<v-card-text>
<v-form v-model="validForm">
<v-text-field
v-model="form.name"
class="mt-2"
filled
:loading="validateLoading"
:label="$t('organization.new.name')"
:rules="[
$util.$vc.require($t('organization.new.name')),
$util.$vc.regex($t('organization.new.name'), validations.org.regex),
$util.$vc.minLength(validations.org.min),
$util.$vc.maxLength(validations.org.max),
]"
:error-messages="nameErrorMessages"
/>
<v-divider />
<MemberList ref="memberList" class="mt-7 elevation-5" no-save-btn :roles="roles" always-editing :search-filter="searchFilter" />
</v-form>
</v-card-text>
<v-card-actions class="justify-end">
<v-btn color="success" :disabled="!canCreate" :loading="loading" @click="create">
<v-icon left>mdi-check</v-icon>
{{ $t('form.memberList.create') }}
</v-btn>
</v-card-actions>
</template>
<v-card-text v-else>
<v-alert type="warning">
{{ $t('organization.new.error.tooManyOrgs', [validations.maxOrgCount]) }}
</v-alert>
</v-card-text>
<v-card-actions class="justify-end">
<v-btn color="success" :disabled="!canCreate" :loading="loading" @click="create">
<v-icon left>mdi-check</v-icon>
{{ $t('form.memberList.create') }}
</v-btn>
</v-card-actions>
</v-card>
</v-col>
</template>

View File

@ -37,17 +37,16 @@ import { UserListPage } from '~/components/mixins';
components: { UserAvatar },
})
export default class StaffPage extends UserListPage {
// TODO i18n for headers
headers: DataTableHeader[] = [
{ text: '', value: 'pic', sortable: false },
{ text: 'Username', value: 'username' },
{ text: 'Roles', value: 'roles', sortable: false },
{ text: 'Joined', value: 'joinDate' },
{ text: this.$t('pages.headers.username') as string, value: 'username' },
{ text: this.$t('pages.headers.roles') as string, value: 'roles', sortable: false },
{ text: this.$t('pages.headers.joined') as string, value: 'joinDate' },
];
head() {
return {
title: this.$t('pages.staff'),
title: this.$t('pages.staffTitle'),
};
}

View File

@ -29,6 +29,7 @@ public interface ActivityDAO {
" FROM project_version_platform_dependencies pvpd " +
" JOIN platform_versions plv ON pvpd.platform_version_id = plv.id" +
" WHERE pv.id = pvpd.version_id" +
" ORDER BY plv.platform" +
" ) platforms" +
" FROM project_version_reviews pvr" +
" JOIN project_versions pv ON pvr.version_id = pv.id" +

View File

@ -66,7 +66,7 @@ public interface ProjectVersionsDAO {
@SingleValue
@UseEnumStrategy(EnumStrategy.BY_ORDINAL)
@SqlQuery("SELECT array_agg(DISTINCT plv.platform)" +
@SqlQuery("SELECT array_agg(DISTINCT plv.platform ORDER BY plv.platform)" +
" FROM project_versions pv" +
" JOIN project_version_platform_dependencies pvpd ON pv.id = pvpd.version_id" +
" JOIN platform_versions plv ON pvpd.platform_version_id = plv.id" +

View File

@ -3,14 +3,15 @@ package io.papermc.hangar.db.dao.internal.table.versions;
import io.papermc.hangar.model.common.Platform;
import io.papermc.hangar.model.db.versions.RecommendedProjectVersionTable;
import org.jdbi.v3.core.enums.EnumByOrdinal;
import org.jdbi.v3.sqlobject.config.KeyColumn;
import org.jdbi.v3.sqlobject.config.ValueColumn;
import org.jdbi.v3.sqlobject.customizer.BindBean;
import org.jdbi.v3.sqlobject.customizer.Timestamped;
import org.jdbi.v3.sqlobject.statement.SqlQuery;
import org.jdbi.v3.sqlobject.statement.SqlUpdate;
import org.springframework.stereotype.Repository;
import org.apache.commons.lang3.tuple.Pair;
import java.util.List;
import java.util.Map;
@Repository
public interface RecommendedProjectVersionsDAO {
@ -22,6 +23,8 @@ public interface RecommendedProjectVersionsDAO {
@SqlUpdate("DELETE FROM recommended_project_versions WHERE project_id = :projectId AND platform = :platform")
void delete(long projectId, @EnumByOrdinal Platform platform);
@SqlQuery("SELECT platform, version_id FROM recommended_project_versions WHERE project_id = :projectId")
List<Pair<Long, Long>> getRecommendedVersions(long projectId);
@KeyColumn("platform")
@ValueColumn("version_id")
@SqlQuery("SELECT platform, version_id FROM recommended_project_versions WHERE project_id = :projectId ORDER BY platform")
Map<Platform, Long> getRecommendedVersions(long projectId);
}

View File

@ -60,6 +60,7 @@ public interface HangarReviewsDAO {
" FROM project_version_platform_dependencies pvpd " +
" JOIN platform_versions plv ON pvpd.platform_version_id = plv.id" +
" WHERE pv.id = pvpd.version_id" +
" ORDER BY plv.platform" +
" ) platforms," +
" pv.created_at version_created_at," +
" coalesce(pvu.name, 'DELETED USER') version_author," +

View File

@ -29,7 +29,7 @@ public interface HangarVersionsDAO {
" pv.external_url," +
" u.name author," +
" pv.review_state," +
" array(SELECT DISTINCT rpv.platform FROM recommended_project_versions rpv WHERE rpv.version_id = pv.id) as recommended," +
" array(SELECT DISTINCT rpv.platform FROM recommended_project_versions rpv WHERE rpv.version_id = pv.id ORDER BY rpv.platform) as recommended," +
" ru.name approved_by" +
" FROM project_versions pv" +
" JOIN projects p ON pv.project_id = p.id" +
@ -60,7 +60,7 @@ public interface HangarVersionsDAO {
" pv.external_url," +
" u.name author," +
" pv.review_state," +
" array(SELECT DISTINCT rpv.platform FROM recommended_project_versions rpv WHERE rpv.version_id = pv.id) as recommended," +
" array(SELECT DISTINCT rpv.platform FROM recommended_project_versions rpv WHERE rpv.version_id = pv.id ORDER BY rpv.platform) as recommended," +
" ru.name approved_by" +
" FROM project_versions pv" +
" JOIN projects p ON pv.project_id = p.id" +

View File

@ -46,7 +46,7 @@ public interface VersionsApiDAO {
" pv.external_url," +
" u.name author," +
" pv.review_state," +
" array(SELECT DISTINCT rpv.platform FROM recommended_project_versions rpv WHERE rpv.version_id = pv.id) as recommended" +
" array(SELECT DISTINCT rpv.platform FROM recommended_project_versions rpv WHERE rpv.version_id = pv.id ORDER BY rpv.platform) 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" +
@ -76,7 +76,7 @@ public interface VersionsApiDAO {
" pv.external_url," +
" u.name author," +
" pv.review_state," +
" array(SELECT DISTINCT rpv.platform FROM recommended_project_versions rpv WHERE rpv.version_id = pv.id) as recommended" +
" array(SELECT DISTINCT rpv.platform FROM recommended_project_versions rpv WHERE rpv.version_id = pv.id ORDER BY rpv.platform) 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" +
@ -108,7 +108,7 @@ public interface VersionsApiDAO {
" pv.external_url," +
" u.name author," +
" pv.review_state," +
" array(SELECT DISTINCT rpv.platform FROM recommended_project_versions rpv WHERE rpv.version_id = pv.id) as recommended" +
" array(SELECT DISTINCT rpv.platform FROM recommended_project_versions rpv WHERE rpv.version_id = pv.id ORDER BY rpv.platform) as recommended" +
" FROM project_versions pv" +
" JOIN projects p ON pv.project_id = p.id" +
" JOIN project_channels pc ON pv.channel_id = pc.id" +

View File

@ -12,6 +12,7 @@ import java.util.stream.Collectors;
@EnumByOrdinal
public enum Platform {
// NOTE: The order here should always be the order they are displayed whenever there is a list somewhere on the frontend
PAPER("Paper", Category.SERVER, TagColor.PAPER, "https://papermc.io/downloads"),
WATERFALL("Waterfall", Category.PROXY, TagColor.WATERFALL, "https://papermc.io/downloads#Waterfall"),
VELOCITY("Velocity", Category.PROXY, TagColor.VELOCITY, "https://www.velocitypowered.com/downloads");

View File

@ -5,11 +5,10 @@ import io.papermc.hangar.db.dao.HangarDao;
import io.papermc.hangar.db.dao.internal.table.versions.RecommendedProjectVersionsDAO;
import io.papermc.hangar.model.common.Platform;
import io.papermc.hangar.model.db.versions.RecommendedProjectVersionTable;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.stream.Collectors;
@Service
public class RecommendedVersionService extends HangarComponent {
@ -27,6 +26,6 @@ public class RecommendedVersionService extends HangarComponent {
}
public Map<Platform, Long> getRecommendedVersions(long projectId) {
return recommendedProjectVersionsDAO.getRecommendedVersions(projectId).stream().collect(Collectors.toMap(pair -> Platform.values()[pair.getKey().intValue()], Pair::getValue));
return recommendedProjectVersionsDAO.getRecommendedVersions(projectId);
}
}