Skip to content

Commit a3453eb

Browse files
committed
feat(webui): implement move playlist to folder
1 parent d291f94 commit a3453eb

File tree

14 files changed

+218
-74
lines changed

14 files changed

+218
-74
lines changed
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"files": {
33
"main.css": "/static/css/main.56b69c4b.css",
4-
"main.js": "/static/js/main.2a80932d.js",
4+
"main.js": "/static/js/main.a9aaf49e.js",
55
"static/js/787.26bf0a29.chunk.js": "/static/js/787.26bf0a29.chunk.js",
66
"static/media/RockfordSans-ExtraBold.otf": "/static/media/RockfordSans-ExtraBold.1513e8fd97078bfb7708.otf",
77
"static/media/RockfordSans-Bold.otf": "/static/media/RockfordSans-Bold.c9f599ae01b13e565598.otf",
@@ -10,11 +10,11 @@
1010
"static/media/RockfordSans-Light.otf": "/static/media/RockfordSans-Light.b4a12e8abb38f7d105c4.otf",
1111
"index.html": "/index.html",
1212
"main.56b69c4b.css.map": "/static/css/main.56b69c4b.css.map",
13-
"main.2a80932d.js.map": "/static/js/main.2a80932d.js.map",
13+
"main.a9aaf49e.js.map": "/static/js/main.a9aaf49e.js.map",
1414
"787.26bf0a29.chunk.js.map": "/static/js/787.26bf0a29.chunk.js.map"
1515
},
1616
"entrypoints": [
1717
"static/css/main.56b69c4b.css",
18-
"static/js/main.2a80932d.js"
18+
"static/js/main.a9aaf49e.js"
1919
]
2020
}

webui/musicplayer/build/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>Music Player</title><script defer="defer" src="/static/js/main.2a80932d.js"></script><link href="/static/css/main.56b69c4b.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
1+
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>Music Player</title><script defer="defer" src="/static/js/main.a9aaf49e.js"></script><link href="/static/css/main.56b69c4b.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>

webui/musicplayer/build/static/js/main.2a80932d.js

Lines changed: 0 additions & 3 deletions
This file was deleted.

webui/musicplayer/build/static/js/main.2a80932d.js.map

Lines changed: 0 additions & 1 deletion
This file was deleted.

webui/musicplayer/build/static/js/main.a9aaf49e.js

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webui/musicplayer/build/static/js/main.2a80932d.js.LICENSE.txt renamed to webui/musicplayer/build/static/js/main.a9aaf49e.js.LICENSE.txt

File renamed without changes.

webui/musicplayer/build/static/js/main.a9aaf49e.js.map

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webui/musicplayer/src/Components/Folder/Folder.tsx

Lines changed: 83 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import styled from "@emotion/styled";
22
import { Cell, Grid } from "baseui/layout-grid";
3-
import { FC } from "react";
3+
import { FC, useState } from "react";
44
import { Link } from "react-router-dom";
55
import Button from "../Button";
66
import ControlBar from "../ControlBar";
@@ -9,10 +9,10 @@ import Play from "../Icons/Play";
99
import Shuffle from "../Icons/Shuffle";
1010
import MainContent from "../MainContent";
1111
import Sidebar from "../Sidebar";
12-
import TracksTable from "../TracksTable";
13-
import AlbumIcon from "../Icons/AlbumCover";
12+
import PlaylistIcon from "../Icons/PlaylistAlt";
1413
import { Track } from "../../Types";
1514
import { Folder as FolderIcon } from "@styled-icons/bootstrap";
15+
import MovePlaylistsModal from "./MovePlaylistsModal";
1616

1717
const Container = styled.div`
1818
display: flex;
@@ -83,6 +83,15 @@ const Title = styled.div`
8383
flex: 1;
8484
`;
8585

86+
const PlaylistName = styled.div`
87+
font-size: 14px;
88+
text-overflow: ellipsis;
89+
overflow: hidden;
90+
white-space: nowrap;
91+
cursor: pointer;
92+
margin-top: 15px;
93+
`;
94+
8695
const Row = styled.div`
8796
display: flex;
8897
flex-direction: row;
@@ -91,27 +100,9 @@ const Row = styled.div`
91100
margin-left: 10px;
92101
`;
93102

94-
const SeeMore = styled.div`
95-
width: 64px;
96-
font-size: 14px;
97-
color: rgba(0, 0, 0, 0.51);
98-
cursor: pointer;
99-
`;
100-
101-
const Tracks = styled.div`
102-
margin-bottom: 48px;
103-
`;
104-
105-
const AlbumCover = styled.img`
106-
height: 169px;
107-
width: 169px;
108-
border-radius: 5px;
109-
cursor: pointer;
110-
`;
111-
112-
const NoAlbumCover = styled.div`
113-
height: 169px;
114-
width: 169px;
103+
const NoPlaylistCover = styled.div`
104+
height: 220px;
105+
width: 220px;
115106
border-radius: 5px;
116107
cursor: pointer;
117108
display: flex;
@@ -120,24 +111,6 @@ const NoAlbumCover = styled.div`
120111
background-color: #ddaefb14;
121112
`;
122113

