123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- <script setup lang="ts">
- import {
- defineProps,
- defineAsyncComponent,
- onMounted,
- ref,
- computed
- } from "vue";
- import Toast from "toasters";
- import { useModalsStore } from "@/stores/modals";
- import { useWebsocketsStore } from "@/stores/websockets";
- const Modal = defineAsyncComponent(() => import("@/components/Modal.vue"));
- const SongItem = defineAsyncComponent(
- () => import("@/components/SongItem.vue")
- );
- const { openModal, closeCurrentModal } = useModalsStore();
- const { socket } = useWebsocketsStore();
- const TAG = "CSS";
- const props = defineProps({
- modalUuid: { type: String, required: true },
- playlistId: { type: String, default: null }
- });
- const playlist = ref(null);
- const allSongs = ref(null);
- const loaded = ref(false);
- const currentConvertType = ref("artist");
- const sortBy = ref("track_count_des");
- const spotifyArtists = ref({});
- const spotifyArtistsArray = computed(() =>
- Object.entries(spotifyArtists.value)
- .map(([spotifyArtistId, spotifyArtist]) => ({
- artistId: spotifyArtistId,
- ...spotifyArtist
- }))
- .sort((a, b) => {
- if (sortBy.value === "track_count_des")
- return b.songs.length - a.songs.length;
- if (sortBy.value === "track_count_asc")
- return a.songs.length - b.songs.length;
- })
- );
- const toggleSpotifyArtistExpanded = spotifyArtistId => {
- spotifyArtists.value[spotifyArtistId].expanded =
- !spotifyArtists.value[spotifyArtistId].expanded;
- };
- onMounted(() => {
- console.debug(TAG, "On mounted start");
- console.debug(TAG, "Getting playlist", props);
- socket.dispatch("playlists.getPlaylist", props.playlistId, res => {
- console.debug(TAG, "Get playlist response", res);
- if (res.status !== "success") {
- new Toast(res.message);
- closeCurrentModal();
- return;
- }
- playlist.value = res.data.playlist;
- allSongs.value = {};
- playlist.value.songs
- .filter(song => song.mediaSource.startsWith("spotify:"))
- .forEach(song => {
- allSongs.value[song.mediaSource] = {
- song,
- track: null
- };
- });
- const mediaSources = Object.keys(allSongs.value);
- console.debug(TAG, "getTracksFromMediaSources start", mediaSources);
- socket.dispatch(
- "spotify.getTracksFromMediaSources",
- mediaSources,
- res => {
- console.debug(TAG, "getTracksFromMediaSources response", res);
- if (res.status !== "success") {
- new Toast(res.message);
- closeCurrentModal();
- return;
- }
- const { tracks } = res.data;
- Object.entries(tracks).forEach(([mediaSource, track]) => {
- allSongs.value[mediaSource].track = track;
- track.artistIds.forEach((artistId, artistIndex) => {
- if (!spotifyArtists.value[artistId]) {
- spotifyArtists.value[artistId] = {
- name: track.artists[artistIndex],
- songs: [mediaSource],
- expanded: false
- };
- } else
- spotifyArtists.value[artistId].songs.push(
- mediaSource
- );
- });
- });
- loaded.value = true;
- }
- );
- });
- console.debug(TAG, "On mounted end");
- });
- </script>
- <template>
- <div>
- <modal
- title="Convert Spotify Songs"
- class="convert-spotify-songs-modal"
- size="wide"
- @closed="closeCurrentModal()"
- >
- <template #body>
- <p>Converting by {{ currentConvertType }}</p>
- <p>Sorting by {{ sortBy }}</p>
- <br />
- <div class="column-headers">
- <div class="spotify-column-header column-header">
- <h3>Spotify</h3>
- </div>
- <div class="soumdcloud-column-header column-header">
- <h3>Soundcloud</h3>
- </div>
- </div>
- <div class="artists">
- <div
- v-for="spotifyArtist in spotifyArtistsArray"
- :key="spotifyArtist.artistId"
- class="artist-item"
- >
- <div class="spotify-section">
- <p
- @click="
- toggleSpotifyArtistExpanded(
- spotifyArtist.artistId
- )
- "
- >
- {{ spotifyArtist.name }} ({{
- spotifyArtist.songs.length
- }}
- songs)
- </p>
- <div
- class="spotify-songs"
- v-if="spotifyArtist.expanded"
- >
- <div
- v-for="mediaSource in spotifyArtist.songs"
- :key="`${spotifyArtist.artistId}-${mediaSource}`"
- class="spotify-song"
- >
- <song-item
- :song="{
- title: allSongs[mediaSource].track
- .name,
- duration:
- allSongs[mediaSource].track
- .duration,
- artists:
- allSongs[mediaSource].track
- .artists,
- thumbnail:
- allSongs[mediaSource].track
- .albumImageUrl
- }"
- :disabled-actions="[
- 'youtube',
- 'report',
- 'addToPlaylist',
- 'edit'
- ]"
- ></song-item>
- </div>
- </div>
- </div>
- <div class="soundcloud-section">
- <p>Not found</p>
- <div v-if="spotifyArtist.expanded">
- <button class="button">Get artist</button>
- </div>
- </div>
- </div>
- </div>
- </template>
- </modal>
- </div>
- </template>
- <style lang="less" scoped>
- .column-headers {
- display: flex;
- flex-direction: row;
- .column-header {
- flex: 1;
- }
- }
- .artists {
- display: flex;
- flex-direction: column;
- .artist-item {
- display: flex;
- flex-direction: column;
- row-gap: 8px;
- box-shadow: inset 0px 0px 1px white;
- width: 50%;
- position: relative;
- .spotify-section {
- display: flex;
- flex-direction: column;
- row-gap: 8px;
- padding: 8px 12px;
- .spotify-songs {
- display: flex;
- flex-direction: column;
- row-gap: 4px;
- }
- }
- .soundcloud-section {
- position: absolute;
- left: 100%;
- top: 0;
- width: 100%;
- height: 100%;
- overflow: hidden;
- box-shadow: inset 0px 0px 1px white;
- padding: 8px 12px;
- }
- }
- }
- </style>
|