Adding sidebar list

This commit is contained in:
James Barnsley
2020-08-09 21:04:07 +12:00
parent 55c06454e0
commit 584b3ea7c4
14 changed files with 384 additions and 365 deletions

View File

@ -1,22 +1,23 @@
import React, { memo } from 'react';
import Icon from './Icon';
export default memo((props) => {
export default memo(({
className = '',
onTrigger,
}) => {
const handleClick = (e) => {
e.preventDefault();
e.stopPropagation();
props.onTrigger(e);
onTrigger(e);
};
let className = 'context-menu-trigger mouse-contextable touch-contextable';
if (props.className) {
className += ` ${props.className}`;
}
return (
<span className={className} onClick={handleClick}>
<button
className={`button button--icon button--default context-menu-trigger mouse-contextable touch-contextable ${className}`}
onClick={handleClick}
type="button"
>
<Icon name="more_horiz" />
</span>
</button>
);
});

View File

@ -1,70 +1,44 @@
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { useSelector, useDispatch } from 'react-redux'
import * as coreActions from '../../services/core/actions';
import Icon from '../Icon';
class PinButton extends React.Component {
remove = () => {
const {
coreActions: {
removePinned,
},
uri,
} = this.props;
removePinned(uri);
}
const PinButton = ({
uri,
className,
}) => {
if (!uri) return null;
add = () => {
const {
coreActions: {
addPinned,
},
uri,
} = this.props;
addPinned(uri);
}
const {
removePinned,
addPinned,
} = coreActions;
render = () => {
const {
uri,
isPinned,
} = this.props;
let { className = '' } = this.props;
if (!uri) return null;
const dispatch = useDispatch();
const isPinned = useSelector((state) => state.core.pinned ? state.core.pinned.find((item) => item === uri) : false)
const remove = () => dispatch(removePinned(uri));
const add = () => dispatch(addPinned(uri));
className += ' button button--discrete';
if (isPinned) {
return (
<button
type="button"
className={`${className} button--destructive`}
onClick={this.remove}
>
<Icon name="bookmark" />
</button>
);
}
if (isPinned) {
return (
<button
type="button"
className={`${className} button--default`}
onClick={this.add}
className={`${className} button button--icon button--default`}
onClick={remove}
>
<Icon name="bookmark_border" />
<Icon name="star" />
</button>
);
}
}
return (
<button
type="button"
className={`${className} button button--icon button--default`}
onClick={add}
>
<Icon name="star_border" />
</button>
);
};
const mapStateToProps = (state, { uri }) => ({
isPinned: state.core.pinned ? state.core.pinned.find((item) => item === uri) : false,
});
const mapDispatchToProps = (dispatch) => ({
coreActions: bindActionCreators(coreActions, dispatch),
});
export default connect(mapStateToProps, mapDispatchToProps)(PinButton);
export default PinButton;

View File

@ -0,0 +1,32 @@
import React from 'react';
import { useSelector } from 'react-redux';
import Link from '../Link';
const PinList = () => {
const uris = useSelector((state) => state.core.pinned || []);
const playlists = useSelector((state) => state.core.playlists);
if (uris.length <= 0) return null;
return (
<div>
{
uris.map((uri) => {
const playlist = playlists[uri] || { uri };
return (
<Link
to={`/playlist/${uri}`}
className="sidebar__menu__item sidebar__menu__item--submenu"
activeClassName="sidebar__menu__item--active"
key={uri}
>
{playlist.name || playlist.uri}
</Link>
);
})
}
</div>
);
};
export default PinList;

View File

@ -6,6 +6,7 @@ import { withRouter } from 'react-router';
import Link from './Link';
import Icon from './Icon';
import Dropzones from './Fields/Dropzones';
import PinList from './Fields/PinList';
import * as uiActions from '../services/ui/actions';
import * as mopidyActions from '../services/mopidy/actions';
import { I18n, i18n } from '../locale';
@ -80,7 +81,7 @@ class Sidebar extends React.Component {
return null;
}
render() {
render = () => {
const {
history,
spotify_available,
@ -134,6 +135,7 @@ class Sidebar extends React.Component {
<Icon name="queue_music" type="material" />
<I18n path="sidebar.playlists" />
</Link>
<PinList />
<Link to="/library/artists" history={history} className="sidebar__menu__item" activeClassName="sidebar__menu__item--active">
<Icon name="recent_actors" type="material" />
<I18n path="sidebar.artists" />

View File

@ -1,5 +1,5 @@
import { createRange } from '../../util/arrays';
import { createRange, removeDuplicates } from '../../util/arrays';
import { uriSource } from '../../util/helpers';
const spotifyActions = require('../../services/spotify/actions');
@ -442,6 +442,6 @@ export function removePinned(uri) {
export function updatePinned(pinned) {
return {
type: 'UPDATE_PINNED',
pinned,
pinned: removeDuplicates(pinned),
};
}

View File

@ -814,7 +814,7 @@ const CoreMiddleware = (function () {
]));
next(action);
break;
case 'REMOVE_PINNED':
store.dispatch(coreActions.updatePinned(
store.getState().core.pinned.filter((item) => item !== action.uri),

View File

@ -324,23 +324,11 @@
}
.context-menu-trigger {
display: inline-block;
padding: 14px 12px;
cursor: pointer;
vertical-align: top;
margin-top: 2px;
position: relative;
border-radius: 3px;
text-align: center;
.actions & {
font-size: 24px;
padding: 2px 10px 1px;
&:hover {
cursor: pointer;
color: colour(blue) !important;
}
}
.icon {

View File

@ -15,28 +15,21 @@
@include noselect();
&--material {
font-family: 'Material Icons';
font-weight: normal;
font-style: normal;
line-height: 1;
text-transform: none;
letter-spacing: normal;
word-wrap: normal;
white-space: nowrap;
direction: ltr;
font-family: 'Material Icons';
font-weight: normal;
font-style: normal;
line-height: 1;
text-transform: none;
letter-spacing: normal;
word-wrap: normal;
white-space: nowrap;
direction: ltr;
vertical-align: top;
font-size: 1.3em;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
-moz-osx-font-smoothing: grayscale;
font-feature-settings: 'liga';
}
&--fontawesome {
}
&--svg {
font-size: 1.3em;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
-moz-osx-font-smoothing: grayscale;
font-feature-settings: 'liga';
}
&--spin {

View File

@ -63,6 +63,22 @@
}
}
&--submenu {
font-size: 1rem;
padding: 0.6em 0.7em;
font-weight: 400 !important;
margin: 0 1.1em 0 3em;
&:before {
display: none;
}
&.sidebar__menu__item--active {
background: transparent;
color: colour(turquoise) !important;
}
}
&--active {
background: colour(turquoise);
color: colour(white) !important;

View File

@ -253,6 +253,21 @@ select {
padding: 16px 50px 14px;
}
&--icon {
padding: 0.2rem;
font-size: 1.4rem;
border: none;
box-shadow: none !important;
&:hover {
color: colour(blue) !important;
}
.icon {
padding: 0 !important;
}
}
&--pull-right {
margin-right: 0;
margin-left: 30px;