EditStation.vue 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. <template>
  2. <modal title="Edit Station">
  3. <template v-slot:body>
  4. <label class="label">Name</label>
  5. <p class="control">
  6. <input class="input" type="text" placeholder="Station Name" v-model="editing.name" />
  7. </p>
  8. <label class="label">Display name</label>
  9. <p class="control">
  10. <input
  11. class="input"
  12. type="text"
  13. placeholder="Station Display Name"
  14. v-model="editing.displayName"
  15. />
  16. </p>
  17. <label class="label">Description</label>
  18. <p class="control">
  19. <input
  20. class="input"
  21. type="text"
  22. placeholder="Station Description"
  23. v-model="editing.description"
  24. />
  25. </p>
  26. <label class="label">Privacy</label>
  27. <p class="control">
  28. <span class="select">
  29. <select v-model="editing.privacy">
  30. <option value="public">Public</option>
  31. <option value="unlisted">Unlisted</option>
  32. <option value="private">Private</option>
  33. </select>
  34. </span>
  35. </p>
  36. <br />
  37. <p class="control">
  38. <label class="checkbox party-mode-inner">
  39. <input type="checkbox" v-model="editing.partyMode" />
  40. &nbsp;Party mode
  41. </label>
  42. </p>
  43. <small>With party mode enabled, people can add songs to a queue that plays. With party mode disabled you can play a private playlist on loop.</small>
  44. <br />
  45. <div v-if="station.partyMode">
  46. <br />
  47. <br />
  48. <label class="label">Queue lock</label>
  49. <small
  50. v-if="station.partyMode"
  51. >With the queue locked, only owners (you) can add songs to the queue.</small>
  52. <br />
  53. <button
  54. class="button is-danger"
  55. v-if="!station.locked"
  56. v-on:click="$parent.toggleLock()"
  57. >Lock the queue</button>
  58. <button
  59. class="button is-success"
  60. v-if="station.locked"
  61. v-on:click="$parent.toggleLock()"
  62. >Unlock the queue</button>
  63. </div>
  64. </template>
  65. <template v-slot:footer>
  66. <button class="button is-success" v-on:click="update()">Update Settings</button>
  67. <button
  68. class="button is-danger"
  69. v-on:click="deleteStation()"
  70. v-if="station.type === 'community'"
  71. >Delete station</button>
  72. </template>
  73. </modal>
  74. </template>
  75. <script>
  76. import { mapState } from "vuex";
  77. import { Toast } from "vue-roaster";
  78. import Modal from "./Modal.vue";
  79. import io from "../../io";
  80. import validation from "../../validation";
  81. export default {
  82. computed: mapState("station", {
  83. station: state => state.station,
  84. editing: state => state.editing
  85. }),
  86. methods: {
  87. update: function() {
  88. if (this.station.name !== this.editing.name) this.updateName();
  89. if (this.station.displayName !== this.editing.displayName)
  90. this.updateDisplayName();
  91. if (this.station.description !== this.editing.description)
  92. this.updateDescription();
  93. if (this.station.privacy !== this.editing.privacy) this.updatePrivacy();
  94. if (this.station.partyMode !== this.editing.partyMode)
  95. this.updatePartyMode();
  96. },
  97. updateName: function() {
  98. const name = this.editing.name;
  99. if (!validation.isLength(name, 2, 16))
  100. return Toast.methods.addToast(
  101. "Name must have between 2 and 16 characters.",
  102. 8000
  103. );
  104. if (!validation.regex.az09_.test(name))
  105. return Toast.methods.addToast(
  106. "Invalid name format. Allowed characters: a-z, 0-9 and _.",
  107. 8000
  108. );
  109. this.socket.emit("stations.updateName", this.editing._id, name, res => {
  110. if (res.status === "success") {
  111. if (this.station) this.station.name = name;
  112. else {
  113. this.$parent.stations.forEach((station, index) => {
  114. if (station._id === this.editing._id)
  115. return (this.$parent.stations[index].name = name);
  116. });
  117. }
  118. }
  119. Toast.methods.addToast(res.message, 8000);
  120. });
  121. },
  122. updateDisplayName: function() {
  123. let _this = this;
  124. const displayName = this.editing.displayName;
  125. if (!validation.isLength(displayName, 2, 32))
  126. return Toast.methods.addToast(
  127. "Display name must have between 2 and 32 characters.",
  128. 8000
  129. );
  130. if (!validation.regex.azAZ09_.test(displayName))
  131. return Toast.methods.addToast(
  132. "Invalid display name format. Allowed characters: a-z, A-Z, 0-9 and _.",
  133. 8000
  134. );
  135. this.socket.emit(
  136. "stations.updateDisplayName",
  137. this.editing._id,
  138. displayName,
  139. res => {
  140. if (res.status === "success") {
  141. if (this.station) this.station.displayName = displayName;
  142. else {
  143. this.$parent.stations.forEach((station, index) => {
  144. if (station._id === this.editing._id)
  145. return (this.$parent.stations[
  146. index
  147. ].displayName = displayName);
  148. });
  149. }
  150. }
  151. Toast.methods.addToast(res.message, 8000);
  152. }
  153. );
  154. },
  155. updateDescription: function() {
  156. let _this = this;
  157. const description = this.editing.description;
  158. if (!validation.isLength(description, 2, 200))
  159. return Toast.methods.addToast(
  160. "Description must have between 2 and 200 characters.",
  161. 8000
  162. );
  163. let characters = description.split("");
  164. characters = characters.filter(character => {
  165. return character.charCodeAt(0) === 21328;
  166. });
  167. if (characters.length !== 0)
  168. return Toast.methods.addToast(
  169. "Invalid description format. Swastika's are not allowed.",
  170. 8000
  171. );
  172. this.socket.emit(
  173. "stations.updateDescription",
  174. this.editing._id,
  175. description,
  176. res => {
  177. if (res.status === "success") {
  178. if (_this.station) _this.station.description = description;
  179. else {
  180. _this.$parent.stations.forEach((station, index) => {
  181. if (station._id === station._id)
  182. return (_this.$parent.stations[
  183. index
  184. ].description = description);
  185. });
  186. }
  187. return Toast.methods.addToast(res.message, 4000);
  188. }
  189. Toast.methods.addToast(res.message, 8000);
  190. }
  191. );
  192. },
  193. updatePrivacy: function() {
  194. let _this = this;
  195. this.socket.emit(
  196. "stations.updatePrivacy",
  197. this.editing._id,
  198. this.editing.privacy,
  199. res => {
  200. if (res.status === "success") {
  201. if (_this.station) _this.station.privacy = _this.editing.privacy;
  202. else {
  203. _this.$parent.stations.forEach((station, index) => {
  204. if (station._id === station._id)
  205. return (_this.$parent.stations[index].privacy =
  206. _this.editing.privacy);
  207. });
  208. }
  209. return Toast.methods.addToast(res.message, 4000);
  210. }
  211. Toast.methods.addToast(res.message, 8000);
  212. }
  213. );
  214. },
  215. updatePartyMode: function() {
  216. let _this = this;
  217. this.socket.emit(
  218. "stations.updatePartyMode",
  219. this.editing._id,
  220. this.editing.partyMode,
  221. res => {
  222. if (res.status === "success") {
  223. if (_this.station)
  224. _this.station.partyMode = _this.editing.partyMode;
  225. else {
  226. _this.$parent.stations.forEach((station, index) => {
  227. if (station._id === station._id)
  228. return (_this.$parent.stations[index].partyMode =
  229. _this.editing.partyMode);
  230. });
  231. }
  232. return Toast.methods.addToast(res.message, 4000);
  233. }
  234. Toast.methods.addToast(res.message, 8000);
  235. }
  236. );
  237. },
  238. deleteStation: function() {
  239. let _this = this;
  240. this.socket.emit("stations.remove", this.editing._id, res => {
  241. Toast.methods.addToast(res.message, 8000);
  242. });
  243. }
  244. },
  245. mounted: function() {
  246. let _this = this;
  247. io.getSocket(socket => (_this.socket = socket));
  248. },
  249. components: { Modal }
  250. };
  251. </script>
  252. <style lang='scss' scoped>
  253. .controls {
  254. display: flex;
  255. a {
  256. display: flex;
  257. align-items: center;
  258. }
  259. }
  260. .table {
  261. margin-bottom: 0;
  262. }
  263. h5 {
  264. padding: 20px 0;
  265. }
  266. .party-mode-inner,
  267. .party-mode-outer {
  268. display: flex;
  269. align-items: center;
  270. }
  271. .select:after {
  272. border-color: #029ce3;
  273. }
  274. </style>