mirror of
https://github.com/navidrome/navidrome.git
synced 2025-04-16 20:12:22 +03:00
Use a better notation for exporting JS components and functions
This commit is contained in:
parent
8a44f61189
commit
9d2426a601
@ -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))
|
||||
})
|
||||
})
|
||||
|
@ -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'
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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'
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 (
|
||||
<Link
|
||||
@ -23,7 +23,7 @@ const ArtistLinkField = ({ record, className, width }) => {
|
||||
{record.albumArtist}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
ArtistLinkField.propTypes = {
|
||||
record: PropTypes.object,
|
||||
@ -33,7 +33,3 @@ ArtistLinkField.propTypes = {
|
||||
ArtistLinkField.defaultProps = {
|
||||
addLabel: true,
|
||||
}
|
||||
|
||||
export { useGetHandleArtistClick }
|
||||
|
||||
export default withWidth()(ArtistLinkField)
|
||||
|
@ -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
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
const BitrateField = ({ record = {}, source }) => {
|
||||
export const BitrateField = ({ record = {}, source }) => {
|
||||
return <span>{`${record[source]} kbps`}</span>
|
||||
}
|
||||
|
||||
@ -14,5 +14,3 @@ BitrateField.propTypes = {
|
||||
BitrateField.defaultProps = {
|
||||
addLabel: true,
|
||||
}
|
||||
|
||||
export default BitrateField
|
||||
|
@ -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: {
|
||||
|
@ -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 }) => (
|
||||
<a href={docsUrl(path)} target={'_blank'} rel="noopener noreferrer">
|
||||
{children}
|
||||
</a>
|
||||
)
|
||||
|
||||
export default DocLink
|
||||
|
@ -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 <span>{format(record[source])}</span>
|
||||
return <span>{formatDuration(record[source])}</span>
|
||||
} catch (e) {
|
||||
console.log('Error in DurationField! Record:', record)
|
||||
return <span>00:00</span>
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -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 (
|
||||
<RAList
|
||||
@ -19,5 +19,3 @@ const List = (props) => {
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default List
|
||||
|
@ -1,8 +1,6 @@
|
||||
import React from 'react'
|
||||
import { Pagination as RAPagination } from 'react-admin'
|
||||
|
||||
const Pagination = (props) => (
|
||||
export const Pagination = (props) => (
|
||||
<RAPagination rowsPerPageOptions={[15, 25, 50]} {...props} />
|
||||
)
|
||||
|
||||
export default Pagination
|
||||
|
@ -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
|
||||
|
@ -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 <Chip className={classes.chip} label={translate(lbl)} />
|
||||
}
|
||||
|
||||
export default QuickFilter
|
||||
|
@ -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 <span className={className}>{formatRange(record, source)}</span>
|
||||
}
|
||||
|
||||
@ -28,6 +15,3 @@ RangeField.propTypes = {
|
||||
RangeField.defaultProps = {
|
||||
addLabel: true,
|
||||
}
|
||||
|
||||
export { formatRange }
|
||||
export default RangeField
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 <span>{formatBytes(record[source])}</span>
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -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) => {
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
export default SongBulkActions
|
||||
|
@ -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
|
||||
|
@ -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) => {
|
||||
</TableContainer>
|
||||
)
|
||||
}
|
||||
|
||||
export default SongDetails
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 <span>{text ? text : 'Navidrome'}</span>
|
||||
}
|
||||
|
||||
export default Title
|
||||
|
@ -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
|
||||
|
@ -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'
|
||||
|
@ -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
|
||||
|
@ -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'
|
||||
|
@ -1,4 +1,4 @@
|
||||
import baseUrl from './utils/baseUrl'
|
||||
import { baseUrl } from './utils'
|
||||
import throttle from 'lodash.throttle'
|
||||
|
||||
let es = null
|
||||
|
@ -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'
|
||||
|
||||
|
@ -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'
|
||||
|
||||
|
@ -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) => (
|
||||
<Filter {...props} variant={'outlined'}>
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
36
ui/src/utils/formatters.js
Normal file
36
ui/src/utils/formatters.js
Normal file
@ -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(':')
|
||||
}
|
3
ui/src/utils/index.js
Normal file
3
ui/src/utils/index.js
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './baseUrl'
|
||||
export * from './docsUrl'
|
||||
export * from './formatters'
|
Loading…
x
Reference in New Issue
Block a user