[client] minor refactors

This commit is contained in:
geoffrey45 2022-03-27 18:22:35 +03:00
parent 9ada6c9058
commit e4640d9985
10 changed files with 128 additions and 57 deletions

View File

@ -41,7 +41,7 @@ $accent: $indigo;
$cta: $blue;
$danger: $red;
$track-hover: $gray4;
$context: $gray4;
$context: $gray5;
// media query mixins
@mixin phone-only {

View File

@ -1,30 +1,47 @@
<template>
<div
class="new-notif rounded"
:class="{ 'notif-error': notif.type == NotificationType.Error }"
v-if="notif.visible"
>
<div>{{ notif.text }}</div>
<div class="toasts" v-if="notifStore.notifs">
<div
class="new-notif rounded"
:class="[
{ 'notif-error': notif.type == NotifType.Error },
{
'notif-info': notif.type == NotifType.Info,
},
]"
v-for="notif in notifStore.notifs"
>
<div>{{ notif.text }}</div>
</div>
</div>
</template>
<script setup lang="ts">
import { useNotificationStore, NotificationType } from "../stores/notification";
import { useNotifStore, NotifType } from "../stores/notification";
const notif = useNotificationStore();
const notifStore = useNotifStore();
</script>
<style lang="scss">
.new-notif {
.toasts {
position: fixed;
z-index: 2000;
width: 25rem;
bottom: 2rem;
padding: $small;
left: 50%;
translate: -50%;
background-color: rgb(5, 62, 168);
z-index: 100;
display: flex;
flex-direction: column-reverse;
gap: $small;
}
.new-notif {
width: 20rem;
height: 3.5rem;
bottom: 2rem;
padding: $small;
background-color: $green;
display: grid;
place-items: center;
align-items: center;
box-shadow: 0px 0px 2rem rgb(0, 0, 0);
.link {
font-weight: bold;
@ -35,4 +52,8 @@ const notif = useNotificationStore();
.notif-error {
background-color: $red;
}
.notif-info {
background-color: $gray2;
}
</style>

View File

@ -32,6 +32,7 @@
class="context-item"
v-for="child in option.children"
:key="child"
:class="[{ critical: child.critical }, child.type]"
@click="child.action()"
>
<div class="label ellip">
@ -56,11 +57,11 @@ const context = useContextStore();
left: 0;
width: 12rem;
height: min-content;
z-index: 100000 !important;
z-index: 10;
transform: scale(0);
padding: $small;
background: $gray3;
background: $context;
transform-origin: top left;
font-size: 0.875rem;
@ -74,6 +75,7 @@ const context = useContextStore();
border-radius: $small;
color: rgb(255, 255, 255);
position: relative;
text-transform: capitalize;
.more {
height: 1.5rem;
@ -90,7 +92,7 @@ const context = useContextStore();
max-height: 21.25rem;
padding: $small !important;
background: $gray3;
background-color: $context;
transform: scale(0);
transform-origin: left;
}
@ -173,7 +175,6 @@ const context = useContextStore();
.context-normalizedY {
.context-item > .children {
bottom: -0.5rem;
transform-origin: bottom right;
}
}

View File

@ -16,6 +16,12 @@
<script setup lang="ts">
import { onMounted } from "vue";
import { createNewPlaylist } from "../../composables/playlists";
import { Track } from "../../interfaces";
import { Notification, NotifType } from "../../stores/notification";
const props = defineProps<{
track: Track;
}>();
onMounted(() => {
document.getElementById("modal-playlist-name-input").focus();
@ -33,7 +39,16 @@ function create(e: Event) {
const name = (e.target as HTMLFormElement).elements["name"].value;
if (name.trim()) {
createNewPlaylist(name).then(() => emit("hideModal"));
createNewPlaylist(name, props.track).then((status: boolean) => {
if (status) {
emit("hideModal");
}
});
} else {
new Notification(
"A Playlist name can not be empty",
NotifType.Error
);
}
}
</script>

View File

@ -65,7 +65,6 @@ import perks from "../../composables/perks.js";
import state from "../../composables/state";
import useContextStore from "../../stores/context";
import useModalStore from "../../stores/modal";
import usePlaylistStore from "../../stores/playlists";
import { ref } from "vue";
import trackContext from "../../contexts/track_context";
@ -73,7 +72,6 @@ import { Track } from "../../interfaces.js";
const contextStore = useContextStore();
const modalStore = useModalStore();
const playlistStore = usePlaylistStore();
const context_on = ref(false);

View File

@ -1,25 +1,40 @@
import axios from "axios";
import { Playlist } from "../interfaces";
import { Notification, NotificationType } from "../stores/notification";
import { Playlist, Track } from "../interfaces";
import { Notification, NotifType } from "../stores/notification";
import state from "./state";
/**
* Creates a new playlist on the server.
* @param playlist_name The name of the playlist to create.
*/
async function createNewPlaylist(playlist_name: string) {
async function createNewPlaylist(playlist_name: string, track?: Track) {
let status = false;
await axios
.post(state.settings.uri + "/playlist/new", {
name: playlist_name,
})
.then(() => {
.then((res) => {
new Notification("✅ Playlist created successfullly!");
if (track) {
setTimeout(() => {
addTrackToPlaylist(res.data.playlist, track);
}, 1000);
}
status = true;
})
.catch((err) => {
if (err.response.status == 409) {
new Notification("❌ Playlist already exists!", NotificationType.Error);
new Notification(
"That playlist already exists ... you might want to try another name!",
NotifType.Error
);
}
});
return status;
}
/**
@ -43,4 +58,20 @@ async function getAllPlaylists(): Promise<Playlist[]> {
return playlists;
}
export { createNewPlaylist, getAllPlaylists };
async function addTrackToPlaylist(playlist: Playlist, track: Track) {
const uri = `${state.settings.uri}/playlist/${playlist.playlistid}/add`;
console.log(track.trackid, playlist.playlistid);
await axios
.post(uri, { track: track.trackid })
.then(() => {
new Notification(track.title + " added to " + playlist.name);
})
.catch((error) => {
if (error.response.status == 409) {
new Notification("Track already exists in playlist", NotifType.Info);
}
});
}
export { createNewPlaylist, getAllPlaylists, addTrackToPlaylist };

View File

@ -1,7 +1,7 @@
import { Playlist, Track } from "../interfaces";
import Router from "../router";
import { Option } from "../interfaces";
import { getAllPlaylists } from "../composables/playlists";
import { getAllPlaylists, addTrackToPlaylist } from "../composables/playlists";
/**
* Returns a list of context menu items for a track.
@ -11,17 +11,20 @@ import { getAllPlaylists } from "../composables/playlists";
*/
export default async (track: Track, modalStore: any): Promise<Option[]> => {
const separator: Option = {
type: "separator",
};
const single_artist = track.artists.length === 1;
let playlists = <Option[]>[];
const p = await getAllPlaylists();
playlists = p.map((playlist: Playlist) => {
return <Option>{
label: playlist.name,
action: () => {
console.log(playlist.name);
addTrackToPlaylist(playlist, track);
},
};
});
@ -43,12 +46,11 @@ export default async (track: Track, modalStore: any): Promise<Option[]> => {
const new_playlist = <Option>{
label: "New playlist",
action: () => {
modalStore.showModal(modalStore.options.newPlaylist);
modalStore.showNewPlaylistModal(track);
},
};
console.log([new_playlist, ...playlists]);
return [new_playlist, ...playlists];
return [new_playlist, separator, ...playlists];
}
const add_to_playlist: Option = {
@ -115,10 +117,6 @@ export default async (track: Track, modalStore: any): Promise<Option[]> => {
icon: "heart",
};
const separator: Option = {
type: "separator",
};
const options: Option[] = [
add_to_playlist,
add_to_q,

View File

@ -1,3 +1,5 @@
import { NotifType } from "./stores/enums";
interface Track {
trackid: string;
title: string;
@ -52,4 +54,9 @@ interface Playlist {
image?: string;
}
export { Track, Folder, AlbumInfo, Artist, Option, Playlist };
interface Notif {
text: string;
type: NotifType;
}
export { Track, Folder, AlbumInfo, Artist, Option, Playlist, Notif };

5
src/stores/enums.ts Normal file
View File

@ -0,0 +1,5 @@
export enum NotifType {
Success,
Info,
Error
}

View File

@ -1,34 +1,29 @@
import { defineStore } from "pinia";
import { Notif } from "../interfaces";
import { NotifType } from "./enums";
enum NotificationType {
Success,
Error,
}
const useNotificationStore = defineStore("notification", {
const useNotifStore = defineStore("notification", {
state: () => ({
text: "",
type: NotificationType.Success,
visible: false,
notifs: <Notif[]>[],
}),
actions: {
showNotification(new_text: string, new_type?: NotificationType) {
console.log(arguments);
this.text = new_text;
this.type = new_type;
this.visible = true;
showNotification(new_text: string, new_type?: NotifType) {
this.notifs.push(<Notif>{
text: new_text,
type: new_type,
});
setTimeout(() => {
this.visible = false;
}, 2000);
this.notifs.shift();
}, 3000);
},
},
});
class Notification {
constructor(text: string, type?: NotificationType) {
useNotificationStore().showNotification(text, type);
constructor(text: string, type?: NotifType) {
useNotifStore().showNotification(text, type);
}
}
export { useNotificationStore, Notification, NotificationType };
export { useNotifStore, Notification, NotifType };