123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498 |
- <template>
- <modal title="Edit Station">
- <template v-slot:body>
- <label class="label">Name</label>
- <p class="control">
- <input
- v-model="editing.name"
- class="input"
- type="text"
- placeholder="Station Name"
- />
- </p>
- <label class="label">Display name</label>
- <p class="control">
- <input
- v-model="editing.displayName"
- class="input"
- type="text"
- placeholder="Station Display Name"
- />
- </p>
- <label class="label">Description</label>
- <p class="control">
- <input
- v-model="editing.description"
- class="input"
- type="text"
- placeholder="Station Description"
- />
- </p>
- <label class="label">Privacy</label>
- <p class="control">
- <span class="select">
- <select v-model="editing.privacy">
- <option value="public">Public</option>
- <option value="unlisted">Unlisted</option>
- <option value="private">Private</option>
- </select>
- </span>
- </p>
- <br />
- <p class="control" v-if="station.type === 'community'">
- <label class="checkbox party-mode-inner">
- <input v-model="editing.partyMode" type="checkbox" />
- Party mode
- </label>
- </p>
- <small v-if="station.type === 'community'"
- >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 />
- <div v-if="station.type === 'community' && station.partyMode">
- <br />
- <br />
- <label class="label">Queue lock</label>
- <small v-if="station.partyMode"
- >With the queue locked, only owners (you) can add songs to
- the queue.</small
- >
- <br />
- <button
- v-if="!station.locked"
- class="button is-danger"
- @click="$parent.toggleLock()"
- >
- Lock the queue
- </button>
- <button
- v-if="station.locked"
- class="button is-success"
- @click="$parent.toggleLock()"
- >
- Unlock the queue
- </button>
- </div>
- <div
- v-if="station.type === 'official'"
- class="control is-grouped genre-wrapper"
- >
- <div class="sector">
- <p class="control has-addons">
- <input
- id="new-genre-edit"
- class="input"
- type="text"
- placeholder="Genre"
- @keyup.enter="addGenre()"
- />
- <a class="button is-info" href="#" @click="addGenre()"
- >Add genre</a
- >
- </p>
- <span
- v-for="(genre, index) in editing.genres"
- :key="index"
- class="tag is-info"
- >
- {{ genre }}
- <button
- class="delete is-info"
- @click="removeGenre(index)"
- />
- </span>
- </div>
- <div class="sector">
- <p class="control has-addons">
- <input
- id="new-blacklisted-genre-edit"
- class="input"
- type="text"
- placeholder="Blacklisted Genre"
- @keyup.enter="addBlacklistedGenre()"
- />
- <a
- class="button is-info"
- href="#"
- @click="addBlacklistedGenre()"
- >Add blacklisted genre</a
- >
- </p>
- <span
- v-for="(genre, index) in editing.blacklistedGenres"
- :key="index"
- class="tag is-info"
- >
- {{ genre }}
- <button
- class="delete is-info"
- @click="removeBlacklistedGenre(index)"
- />
- </span>
- </div>
- </div>
- </template>
- <template v-slot:footer>
- <button class="button is-success" v-on:click="update()">
- Update Settings
- </button>
- <button
- v-if="station.type === 'community'"
- class="button is-danger"
- @click="deleteStation()"
- >
- Delete station
- </button>
- </template>
- </modal>
- </template>
- <script>
- import { mapState } from "vuex";
- import { Toast } from "vue-roaster";
- import Modal from "../Modals/Modal.vue";
- import io from "../../io";
- import validation from "../../validation";
- export default {
- computed: mapState("admin/stations", {
- station: state => state.station,
- editing: state => state.editing
- }),
- mounted() {
- const _this = this;
- io.getSocket(socket => {
- _this.socket = socket;
- return socket;
- });
- },
- methods: {
- update() {
- if (this.station.name !== this.editing.name) this.updateName();
- if (this.station.displayName !== this.editing.displayName)
- this.updateDisplayName();
- if (this.station.description !== this.editing.description)
- this.updateDescription();
- if (this.station.privacy !== this.editing.privacy)
- this.updatePrivacy();
- if (this.station.partyMode !== this.editing.partyMode)
- this.updatePartyMode();
- if (
- this.station.genres.toString() !==
- this.editing.genres.toString()
- )
- this.updateGenres();
- if (
- this.station.blacklistedGenres.toString() !==
- this.editing.blacklistedGenres.toString()
- )
- this.updateBlacklistedGenres();
- },
- updateName() {
- const { name } = this.editing;
- if (!validation.isLength(name, 2, 16))
- return Toast.methods.addToast(
- "Name must have between 2 and 16 characters.",
- 8000
- );
- if (!validation.regex.az09_.test(name))
- return Toast.methods.addToast(
- "Invalid name format. Allowed characters: a-z, 0-9 and _.",
- 8000
- );
- return this.socket.emit(
- "stations.updateName",
- this.editing._id,
- name,
- res => {
- if (res.status === "success") {
- if (this.station) this.station.name = name;
- this.$parent.stations.forEach((station, index) => {
- if (station._id === this.editing._id) {
- this.$parent.stations[index].name = name;
- return name;
- }
- return false;
- });
- }
- Toast.methods.addToast(res.message, 8000);
- }
- );
- },
- updateDisplayName() {
- const { displayName } = this.editing;
- if (!validation.isLength(displayName, 2, 32))
- return Toast.methods.addToast(
- "Display name must have between 2 and 32 characters.",
- 8000
- );
- if (!validation.regex.azAZ09_.test(displayName))
- return Toast.methods.addToast(
- "Invalid display name format. Allowed characters: a-z, A-Z, 0-9 and _.",
- 8000
- );
- return this.socket.emit(
- "stations.updateDisplayName",
- this.editing._id,
- displayName,
- res => {
- if (res.status === "success") {
- if (this.station) {
- this.station.displayName = displayName;
- return displayName;
- }
- this.$parent.stations.forEach((station, index) => {
- if (station._id === this.editing._id) {
- this.$parent.stations[
- index
- ].displayName = displayName;
- return displayName;
- }
- return false;
- });
- }
- return Toast.methods.addToast(res.message, 8000);
- }
- );
- },
- updateDescription() {
- const _this = this;
- const { description } = this.editing;
- if (!validation.isLength(description, 2, 200))
- return Toast.methods.addToast(
- "Description must have between 2 and 200 characters.",
- 8000
- );
- let characters = description.split("");
- characters = characters.filter(character => {
- return character.charCodeAt(0) === 21328;
- });
- if (characters.length !== 0)
- return Toast.methods.addToast(
- "Invalid description format. Swastika's are not allowed.",
- 8000
- );
- return this.socket.emit(
- "stations.updateDescription",
- this.editing._id,
- description,
- res => {
- if (res.status === "success") {
- if (_this.station) {
- _this.station.description = description;
- return description;
- }
- _this.$parent.stations.forEach((station, index) => {
- if (station._id === _this.editing._id) {
- _this.$parent.stations[
- index
- ].description = description;
- return description;
- }
- return false;
- });
- return Toast.methods.addToast(res.message, 4000);
- }
- return Toast.methods.addToast(res.message, 8000);
- }
- );
- },
- updatePrivacy() {
- const _this = this;
- this.socket.emit(
- "stations.updatePrivacy",
- this.editing._id,
- this.editing.privacy,
- res => {
- if (res.status === "success") {
- if (_this.station)
- _this.station.privacy = _this.editing.privacy;
- else {
- _this.$parent.stations.forEach((station, index) => {
- if (station._id === _this.editing._id) {
- _this.$parent.stations[index].privacy =
- _this.editing.privacy;
- return _this.editing.privacy;
- }
- return false;
- });
- }
- return Toast.methods.addToast(res.message, 4000);
- }
- return Toast.methods.addToast(res.message, 8000);
- }
- );
- },
- updateGenres() {
- const _this = this;
- this.socket.emit(
- "stations.updateGenres",
- this.editing._id,
- this.editing.genres,
- res => {
- if (res.status === "success") {
- const genres = JSON.parse(
- JSON.stringify(_this.editing.genres)
- );
- if (_this.station) _this.station.genres = genres;
- _this.$parent.stations.forEach((station, index) => {
- if (station._id === _this.editing._id) {
- _this.$parent.stations[index].genres = genres;
- return genres;
- }
- return false;
- });
- return Toast.methods.addToast(res.message, 4000);
- }
- return Toast.methods.addToast(res.message, 8000);
- }
- );
- },
- updateBlacklistedGenres() {
- const _this = this;
- this.socket.emit(
- "stations.updateBlacklistedGenres",
- this.editing._id,
- this.editing.blacklistedGenres,
- res => {
- if (res.status === "success") {
- const blacklistedGenres = JSON.parse(
- JSON.stringify(_this.editing.blacklistedGenres)
- );
- if (_this.station)
- _this.station.blacklistedGenres = blacklistedGenres;
- _this.$parent.stations.forEach((station, index) => {
- if (station._id === _this.editing._id) {
- _this.$parent.stations[
- index
- ].blacklistedGenres = blacklistedGenres;
- return blacklistedGenres;
- }
- return false;
- });
- return Toast.methods.addToast(res.message, 4000);
- }
- return Toast.methods.addToast(res.message, 8000);
- }
- );
- },
- updatePartyMode() {
- const _this = this;
- this.socket.emit(
- "stations.updatePartyMode",
- this.editing._id,
- this.editing.partyMode,
- res => {
- if (res.status === "success") {
- if (_this.station)
- _this.station.partyMode = _this.editing.partyMode;
- _this.$parent.stations.forEach((station, index) => {
- if (station._id === _this.editing._id) {
- _this.$parent.stations[index].partyMode =
- _this.editing.partyMode;
- return _this.editing.partyMode;
- }
- return false;
- });
- return Toast.methods.addToast(res.message, 4000);
- }
- return Toast.methods.addToast(res.message, 8000);
- }
- );
- },
- addGenre() {
- const genre = document
- .getElementById(`new-genre-edit`)
- .value.toLowerCase()
- .trim();
- if (this.editing.genres.indexOf(genre) !== -1)
- return Toast.methods.addToast("Genre already exists", 3000);
- if (genre) {
- this.editing.genres.push(genre);
- document.getElementById(`new-genre`).value = "";
- return true;
- }
- return Toast.methods.addToast("Genre cannot be empty", 3000);
- },
- removeGenre(index) {
- this.editing.genres.splice(index, 1);
- },
- addBlacklistedGenre() {
- const genre = document
- .getElementById(`new-blacklisted-genre-edit`)
- .value.toLowerCase()
- .trim();
- if (this.editing.blacklistedGenres.indexOf(genre) !== -1)
- return Toast.methods.addToast("Genre already exists", 3000);
- if (genre) {
- this.editing.blacklistedGenres.push(genre);
- document.getElementById(`new-blacklisted-genre`).value = "";
- return true;
- }
- return Toast.methods.addToast("Genre cannot be empty", 3000);
- },
- removeBlacklistedGenre(index) {
- this.editing.blacklistedGenres.splice(index, 1);
- },
- deleteStation() {
- this.socket.emit("stations.remove", this.editing._id, res => {
- Toast.methods.addToast(res.message, 8000);
- });
- }
- },
- components: { Modal }
- };
- </script>
- <style lang="scss" scoped>
- .controls {
- display: flex;
- a {
- display: flex;
- align-items: center;
- }
- }
- .table {
- margin-bottom: 0;
- }
- h5 {
- padding: 20px 0;
- }
- .party-mode-inner,
- .party-mode-outer {
- display: flex;
- align-items: center;
- }
- .select:after {
- border-color: #029ce3;
- }
- </style>
|