index.vue 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. <template>
  2. <div id="tabs-container">
  3. <div id="tab-selection">
  4. <button
  5. class="button is-default"
  6. :class="{ selected: tab === 'queue' }"
  7. @click="showTab('queue')"
  8. >
  9. Queue
  10. </button>
  11. <button
  12. class="button is-default"
  13. :class="{ selected: tab === 'users' }"
  14. @click="showTab('users')"
  15. >
  16. Users
  17. </button>
  18. <button
  19. v-if="canRequest()"
  20. class="button is-default"
  21. :class="{ selected: tab === 'request' }"
  22. @click="showTab('request')"
  23. >
  24. Request
  25. </button>
  26. <button
  27. v-else-if="canRequest(false)"
  28. class="button is-default"
  29. content="Login to request songs"
  30. v-tippy="{ theme: 'info' }"
  31. >
  32. Request
  33. </button>
  34. </div>
  35. <queue class="tab" v-show="tab === 'queue'" />
  36. <users class="tab" v-show="tab === 'users'" />
  37. <request
  38. v-if="canRequest()"
  39. v-show="tab === 'request'"
  40. class="tab requests-tab"
  41. sector="station"
  42. />
  43. </div>
  44. </template>
  45. <script>
  46. import { mapActions, mapState } from "vuex";
  47. import Queue from "@/components/Queue.vue";
  48. import TabQueryHandler from "@/mixins/TabQueryHandler.vue";
  49. import Users from "./Users.vue";
  50. import Request from "@/components/Request.vue";
  51. export default {
  52. components: { Queue, Users, Request },
  53. mixins: [TabQueryHandler],
  54. data() {
  55. return {
  56. tab: "queue"
  57. };
  58. },
  59. computed: mapState({
  60. station: state => state.station.station,
  61. users: state => state.station.users,
  62. userCount: state => state.station.userCount,
  63. userId: state => state.user.auth.userId,
  64. loggedIn: state => state.user.auth.loggedIn,
  65. role: state => state.user.auth.role
  66. }),
  67. watch: {
  68. // eslint-disable-next-line
  69. "station.requests": function (requests) {
  70. if (this.tab === "request" && !this.canRequest())
  71. this.showTab("queue");
  72. }
  73. },
  74. mounted() {
  75. if (
  76. this.$route.query.tab === "queue" ||
  77. this.$route.query.tab === "users" ||
  78. this.$route.query.tab === "request"
  79. )
  80. this.tab = this.$route.query.tab;
  81. },
  82. methods: {
  83. isOwner() {
  84. return (
  85. this.loggedIn &&
  86. this.station &&
  87. this.userId === this.station.owner
  88. );
  89. },
  90. isAdmin() {
  91. return this.loggedIn && this.role === "admin";
  92. },
  93. isOwnerOrAdmin() {
  94. return this.isOwner() || this.isAdmin();
  95. },
  96. canRequest(requireLogin = true) {
  97. return (
  98. this.station &&
  99. (!requireLogin || this.loggedIn) &&
  100. this.station.requests &&
  101. this.station.requests.enabled &&
  102. (this.station.requests.access === "user" ||
  103. (this.station.requests.access === "owner" &&
  104. this.isOwnerOrAdmin()))
  105. );
  106. },
  107. ...mapActions("modalVisibility", ["openModal"])
  108. }
  109. };
  110. </script>
  111. <style lang="less" scoped>
  112. .night-mode {
  113. #tab-selection .button {
  114. background: var(--dark-grey);
  115. color: var(--white);
  116. }
  117. .tab.requests-tab {
  118. background-color: var(--dark-grey-3) !important;
  119. border: 0 !important;
  120. }
  121. }
  122. #tabs-container .tab {
  123. width: 100%;
  124. height: calc(100% - 36px);
  125. position: absolute;
  126. border: 1px solid var(--light-grey-3);
  127. border-top: 0;
  128. }
  129. #tab-selection {
  130. display: flex;
  131. overflow-x: auto;
  132. .button {
  133. border-radius: @border-radius @border-radius 0 0;
  134. border: 0;
  135. text-transform: uppercase;
  136. font-size: 17px;
  137. color: var(--dark-grey-3);
  138. background-color: var(--light-grey-2);
  139. flex-grow: 1;
  140. &:not(:first-of-type) {
  141. margin-left: 5px;
  142. }
  143. }
  144. .selected {
  145. background-color: var(--primary-color) !important;
  146. color: var(--white) !important;
  147. font-weight: 600;
  148. }
  149. }
  150. :deep(.nothing-here-text) {
  151. height: 100%;
  152. }
  153. :deep(.tab) {
  154. .nothing-here-text:not(:only-child) {
  155. height: calc(100% - 40px);
  156. }
  157. &.requests-tab {
  158. background-color: var(--white);
  159. margin-bottom: 20px;
  160. border-radius: 0 0 @border-radius @border-radius;
  161. max-height: 100%;
  162. padding: 15px 10px;
  163. overflow-y: auto;
  164. .scrollable-list {
  165. padding: 10px 0;
  166. }
  167. }
  168. }
  169. :deep(.tab-actionable-button) {
  170. width: calc(100% - 20px);
  171. height: 40px;
  172. border-radius: @border-radius;
  173. margin: 10px;
  174. position: absolute;
  175. bottom: 0;
  176. border: 0;
  177. background-color: var(--primary-color) !important;
  178. color: var(--white) !important;
  179. &:active,
  180. &:focus {
  181. border: 0;
  182. }
  183. &:hover,
  184. &:focus {
  185. background-color: var(--primary-color) !important;
  186. filter: brightness(90%);
  187. }
  188. }
  189. :deep(.scrollable-list) {
  190. width: 100%;
  191. max-height: calc(100% - 40px - 20px);
  192. overflow: auto;
  193. padding: 10px;
  194. .song-item:not(:last-of-type) {
  195. margin-bottom: 10px;
  196. }
  197. }
  198. </style>