Commit b8d024f5 authored by SpinShare's avatar SpinShare

added new navigation

parent ca00bc0b
......@@ -10,6 +10,7 @@ parameters:
avatar_path: "%kernel.project_dir%/public/uploads/avatar"
promo_path: "%kernel.project_dir%/public/uploads/promo"
client_path: "%kernel.project_dir%/public/uploads/client"
thumbnail_path: "%kernel.project_dir%/public/uploads/thumbnail"
temp_path: "%kernel.project_dir%/public/uploads/temp"
services:
......
......@@ -28,38 +28,97 @@ body {
}
main {
display: grid;
margin-left: 60px;
padding-top: 60px;
}
main aside {
background: rgba(255, 255, 255, 0.1);
background: #000;
display: grid;
position: fixed;
z-index: 1000;
top: 0px;
left: 0px;
bottom: 0px;
grid-template-rows: 1fr auto;
right: 0px;
grid-template-columns: 180px auto 1fr auto;
}
main aside .item {
width: 60px;
main aside .logo {
padding: 15px 30px;
height: 60px;
}
main aside .logo img {
height: 100%;
}
main aside nav {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
main aside nav .upload-button {
align-items: center;
justify-content: center;
padding: 0px 15px;
}
main aside nav .item {
min-width: 60px;
height: 60px;
opacity: 0.4;
display: flex;
justify-content: center;
align-items: center;
background: transparent;
border-bottom: 2px solid transparent;
color: #fff;
transition: 0.2s ease opacity, 0.2s ease background;
}
main aside .item:hover {
opacity: 1;
main aside nav .item:hover {
cursor: pointer;
}
main aside .item.active {
main aside nav .item:hover .mdi {
opacity: 1;
background: #e22c78;
}
main aside .item .mdi {
main aside nav .item.active {
border-color: #e22c78;
}
main aside nav .item.active .mdi {
opacity: 1;
}
main aside nav .item .mdi {
font-size: 22px;
opacity: 0.4;
}
main aside nav .user-avatar {
width: 32px;
height: 32px;
background-position: center;
background-size: cover;
border-radius: 50px;
}
main aside .search {
align-self: center;
justify-self: center;
}
main aside .search input {
width: 100%;
font-family: 'Open Sans', sans-serif;
font-size: 14px;
background: transparent;
color: #fff;
border-radius: 4px;
padding: 9px 20px;
background: rgba(255, 255, 255, 0.15);
border: 0px;
transition: 0.2s ease-in-out all;
min-width: 500px;
}
main aside .search input:hover {
background: rgba(255, 255, 255, 0.3);
color: #fff;
}
main aside .search input:focus {
outline: 0;
background: rgba(255, 255, 255, 0.3);
}
main aside .search input::placeholder {
color: rgba(255, 255, 255, 0.5);
}
section.section-startup {
padding: 50px;
......@@ -86,6 +145,7 @@ button,
button:hover,
.button:hover {
opacity: 0.6;
text-decoration: none;
}
button:focus,
.button:focus {
......@@ -342,3 +402,28 @@ input[type="range"]::-ms-fill-lower {
.user-item.inactive {
box-shadow: 0px 2px 10px 5px rgba(0, 0, 0, 0.2);
}
@media screen and (max-width: 550px) {
.song-row .song-list {
grid-template-columns: repeat(1, 1fr);
}
}
@media screen and (min-width: 550px) and (max-width: 780px) {
.song-row .song-list {
grid-template-columns: repeat(2, 1fr);
}
}
@media screen and (min-width: 780px) and (max-width: 1000px) {
.song-row .song-list {
grid-template-columns: repeat(3, 1fr);
}
}
@media screen and (min-width: 1000px) and (max-width: 1400px) {
.song-row .song-list {
grid-template-columns: repeat(4, 1fr);
}
}
@media screen and (min-width: 1400px) {
.song-row .song-list {
grid-template-columns: repeat(6, 1fr);
}
}
......@@ -26,39 +26,103 @@ body {
}
main {
display: grid;
margin-left: 60px;
padding-top: 60px;
& aside {
background: rgba(255,255,255,0.1);
background: #000;
display: grid;
position: fixed;
z-index: 1000;
top: 0px;
left: 0px;
bottom: 0px;
grid-template-rows: 1fr auto;
right: 0px;
grid-template-columns: 180px auto 1fr auto;
& .item {
width: 60px;
& .logo {
padding: 15px 30px;
height: 60px;
opacity: 0.4;
& img {
height: 100%;
}
}
& nav {
display: flex;
justify-content: center;
flex-direction: row;
align-items: center;
background: transparent;
color :#fff;
transition: 0.2s ease opacity, 0.2s ease background;
justify-content: center;
& .upload-button {
align-items: center;
justify-content: center;
padding: 0px 15px;
}
& .item {
min-width: 60px;
height: 60px;
display: flex;
justify-content: center;
align-items: center;
background: transparent;
border-bottom: 2px solid transparent;
color :#fff;
transition: 0.2s ease opacity, 0.2s ease background;
&:hover {
cursor: pointer;
&:hover {
opacity: 1;
cursor: pointer;
& .mdi {
opacity: 1;
}
}
&.active {
border-color: rgb(226, 44, 120);
& .mdi {
opacity: 1;
}
}
& .mdi {
font-size: 22px;
opacity: 0.4;
}
}
&.active {
opacity: 1;
background: rgb(226, 44, 120);
& .user-avatar {
width: 32px;
height: 32px;
background-position: center;
background-size: cover;
border-radius: 50px;
}
& .mdi {
font-size: 22px;
}
& .search {
align-self: center;
justify-self: center;
input {
width: 100%;
font-family: 'Open Sans', sans-serif;
font-size: 14px;
background: transparent;
color: #fff;
border-radius: 4px;
padding: 9px 20px;
background: rgba(255,255,255,0.15);
border: 0px;
transition: 0.2s ease-in-out all;
min-width: 500px;
&:hover {
background: rgba(255,255,255,0.3);
color: #fff;
}
&:focus {
outline: 0;
background: rgba(255,255,255,0.3);
}
&::placeholder {
color: rgba(255,255,255,0.5);
}
}
}
}
......@@ -90,6 +154,7 @@ button, .button {
&:hover {
opacity: 0.6;
text-decoration: none;
}
&:focus {
outline: 0;
......@@ -370,4 +435,39 @@ input[type="range"]::-ms-fill-lower {
&.inactive {
box-shadow: 0px 2px 10px 5px rgba(0, 0, 0, 0.2);
}
}
@media screen and (max-width: 550px) {
.song-row {
& .song-list {
grid-template-columns: repeat(1, 1fr);
}
}
}
@media screen and (min-width: 550px) and (max-width: 780px) {
.song-row {
& .song-list {
grid-template-columns: repeat(2, 1fr);
}
}
}
@media screen and (min-width: 780px) and (max-width: 1000px) {
.song-row {
& .song-list {
grid-template-columns: repeat(3, 1fr);
}
}
}
@media screen and (min-width: 1000px) and (max-width: 1400px) {
.song-row {
& .song-list {
grid-template-columns: repeat(4, 1fr);
}
}
}
@media screen and (min-width: 1400px) {
.song-row {
& .song-list {
grid-template-columns: repeat(6, 1fr);
}
}
}
\ No newline at end of file
.section-moderator-dashboard {
.section-moderator-dashboard header {
background: rgba(0, 0, 0, 0.5);
padding: 50px;
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 25px;
padding-bottom: 0px;
}
.section-moderator-dashboard header .title {
font-size: 32px;
letter-spacing: 0.05em;
text-transform: uppercase;
margin-bottom: 15px;
font-family: 'Oswald', sans-serif;
}
.section-moderator-dashboard header .tabs {
display: flex;
}
.section-moderator-dashboard header .tabs .tab {
font-size: 14px;
font-weight: bold;
text-transform: uppercase;
letter-spacing: 0.25em;
padding: 15px 40px;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
background: rgba(0, 0, 0, 0.6);
color: rgba(255, 255, 255, 0.4);
transition: 0.2s ease-in-out all;
text-decoration: none;
}
.section-moderator-dashboard header .tabs .tab:not(.active):hover {
cursor: pointer;
background: #272c2e;
color: rgba(255, 255, 255, 0.75);
}
.section-moderator-dashboard header .tabs .tab.active {
opacity: 1;
color: #ffffff;
background: #212629;
}
.section-moderator-dashboard .box {
background: rgba(255, 255, 255, 0.1);
......@@ -44,6 +76,9 @@
padding: 10px;
border: 1px solid #000;
}
.section-moderator-list {
padding: 50px;
}
.section-moderator-add {
padding: 50px;
}
......
.section-moderator-dashboard {
padding: 50px;
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 25px;
& header {
background: rgba(0,0,0,0.5);
padding: 50px;
padding-bottom: 0px;
& .title {
font-size: 32px;
letter-spacing: 0.05em;
text-transform: uppercase;
margin-bottom: 15px;
font-family: 'Oswald', sans-serif;
}
& .tabs {
display: flex;
& .tab {
font-size: 14px;
font-weight: bold;
text-transform: uppercase;
letter-spacing: 0.25em;
padding: 15px 40px;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
background: rgba(0,0,0,0.6);
color: rgba(255,255,255,0.4);
transition: 0.2s ease-in-out all;
text-decoration: none;
&:not(.active):hover {
cursor: pointer;
background: #272c2e;
color: rgba(255,255,255,0.75);
}
&.active {
opacity: 1;
color: rgba(255,255,255,1);
background: #212629;
}
}
}
}
& .box {
background: rgba(255,255,255,0.1);
......@@ -48,6 +85,9 @@
}
}
}
.section-moderator-list {
padding: 50px;
}
.section-moderator-add {
padding: 50px;
......
......@@ -36,17 +36,17 @@
color: #fff;
border-radius: 4px;
padding: 9px 20px;
background: rgba(255, 255, 255, 0.2);
background: rgba(255, 255, 255, 0.15);
border: 0px;
transition: 0.2s ease-in-out all;
}
.section-search header .actions input:hover {
background: rgba(255, 255, 255, 0.1);
background: rgba(255, 255, 255, 0.3);
color: #fff;
}
.section-search header .actions input:focus {
outline: 0;
border-color: rgba(255, 255, 255, 0.6);
background: rgba(255, 255, 255, 0.3);
}
.section-search header .actions input::placeholder {
color: rgba(255, 255, 255, 0.6);
......
......@@ -37,17 +37,17 @@
color: #fff;
border-radius: 4px;
padding: 9px 20px;
background: rgba(255,255,255,0.2);
background: rgba(255,255,255,0.15);
border: 0px;
transition: 0.2s ease-in-out all;
&:hover {
background: rgba(255,255,255,0.1);
background: rgba(255,255,255,0.3);
color: #fff;
}
&:focus {
outline: 0;
border-color: rgba(255,255,255,0.6);
background: rgba(255,255,255,0.3);
}
&::placeholder {
color: rgba(255,255,255,0.6);
......
......@@ -9,7 +9,7 @@
background-size: cover;
position: absolute;
top: 0px;
left: 60px;
left: 0px;
right: 0px;
height: 300px;
z-index: -1;
......
......@@ -9,7 +9,7 @@
background-size: cover;
position: absolute;
top: 0px;
left: 60px;
left: 0px;
right: 0px;
height: 300px;
z-index: -1;
......
.blm-banner {
background: rgba(255, 255, 255, 0.1);
padding: 20px;
border-radius: 4px;
display: grid;
grid-template-columns: 40px 1fr auto;
grid-gap: 15px;
border: 2px solid rgba(255, 255, 255, 0.4);
margin-bottom: 50px;
align-items: center;
}
.blm-banner .icon {
width: 40px;
height: 40px;
.section-startup .tabs {
display: flex;
justify-content: center;
align-items: center;
}
.blm-banner .icon img {
max-width: 100%;
max-height: 100%;
margin-bottom: 25px;
}
.blm-banner .text h1 {
margin: 0;
letter-spacing: 0.25em;
font-size: 14px;
.section-startup .tabs a {
color: inherit;
text-decoration: none;
font-weight: bold;
letter-spacing: 0.1em;
padding: 10px 15px;
margin: 0px 5px;
text-align: center;
text-transform: uppercase;
}
.blm-banner .text .copy {
opacity: 0.6;
line-height: 1.5;
transition: 0.2s ease-in-out background, 0.2s ease-in-out opacity;
}
.section-startup .tabs a span {
display: block;
transition: 0.2s ease-in-out transform;
transform: translateY(4px);
}
.section-startup .tabs a:hover {
background: rgba(255, 255, 255, 0.2);
border-radius: 5px;
}
.section-startup .tabs a:after {
transition: 0.2s ease-in-out background;
margin: 0 auto;
margin-top: 5px;
width: 20px;
height: 3px;
border-radius: 5px;
background: transparent;
content: "";
display: block;
}
.section-startup .tabs a.active {
opacity: 1;
}
.section-startup .tabs a.active span {
transform: translateY(0px);
}
.section-startup .tabs a.active:after {
background: linear-gradient(135deg, #fd2f85, #7a34ec);
}
.staff-promos {
display: grid;
......@@ -81,6 +94,42 @@
cursor: pointer;
opacity: 0.6;
}
.song-row-new {
margin-bottom: 25px;
.social-buttons {
display: grid;
width: 650px;
margin: 0 auto;
margin-top: 25px;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
grid-gap: 15px;
}
.social-buttons .item {
height: 75px;
display: flex;
color: #fff;
justify-content: center;
align-items: center;
font-size: 32px;
background: rgba(255, 255, 255, 0.2);
border-radius: 6px;
transition: 0.2s ease-in-out all;
}
.social-buttons .item.item-discord {
background: linear-gradient(135deg, #99aab5, #7289da);
}
.social-buttons .item.item-twitter {
background: linear-gradient(135deg, #d0e6f7, #1da1f2);
}
.social-buttons .item.item-youtube {
background: linear-gradient(135deg, #ff0000, #c20000);
}
.social-buttons .item.item-twitch {
background: linear-gradient(135deg, #b9a3e3, #6441a5);
}
.social-buttons .item.item-patreon {
background: linear-gradient(135deg, #ff8575, #e75744);
}
.social-buttons .item:hover {
transform: scale(1.1);
box-shadow: 0px 4px 16px rgba(0, 0, 0, 0.4);
cursor: pointer;
}
.blm-banner {
background: rgba(255,255,255,0.1);
padding: 20px;
border-radius: 4px;
display: grid;
grid-template-columns: 40px 1fr auto;
grid-gap: 15px;
border: 2px solid rgba(255,255,255,0.4);
margin-bottom: 50px;
align-items: center;
& .icon {
width: 40px;
height: 40px;
.section-startup {
& .tabs {
display: flex;
justify-content: center;
align-items: center;
& img {
max-width: 100%;
max-height: 100%;
}
}
margin-bottom: 25px;
& .text {
h1 {
margin: 0;
letter-spacing: 0.25em;
font-size: 14px;
& a {
color: inherit;
text-decoration: none;
font-weight: bold;
letter-spacing: 0.1em;
padding: 10px 15px;
margin: 0px 5px;
text-align: center;
text-transform: uppercase;
}
& .copy {
opacity: 0.6;
line-height: 1.5;
transition: 0.2s ease-in-out background, 0.2s ease-in-out opacity;
& span {
display: block;
transition: 0.2s ease-in-out transform;
transform: translateY(4px);
}
&:hover {
background: rgba(255,255,255,0.2);
border-radius: 5px;
}
&:after {
transition: 0.2s ease-in-out background;
margin: 0 auto;
margin-top: 5px;
width: 20px;
height: 3px;
border-radius: 5px;
background: transparent;
content: "";
display: block;
}
&.active {
opacity: 1;
& span {
transform: translateY(0px);
}
&:after {
background: linear-gradient(135deg, #fd2f85, #7a34ec);
}
}
}
}
}
.staff-promos {
display: grid;
grid-template-columns: 1fr 1fr;
......@@ -90,6 +105,45 @@
}
}
}
.song-row-new {
margin-bottom: 25px;
.social-buttons {
display: grid;
width: 650px;
margin: 0 auto;
margin-top: 25px;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
grid-gap: 15px;
& .item {
height: 75px;
display: flex;
color: #fff;
justify-content: center;
align-items: center;
font-size: 32px;
background: rgba(255,255,255,0.2);
border-radius: 6px;
transition: 0.2s ease-in-out all;
&.item-discord {
background: linear-gradient(135deg, #99aab5, #7289da);
}
&.item-twitter {
background: linear-gradient(135deg, #d0e6f7, #1da1f2);
}
&.item-youtube {
background: linear-gradient(135deg, #ff0000, #c20000);
}
&.item-twitch {
background: linear-gradient(135deg, #b9a3e3, #6441a5);
}
&.item-patreon {
background: linear-gradient(135deg, #ff8575, #e75744);
}
&:hover {
transform: scale(1.1);
box-shadow: 0px 4px 16px rgba(0,0,0,0.4);
cursor: pointer;
}
}
}
\ No newline at end of file
This diff is collapsed.
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 828.37 200" style="enable-background:new 0 0 828.37 200;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FB1357;}
.st1{fill:#25A7FB;}
.st2{fill:#3DFB84;}
.st3{fill:#FFFFFF;}
</style>
<g>
<path class="st0" d="M100,190V10c0-5.52-4.48-10-10-10S80,4.48,80,10v180c0,5.52,4.48,10,10,10S100,195.52,100,190z"/>
<path class="st1" d="M130,25c-5.52,0-10,4.48-10,10v130c0,5.52,4.48,10,10,10s10-4.48,10-10V35C140,29.48,135.52,25,130,25z"/>
<path class="st2" d="M170,50c-5.52,0-10,4.48-10,10v80c0,5.52,4.48,10,10,10s10-4.48,10-10V60C180,54.48,175.52,50,170,50z"/>
<path class="st2" d="M10,150c5.52,0,10-4.48,10-10V60c0-5.52-4.48-10-10-10S0,54.48,0,60v80C0,145.52,4.48,150,10,150z"/>
<path class="st1" d="M50,25c-5.52,0-10,4.48-10,10v130c0,5.52,4.48,10,10,10s10-4.48,10-10V35C60,29.48,55.52,25,50,25z"/>
</g>
<g>
<path class="st3" d="M288.83,138.84c-6.79,7.36-17.55,10.19-27.17,10.19c-8.49,0-17.26-1.42-24.9-5.09
c-4.53-2.26-7.92-6.23-7.92-11.6c0-4.81,4.24-9.62,9.34-9.62c1.98,0,3.68,0.28,5.38,0.85l7.64,2.83c3.11,1.41,6.79,2.26,10.47,2.26
c5.66,0,11.89-3.4,11.89-9.91c0-2.83-1.13-5.38-3.4-6.79c-4.53-2.83-10.19-4.25-15.28-5.66c-14.43-4.24-25.47-9.06-25.47-26.32
c0-18.96,16.7-30.28,34.24-30.28c8.49,0,26.6,2.26,26.6,13.3c0,5.94-4.25,10.75-9.9,10.75c-1.13,0-2.26-0.28-3.4-0.57l-3.96-1.41
c-3.11-1.13-6.51-1.7-9.62-1.7c-4.81,0-10.75,2.26-10.75,7.64c0,4.81,4.81,7.07,8.77,8.21l5.66,1.41
c15.28,4.25,29.71,10.75,29.71,28.3C296.76,123.84,294.49,132.62,288.83,138.84z"/>
<path class="st3" d="M342.32,147.9c-6.51,0-11.32-2.26-16.13-6.23v22.64c0,6.23-3.68,11.6-10.47,11.6
c-6.51,0-10.47-5.38-10.47-11.6v-78.1c0-6.23,2.83-12.45,9.9-12.45c5.66,0,8.21,3.11,10.19,7.92c4.53-5.09,10.19-8.21,17.26-8.21
c7.92,0,15,2.26,20.66,7.92c7.36,7.07,11.32,17.55,11.32,27.73C374.58,128.37,363.55,147.9,342.32,147.9z M340.34,92.71
c-9.9,0-15,9.06-15,17.83c0,8.77,5.09,18.11,15,18.11c8.77,0,13.58-9.91,13.58-18.11C353.92,102.62,349.11,92.71,340.34,92.71z"/>
<path class="st3" d="M392.98,66.96c-6.79,0-12.17-5.66-12.17-12.17s5.38-12.17,12.17-12.17c6.51,0,11.89,5.66,11.89,12.17
S399.49,66.96,392.98,66.96z M392.7,147.61c-6.51,0-10.47-5.66-10.47-11.89V85.36c0-6.23,3.68-11.6,10.47-11.6
c6.51,0,10.47,5.38,10.47,11.6v50.37C403.17,142.24,399.49,147.61,392.7,147.61z"/>
<path class="st3" d="M469.1,147.61c-6.51,0-10.47-5.66-10.47-11.89v-31.41c0-7.07-3.96-13.02-11.89-13.02
c-6.51,0-11.32,5.94-11.32,12.17v32.26c0,6.51-3.68,11.89-10.47,11.89c-6.51,0-10.47-5.66-10.47-11.89V85.92
c0-6.23,3.4-11.89,10.19-12.17h0.57c4.53,0,7.92,3.11,9.62,7.36c5.66-5.38,11.04-7.64,18.96-7.64c6.51,0,13.02,1.7,18.11,6.23
c6.23,5.38,7.64,11.89,7.64,19.81v36.22C479.57,142.24,475.9,147.61,469.1,147.61z"/>
<path class="st3" d="M547.78,138.84c-6.79,7.36-17.54,10.19-27.17,10.19c-8.49,0-17.26-1.42-24.9-5.09
c-4.53-2.26-7.92-6.23-7.92-11.6c0-4.81,4.25-9.62,9.34-9.62c1.98,0,3.68,0.28,5.38,0.85l7.64,2.83c3.11,1.41,6.79,2.26,10.47,2.26
c5.66,0,11.89-3.4,11.89-9.91c0-2.83-1.13-5.38-3.4-6.79c-4.53-2.83-10.19-4.25-15.28-5.66c-14.43-4.24-25.47-9.06-25.47-26.32
c0-18.96,16.7-30.28,34.24-30.28c8.49,0,26.6,2.26,26.6,13.3c0,5.94-4.25,10.75-9.9,10.75c-1.13,0-2.26-0.28-3.4-0.57l-3.96-1.41
c-3.11-1.13-6.51-1.7-9.62-1.7c-4.81,0-10.75,2.26-10.75,7.64c0,4.81,4.81,7.07,8.77,8.21l5.66,1.41
c15.28,4.25,29.71,10.75,29.71,28.3C555.7,123.84,553.44,132.62,547.78,138.84z"/>
<path class="st3" d="M619.09,147.61c-6.51,0-10.47-5.66-10.47-11.89v-30.28c0-7.36-3.11-14.15-11.88-14.15
c-6.79,0-11.6,6.23-11.6,12.73v31.69c0,6.51-3.68,11.89-10.47,11.89c-6.51,0-10.47-5.66-10.47-11.89v-81.5
c0-6.23,3.68-11.6,10.47-11.6c6.51,0,10.47,5.38,10.47,11.6v25.19c5.66-3.4,11.89-5.94,18.68-5.94s13.58,1.98,18.68,6.79
c5.66,5.38,7.07,11.89,7.07,19.53v35.94C629.56,142.24,625.89,147.61,619.09,147.61z"/>
<path class="st3" d="M696.07,147.61c-5.09,0-8.49-3.96-9.9-8.49c-5.09,5.94-9.62,8.77-17.55,8.77c-7.36,0-14.71-3.11-20.38-7.92
c-8.49-7.64-12.17-18.39-12.17-29.43c0-10.75,3.11-20.09,10.75-27.73c5.66-5.66,13.3-9.62,21.51-9.62c7.64,0,12.45,2.83,17.83,8.21
c1.98-4.25,5.09-7.64,10.19-7.64c5.94,0,10.47,4.81,10.47,10.75v50.66C706.82,141.67,702.86,147.61,696.07,147.61z M670.6,92.71
c-9.34,0-13.87,9.34-13.87,17.55c0,8.49,3.96,18.11,13.87,18.11c9.62,0,15-8.49,15-17.26C685.6,101.49,681.36,92.71,670.6,92.71z"
/>
<path class="st3" d="M751.82,93.56c-3.68,1.42-7.64,2.83-11.04,5.38c-2.55,1.98-3.11,5.09-3.11,8.49v28.3
c0,6.51-3.68,11.89-10.47,11.89c-6.51,0-10.47-5.66-10.47-11.89V85.64c0-2.83,0.57-5.94,2.55-8.21c1.98-2.26,4.81-3.68,7.64-3.68
c5.09,0,8.49,2.83,10.75,7.36c3.68-3.68,8.21-7.64,13.87-7.64c5.94,0,11.04,4.24,11.04,9.9C762.57,90.17,757.2,91.86,751.82,93.56z
"/>
<path class="st3" d="M819.32,117.33h-38.77c1.42,3.68,3.11,6.79,6.23,9.06c2.83,2.26,6.23,3.4,9.91,3.4c3.96,0,7.92-1.13,11.6-2.83
l5.94-3.11c1.13-0.57,2.55-0.85,3.96-0.85h0.28c4.53,0,8.77,4.25,8.77,8.49c0,4.81-4.81,8.49-8.49,10.47
c-7.08,4.25-15,5.94-23.21,5.94c-11.32,0-22.07-4.53-29.43-13.3c-5.94-7.36-7.92-15.28-7.92-24.34c0-20.09,15.56-37.07,35.94-37.07
c19.53,0,34.24,15.85,34.24,34.81C828.37,114.5,825.82,117.33,819.32,117.33z M793.85,90.17c-7.92,0-11.6,6.23-13.87,13.02H808
C806.02,96.11,802.34,90.17,793.85,90.17z"/>
</g>
</svg>
......@@ -123,7 +123,7 @@ class APIController extends AbstractController
$oneResult['hasHardDifficulty'] = $result->getHasHardDifficulty();
$oneResult['hasExtremeDifficulty'] = $result->getHasExtremeDifficulty();
$oneResult['hasXDDifficulty'] = $result->getHasXDDifficulty();
$oneResult['cover'] = $baseUrl."/uploads/cover/".$result->getFileReference().".png";
$oneResult['cover'] = $baseUrl."/uploads/thumbnail/".$result->getFileReference().".jpg";
$oneResult['zip'] = $this->generateUrl('api.songs.download', array('id' => $result->getId()), UrlGeneratorInterface::ABSOLUTE_URL);
$data[] = $oneResult;
......@@ -158,7 +158,7 @@ class APIController extends AbstractController
$oneResult['hasHardDifficulty'] = $result->getHasHardDifficulty();
$oneResult['hasExtremeDifficulty'] = $result->getHasExtremeDifficulty();
$oneResult['hasXDDifficulty'] = $result->getHasXDDifficulty();
$oneResult['cover'] = $baseUrl."/uploads/cover/".$result->getFileReference().".png";
$oneResult['cover'] = $baseUrl."/uploads/thumbnail/".$result->getFileReference().".jpg";
$oneResult['zip'] = $this->generateUrl('api.songs.download', array('id' => $result->getId()), UrlGeneratorInterface::ABSOLUTE_URL);
$data[] = $oneResult;
......@@ -193,7 +193,7 @@ class APIController extends AbstractController
$oneResult['hasHardDifficulty'] = $result->getHasHardDifficulty();
$oneResult['hasExtremeDifficulty'] = $result->getHasExtremeDifficulty();
$oneResult['hasXDDifficulty'] = $result->getHasXDDifficulty();
$oneResult['cover'] = $baseUrl."/uploads/cover/".$result->getFileReference().".png";
$oneResult['cover'] = $baseUrl."/uploads/thumbnail/".$result->getFileReference().".jpg";
$oneResult['zip'] = $this->generateUrl('api.songs.download', array('id' => $result->getId()), UrlGeneratorInterface::ABSOLUTE_URL);
$data[] = $oneResult;
......@@ -245,7 +245,7 @@ class APIController extends AbstractController
$data['tags'] = $result->getTagsArray();
$data['fileReference'] = $result->getFileReference();
$data['paths']['ogg'] = $baseUrl."/uploads/audio/".$result->getFileReference()."_0.ogg";
$data['paths']['cover'] = $baseUrl."/uploads/cover/".$result->getFileReference().".png";
$data['paths']['cover'] = $baseUrl."/uploads/thumbnail/".$result->getFileReference().".jpg";
$data['paths']['zip'] = $this->generateUrl('api.songs.download', array('id' => $result->getId()), UrlGeneratorInterface::ABSOLUTE_URL);
$data['description'] = $result->getDescription();
$data['views'] = $result->getViews();
......@@ -462,7 +462,7 @@ class APIController extends AbstractController
$oneResult['hasHardDifficulty'] = $result->getHasHardDifficulty();
$oneResult['hasExtremeDifficulty'] = $result->getHasExtremeDifficulty();
$oneResult['hasXDDifficulty'] = $result->getHasXDDifficulty();
$oneResult['cover'] = $baseUrl."/uploads/cover/".$result->getFileReference().".png";
$oneResult['cover'] = $baseUrl."/uploads/thumbnail/".$result->getFileReference().".jpg";
$oneResult['zip'] = $this->generateUrl('api.songs.download', array('id' => $result->getId()), UrlGeneratorInterface::ABSOLUTE_URL);
$data['songs'][] = $oneResult;
......@@ -535,7 +535,7 @@ class APIController extends AbstractController
$oneResult['hasHardDifficulty'] = $result->getHasHardDifficulty();
$oneResult['hasExtremeDifficulty'] = $result->getHasExtremeDifficulty();
$oneResult['hasXDDifficulty'] = $result->getHasXDDifficulty();
$oneResult['cover'] = $baseUrl."/uploads/cover/".$result->getFileReference().".png";
$oneResult['cover'] = $baseUrl."/uploads/thumbnail/".$result->getFileReference().".jpg";
$oneResult['zip'] = $this->generateUrl('api.songs.download', array('id' => $result->getId()), UrlGeneratorInterface::ABSOLUTE_URL);
$data['songs'][] = $oneResult;
......@@ -574,7 +574,7 @@ class APIController extends AbstractController
$oneResult['hasHardDifficulty'] = $result->getHasHardDifficulty();
$oneResult['hasExtremeDifficulty'] = $result->getHasExtremeDifficulty();
$oneResult['hasXDDifficulty'] = $result->getHasXDDifficulty();
$oneResult['cover'] = $baseUrl."/uploads/cover/".$result->getFileReference().".png";
$oneResult['cover'] = $baseUrl."/uploads/thumbnail/".$result->getFileReference().".jpg";
$oneResult['zip'] = $this->generateUrl('api.songs.download', array('id' => $result->getId()), UrlGeneratorInterface::ABSOLUTE_URL);
$data['songs'][] = $oneResult;
......
......@@ -24,22 +24,73 @@ class IndexController extends AbstractController
$data = [];
$activePromos = $em->getRepository(Promo::class)->findBy(array('isVisible' => true), array('id' => 'DESC'), 2);
$data['promos'] = $activePromos;
$newOffset = $request->query->get('newOffset');
/* $newOffset = $request->query->get('newOffset');
$popularOffset = $request->query->get('popularOffset');
$resultsNewSongs = $em->getRepository(Song::class)->findBy(array(), array('id' => 'DESC'), 6, $newOffset * 6);
$resultsPopularSongs = $em->getRepository(Song::class)->findBy(array(), array('downloads' => 'DESC', 'views' => 'DESC'), 6, $popularOffset * 6);
$data['promos'] = $activePromos;
$data['newSongs'] = $resultsNewSongs;
$data['newOffset'] = $newOffset;
$data['popularSongs'] = $resultsPopularSongs;
$data['popularOffset'] = $popularOffset;
$data['popularOffset'] = $popularOffset; */
return $this->render('index/index.html.twig', $data);
}
/**
* @Route("/new", name="index.new")
*/
public function new(Request $request)
{
$em = $this->getDoctrine()->getManager();
$data = [];
$newOffset = $request->query->get('newOffset') ? $request->query->get('newOffset') : 0;
$resultsNewSongs = $em->getRepository(Song::class)->getNew($newOffset);
$data['newSongs'] = $resultsNewSongs;
$data['newOffset'] = $newOffset;
return $this->render('index/new.html.twig', $data);
}
/**
* @Route("/hot", name="index.hot")
*/
public function hot(Request $request)
{
$em = $this->getDoctrine()->getManager();
$data = [];
$hotOffset = $request->query->get('hotOffset') ? $request->query->get('hotOffset') : 0;
$resultsHotSongs = $em->getRepository(Song::class)->getHot($hotOffset);
$data['hotSongs'] = $resultsHotSongs;
$data['hotOffset'] = $hotOffset;
return $this->render('index/hot.html.twig', $data);
}
/**
* @Route("/popular", name="index.popular")
*/
public function popular(Request $request)
{
$em = $this->getDoctrine()->getManager();
$data = [];
$popularOffset = $request->query->get('popularOffset') ? $request->query->get('popularOffset') : 0;
$resultsPopularSongs = $em->getRepository(Song::class)->getPopular($popularOffset);
$data['popularSongs'] = $resultsPopularSongs;
$data['popularOffset'] = $popularOffset;
return $this->render('index/popular.html.twig', $data);
}
/**
* @Route("/support", name="index.support")
*/
......
<?php
namespace App\Controller\Moderation;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use App\Entity\ClientRelease;
use App\Entity\Song;
use App\Entity\User;
use App\Entity\SongReport;
use App\Entity\UserReport;
use App\Entity\Promo;
class ClientReleasesController extends AbstractController
{
/**
* @Route("/moderation/clientReleases/", name="moderation.clientreleases.index")
*/
public function clientReleasesIndex(Request $request)
{
$em = $this->getDoctrine()->getManager();
$data = [];
$clientReleases = $em->getRepository(ClientRelease::class)->findBy(array(), array('uploadDate' => 'DESC'));
$data['clientReleases'] = $clientReleases;
return $this->render('moderation/clientReleases/index.html.twig', $data);
}
/**
* @Route("/moderation/clientReleases/add", name="moderation.clientreleases.add")
*/
public function clientReleasesAdd(Request $request)
{
$em = $this->getDoctrine()->getManager();
$data = [];
$form = $this->createFormBuilder()
->add('executableFile', FileType::class, ['label' => 'Executable File', 'attr' => array('accept' => '.exe, .dmg')])
->add('majorVersion', TextType::class, ['label' => 'Major Version'])
->add('minorVersion', TextType::class, ['label' => 'Minor Version'])
->add('patchVersion', TextType::class, ['label' => 'Patch Version'])
->add('platform', ChoiceType::class, ['label' => 'Platform', 'choices' => array('Windows' => 'win32', 'Mac' => 'darwin')])
->add('save', SubmitType::class, ['label' => 'Release'])
->getForm();
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
try {
$newRelease = new ClientRelease();
$newRelease->setMajorVersion($data['majorVersion']);
$newRelease->setMinorVersion($data['minorVersion']);
$newRelease->setPatchVersion($data['patchVersion']);
$newRelease->setPlatform($data['platform']);
$newRelease->setUploadDate(new \DateTime());
$fileEnding = "";
switch($data['platform']) {
case "win32":
$fileEnding = ".exe";
break;
case "darwin":
$fileEnding = ".dmg";
break;
}
$newFilename = "SpinShare_".$data['platform']."_".$data['majorVersion']."_".$data['minorVersion']."_".$data['patchVersion'].$fileEnding;
$data['executableFile']->move($this->getParameter('client_path'), $newFilename);
$newRelease->setFileReference($newFilename);
$em->persist($newRelease);
$em->flush();
return $this->redirectToRoute('moderation.index');
} catch(FileException $e) {
}
}
$data['addForm'] = $form->createView();
return $this->render('moderation/clientReleases/add.html.twig', $data);
}
/**
* @Route("/moderation/clientReleases/remove/{releaseId}", name="moderation.clientreleases.remove")
*/
public function clientReleasesRemove(Request $request, int $releaseId)
{
$em = $this->getDoctrine()->getManager();
$data = [];
$releaseToRemove = $em->getRepository(ClientRelease::class)->findOneBy(array('id' => $releaseId));
// Remove EXE file
try {
$fileToRemove = glob($this->getParameter('client_path').DIRECTORY_SEPARATOR.$releaseToRemove->getFileReference());
if(count($fileToRemove) > 0) {
@unlink($fileToRemove[0]);
}
} catch(FileException $e) {
}
// Remove Entity
$em->remove($releaseToRemove);
$em->flush();
return $this->redirectToRoute('moderation.index');
}
}
<?php
namespace App\Controller\Moderation;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use App\Entity\ClientRelease;
use App\Entity\Song;
use App\Entity\User;
use App\Entity\SongReport;
use App\Entity\UserReport;
use App\Entity\Promo;
class ModerationController extends AbstractController
{
/**
* @Route("/moderation", name="moderation.index")
*/
public function index(Request $request)
{
return $this->redirectToRoute('moderation.reports.user.index');
}
}
<?php
namespace App\Controller\Moderation;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use App\Entity\Promo;
class PromosController extends AbstractController
{
/**
* @Route("/moderation/promos/", name="moderation.promos.index")
*/
public function promosIndex(Request $request)
{
$em = $this->getDoctrine()->getManager();
$data = [];
$promos = $em->getRepository(Promo::class)->findBy(array(), array('id' => 'DESC'));
$data['promos'] = $promos;
return $this->render('moderation/promos/index.html.twig', $data);
}
/**
* @Route("/moderation/promos/add", name="moderation.promos.add")
*/
public function promosAdd(Request $request)
{
$em = $this->getDoctrine()->getManager();
$data = [];
$form = $this->createFormBuilder()
->add('imagePath', FileType::class, ['label' => 'Banner File (550x256px)', 'attr' => array('accept' => '.png, .jpg, .jpeg')])
->add('title', TextType::class, ['label' => 'Title'])
->add('type', TextType::class, ['label' => 'Type'])
->add('textColor', TextType::class, ['label' => 'Text Color'])
->add('color', TextType::class, ['label' => 'Primary Color'])
->add('buttonType', ChoiceType::class, ['label' => 'Button Type', 'choices' => array('Song' => 0, 'Playlist (Unused)' => 1, 'Search Query' => 2, 'External' => 3)])
->add('buttonData', TextType::class, ['label' => 'Button Data'])
->add('isVisible', ChoiceType::class, ['label' => 'Is Visible?', 'choices' => array('Yes' => true, 'No' => false)])
->add('save', SubmitType::class, ['label' => 'Save'])
->getForm();
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
try {
$newPromo = new Promo();
$newPromo->setTitle($data['title']);
$newPromo->setType($data['type']);
$newPromo->setTextColor($data['textColor']);
$newPromo->setColor($data['color']);
$newPromo->setButtonType($data['buttonType']);
$newPromo->setButtonData($data['buttonData']);
$newPromo->setIsVisible($data['isVisible']);
$newFilename = "promo_".uniqid().".png";
$data['imagePath']->move($this->getParameter('promo_path'), $newFilename);
$newPromo->setImagePath($newFilename);
$em->persist($newPromo);
$em->flush();
return $this->redirectToRoute('moderation.index');
} catch(FileException $e) {
}
}
$data['addForm'] = $form->createView();
return $this->render('moderation/promos/add.html.twig', $data);
}
/**
* @Route("/moderation/promos/edit/{promoId}", name="moderation.promos.edit")
*/
public function promosEdit(Request $request, int $promoId)
{
$em = $this->getDoctrine()->getManager();
$data = [];
$promo = $em->getRepository(Promo::class)->findOneBy(array('id' => $promoId));
$form = $this->createFormBuilder()
->add('imagePath', FileType::class, ['label' => 'New Banner File (550x256px)', 'attr' => array('accept' => '.png, .jpg, .jpeg'), 'required' => false])
->add('title', TextType::class, ['label' => 'Title', 'data' => $promo->getTitle()])
->add('type', TextType::class, ['label' => 'Type', 'data' => $promo->getType()])
->add('textColor', TextType::class, ['label' => 'Text Color', 'data' => $promo->getTextColor()])
->add('color', TextType::class, ['label' => 'Primary Color', 'data' => $promo->getColor()])
->add('buttonType', ChoiceType::class, ['label' => 'Button Type', 'choices' => array('Song' => 0, 'Playlist (Unused)' => 1, 'Search Query' => 2, 'External' => 3), 'data' => $promo->getButtonType()])
->add('buttonData', TextType::class, ['label' => 'Button Data', 'data' => $promo->getButtonData()])
->add('isVisible', ChoiceType::class, ['label' => 'Is Visible?', 'choices' => array('Yes' => true, 'No' => false), 'data' => $promo->getIsVisible()])
->add('save', SubmitType::class, ['label' => 'Save'])
->getForm();
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
try {
$promo->setTitle($data['title']);
$promo->setType($data['type']);
$promo->setTextColor($data['textColor']);
$promo->setColor($data['color']);
$promo->setButtonType($data['buttonType']);
$promo->setButtonData($data['buttonData']);
$promo->setIsVisible($data['isVisible']);
if($data['imagePath'] != null) {
try {
$fileToRemove = glob($this->getParameter('promo_path').DIRECTORY_SEPARATOR.$promo->getImagePath());
if(count($fileToRemove) > 0) {
@unlink($fileToRemove[0]);
}
} catch(FileException $e) {
}
$newFilename = "promo_".uniqid().".png";
$data['imagePath']->move($this->getParameter('promo_path'), $newFilename);
$promo->setImagePath($newFilename);
}
$em->persist($promo);
$em->flush();
return $this->redirectToRoute('moderation.index');
} catch(FileException $e) {
}
}
$data['editForm'] = $form->createView();
return $this->render('moderation/promos/edit.html.twig', $data);
}
/**
* @Route("/moderation/promos/switchVisibility/{promoId}", name="moderation.promos.switchVisibility")
*/
public function promosSwitchVisibility(Request $request, int $promoId)
{
$em = $this->getDoctrine()->getManager();
$data = [];
$promoToSwitch = $em->getRepository(Promo::class)->findOneBy(array('id' => $promoId));
$promoToSwitch->setIsVisible(!$promoToSwitch->getIsVisible());
$em->persist($promoToSwitch);
$em->flush();
return $this->redirectToRoute('moderation.promos.index');
}
/**
* @Route("/moderation/promos/remove/{promoId}", name="moderation.promos.remove")
*/
public function promosRemove(Request $request, int $promoId)
{
$em = $this->getDoctrine()->getManager();
$data = [];
$promoToRemove = $em->getRepository(Promo::class)->findOneBy(array('id' => $promoId));
// Remove PNG file
try {
$fileToRemove = glob($this->getParameter('promo_path').DIRECTORY_SEPARATOR.$promoToRemove->getImagePath());
if(count($fileToRemove) > 0) {
@unlink($fileToRemove[0]);
}
} catch(FileException $e) {
}
// Remove Entity
$em->remove($promoToRemove);
$em->flush();
return $this->redirectToRoute('moderation.promos.index');
}
}
<?php
namespace App\Controller\Moderation;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use App\Entity\Song;
use App\Entity\User;
use App\Entity\SongReport;
use App\Entity\UserReport;
class SongReportsController extends AbstractController
{
/**
* @Route("/moderation/reports/song/", name="moderation.reports.song.index")
*/
public function reportsSongIndex(Request $request)
{
$em = $this->getDoctrine()->getManager();
$data = [];
$openSongReports = $em->getRepository(SongReport::class)->findBy(array(), array('status' => 'ASC', 'reportDate' => 'DESC'));
$data['songReports'] = $openSongReports;
return $this->render('moderation/reports/songIndex.html.twig', $data);
}
/**
* @Route("/moderation/reports/song/{reportId}", name="moderation.reports.song")
*/
public function reportsSongDetail(Request $request, int $reportId)
{
$em = $this->getDoctrine()->getManager();
$data = [];
$report = $em->getRepository(SongReport::class)->findOneBy(array('id' => $reportId));
$data['report'] = $report;
$reportSong = $em->getRepository(Song::class)->findOneBy(array('id' => $report->getSongId()));
$data['reportSong'] = $reportSong;
if($reportSong) {
$reportSongUploader = $em->getRepository(User::class)->findOneBy(array('id' => $reportSong->getUploader()));
$data['reportSongUploader'] = $reportSongUploader;
}
return $this->render('moderation/reports/song.html.twig', $data);
}
/**
* @Route("/moderation/reports/song/{reportId}/status/{newStatus}", name="moderation.reports.song.changeStatus")
*/
public function reportsSongChangeStatus(Request $request, int $reportId, int $newStatus, \Swift_Mailer $mailer)
{
$em = $this->getDoctrine()->getManager();
$data = [];
$reportToChange = $em->getRepository(SongReport::class)->findOneBy(array('id' => $reportId));
try {
$message = (new \Swift_Message('[#SONG-'.$reportToChange->getId().'] Your reports status changed!'))
->setFrom('legal@spinsha.re')
->setTo($reportToChange->getEmail())
->setBody(
$this->renderView(
'emails/moderation/changeStatus.txt.twig',
['report' => $reportToChange, 'type' => 'SONG']
), 'text/plain');
@$mailer->send($message);
} catch ( \Exception $e ) { }
$reportToChange->setStatus($newStatus);
$em->persist($reportToChange);
$em->flush();
return $this->redirectToRoute('moderation.reports.song', array('reportId' => $reportId));
}
}
<?php
namespace App\Controller\Moderation;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Session\Session;
use App\Utils\HelperFunctions;
use App\Entity\Song;
class SystemController extends AbstractController
{
/**
* @Route("/moderation/system/", name="moderation.system.index")
*/
public function systemIndex(Request $request)
{
$em = $this->getDoctrine()->getManager();
$data = [];
return $this->render('moderation/system/index.html.twig', $data);
}
/**
* @Route("/moderation/system/deploy", name="moderation.system.deploy")
*/
public function systemDeploy(Request $request)
{
shell_exec("bash /var/www/spinshare/pull-volatile.sh");
return $this->redirectToRoute('moderation.system.index');
}
/**
* @Route("/moderation/system/rollback", name="moderation.system.rollback")
*/
public function systemRollback(Request $request)
{
shell_exec("dep rollback");
return $this->redirectToRoute('moderation.system.index');
}
/**
* @Route("/moderation/system/cleanup/temp", name="moderation.system.cleanup.temp")
*/
public function systemCleanupTemp(Request $request)
{
$filesToRemove = glob($this->getParameter('temp_path').DIRECTORY_SEPARATOR."*");
foreach($filesToRemove as $fileToRemove) {
try {
@unlink($fileToRemove);
} catch(FileNotFoundException $e) {
}
}
return $this->redirectToRoute('moderation.system.index');
}
/**
* @Route("/moderation/system/generate/thumbnails", name="moderation.system.generate.thumbnails")
*/
public function systemGenerateThumbnails(Request $request)
{
$em = $this->getDoctrine()->getManager();
$baseUrl = $request->getScheme() . '://' . $request->getHttpHost() . $request->getBasePath();
$allSongs = $em->getRepository(Song::class)->findAll();
foreach($allSongs as $oneSong) {
$filePath = glob($this->getParameter('cover_path').DIRECTORY_SEPARATOR.$oneSong->getFileReference().".png");
if(count($filePath) > 0) {
$hf = new HelperFunctions();
$hf->generateThumbnail($filePath[0], $this->getParameter('thumbnail_path').DIRECTORY_SEPARATOR.$oneSong->getFileReference().".jpg", 300);
}
}
return $this->redirectToRoute('moderation.system.index');
}
}
<?php
namespace App\Controller\Moderation;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use App\Entity\ClientRelease;
use App\Entity\Song;
use App\Entity\User;
use App\Entity\SongReport;
use App\Entity\UserReport;
use App\Entity\Promo;
class UserReportsController extends AbstractController
{
/**
* @Route("/moderation/reports/user/", name="moderation.reports.user.index")
*/
public function reportsUserIndex(Request $request)
{
$em = $this->getDoctrine()->getManager();
$data = [];
$openUserReports = $em->getRepository(UserReport::class)->findBy(array(), array('status' => 'ASC', 'reportDate' => 'DESC'));
$data['userReports'] = $openUserReports;
return $this->render('moderation/reports/userIndex.html.twig', $data);
}
/**
* @Route("/moderation/reports/user/{reportId}", name="moderation.reports.user")
*/
public function reportsUserDetail(Request $request, int $reportId)
{
$em = $this->getDoctrine()->getManager();
$data = [];
$report = $em->getRepository(UserReport::class)->findOneBy(array('id' => $reportId));
$reportUser = $em->getRepository(User::class)->findOneBy(array('id' => $report->getUserId()));
$data['report'] = $report;
$data['reportUser'] = $reportUser;
return $this->render('moderation/reports/user.html.twig', $data);
}
/**
* @Route("/moderation/reports/user/{reportId}/status/{newStatus}", name="moderation.reports.user.changeStatus")
*/
public function reportsUserChangeStatus(Request $request, int $reportId, int $newStatus, \Swift_Mailer $mailer)
{
$em = $this->getDoctrine()->getManager();
$data = [];
$reportToChange = $em->getRepository(UserReport::class)->findOneBy(array('id' => $reportId));
try {
$message = (new \Swift_Message('[#USER-'.$reportToChange->getId().'] Your reports status changed!'))
->setFrom('legal@spinsha.re')
->setTo($reportToChange->getEmail())
->setBody(
$this->renderView(
'emails/moderation/changeStatus.txt.twig',
['report' => $reportToChange, 'type' => 'USER']
), 'text/plain');
@$mailer->send($message);
} catch ( \Exception $e ) { }
$reportToChange->setStatus($newStatus);
$em->persist($reportToChange);
$em->flush();
return $this->redirectToRoute('moderation.reports.user', array('reportId' => $reportId));
}
}
......@@ -203,6 +203,13 @@ class SongController extends AbstractController
}
// Remove thumbnail
try {
@unlink($this->getParameter('thumbnail_path').DIRECTORY_SEPARATOR.$song->getFileReference().".jpg");
} catch(FileNotFoundException $e) {
}
// Remove .ogg files
try {
$oggFiles = glob($this->getParameter('audio_path').DIRECTORY_SEPARATOR.$song->getFileReference()."_*.ogg");
......@@ -288,6 +295,10 @@ class SongController extends AbstractController
if(in_array($fileType, array('jpg', 'png'))) {
$trackInfo->albumArtReference->assetName = $song->getFileReference();
rename($coverFiles[0], $this->getParameter('cover_path').DIRECTORY_SEPARATOR.$song->getFileReference().".png");
// Generate Thumbnail
$hf = new HelperFunctions();
$hf->generateThumbnail($coverFiles[0], $this->getParameter('thumbnail_path').DIRECTORY_SEPARATOR.$song->getFileReference().".jpg", 300);
}
}
} catch(Exception $e) {
......@@ -391,6 +402,13 @@ class SongController extends AbstractController
}
// Remove thumbnail
try {
@unlink($this->getParameter('thumbnail_path').DIRECTORY_SEPARATOR.$result->getFileReference().".jpg");
} catch(FileNotFoundException $e) {
}
// Remove .ogg files
try {
$oggFiles = glob($this->getParameter('audio_path').DIRECTORY_SEPARATOR.$result->getFileReference()."_*.ogg");
......
......@@ -134,6 +134,10 @@ class UploadController extends AbstractController
if(in_array($fileType, array('jpg', 'png'))) {
$trackInfo->albumArtReference->assetName = $song->getFileReference();
rename($coverFiles[0], $this->getParameter('cover_path').DIRECTORY_SEPARATOR.$song->getFileReference().".png");
// Generate Thumbnail
$hf = new HelperFunctions();
$hf->generateThumbnail($coverFiles[0], $this->getParameter('thumbnail_path').DIRECTORY_SEPARATOR.$song->getFileReference().".jpg", 300);
}
}
} catch(Exception $e) {
......
......@@ -14,4 +14,22 @@ class HelperFunctions {
}
return rmdir($dir);
}
// Source: https://davidwalsh.name/create-image-thumbnail-php
// Creating a Thumbnail without Imagick
public static function generateThumbnail($src, $dest, $thumbnailSize) {
/* Using imagecreatfromstring and file_get_contents because we don't if the file will be png/gif/jpg */
$source_image = imagecreatefromstring(file_get_contents($src));
$width = imagesx($source_image);
$height = imagesy($source_image);
// Resizing the image
$virtual_image = imagecreatetruecolor($thumbnailSize, $thumbnailSize);
// Resample Image
imagecopyresampled($virtual_image, $source_image, 0, 0, 0, 0, $thumbnailSize, $thumbnailSize, $width, $height);
// Save Image
imagejpeg($virtual_image, $dest);
}
}
\ No newline at end of file
......@@ -22,22 +22,35 @@
<body>
<main>
<aside>
<div class="logo">
<a href="{{ path('index.index') }}"><img src="{{ asset('assets/img/logo_colored_ondark.svg') }}" alt="SpinShare Logo" /></a>
</div>
<nav>
<a class="item {% if app.request.attributes.get('_route') == 'index.index' %}active{% endif %}" href="{{ path('index.index') }}" title="Home"><i class="mdi mdi-home-outline"></i></a>
<a class="item {% if app.request.attributes.get('_route') == 'search.index' %}active{% endif %}" href="{{ path('search.index') }}" title="Search"><i class="mdi mdi-magnify"></i></a>
<a class="item {% if app.request.attributes.get('_route') == 'index.client' %}active{% endif %}" href="{{ path('index.client') }}" title="Download Client"><i class="mdi mdi-desktop-tower-monitor"></i></a>
<a class="item {% if app.request.attributes.get('_route') == 'index.support' %}active{% endif %}" href="{{ path('index.support') }}" title="Support"><i class="mdi mdi-hand-heart"></i></a>
<a class="item {% if app.request.attributes.get('_route') == 'index.legal' %}active{% endif %}" href="{{ path('index.legal') }}" title="Legal"><i class="mdi mdi-gavel"></i></a>
</nav>
<form action="{{ path('search.index') }}" method="GET" class="search">
{% if app.request.attributes.get('_route') != 'search.index' %}
<input name="q" type="search" placeholder="Search for songs, tags & profiles..." value="{{ searchQuery|default('') }}" />
{% endif %}
</form>
<nav>
{% if is_granted("ROLE_USER") %}
{% if is_granted("ROLE_MODERATOR") or is_granted("ROLE_ADMIN") %}
<a class="item {% if app.request.attributes.get('_route') == 'moderation.index' %}active{% endif %}" href="{{ path('moderation.index') }}" title="Moderator Dashboard"><i class="mdi mdi-shield-outline"></i></a>
{% endif %}
<a class="item {% if app.request.attributes.get('_route') == 'upload.index' %}active{% endif %}" href="{{ path('upload.index') }}" title="Upload"><i class="mdi mdi-upload-outline"></i></a>
<div class="upload-button">
<a href="{{ path('upload.index') }}" class="button">Upload</a>
</div>
<a class="item {% if app.request.attributes.get('_route') == 'user.detail' and app.request.attributes.get('_route_params')['userId']|default('') == app.user.id %}active{% endif %}" href="{{ path('user.detail', {userId: app.user.id}) }}" title="My Profile">
<div class="user-avatar" style="background-image: url({{ asset('uploads/avatar/' ~ app.user.coverReference ~ '?t=' ~ date().timestamp) }}), url({{ asset("assets/img/defaultAvatar.jpg") }});"></div>
</a>
{% if is_granted("ROLE_MODERATOR") or is_granted("ROLE_ADMIN") %}
<a class="item {% if 'moderation' in app.request.attributes.get('_route') %}active{% endif %}" href="{{ path('moderation.index') }}" title="Moderator Dashboard"><i class="mdi mdi-shield-outline"></i></a>
{% endif %}
<a class="item {% if app.request.attributes.get('_route') == 'user.settings' %}active{% endif %}" href="{{ path('user.settings') }}" title="Settings"><i class="mdi mdi-cog-outline"></i></a>
<a class="item {% if app.request.attributes.get('_route') == 'user.detail' and app.request.attributes.get('_route_params')['userId']|default('') == app.user.id %}active{% endif %}" href="{{ path('user.detail', {userId: app.user.id}) }}" title="My Profile"><i class="mdi mdi-account-circle-outline"></i></a>
<a class="item" href="{{ path('fos_user_security_logout') }}" title="Logout"><i class="mdi mdi-close-circle-outline"></i></a>
{% else %}
<a class="item" href="{{ path('fos_user_security_login') }}" title="Login/Register"><i class="mdi mdi-login-variant"></i></a>
......
{% extends 'base.html.twig' %}
{% extends 'bundles/FOSUserBundle/base.html.twig' %}
{% block title %}Confirmed{% endblock %}
{% set sectionTitle = 'Confirm your email' %}
{% block content %}
<section class="section-login">
<div class="box">
<div class="text">
<div class="title">Confirm your email</div>
{% block securityContent %}
<div class="security-content">
<img src="{{ asset('assets/img/illustration-confirm.svg') }}" alt="Illustration for Forgot Password" />
<p>To activate your user account, please click on the link provided in the email sent to you.</p>
</div>
<div class="illustration">
<img src="{{ asset('assets/img/illustration-confirm.svg') }}" alt="Confirmed Illustration" />
</div>
</div>
</section>
{% endblock content %}
{% block styles %}
<link rel="stylesheet" href="{{ asset('assets/css/login.css') }}" />
{% endblock %}
\ No newline at end of file
<p>To activate your user account, please click on the link provided in the email sent to you.</p>
</div>
{% endblock securityContent %}
\ No newline at end of file
{% extends 'base.html.twig' %}
{% trans_default_domain 'FOSUserBundle' %}
{% extends 'bundles/FOSUserBundle/base.html.twig' %}
{% block title %}Confirmed{% endblock %}
{% set sectionTitle = 'Email confirmed!' %}
{% block content %}
<section class="section-login">
<div class="box">
<div class="text">
<div class="title">Confirmed</div>
{% block securityContent %}
<div class="security-content">
<img src="{{ asset('assets/img/illustration-confirmed.svg') }}" alt="Illustration for Confirm Email" />
<p>Awesome, {{ user.username }}! Your account is now activated.</p>
</div>
<div class="illustration">
<img src="{{ asset('assets/img/illustration-confirmed.svg') }}" alt="Confirmed Illustration" />
</div>
</div>
</section>
{% endblock content %}
{% block styles %}
<link rel="stylesheet" href="{{ asset('assets/css/login.css') }}" />
{% endblock %}
\ No newline at end of file
<p>Awesome, your account was now activated!</p>
</div>
{% endblock securityContent %}
\ No newline at end of file
{% extends 'base.html.twig' %}
{% block title %}Spin Rhythm XD Custom Charts{% endblock %}
{% block content %}
<section class="section-startup">
<div class="tabs">
<a href="{{ path('index.index') }}" {% if app.request.attributes.get('_route') == 'index.index' %}class="active"{% endif %}><span>Frontpage</span></a>
<a href="{{ path('index.new') }}" {% if app.request.attributes.get('_route') == 'index.new' %}class="active"{% endif %}><span>New</span></a>
<a href="{{ path('index.hot') }}" {% if app.request.attributes.get('_route') == 'index.hot' %}class="active"{% endif %}><span>Hot</span></a>
<a href="{{ path('index.popular') }}" {% if app.request.attributes.get('_route') == 'index.popular' %}class="active"{% endif %}><span>Popular</span></a>
</div>
{% block indexContent %}{% endblock %}
</section>
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="{{ asset('assets/css/startup.css?v=' ~ date().timestamp) }}" />
{% endblock %}
\ No newline at end of file
{% extends 'index/base.html.twig' %}
{% block indexContent %}
<div class="song-row song-row-hot">
<div class="song-header">
<div class="row-title">Hot Songs</div>
<div class="row-controls">
{% if hotOffset > 0 %}
<a href="{{ path('index.hot', {hotOffset: hotOffset - 1}) }}" class="item row-controls-previous"><i class="mdi mdi-chevron-left"></i></a>
{% else %}
<a href="#" class="item disabled row-controls-previous"><i class="mdi mdi-chevron-left"></i></a>
{% endif %}
<a href="{{ path('index.hot', {hotOffset: hotOffset + 1}) }}" class="item row-controls-next"><i class="mdi mdi-chevron-right"></i></a>
</div>
</div>
<div class="song-list">
{% for song in hotSongs %}
<a class="song-item" href="{{ path('song.detail', {songId: song.id}) }}">
<div class="song-cover" style="background-image: url({{ asset("uploads/thumbnail/" ~ song.fileReference ~ ".jpg?v=" ~ date().timestamp) }}), url({{ asset("assets/img/defaultAlbumArt.jpg") }});">
<div class="song-charter-info">
<div class="song-charter"><i class="mdi mdi-account-circle"></i><span>{{ song.charter|default('Unknown') }}</span></div>
</div>
</div>
<div class="song-metadata">
<div class="song-title">{{ song.title|default('Untitles') }}</div>
<div class="song-artist">{{ song.artist|default('Unknown') }}</div>
<div class="song-difficulties">
<img src="{{ asset('assets/img/difficultyEasy.svg') }}" class="{{ song.hasEasyDifficulty ? "active" : "" }}" alt="Easy Difficulty" />
<img src="{{ asset('assets/img/difficultyNormal.svg') }}" class="{{ song.hasNormalDifficulty ? "active" : "" }}" alt="Normal Difficulty" />
<img src="{{ asset('assets/img/difficultyHard.svg') }}" class="{{ song.hasHardDifficulty ? "active" : "" }}" alt="Hard Difficulty" />
<img src="{{ asset('assets/img/difficultyExtreme.svg') }}" class="{{ song.hasExtremeDifficulty ? "active" : "" }}" alt="Extreme Difficulty" />
<img src="{{ asset('assets/img/difficultyXD.svg') }}" class="{{ song.hasXDDifficulty ? "active" : "" }}" alt="xD Difficulty" />
</div>
</div>
</a>
{% endfor %}
</div>
</div>
{% endblock %}
\ No newline at end of file
{% extends 'base.html.twig' %}
{% extends 'index/base.html.twig' %}
{% block title %}Welcome!{% endblock %}
{% block content %}
<section class="section-startup">
<div class="blm-banner">
<div class="icon">
<img src="{{ asset('assets/img/blmfist.svg') }}" />
</div>
<div class="text">
<h1>Music connects people! &dash; Black Lives Matter!</h1>
<div class="copy">We openly denounce the systemic racism and violence against the black community in our society!<br />This is why the SpinShare team stands in solidarity with the Black Lives Matter movement.</div>
</div>
<a href="https://blacklivesmatters.carrd.co/" target="_blank" class="button">How you can help</a>
</div>
<div class="staff-promos">
{% for promo in promos %}
<div class="staff-promo" style="background-image: url({{ asset('uploads/promo/' ~ promo.imagePath) }});">
<div class="promo-type" style="color: {{ promo.color }};">{{ promo.type }}</div>
<div class="promo-title" style="color: {{ promo.textColor }};">{{ promo.title|raw }}</div>
{% if promo.buttonType == 0 %}
{# Song #}
<a href="{{ path('song.detail', {songId: promo.buttonData}) }}" class="promo-button" style="background-color: {{ promo.color }};">CHECK IT OUT</a>
{% endif %}
{% if promo.buttonType == 2 %}
{# Search Query #}
<a href="{{ path('search.index', {q: promo.buttonData}) }}" class="promo-button" style="background-color: {{ promo.color }};">CHECK IT OUT</a>
{% endif %}
{% if promo.buttonType == 3 %}
{# External Link #}
<a href="{{ promo.buttonData }}" target="_blank" class="promo-button" style="background-color: {{ promo.color }};">CHECK IT OUT</a>
{% endif %}
</div>
{% endfor %}
</div>
<div class="song-row song-row-new">
<div class="song-header">
<div class="row-title">New Songs</div>
<div class="row-controls">
{% if newOffset > 0 %}
<a href="{{ path('index.index', {newOffset: newOffset - 1}) }}" class="item row-controls-previous"><i class="mdi mdi-chevron-left"></i></a>
{% else %}
<a href="#" class="item disabled row-controls-previous"><i class="mdi mdi-chevron-left"></i></a>
{% endif %}
<a href="{{ path('index.index', {newOffset: newOffset + 1}) }}" class="item row-controls-next"><i class="mdi mdi-chevron-right"></i></a>
</div>
</div>
<div class="song-list">
{% for song in newSongs %}
<a class="song-item" href="{{ path('song.detail', {songId: song.id}) }}">
<div class="song-cover" style="background-image: url({{ asset("uploads/cover/" ~ song.fileReference ~ ".png?v=" ~ date().timestamp) }}), url({{ asset("assets/img/defaultAlbumArt.jpg") }});">
<div class="song-charter-info">
<div class="song-charter"><i class="mdi mdi-account-circle"></i><span>{{ song.charter|default('Unknown') }}</span></div>
</div>
</div>
<div class="song-metadata">
<div class="song-title">{{ song.title|default('Untitles') }}</div>
<div class="song-artist">{{ song.artist|default('Unknown') }}</div>
<div class="song-difficulties">
<img src="{{ asset('assets/img/difficultyEasy.svg') }}" class="{{ song.hasEasyDifficulty ? "active" : "" }}" alt="Easy Difficulty" />
<img src="{{ asset('assets/img/difficultyNormal.svg') }}" class="{{ song.hasNormalDifficulty ? "active" : "" }}" alt="Normal Difficulty" />
<img src="{{ asset('assets/img/difficultyHard.svg') }}" class="{{ song.hasHardDifficulty ? "active" : "" }}" alt="Hard Difficulty" />
<img src="{{ asset('assets/img/difficultyExtreme.svg') }}" class="{{ song.hasExtremeDifficulty ? "active" : "" }}" alt="Extreme Difficulty" />
<img src="{{ asset('assets/img/difficultyXD.svg') }}" class="{{ song.hasXDDifficulty ? "active" : "" }}" alt="xD Difficulty" />
</div>
</div>
</a>
{% endfor %}
</div>
</div>
<div class="song-row song-row-popular">
<div class="song-header">
<div class="row-title">Popular Songs</div>
<div class="row-controls">
{% if popularOffset > 0 %}
<a href="{{ path('index.index', {popularOffset: popularOffset - 1}) }}" class="item row-controls-previous"><i class="mdi mdi-chevron-left"></i></a>
{% else %}
<a href="#" class="item disabled row-controls-previous"><i class="mdi mdi-chevron-left"></i></a>
{% endif %}
<a href="{{ path('index.index', {popularOffset: popularOffset + 1}) }}" class="item row-controls-next"><i class="mdi mdi-chevron-right"></i></a>
</div>
</div>
<div class="song-list">
{% for song in popularSongs %}
<a class="song-item" href="{{ path('song.detail', {songId: song.id}) }}">
<div class="song-cover" style="background-image: url({{ asset("uploads/cover/" ~ song.fileReference ~ ".png?v=" ~ date().timestamp) }}), url({{ asset("assets/img/defaultAlbumArt.jpg") }});">
<div class="song-charter-info">
<div class="song-charter"><i class="mdi mdi-account-circle"></i><span>{{ song.charter|default('Unknown') }}</span></div>
</div>
</div>
<div class="song-metadata">
<div class="song-title">{{ song.title|default('Untitles') }}</div>
<div class="song-artist">{{ song.artist|default('Unknown') }}</div>
<div class="song-difficulties">
<img src="{{ asset('assets/img/difficultyEasy.svg') }}" class="{{ song.hasEasyDifficulty ? "active" : "" }}" alt="Easy Difficulty" />
<img src="{{ asset('assets/img/difficultyNormal.svg') }}" class="{{ song.hasNormalDifficulty ? "active" : "" }}" alt="Normal Difficulty" />
<img src="{{ asset('assets/img/difficultyHard.svg') }}" class="{{ song.hasHardDifficulty ? "active" : "" }}" alt="Hard Difficulty" />
<img src="{{ asset('assets/img/difficultyExtreme.svg') }}" class="{{ song.hasExtremeDifficulty ? "active" : "" }}" alt="Extreme Difficulty" />
<img src="{{ asset('assets/img/difficultyXD.svg') }}" class="{{ song.hasXDDifficulty ? "active" : "" }}" alt="xD Difficulty" />
</div>
</div>
</a>
{% endfor %}
{% block indexContent %}
<div class="staff-promos">
{% for promo in promos %}
<div class="staff-promo" style="background-image: url({{ asset('uploads/promo/' ~ promo.imagePath) }});">
<div class="promo-type" style="color: {{ promo.color }};">{{ promo.type }}</div>
<div class="promo-title" style="color: {{ promo.textColor }};">{{ promo.title|raw }}</div>
{% if promo.buttonType == 0 %}
{# Song #}
<a href="{{ path('song.detail', {songId: promo.buttonData}) }}" class="promo-button" style="background-color: {{ promo.color }};">CHECK IT OUT</a>
{% endif %}
{% if promo.buttonType == 2 %}
{# Search Query #}
<a href="{{ path('search.index', {q: promo.buttonData}) }}" class="promo-button" style="background-color: {{ promo.color }};">CHECK IT OUT</a>
{% endif %}
{% if promo.buttonType == 3 %}
{# External Link #}
<a href="{{ promo.buttonData }}" target="_blank" class="promo-button" style="background-color: {{ promo.color }};">CHECK IT OUT</a>
{% endif %}
</div>
</div>
</section>
{% endblock %}
{% endfor %}
</div>
{% block styles %}
<link rel="stylesheet" href="{{ asset('assets/css/startup.css?v=' ~ date().timestamp) }}" />
<div class="social-buttons">
<a href="https://spinsha.re/discord" class="item item-discord"><i class="mdi mdi-discord"></i></a>
<a href="https://twitter.com/WeAreSpinShare" class="item item-twitter"><i class="mdi mdi-twitter"></i></a>
<a href="https://www.youtube.com/channel/UCh7ftpzIqlHw5p_-HXHwMBw" class="item item-youtube"><i class="mdi mdi-youtube"></i></a>
<a href="https://twitch.tv/SpinShare" class="item item-twitch"><i class="mdi mdi-twitch"></i></a>
<a href="https://patreon.com/spinshare" class="item item-patreon"><i class="mdi mdi-patreon"></i></a>
</div>
{% endblock %}
\ No newline at end of file
{% extends 'index/base.html.twig' %}
{% block indexContent %}
<div class="song-row song-row-new">
<div class="song-header">
<div class="row-title">New Songs</div>
<div class="row-controls">
{% if newOffset > 0 %}
<a href="{{ path('index.new', {newOffset: newOffset - 1}) }}" class="item row-controls-previous"><i class="mdi mdi-chevron-left"></i></a>
{% else %}
<a href="#" class="item disabled row-controls-previous"><i class="mdi mdi-chevron-left"></i></a>
{% endif %}
<a href="{{ path('index.new', {newOffset: newOffset + 1}) }}" class="item row-controls-next"><i class="mdi mdi-chevron-right"></i></a>
</div>
</div>
<div class="song-list">
{% for song in newSongs %}
<a class="song-item" href="{{ path('song.detail', {songId: song.id}) }}">
<div class="song-cover" style="background-image: url({{ asset("uploads/thumbnail/" ~ song.fileReference ~ ".jpg?v=" ~ date().timestamp) }}), url({{ asset("assets/img/defaultAlbumArt.jpg") }});">
<div class="song-charter-info">
<div class="song-charter"><i class="mdi mdi-account-circle"></i><span>{{ song.charter|default('Unknown') }}</span></div>
</div>
</div>
<div class="song-metadata">
<div class="song-title">{{ song.title|default('Untitles') }}</div>
<div class="song-artist">{{ song.artist|default('Unknown') }}</div>
<div class="song-difficulties">
<img src="{{ asset('assets/img/difficultyEasy.svg') }}" class="{{ song.hasEasyDifficulty ? "active" : "" }}" alt="Easy Difficulty" />
<img src="{{ asset('assets/img/difficultyNormal.svg') }}" class="{{ song.hasNormalDifficulty ? "active" : "" }}" alt="Normal Difficulty" />
<img src="{{ asset('assets/img/difficultyHard.svg') }}" class="{{ song.hasHardDifficulty ? "active" : "" }}" alt="Hard Difficulty" />
<img src="{{ asset('assets/img/difficultyExtreme.svg') }}" class="{{ song.hasExtremeDifficulty ? "active" : "" }}" alt="Extreme Difficulty" />
<img src="{{ asset('assets/img/difficultyXD.svg') }}" class="{{ song.hasXDDifficulty ? "active" : "" }}" alt="xD Difficulty" />
</div>
</div>
</a>
{% endfor %}
</div>
</div>
{% endblock %}
\ No newline at end of file
{% extends 'index/base.html.twig' %}
{% block indexContent %}
<div class="song-row song-row-popular">
<div class="song-header">
<div class="row-title">Popular Songs</div>
<div class="row-controls">
{% if popularOffset > 0 %}
<a href="{{ path('index.popular', {popularOffset: popularOffset - 1}) }}" class="item row-controls-previous"><i class="mdi mdi-chevron-left"></i></a>
{% else %}
<a href="#" class="item disabled row-controls-previous"><i class="mdi mdi-chevron-left"></i></a>
{% endif %}
<a href="{{ path('index.popular', {popularOffset: popularOffset + 1}) }}" class="item row-controls-next"><i class="mdi mdi-chevron-right"></i></a>
</div>
</div>
<div class="song-list">
{% for song in popularSongs %}
<a class="song-item" href="{{ path('song.detail', {songId: song.id}) }}">
<div class="song-cover" style="background-image: url({{ asset("uploads/thumbnail/" ~ song.fileReference ~ ".jpg?v=" ~ date().timestamp) }}), url({{ asset("assets/img/defaultAlbumArt.jpg") }});">
<div class="song-charter-info">
<div class="song-charter"><i class="mdi mdi-account-circle"></i><span>{{ song.charter|default('Unknown') }}</span></div>
</div>
</div>
<div class="song-metadata">
<div class="song-title">{{ song.title|default('Untitles') }}</div>
<div class="song-artist">{{ song.artist|default('Unknown') }}</div>
<div class="song-difficulties">
<img src="{{ asset('assets/img/difficultyEasy.svg') }}" class="{{ song.hasEasyDifficulty ? "active" : "" }}" alt="Easy Difficulty" />
<img src="{{ asset('assets/img/difficultyNormal.svg') }}" class="{{ song.hasNormalDifficulty ? "active" : "" }}" alt="Normal Difficulty" />
<img src="{{ asset('assets/img/difficultyHard.svg') }}" class="{{ song.hasHardDifficulty ? "active" : "" }}" alt="Hard Difficulty" />
<img src="{{ asset('assets/img/difficultyExtreme.svg') }}" class="{{ song.hasExtremeDifficulty ? "active" : "" }}" alt="Extreme Difficulty" />
<img src="{{ asset('assets/img/difficultyXD.svg') }}" class="{{ song.hasXDDifficulty ? "active" : "" }}" alt="xD Difficulty" />
</div>
</div>
</a>
{% endfor %}
</div>
</div>
{% endblock %}
\ No newline at end of file
{% extends 'base.html.twig' %}
{% block title %}{{ sectionTitle }}{% endblock %}
{% block content %}
<section class="section-moderator-dashboard">
<header>
<div class="title">{{ sectionTitle }}</div>
<div class="tabs">
<a class="tab {% if 'moderation.reports.user' in app.request.attributes.get('_route') %}active{% endif %}" href="{{ path('moderation.reports.user.index') }}">User Reports</a>
<a class="tab {% if 'moderation.reports.song' in app.request.attributes.get('_route') %}active{% endif %}" href="{{ path('moderation.reports.song.index') }}">Song Reports</a>
{% if is_granted('ROLE_ADMIN') %}
<a class="tab {% if 'moderation.promos' in app.request.attributes.get('_route') %}active{% endif %}" href="{{ path('moderation.promos.index') }}">Promos</a>
<a class="tab {% if 'moderation.clientreleases' in app.request.attributes.get('_route') %}active{% endif %}" href="{{ path('moderation.clientreleases.index') }}">Client Releases</a>
<a class="tab {% if 'moderation.system' in app.request.attributes.get('_route') %}active{% endif %}" href="{{ path('moderation.system.index') }}">System</a>
{% endif %}
</div>
</header>
{% block moderationContent %}
{% endblock %}
</section>
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="{{ asset('assets/css/moderation.css?v=' ~ date().timestamp) }}" />
{% endblock %}
\ No newline at end of file
{% extends 'moderation/base.html.twig' %}
{% set sectionTitle = 'Client Releases' %}
{% block moderationContent %}
<section class="section-moderator-list">
<div class="box">
<table>
<tr>
<th>Version</th>
<th>Platform</th>
<th>UploadDate</th>
<th style="width: 40px"></th>
</tr>
{% for release in clientReleases %}
<tr>
<td>{{ release.majorVersion }}.{{ release.minorVersion }}.{{ release.patchVersion }}</td>
<td>{{ release.platform }}</td>
<td>{{ release.uploadDate|date('d/m/Y') }}</td>
<td><a href="{{ path('moderation.clientreleases.remove', {releaseId: release.id}) }}" class="button">X</a></td>
</tr>
{% endfor %}
</table>
<br /><br /><a href="{{ path('moderation.clientreleases.add') }}" class="button">New Release</a>
</div>
</section>
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="{{ asset('assets/css/moderation.css?v=' ~ date().timestamp) }}" />
{% endblock %}
\ No newline at end of file
{% extends 'base.html.twig' %}
{% block title %}Moderator Dashboard{% endblock %}
{% block content %}
<section class="section-moderator-dashboard">
<div class="reports-column">
<div class="box">
<div class="title">Open User Reports</div>
<table>
<tr>
<th style="width: 120px">User ID</th>
<th>Reason</th>
<th style="width: 150px">Report Date</th>
<th style="width: 80px"></th>
</tr>
{% for report in userReports %}
<tr {{ report.status == 2 ? "class=\"inactive\"" : ""}}>
<td>{{ report.userId }}</td>
<td>{{ report.reason }}</td>
<td>{{ report.reportDate|date('d/m/Y') }}</td>
<td><a href="{{ path('moderation.reports.user', {reportId: report.id}) }}" class="button">Open</a></td>
</tr>
{% endfor %}
</table>
</div>
<div class="box">
<div class="title">Open Song Reports</div>
<table>
<tr>
<th style="width: 120px">Song ID</th>
<th>Reason</th>
<th style="width: 150px">Report Date</th>
<th style="width: 80px"></th>
</tr>
{% for report in songReports %}
<tr {{ report.status == 2 ? "class=\"inactive\"" : ""}}>
<td>{{ report.songId }}</td>
<td>{{ report.reason }}</td>
<td>{{ report.reportDate|date('d/m/Y') }}</td>
<td><a href="{{ path('moderation.reports.song', {reportId: report.id}) }}" class="button">Open</a></td>
</tr>
{% endfor %}
</table>
</div>
</div>
<div class="content-column">
{% if is_granted('ROLE_ADMIN') %}
<div class="box">
<div class="title">Promos</div>
<table>
<tr>
<th>Type</th>
<th>Title</th>
<th>Visible</th>
<th style="width: 110px"></th>
</tr>
{% for promo in promos %}
<tr {{ promo.isVisible ? "class=\"active\"" : ""}}>
<td>{{ promo.type }}</td>
<td>{{ promo.title }}</td>
<td>{{ promo.isVisible ? "Yes" : "No" }}</td>
<td><a href="{{ path('moderation.promos.remove', {promoId: promo.id}) }}" class="button">X</a> <a href="{{ path('moderation.promos.switchVisibility', {promoId: promo.id}) }}" class="button">Vis</a></td>
</tr>
{% endfor %}
</table>
<br />
<a href="{{ path('moderation.promos.add') }}" class="button">New Promo</a>
</div>
<div class="box">
<div class="title">Client Releases</div>
<table>
<tr>
<th>Version</th>
<th>Platform</th>
<th>UploadDate</th>
<th style="width: 40px"></th>
</tr>
{% for release in clientReleases %}
<tr>
<td>{{ release.majorVersion }}.{{ release.minorVersion }}.{{ release.patchVersion }}</td>
<td>{{ release.platform }}</td>
<td>{{ release.uploadDate|date('d/m/Y') }}</td>
<td><a href="{{ path('moderation.clientreleases.remove', {releaseId: release.id}) }}" class="button">X</a></td>
</tr>
{% endfor %}
</table>
<br />
<a href="{{ path('moderation.clientreleases.add') }}" class="button">New Release</a>
</div>
<div class="box">
<div class="title">System</div>
<p>Don't play around with these buttons!!!</p>
<br />
<a href="{{ path('moderation.system.deploy') }}" class="button">Deploy</a>
<br /><br />
<a href="{{ path('moderation.system.rollback') }}" class="button">Rollback</a>
</div>
{% endif %}
</div>
</section>
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="{{ asset('assets/css/moderation.css?v=' ~ date().timestamp) }}" />
{% endblock %}
\ No newline at end of file
{% extends 'base.html.twig' %}
{% extends 'moderation/base.html.twig' %}
{% block title %}Moderator Dashboard{% endblock %}
{% set sectionTitle = 'Add a new promo' %}
{% block content %}
<section class="section-moderator-add">
<div class="box">
<div class="title">Add new Promo</div>
{{ form_start(addForm) }}
{{ form_widget(addForm) }}
{{ form_end(addForm) }}
</div>
</section>
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="{{ asset('assets/css/moderation.css?v=' ~ date().timestamp) }}" />
{% block moderationContent %}
<section class="section-moderator-add">
<div class="box">
{{ form_start(addForm) }}
{{ form_widget(addForm) }}
{{ form_end(addForm) }}
</div>
</section>
{% endblock %}
\ No newline at end of file
{% extends 'moderation/base.html.twig' %}
{% set sectionTitle = 'Edit an existing promo' %}
{% block moderationContent %}
<section class="section-moderator-add">
<div class="box">
{{ form_start(editForm) }}
{{ form_widget(editForm) }}
{{ form_end(editForm) }}
</div>
</section>
{% endblock %}
\ No newline at end of file
{% extends 'moderation/base.html.twig' %}
{% set sectionTitle = 'Promos' %}
{% block moderationContent %}
<section class="section-moderator-list">
<div class="box">
<table>
<tr>
<th>Type</th>
<th>Title</th>
<th>Visible</th>
<th style="width: 150px"></th>
</tr>
{% for promo in promos %}
<tr {{ promo.isVisible ? "class=\"active\"" : ""}}>
<td>{{ promo.type }}</td>
<td>{{ promo.title }}</td>
<td>{{ promo.isVisible ? "Yes" : "No" }}</td>
<td>
<a href="{{ path('moderation.promos.remove', {promoId: promo.id}) }}" class="button">X</a>
<a href="{{ path('moderation.promos.switchVisibility', {promoId: promo.id}) }}" class="button">Vis</a>
<a href="{{ path('moderation.promos.edit', {promoId: promo.id}) }}" class="button">Edit</a>
</td>
</tr>
{% endfor %}
</table>
<br /><br /><a href="{{ path('moderation.promos.add') }}" class="button">New Promo</a>
</div>
</section>
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="{{ asset('assets/css/moderation.css?v=' ~ date().timestamp) }}" />
{% endblock %}
\ No newline at end of file
{% extends 'base.html.twig' %}
{% extends 'moderation/base.html.twig' %}
{% block title %}Moderator Dashboard{% endblock %}
{% set sectionTitle = 'Song Report' %}
{% block content %}
{% block moderationContent %}
<section class="section-moderator-report">
<div class="user-column">
<div class="box">
......@@ -113,8 +113,4 @@
{% endif %}
</div>
</section>
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="{{ asset('assets/css/moderation.css?v=' ~ date().timestamp) }}" />
{% endblock %}
\ No newline at end of file
{% extends 'moderation/base.html.twig' %}
{% set sectionTitle = 'Song Reports' %}
{% block moderationContent %}
<section class="section-moderator-list">
<div class="box">
<table>
<tr>
<th style="width: 120px">Song ID</th>
<th>Reason</th>
<th style="width: 150px">Report Date</th>
<th style="width: 80px"></th>
</tr>
{% for report in songReports %}
<tr {{ report.status == 2 ? "class=\"inactive\"" : ""}}>
<td>{{ report.songId }}</td>
<td>{{ report.reason }}</td>
<td>{{ report.reportDate|date('d/m/Y') }}</td>
<td><a href="{{ path('moderation.reports.song', {reportId: report.id}) }}" class="button">Open</a></td>
</tr>
{% endfor %}
</table>
</div>
</section>
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="{{ asset('assets/css/moderation.css?v=' ~ date().timestamp) }}" />
{% endblock %}
\ No newline at end of file
{% extends 'base.html.twig' %}
{% extends 'moderation/base.html.twig' %}
{% block title %}Moderator Dashboard{% endblock %}
{% set sectionTitle = 'User Report' %}
{% block content %}
{% block moderationContent %}
<section class="section-moderator-report">
<div class="user-column">
<div class="box">
......@@ -101,8 +101,4 @@
</div>
</div>
</section>
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="{{ asset('assets/css/moderation.css?v=' ~ date().timestamp) }}" />
{% endblock %}
\ No newline at end of file
{% extends 'moderation/base.html.twig' %}
{% set sectionTitle = 'User Reports' %}
{% block moderationContent %}
<section class="section-moderator-list">
<div class="box">
<table>
<tr>
<th style="width: 120px">User ID</th>
<th>Reason</th>
<th style="width: 150px">Report Date</th>
<th style="width: 80px"></th>
</tr>
{% for report in userReports %}
<tr {{ report.status == 2 ? "class=\"inactive\"" : ""}}>
<td>{{ report.userId }}</td>
<td>{{ report.reason }}</td>
<td>{{ report.reportDate|date('d/m/Y') }}</td>
<td><a href="{{ path('moderation.reports.user', {reportId: report.id}) }}" class="button">Open</a></td>
</tr>
{% endfor %}
</table>
</div>
</section>
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="{{ asset('assets/css/moderation.css?v=' ~ date().timestamp) }}" />
{% endblock %}
\ No newline at end of file
{% extends 'moderation/base.html.twig' %}
{% set sectionTitle = 'System' %}
{% block moderationContent %}
<section class="section-moderator-list">
{% if (app.session.flashbag.get('message')) %}
<div class="flashbang flashbang-error">{{ app.session.flashbag.get('message') }}</div>
{% endif %}
<div class="box">
<a href="{{ path('moderation.system.deploy') }}" class="button">Deploy</a> <a href="{{ path('moderation.system.rollback') }}" class="button">Rollback</a>
</div>
<div class="box">
Generate On All Songs Actions<br /><strong>(ATTENTION: They can take a while!)</strong><br /><br />
<a href="{{ path('moderation.system.generate.thumbnails') }}" class="button">Generate Thumbnails</a><br /><br />
<a href="{{ path('moderation.system.cleanup.temp') }}" class="button">Cleanup Temp Folder</a>
</div>
</section>
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="{{ asset('assets/css/moderation.css?v=' ~ date().timestamp) }}" />
{% endblock %}
\ No newline at end of file
......@@ -7,7 +7,7 @@
<header>
<div class="title">Search</div>
<div class="actions">
<form action="" method="GET">
<form action="{{ path('search.index') }}" method="GET">
<input name="q" type="search" placeholder="Search for songs, tags & profiles..." value="{{ searchQuery|default('') }}" />
</form>
<a href="{{ path('search.index', {showAll: true}) }}" class="button">Show all</a>
......
......@@ -7,17 +7,17 @@
<meta property="og:description" content="Charted by {{ song.charter }} &dash; Views: {{ song.views|default(0) }}, Downloads: {{ song.downloads|default(0) }}"/>
<meta property="og:type" content="music.song"/>
<meta property="og:url" content="{{ path('song.detail', {songId: song.id}) }}"/>
<meta property="og:image" content="{{ asset("uploads/cover/" ~ song.fileReference ~ ".png?v=" ~ date().timestamp) }}"/>
<meta property="og:image" content="{{ asset("uploads/thumbnail/" ~ song.fileReference ~ ".jpg?v=" ~ date().timestamp) }}"/>
{% endblock %}
{% block content %}
<section class="section-song-detail">
<div class="song-detail-background" style="background-image: url({{ asset("uploads/cover/" ~ song.fileReference ~ ".png?v=" ~ date().timestamp) }}), url({{ asset("assets/img/defaultAlbumArt.jpg") }});">
<div class="song-detail-background" style="background-image: url({{ asset("uploads/thumbnail/" ~ song.fileReference ~ ".jpg?v=" ~ date().timestamp) }}), url({{ asset("assets/img/defaultAlbumArt.jpg") }});">
<div class="song-detail-background-cover"></div>
</div>
<div class="song-detail">
<div class="song-meta">
<div class="cover" style="background-image: url({{ asset("uploads/cover/" ~ song.fileReference ~ ".png?v=" ~ date().timestamp) }}), url({{ asset("assets/img/defaultAlbumArt.jpg") }});"></div>
<div class="cover" style="background-image: url({{ asset("uploads/thumbnail/" ~ song.fileReference ~ ".jpg?v=" ~ date().timestamp) }}), url({{ asset("assets/img/defaultAlbumArt.jpg") }});"></div>
<div class="song-metadata">
<div class="song-title">{{ song.title }}</div>
<div class="song-subtitle">{{ song.subtitle }}</div>
......
......@@ -26,6 +26,9 @@
<div></div>
</div>
</div>
<div class="tags-input">
{{ form_row(uploadForm.description) }}
</div>
<div class="tags-input">
{{ form_row(uploadForm.tags) }}
<div class="input-notice">Add multiple tags by seperating them with a comma. (eg: "Memes,Funny,Osu")</div>
......
......@@ -59,7 +59,7 @@
<div class="song-list">
{% for song in uploads %}
<a class="song-item" href="{{ path('song.detail', {songId: song.id}) }}">
<div class="song-cover" style="background-image: url({{ asset("uploads/cover/" ~ song.fileReference ~ ".png?v=" ~ date().timestamp) }}), url({{ asset("assets/img/defaultAlbumArt.jpg") }});">
<div class="song-cover" style="background-image: url({{ asset("uploads/thumbnail/" ~ song.fileReference ~ ".jpg?v=" ~ date().timestamp) }}), url({{ asset("assets/img/defaultAlbumArt.jpg") }});">
<div class="song-charter-info">
<div class="song-charter"><i class="mdi mdi-account-circle"></i><span>{{ song.charter|default('Unknown') }}</span></div>
</div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment