StationInfoBox.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. <script setup lang="ts">
  2. import Toast from "toasters";
  3. import { storeToRefs } from "pinia";
  4. import { useWebsocketsStore } from "@/stores/websockets";
  5. import { useUserAuthStore } from "@/stores/userAuth";
  6. import { useModalsStore } from "@/stores/modals";
  7. import { useStationStore } from "@/stores/station";
  8. import { useManageStationStore } from "@/stores/manageStation";
  9. const props = defineProps({
  10. station: { type: Object, default: null },
  11. stationPaused: { type: Boolean, default: null },
  12. showManageStation: { type: Boolean, default: false },
  13. showGoToStation: { type: Boolean, default: false },
  14. modalUuid: { type: String, default: "" },
  15. sector: { type: String, default: "station" }
  16. });
  17. const userAuthStore = useUserAuthStore();
  18. const stationStore = useStationStore();
  19. const manageStationStore = useManageStationStore(props);
  20. const { socket } = useWebsocketsStore();
  21. const { loggedIn } = storeToRefs(userAuthStore);
  22. const { openModal } = useModalsStore();
  23. const hasPermission = permission =>
  24. props.sector === "manageStation"
  25. ? manageStationStore.hasPermission(permission)
  26. : stationStore.hasPermission(permission);
  27. const resumeStation = () => {
  28. socket.dispatch("stations.resume", props.station._id, data => {
  29. if (data.status !== "success") new Toast(`Error: ${data.message}`);
  30. else new Toast("Successfully resumed the station.");
  31. });
  32. };
  33. const pauseStation = () => {
  34. socket.dispatch("stations.pause", props.station._id, data => {
  35. if (data.status !== "success") new Toast(`Error: ${data.message}`);
  36. else new Toast("Successfully paused the station.");
  37. });
  38. };
  39. const skipStation = () => {
  40. socket.dispatch("stations.forceSkip", props.station._id, data => {
  41. if (data.status !== "success") new Toast(`Error: ${data.message}`);
  42. else new Toast("Successfully skipped the station's current song.");
  43. });
  44. };
  45. const favoriteStation = () => {
  46. socket.dispatch("stations.favoriteStation", props.station._id, res => {
  47. if (res.status === "success") {
  48. new Toast("Successfully favorited station.");
  49. } else new Toast(res.message);
  50. });
  51. };
  52. const unfavoriteStation = () => {
  53. socket.dispatch("stations.unfavoriteStation", props.station._id, res => {
  54. if (res.status === "success") {
  55. new Toast("Successfully unfavorited station.");
  56. } else new Toast(res.message);
  57. });
  58. };
  59. </script>
  60. <template>
  61. <div class="about-station-container">
  62. <div class="station-info">
  63. <div class="row station-name">
  64. <h1>{{ station.displayName }}</h1>
  65. <i
  66. v-if="station.type === 'official'"
  67. class="material-icons verified-station"
  68. content="Verified Station"
  69. v-tippy
  70. >
  71. check_circle
  72. </i>
  73. <a>
  74. <!-- Favorite Station Button -->
  75. <i
  76. v-if="loggedIn && station.isFavorited"
  77. @click.prevent="unfavoriteStation()"
  78. content="Unfavorite Station"
  79. v-tippy
  80. class="material-icons"
  81. >star</i
  82. >
  83. <i
  84. v-if="loggedIn && !station.isFavorited"
  85. @click.prevent="favoriteStation()"
  86. class="material-icons"
  87. content="Favorite Station"
  88. v-tippy
  89. >star_border</i
  90. >
  91. </a>
  92. </div>
  93. <p>{{ station.description }}</p>
  94. </div>
  95. <div class="admin-buttons">
  96. <!-- (Admin) Pause/Resume Button -->
  97. <button
  98. class="button is-danger"
  99. v-if="
  100. hasPermission('stations.playback.toggle') && stationPaused
  101. "
  102. @click="resumeStation()"
  103. >
  104. <i class="material-icons icon-with-button">play_arrow</i>
  105. <span> Resume Station </span>
  106. </button>
  107. <button
  108. class="button is-danger"
  109. @click="pauseStation()"
  110. v-if="
  111. hasPermission('stations.playback.toggle') && !stationPaused
  112. "
  113. >
  114. <i class="material-icons icon-with-button">pause</i>
  115. <span> Pause Station </span>
  116. </button>
  117. <!-- (Admin) Skip Button -->
  118. <button
  119. class="button is-danger"
  120. @click="skipStation()"
  121. v-if="hasPermission('stations.skip')"
  122. >
  123. <i class="material-icons icon-with-button">skip_next</i>
  124. <span> Force Skip </span>
  125. </button>
  126. <!-- (Admin) Station Settings Button -->
  127. <button
  128. class="button is-primary"
  129. @click="
  130. openModal({
  131. modal: 'manageStation',
  132. data: {
  133. stationId: station._id,
  134. sector: 'station'
  135. }
  136. })
  137. "
  138. v-if="
  139. hasPermission('stations.view.manage') && showManageStation
  140. "
  141. >
  142. <i class="material-icons icon-with-button">settings</i>
  143. <span> Manage Station </span>
  144. </button>
  145. <router-link
  146. v-if="showGoToStation"
  147. :to="{
  148. name: 'station',
  149. params: { id: station.name }
  150. }"
  151. class="button is-primary"
  152. >
  153. Go To Station
  154. </router-link>
  155. </div>
  156. </div>
  157. </template>
  158. <style lang="less">
  159. .night-mode {
  160. .about-station-container {
  161. background-color: var(--dark-grey-3) !important;
  162. }
  163. }
  164. .about-station-container {
  165. padding: 20px;
  166. display: flex;
  167. flex-direction: column;
  168. flex-grow: unset;
  169. .row {
  170. display: flex;
  171. flex-direction: row;
  172. max-width: 100%;
  173. }
  174. .station-info {
  175. .station-name {
  176. flex-direction: row !important;
  177. h1 {
  178. margin: 0;
  179. font-size: 36px;
  180. line-height: 0.8;
  181. text-overflow: ellipsis;
  182. overflow: hidden;
  183. }
  184. i {
  185. margin-left: 10px;
  186. font-size: 30px;
  187. color: var(--yellow);
  188. &.stationMode {
  189. padding-left: 10px;
  190. margin-left: auto;
  191. color: var(--primary-color);
  192. }
  193. }
  194. .verified-station {
  195. color: var(--primary-color);
  196. }
  197. }
  198. p {
  199. display: -webkit-box;
  200. max-width: 700px;
  201. margin-bottom: 10px;
  202. overflow: hidden;
  203. text-overflow: ellipsis;
  204. -webkit-box-orient: vertical;
  205. -webkit-line-clamp: 3;
  206. }
  207. }
  208. .admin-buttons {
  209. display: flex;
  210. .button {
  211. margin: 3px;
  212. }
  213. }
  214. }
  215. </style>