mirror of
https://github.com/HangarMC/Hangar.git
synced 2025-01-06 13:56:14 +08:00
switched versions table to vue
This commit is contained in:
parent
bb1a5b0fb9
commit
5bf2d594c7
@ -14,10 +14,12 @@
|
||||
"@fortawesome/free-brands-svg-icons": "5.14.0",
|
||||
"@fortawesome/free-regular-svg-icons": "5.14.0",
|
||||
"@fortawesome/free-solid-svg-icons": "5.14.0",
|
||||
"axios": "^0.20.0",
|
||||
"jquery": "3.5.1",
|
||||
"lodash": "4.17.20",
|
||||
"query-string": "6.13.1",
|
||||
"vue": "2.6.11"
|
||||
"vue": "2.6.11",
|
||||
"vuetable-2": "^2.0.0-beta.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.11.1",
|
||||
|
141
src/main/frontend/src/PlatformVersionTable.vue
Normal file
141
src/main/frontend/src/PlatformVersionTable.vue
Normal file
@ -0,0 +1,141 @@
|
||||
<template>
|
||||
<div>
|
||||
<vuetable ref="platform-table" :api-mode="false" :data="data" :fields="fields" class="platform-versions">
|
||||
<div slot="versions-slot" slot-scope="props">
|
||||
<div class="platform-version" v-for="v in props.rowData.versions">
|
||||
<span @click="removeVersion(props.rowData.platform, v)" style="cursor:pointer;">
|
||||
<i class="fas fa-times" style="color: #bb0400"></i>
|
||||
</span>
|
||||
{{ v }}
|
||||
</div>
|
||||
</div>
|
||||
<div slot="actions-slot" slot-scope="props">
|
||||
<div class="form-group form-inline">
|
||||
<label for="add-version-input" class="sr-only">Add Version</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">Version Identifier</div>
|
||||
<input type="text" id="add-version-input" class="form-control" v-model="inputs[props.rowData.platform]">
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-primary" @click="addVersion(props.rowData.platform)" :disabled="!inputs[props.rowData.platform]">
|
||||
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
|
||||
</button>
|
||||
</div>
|
||||
</vuetable>
|
||||
<button v-if="!loading" type="button" class="btn btn-success" @click="save" :disabled="!changesMade">
|
||||
<span class="glyphicon glyphicon-floppy-disk"></span>
|
||||
Save Changes
|
||||
</button>
|
||||
<div v-else>
|
||||
<i class="fas fa-spinner fa-spin"></i>
|
||||
<span>Loading projects for you...</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import _ from 'lodash'
|
||||
import axios from 'axios'
|
||||
import Vuetable from 'vuetable-2'
|
||||
|
||||
export default {
|
||||
name: 'PlatformVersionTable',
|
||||
components: {
|
||||
Vuetable
|
||||
},
|
||||
props: {
|
||||
platforms: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
changesMade: false,
|
||||
data: [],
|
||||
inputs: {},
|
||||
fields: [
|
||||
{
|
||||
name: 'platform',
|
||||
width: '40px',
|
||||
formatter(value) {
|
||||
return value.charAt(0).toUpperCase() + value.slice(1)
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'versions-slot',
|
||||
title: '<i class="fas fa-tags"></i> Versions'
|
||||
},
|
||||
{
|
||||
name: 'actions-slot',
|
||||
title: '<i class="fas fa-plus"></i> Add Version'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
addVersion(platform) {
|
||||
const versions = this.data.find(o => o.platform === platform).versions
|
||||
if (versions.indexOf(this.inputs[platform]) < 0) {
|
||||
versions.push(this.inputs[platform])
|
||||
this.changesMade = true
|
||||
}
|
||||
this.inputs[platform] = ''
|
||||
},
|
||||
removeVersion(platform, version) {
|
||||
const versions = this.data.find(o => o.platform === platform).versions
|
||||
this.$delete(versions, versions.indexOf(version))
|
||||
this.changesMade = true
|
||||
},
|
||||
save() {
|
||||
const additions = {}
|
||||
const removals = {}
|
||||
for (const platform in this.platforms) {
|
||||
const versions = this.data.find(o => o.platform === platform.toLowerCase()).versions
|
||||
additions[platform] = _.difference(versions, this.platforms[platform])
|
||||
removals[platform] = _.difference(this.platforms[platform], versions)
|
||||
}
|
||||
let hasChanges = false
|
||||
for (const platform in this.platforms) {
|
||||
if (additions[platform].length > 0 || removals[platform].length > 0) {
|
||||
hasChanges = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!hasChanges) { // NO actual changes
|
||||
return
|
||||
}
|
||||
this.loading = true
|
||||
axios.post("/admin/versions/", {
|
||||
additions,
|
||||
removals
|
||||
}).then(() => {
|
||||
this.changesMade = false
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
for (const platform in this.platforms) {
|
||||
this.inputs[platform] = ''
|
||||
this.data.push({
|
||||
platform: platform.toLowerCase(),
|
||||
versions: [...this.platforms[platform]]
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.platform-versions {
|
||||
display: inherit;
|
||||
}
|
||||
.platform-version {
|
||||
display: inline-block;
|
||||
padding: 1px 4px 0 4px;
|
||||
margin-right: 5px;
|
||||
background-color: #cdcdcd;
|
||||
border-radius: 2px;
|
||||
}
|
||||
</style>
|
15
src/main/frontend/src/entries/platform-version-table.js
Normal file
15
src/main/frontend/src/entries/platform-version-table.js
Normal file
@ -0,0 +1,15 @@
|
||||
import Vue from 'vue'
|
||||
import axios from 'axios'
|
||||
|
||||
import PlatformVersionTable from '../PlatformVersionTable.vue'
|
||||
|
||||
axios.defaults.headers.post[window.csrfInfo.headerName] = window.csrfInfo.token;
|
||||
|
||||
const app = new Vue({
|
||||
el: '#platform-version-table',
|
||||
render: createElement => createElement(PlatformVersionTable, {
|
||||
props: {
|
||||
platforms: PLATFORMS
|
||||
}
|
||||
})
|
||||
});
|
@ -5,19 +5,22 @@ const CopyPlugin = require('copy-webpack-plugin');
|
||||
//const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
|
||||
|
||||
const Path = require('path');
|
||||
const fs = require('fs');
|
||||
const sourceDir = Path.resolve(__dirname, 'src');
|
||||
const entryDir = Path.resolve(sourceDir, 'entries');
|
||||
const modulesDir = Path.resolve(__dirname, 'node_modules');
|
||||
const outputDir = Path.resolve(__dirname, '..', '..', '..', 'target', 'classes', 'public', 'build');
|
||||
const javascriptDir = Path.resolve(__dirname, '..', '..', '..', 'target', 'classes', 'public', 'javascripts');
|
||||
|
||||
const entries = {}
|
||||
for (const file of fs.readdirSync(entryDir)) {
|
||||
entries[file.replace('.js', "")] = Path.resolve(entryDir, file);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
main: Path.resolve(sourceDir, 'scss', 'main.scss'),
|
||||
home: Path.resolve(entryDir, 'home.js'),
|
||||
'font-awesome': Path.resolve(entryDir, 'font-awesome.js'),
|
||||
'user-profile': Path.resolve(entryDir, 'user-profile.js'),
|
||||
'version-list': Path.resolve(entryDir, 'version-list.js'),
|
||||
...entries
|
||||
},
|
||||
output: {
|
||||
path: outputDir,
|
||||
|
@ -1397,6 +1397,20 @@ aws4@^1.8.0:
|
||||
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.0.tgz#a17b3a8ea811060e74d47d306122400ad4497ae2"
|
||||
integrity sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==
|
||||
|
||||
axios@^0.15.3:
|
||||
version "0.15.3"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.15.3.tgz#2c9d638b2e191a08ea1d6cc988eadd6ba5bdc053"
|
||||
integrity sha1-LJ1jiy4ZGgjqHWzJiOrda6W9wFM=
|
||||
dependencies:
|
||||
follow-redirects "1.0.0"
|
||||
|
||||
axios@^0.20.0:
|
||||
version "0.20.0"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.20.0.tgz#057ba30f04884694993a8cd07fa394cff11c50bd"
|
||||
integrity sha512-ANA4rr2BDcmmAQLOKft2fufrtuvlqR+cXNNinUmvfeSNCOF98PZL+7M/v1zIdGo7OLjEA9J2gXJL+j4zGsl0bA==
|
||||
dependencies:
|
||||
follow-redirects "^1.10.0"
|
||||
|
||||
babel-loader@8.1.0:
|
||||
version "8.1.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.1.0.tgz#c611d5112bd5209abe8b9fa84c3e4da25275f1c3"
|
||||
@ -2915,6 +2929,18 @@ flush-write-stream@^1.0.0:
|
||||
inherits "^2.0.3"
|
||||
readable-stream "^2.3.6"
|
||||
|
||||
follow-redirects@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.0.0.tgz#8e34298cbd2e176f254effec75a1c78cc849fd37"
|
||||
integrity sha1-jjQpjL0uF28lTv/sdaHHjMhJ/Tc=
|
||||
dependencies:
|
||||
debug "^2.2.0"
|
||||
|
||||
follow-redirects@^1.10.0:
|
||||
version "1.13.0"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db"
|
||||
integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==
|
||||
|
||||
for-in@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
|
||||
@ -6590,6 +6616,13 @@ vue@2.6.11:
|
||||
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.11.tgz#76594d877d4b12234406e84e35275c6d514125c5"
|
||||
integrity sha512-VfPwgcGABbGAue9+sfrD4PuwFar7gPb1yl1UK1MwXoQPAw0BKSqWfoYCT/ThFrdEVWoI51dBuyCoiNU9bZDZxQ==
|
||||
|
||||
vuetable-2@^2.0.0-beta.4:
|
||||
version "2.0.0-beta.4"
|
||||
resolved "https://registry.yarnpkg.com/vuetable-2/-/vuetable-2-2.0.0-beta.4.tgz#474a28dfbf9372e88b34b0659f4b524bc19aa676"
|
||||
integrity sha512-sWSdKIPYiATI9hOuPlQ09iSWEFAfhe6sPovl4hK2SemvqvgxLIF8UjG3LwJJC7idWS9UPpK9fRrSXoFJhRcluQ==
|
||||
dependencies:
|
||||
axios "^0.15.3"
|
||||
|
||||
watchpack-chokidar2@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz#9948a1866cbbd6cb824dea13a7ed691f6c8ddff0"
|
||||
|
@ -1,5 +1,7 @@
|
||||
package io.papermc.hangar.controller;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import io.papermc.hangar.controller.util.StatusZ;
|
||||
import io.papermc.hangar.db.customtypes.LoggedActionType;
|
||||
@ -30,7 +32,6 @@ import io.papermc.hangar.service.VersionService;
|
||||
import io.papermc.hangar.service.project.FlagService;
|
||||
import io.papermc.hangar.service.project.ProjectService;
|
||||
import io.papermc.hangar.util.AlertUtil;
|
||||
import io.papermc.hangar.util.Routes;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
@ -43,6 +44,7 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
@ -72,11 +74,12 @@ public class ApplicationController extends HangarController {
|
||||
private final SitemapService sitemapService;
|
||||
private final StatsService statsService;
|
||||
private final StatusZ statusZ;
|
||||
private final ObjectMapper mapper;
|
||||
|
||||
private final HttpServletRequest request;
|
||||
|
||||
@Autowired
|
||||
public ApplicationController(HangarDao<PlatformVersionsDao> platformVersionsDao, UserService userService, ProjectService projectService, OrgService orgService, VersionService versionService, FlagService flagService, UserActionLogService userActionLogService, JobService jobService, SitemapService sitemapService, StatsService statsService, StatusZ statusZ, HttpServletRequest request) {
|
||||
public ApplicationController(HangarDao<PlatformVersionsDao> platformVersionsDao, UserService userService, ProjectService projectService, OrgService orgService, VersionService versionService, FlagService flagService, UserActionLogService userActionLogService, JobService jobService, SitemapService sitemapService, StatsService statsService, StatusZ statusZ, ObjectMapper mapper, HttpServletRequest request) {
|
||||
this.platformVersionsDao = platformVersionsDao;
|
||||
this.userService = userService;
|
||||
this.projectService = projectService;
|
||||
@ -87,6 +90,7 @@ public class ApplicationController extends HangarController {
|
||||
this.jobService = jobService;
|
||||
this.sitemapService = sitemapService;
|
||||
this.statusZ = statusZ;
|
||||
this.mapper = mapper;
|
||||
this.request = request;
|
||||
this.statsService = statsService;
|
||||
}
|
||||
@ -245,21 +249,31 @@ public class ApplicationController extends HangarController {
|
||||
for (Platform p : Platform.getValues()) {
|
||||
versions.putIfAbsent(p, new ArrayList<>());
|
||||
}
|
||||
mav.addObject("platformVersions", versions);
|
||||
mav.addObject("platformVersions", mapper.valueToTree(versions));
|
||||
return fillModel(mav);
|
||||
}
|
||||
|
||||
// @SuppressWarnings("unchecked")
|
||||
@GlobalPermission(NamedPermission.MANUAL_VALUE_CHANGES)
|
||||
@Secured("ROLE_USER")
|
||||
@PostMapping("/admin/versions/{platform}")
|
||||
public ModelAndView updatePlatformVersions(@PathVariable Platform platform, @RequestParam(required = false) List<String> versions, @RequestParam(required = false) List<String> removedVersions) {
|
||||
if (versions != null) {
|
||||
platformVersionsDao.get().insert(versions.stream().map(s -> new PlatformVersionsTable(platform, s)).collect(Collectors.toList()));
|
||||
@PostMapping("/admin/versions/")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public void updatePlatformVersions(@RequestBody ObjectNode object) {
|
||||
Map<String, List<String>> additions;
|
||||
Map<String, List<String>> removals;
|
||||
try {
|
||||
additions = mapper.treeToValue(object.get("additions"), (Class<Map<String,List<String>>>)(Class)Map.class);
|
||||
removals = mapper.treeToValue(object.get("removals"), (Class<Map<String,List<String>>>)(Class)Map.class);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Bad formatting", e);
|
||||
}
|
||||
if (removedVersions != null) {
|
||||
platformVersionsDao.get().delete(removedVersions, platform.ordinal());
|
||||
if (additions == null || removals == null) {
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Bad formatting");
|
||||
}
|
||||
return Routes.SHOW_PLATFORM_VERSIONS.getRedirect();
|
||||
additions.forEach((platform, versions) -> {
|
||||
platformVersionsDao.get().insert(versions.stream().map(v -> new PlatformVersionsTable(Platform.valueOf(platform), v)).collect(Collectors.toList()));
|
||||
});
|
||||
removals.forEach((platform, versions) -> platformVersionsDao.get().delete(versions, Platform.valueOf(platform).ordinal()));
|
||||
}
|
||||
|
||||
@GlobalPermission(NamedPermission.EDIT_ALL_USER_SETTINGS)
|
||||
|
@ -98,6 +98,10 @@ showFooter: Boolean = true, noContainer: Boolean = false, additionalMeta: Html =
|
||||
<#if _csrf?? && _csrf.token??>
|
||||
<script>
|
||||
window.csrf = '${_csrf.token}';
|
||||
window.csrfInfo = {
|
||||
'headerName': '${_csrf.headerName}',
|
||||
'token': '${_csrf.token}'
|
||||
};
|
||||
window.ajaxSettings = {"headers": { '${_csrf.headerName}': window.csrf}};
|
||||
window.isLoggedIn = ${headerData.hasUser()?c};
|
||||
$.ajaxSetup(window.ajaxSettings);
|
||||
|
@ -5,14 +5,20 @@
|
||||
<#import "*/layout/base.ftlh" as base />
|
||||
|
||||
<#assign scriptsVar>
|
||||
<link rel="stylesheet" href="<@hangar.url "build/platform-version-table.css" />">
|
||||
<script type="text/javascript" src="<@hangar.url "javascripts/platformVersions.js" />"></script>
|
||||
<script type="text/javascript" src="<@hangar.url "CSSescape/css.escape.js" />"></script>
|
||||
<script>
|
||||
PLATFORMS = ${platformVersions}
|
||||
</script>
|
||||
<script type="text/javascript" src="<@hangar.url "build/platform-version-table.js" />"></script>
|
||||
</#assign>
|
||||
|
||||
<#assign message><@spring.message "admin.platformVersions.title" /></#assign>
|
||||
<@base.base title="${message}" additionalScripts=scriptsVar>
|
||||
<#assign Platform=@helper["io.papermc.hangar.model.Platform"] />
|
||||
<#-- @ftlvariable name="Platform" type="io.papermc.hangar.model.Platform" -->
|
||||
<div id="platform-version-table"></div>
|
||||
<#--<#assign Platform=@helper["io.papermc.hangar.model.Platform"] />
|
||||
<#– @ftlvariable name="Platform" type="io.papermc.hangar.model.Platform" –>
|
||||
<#list platformVersions as platform, versions>
|
||||
<@form.form action="${Routes.UPDATE_PLATFORM_VERSIONS.getRouteUrl(platform.ordinal()?string)}" method="POST" id="${platform.getName()?lower_case}-form" class="form-inline">
|
||||
<@csrf.formField />
|
||||
@ -49,5 +55,5 @@
|
||||
</button>
|
||||
<div style="width: 80%; border-top: #555555 solid 1px; margin-top: 10px;"></div>
|
||||
</@form.form>
|
||||
</#list>
|
||||
</#list>-->
|
||||
</@base.base>
|
Loading…
Reference in New Issue
Block a user