EditStation.vue 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. <template>
  2. <div>
  3. <modal title='Edit Station'>
  4. <div slot='body'>
  5. <label class='label'>Name</label>
  6. <p class='control'>
  7. <input class='input' type='text' placeholder='Station Name' v-model='editing.name'>
  8. </p>
  9. <label class='label'>Display name</label>
  10. <p class='control'>
  11. <input class='input' type='text' placeholder='Station Display Name' v-model='editing.displayName'>
  12. </p>
  13. <label class='label'>Description</label>
  14. <p class='control'>
  15. <input class='input' type='text' placeholder='Station Display Name' v-model='editing.description'>
  16. </p>
  17. <label class='label'>Privacy</label>
  18. <p class='control'>
  19. <span class='select'>
  20. <select v-model='editing.privacy'>
  21. <option :value='"public"'>Public</option>
  22. <option :value='"unlisted"'>Unlisted</option>
  23. <option :value='"private"'>Private</option>
  24. </select>
  25. </span>
  26. </p>
  27. <br><br>
  28. <p class='control'>
  29. <label class="checkbox party-mode-inner">
  30. <input type="checkbox" v-model="editing.partyMode">
  31. &nbsp;Party mode
  32. </label>
  33. </p>
  34. <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><br>
  35. <div v-if="$parent.station.partyMode">
  36. <br>
  37. <br>
  38. <label class='label'>Queue lock</label>
  39. <small v-if="$parent.station.partyMode">With the queue locked, only owners (you) can add songs to the queue.</small><br>
  40. <button class='button is-danger' v-if='!$parent.station.locked' @click="$parent.toggleLock()">Lock the queue</button>
  41. <button class='button is-success' v-if='$parent.station.locked' @click="$parent.toggleLock()">Unlock the queue</button>
  42. </div>
  43. </div>
  44. <div slot='footer'>
  45. <button class='button is-success' @click='update()'>Update Settings</button>
  46. <button class='button is-danger' @click='deleteStation()' v-if="$parent.type === 'community'">Delete station</button>
  47. </div>
  48. </modal>
  49. </div>
  50. </template>
  51. <script>
  52. import { Toast } from 'vue-roaster';
  53. import Modal from './Modal.vue';
  54. import io from '../../io';
  55. import validation from '../../validation';
  56. export default {
  57. data: function() {
  58. return {
  59. editing: {
  60. _id: '',
  61. name: '',
  62. type: '',
  63. displayName: '',
  64. description: '',
  65. privacy: 'private',
  66. partyMode: false
  67. }
  68. }
  69. },
  70. methods: {
  71. update: function () {
  72. if (this.$parent.station.name !== this.editing.name) this.updateName();
  73. if (this.$parent.station.displayName !== this.editing.displayName) this.updateDisplayName();
  74. if (this.$parent.station.description !== this.editing.description) this.updateDescription();
  75. if (this.$parent.station.privacy !== this.editing.privacy) this.updatePrivacy();
  76. if (this.$parent.station.partyMode !== this.editing.partyMode) this.updatePartyMode();
  77. },
  78. updateName: function () {
  79. const name = this.editing.name;
  80. if (!validation.isLength(name, 2, 16)) return Toast.methods.addToast('Name must have between 2 and 16 characters.', 8000);
  81. if (!validation.regex.az09_.test(name)) return Toast.methods.addToast('Invalid name format. Allowed characters: a-z, 0-9 and _.', 8000);
  82. this.socket.emit('stations.updateName', this.editing._id, name, res => {
  83. if (res.status === 'success') {
  84. if (this.$parent.station) _this.$parent.station.name = name;
  85. else {
  86. this.$parent.stations.forEach((station, index) => {
  87. if (station._id === this.editing._id) return this.$parent.stations[index].name = name;
  88. });
  89. }
  90. }
  91. Toast.methods.addToast(res.message, 8000);
  92. });
  93. },
  94. updateDisplayName: function () {
  95. const displayName = this.editing.displayName;
  96. if (!validation.isLength(displayName, 2, 32)) return Toast.methods.addToast('Display name must have between 2 and 32 characters.', 8000);
  97. if (!validation.regex.azAZ09_.test(displayName)) return Toast.methods.addToast('Invalid display name format. Allowed characters: a-z, A-Z, 0-9 and _.', 8000);
  98. this.socket.emit('stations.updateDisplayName', this.editing._id, displayName, res => {
  99. if (res.status === 'success') {
  100. if (this.$parent.station) _this.$parent.station.displayName = displayName;
  101. else {
  102. this.$parent.stations.forEach((station, index) => {
  103. if (station._id === this.editing._id) return this.$parent.stations[index].displayName = displayName;
  104. });
  105. }
  106. }
  107. Toast.methods.addToast(res.message, 8000);
  108. });
  109. },
  110. updateDescription: function () {
  111. const description = this.editing.description;
  112. if (!validation.isLength(description, 2, 200)) return Toast.methods.addToast('Description must have between 2 and 200 characters.', 8000);
  113. let characters = description.split("");
  114. characters = characters.filter(function(character) {
  115. return character.charCodeAt(0) === 21328;
  116. });
  117. if (characters.length !== 0) return Toast.methods.addToast('Invalid description format. Swastika\'s are not allowed.', 8000);
  118. this.socket.emit('stations.updateDescription', this.editing._id, description, res => {
  119. if (res.status === 'success') {
  120. if (_this.$parent.station) _this.$parent.station.description = description;
  121. else {
  122. _this.$parent.stations.forEach((station, index) => {
  123. if (station._id === station._id) return _this.$parent.stations[index].description = description;
  124. });
  125. }
  126. return Toast.methods.addToast(res.message, 4000);
  127. }
  128. Toast.methods.addToast(res.message, 8000);
  129. });
  130. },
  131. updatePrivacy: function () {
  132. let _this = this;
  133. this.socket.emit('stations.updatePrivacy', this.editing._id, this.editing.privacy, res => {
  134. if (res.status === 'success') {
  135. if (_this.$parent.station) _this.$parent.station.privacy = _this.editing.privacy;
  136. else {
  137. _this.$parent.stations.forEach((station, index) => {
  138. if (station._id === station._id) return _this.$parent.stations[index].privacy = _this.editing.privacy;
  139. });
  140. }
  141. return Toast.methods.addToast(res.message, 4000);
  142. }
  143. Toast.methods.addToast(res.message, 8000);
  144. });
  145. },
  146. updatePartyMode: function () {
  147. let _this = this;
  148. this.socket.emit('stations.updatePartyMode', this.editing._id, this.editing.partyMode, res => {
  149. if (res.status === 'success') {
  150. if (_this.$parent.station) _this.$parent.station.partyMode = _this.editing.partyMode;
  151. else {
  152. _this.$parent.stations.forEach((station, index) => {
  153. if (station._id === station._id) return _this.$parent.stations[index].partyMode = _this.editing.partyMode;
  154. });
  155. }
  156. return Toast.methods.addToast(res.message, 4000);
  157. }
  158. Toast.methods.addToast(res.message, 8000);
  159. });
  160. },
  161. deleteStation: function() {
  162. let _this = this;
  163. this.socket.emit('stations.remove', this.editing._id, res => {
  164. Toast.methods.addToast(res.message, 8000);
  165. });
  166. }
  167. },
  168. ready: function () {
  169. let _this = this;
  170. io.getSocket(socket => {
  171. _this.socket = socket;
  172. });
  173. },
  174. events: {
  175. closeModal: function() {
  176. this.$parent.modals.editStation = false;
  177. },
  178. editStation: function(station) {
  179. for (let prop in station) {
  180. this.editing[prop] = station[prop];
  181. }
  182. this.$parent.modals.editStation = true;
  183. }
  184. },
  185. components: { Modal }
  186. }
  187. </script>
  188. <style type='scss' scoped>
  189. .controls {
  190. display: flex;
  191. a {
  192. display: flex;
  193. align-items: center;
  194. }
  195. }
  196. .table { margin-bottom: 0; }
  197. h5 { padding: 20px 0; }
  198. .party-mode-inner, .party-mode-outer {
  199. display: flex;
  200. align-items: center;
  201. }
  202. .select:after { border-color: #029ce3; }
  203. </style>