Bläddra i källkod

chore: improved Vue folder structure

Signed-off-by: Jonathan <theflametrooper@gmail.com>
Jonathan 4 år sedan
förälder
incheckning
2ac517db96
68 ändrade filer med 810 tillägg och 808 borttagningar
  1. 1 1
      frontend/package.json
  2. 6 6
      frontend/src/App.vue
  3. 0 0
      frontend/src/api/admin/index.js
  4. 0 0
      frontend/src/api/admin/reports.js
  5. 96 96
      frontend/src/api/auth.js
  6. 0 0
      frontend/src/auth.js
  7. 0 0
      frontend/src/components/Modal.vue
  8. 1 1
      frontend/src/components/Sidebar.vue
  9. 1 1
      frontend/src/components/common/MobileAlert.vue
  10. 0 0
      frontend/src/components/common/UserIdToUsername.vue
  11. 1 1
      frontend/src/components/layout/MainFooter.vue
  12. 1 1
      frontend/src/components/layout/MainHeader.vue
  13. 3 3
      frontend/src/components/modals/CreatePlaylist.vue
  14. 3 3
      frontend/src/components/modals/EditPlaylist.vue
  15. 4 3
      frontend/src/components/modals/EditSong.vue
  16. 3 3
      frontend/src/components/modals/EditStation.vue
  17. 1 1
      frontend/src/components/modals/Login.vue
  18. 2 2
      frontend/src/components/modals/Register.vue
  19. 1 1
      frontend/src/components/modals/WhatIsNew.vue
  20. 2 2
      frontend/src/components/ui/PlaylistItem.vue
  21. 0 0
      frontend/src/io.js
  22. 0 0
      frontend/src/keyboardShortcuts.js
  23. 16 16
      frontend/src/main.js
  24. 1 1
      frontend/src/pages/404.vue
  25. 3 3
      frontend/src/pages/About.vue
  26. 2 2
      frontend/src/pages/Admin/EditNews.vue
  27. 2 2
      frontend/src/pages/Admin/EditUser.vue
  28. 3 3
      frontend/src/pages/Admin/IssuesModal.vue
  29. 2 2
      frontend/src/pages/Admin/ViewPunishment.vue
  30. 11 11
      frontend/src/pages/Admin/index.vue
  31. 2 2
      frontend/src/pages/Admin/tabs/NewStatistics.vue
  32. 3 3
      frontend/src/pages/Admin/tabs/News.vue
  33. 3 3
      frontend/src/pages/Admin/tabs/Punishments.vue
  34. 4 4
      frontend/src/pages/Admin/tabs/QueueSongs.vue
  35. 4 4
      frontend/src/pages/Admin/tabs/Reports.vue
  36. 4 4
      frontend/src/pages/Admin/tabs/Songs.vue
  37. 4 4
      frontend/src/pages/Admin/tabs/Stations.vue
  38. 2 2
      frontend/src/pages/Admin/tabs/Statistics.vue
  39. 3 3
      frontend/src/pages/Admin/tabs/Users.vue
  40. 1 1
      frontend/src/pages/Banned.vue
  41. 1 1
      frontend/src/pages/Home/CreateCommunityStation.vue
  42. 5 5
      frontend/src/pages/Home/index.vue
  43. 4 4
      frontend/src/pages/News.vue
  44. 2 2
      frontend/src/pages/Privacy.vue
  45. 7 7
      frontend/src/pages/Profile.vue
  46. 4 4
      frontend/src/pages/ResetPassword.vue
  47. 5 5
      frontend/src/pages/Settings.vue
  48. 2 2
      frontend/src/pages/Station/AddSongToPlaylist.vue
  49. 3 3
      frontend/src/pages/Station/AddSongToQueue.vue
  50. 2 2
      frontend/src/pages/Station/Report.vue
  51. 4 4
      frontend/src/pages/Station/SongsList.vue
  52. 1 1
      frontend/src/pages/Station/StationHeader.vue
  53. 1 1
      frontend/src/pages/Station/UsersList.vue
  54. 12 11
      frontend/src/pages/Station/index.vue
  55. 3 3
      frontend/src/pages/Team.vue
  56. 2 2
      frontend/src/pages/Terms.vue
  57. 0 0
      frontend/src/store/index.js
  58. 247 247
      frontend/src/store/modules/admin.js
  59. 0 0
      frontend/src/store/modules/modals.js
  60. 64 64
      frontend/src/store/modules/sidebars.js
  61. 0 0
      frontend/src/store/modules/station.js
  62. 242 242
      frontend/src/store/modules/user.js
  63. 0 0
      frontend/src/styles/colors.scss
  64. 0 0
      frontend/src/styles/global.scss
  65. 0 0
      frontend/src/validation.js
  66. 1 1
      frontend/webpack.common.js
  67. 1 1
      frontend/webpack.dev.js
  68. 1 1
      frontend/webpack.prod.js

+ 1 - 1
frontend/package.json

