index.vue 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. <template>
  2. <div class="app admin-area">
  3. <main-header />
  4. <div class="tabs is-centered">
  5. <ul>
  6. <li
  7. :class="{ 'is-active': currentTab == 'hiddensongs' }"
  8. ref="hiddensongs-tab"
  9. @click="showTab('hiddensongs')"
  10. >
  11. <router-link
  12. class="tab hiddensongs"
  13. to="/admin/hiddensongs"
  14. >
  15. <i class="material-icons">music_note</i>
  16. <span>&nbsp;Hidden Songs</span>
  17. </router-link>
  18. </li>
  19. <li
  20. :class="{ 'is-active': currentTab == 'unverifiedsongs' }"
  21. ref="unverifiedsongs-tab"
  22. @click="showTab('unverifiedsongs')"
  23. >
  24. <router-link
  25. class="tab unverifiedsongs"
  26. to="/admin/unverifiedsongs"
  27. >
  28. <i class="material-icons">unpublished</i>
  29. <span>&nbsp;Unverified Songs</span>
  30. </router-link>
  31. </li>
  32. <li
  33. :class="{ 'is-active': currentTab == 'verifiedsongs' }"
  34. ref="verifiedsongs-tab"
  35. @click="showTab('verifiedsongs')"
  36. >
  37. <router-link
  38. class="tab verifiedsongs"
  39. to="/admin/verifiedsongs"
  40. >
  41. <i class="material-icons">check_circle</i>
  42. <span>&nbsp;Verified Songs</span>
  43. </router-link>
  44. </li>
  45. <li
  46. :class="{ 'is-active': currentTab == 'stations' }"
  47. ref="stations-tab"
  48. @click="showTab('stations')"
  49. >
  50. <router-link class="tab stations" to="/admin/stations">
  51. <i class="material-icons">radio</i>
  52. <span>&nbsp;Stations</span>
  53. </router-link>
  54. </li>
  55. <li
  56. :class="{ 'is-active': currentTab == 'playlists' }"
  57. ref="playlists-tab"
  58. @click="showTab('playlists')"
  59. >
  60. <router-link class="tab playlists" to="/admin/playlists">
  61. <i class="material-icons">library_music</i>
  62. <span>&nbsp;Playlists</span>
  63. </router-link>
  64. </li>
  65. <li
  66. :class="{ 'is-active': currentTab == 'reports' }"
  67. ref="reports-tab"
  68. @click="showTab('reports')"
  69. >
  70. <router-link class="tab reports" to="/admin/reports">
  71. <i class="material-icons">flag</i>
  72. <span>&nbsp;Reports</span>
  73. </router-link>
  74. </li>
  75. <li
  76. :class="{ 'is-active': currentTab == 'news' }"
  77. ref="news-tab"
  78. @click="showTab('news')"
  79. >
  80. <router-link class="tab news" to="/admin/news">
  81. <i class="material-icons">chrome_reader_mode</i>
  82. <span>&nbsp;News</span>
  83. </router-link>
  84. </li>
  85. <li
  86. :class="{ 'is-active': currentTab == 'users' }"
  87. ref="users-tab"
  88. @click="showTab('users')"
  89. >
  90. <router-link class="tab users" to="/admin/users">
  91. <i class="material-icons">people</i>
  92. <span>&nbsp;Users</span>
  93. </router-link>
  94. </li>
  95. <li
  96. :class="{ 'is-active': currentTab == 'statistics' }"
  97. ref="statistics-tab"
  98. @click="showTab('statistics')"
  99. >
  100. <router-link class="tab statistics" to="/admin/statistics">
  101. <i class="material-icons">show_chart</i>
  102. <span>&nbsp;Statistics</span>
  103. </router-link>
  104. </li>
  105. <li
  106. :class="{ 'is-active': currentTab == 'punishments' }"
  107. ref="punishments-tab"
  108. @click="showTab('punishments')"
  109. >
  110. <router-link
  111. class="tab punishments"
  112. to="/admin/punishments"
  113. >
  114. <i class="material-icons">gavel</i>
  115. <span>&nbsp;Punishments</span>
  116. </router-link>
  117. </li>
  118. </ul>
  119. </div>
  120. <unverified-songs v-if="currentTab == 'unverifiedsongs'" />
  121. <verified-songs v-if="currentTab == 'verifiedsongs'" />
  122. <hidden-songs v-if="currentTab == 'hiddensongs'" />
  123. <stations v-if="currentTab == 'stations'" />
  124. <playlists v-if="currentTab == 'playlists'" />
  125. <reports v-if="currentTab == 'reports'" />
  126. <news v-if="currentTab == 'news'" />
  127. <users v-if="currentTab == 'users'" />
  128. <statistics v-if="currentTab == 'statistics'" />
  129. <punishments v-if="currentTab == 'punishments'" />
  130. </div>
  131. </template>
  132. <script>
  133. import { mapGetters } from "vuex";
  134. import { defineAsyncComponent } from "vue";
  135. import MainHeader from "@/components/layout/MainHeader.vue";
  136. export default {
  137. components: {
  138. MainHeader,
  139. UnverifiedSongs: defineAsyncComponent(() =>
  140. import("./tabs/UnverifiedSongs.vue")
  141. ),
  142. VerifiedSongs: defineAsyncComponent(() =>
  143. import("./tabs/VerifiedSongs.vue")
  144. ),
  145. HiddenSongs: defineAsyncComponent(() =>
  146. import("./tabs/HiddenSongs.vue")
  147. ),
  148. Stations: defineAsyncComponent(() => import("./tabs/Stations.vue")),
  149. Playlists: defineAsyncComponent(() => import("./tabs/Playlists.vue")),
  150. Reports: defineAsyncComponent(() => import("./tabs/Reports.vue")),
  151. News: defineAsyncComponent(() => import("./tabs/News.vue")),
  152. Users: defineAsyncComponent(() => import("./tabs/Users.vue")),
  153. Statistics: defineAsyncComponent(() => import("./tabs/Statistics.vue")),
  154. Punishments: defineAsyncComponent(() =>
  155. import("./tabs/Punishments.vue")
  156. )
  157. },
  158. data() {
  159. return {
  160. currentTab: ""
  161. };
  162. },
  163. computed: mapGetters({
  164. socket: "websockets/getSocket"
  165. }),
  166. watch: {
  167. $route(route) {
  168. this.changeTab(route.path);
  169. }
  170. },
  171. mounted() {
  172. this.changeTab(this.$route.path);
  173. },
  174. beforeUnmount() {
  175. this.socket.dispatch("apis.leaveRooms");
  176. },
  177. methods: {
  178. changeTab(path) {
  179. switch (path) {
  180. case "/admin/unverifiedsongs":
  181. this.showTab("unverifiedsongs");
  182. break;
  183. case "/admin/verifiedsongs":
  184. this.showTab("verifiedsongs");
  185. break;
  186. case "/admin/hiddensongs":
  187. this.showTab("hiddensongs");
  188. break;
  189. case "/admin/stations":
  190. this.showTab("stations");
  191. break;
  192. case "/admin/playlists":
  193. this.showTab("playlists");
  194. break;
  195. case "/admin/reports":
  196. this.showTab("reports");
  197. break;
  198. case "/admin/news":
  199. this.showTab("news");
  200. break;
  201. case "/admin/users":
  202. this.showTab("users");
  203. break;
  204. case "/admin/statistics":
  205. this.showTab("statistics");
  206. break;
  207. case "/admin/punishments":
  208. this.showTab("punishments");
  209. break;
  210. default:
  211. if (localStorage.getItem("lastAdminPage")) {
  212. this.showTab(localStorage.getItem("lastAdminPage"));
  213. } else {
  214. this.showTab("verifiedsongs");
  215. }
  216. }
  217. },
  218. showTab(tab) {
  219. if (this.$refs[`${tab}-tab`])
  220. this.$refs[`${tab}-tab`].scrollIntoView({
  221. inline: "center",
  222. block: "nearest"
  223. });
  224. this.currentTab = tab;
  225. localStorage.setItem("lastAdminPage", tab);
  226. }
  227. }
  228. };
  229. </script>
  230. <style lang="scss">
  231. .christmas-mode .admin-area .christmas-lights {
  232. top: 102px !important;
  233. }
  234. .main-container .container {
  235. .button-row {
  236. display: flex;
  237. flex-direction: row;
  238. flex-wrap: wrap;
  239. justify-content: center;
  240. margin-bottom: 5px;
  241. & > .button,
  242. & > span {
  243. margin: 5px 0;
  244. &:not(:first-child) {
  245. margin-left: 5px;
  246. }
  247. }
  248. }
  249. }
  250. </style>
  251. <style lang="scss" scoped>
  252. .night-mode {
  253. .tabs {
  254. background-color: var(--dark-grey-2);
  255. border: 0;
  256. ul {
  257. border-bottom: 0;
  258. }
  259. }
  260. }
  261. /deep/ .container {
  262. position: relative;
  263. }
  264. /deep/ .box {
  265. box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1);
  266. display: block;
  267. &:not(:last-child) {
  268. margin-bottom: 20px;
  269. }
  270. }
  271. .main-container {
  272. height: auto;
  273. }
  274. .tabs {
  275. padding-top: 10px;
  276. margin-top: -10px;
  277. background-color: var(--white);
  278. display: flex;
  279. line-height: 24px;
  280. overflow-y: hidden;
  281. overflow-x: auto;
  282. margin-bottom: 20px;
  283. user-select: none;
  284. ul {
  285. display: flex;
  286. align-items: center;
  287. /* -webkit-box-flex: 1; */
  288. flex-grow: 1;
  289. flex-shrink: 0;
  290. justify-content: center;
  291. border-bottom: 1px solid var(--light-grey-2);
  292. }
  293. .unverifiedsongs {
  294. color: var(--teal);
  295. border-color: var(--teal);
  296. }
  297. .verifiedsongs {
  298. color: var(--primary-color);
  299. border-color: var(--primary-color);
  300. }
  301. .hiddensongs {
  302. color: var(--grey);
  303. border-color: var(--grey);
  304. }
  305. .stations {
  306. color: var(--purple);
  307. border-color: var(--purple);
  308. }
  309. .playlists {
  310. color: var(--light-purple);
  311. border-color: var(--light-purple);
  312. }
  313. .reports {
  314. color: var(--yellow);
  315. border-color: var(--yellow);
  316. }
  317. .news {
  318. color: var(--light-pink);
  319. border-color: var(--light-pink);
  320. }
  321. .users {
  322. color: var(--dark-pink);
  323. border-color: var(--dark-pink);
  324. }
  325. .statistics {
  326. color: var(--orange);
  327. border-color: var(--orange);
  328. }
  329. .punishments {
  330. color: var(--dark-orange);
  331. border-color: var(--dark-orange);
  332. }
  333. .tab {
  334. transition: all 0.2s ease-in-out;
  335. font-weight: 500;
  336. border-bottom: solid 0px;
  337. padding: 6px 12px;
  338. display: flex;
  339. margin-bottom: -1px;
  340. }
  341. .tab:hover {
  342. border-width: 3px;
  343. transition: all 0.2s ease-in-out;
  344. font-weight: 600;
  345. }
  346. .is-active .tab {
  347. font-weight: 600;
  348. border-width: 3px;
  349. }
  350. }
  351. @media screen and (min-width: 980px) {
  352. /deep/ .container {
  353. margin: 0 auto;
  354. max-width: 960px;
  355. }
  356. }
  357. @media screen and (min-width: 1180px) {
  358. /deep/ .container {
  359. max-width: 1200px;
  360. }
  361. }
  362. </style>