StationInfoBox.vue 5.5 KB

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