@@ -8,7 +8,7 @@
   "license": "GPL-3.0",
   "repository": "https://github.com/Musare/MusareNode",
   "scripts": {
-    "lint": "npx eslint . --ext .js,.vue",
+    "lint": "npx eslint src --ext .js,.vue",
     "bundle-analyse": "webpack --config webpack.prod.js --profile --json > bundle-stats.json && npx webpack-bundle-analyzer bundle-stats.json --mode static --report bundle-report.html --no-open",
     "dev": "webpack-dev-server --config webpack.dev.js",
     "prod": "webpack --config webpack.prod.js"

+ 6 - 6
frontend/App.vue → frontend/src/App.vue

@@ -15,11 +15,11 @@
 import { mapState, mapActions } from "vuex";
 import Toast from "toasters";
 
-import Banned from "./components/pages/Banned.vue";
-import WhatIsNew from "./components/Modals/WhatIsNew.vue";
-import MobileAlert from "./components/Modals/MobileAlert.vue";
-import LoginModal from "./components/Modals/Login.vue";
-import RegisterModal from "./components/Modals/Register.vue";
+import Banned from "./pages/Banned.vue";
+import WhatIsNew from "./components/modals/WhatIsNew.vue";
+import MobileAlert from "./components/common/MobileAlert.vue";
+import LoginModal from "./components/modals/Login.vue";
+import RegisterModal from "./components/modals/Register.vue";
 import io from "./io";
 import keyboardShortcuts from "./keyboardShortcuts";
 
@@ -177,7 +177,7 @@ export default {
 </script>
 
 <style lang="scss">
-@import "styles/global.scss";
+@import "./styles/global.scss";
 
 .night-mode {
 	div {

+ 0 - 0
frontend/api/admin/index.js → frontend/src/api/admin/index.js


+ 0 - 0
frontend/api/admin/reports.js → frontend/src/api/admin/reports.js


+ 96 - 96
frontend/api/auth.js → frontend/src/api/auth.js

@@ -1,96 +1,96 @@
-import Toast from "toasters";
-import io from "../io";
-
-// when Vuex needs to interact with socket.io
-
-export default {
-	register(user) {
-		return new Promise((resolve, reject) => {
-			const { username, email, password, recaptchaToken } = user;
-
-			io.getSocket(socket => {
-				socket.emit(
-					"users.register",
-					username,
-					email,
-					password,
-					recaptchaToken,
-					res => {
-						if (res.status === "success") {
-							if (res.SID) {
-								return lofig.get("cookie").then(cookie => {
-									const date = new Date();
-									date.setTime(
-										new Date().getTime() +
-											2 * 365 * 24 * 60 * 60 * 1000
-									);
-									const secure = cookie.secure
-										? "secure=true; "
-										: "";
-									document.cookie = `SID=${
-										res.SID
-									}; expires=${date.toGMTString()}; domain=${
-										cookie.domain
-									}; ${secure}path=/`;
-
-									return resolve({
-										status: "success",
-										message: "Account registered!"
-									});
-								});
-							}
-							return reject(new Error("You must login"));
-						}
-
-						return reject(new Error(res.message));
-					}
-				);
-			});
-		});
-	},
-	login(user) {
-		return new Promise((resolve, reject) => {
-			const { email, password } = user;
-
-			io.getSocket(socket => {
-				socket.emit("users.login", email, password, res => {
-					if (res.status === "success") {
-						return lofig.get("cookie").then(cookie => {
-							const date = new Date();
-							date.setTime(
-								new Date().getTime() +
-									2 * 365 * 24 * 60 * 60 * 1000
-							);
-							const secure = cookie.secure ? "secure=true; " : "";
-							let domain = "";
-							if (cookie.domain !== "localhost")
-								domain = ` domain=${cookie.domain};`;
-							document.cookie = `${cookie.SIDname}=${
-								res.SID
-							}; expires=${date.toGMTString()}; ${domain}${secure}path=/`;
-							return resolve({ status: "success" });
-						});
-					}
-
-					return reject(new Error(res.message));
-				});
-			});
-		});
-	},
-	logout() {
-		return new Promise((resolve, reject) => {
-			io.getSocket(socket => {
-				socket.emit("users.logout", res => {
-					if (res.status === "success") {
-						return lofig.get("cookie").then(cookie => {
-							document.cookie = `${cookie.SIDname}=;expires=Thu, 01 Jan 1970 00:00:01 GMT;`;
-							return window.location.reload();
-						});
-					}
-					new Toast({ content: res.message, timeout: 4000 });
-					return reject(new Error(res.message));
-				});
-			});
-		});
-	}
-};
+import Toast from "toasters";
+import io from "../io";
+
+// when Vuex needs to interact with socket.io
+
+export default {
+	register(user) {
+		return new Promise((resolve, reject) => {
+			const { username, email, password, recaptchaToken } = user;
+
+			io.getSocket(socket => {
+				socket.emit(
+					"users.register",
+					username,
+					email,
+					password,
+					recaptchaToken,
+					res => {
+						if (res.status === "success") {
+							if (res.SID) {
+								return lofig.get("cookie").then(cookie => {
+									const date = new Date();
+									date.setTime(
+										new Date().getTime() +
+											2 * 365 * 24 * 60 * 60 * 1000
+									);
+									const secure = cookie.secure
+										? "secure=true; "
+										: "";
+									document.cookie = `SID=${
+										res.SID
+									}; expires=${date.toGMTString()}; domain=${
+										cookie.domain
+									}; ${secure}path=/`;
+
+									return resolve({
+										status: "success",
+										message: "Account registered!"
+									});
+								});
+							}
+							return reject(new Error("You must login"));
+						}
+
+						return reject(new Error(res.message));
+					}
+				);
+			});
+		});
+	},
+	login(user) {
+		return new Promise((resolve, reject) => {
+			const { email, password } = user;
+
+			io.getSocket(socket => {
+				socket.emit("users.login", email, password, res => {
+					if (res.status === "success") {
+						return lofig.get("cookie").then(cookie => {
+							const date = new Date();
+							date.setTime(
+								new Date().getTime() +
+									2 * 365 * 24 * 60 * 60 * 1000
+							);
+							const secure = cookie.secure ? "secure=true; " : "";
+							let domain = "";
+							if (cookie.domain !== "localhost")
+								domain = ` domain=${cookie.domain};`;
+							document.cookie = `${cookie.SIDname}=${
+								res.SID
+							}; expires=${date.toGMTString()}; ${domain}${secure}path=/`;
+							return resolve({ status: "success" });
+						});
+					}
+
+					return reject(new Error(res.message));
+				});
+			});
+		});
+	},
+	logout() {
+		return new Promise((resolve, reject) => {
+			io.getSocket(socket => {
+				socket.emit("users.logout", res => {
+					if (res.status === "success") {
+						return lofig.get("cookie").then(cookie => {
+							document.cookie = `${cookie.SIDname}=;expires=Thu, 01 Jan 1970 00:00:01 GMT;`;
+							return window.location.reload();
+						});
+					}
+					new Toast({ content: res.message, timeout: 4000 });
+					return reject(new Error(res.message));
+				});
+			});
+		});
+	}
+};

+ 0 - 0
frontend/auth.js → frontend/src/auth.js


+ 0 - 0
frontend/components/Modals/Modal.vue → frontend/src/components/Modal.vue


+ 1 - 1
frontend/components/Sidebars/Sidebar.vue → frontend/src/components/Sidebar.vue

@@ -16,7 +16,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../styles/global.scss";
 
 .night-mode {
 	.sidebar {

+ 1 - 1
frontend/components/Modals/MobileAlert.vue → frontend/src/components/common/MobileAlert.vue

@@ -47,7 +47,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../styles/global.scss";
 
 @media (min-width: 735px) {
 	.modal {

+ 0 - 0
frontend/components/UserIdToUsername.vue → frontend/src/components/common/UserIdToUsername.vue


+ 1 - 1
frontend/components/MainFooter.vue → frontend/src/components/layout/MainFooter.vue

@@ -78,7 +78,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "./../../styles/global.scss";
 
 .night-mode {
 	footer.footer,

+ 1 - 1
frontend/components/MainHeader.vue → frontend/src/components/layout/MainHeader.vue

@@ -107,7 +107,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../styles/global.scss";
 
 .night-mode {
 	.nav-left,

+ 3 - 3
frontend/components/Modals/Playlists/Create.vue → frontend/src/components/modals/CreatePlaylist.vue

@@ -25,8 +25,8 @@ import { mapActions } from "vuex";
 
 import Toast from "toasters";
 import Modal from "../Modal.vue";
-import io from "../../../io";
-import validation from "../../../validation";
+import io from "../../io";
+import validation from "../../validation";
 
 export default {
 	components: { Modal },
@@ -82,7 +82,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../styles/global.scss";
 
 .menu {
 	padding: 0 20px;

+ 3 - 3
frontend/components/Modals/Playlists/Edit.vue → frontend/src/components/modals/EditPlaylist.vue

@@ -166,8 +166,8 @@ import { mapState, mapActions } from "vuex";
 
 import Toast from "toasters";
 import Modal from "../Modal.vue";
-import io from "../../../io";
-import validation from "../../../validation";
+import io from "../../io";
+import validation from "../../validation";
 import utils from "../../../js/utils";
 
 export default {
@@ -398,7 +398,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../styles/global.scss";
 
 .menu {
 	padding: 0 20px;

+ 4 - 3
frontend/components/Modals/EditSong.vue → frontend/src/components/modals/EditSong.vue

@@ -570,7 +570,7 @@ import Toast from "toasters";
 import io from "../../io";
 import keyboardShortcuts from "../../keyboardShortcuts";
 import validation from "../../validation";
-import Modal from "./Modal.vue";
+import Modal from "../Modal.vue";
 
 export default {
 	components: { Modal },
@@ -1496,7 +1496,7 @@ export default {
 </script>
 
 <style lang="scss">
-@import "styles/global.scss";
+@import "../../styles/global.scss";
 
 #genre-helper-container {
 	background-color: white;
@@ -1547,7 +1547,8 @@ export default {
 </style>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../styles/global.scss";
+
 .modal-card-body > div {
 	display: flex;
 	height: 100%;

+ 3 - 3
frontend/components/Modals/EditStation.vue → frontend/src/components/modals/EditStation.vue

@@ -394,8 +394,8 @@ import { mapState, mapActions } from "vuex";
 
 import Toast from "toasters";
 
-import PlaylistItem from "../PlaylistItem.vue";
-import Modal from "./Modal.vue";
+import PlaylistItem from "../ui/PlaylistItem.vue";
+import Modal from "../Modal.vue";
 
 import io from "../../io";
 import validation from "../../validation";
@@ -990,7 +990,7 @@ export default {
 </script>
 
 <style lang="scss">
-@import "styles/global.scss";
+@import "../../styles/global.scss";
 
 .night-mode {
 	.modal-card,

+ 1 - 1
frontend/components/Modals/Login.vue → frontend/src/components/modals/Login.vue

@@ -122,7 +122,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../styles/global.scss";
 
 .night-mode {
 	.modal-card,

+ 2 - 2
frontend/components/Modals/Register.vue → frontend/src/components/modals/Register.vue

@@ -258,7 +258,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../styles/global.scss";
 
 .night-mode {
 	.modal-card,
@@ -300,7 +300,7 @@ a {
 </style>
 
 <style lang="scss">
-@import "styles/global.scss";
+@import "../../styles/global.scss";
 
 .grecaptcha-badge {
 	z-index: 2000;

+ 1 - 1
frontend/components/Modals/WhatIsNew.vue → frontend/src/components/modals/WhatIsNew.vue

@@ -127,7 +127,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../styles/global.scss";
 
 .night-mode {
 	.modal-card,

+ 2 - 2
frontend/components/PlaylistItem.vue → frontend/src/components/ui/PlaylistItem.vue

@@ -15,7 +15,7 @@
 </template>
 
 <script>
-import utils from "../js/utils";
+import utils from "../../../js/utils";
 
 export default {
 	props: {
@@ -39,7 +39,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../styles/global.scss";
 
 .playlist {
 	width: 100%;

+ 0 - 0
frontend/io.js → frontend/src/io.js


+ 0 - 0
frontend/keyboardShortcuts.js → frontend/src/keyboardShortcuts.js


+ 16 - 16
frontend/main.js → frontend/src/main.js

@@ -53,70 +53,70 @@ const router = new VueRouter({
 	routes: [
 		{
 			path: "/",
-			component: () => import("./components/pages/Home.vue")
+			component: () => import("./pages/Home/index.vue")
 		},
 		{
 			path: "*",
-			component: () => import("./components/404.vue")
+			component: () => import("./pages/404.vue")
 		},
 		{
 			path: "/404",
-			component: () => import("./components/404.vue")
+			component: () => import("./pages/404.vue")
 		},
 		{
 			path: "/terms",
-			component: () => import("./components/pages/Terms.vue")
+			component: () => import("./pages/Terms.vue")
 		},
 		{
 			path: "/privacy",
-			component: () => import("./components/pages/Privacy.vue")
+			component: () => import("./pages/Privacy.vue")
 		},
 		{
 			path: "/team",
-			component: () => import("./components/pages/Team.vue")
+			component: () => import("./pages/Team.vue")
 		},
 		{
 			path: "/news",
-			component: () => import("./components/pages/News.vue")
+			component: () => import("./pages/News.vue")
 		},
 		{
 			path: "/about",
-			component: () => import("./components/pages/About.vue")
+			component: () => import("./pages/About.vue")
 		},
 		{
 			name: "profile",
 			path: "/u/:username",
-			component: () => import("./components/User/Show.vue")
+			component: () => import("./pages/Profile.vue")
 		},
 		{
 			path: "/settings",
-			component: () => import("./components/User/Settings.vue"),
+			component: () => import("./pages/Settings.vue"),
 			meta: {
 				loginRequired: true
 			}
 		},
 		{
 			path: "/reset_password",
-			component: () => import("./components/User/ResetPassword.vue")
+			component: () => import("./pages/ResetPassword.vue")
 		},
 		{
 			path: "/login",
-			component: () => import("./components/Modals/Login.vue")
+			component: () => import("./components/modals/Login.vue")
 		},
 		{
 			path: "/register",
-			component: () => import("./components/Modals/Register.vue")
+			component: () => import("./components/modals/Register.vue")
 		},
 		{
 			path: "/admin",
-			component: () => import("./components/pages/Admin.vue"),
+			component: () => import("./pages/Admin/index.vue"),
 			meta: {
 				adminRequired: true
 			}
 		},
 		{
 			path: "/admin/:page",
-			component: () => import("./components/pages/Admin.vue"),
+			component: () => import("./pages/Admin/index.vue"),
 			meta: {
 				adminRequired: true
 			}
@@ -124,7 +124,7 @@ const router = new VueRouter({
 		{
 			name: "station",
 			path: "/:id",
-			component: () => import("./components/Station/Station.vue")
+			component: () => import("./pages/Station/index.vue")
 		}
 	]
 });

+ 1 - 1
frontend/components/404.vue → frontend/src/pages/404.vue

@@ -8,7 +8,7 @@
 </template>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../styles/global.scss";
 
 .wrapper {
 	height: 100vh;

+ 3 - 3
frontend/components/pages/About.vue → frontend/src/pages/About.vue

@@ -66,8 +66,8 @@
 </template>
 
 <script>
-import MainHeader from "../MainHeader.vue";
-import MainFooter from "../MainFooter.vue";
+import MainHeader from "../components/layout/MainHeader.vue";
+import MainFooter from "../components/layout/MainFooter.vue";
 
 export default {
 	components: { MainHeader, MainFooter },
@@ -80,7 +80,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../styles/global.scss";
 
 .night-mode {
 	.card {

+ 2 - 2
frontend/components/Modals/EditNews.vue → frontend/src/pages/Admin/EditNews.vue

@@ -172,7 +172,7 @@ import { mapActions, mapState } from "vuex";
 import Toast from "toasters";
 import io from "../../io";
 
-import Modal from "./Modal.vue";
+import Modal from "../../components/Modal.vue";
 
 export default {
 	components: { Modal },
@@ -233,7 +233,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../styles/global.scss";
 
 input[type="range"] {
 	-webkit-appearance: none;

+ 2 - 2
frontend/components/Modals/EditUser.vue → frontend/src/pages/Admin/EditUser.vue

@@ -94,7 +94,7 @@ import { mapState, mapActions } from "vuex";
 
 import Toast from "toasters";
 import io from "../../io";
-import Modal from "./Modal.vue";
+import Modal from "../../components/Modal.vue";
 import validation from "../../validation";
 
 export default {
@@ -221,7 +221,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../styles/global.scss";
 
 .save-changes {
 	color: $white;

+ 3 - 3
frontend/components/Modals/IssuesModal.vue → frontend/src/pages/Admin/IssuesModal.vue

@@ -93,8 +93,8 @@ import { mapActions, mapState } from "vuex";
 import { formatDistance } from "date-fns";
 import Toast from "toasters";
 
-import UserIdToUsername from "../UserIdToUsername.vue";
-import Modal from "./Modal.vue";
+import UserIdToUsername from "../../components/common/UserIdToUsername.vue";
+import Modal from "../../components/Modal.vue";
 
 export default {
 	computed: {
@@ -130,7 +130,7 @@ export default {
 </script>
 
 <style lang="scss">
-@import "styles/global.scss";
+@import "../../styles/global.scss";
 
 .back-to-song {
 	display: flex;

+ 2 - 2
frontend/components/Modals/ViewPunishment.vue → frontend/src/pages/Admin/ViewPunishment.vue

@@ -77,8 +77,8 @@ import { mapState, mapActions } from "vuex";
 import { format, formatDistance, parseISO } from "date-fns"; // eslint-disable-line no-unused-vars
 
 import io from "../../io";
-import Modal from "./Modal.vue";
-import UserIdToUsername from "../UserIdToUsername.vue";
+import Modal from "../../components/Modal.vue";
+import UserIdToUsername from "../../components/common/UserIdToUsername.vue";
 
 export default {
 	components: { Modal, UserIdToUsername },

+ 11 - 11
frontend/components/pages/Admin.vue → frontend/src/pages/Admin/index.vue

@@ -106,20 +106,20 @@
 </template>
 
 <script>
-import MainHeader from "../MainHeader.vue";
+import MainHeader from "../../components/layout/MainHeader.vue";
 
 export default {
 	components: {
 		MainHeader,
-		QueueSongs: () => import("../Admin/QueueSongs.vue"),
-		Songs: () => import("../Admin/Songs.vue"),
-		Stations: () => import("../Admin/Stations.vue"),
-		Reports: () => import("../Admin/Reports.vue"),
-		News: () => import("../Admin/News.vue"),
-		Users: () => import("../Admin/Users.vue"),
-		Statistics: () => import("../Admin/Statistics.vue"),
-		NewStatistics: () => import("../Admin/NewStatistics.vue"),
-		Punishments: () => import("../Admin/Punishments.vue")
+		QueueSongs: () => import("./tabs/QueueSongs.vue"),
+		Songs: () => import("./tabs/Songs.vue"),
+		Stations: () => import("./tabs/Stations.vue"),
+		Reports: () => import("./tabs/Reports.vue"),
+		News: () => import("./tabs/News.vue"),
+		Users: () => import("./tabs/Users.vue"),
+		Statistics: () => import("./tabs/Statistics.vue"),
+		NewStatistics: () => import("./tabs/NewStatistics.vue"),
+		Punishments: () => import("./tabs/Punishments.vue")
 	},
 	data() {
 		return {
@@ -176,7 +176,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../styles/global.scss";
 
 .night-mode {
 	.tabs {

+ 2 - 2
frontend/components/Admin/NewStatistics.vue → frontend/src/pages/Admin/tabs/NewStatistics.vue

@@ -127,7 +127,7 @@
 </template>
 
 <script>
-import io from "../../io";
+import io from "../../../io";
 
 export default {
 	components: {},
@@ -178,7 +178,7 @@ export default {
 
 //
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../../styles/global.scss";
 
 .night-mode {
 	.table {

+ 3 - 3
frontend/components/Admin/News.vue → frontend/src/pages/Admin/tabs/News.vue

@@ -214,9 +214,9 @@
 import { mapActions, mapState } from "vuex";
 
 import Toast from "toasters";
-import io from "../../io";
+import io from "../../../io";
 
-import EditNews from "../Modals/EditNews.vue";
+import EditNews from "../EditNews.vue";
 
 export default {
 	components: { EditNews },
@@ -350,7 +350,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../../styles/global.scss";
 
 .night-mode {
 	.table {

+ 3 - 3
frontend/components/Admin/Punishments.vue → frontend/src/pages/Admin/tabs/Punishments.vue

@@ -93,8 +93,8 @@
 import { mapState, mapActions } from "vuex";
 import Toast from "toasters";
 
-import ViewPunishment from "../Modals/ViewPunishment.vue";
-import io from "../../io";
+import ViewPunishment from "../ViewPunishment.vue";
+import io from "../../../io";
 
 export default {
 	components: { ViewPunishment },
@@ -154,7 +154,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../../styles/global.scss";
 
 .night-mode {
 	.table {

+ 4 - 4
frontend/components/Admin/QueueSongs.vue → frontend/src/pages/Admin/tabs/QueueSongs.vue

@@ -112,10 +112,10 @@ import Vue from "vue";
 
 import Toast from "toasters";
 
-import EditSong from "../Modals/EditSong.vue";
-import UserIdToUsername from "../UserIdToUsername.vue";
+import EditSong from "../../../components/modals/EditSong.vue";
+import UserIdToUsername from "../../../components/common/UserIdToUsername.vue";
 
-import io from "../../io";
+import io from "../../../io";
 
 export default {
 	components: { EditSong, UserIdToUsername },
@@ -263,7 +263,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../../styles/global.scss";
 
 .night-mode {
 	.table {

+ 4 - 4
frontend/components/Admin/Reports.vue → frontend/src/pages/Admin/tabs/Reports.vue

@@ -67,10 +67,10 @@ import { mapState, mapActions } from "vuex";
 import { formatDistance } from "date-fns";
 
 import Toast from "toasters";
-import io from "../../io";
+import io from "../../../io";
 
-import IssuesModal from "../Modals/IssuesModal.vue";
-import UserIdToUsername from "../UserIdToUsername.vue";
+import IssuesModal from "../IssuesModal.vue";
+import UserIdToUsername from "../../../components/common/UserIdToUsername.vue";
 
 export default {
 	components: { IssuesModal, UserIdToUsername },
@@ -148,7 +148,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../../styles/global.scss";
 
 .night-mode {
 	.table {

+ 4 - 4
frontend/components/Admin/Songs.vue → frontend/src/pages/Admin/tabs/Songs.vue

@@ -104,10 +104,10 @@ import { mapState, mapActions } from "vuex";
 
 import Toast from "toasters";
 
-import EditSong from "../Modals/EditSong.vue";
-import UserIdToUsername from "../UserIdToUsername.vue";
+import EditSong from "../../../components/modals/EditSong.vue";
+import UserIdToUsername from "../../../components/common/UserIdToUsername.vue";
 
-import io from "../../io";
+import io from "../../../io";
 
 export default {
 	components: { EditSong, UserIdToUsername },
@@ -253,7 +253,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../../styles/global.scss";
 
 .night-mode {
 	.table {

+ 4 - 4
frontend/components/Admin/Stations.vue → frontend/src/pages/Admin/tabs/Stations.vue

@@ -183,10 +183,10 @@
 import { mapState, mapActions } from "vuex";
 
 import Toast from "toasters";
-import io from "../../io";
+import io from "../../../io";
 
-import EditStation from "../Modals/EditStation.vue";
-import UserIdToUsername from "../UserIdToUsername.vue";
+import EditStation from "../../../components/modals/EditStation.vue";
+import UserIdToUsername from "../../../components/common/UserIdToUsername.vue";
 
 export default {
 	components: { EditStation, UserIdToUsername },
@@ -361,7 +361,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../../styles/global.scss";
 
 .night-mode {
 	.table {

+ 2 - 2
frontend/components/Admin/Statistics.vue → frontend/src/pages/Admin/tabs/Statistics.vue

@@ -105,7 +105,7 @@
 import { Line } from "chart.js";
 import "chartjs-adapter-date-fns";
 
-import io from "../../io";
+import io from "../../../io";
 
 export default {
 	components: {},
@@ -326,7 +326,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../../styles/global.scss";
 
 .night-mode {
 	.table {

+ 3 - 3
frontend/components/Admin/Users.vue → frontend/src/pages/Admin/tabs/Users.vue

@@ -60,8 +60,8 @@
 <script>
 import { mapState, mapActions } from "vuex";
 
-import EditUser from "../Modals/EditUser.vue";
-import io from "../../io";
+import EditUser from "../EditUser.vue";
+import io from "../../../io";
 
 export default {
 	components: { EditUser },
@@ -108,7 +108,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../../styles/global.scss";
 
 .night-mode {
 	.table {

+ 1 - 1
frontend/components/pages/Banned.vue → frontend/src/pages/Banned.vue

@@ -27,7 +27,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../styles/global.scss";
 
 .container {
 	display: flex;

+ 1 - 1
frontend/components/Modals/CreateCommunityStation.vue → frontend/src/pages/Home/CreateCommunityStation.vue

@@ -42,7 +42,7 @@
 import { mapActions } from "vuex";
 
 import Toast from "toasters";
-import Modal from "./Modal.vue";
+import Modal from "../../components/Modal.vue";
 import io from "../../io";
 import validation from "../../validation";
 

+ 5 - 5
frontend/components/pages/Home.vue → frontend/src/pages/Home/index.vue

@@ -146,10 +146,10 @@
 import { mapState, mapActions } from "vuex";
 import Toast from "toasters";
 
-import MainHeader from "../MainHeader.vue";
-import MainFooter from "../MainFooter.vue";
-import CreateCommunityStation from "../Modals/CreateCommunityStation.vue";
-import UserIdToUsername from "../UserIdToUsername.vue";
+import MainHeader from "../../components/layout/MainHeader.vue";
+import MainFooter from "../../components/layout/MainFooter.vue";
+import CreateCommunityStation from "./CreateCommunityStation.vue";
+import UserIdToUsername from "../../components/common/UserIdToUsername.vue";
 
 import io from "../../io";
 
@@ -301,7 +301,7 @@ export default {
 </script>
 
 <style lang="scss">
-@import "styles/global.scss";
+@import "../../styles/global.scss";
 
 * {
 	box-sizing: border-box;

+ 4 - 4
frontend/components/pages/News.vue → frontend/src/pages/News.vue

@@ -84,9 +84,9 @@
 import { format } from "date-fns";
 import Vue from "vue";
 
-import MainHeader from "../MainHeader.vue";
-import MainFooter from "../MainFooter.vue";
-import io from "../../io";
+import MainHeader from "../components/layout/MainHeader.vue";
+import MainFooter from "../components/layout/MainFooter.vue";
+import io from "../io";
 
 export default {
 	components: { MainHeader, MainFooter },
@@ -129,7 +129,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../styles/global.scss";
 
 .night-mode {
 	p {

+ 2 - 2
frontend/components/pages/Privacy.vue → frontend/src/pages/Privacy.vue

@@ -204,8 +204,8 @@
 </template>
 
 <script>
-import MainHeader from "../MainHeader.vue";
-import MainFooter from "../MainFooter.vue";
+import MainHeader from "../components/layout/MainHeader.vue";
+import MainFooter from "../components/layout/MainFooter.vue";
 
 export default {
 	components: { MainHeader, MainFooter }

+ 7 - 7
frontend/components/User/Show.vue → frontend/src/pages/Profile.vue

@@ -172,19 +172,19 @@ import { mapState, mapActions } from "vuex";
 import { format, formatDistance, parseISO } from "date-fns";
 import Toast from "toasters";
 
-import PlaylistItem from "../PlaylistItem.vue";
-import MainHeader from "../MainHeader.vue";
-import MainFooter from "../MainFooter.vue";
+import PlaylistItem from "../components/ui/PlaylistItem.vue";
+import MainHeader from "../components/layout/MainHeader.vue";
+import MainFooter from "../components/layout/MainFooter.vue";
 
-import io from "../../io";
+import io from "../io";
 
 export default {
 	components: {
 		MainHeader,
 		MainFooter,
 		PlaylistItem,
-		CreatePlaylist: () => import("../Modals/Playlists/Create.vue"),
-		EditPlaylist: () => import("../Modals/Playlists/Edit.vue")
+		CreatePlaylist: () => import("../components/modals/CreatePlaylist.vue"),
+		EditPlaylist: () => import("../components/modals/EditPlaylist.vue")
 	},
 	data() {
 		return {
@@ -506,7 +506,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../styles/global.scss";
 
 .info-section {
 	width: 912px;

+ 4 - 4
frontend/components/User/ResetPassword.vue → frontend/src/pages/ResetPassword.vue

@@ -71,10 +71,10 @@
 <script>
 import Toast from "toasters";
 
-import MainHeader from "../MainHeader.vue";
-import MainFooter from "../MainFooter.vue";
+import MainHeader from "../components/layout/MainHeader.vue";
+import MainFooter from "../components/layout/MainFooter.vue";
 
-import io from "../../io";
+import io from "../io";
 
 export default {
 	components: { MainHeader, MainFooter },
@@ -149,7 +149,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../styles/global.scss";
 
 .night-mode {
 	.label {

+ 5 - 5
frontend/components/User/Settings.vue → frontend/src/pages/Settings.vue

@@ -246,11 +246,11 @@ import { mapState, mapActions } from "vuex";
 
 import Toast from "toasters";
 
-import MainHeader from "../MainHeader.vue";
-import MainFooter from "../MainFooter.vue";
+import MainHeader from "../components/layout/MainHeader.vue";
+import MainFooter from "../components/layout/MainFooter.vue";
 
-import io from "../../io";
-import validation from "../../validation";
+import io from "../io";
+import validation from "../validation";
 
 export default {
 	components: { MainHeader, MainFooter },
@@ -649,7 +649,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../styles/global.scss";
 
 .container {
 	@media only screen and (min-width: 900px) {

+ 2 - 2
frontend/components/Modals/AddSongToPlaylist.vue → frontend/src/pages/Station/AddSongToPlaylist.vue

@@ -39,7 +39,7 @@
 import { mapState } from "vuex";
 
 import Toast from "toasters";
-import Modal from "./Modal.vue";
+import Modal from "../../components/Modal.vue";
 import io from "../../io";
 
 export default {
@@ -129,7 +129,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../styles/global.scss";
 
 .icon.is-small {
 	margin-right: 10px !important;

+ 3 - 3
frontend/components/Modals/AddSongToQueue.vue → frontend/src/pages/Station/AddSongToQueue.vue

@@ -211,8 +211,8 @@ import { mapState, mapActions } from "vuex";
 
 import Toast from "toasters";
 
-import PlaylistItem from "../PlaylistItem.vue";
-import Modal from "./Modal.vue";
+import PlaylistItem from "../../components/ui/PlaylistItem.vue";
+import Modal from "../../components/Modal.vue";
 
 import io from "../../io";
 
@@ -361,7 +361,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../styles/global.scss";
 
 tr td {
 	vertical-align: middle;

+ 2 - 2
frontend/components/Modals/Report.vue → frontend/src/pages/Station/Report.vue

@@ -147,7 +147,7 @@
 import { mapState, mapActions } from "vuex";
 
 import Toast from "toasters";
-import Modal from "./Modal.vue";
+import Modal from "../../components/Modal.vue";
 import io from "../../io";
 
 export default {
@@ -258,7 +258,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../styles/global.scss";
 
 h6 {
 	margin-bottom: 15px;

+ 4 - 4
frontend/components/Sidebars/SongsList.vue → frontend/src/pages/Station/SongsList.vue

@@ -123,11 +123,11 @@
 import { mapState, mapActions } from "vuex";
 import Toast from "toasters";
 
-import utils from "../../js/utils";
+import utils from "../../../js/utils";
 
-import Sidebar from "./Sidebar.vue";
+import Sidebar from "../../components/Sidebar.vue";
 
-import UserIdToUsername from "../UserIdToUsername.vue";
+import UserIdToUsername from "../../components/common/UserIdToUsername.vue";
 
 export default {
 	data() {
@@ -175,7 +175,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../styles/global.scss";
 
 .inner-wrapper {
 	overflow: auto;

+ 1 - 1
frontend/components/Station/StationHeader.vue → frontend/src/pages/Station/StationHeader.vue

@@ -270,7 +270,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../../styles/global.scss";
 
 .nav {
 	background-color: $primary-color;

+ 1 - 1
frontend/components/Sidebars/UsersList.vue → frontend/src/pages/Station/UsersList.vue

@@ -21,7 +21,7 @@
 <script>
 import { mapState } from "vuex";
 
-import Sidebar from "./Sidebar.vue";
+import Sidebar from "../../components/Sidebar.vue";
 
 export default {
 	computed: mapState({

+ 12 - 11
frontend/components/Station/Station.vue → frontend/src/pages/Station/index.vue

@@ -441,12 +441,12 @@ import Toast from "toasters";
 
 import StationHeader from "./StationHeader.vue";
 
-import UserIdToUsername from "../UserIdToUsername.vue";
+import UserIdToUsername from "../../components/common/UserIdToUsername.vue";
 import Z404 from "../404.vue";
 
 import io from "../../io";
 import keyboardShortcuts from "../../keyboardShortcuts";
-import utils from "../../js/utils";
+import utils from "../../../js/utils";
 
 export default {
 	data() {
@@ -1390,14 +1390,15 @@ export default {
 	},
 	components: {
 		StationHeader,
-		SongQueue: () => import("../Modals/AddSongToQueue.vue"),
-		AddToPlaylist: () => import("../Modals/AddSongToPlaylist.vue"),
-		EditPlaylist: () => import("../Modals/Playlists/Edit.vue"),
-		CreatePlaylist: () => import("../Modals/Playlists/Create.vue"),
-		EditStation: () => import("../Modals/EditStation.vue"),
-		Report: () => import("../Modals/Report.vue"),
-		SongsListSidebar: () => import("../Sidebars/SongsList.vue"),
-		UsersSidebar: () => import("../Sidebars/UsersList.vue"),
+		SongQueue: () => import("./AddSongToQueue.vue"),
+		AddToPlaylist: () => import("./AddSongToPlaylist.vue"),
+		EditPlaylist: () => import("../../components/modals/EditPlaylist.vue"),
+		CreatePlaylist: () =>
+			import("../../components/modals/CreatePlaylist.vue"),
+		EditStation: () => import("../../components/modals/EditStation.vue"),
+		Report: () => import("./Report.vue"),
+		SongsListSidebar: () => import("./SongsList.vue"),
+		UsersSidebar: () => import("./UsersList.vue"),
 		UserIdToUsername,
 		Z404
 	}
@@ -1405,7 +1406,7 @@ export default {
 </script>
 
 <style lang="scss">
-@import "styles/global.scss";
+@import "../../styles/global.scss";
 
 .station-parent {
 	display: flex;

+ 3 - 3
frontend/components/pages/Team.vue → frontend/src/pages/Team.vue

@@ -119,8 +119,8 @@
 </template>
 
 <script>
-import MainHeader from "../MainHeader.vue";
-import MainFooter from "../MainFooter.vue";
+import MainHeader from "../components/layout/MainHeader.vue";
+import MainFooter from "../components/layout/MainFooter.vue";
 
 export default {
 	components: { MainHeader, MainFooter }
@@ -128,7 +128,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-@import "styles/global.scss";
+@import "../styles/global.scss";
 
 .night-mode {
 	.card {

+ 2 - 2
frontend/components/pages/Terms.vue → frontend/src/pages/Terms.vue

@@ -1096,8 +1096,8 @@
 </template>
 
 <script>
-import MainHeader from "../MainHeader.vue";
-import MainFooter from "../MainFooter.vue";
+import MainHeader from "../components/layout/MainHeader.vue";
+import MainFooter from "../components/layout/MainFooter.vue";
 
 export default {
 	components: { MainHeader, MainFooter }

+ 0 - 0
frontend/store/index.js → frontend/src/store/index.js


+ 247 - 247
frontend/store/modules/admin.js → frontend/src/store/modules/admin.js

@@ -1,247 +1,247 @@
-/* eslint no-param-reassign: 0 */
-
-import Vue from "vue";
-import admin from "../../api/admin/index";
-
-const state = {};
-const getters = {};
-const actions = {};
-const mutations = {};
-
-const modules = {
-	songs: {
-		namespaced: true,
-		state: {
-			video: {
-				player: null,
-				paused: true,
-				playerReady: false,
-				autoPlayed: false,
-				currentTime: 0
-			},
-			editing: {},
-			songs: []
-		},
-		getters: {},
-		actions: {
-			editSong: ({ commit }, song) => commit("editSong", song),
-			stopVideo: ({ commit }) => commit("stopVideo"),
-			loadVideoById: ({ commit }, id, skipDuration) =>
-				commit("loadVideoById", id, skipDuration),
-			pauseVideo: ({ commit }, status) => commit("pauseVideo", status),
-			getCurrentTime: ({ commit, state }, fixedVal) => {
-				return new Promise(resolve => {
-					commit("getCurrentTime", fixedVal);
-					resolve(state.video.currentTime);
-				});
-			},
-			addSong: ({ commit }, song) => commit("addSong", song),
-			removeSong: ({ commit }, songId) => commit("removeSong", songId),
-			updateSong: ({ commit }, updatedSong) =>
-				commit("updateSong", updatedSong),
-			updateSongField: ({ commit }, data) =>
-				commit("updateSongField", data),
-			selectDiscogsInfo: ({ commit }, discogsInfo) =>
-				commit("selectDiscogsInfo", discogsInfo)
-		},
-		mutations: {
-			editSong(state, song) {
-				if (song.song.discogs === undefined) song.song.discogs = null;
-				state.editing = { ...song };
-			},
-			stopVideo(state) {
-				state.video.player.stopVideo();
-			},
-			loadVideoById(state, id, skipDuration) {
-				state.video.player.loadVideoById(id, skipDuration);
-			},
-			pauseVideo(state, status) {
-				if (status) state.video.player.pauseVideo();
-				else state.video.player.playVideo();
-				state.video.paused = status;
-			},
-			getCurrentTime(state, fixedVal) {
-				if (!state.playerReady) state.video.currentTime = 0;
-				else {
-					Promise.resolve(state.video.player.getCurrentTime()).then(
-						time => {
-							if (fixedVal)
-								Promise.resolve(time.toFixed(fixedVal)).then(
-									fixedTime => {
-										state.video.currentTime = fixedTime;
-									}
-								);
-							else state.video.currentTime = time;
-						}
-					);
-				}
-			},
-			addSong(state, song) {
-				state.songs.push(song);
-			},
-			removeSong(state, songId) {
-				state.songs = state.songs.filter(song => {
-					return song._id !== songId;
-				});
-			},
-			updateSong(state, updatedSong) {
-				state.songs.forEach((song, index) => {
-					if (song._id === updatedSong._id)
-						Vue.set(state.songs, index, updatedSong);
-				});
-			},
-			updateSongField(state, data) {
-				state.editing.song[data.field] = data.value;
-			},
-			selectDiscogsInfo(state, discogsInfo) {
-				state.editing.song.discogs = discogsInfo;
-			}
-		}
-	},
-	stations: {
-		namespaced: true,
-		state: {
-			stations: [],
-			station: {},
-			editing: {}
-		},
-		getters: {},
-		actions: {
-			editStation: ({ commit }, station) =>
-				commit("editStation", station),
-			loadStations: ({ commit }, stations) =>
-				commit("loadStations", stations),
-			stationRemoved: ({ commit }, stationId) =>
-				commit("stationRemoved", stationId),
-			stationAdded: ({ commit }, station) =>
-				commit("stationAdded", station)
-		},
-		mutations: {
-			editStation(state, station) {
-				state.station = station;
-				state.editing = JSON.parse(JSON.stringify(station));
-			},
-			loadStations(state, stations) {
-				state.stations = stations;
-			},
-			stationAdded(state, station) {
-				state.stations.push(station);
-			},
-			stationRemoved(state, stationId) {
-				state.stations = state.stations.filter(station => {
-					return station._id !== stationId;
-				});
-			}
-		}
-	},
-	reports: {
-		namespaced: true,
-		state: {
-			report: {}
-		},
-		getters: {},
-		actions: {
-			viewReport: ({ commit }, report) => commit("viewReport", report),
-			/* eslint-disable-next-line no-unused-vars */
-			resolveReport: ({ commit }, reportId) => {
-				return new Promise((resolve, reject) => {
-					return admin.reports
-						.resolve(reportId)
-						.then(res => {
-							return resolve(res);
-						})
-						.catch(err => {
-							return reject(new Error(err.message));
-						});
-				});
-			}
-		},
-		mutations: {
-			viewReport(state, report) {
-				state.report = report;
-			}
-		}
-	},
-	punishments: {
-		namespaced: true,
-		state: {
-			punishment: {}
-		},
-		getters: {},
-		actions: {
-			viewPunishment: ({ commit }, punishment) =>
-				commit("viewPunishment", punishment)
-		},
-		mutations: {
-			viewPunishment(state, punishment) {
-				state.punishment = punishment;
-			}
-		}
-	},
-	users: {
-		namespaced: true,
-		state: {
-			editing: {}
-		},
-		getters: {},
-		actions: {
-			editUser: ({ commit }, user) => commit("editUser", user)
-		},
-		mutations: {
-			editUser(state, user) {
-				state.editing = user;
-			}
-		}
-	},
-	news: {
-		namespaced: true,
-		state: {
-			editing: {},
-			news: []
-		},
-		getters: {},
-		actions: {
-			editNews: ({ commit }, news) => commit("editNews", news),
-			addChange: ({ commit }, data) => commit("addChange", data),
-			removeChange: ({ commit }, data) => commit("removeChange", data),
-			addNews: ({ commit }, news) => commit("addNews", news),
-			removeNews: ({ commit }, newsId) => commit("removeNews", newsId),
-			updateNews: ({ commit }, updatedNews) =>
-				commit("updateNews", updatedNews)
-		},
-		mutations: {
-			editNews(state, news) {
-				state.editing = news;
-			},
-			addChange(state, data) {
-				state.editing[data.type].push(data.change);
-			},
-			removeChange(state, data) {
-				state.editing[data.type].splice(data.index, 1);
-			},
-			addNews(state, news) {
-				state.news.push(news);
-			},
-			removeNews(state, newsId) {
-				state.news = state.news.filter(news => {
-					return news._id !== newsId;
-				});
-			},
-			updateNews(state, updatedNews) {
-				state.news.forEach((news, index) => {
-					if (news._id === updatedNews._id)
-						Vue.set(state.news, index, updatedNews);
-				});
-			}
-		}
-	}
-};
-
-export default {
-	namespaced: true,
-	state,
-	getters,
-	actions,
-	mutations,
-	modules
-};
+/* eslint no-param-reassign: 0 */
+
+import Vue from "vue";
+import admin from "../../api/admin/index";
+
+const state = {};
+const getters = {};
+const actions = {};
+const mutations = {};
+
+const modules = {
+	songs: {
+		namespaced: true,
+		state: {
+			video: {
+				player: null,
+				paused: true,
+				playerReady: false,
+				autoPlayed: false,
+				currentTime: 0
+			},
+			editing: {},
+			songs: []
+		},
+		getters: {},
+		actions: {
+			editSong: ({ commit }, song) => commit("editSong", song),
+			stopVideo: ({ commit }) => commit("stopVideo"),
+			loadVideoById: ({ commit }, id, skipDuration) =>
+				commit("loadVideoById", id, skipDuration),
+			pauseVideo: ({ commit }, status) => commit("pauseVideo", status),
+			getCurrentTime: ({ commit, state }, fixedVal) => {
+				return new Promise(resolve => {
+					commit("getCurrentTime", fixedVal);
+					resolve(state.video.currentTime);
+				});
+			},
+			addSong: ({ commit }, song) => commit("addSong", song),
+			removeSong: ({ commit }, songId) => commit("removeSong", songId),
+			updateSong: ({ commit }, updatedSong) =>
+				commit("updateSong", updatedSong),
+			updateSongField: ({ commit }, data) =>
+				commit("updateSongField", data),
+			selectDiscogsInfo: ({ commit }, discogsInfo) =>
+				commit("selectDiscogsInfo", discogsInfo)
+		},
+		mutations: {
+			editSong(state, song) {
+				if (song.song.discogs === undefined) song.song.discogs = null;
+				state.editing = { ...song };
+			},
+			stopVideo(state) {
+				state.video.player.stopVideo();
+			},
+			loadVideoById(state, id, skipDuration) {
+				state.video.player.loadVideoById(id, skipDuration);
+			},
+			pauseVideo(state, status) {
+				if (status) state.video.player.pauseVideo();
+				else state.video.player.playVideo();
+				state.video.paused = status;
+			},
+			getCurrentTime(state, fixedVal) {
+				if (!state.playerReady) state.video.currentTime = 0;
+				else {
+					Promise.resolve(state.video.player.getCurrentTime()).then(
+						time => {
+							if (fixedVal)
+								Promise.resolve(time.toFixed(fixedVal)).then(
+									fixedTime => {
+										state.video.currentTime = fixedTime;
+									}
+								);
+							else state.video.currentTime = time;
+						}
+					);
+				}
+			},
+			addSong(state, song) {
+				state.songs.push(song);
+			},
+			removeSong(state, songId) {
+				state.songs = state.songs.filter(song => {
+					return song._id !== songId;
+				});
+			},
+			updateSong(state, updatedSong) {
+				state.songs.forEach((song, index) => {
+					if (song._id === updatedSong._id)
+						Vue.set(state.songs, index, updatedSong);
+				});
+			},
+			updateSongField(state, data) {
+				state.editing.song[data.field] = data.value;
+			},
+			selectDiscogsInfo(state, discogsInfo) {
+				state.editing.song.discogs = discogsInfo;
+			}
+		}
+	},
+	stations: {
+		namespaced: true,
+		state: {
+			stations: [],
+			station: {},
+			editing: {}
+		},
+		getters: {},
+		actions: {
+			editStation: ({ commit }, station) =>
+				commit("editStation", station),
+			loadStations: ({ commit }, stations) =>
+				commit("loadStations", stations),
+			stationRemoved: ({ commit }, stationId) =>
+				commit("stationRemoved", stationId),
+			stationAdded: ({ commit }, station) =>
+				commit("stationAdded", station)
+		},
+		mutations: {
+			editStation(state, station) {
+				state.station = station;
+				state.editing = JSON.parse(JSON.stringify(station));
+			},
+			loadStations(state, stations) {
+				state.stations = stations;
+			},
+			stationAdded(state, station) {
+				state.stations.push(station);
+			},
+			stationRemoved(state, stationId) {
+				state.stations = state.stations.filter(station => {
+					return station._id !== stationId;
+				});
+			}
+		}
+	},
+	reports: {
+		namespaced: true,
+		state: {
+			report: {}
+		},
+		getters: {},
+		actions: {
+			viewReport: ({ commit }, report) => commit("viewReport", report),
+			/* eslint-disable-next-line no-unused-vars */
+			resolveReport: ({ commit }, reportId) => {
+				return new Promise((resolve, reject) => {
+					return admin.reports
+						.resolve(reportId)
+						.then(res => {
+							return resolve(res);
+						})
+						.catch(err => {
+							return reject(new Error(err.message));
+						});
+				});
+			}
+		},
+		mutations: {
+			viewReport(state, report) {
+				state.report = report;
+			}
+		}
+	},
+	punishments: {
+		namespaced: true,
+		state: {
+			punishment: {}
+		},
+		getters: {},
+		actions: {
+			viewPunishment: ({ commit }, punishment) =>
+				commit("viewPunishment", punishment)
+		},
+		mutations: {
+			viewPunishment(state, punishment) {
+				state.punishment = punishment;
+			}
+		}
+	},
+	users: {
+		namespaced: true,
+		state: {
+			editing: {}
+		},
+		getters: {},
+		actions: {
+			editUser: ({ commit }, user) => commit("editUser", user)
+		},
+		mutations: {
+			editUser(state, user) {
+				state.editing = user;
+			}
+		}
+	},
+	news: {
+		namespaced: true,
+		state: {
+			editing: {},
+			news: []
+		},
+		getters: {},
+		actions: {
+			editNews: ({ commit }, news) => commit("editNews", news),
+			addChange: ({ commit }, data) => commit("addChange", data),
+			removeChange: ({ commit }, data) => commit("removeChange", data),
+			addNews: ({ commit }, news) => commit("addNews", news),
+			removeNews: ({ commit }, newsId) => commit("removeNews", newsId),
+			updateNews: ({ commit }, updatedNews) =>
+				commit("updateNews", updatedNews)
+		},
+		mutations: {
+			editNews(state, news) {
+				state.editing = news;
+			},
+			addChange(state, data) {
+				state.editing[data.type].push(data.change);
+			},
+			removeChange(state, data) {
+				state.editing[data.type].splice(data.index, 1);
+			},
+			addNews(state, news) {
+				state.news.push(news);
+			},
+			removeNews(state, newsId) {
+				state.news = state.news.filter(news => {
+					return news._id !== newsId;
+				});
+			},
+			updateNews(state, updatedNews) {
+				state.news.forEach((news, index) => {
+					if (news._id === updatedNews._id)
+						Vue.set(state.news, index, updatedNews);
+				});
+			}
+		}
+	}
+};
+
+export default {
+	namespaced: true,
+	state,
+	getters,
+	actions,
+	mutations,
+	modules
+};

+ 0 - 0
frontend/store/modules/modals.js → frontend/src/store/modules/modals.js


+ 64 - 64
frontend/store/modules/sidebars.js → frontend/src/store/modules/sidebars.js

@@ -1,64 +1,64 @@
-/* eslint no-param-reassign: 0 */
-
-const state = {
-	sidebars: {
-		station: {
-			songslist: false,
-			users: false
-		}
-	},
-	currentlyActive: {}
-};
-
-const getters = {};
-
-const actions = {
-	toggleSidebar: ({ commit }, data) => {
-		commit("toggleSidebar", data);
-	},
-	openSidebar: ({ commit }, data) => {
-		commit("openSidebar", data);
-	},
-	closeCurrentSidebar: ({ commit }) => {
-		commit("closeCurrentSidebar");
-	}
-};
-
-const mutations = {
-	toggleSidebar(state, data) {
-		const { sector, sidebar } = data;
-
-		if (
-			state.currentlyActive.sidebar &&
-			state.currentlyActive.sidebar !== sidebar
-		) {
-			state.sidebars[state.currentlyActive.sector][
-				state.currentlyActive.sidebar
-			] = false;
-			state.currentlyActive = {};
-		}
-
-		state.sidebars[sector][sidebar] = !state.sidebars[sector][sidebar];
-
-		if (state.sidebars[sector][sidebar])
-			state.currentlyActive = { sector, sidebar };
-	},
-	openSidebar(state, data) {
-		const { sector, sidebar } = data;
-		state.sidebars[sector][sidebar] = true;
-		state.currentlyActive = { sector, sidebar };
-	},
-	closeCurrentSidebar(state) {
-		const { sector, sidebar } = state.currentlyActive;
-		state.sidebars[sector][sidebar] = false;
-		state.currentlyActive = {};
-	}
-};
-
-export default {
-	namespaced: true,
-	state,
-	getters,
-	actions,
-	mutations
-};
+/* eslint no-param-reassign: 0 */
+
+const state = {
+	sidebars: {
+		station: {
+			songslist: false,
+			users: false
+		}
+	},
+	currentlyActive: {}
+};
+
+const getters = {};
+
+const actions = {
+	toggleSidebar: ({ commit }, data) => {
+		commit("toggleSidebar", data);
+	},
+	openSidebar: ({ commit }, data) => {
+		commit("openSidebar", data);
+	},
+	closeCurrentSidebar: ({ commit }) => {
+		commit("closeCurrentSidebar");
+	}
+};
+
+const mutations = {
+	toggleSidebar(state, data) {
+		const { sector, sidebar } = data;
+
+		if (
+			state.currentlyActive.sidebar &&
+			state.currentlyActive.sidebar !== sidebar
+		) {
+			state.sidebars[state.currentlyActive.sector][
+				state.currentlyActive.sidebar
+			] = false;
+			state.currentlyActive = {};
+		}
+
+		state.sidebars[sector][sidebar] = !state.sidebars[sector][sidebar];
+
+		if (state.sidebars[sector][sidebar])
+			state.currentlyActive = { sector, sidebar };
+	},
+	openSidebar(state, data) {
+		const { sector, sidebar } = data;
+		state.sidebars[sector][sidebar] = true;
+		state.currentlyActive = { sector, sidebar };
+	},
+	closeCurrentSidebar(state) {
+		const { sector, sidebar } = state.currentlyActive;
+		state.sidebars[sector][sidebar] = false;
+		state.currentlyActive = {};
+	}
+};
+
+export default {
+	namespaced: true,
+	state,
+	getters,
+	actions,
+	mutations
+};

+ 0 - 0
frontend/store/modules/station.js → frontend/src/store/modules/station.js


+ 242 - 242
frontend/store/modules/user.js → frontend/src/store/modules/user.js

@@ -1,242 +1,242 @@
-/* eslint no-param-reassign: 0 */
-
-import auth from "../../api/auth";
-import io from "../../io";
-import validation from "../../validation";
-
-const state = {};
-const getters = {};
-const actions = {};
-const mutations = {};
-
-const modules = {
-	auth: {
-		namespaced: true,
-		state: {
-			userIdMap: {},
-			userIdRequested: {},
-			pendingUserIdCallbacks: {},
-			loggedIn: false,
-			role: "",
-			username: "",
-			userId: "",
-			banned: false,
-			ban: {},
-			gotData: false
-		},
-		actions: {
-			/* eslint-disable-next-line no-unused-vars */
-			register: ({ commit }, user) => {
-				return new Promise((resolve, reject) => {
-					const { username, email, password } = user;
-
-					if (!email || !username || !password)
-						return reject(new Error("Please fill in all fields"));
-
-					if (!validation.isLength(email, 3, 254))
-						return reject(
-							new Error(
-								"Email must have between 3 and 254 characters."
-							)
-						);
-
-					if (
-						email.indexOf("@") !== email.lastIndexOf("@") ||
-						!validation.regex.emailSimple.test(email)
-					)
-						return reject(new Error("Invalid email format."));
-
-					if (!validation.isLength(username, 2, 32))
-						return reject(
-							new Error(
-								"Username must have between 2 and 32 characters."
-							)
-						);
-
-					if (!validation.regex.azAZ09_.test(username))
-						return reject(
-							new Error(
-								"Invalid username format. Allowed characters: a-z, A-Z, 0-9 and _."
-							)
-						);
-
-					if (!validation.isLength(password, 6, 200))
-						return reject(
-							new Error(
-								"Password must have between 6 and 200 characters."
-							)
-						);
-
-					if (!validation.regex.password.test(password))
-						return reject(
-							new Error(
-								"Invalid password format. Must have one lowercase letter, one uppercase letter, one number and one special character."
-							)
-						);
-
-					return auth
-						.register(user)
-						.then(res => {
-							return resolve(res);
-						})
-						.catch(err => {
-							return reject(new Error(err.message));
-						});
-				});
-			},
-			/* eslint-disable-next-line no-unused-vars */
-			login: ({ commit }, user) => {
-				return new Promise((resolve, reject) => {
-					auth.login(user)
-						.then(() => {
-							return resolve({
-								status: "success",
-								message: "Logged in!"
-							});
-						})
-						.catch(err => {
-							return reject(new Error(err.message));
-						});
-				});
-			},
-			logout: () => {
-				return new Promise((resolve, reject) => {
-					return auth
-						.logout()
-						.then(() => {
-							return resolve();
-						})
-						.catch(() => {
-							return reject();
-						});
-				});
-			},
-			getUsernameFromId: ({ commit, state }, userId) => {
-				return new Promise(resolve => {
-					if (typeof state.userIdMap[`Z${userId}`] !== "string") {
-						if (state.userIdRequested[`Z${userId}`] !== true) {
-							commit("requestingUserId", userId);
-							io.getSocket(socket => {
-								socket.emit(
-									"users.getUsernameFromId",
-									userId,
-									res => {
-										if (res.status === "success") {
-											commit("mapUserId", {
-												userId,
-												username: res.data
-											});
-
-											state.pendingUserIdCallbacks[
-												`Z${userId}`
-											].forEach(cb => cb(res.data));
-
-											commit(
-												"clearPendingCallbacks",
-												userId
-											);
-
-											return resolve(res.data);
-										}
-										return resolve();
-									}
-								);
-							});
-						} else {
-							commit("pendingUsername", {
-								userId,
-								callback: username => {
-									return resolve(username);
-								}
-							});
-						}
-					} else {
-						resolve(state.userIdMap[`Z${userId}`]);
-					}
-				});
-			},
-			authData: ({ commit }, data) => {
-				commit("authData", data);
-			},
-			banUser: ({ commit }, ban) => {
-				commit("banUser", ban);
-			},
-			updateUsername: ({ commit }, username) => {
-				commit("updateUsername", username);
-			}
-		},
-		mutations: {
-			mapUserId(state, data) {
-				state.userIdMap[`Z${data.userId}`] = data.username;
-				state.userIdRequested[`Z${data.userId}`] = false;
-			},
-			requestingUserId(state, userId) {
-				state.userIdRequested[`Z${userId}`] = true;
-				if (!state.pendingUserIdCallbacks[`Z${userId}`])
-					state.pendingUserIdCallbacks[`Z${userId}`] = [];
-			},
-			pendingUsername(state, data) {
-				state.pendingUserIdCallbacks[`Z${data.userId}`].push(
-					data.callback
-				);
-			},
-			clearPendingCallbacks(state, userId) {
-				state.pendingUserIdCallbacks[`Z${userId}`] = [];
-			},
-			authData(state, data) {
-				state.loggedIn = data.loggedIn;
-				state.role = data.role;
-				state.username = data.username;
-				state.userId = data.userId;
-				state.gotData = true;
-			},
-			banUser(state, ban) {
-				state.banned = true;
-				state.ban = ban;
-			},
-			updateUsername(state, username) {
-				state.username = username;
-			}
-		}
-	},
-	playlists: {
-		namespaced: true,
-		state: {
-			editing: ""
-		},
-		getters: {},
-		actions: {
-			editPlaylist: ({ commit }, id) => commit("editPlaylist", id)
-		},
-		mutations: {
-			editPlaylist(state, id) {
-				state.editing = id;
-			}
-		}
-	},
-	preferences: {
-		namespaced: true,
-		state: {
-			nightmode: true
-		},
-		actions: {
-			changeNightmode: ({ commit }, nightmode) => {
-				commit("changeNightmode", nightmode);
-			}
-		},
-		mutations: {
-			changeNightmode(state, nightmode) {
-				state.nightmode = nightmode;
-			}
-		}
-	}
-};
-
-export default {
-	namespaced: true,
-	state,
-	getters,
-	actions,
-	mutations,
-	modules
-};
+/* eslint no-param-reassign: 0 */
+
+import auth from "../../api/auth";
+import io from "../../io";
+import validation from "../../validation";
+
+const state = {};
+const getters = {};
+const actions = {};
+const mutations = {};
+
+const modules = {
+	auth: {
+		namespaced: true,
+		state: {
+			userIdMap: {},
+			userIdRequested: {},
+			pendingUserIdCallbacks: {},
+			loggedIn: false,
+			role: "",
+			username: "",
+			userId: "",
+			banned: false,
+			ban: {},
+			gotData: false
+		},
+		actions: {
+			/* eslint-disable-next-line no-unused-vars */
+			register: ({ commit }, user) => {
+				return new Promise((resolve, reject) => {
+					const { username, email, password } = user;
+
+					if (!email || !username || !password)
+						return reject(new Error("Please fill in all fields"));
+
+					if (!validation.isLength(email, 3, 254))
+						return reject(
+							new Error(
+								"Email must have between 3 and 254 characters."
+							)
+						);
+
+					if (
+						email.indexOf("@") !== email.lastIndexOf("@") ||
+						!validation.regex.emailSimple.test(email)
+					)
+						return reject(new Error("Invalid email format."));
+
+					if (!validation.isLength(username, 2, 32))
+						return reject(
+							new Error(
+								"Username must have between 2 and 32 characters."
+							)
+						);
+
+					if (!validation.regex.azAZ09_.test(username))
+						return reject(
+							new Error(
+								"Invalid username format. Allowed characters: a-z, A-Z, 0-9 and _."
+							)
+						);
+
+					if (!validation.isLength(password, 6, 200))
+						return reject(
+							new Error(
+								"Password must have between 6 and 200 characters."
+							)
+						);
+
+					if (!validation.regex.password.test(password))
+						return reject(
+							new Error(
+								"Invalid password format. Must have one lowercase letter, one uppercase letter, one number and one special character."
+							)
+						);
+
+					return auth
+						.register(user)
+						.then(res => {
+							return resolve(res);
+						})
+						.catch(err => {
+							return reject(new Error(err.message));
+						});
+				});
+			},
+			/* eslint-disable-next-line no-unused-vars */
+			login: ({ commit }, user) => {
+				return new Promise((resolve, reject) => {
+					auth.login(user)
+						.then(() => {
+							return resolve({
+								status: "success",
+								message: "Logged in!"
+							});
+						})
+						.catch(err => {
+							return reject(new Error(err.message));
+						});
+				});
+			},
+			logout: () => {
+				return new Promise((resolve, reject) => {
+					return auth
+						.logout()
+						.then(() => {
+							return resolve();
+						})
+						.catch(() => {
+							return reject();
+						});
+				});
+			},
+			getUsernameFromId: ({ commit, state }, userId) => {
+				return new Promise(resolve => {
+					if (typeof state.userIdMap[`Z${userId}`] !== "string") {
+						if (state.userIdRequested[`Z${userId}`] !== true) {
+							commit("requestingUserId", userId);
+							io.getSocket(socket => {
+								socket.emit(
+									"users.getUsernameFromId",
+									userId,
+									res => {
+										if (res.status === "success") {
+											commit("mapUserId", {
+												userId,
+												username: res.data
+											});
+
+											state.pendingUserIdCallbacks[
+												`Z${userId}`
+											].forEach(cb => cb(res.data));
+
+											commit(
+												"clearPendingCallbacks",
+												userId
+											);
+
+											return resolve(res.data);
+										}
+										return resolve();
+									}
+								);
+							});
+						} else {
+							commit("pendingUsername", {
+								userId,
+								callback: username => {
+									return resolve(username);
+								}
+							});
+						}
+					} else {
+						resolve(state.userIdMap[`Z${userId}`]);
+					}
+				});
+			},
+			authData: ({ commit }, data) => {
+				commit("authData", data);
+			},
+			banUser: ({ commit }, ban) => {
+				commit("banUser", ban);
+			},
+			updateUsername: ({ commit }, username) => {
+				commit("updateUsername", username);
+			}
+		},
+		mutations: {
+			mapUserId(state, data) {
+				state.userIdMap[`Z${data.userId}`] = data.username;
+				state.userIdRequested[`Z${data.userId}`] = false;
+			},
+			requestingUserId(state, userId) {
+				state.userIdRequested[`Z${userId}`] = true;
+				if (!state.pendingUserIdCallbacks[`Z${userId}`])
+					state.pendingUserIdCallbacks[`Z${userId}`] = [];
+			},
+			pendingUsername(state, data) {
+				state.pendingUserIdCallbacks[`Z${data.userId}`].push(
+					data.callback
+				);
+			},
+			clearPendingCallbacks(state, userId) {
+				state.pendingUserIdCallbacks[`Z${userId}`] = [];
+			},
+			authData(state, data) {
+				state.loggedIn = data.loggedIn;
+				state.role = data.role;
+				state.username = data.username;
+				state.userId = data.userId;
+				state.gotData = true;
+			},
+			banUser(state, ban) {
+				state.banned = true;
+				state.ban = ban;
+			},
+			updateUsername(state, username) {
+				state.username = username;
+			}
+		}
+	},
+	playlists: {
+		namespaced: true,
+		state: {
+			editing: ""
+		},
+		getters: {},
+		actions: {
+			editPlaylist: ({ commit }, id) => commit("editPlaylist", id)
+		},
+		mutations: {
+			editPlaylist(state, id) {
+				state.editing = id;
+			}
+		}
+	},
+	preferences: {
+		namespaced: true,
+		state: {
+			nightmode: true
+		},
+		actions: {
+			changeNightmode: ({ commit }, nightmode) => {
+				commit("changeNightmode", nightmode);
+			}
+		},
+		mutations: {
+			changeNightmode(state, nightmode) {
+				state.nightmode = nightmode;
+			}
+		}
+	}
+};
+
+export default {
+	namespaced: true,
+	state,
+	getters,
+	actions,
+	mutations,
+	modules
+};

+ 0 - 0
frontend/styles/colors.scss → frontend/src/styles/colors.scss


+ 0 - 0
frontend/styles/global.scss → frontend/src/styles/global.scss


+ 0 - 0
frontend/validation.js → frontend/src/validation.js


+ 1 - 1
frontend/webpack.common.js

@@ -3,7 +3,7 @@ const WebpackMd5Hash = require("webpack-md5-hash");
 const HtmlWebpackPlugin = require("html-webpack-plugin");
 
 module.exports = {
-	entry: "./main.js",
+	entry: "./src/main.js",
 	output: {
 		path: `${__dirname}/dist/build/`,
 		filename: "[name].[hash].js"

+ 1 - 1
frontend/webpack.dev.js

@@ -13,7 +13,7 @@ module.exports = merge(common, {
 	resolve: {
 		alias: {
 			vue: "vue/dist/vue.js",
-			styles: "styles"
+			styles: "src/styles"
 		}
 	},
 	devServer: {

+ 1 - 1
frontend/webpack.prod.js

@@ -10,7 +10,7 @@ module.exports = merge(common, {
 	resolve: {
 		alias: {
 			vue: "vue/dist/vue.min.js",
-			styles: "styles"
+			styles: "src/styles"
 		}
 	}
 });