diff --git a/core/pool/pool_test.go b/core/pool/pool_test.go index 1fcf429d..9a14357c 100644 --- a/core/pool/pool_test.go +++ b/core/pool/pool_test.go @@ -20,13 +20,9 @@ type testItem struct { ID int } -type results []int +var processed []int -func (r results) Len() int { return len(r) } - -var processed results - -var _ = XDescribe("Pool", func() { +var _ = Describe("Pool", func() { var pool *Pool BeforeEach(func() { @@ -38,7 +34,7 @@ var _ = XDescribe("Pool", func() { for i := 0; i < 5; i++ { pool.Submit(&testItem{ID: i}) } - Eventually(processed.Len, "10s").Should(Equal(5)) + Eventually(func() []int { return processed }, "10s").Should(HaveLen(5)) Expect(processed).To(ContainElements(0, 1, 2, 3, 4)) }) }) diff --git a/ui/src/album/AlbumActions.js b/ui/src/album/AlbumActions.js index b1328475..97778cbf 100644 --- a/ui/src/album/AlbumActions.js +++ b/ui/src/album/AlbumActions.js @@ -13,7 +13,7 @@ import CloudDownloadOutlinedIcon from '@material-ui/icons/CloudDownloadOutlined' import { RiPlayListAddFill, RiPlayList2Fill } from 'react-icons/ri' import { playNext, addTracks, playTracks, shuffleTracks } from '../actions' import subsonic from '../subsonic' -import { formatBytes } from '../common/SizeField' +import { formatBytes } from '../utils' import { useMediaQuery } from '@material-ui/core' import config from '../config' diff --git a/ui/src/album/AlbumDetails.js b/ui/src/album/AlbumDetails.js index 65becef5..f3979995 100644 --- a/ui/src/album/AlbumDetails.js +++ b/ui/src/album/AlbumDetails.js @@ -4,8 +4,9 @@ import { useTranslate } from 'react-admin' import Lightbox from 'react-image-lightbox' import 'react-image-lightbox/style.css' import subsonic from '../subsonic' -import { DurationField, formatRange, StarButton, SizeField } from '../common' +import { DurationField, StarButton, SizeField } from '../common' import { ArtistLinkField } from '../common' +import { formatRange } from '../utils' const AlbumDetails = ({ classes, record }) => { const [isLightboxOpen, setLightboxOpen] = React.useState(false) diff --git a/ui/src/authProvider.js b/ui/src/authProvider.js index d4c15b9a..386d79e5 100644 --- a/ui/src/authProvider.js +++ b/ui/src/authProvider.js @@ -1,6 +1,6 @@ import jwtDecode from 'jwt-decode' import md5 from 'md5-hex' -import baseUrl from './utils/baseUrl' +import { baseUrl } from './utils' import config from './config' import { v4 as uuidv4 } from 'uuid' diff --git a/ui/src/common/AddToPlaylistButton.js b/ui/src/common/AddToPlaylistButton.js index 4748a519..8115239c 100644 --- a/ui/src/common/AddToPlaylistButton.js +++ b/ui/src/common/AddToPlaylistButton.js @@ -5,7 +5,7 @@ import { Button, useTranslate, useUnselectAll } from 'react-admin' import PlaylistAddIcon from '@material-ui/icons/PlaylistAdd' import { openAddToPlaylist } from '../actions' -const AddToPlaylistButton = ({ resource, selectedIds, className }) => { +export const AddToPlaylistButton = ({ resource, selectedIds, className }) => { const translate = useTranslate() const dispatch = useDispatch() const unselectAll = useUnselectAll() @@ -34,5 +34,3 @@ AddToPlaylistButton.propTypes = { selectedIds: PropTypes.arrayOf(PropTypes.string).isRequired, className: PropTypes.object, } - -export default AddToPlaylistButton diff --git a/ui/src/common/ArtistLinkField.js b/ui/src/common/ArtistLinkField.js index c5e2d7dc..caaea615 100644 --- a/ui/src/common/ArtistLinkField.js +++ b/ui/src/common/ArtistLinkField.js @@ -4,7 +4,7 @@ import { Link } from 'react-admin' import { useAlbumsPerPage } from './index' import { withWidth } from '@material-ui/core' -const useGetHandleArtistClick = (width) => { +export const useGetHandleArtistClick = (width) => { const [perPage] = useAlbumsPerPage(width) return (id) => { @@ -12,7 +12,7 @@ const useGetHandleArtistClick = (width) => { } } -const ArtistLinkField = ({ record, className, width }) => { +export const ArtistLinkField = withWidth()(({ record, className, width }) => { const artistLink = useGetHandleArtistClick(width) return ( { {record.albumArtist} ) -} +}) ArtistLinkField.propTypes = { record: PropTypes.object, @@ -33,7 +33,3 @@ ArtistLinkField.propTypes = { ArtistLinkField.defaultProps = { addLabel: true, } - -export { useGetHandleArtistClick } - -export default withWidth()(ArtistLinkField) diff --git a/ui/src/common/BatchPlayButton.js b/ui/src/common/BatchPlayButton.js index c1a8dc27..37f29a01 100644 --- a/ui/src/common/BatchPlayButton.js +++ b/ui/src/common/BatchPlayButton.js @@ -9,7 +9,7 @@ import { } from 'react-admin' import { useDispatch } from 'react-redux' -const BatchPlayButton = ({ +export const BatchPlayButton = ({ resource, selectedIds, action, @@ -60,5 +60,3 @@ BatchPlayButton.propTypes = { icon: PropTypes.object.isRequired, className: PropTypes.object, } - -export default BatchPlayButton diff --git a/ui/src/common/BitrateField.js b/ui/src/common/BitrateField.js index 01cffd9f..d6ac2fd0 100644 --- a/ui/src/common/BitrateField.js +++ b/ui/src/common/BitrateField.js @@ -1,7 +1,7 @@ import React from 'react' import PropTypes from 'prop-types' -const BitrateField = ({ record = {}, source }) => { +export const BitrateField = ({ record = {}, source }) => { return {`${record[source]} kbps`} } @@ -14,5 +14,3 @@ BitrateField.propTypes = { BitrateField.defaultProps = { addLabel: true, } - -export default BitrateField diff --git a/ui/src/common/ContextMenus.js b/ui/src/common/ContextMenus.js index 88f8d36e..8ed47d24 100644 --- a/ui/src/common/ContextMenus.js +++ b/ui/src/common/ContextMenus.js @@ -15,9 +15,9 @@ import { openAddToPlaylist, } from '../actions' import subsonic from '../subsonic' -import StarButton from './StarButton' -import { formatBytes } from './SizeField' +import { StarButton } from './StarButton' import config from '../config' +import { formatBytes } from '../utils' const useStyles = makeStyles({ noWrap: { diff --git a/ui/src/common/DocLink.js b/ui/src/common/DocLink.js index 75b0b3c0..d647ad1b 100644 --- a/ui/src/common/DocLink.js +++ b/ui/src/common/DocLink.js @@ -1,10 +1,8 @@ import React from 'react' -import { docsUrl } from '../utils/docsUrl' +import { docsUrl } from '../utils' -const DocLink = ({ path, children }) => ( +export const DocLink = ({ path, children }) => ( {children} ) - -export default DocLink diff --git a/ui/src/common/DurationField.js b/ui/src/common/DurationField.js index 11373791..0222faa8 100644 --- a/ui/src/common/DurationField.js +++ b/ui/src/common/DurationField.js @@ -1,26 +1,16 @@ import React from 'react' import PropTypes from 'prop-types' +import { formatDuration } from '../utils' -const DurationField = ({ record = {}, source }) => { +export const DurationField = ({ record = {}, source }) => { try { - return {format(record[source])} + return {formatDuration(record[source])} } catch (e) { console.log('Error in DurationField! Record:', record) return 00:00 } } -const format = (d) => { - const hours = Math.floor(d / 3600) - const minutes = Math.floor(d / 60) % 60 - const seconds = d % 60 - return [hours, minutes, seconds] - .map((v) => Math.round(v).toString()) - .map((v) => (v.length !== 2 ? '0' + v : v)) - .filter((v, i) => v !== '00' || i > 0) - .join(':') -} - DurationField.propTypes = { label: PropTypes.string, record: PropTypes.object, @@ -30,5 +20,3 @@ DurationField.propTypes = { DurationField.defaultProps = { addLabel: true, } - -export default DurationField diff --git a/ui/src/common/List.js b/ui/src/common/List.js index ccd47997..f74ab027 100644 --- a/ui/src/common/List.js +++ b/ui/src/common/List.js @@ -1,9 +1,9 @@ import React from 'react' import { List as RAList } from 'react-admin' -import Pagination from './Pagination' +import { Pagination } from './Pagination' import { Title } from './index' -const List = (props) => { +export const List = (props) => { const { resource } = props return ( { /> ) } - -export default List diff --git a/ui/src/common/Pagination.js b/ui/src/common/Pagination.js index f2d507a3..e17d9e63 100644 --- a/ui/src/common/Pagination.js +++ b/ui/src/common/Pagination.js @@ -1,8 +1,6 @@ import React from 'react' import { Pagination as RAPagination } from 'react-admin' -const Pagination = (props) => ( +export const Pagination = (props) => ( ) - -export default Pagination diff --git a/ui/src/common/PlayButton.js b/ui/src/common/PlayButton.js index 69698b8e..d2716495 100644 --- a/ui/src/common/PlayButton.js +++ b/ui/src/common/PlayButton.js @@ -13,7 +13,7 @@ const useStyles = makeStyles({ }, }) -const PlayButton = ({ record, color, size, ...rest }) => { +export const PlayButton = ({ record, color, size, ...rest }) => { const classes = useStyles({ color }) let extractSongsData = function (response) { const data = response.data.reduce( @@ -64,4 +64,3 @@ PlayButton.propTypes = { PlayButton.defaultProps = { size: 'small', } -export default PlayButton diff --git a/ui/src/common/QuickFilter.js b/ui/src/common/QuickFilter.js index 9ce40e9e..679739d6 100644 --- a/ui/src/common/QuickFilter.js +++ b/ui/src/common/QuickFilter.js @@ -8,11 +8,9 @@ const useQuickFilterStyles = makeStyles((theme) => ({ }, })) -const QuickFilter = ({ source, label }) => { +export const QuickFilter = ({ source, label }) => { const translate = useTranslate() const classes = useQuickFilterStyles() const lbl = label || `resources.song.fields.${source}` return } - -export default QuickFilter diff --git a/ui/src/common/RangeField.js b/ui/src/common/RangeField.js index 2991a771..b88e155e 100644 --- a/ui/src/common/RangeField.js +++ b/ui/src/common/RangeField.js @@ -1,21 +1,8 @@ import React from 'react' import PropTypes from 'prop-types' +import { formatRange } from '../utils' -const formatRange = (record, source) => { - const nameCapitalized = source.charAt(0).toUpperCase() + source.slice(1) - const min = record[`min${nameCapitalized}`] - const max = record[`max${nameCapitalized}`] - let range = [] - if (min) { - range.push(min) - } - if (max && max !== min) { - range.push(max) - } - return range.join('-') -} - -const RangeField = ({ className, record = {}, source }) => { +export const RangeField = ({ className, record = {}, source }) => { return {formatRange(record, source)} } @@ -28,6 +15,3 @@ RangeField.propTypes = { RangeField.defaultProps = { addLabel: true, } - -export { formatRange } -export default RangeField diff --git a/ui/src/common/ShuffleAllButton.js b/ui/src/common/ShuffleAllButton.js index 255a3e5a..8cde1f10 100644 --- a/ui/src/common/ShuffleAllButton.js +++ b/ui/src/common/ShuffleAllButton.js @@ -5,7 +5,7 @@ import ShuffleIcon from '@material-ui/icons/Shuffle' import { playTracks } from '../actions' import PropTypes from 'prop-types' -const ShuffleAllButton = ({ filters }) => { +export const ShuffleAllButton = ({ filters }) => { const translate = useTranslate() const dataProvider = useDataProvider() const dispatch = useDispatch() @@ -46,5 +46,3 @@ ShuffleAllButton.propTypes = { ShuffleAllButton.defaultProps = { filters: {}, } - -export default ShuffleAllButton diff --git a/ui/src/common/SimpleList.js b/ui/src/common/SimpleList.js index d57c7f34..969bf58a 100644 --- a/ui/src/common/SimpleList.js +++ b/ui/src/common/SimpleList.js @@ -46,7 +46,7 @@ const LinkOrNot = ({ ) } -const SimpleList = ({ +export const SimpleList = ({ basePath, className, classes: classesOverride, @@ -145,5 +145,3 @@ SimpleList.defaultProps = { hasBulkActions: false, selectedIds: [], } - -export default SimpleList diff --git a/ui/src/common/SizeField.js b/ui/src/common/SizeField.js index e1159b19..c5c02c5e 100644 --- a/ui/src/common/SizeField.js +++ b/ui/src/common/SizeField.js @@ -1,22 +1,11 @@ import React from 'react' import PropTypes from 'prop-types' +import { formatBytes } from '../utils' -const SizeField = ({ record = {}, source }) => { +export const SizeField = ({ record = {}, source }) => { return {formatBytes(record[source])} } -export const formatBytes = (bytes, decimals = 2) => { - if (bytes === 0) return '0 Bytes' - - const k = 1024 - const dm = decimals < 0 ? 0 : decimals - const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] - - const i = Math.floor(Math.log(bytes) / Math.log(k)) - - return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i] -} - SizeField.propTypes = { label: PropTypes.string, record: PropTypes.object, @@ -26,5 +15,3 @@ SizeField.propTypes = { SizeField.defaultProps = { addLabel: true, } - -export default SizeField diff --git a/ui/src/common/SongBulkActions.js b/ui/src/common/SongBulkActions.js index a80eaf2b..56d07b46 100644 --- a/ui/src/common/SongBulkActions.js +++ b/ui/src/common/SongBulkActions.js @@ -4,7 +4,7 @@ import { addTracks, playNext, playTracks } from '../actions' import { RiPlayList2Fill, RiPlayListAddFill } from 'react-icons/ri' import PlayArrowIcon from '@material-ui/icons/PlayArrow' import { BatchPlayButton } from './index' -import AddToPlaylistButton from './AddToPlaylistButton' +import { AddToPlaylistButton } from './AddToPlaylistButton' import { makeStyles } from '@material-ui/core/styles' const useStyles = makeStyles((theme) => ({ @@ -13,7 +13,7 @@ const useStyles = makeStyles((theme) => ({ }, })) -const SongBulkActions = (props) => { +export const SongBulkActions = (props) => { const classes = useStyles() const unselectAll = useUnselectAll() useEffect(() => { @@ -46,5 +46,3 @@ const SongBulkActions = (props) => { ) } - -export default SongBulkActions diff --git a/ui/src/common/SongContextMenu.js b/ui/src/common/SongContextMenu.js index f4499b90..ff816af9 100644 --- a/ui/src/common/SongContextMenu.js +++ b/ui/src/common/SongContextMenu.js @@ -7,9 +7,9 @@ import { makeStyles } from '@material-ui/core/styles' import MoreVertIcon from '@material-ui/icons/MoreVert' import { playNext, addTracks, setTrack, openAddToPlaylist } from '../actions' import subsonic from '../subsonic' -import StarButton from './StarButton' -import { formatBytes } from './SizeField' +import { StarButton } from './StarButton' import config from '../config' +import { formatBytes } from '../utils' const useStyles = makeStyles({ noWrap: { @@ -20,7 +20,7 @@ const useStyles = makeStyles({ }, }) -const SongContextMenu = ({ +export const SongContextMenu = ({ resource, record, showStar, @@ -130,5 +130,3 @@ SongContextMenu.defaultProps = { showStar: true, addLabel: true, } - -export default SongContextMenu diff --git a/ui/src/common/SongDetails.js b/ui/src/common/SongDetails.js index 589e64bf..fe4c39cc 100644 --- a/ui/src/common/SongDetails.js +++ b/ui/src/common/SongDetails.js @@ -9,7 +9,7 @@ import { BooleanField, DateField, TextField, useTranslate } from 'react-admin' import inflection from 'inflection' import { BitrateField, SizeField } from './index' -const SongDetails = (props) => { +export const SongDetails = (props) => { const translate = useTranslate() const { record } = props const data = { @@ -52,5 +52,3 @@ const SongDetails = (props) => { ) } - -export default SongDetails diff --git a/ui/src/common/SongTitleField.js b/ui/src/common/SongTitleField.js index 60915dee..66d53531 100644 --- a/ui/src/common/SongTitleField.js +++ b/ui/src/common/SongTitleField.js @@ -24,7 +24,7 @@ const useStyles = makeStyles({ }, }) -const SongTitleField = ({ showTrackNumbers, ...props }) => { +export const SongTitleField = ({ showTrackNumbers, ...props }) => { const theme = useTheme() const classes = useStyles() const { record } = props @@ -80,5 +80,3 @@ SongTitleField.defaultProps = { record: {}, showTrackNumbers: false, } - -export default SongTitleField diff --git a/ui/src/common/StarButton.js b/ui/src/common/StarButton.js index 5eecee96..9958747f 100644 --- a/ui/src/common/StarButton.js +++ b/ui/src/common/StarButton.js @@ -15,7 +15,7 @@ const useStyles = makeStyles({ }, }) -const StarButton = ({ resource, record, color, visible, size }) => { +export const StarButton = ({ resource, record, color, visible, size }) => { const [loading, setLoading] = useState(false) const classes = useStyles({ color, visible, starred: record.starred }) const notify = useNotify() @@ -86,5 +86,3 @@ StarButton.defaultProps = { size: 'small', color: 'inherit', } - -export default StarButton diff --git a/ui/src/common/Title.js b/ui/src/common/Title.js index 0b4765c4..63eabcb1 100644 --- a/ui/src/common/Title.js +++ b/ui/src/common/Title.js @@ -2,7 +2,7 @@ import React from 'react' import { useMediaQuery } from '@material-ui/core' import { useTranslate } from 'react-admin' -const Title = ({ subTitle, args }) => { +export const Title = ({ subTitle, args }) => { const translate = useTranslate() const isDesktop = useMediaQuery((theme) => theme.breakpoints.up('md')) const text = translate(subTitle, { ...args, _: subTitle }) @@ -12,5 +12,3 @@ const Title = ({ subTitle, args }) => { } return {text ? text : 'Navidrome'} } - -export default Title diff --git a/ui/src/common/Writable.js b/ui/src/common/Writable.js index 79138247..0adedb1a 100644 --- a/ui/src/common/Writable.js +++ b/ui/src/common/Writable.js @@ -11,7 +11,7 @@ export const isReadOnly = (owner) => { return !isWritable(owner) } -const Writable = (props) => { +export const Writable = (props) => { const { record = {}, children } = props if (isWritable(record.owner)) { return Children.map(children, (child) => @@ -20,5 +20,3 @@ const Writable = (props) => { } return null } - -export default Writable diff --git a/ui/src/common/index.js b/ui/src/common/index.js index 1bba50b9..18c8c9b8 100644 --- a/ui/src/common/index.js +++ b/ui/src/common/index.js @@ -1,53 +1,24 @@ -import Title from './Title' -import DurationField from './DurationField' -import BitrateField from './BitrateField' -import Pagination from './Pagination' -import PlayButton from './PlayButton' -import BatchPlayButton from './BatchPlayButton' -import SongBulkActions from './SongBulkActions' -import AddToPlaylistButton from './AddToPlaylistButton' -import SimpleList from './SimpleList' -import RangeField, { formatRange } from './RangeField' -import ArtistLinkField, { useGetHandleArtistClick } from './ArtistLinkField' -import SongDetails from './SongDetails' -import SizeField from './SizeField' -import DocLink from './DocLink' -import List from './List' -import { SongDatagrid, SongDatagridRow } from './SongDatagrid' -import SongContextMenu from './SongContextMenu' -import SongTitleField from './SongTitleField' -import QuickFilter from './QuickFilter' -import useAlbumsPerPage from './useAlbumsPerPage' -import ShuffleAllButton from './ShuffleAllButton' -import { AlbumContextMenu, ArtistContextMenu } from './ContextMenus' -import StarButton from './StarButton' - -export { - Title, - DurationField, - SizeField, - BitrateField, - Pagination, - List, - PlayButton, - BatchPlayButton, - SongBulkActions, - AddToPlaylistButton, - SimpleList, - RangeField, - SongDetails, - SongDatagrid, - SongDatagridRow, - SongTitleField, - DocLink, - formatRange, - ArtistLinkField, - AlbumContextMenu, - ArtistContextMenu, - StarButton, - useGetHandleArtistClick, - SongContextMenu, - QuickFilter, - useAlbumsPerPage, - ShuffleAllButton, -} +export * from './AddToPlaylistButton' +export * from './ArtistLinkField' +export * from './BatchPlayButton' +export * from './BitrateField' +export * from './ContextMenus' +export * from './DocLink' +export * from './DurationField' +export * from './List' +export * from './Pagination' +export * from './PlayButton' +export * from './QuickFilter' +export * from './RangeField' +export * from './ShuffleAllButton' +export * from './SimpleList' +export * from './SizeField' +export * from './SongContextMenu' +export * from './SongDatagrid' +export * from './SongDetails' +export * from './SongTitleField' +export * from './StarButton' +export * from './Title' +export * from './SongBulkActions' +export * from './useAlbumsPerPage' +export * from './Writable' diff --git a/ui/src/common/useAlbumsPerPage.js b/ui/src/common/useAlbumsPerPage.js index 14c46511..316593f3 100644 --- a/ui/src/common/useAlbumsPerPage.js +++ b/ui/src/common/useAlbumsPerPage.js @@ -17,7 +17,7 @@ const getPerPageOptions = (width) => { return options.map((v) => v * 6) } -const useAlbumsPerPage = (width) => { +export const useAlbumsPerPage = (width) => { const perPage = useSelector((state) => get(state.admin.resources, ['album', 'list', 'params', 'perPage']) @@ -25,5 +25,3 @@ const useAlbumsPerPage = (width) => { return [perPage, getPerPageOptions(width)] } - -export default useAlbumsPerPage diff --git a/ui/src/dataProvider/httpClient.js b/ui/src/dataProvider/httpClient.js index e35b44c6..153c2cbd 100644 --- a/ui/src/dataProvider/httpClient.js +++ b/ui/src/dataProvider/httpClient.js @@ -1,5 +1,5 @@ import { fetchUtils } from 'react-admin' -import baseUrl from '../utils/baseUrl' +import { baseUrl } from '../utils' import config from '../config' const customAuthorizationHeader = 'X-ND-Authorization' diff --git a/ui/src/eventStream.js b/ui/src/eventStream.js index 7b236cb1..981f99f9 100644 --- a/ui/src/eventStream.js +++ b/ui/src/eventStream.js @@ -1,4 +1,4 @@ -import baseUrl from './utils/baseUrl' +import { baseUrl } from './utils' import throttle from 'lodash.throttle' let es = null diff --git a/ui/src/personal/Personal.js b/ui/src/personal/Personal.js index 2095d468..254324ba 100644 --- a/ui/src/personal/Personal.js +++ b/ui/src/personal/Personal.js @@ -13,7 +13,7 @@ import { makeStyles } from '@material-ui/core/styles' import HelpOutlineIcon from '@material-ui/icons/HelpOutline' import { changeTheme } from '../actions' import themes from '../themes' -import { docsUrl } from '../utils/docsUrl' +import { docsUrl } from '../utils' import { useGetLanguageChoices } from '../i18n' import albumLists, { defaultAlbumList } from '../album/albumLists' diff --git a/ui/src/playlist/PlaylistActions.js b/ui/src/playlist/PlaylistActions.js index 0586514e..b0cc988a 100644 --- a/ui/src/playlist/PlaylistActions.js +++ b/ui/src/playlist/PlaylistActions.js @@ -16,7 +16,7 @@ import { playNext, addTracks, playTracks, shuffleTracks } from '../actions' import { M3U_MIME_TYPE, REST_URL } from '../consts' import subsonic from '../subsonic' import PropTypes from 'prop-types' -import { formatBytes } from '../common/SizeField' +import { formatBytes } from '../utils' import { useMediaQuery } from '@material-ui/core' import config from '../config' diff --git a/ui/src/playlist/PlaylistList.js b/ui/src/playlist/PlaylistList.js index a9a0cc47..56d0e5d9 100644 --- a/ui/src/playlist/PlaylistList.js +++ b/ui/src/playlist/PlaylistList.js @@ -11,8 +11,7 @@ import { useNotify, } from 'react-admin' import Switch from '@material-ui/core/Switch' -import { DurationField, List } from '../common' -import Writable, { isWritable } from '../common/Writable' +import { DurationField, List, Writable, isWritable } from '../common' const PlaylistFilter = (props) => ( diff --git a/ui/src/subsonic/index.js b/ui/src/subsonic/index.js index c59bb9f1..07b061ce 100644 --- a/ui/src/subsonic/index.js +++ b/ui/src/subsonic/index.js @@ -1,5 +1,5 @@ import { fetchUtils } from 'react-admin' -import baseUrl from '../utils/baseUrl' +import { baseUrl } from '../utils' const url = (command, id, options) => { const params = new URLSearchParams() diff --git a/ui/src/utils/baseUrl.js b/ui/src/utils/baseUrl.js index 92c29fb8..d9f4dfb3 100644 --- a/ui/src/utils/baseUrl.js +++ b/ui/src/utils/baseUrl.js @@ -1,10 +1,8 @@ import config from '../config' -const baseUrl = (path) => { +export const baseUrl = (path) => { const base = config.baseURL || '' const parts = [base] parts.push(path.replace(/^\//, '')) return parts.join('/') } - -export default baseUrl diff --git a/ui/src/utils/formatters.js b/ui/src/utils/formatters.js new file mode 100644 index 00000000..537fafc6 --- /dev/null +++ b/ui/src/utils/formatters.js @@ -0,0 +1,36 @@ +export const formatBytes = (bytes, decimals = 2) => { + if (bytes === 0) return '0 Bytes' + + const k = 1024 + const dm = decimals < 0 ? 0 : decimals + const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] + + const i = Math.floor(Math.log(bytes) / Math.log(k)) + + return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i] +} + +export const formatRange = (record, source) => { + const nameCapitalized = source.charAt(0).toUpperCase() + source.slice(1) + const min = record[`min${nameCapitalized}`] + const max = record[`max${nameCapitalized}`] + let range = [] + if (min) { + range.push(min) + } + if (max && max !== min) { + range.push(max) + } + return range.join('-') +} + +export const formatDuration = (d) => { + const hours = Math.floor(d / 3600) + const minutes = Math.floor(d / 60) % 60 + const seconds = d % 60 + return [hours, minutes, seconds] + .map((v) => Math.round(v).toString()) + .map((v) => (v.length !== 2 ? '0' + v : v)) + .filter((v, i) => v !== '00' || i > 0) + .join(':') +} diff --git a/ui/src/utils/index.js b/ui/src/utils/index.js new file mode 100644 index 00000000..b8c5c5c6 --- /dev/null +++ b/ui/src/utils/index.js @@ -0,0 +1,3 @@ +export * from './baseUrl' +export * from './docsUrl' +export * from './formatters'