|
@@ -1,17 +1,15 @@
|
|
|
<template>
|
|
|
<div class="station-settings">
|
|
|
- <label class="label">Change Station Name</label>
|
|
|
+ <label class="label">Name</label>
|
|
|
<div class="control is-grouped input-with-button">
|
|
|
<p class="control is-expanded">
|
|
|
<input class="input" type="text" v-model="station.name" />
|
|
|
</p>
|
|
|
<p class="control">
|
|
|
- <a class="button is-info" @click.prevent="saveChanges()"
|
|
|
- >Save</a
|
|
|
- >
|
|
|
+ <a class="button is-info" @click.prevent="updateName()">Save</a>
|
|
|
</p>
|
|
|
</div>
|
|
|
- <label class="label">Change Station Display Name</label>
|
|
|
+ <label class="label">Display Name</label>
|
|
|
<div class="control is-grouped input-with-button">
|
|
|
<p class="control is-expanded">
|
|
|
<input
|
|
@@ -21,12 +19,12 @@
|
|
|
/>
|
|
|
</p>
|
|
|
<p class="control">
|
|
|
- <a class="button is-info" @click.prevent="saveChanges()"
|
|
|
+ <a class="button is-info" @click.prevent="updateDisplayName()"
|
|
|
>Save</a
|
|
|
>
|
|
|
</p>
|
|
|
</div>
|
|
|
- <label class="label">Change Description</label>
|
|
|
+ <label class="label">Description</label>
|
|
|
<div class="control is-grouped input-with-button">
|
|
|
<p class="control is-expanded">
|
|
|
<input
|
|
@@ -36,7 +34,7 @@
|
|
|
/>
|
|
|
</p>
|
|
|
<p class="control">
|
|
|
- <a class="button is-info" @click.prevent="saveChanges()"
|
|
|
+ <a class="button is-info" @click.prevent="updateDescription()"
|
|
|
>Save</a
|
|
|
>
|
|
|
</p>
|
|
@@ -61,7 +59,7 @@
|
|
|
<button
|
|
|
class="blue"
|
|
|
v-if="station.theme !== 'blue'"
|
|
|
- @click="updateThemeLocal('blue')"
|
|
|
+ @click="updateTheme('blue')"
|
|
|
>
|
|
|
<i class="material-icons">palette</i>
|
|
|
Blue
|
|
@@ -69,7 +67,7 @@
|
|
|
<button
|
|
|
class="purple"
|
|
|
v-if="station.theme !== 'purple'"
|
|
|
- @click="updateThemeLocal('purple')"
|
|
|
+ @click="updateTheme('purple')"
|
|
|
>
|
|
|
<i class="material-icons">palette</i>
|
|
|
Purple
|
|
@@ -77,7 +75,7 @@
|
|
|
<button
|
|
|
class="teal"
|
|
|
v-if="station.theme !== 'teal'"
|
|
|
- @click="updateThemeLocal('teal')"
|
|
|
+ @click="updateTheme('teal')"
|
|
|
>
|
|
|
<i class="material-icons">palette</i>
|
|
|
Teal
|
|
@@ -85,7 +83,7 @@
|
|
|
<button
|
|
|
class="orange"
|
|
|
v-if="station.theme !== 'orange'"
|
|
|
- @click="updateThemeLocal('orange')"
|
|
|
+ @click="updateTheme('orange')"
|
|
|
>
|
|
|
<i class="material-icons">palette</i>
|
|
|
Orange
|
|
@@ -113,7 +111,7 @@
|
|
|
<button
|
|
|
class="green"
|
|
|
v-if="station.privacy !== 'public'"
|
|
|
- @click="updatePrivacyLocal('public')"
|
|
|
+ @click="updatePrivacy('public')"
|
|
|
>
|
|
|
<i class="material-icons">{{
|
|
|
privacyButtons["public"].iconName
|
|
@@ -123,7 +121,7 @@
|
|
|
<button
|
|
|
class="orange"
|
|
|
v-if="station.privacy !== 'unlisted'"
|
|
|
- @click="updatePrivacyLocal('unlisted')"
|
|
|
+ @click="updatePrivacy('unlisted')"
|
|
|
>
|
|
|
<i class="material-icons">{{
|
|
|
privacyButtons["unlisted"].iconName
|
|
@@ -133,7 +131,7 @@
|
|
|
<button
|
|
|
class="red"
|
|
|
v-if="station.privacy !== 'private'"
|
|
|
- @click="updatePrivacyLocal('private')"
|
|
|
+ @click="updatePrivacy('private')"
|
|
|
>
|
|
|
<i class="material-icons">{{
|
|
|
privacyButtons["private"].iconName
|
|
@@ -170,7 +168,7 @@
|
|
|
<button
|
|
|
class="blue"
|
|
|
v-if="station.partyMode"
|
|
|
- @click="updatePartyModeLocal(false)"
|
|
|
+ @click="updatePartyMode(false)"
|
|
|
>
|
|
|
<i class="material-icons">playlist_play</i>
|
|
|
Playlist
|
|
@@ -178,7 +176,7 @@
|
|
|
<button
|
|
|
class="yellow"
|
|
|
v-if="!station.partyMode"
|
|
|
- @click="updatePartyModeLocal(true)"
|
|
|
+ @click="updatePartyMode(true)"
|
|
|
>
|
|
|
<i class="material-icons">emoji_people</i>
|
|
|
Party
|
|
@@ -212,7 +210,7 @@
|
|
|
<button
|
|
|
class="blue"
|
|
|
v-if="station.playMode === 'sequential'"
|
|
|
- @click="updatePlayModeLocal('random')"
|
|
|
+ @click="updatePlayMode('random')"
|
|
|
>
|
|
|
<i class="material-icons">shuffle</i>
|
|
|
Random
|
|
@@ -220,7 +218,7 @@
|
|
|
<button
|
|
|
class="blue"
|
|
|
v-if="station.playMode === 'random'"
|
|
|
- @click="updatePlayModeLocal('sequential')"
|
|
|
+ @click="updatePlayMode('sequential')"
|
|
|
>
|
|
|
<i class="material-icons">format_list_numbered</i>
|
|
|
Sequential
|
|
@@ -234,44 +232,44 @@
|
|
|
class="small-section"
|
|
|
>
|
|
|
<label class="label">Queue lock</label>
|
|
|
- <div class="button-wrapper">
|
|
|
- <button
|
|
|
- :class="{
|
|
|
- green: station.locked,
|
|
|
- red: !station.locked
|
|
|
- }"
|
|
|
- @click="
|
|
|
- station.locked
|
|
|
- ? updateQueueLockLocal(true)
|
|
|
- : updateQueueLockLocal(false)
|
|
|
- "
|
|
|
- >
|
|
|
- <i class="material-icons">{{
|
|
|
- station.locked ? "lock" : "lock_open"
|
|
|
- }}</i>
|
|
|
- {{ station.locked ? "Locked" : "Unlocked" }}
|
|
|
- </button>
|
|
|
- <transition name="slide-down">
|
|
|
- <button
|
|
|
- class="green"
|
|
|
- v-if="!station.locked"
|
|
|
- @click="updateQueueLockLocal(true)"
|
|
|
- >
|
|
|
- <i class="material-icons">lock</i>
|
|
|
- Locked
|
|
|
- </button>
|
|
|
- </transition>
|
|
|
- <transition name="slide-down">
|
|
|
+ <tippy
|
|
|
+ class="button-wrapper"
|
|
|
+ theme="addToPlaylist"
|
|
|
+ interactive="true"
|
|
|
+ placement="bottom"
|
|
|
+ trigger="click"
|
|
|
+ append-to="parent"
|
|
|
+ >
|
|
|
+ <template #trigger>
|
|
|
<button
|
|
|
- class="red"
|
|
|
- v-if="station.locked"
|
|
|
- @click="updateQueueLockLocal(false)"
|
|
|
+ :class="{
|
|
|
+ green: station.locked,
|
|
|
+ red: !station.locked
|
|
|
+ }"
|
|
|
>
|
|
|
- <i class="material-icons">lock_open</i>
|
|
|
- Unlocked
|
|
|
+ <i class="material-icons">{{
|
|
|
+ station.locked ? "lock" : "lock_open"
|
|
|
+ }}</i>
|
|
|
+ {{ station.locked ? "Locked" : "Unlocked" }}
|
|
|
</button>
|
|
|
- </transition>
|
|
|
- </div>
|
|
|
+ </template>
|
|
|
+ <button
|
|
|
+ class="green"
|
|
|
+ v-if="!station.locked"
|
|
|
+ @click="updateQueueLock(true)"
|
|
|
+ >
|
|
|
+ <i class="material-icons">lock</i>
|
|
|
+ Locked
|
|
|
+ </button>
|
|
|
+ <button
|
|
|
+ class="red"
|
|
|
+ v-if="station.locked"
|
|
|
+ @click="updateQueueLock(false)"
|
|
|
+ >
|
|
|
+ <i class="material-icons">lock_open</i>
|
|
|
+ Unlocked
|
|
|
+ </button>
|
|
|
+ </tippy>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
@@ -280,6 +278,10 @@
|
|
|
<script>
|
|
|
import { mapState, mapGetters } from "vuex";
|
|
|
|
|
|
+import Toast from "toasters";
|
|
|
+
|
|
|
+import validation from "@/validation";
|
|
|
+
|
|
|
export default {
|
|
|
data() {
|
|
|
return {
|
|
@@ -300,8 +302,8 @@ export default {
|
|
|
};
|
|
|
},
|
|
|
computed: {
|
|
|
- ...mapState({
|
|
|
- station: state => state.station.station,
|
|
|
+ ...mapState("modals/editStation", {
|
|
|
+ station: state => state.station,
|
|
|
originalStation: state => state.originalStation
|
|
|
}),
|
|
|
...mapGetters({
|
|
@@ -309,11 +311,185 @@ export default {
|
|
|
})
|
|
|
},
|
|
|
methods: {
|
|
|
- updateThemeLocal() {},
|
|
|
- updatePrivacyLocal() {},
|
|
|
- updatePartyModeLocal() {},
|
|
|
- updatePlayModeLocal() {},
|
|
|
- updateQueueLockLocal() {}
|
|
|
+ updateName() {
|
|
|
+ if (this.originalStation.name !== this.station.name) {
|
|
|
+ const { name } = this.station;
|
|
|
+ if (!validation.isLength(name, 2, 16)) {
|
|
|
+ new Toast("Name must have between 2 and 16 characters.");
|
|
|
+ } else if (!validation.regex.az09_.test(name)) {
|
|
|
+ new Toast(
|
|
|
+ "Invalid name format. Allowed characters: a-z, 0-9 and _."
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ this.socket.dispatch(
|
|
|
+ "stations.updateName",
|
|
|
+ this.station._id,
|
|
|
+ name,
|
|
|
+ res => {
|
|
|
+ new Toast(res.message);
|
|
|
+
|
|
|
+ if (res.status === "success") {
|
|
|
+ this.station.name = name;
|
|
|
+ this.originalStation.name = name;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ new Toast("Please make a change before saving.");
|
|
|
+ }
|
|
|
+ },
|
|
|
+ updateDisplayName() {
|
|
|
+ if (this.originalStation.displayName !== this.station.displayName) {
|
|
|
+ const { displayName } = this.station;
|
|
|
+ if (!validation.isLength(displayName, 2, 32)) {
|
|
|
+ new Toast(
|
|
|
+ "Display name must have between 2 and 32 characters."
|
|
|
+ );
|
|
|
+ } else if (!validation.regex.ascii.test(displayName)) {
|
|
|
+ new Toast(
|
|
|
+ "Invalid display name format. Only ASCII characters are allowed."
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ this.socket.dispatch(
|
|
|
+ "stations.updateDisplayName",
|
|
|
+ this.station._id,
|
|
|
+ displayName,
|
|
|
+ res => {
|
|
|
+ new Toast(res.message);
|
|
|
+
|
|
|
+ if (res.status === "success") {
|
|
|
+ this.station.displayName = displayName;
|
|
|
+ this.originalStation.displayName = displayName;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ new Toast("Please make a change before saving.");
|
|
|
+ }
|
|
|
+ },
|
|
|
+ updateDescription() {
|
|
|
+ if (this.originalStation.description !== this.station.description) {
|
|
|
+ const { description } = this.station;
|
|
|
+ const characters = description.split("").filter(character => {
|
|
|
+ return character.charCodeAt(0) === 21328;
|
|
|
+ });
|
|
|
+ if (!validation.isLength(description, 2, 200)) {
|
|
|
+ new Toast(
|
|
|
+ "Description must have between 2 and 200 characters."
|
|
|
+ );
|
|
|
+ } else if (characters.length !== 0) {
|
|
|
+ new Toast("Invalid description format.");
|
|
|
+ } else {
|
|
|
+ this.socket.dispatch(
|
|
|
+ "stations.updateDescription",
|
|
|
+ this.station._id,
|
|
|
+ description,
|
|
|
+ res => {
|
|
|
+ new Toast(res.message);
|
|
|
+
|
|
|
+ if (res.status === "success") {
|
|
|
+ this.station.description = description;
|
|
|
+ this.originalStation.description = description;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ new Toast("Please make a change before saving.");
|
|
|
+ }
|
|
|
+ },
|
|
|
+ updateTheme(theme) {
|
|
|
+ if (this.station.theme !== theme) {
|
|
|
+ this.socket.dispatch(
|
|
|
+ "stations.updateTheme",
|
|
|
+ this.station._id,
|
|
|
+ theme,
|
|
|
+ res => {
|
|
|
+ new Toast(res.message);
|
|
|
+
|
|
|
+ if (res.status === "success") {
|
|
|
+ this.station.theme = theme;
|
|
|
+ this.originalStation.theme = theme;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+ }
|
|
|
+ },
|
|
|
+ updatePrivacy(privacy) {
|
|
|
+ if (this.station.privacy !== privacy) {
|
|
|
+ this.socket.dispatch(
|
|
|
+ "stations.updatePrivacy",
|
|
|
+ this.station._id,
|
|
|
+ privacy,
|
|
|
+ res => {
|
|
|
+ new Toast(res.message);
|
|
|
+
|
|
|
+ if (res.status === "success") {
|
|
|
+ this.station.privacy = privacy;
|
|
|
+ this.originalStation.privacy = privacy;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+ }
|
|
|
+ },
|
|
|
+ updatePartyMode(partyMode) {
|
|
|
+ if (this.station.partyMode !== partyMode) {
|
|
|
+ this.socket.dispatch(
|
|
|
+ "stations.updatePartyMode",
|
|
|
+ this.station._id,
|
|
|
+ partyMode,
|
|
|
+ res => {
|
|
|
+ new Toast(res.message);
|
|
|
+
|
|
|
+ if (res.status === "success") {
|
|
|
+ this.station.partyMode = partyMode;
|
|
|
+ this.originalStation.partyMode = partyMode;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+ }
|
|
|
+ },
|
|
|
+ updatePlayMode(playMode) {
|
|
|
+ if (this.station.playMode !== playMode) {
|
|
|
+ this.socket.dispatch(
|
|
|
+ "stations.updatePlayMode",
|
|
|
+ this.station._id,
|
|
|
+ playMode,
|
|
|
+ res => {
|
|
|
+ new Toast(res.message);
|
|
|
+
|
|
|
+ if (res.status === "success") {
|
|
|
+ this.station.playMode = playMode;
|
|
|
+ this.originalStation.playMode = playMode;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+ }
|
|
|
+ },
|
|
|
+ updateQueueLock(locked) {
|
|
|
+ if (this.station.locked !== locked) {
|
|
|
+ this.socket.dispatch(
|
|
|
+ "stations.toggleLock",
|
|
|
+ this.station._id,
|
|
|
+ res => {
|
|
|
+ if (res.status === "success") {
|
|
|
+ if (this.originalStation) {
|
|
|
+ this.station.locked = res.data;
|
|
|
+ this.originalStation.locked = res.data;
|
|
|
+ }
|
|
|
+
|
|
|
+ new Toast(
|
|
|
+ `Toggled queue lock successfully to ${res.data}`
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ new Toast("Failed to toggle queue lock.");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
};
|
|
|
</script>
|