123-
const AlbumArtist = styled.div`
124-
color: #828282;
125-
margin-bottom: 56px;
126-
font-size: 14px;
127-
text-overflow: ellipsis;
128-
overflow: hidden;
129-
white-space: nowrap;
130-
cursor: pointer;
131-
`;
132-
133-
const AlbumTitle = styled.div`
134-
font-size: 14px;
135-
text-overflow: ellipsis;
136-
overflow: hidden;
137-
white-space: nowrap;
138-
cursor: pointer;
139-
`;
140-
141114
const PlaceholderWrapper = styled.div`
142115
display: flex;
143116
justify-content: center;
@@ -154,6 +127,35 @@ const Placeholder = styled.div`
154127
margin-bottom: 35px;
155128
`;
156129

130+
const Wrapper = styled.div`
131+
margin-top: 34px;
132+
margin-left: 10px;
133+
`;
134+
135+
export type PlaylistProps = {
136+
playlist: any;
137+
};
138+
139+
const Playlist: FC<PlaylistProps> = ({ playlist }) => {
140+
return (
141+
<>
142+
<Link
143+
to={`/playlists/${playlist.id}`}
144+
style={{ textDecoration: "initial" }}
145+
>
146+
<NoPlaylistCover>
147+
<PlaylistIcon
148+
size={48}
149+
color="#ab28fc"
150+
style={{ marginRight: -38, marginTop: 30 }}
151+
/>
152+
</NoPlaylistCover>
153+
<PlaylistName>{playlist.name}</PlaylistName>
154+
</Link>
155+
</>
156+
);
157+
};
158+
157159
export type FolderProps = {
158160
onBack: () => void;
159161
onClickLibraryItem: (item: string) => void;
@@ -183,30 +185,58 @@ export type FolderProps = {
183185
shuffle: boolean,
184186
position?: number
185187
) => void;
188+
onMovePlaylists: (playlistIds: string[], folderId: string) => void;
189+
folder?: any;
186190
};
187191

188192
const Folder: FC<FolderProps> = (props) => {
189-
const { onBack, onPlayNext, onCreatePlaylist } = props;
193+
const { onPlayNext, onCreatePlaylist, playlists, folder, onMovePlaylists } =
194+
props;
195+
const [isMovePlaylistsModalOpen, setIsMovePlaylistsModalOpen] =
196+
useState(false);
190197
return (
191198
<Container>
192199
<Sidebar active="artists" {...props} />
193200
<Content>
194201
<ControlBar {...props} />
195202
<MainContent displayHeader={false}>
196203
<Scrollable>
197-
<BackButton onClick={onBack}>
198-
<div style={{ marginTop: 2 }}>
199-
<ArrowBack />
200-
</div>
201-
</BackButton>
202-
<PlaceholderWrapper>
203-
<FolderIcon size={100} color="rgb(70, 70, 70)" />
204-
<Placeholder>Start moving playlists to your folder.</Placeholder>
205-
<Button onClick={() => {}}>Move Playlists</Button>
206-
</PlaceholderWrapper>
204+
{folder?.playlists?.length > 0 && (
205+
<Scrollable>
206+
<MainContent title="Playlists" placeholder="Filter Playlists">
207+
<Wrapper>
208+
<Grid gridColumns={[2, 3, 4, 6]} gridMargins={[8, 16, 18]}>
209+
{folder?.playlists.map((item: any) => (
210+
<Cell key={item.id}>
211+
<Playlist playlist={item} />
212+
</Cell>
213+
))}
214+
</Grid>
215+
</Wrapper>
216+
</MainContent>
217+
</Scrollable>
218+
)}
219+
{folder?.playlists?.length === 0 && (
220+
<PlaceholderWrapper>
221+
<FolderIcon size={100} color="rgb(70, 70, 70)" />
222+
<Placeholder>
223+
Start moving playlists to your folder.
224+
</Placeholder>
225+
<Button onClick={() => setIsMovePlaylistsModalOpen(true)}>
226+
Move Playlists
227+
</Button>
228+
</PlaceholderWrapper>
229+
)}
207230
</Scrollable>
208231
</MainContent>
209232
</Content>
233+
<MovePlaylistsModal
234+
isOpen={isMovePlaylistsModalOpen}
235+
onClose={() => setIsMovePlaylistsModalOpen(false)}
236+
onMovePlaylists={onMovePlaylists}
237+
playlists={playlists}
238+
folderId={folder?.id}
239+
/>
210240
</Container>
211241
);
212242
};
Lines changed: 89 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,99 @@
1-
import { FC } from "react";
1+
import { Modal, ModalHeader, ModalBody, ModalFooter } from "baseui/modal";
2+
import { FC, useState } from "react";
3+
import Button from "../Button";
4+
import Search from "../Search";
5+
import { ListItem, ListItemLabel } from "baseui/list";
6+
import { Checkbox } from "baseui/checkbox";
27

3-
export type ModalPlaylistsModalProps = {
8+
export type PlaylistItemProps = {
9+
playlist: {
10+
id: string;
11+
name: string;
12+
};
13+
onSelected: (id: string) => void;
14+
onDeselected: (id: string) => void;
15+
};
16+
17+
const PlaylistItem: FC<PlaylistItemProps> = ({
18+
playlist,
19+
onSelected,
20+
onDeselected,
21+
}) => {
22+
const [checked, setChecked] = useState(false);
23+
const { name } = playlist;
24+
return (
25+
<ListItem
26+
endEnhancer={(props) => (
27+
<Checkbox
28+
checked={checked}
29+
onChange={(e) => {
30+
setChecked(e.target.checked);
31+
if (e.target.checked) {
32+
onSelected(playlist.id);
33+
return;
34+
}
35+
onDeselected(playlist.id);
36+
}}
37+
></Checkbox>
38+
)}
39+
overrides={{
40+
Content: {
41+
style: () => ({
42+
borderBottomWidth: "0px !important",
43+
}),
44+
},
45+
}}
46+
>
47+
<ListItemLabel>{name}</ListItemLabel>
48+
</ListItem>
49+
);
50+
};
51+
52+
export type MovePlaylistsModalProps = {
453
isOpen: boolean;
554
onClose: () => void;
655
onMovePlaylists: (playlistIds: string[], folderId: string) => void;
756
playlists: any[];
57+
folderId: string;
858
};
959

10-
const MovePlaylistsModal: FC = () => {
11-
return <div></div>;
60+
const MovePlaylistsModal: FC<MovePlaylistsModalProps> = ({
61+
isOpen,
62+
onClose,
63+
onMovePlaylists,
64+
playlists,
65+
folderId,
66+
}) => {
67+
const [selectedPlaylists, setSelectedPlaylists] = useState<string[]>([]);
68+
const _onMovePlaylists = () => {
69+
onMovePlaylists(selectedPlaylists, folderId);
70+
onClose();
71+
};
72+
const onSelected = (id: string) => {
73+
setSelectedPlaylists([...selectedPlaylists, id]);
74+
};
75+
const onDeselected = (id: string) => {
76+
setSelectedPlaylists(selectedPlaylists.filter((p) => p !== id));
77+
};
78+
return (
79+
<Modal onClose={onClose} isOpen={isOpen}>
80+
<ModalHeader>Move Playlists</ModalHeader>
81+
<ModalBody>
82+
<Search onSearch={(q) => {}} height="40px" width="100%" />
83+
{playlists.map((item: any) => (
84+
<PlaylistItem
85+
key={item.id}
86+
playlist={item}
87+
onSelected={onSelected}
88+
onDeselected={onDeselected}
89+
/>
90+
))}
91+
</ModalBody>
92+
<ModalFooter>
93+
<Button onClick={_onMovePlaylists}>Move Playlists</Button>
94+
</ModalFooter>
95+
</Modal>
96+
);
1297
};
1398

1499
export default MovePlaylistsModal;

webui/musicplayer/src/Components/Search/Search.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ import { FC } from "react";
33

44
export type SearchProps = {
55
onSearch: (query: string) => void;
6+
height?: string;
7+
width?: string;
68
};
79

8-
const Search: FC<SearchProps> = ({ onSearch }) => {
10+
const Search: FC<SearchProps> = ({ onSearch, width, height }) => {
911
const handleKeyPress = (
1012
event: React.KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>
1113
) => {
@@ -21,8 +23,8 @@ const Search: FC<SearchProps> = ({ onSearch }) => {
2123
overrides={{
2224
Root: {
2325
style: {
24-
height: "36px",
25-
width: "222px",
26+
height,
27+
width,
2628
borderTopWidth: "0px !important",
2729
borderBottomWidth: "0px !important",
2830
borderLeftWidth: "0px !important",
@@ -51,4 +53,9 @@ const Search: FC<SearchProps> = ({ onSearch }) => {
5153
);
5254
};
5355

56+
Search.defaultProps = {
57+
height: "36px",
58+
width: "222px",
59+
};
60+
5461
export default Search;

0 commit comments

Comments
 (0)