index.vue 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. <template>
  2. <div class="app">
  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. .main-container .container {
  232. .button-row {
  233. display: flex;
  234. flex-direction: row;
  235. flex-wrap: wrap;
  236. justify-content: center;
  237. margin-bottom: 5px;
  238. & > .button,
  239. & > span {
  240. margin: 5px 0;
  241. &:not(:first-child) {
  242. margin-left: 5px;
  243. }
  244. }
  245. }
  246. }
  247. </style>
  248. <style lang="scss" scoped>
  249. .night-mode {
  250. .tabs {
  251. background-color: var(--dark-grey-2);
  252. border: 0;
  253. ul {
  254. border-bottom: 0;
  255. }
  256. }
  257. }
  258. /deep/ .container {
  259. position: relative;
  260. }
  261. /deep/ .box {
  262. box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1);
  263. display: block;
  264. &:not(:last-child) {
  265. margin-bottom: 20px;
  266. }
  267. }
  268. .main-container {
  269. height: auto;
  270. }
  271. .tabs {
  272. padding-top: 10px;
  273. margin-top: -10px;
  274. background-color: var(--white);
  275. display: flex;
  276. line-height: 24px;
  277. overflow-y: hidden;
  278. overflow-x: auto;
  279. margin-bottom: 20px;
  280. user-select: none;
  281. ul {
  282. display: flex;
  283. align-items: center;
  284. /* -webkit-box-flex: 1; */
  285. flex-grow: 1;
  286. flex-shrink: 0;
  287. justify-content: center;
  288. border-bottom: 1px solid var(--light-grey-2);
  289. }
  290. .unverifiedsongs {
  291. color: var(--teal);
  292. border-color: var(--teal);
  293. }
  294. .verifiedsongs {
  295. color: var(--primary-color);
  296. border-color: var(--primary-color);
  297. }
  298. .hiddensongs {
  299. color: var(--grey);
  300. border-color: var(--grey);
  301. }
  302. .stations {
  303. color: var(--purple);
  304. border-color: var(--purple);
  305. }
  306. .playlists {
  307. color: var(--light-purple);
  308. border-color: var(--light-purple);
  309. }
  310. .reports {
  311. color: var(--yellow);
  312. border-color: var(--yellow);
  313. }
  314. .news {
  315. color: var(--light-pink);
  316. border-color: var(--light-pink);
  317. }
  318. .users {
  319. color: var(--dark-pink);
  320. border-color: var(--dark-pink);
  321. }
  322. .statistics {
  323. color: var(--orange);
  324. border-color: var(--orange);
  325. }
  326. .punishments {
  327. color: var(--dark-orange);
  328. border-color: var(--dark-orange);
  329. }
  330. .tab {
  331. transition: all 0.2s ease-in-out;
  332. font-weight: 500;
  333. border-bottom: solid 0px;
  334. padding: 6px 12px;
  335. display: flex;
  336. margin-bottom: -1px;
  337. }
  338. .tab:hover {
  339. border-width: 3px;
  340. transition: all 0.2s ease-in-out;
  341. font-weight: 600;
  342. }
  343. .is-active .tab {
  344. font-weight: 600;
  345. border-width: 3px;
  346. }
  347. }
  348. @media screen and (min-width: 980px) {
  349. /deep/ .container {
  350. margin: 0 auto;
  351. max-width: 960px;
  352. }
  353. }
  354. @media screen and (min-width: 1180px) {
  355. /deep/ .container {
  356. max-width: 1200px;
  357. }
  358. }
  359. </style>