fix: corriger toutes les erreurs de lint restantes (263 -> 0)
This commit is contained in:
@@ -20,7 +20,7 @@ async function jwennAwtis(slug) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function generateMetadata(props) {
|
export async function generateMetadata(props) {
|
||||||
const params = await props.params;
|
const params = await props.params
|
||||||
const {slug} = params
|
const {slug} = params
|
||||||
const anAwtis = await jwennAwtis(slug)
|
const anAwtis = await jwennAwtis(slug)
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ export async function generateMetadata(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default async function AwtisPajSlug(props) {
|
export default async function AwtisPajSlug(props) {
|
||||||
const params = await props.params;
|
const params = await props.params
|
||||||
const {slug} = params
|
const {slug} = params
|
||||||
const anAwtis = await jwennAwtis(slug)
|
const anAwtis = await jwennAwtis(slug)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -63,7 +63,7 @@ async function jwennDone(paj) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default async function AwitsPaj(props) {
|
export default async function AwitsPaj(props) {
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams
|
||||||
const {paj} = searchParams
|
const {paj} = searchParams
|
||||||
const {pajTotal, awtisPouChakPaj, pajParsed} = await jwennDone(paj || 1)
|
const {pajTotal, awtisPouChakPaj, pajParsed} = await jwennDone(paj || 1)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -78,7 +78,7 @@ export default async function RootLayout({children}) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<html lang='fr' suppressHydrationWarning>
|
<html suppressHydrationWarning lang='fr'>
|
||||||
<body>
|
<body>
|
||||||
{plausibleUrl
|
{plausibleUrl
|
||||||
? <PlausibleProvider src={plausibleUrl}>{inner}</PlausibleProvider>
|
? <PlausibleProvider src={plausibleUrl}>{inner}</PlausibleProvider>
|
||||||
|
|||||||
+1
-2
@@ -7,7 +7,6 @@ import Statistik from '../components/akey/statistik'
|
|||||||
import Akey from '../components/akey'
|
import Akey from '../components/akey'
|
||||||
import AnVedette from '../components/akey/an-vedette'
|
import AnVedette from '../components/akey/an-vedette'
|
||||||
|
|
||||||
import okiLogo from '../public/logo-512x512.png'
|
|
||||||
import Footer from '../components/footer'
|
import Footer from '../components/footer'
|
||||||
import Aso from '../components/akey/aso'
|
import Aso from '../components/akey/aso'
|
||||||
|
|
||||||
@@ -26,7 +25,7 @@ export default async function Page() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{display: 'flex', flexDirection: 'column', minHeight: '100vh'}}>
|
<Box sx={{display: 'flex', flexDirection: 'column', minHeight: '100vh'}}>
|
||||||
<Akey logo={okiLogo} />
|
<Akey />
|
||||||
<Container sx={{flexGrow: 100}}>
|
<Container sx={{flexGrow: 100}}>
|
||||||
{dernierTeks && <AnVedette teks={dernierTeks} />}
|
{dernierTeks && <AnVedette teks={dernierTeks} />}
|
||||||
<Statistik statistik={statistik} />
|
<Statistik statistik={statistik} />
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ async function jwennAnTeks(slug) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function generateMetadata(props) {
|
export async function generateMetadata(props) {
|
||||||
const params = await props.params;
|
const params = await props.params
|
||||||
const {slug} = params
|
const {slug} = params
|
||||||
|
|
||||||
const anTeks = await jwennAnTeks(slug)
|
const anTeks = await jwennAnTeks(slug)
|
||||||
@@ -67,7 +67,7 @@ export async function generateMetadata(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default async function AnPawolPaj(props) {
|
export default async function AnPawolPaj(props) {
|
||||||
const params = await props.params;
|
const params = await props.params
|
||||||
const {slug} = params
|
const {slug} = params
|
||||||
|
|
||||||
const anTeks = await jwennAnTeks(slug)
|
const anTeks = await jwennAnTeks(slug)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import {Suspense} from 'react'
|
import {Suspense} from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
import TeksDrawerLoader from '../../components/teks/teks-drawer-loader'
|
import TeksDrawerLoader from '../../components/teks/teks-drawer-loader'
|
||||||
import {CurrentTrackProvider} from '../../components/teks/current-track-context'
|
import {CurrentTrackProvider} from '../../components/teks/current-track-context'
|
||||||
import Loading from './loading'
|
import Loading from './loading'
|
||||||
@@ -50,3 +51,7 @@ export default function PawolLayout({children}) {
|
|||||||
</CurrentTrackProvider>
|
</CurrentTrackProvider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PawolLayout.propTypes = {
|
||||||
|
children: PropTypes.node.isRequired
|
||||||
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
export default function robots() {
|
export default function robots() {
|
||||||
const isProduction = process.env.NODE_ENV === 'production';
|
const isProduction = process.env.NODE_ENV === 'production'
|
||||||
|
|
||||||
if (!isProduction) {
|
if (!isProduction) {
|
||||||
return {
|
return {
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@ export default function Sipote() {
|
|||||||
<Box sx={{display: 'flex', marginTop: 10, flexDirection: 'column', minHeight: '100vh'}}>
|
<Box sx={{display: 'flex', marginTop: 10, flexDirection: 'column', minHeight: '100vh'}}>
|
||||||
<Box sx={{flexGrow: 1, marginBottom: 10}}>
|
<Box sx={{flexGrow: 1, marginBottom: 10}}>
|
||||||
<Container>
|
<Container>
|
||||||
<Typography gutterBottom sx={{fontWeight: 'bold', textAlign:'center' }} variant='h4' component='h1'>
|
<Typography gutterBottom sx={{fontWeight: 'bold', textAlign: 'center'}} variant='h4' component='h1'>
|
||||||
Soutenir ORGANISATION KA INTERNATIONALE !
|
Soutenir ORGANISATION KA INTERNATIONALE !
|
||||||
</Typography>
|
</Typography>
|
||||||
<Paper sx={{padding: 2, marginTop: 3}}>
|
<Paper sx={{padding: 2, marginTop: 3}}>
|
||||||
|
|||||||
@@ -36,10 +36,10 @@ export default function AnVedette({teks}) {
|
|||||||
<Box sx={{position: 'relative', width: '100%', aspectRatio: {xs: '1 / 1', sm: '16 / 9'}, maxHeight: {sm: 420}}}>
|
<Box sx={{position: 'relative', width: '100%', aspectRatio: {xs: '1 / 1', sm: '16 / 9'}, maxHeight: {sm: 420}}}>
|
||||||
{fmt?.url ? (
|
{fmt?.url ? (
|
||||||
<Image
|
<Image
|
||||||
src={`${IMAGE_URL}${fmt.url}`}
|
|
||||||
alt={titre}
|
|
||||||
fill
|
fill
|
||||||
priority
|
priority
|
||||||
|
src={`${IMAGE_URL}${fmt.url}`}
|
||||||
|
alt={titre}
|
||||||
placeholder='blur'
|
placeholder='blur'
|
||||||
blurDataURL={BLUR_DATA_URL}
|
blurDataURL={BLUR_DATA_URL}
|
||||||
sizes='(max-width: 600px) 100vw, 800px'
|
sizes='(max-width: 600px) 100vw, 800px'
|
||||||
|
|||||||
@@ -1,13 +1,8 @@
|
|||||||
import PropTypes from 'prop-types'
|
|
||||||
import Container from '@mui/material/Container'
|
import Container from '@mui/material/Container'
|
||||||
import Typography from '@mui/material/Typography'
|
import Typography from '@mui/material/Typography'
|
||||||
import Box from '@mui/material/Box'
|
import Box from '@mui/material/Box'
|
||||||
import Grid from '@mui/material/Grid'
|
|
||||||
import Button from '@mui/material/Button'
|
|
||||||
import Image from 'next/image'
|
|
||||||
import Link from 'next/link'
|
|
||||||
|
|
||||||
export default function Akey({logo}) {
|
export default function Akey() {
|
||||||
return (
|
return (
|
||||||
<Box sx={{flexGrow: 1, marginBottom: 3, marginTop: 7}}>
|
<Box sx={{flexGrow: 1, marginBottom: 3, marginTop: 7}}>
|
||||||
<Container align='center'>
|
<Container align='center'>
|
||||||
@@ -25,7 +20,3 @@ export default function Akey({logo}) {
|
|||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Akey.propTypes = {
|
|
||||||
logo: PropTypes.object.isRequired
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -72,7 +72,8 @@ export default function AwtisDetay({anAwtis}) {
|
|||||||
position: 'relative',
|
position: 'relative',
|
||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
mb: 2,
|
mb: 2,
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
{photoUrl ? (
|
{photoUrl ? (
|
||||||
<Image
|
<Image
|
||||||
src={photoUrl}
|
src={photoUrl}
|
||||||
@@ -94,8 +95,8 @@ export default function AwtisDetay({anAwtis}) {
|
|||||||
|
|
||||||
{rezoSosyal?.length > 0 && (
|
{rezoSosyal?.length > 0 && (
|
||||||
<Box sx={{display: 'flex', gap: 0.75, flexWrap: 'wrap', justifyContent: 'center', mb: 1.5}}>
|
<Box sx={{display: 'flex', gap: 0.75, flexWrap: 'wrap', justifyContent: 'center', mb: 1.5}}>
|
||||||
{rezoSosyal.map((rezo, i) => (
|
{rezoSosyal.map(rezo => (
|
||||||
<SocialButton key={i} rezo={rezo} />
|
<SocialButton key={rezo.url} rezo={rezo} />
|
||||||
))}
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
@@ -149,9 +150,9 @@ export default function AwtisDetay({anAwtis}) {
|
|||||||
<Link href={`/paroles/${titrePhare.slug}`} style={{display: 'block', height: '100%'}}>
|
<Link href={`/paroles/${titrePhare.slug}`} style={{display: 'block', height: '100%'}}>
|
||||||
<Box sx={{position: 'relative', minHeight: 130, height: '100%'}}>
|
<Box sx={{position: 'relative', minHeight: 130, height: '100%'}}>
|
||||||
<Image
|
<Image
|
||||||
|
fill
|
||||||
src={coverUrl}
|
src={coverUrl}
|
||||||
alt={titrePhare.titre}
|
alt={titrePhare.titre}
|
||||||
fill
|
|
||||||
placeholder='blur'
|
placeholder='blur'
|
||||||
blurDataURL={BLUR_DATA_URL}
|
blurDataURL={BLUR_DATA_URL}
|
||||||
sizes='200px'
|
sizes='200px'
|
||||||
@@ -163,7 +164,7 @@ export default function AwtisDetay({anAwtis}) {
|
|||||||
)}
|
)}
|
||||||
<Grid size={{xs: 12, sm: coverUrl ? 8 : 12}}>
|
<Grid size={{xs: 12, sm: coverUrl ? 8 : 12}}>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography variant='subtitle1' sx={{fontWeight: 700}} gutterBottom>
|
<Typography gutterBottom variant='subtitle1' sx={{fontWeight: 700}}>
|
||||||
<Link href={`/paroles/${titrePhare.slug}`} style={{color: 'inherit', textDecoration: 'none'}}>
|
<Link href={`/paroles/${titrePhare.slug}`} style={{color: 'inherit', textDecoration: 'none'}}>
|
||||||
{titrePhare.titre}
|
{titrePhare.titre}
|
||||||
</Link>
|
</Link>
|
||||||
@@ -172,8 +173,8 @@ export default function AwtisDetay({anAwtis}) {
|
|||||||
Écouter sur
|
Écouter sur
|
||||||
</Typography>
|
</Typography>
|
||||||
<Box sx={{display: 'flex', flexWrap: 'wrap', gap: 1}}>
|
<Box sx={{display: 'flex', flexWrap: 'wrap', gap: 1}}>
|
||||||
{titrePhare.streamAudio.map((lyen, i) => (
|
{titrePhare.streamAudio.map(lyen => (
|
||||||
<StreamButton key={i} lyen={lyen} />
|
<StreamButton key={lyen.url} lyen={lyen} />
|
||||||
))}
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
@@ -202,7 +203,7 @@ export default function AwtisDetay({anAwtis}) {
|
|||||||
})}
|
})}
|
||||||
</AccordionDetails>
|
</AccordionDetails>
|
||||||
</Accordion>
|
</Accordion>
|
||||||
) : paroles.length === 0 ? (
|
) : (paroles.length === 0 ? (
|
||||||
<Typography textAlign='center' variant='body1' color='text.secondary'>
|
<Typography textAlign='center' variant='body1' color='text.secondary'>
|
||||||
Aucune parole pour le moment
|
Aucune parole pour le moment
|
||||||
</Typography>
|
</Typography>
|
||||||
@@ -213,7 +214,7 @@ export default function AwtisDetay({anAwtis}) {
|
|||||||
<MizikLyen anPawol={paroles[0]} kuveti={formatKuveti(paroles[0].couverture, 'thumbnail')} />
|
<MizikLyen anPawol={paroles[0]} kuveti={formatKuveti(paroles[0].couverture, 'thumbnail')} />
|
||||||
</Paper>
|
</Paper>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
))}
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import {formatKuveti} from '../../lib/kuveti'
|
|||||||
import AwtisBiyografi from './awtis-biyografi'
|
import AwtisBiyografi from './awtis-biyografi'
|
||||||
|
|
||||||
const PREFIX = 'awtis-kat'
|
const PREFIX = 'awtis-kat'
|
||||||
const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3001'
|
|
||||||
const IMAGE_URL = process.env.NEXT_PUBLIC_API_URL_ROOT || 'http://localhost:1337'
|
const IMAGE_URL = process.env.NEXT_PUBLIC_API_URL_ROOT || 'http://localhost:1337'
|
||||||
const EXCLUSIVE_LABEL = process.env.NEXT_PUBLIC_EXCLUSIVE_ARTIST_LABEL || 'OKI Exclusif'
|
const EXCLUSIVE_LABEL = process.env.NEXT_PUBLIC_EXCLUSIVE_ARTIST_LABEL || 'OKI Exclusif'
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import {useRouter} from 'next/navigation'
|
|||||||
import TextField from '@mui/material/TextField'
|
import TextField from '@mui/material/TextField'
|
||||||
import Autocomplete from '@mui/material/Autocomplete'
|
import Autocomplete from '@mui/material/Autocomplete'
|
||||||
import Avatar from '@mui/material/Avatar'
|
import Avatar from '@mui/material/Avatar'
|
||||||
import CircularProgress from '@mui/material/CircularProgress'
|
|
||||||
import Container from '@mui/material/Container'
|
import Container from '@mui/material/Container'
|
||||||
|
|
||||||
import {jwennToutAwtis} from '../../lib/oki-api'
|
import {jwennToutAwtis} from '../../lib/oki-api'
|
||||||
@@ -50,15 +49,13 @@ export default function ChecheAwtis() {
|
|||||||
}
|
}
|
||||||
}, [loading])
|
}, [loading])
|
||||||
|
|
||||||
const sortedOptions = useMemo(() => {
|
const sortedOptions = useMemo(() => [...options].sort((a, b) =>
|
||||||
return [...options].sort((a, b) =>
|
|
||||||
-b.firstLetter.localeCompare(a.firstLetter)
|
-b.firstLetter.localeCompare(a.firstLetter)
|
||||||
);
|
), [options])
|
||||||
}, [options]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container
|
<Container
|
||||||
sx={{ display: 'flex', justifyContent: 'center', marginBottom: 3 }}
|
sx={{display: 'flex', justifyContent: 'center', marginBottom: 3}}
|
||||||
>
|
>
|
||||||
<Autocomplete
|
<Autocomplete
|
||||||
autoHighlight
|
autoHighlight
|
||||||
@@ -70,35 +67,35 @@ export default function ChecheAwtis() {
|
|||||||
noOptionsText='Aucun résultat'
|
noOptionsText='Aucun résultat'
|
||||||
id='cheche-awtis'
|
id='cheche-awtis'
|
||||||
options={sortedOptions}
|
options={sortedOptions}
|
||||||
groupBy={(option) => option?.firstLetter}
|
groupBy={option => option?.firstLetter}
|
||||||
getOptionLabel={(option) => option?.alias}
|
getOptionLabel={option => option?.alias}
|
||||||
renderOption={(props, option) => {
|
renderOption={(optionProps, option) => {
|
||||||
const {key, ...rest} = props;
|
const {key, ...rest} = optionProps
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li key={key} {...rest}>
|
<li key={key} {...rest}>
|
||||||
<Avatar
|
<Avatar
|
||||||
style={{ marginRight: 8 }}
|
style={{marginRight: 8}}
|
||||||
alt={option?.alias}
|
alt={option?.alias}
|
||||||
src={`${IMAGE_URL}${formatKuveti(option?.photo, 'thumbnail')?.url || ''}`}
|
src={`${IMAGE_URL}${formatKuveti(option?.photo, 'thumbnail')?.url || ''}`}
|
||||||
/>
|
/>
|
||||||
{option?.alias}
|
{option?.alias}
|
||||||
</li>
|
</li>
|
||||||
);
|
)
|
||||||
}}
|
}}
|
||||||
sx={{ width: 300 }}
|
sx={{width: 300}}
|
||||||
renderInput={(params) => (
|
renderInput={params => (
|
||||||
<TextField
|
<TextField
|
||||||
{...params}
|
{...params}
|
||||||
label='Rechercher un artiste'
|
label='Rechercher un artiste'
|
||||||
slotProps={{
|
slotProps={{
|
||||||
...params.slotProps,
|
...params.slotProps,
|
||||||
htmlInput: { ...params.slotProps.htmlInput },
|
htmlInput: {...params.slotProps.htmlInput},
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
onChange={(event, newValue) => {
|
onChange={(event, newValue) => {
|
||||||
router.push(`/awtis/${newValue.slug}`);
|
router.push(`/awtis/${newValue.slug}`)
|
||||||
}}
|
}}
|
||||||
onOpen={() => setOpen(true)}
|
onOpen={() => setOpen(true)}
|
||||||
onClose={() => setOpen(false)}
|
onClose={() => setOpen(false)}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
import Chip from '@mui/material/Chip'
|
import Chip from '@mui/material/Chip'
|
||||||
import IconButton from '@mui/material/IconButton'
|
import IconButton from '@mui/material/IconButton'
|
||||||
import Tooltip from '@mui/material/Tooltip'
|
import Tooltip from '@mui/material/Tooltip'
|
||||||
@@ -59,15 +60,22 @@ export function SocialButton({rezo}) {
|
|||||||
return (
|
return (
|
||||||
<Tooltip title={rezo.url}>
|
<Tooltip title={rezo.url}>
|
||||||
<Chip
|
<Chip
|
||||||
|
clickable
|
||||||
label={config.label}
|
label={config.label}
|
||||||
component='a'
|
component='a'
|
||||||
href={rezo.url}
|
href={rezo.url}
|
||||||
target='_blank'
|
target='_blank'
|
||||||
rel='noopener noreferrer'
|
rel='noopener noreferrer'
|
||||||
clickable
|
|
||||||
size='small'
|
size='small'
|
||||||
sx={{bgcolor: config.bg, color: config.color, fontWeight: 600}}
|
sx={{bgcolor: config.bg, color: config.color, fontWeight: 600}}
|
||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SocialButton.propTypes = {
|
||||||
|
rezo: PropTypes.shape({
|
||||||
|
plateforme: PropTypes.string.isRequired,
|
||||||
|
url: PropTypes.string.isRequired
|
||||||
|
}).isRequired
|
||||||
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ export default function LicenseModal({license, sourceOriginale, remixes}) {
|
|||||||
<DialogContent dividers>
|
<DialogContent dividers>
|
||||||
{sourceOriginale && (
|
{sourceOriginale && (
|
||||||
<Box sx={{mb: 3}}>
|
<Box sx={{mb: 3}}>
|
||||||
<Typography variant='overline' color='text.secondary' display='block' gutterBottom>
|
<Typography gutterBottom variant='overline' color='text.secondary' display='block'>
|
||||||
Basé sur
|
Basé sur
|
||||||
</Typography>
|
</Typography>
|
||||||
<Link href={`/paroles/${sourceOriginale.slug}`} underline='hover' color='inherit'>
|
<Link href={`/paroles/${sourceOriginale.slug}`} underline='hover' color='inherit'>
|
||||||
@@ -76,7 +76,7 @@ export default function LicenseModal({license, sourceOriginale, remixes}) {
|
|||||||
)}
|
)}
|
||||||
{remixes && (
|
{remixes && (
|
||||||
<Box sx={{mb: 3}}>
|
<Box sx={{mb: 3}}>
|
||||||
<Typography variant='overline' color='text.secondary' display='block' gutterBottom>
|
<Typography gutterBottom variant='overline' color='text.secondary' display='block'>
|
||||||
Déclinaisons
|
Déclinaisons
|
||||||
</Typography>
|
</Typography>
|
||||||
{remixes.map(remix => (
|
{remixes.map(remix => (
|
||||||
|
|||||||
@@ -70,12 +70,14 @@ export default function FilesList({files}) {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const audioFiles = files.filter(f => f.mime.startsWith('audio'))
|
const audioFiles = files.filter(f => f.mime.startsWith('audio'))
|
||||||
if (audioFiles.length === 0) return
|
if (audioFiles.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let cancelled = false
|
let cancelled = false
|
||||||
|
|
||||||
async function fetchAllMeta() {
|
async function fetchAllMeta() {
|
||||||
const mm = await import('music-metadata-browser')
|
const mm = await import('music-metadata-browser') // eslint-disable-line node/no-unsupported-features/es-syntax
|
||||||
const results = {}
|
const results = {}
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
audioFiles.map(async file => {
|
audioFiles.map(async file => {
|
||||||
@@ -98,7 +100,9 @@ export default function FilesList({files}) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
if (!cancelled) setAudioMeta(results)
|
if (!cancelled) {
|
||||||
|
setAudioMeta(results)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchAllMeta()
|
fetchAllMeta()
|
||||||
@@ -121,7 +125,8 @@ export default function FilesList({files}) {
|
|||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
letterSpacing: '0.05rem',
|
letterSpacing: '0.05rem',
|
||||||
textTransform: 'uppercase',
|
textTransform: 'uppercase',
|
||||||
}}>{isHaute ? 'Haute' : 'Faible'}</Typography>
|
}}
|
||||||
|
>{isHaute ? 'Haute' : 'Faible'}</Typography>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,12 +155,16 @@ export default function FilesList({files}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => () => {
|
useEffect(() => () => {
|
||||||
Object.values(controllersRef.current).forEach(c => c.abort())
|
for (const c of Object.values(controllersRef.current)) {
|
||||||
|
c.abort()
|
||||||
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const handleClick = async (e, url, fileName, fileId) => {
|
const handleClick = async (e, url, fileName, fileId) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
if (fileId in downloading) return
|
if (fileId in downloading) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const controller = new AbortController()
|
const controller = new AbortController()
|
||||||
controllersRef.current[fileId] = controller
|
controllersRef.current[fileId] = controller
|
||||||
@@ -163,14 +172,18 @@ export default function FilesList({files}) {
|
|||||||
setDownloading(prev => ({...prev, [fileId]: 0}))
|
setDownloading(prev => ({...prev, [fileId]: 0}))
|
||||||
try {
|
try {
|
||||||
const response = await fetch(url, {signal: controller.signal})
|
const response = await fetch(url, {signal: controller.signal})
|
||||||
const contentLength = +response.headers.get('content-length')
|
const contentLength = Number(response.headers.get('content-length'))
|
||||||
const reader = response.body.getReader()
|
const reader = response.body.getReader()
|
||||||
const chunks = []
|
const chunks = []
|
||||||
let received = 0
|
let received = 0
|
||||||
|
|
||||||
while (true) {
|
for (;;) {
|
||||||
|
// eslint-disable-next-line no-await-in-loop -- chaque chunk dépend du précédent, la lecture est intrinsèquement séquentielle
|
||||||
const {done, value} = await reader.read()
|
const {done, value} = await reader.read()
|
||||||
if (done) break
|
if (done) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
chunks.push(value)
|
chunks.push(value)
|
||||||
received += value.length
|
received += value.length
|
||||||
if (contentLength) {
|
if (contentLength) {
|
||||||
@@ -186,7 +199,9 @@ export default function FilesList({files}) {
|
|||||||
a.click()
|
a.click()
|
||||||
URL.revokeObjectURL(blobUrl)
|
URL.revokeObjectURL(blobUrl)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.name !== 'AbortError') throw error
|
if (error.name !== 'AbortError') {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
delete controllersRef.current[fileId]
|
delete controllersRef.current[fileId]
|
||||||
setDownloading(prev => {
|
setDownloading(prev => {
|
||||||
|
|||||||
@@ -48,10 +48,10 @@ export default function KitsDialog({kits}) {
|
|||||||
<DialogTitle>Télécharger un kit</DialogTitle>
|
<DialogTitle>Télécharger un kit</DialogTitle>
|
||||||
<DialogContent dividers>
|
<DialogContent dividers>
|
||||||
<List>
|
<List>
|
||||||
{kits.map((kit, index) => {
|
{kits.map(kit => {
|
||||||
const PlatformIcon = PLATFORM_ICON[kit.plateforme] ?? CloudDownloadIcon
|
const PlatformIcon = PLATFORM_ICON[kit.plateforme] ?? CloudDownloadIcon
|
||||||
return (
|
return (
|
||||||
<ListItem key={index} disablePadding>
|
<ListItem key={kit.url} disablePadding>
|
||||||
<ListItemButton component='a' href={kit.url} target='_blank' rel='noopener noreferrer'>
|
<ListItemButton component='a' href={kit.url} target='_blank' rel='noopener noreferrer'>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<PlatformIcon />
|
<PlatformIcon />
|
||||||
|
|||||||
@@ -70,7 +70,8 @@ export default function Navigasyon() {
|
|||||||
<Appdiv>
|
<Appdiv>
|
||||||
<div className={classes.root}>
|
<div className={classes.root}>
|
||||||
<AppBar style={{zIndex: 1, boxShadow: 'none'}} position='fixed' color='default'>
|
<AppBar style={{zIndex: 1, boxShadow: 'none'}} position='fixed' color='default'>
|
||||||
{selectedTab !== undefined && <Tabs
|
{selectedTab !== undefined && (
|
||||||
|
<Tabs
|
||||||
allowScrollButtonsMobile
|
allowScrollButtonsMobile
|
||||||
scrollButtons
|
scrollButtons
|
||||||
centered={Boolean(!isMobile)}
|
centered={Boolean(!isMobile)}
|
||||||
@@ -91,7 +92,7 @@ export default function Navigasyon() {
|
|||||||
<Tab icon={<MusicNoteIcon />} aria-label='Paroles' {...a11yProps(2)} />
|
<Tab icon={<MusicNoteIcon />} aria-label='Paroles' {...a11yProps(2)} />
|
||||||
<Tab icon={<RecordVoiceOverIcon />} aria-label='Artistes' {...a11yProps(3)} />
|
<Tab icon={<RecordVoiceOverIcon />} aria-label='Artistes' {...a11yProps(3)} />
|
||||||
</Tabs>
|
</Tabs>
|
||||||
}
|
)}
|
||||||
</AppBar>
|
</AppBar>
|
||||||
</div>
|
</div>
|
||||||
</Appdiv>
|
</Appdiv>
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ import ArrowRightAltIcon from '@mui/icons-material/ArrowRightAlt'
|
|||||||
|
|
||||||
import CGUDialog from '../cgu/cgu-dialog'
|
import CGUDialog from '../cgu/cgu-dialog'
|
||||||
|
|
||||||
const CGU_PDF_LINK = process.env.NEXT_PUBLIC_CGU_DOWNLOAD_LINK
|
|
||||||
|
|
||||||
export default function Presantasyon() {
|
export default function Presantasyon() {
|
||||||
const [open, setOpen] = useState(false)
|
const [open, setOpen] = useState(false)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
import Button from '@mui/material/Button'
|
import Button from '@mui/material/Button'
|
||||||
import OpenInNewIcon from '@mui/icons-material/OpenInNew'
|
import OpenInNewIcon from '@mui/icons-material/OpenInNew'
|
||||||
import {Spotify, Applemusic, Deezer, Tidal, Youtubemusic, Amazon, Soundcloud} from '@icons-pack/react-simple-icons'
|
import {Spotify, Applemusic, Deezer, Tidal, Youtubemusic, Amazon, Soundcloud} from '@icons-pack/react-simple-icons'
|
||||||
@@ -39,3 +40,10 @@ export function StreamButton({lyen}) {
|
|||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StreamButton.propTypes = {
|
||||||
|
lyen: PropTypes.shape({
|
||||||
|
plateforme: PropTypes.string.isRequired,
|
||||||
|
url: PropTypes.string.isRequired
|
||||||
|
}).isRequired
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const pulse = keyframes`
|
|||||||
`
|
`
|
||||||
|
|
||||||
const SlideUp = forwardRef(function SlideUp(props, ref) {
|
const SlideUp = forwardRef(function SlideUp(props, ref) {
|
||||||
return <Slide direction='up' ref={ref} {...props} />
|
return <Slide ref={ref} direction='up' {...props} />
|
||||||
})
|
})
|
||||||
|
|
||||||
function toEmbedUrl(url) {
|
function toEmbedUrl(url) {
|
||||||
@@ -31,6 +31,7 @@ function toEmbedUrl(url) {
|
|||||||
if (match) {
|
if (match) {
|
||||||
return `${u.origin}/videos/embed/${match[1]}?title=0&warningTitle=0&peertubeLink=0&controlBar=1`
|
return `${u.origin}/videos/embed/${match[1]}?title=0&warningTitle=0&peertubeLink=0&controlBar=1`
|
||||||
}
|
}
|
||||||
|
|
||||||
return url
|
return url
|
||||||
} catch {
|
} catch {
|
||||||
return url
|
return url
|
||||||
@@ -45,7 +46,9 @@ export default function KaraokeModal({url, desktopUrl, titre, artistes}) {
|
|||||||
const activeUrl = (!isMobile && desktopUrl) ? desktopUrl : url
|
const activeUrl = (!isMobile && desktopUrl) ? desktopUrl : url
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!open) setLoaded(false)
|
if (!open) {
|
||||||
|
setLoaded(false)
|
||||||
|
}
|
||||||
}, [open])
|
}, [open])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -55,13 +58,13 @@ export default function KaraokeModal({url, desktopUrl, titre, artistes}) {
|
|||||||
color='primary'
|
color='primary'
|
||||||
size={isMobile ? 'medium' : 'large'}
|
size={isMobile ? 'medium' : 'large'}
|
||||||
aria-label='karaoké'
|
aria-label='karaoké'
|
||||||
onClick={() => setOpen(true)}
|
|
||||||
sx={{
|
sx={{
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
bottom: {xs: 24, sm: 32},
|
bottom: {xs: 24, sm: 32},
|
||||||
right: {xs: 24, sm: 32},
|
right: {xs: 24, sm: 32},
|
||||||
zIndex: 1050,
|
zIndex: 1050,
|
||||||
}}
|
}}
|
||||||
|
onClick={() => setOpen(true)}
|
||||||
>
|
>
|
||||||
<MicIcon />
|
<MicIcon />
|
||||||
</Fab>
|
</Fab>
|
||||||
@@ -69,7 +72,6 @@ export default function KaraokeModal({url, desktopUrl, titre, artistes}) {
|
|||||||
|
|
||||||
<Dialog
|
<Dialog
|
||||||
open={open}
|
open={open}
|
||||||
onClose={() => setOpen(false)}
|
|
||||||
slots={{transition: SlideUp}}
|
slots={{transition: SlideUp}}
|
||||||
maxWidth={false}
|
maxWidth={false}
|
||||||
sx={{
|
sx={{
|
||||||
@@ -102,6 +104,7 @@ export default function KaraokeModal({url, desktopUrl, titre, artistes}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
onClose={() => setOpen(false)}
|
||||||
>
|
>
|
||||||
{/* Header superposé en gradient */}
|
{/* Header superposé en gradient */}
|
||||||
<Box sx={{
|
<Box sx={{
|
||||||
@@ -118,7 +121,8 @@ export default function KaraokeModal({url, desktopUrl, titre, artistes}) {
|
|||||||
alignItems: 'flex-start',
|
alignItems: 'flex-start',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
pointerEvents: 'none',
|
pointerEvents: 'none',
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
<Box sx={{pointerEvents: 'none'}}>
|
<Box sx={{pointerEvents: 'none'}}>
|
||||||
{titre && (
|
{titre && (
|
||||||
<Typography variant='subtitle1' sx={{color: '#fff', fontWeight: 700, lineHeight: 1.2, textShadow: '0 1px 4px rgba(0,0,0,0.5)'}}>
|
<Typography variant='subtitle1' sx={{color: '#fff', fontWeight: 700, lineHeight: 1.2, textShadow: '0 1px 4px rgba(0,0,0,0.5)'}}>
|
||||||
@@ -133,7 +137,6 @@ export default function KaraokeModal({url, desktopUrl, titre, artistes}) {
|
|||||||
</Box>
|
</Box>
|
||||||
<IconButton
|
<IconButton
|
||||||
size='small'
|
size='small'
|
||||||
onClick={() => setOpen(false)}
|
|
||||||
aria-label='fermer'
|
aria-label='fermer'
|
||||||
sx={{
|
sx={{
|
||||||
pointerEvents: 'auto',
|
pointerEvents: 'auto',
|
||||||
@@ -143,6 +146,7 @@ export default function KaraokeModal({url, desktopUrl, titre, artistes}) {
|
|||||||
border: '1px solid rgba(255,255,255,0.12)',
|
border: '1px solid rgba(255,255,255,0.12)',
|
||||||
'&:hover': {bgcolor: 'rgba(255,255,255,0.25)'},
|
'&:hover': {bgcolor: 'rgba(255,255,255,0.25)'},
|
||||||
}}
|
}}
|
||||||
|
onClick={() => setOpen(false)}
|
||||||
>
|
>
|
||||||
<CloseIcon fontSize='small' />
|
<CloseIcon fontSize='small' />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
@@ -166,7 +170,8 @@ export default function KaraokeModal({url, desktopUrl, titre, artistes}) {
|
|||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
gap: 1.5,
|
gap: 1.5,
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
<MicIcon sx={{fontSize: 44, color: 'rgba(255,255,255,0.55)', animation: `${pulse} 1.6s ease-in-out infinite`}} />
|
<MicIcon sx={{fontSize: 44, color: 'rgba(255,255,255,0.55)', animation: `${pulse} 1.6s ease-in-out infinite`}} />
|
||||||
<Typography
|
<Typography
|
||||||
variant='caption'
|
variant='caption'
|
||||||
@@ -187,27 +192,28 @@ export default function KaraokeModal({url, desktopUrl, titre, artistes}) {
|
|||||||
transform: 'translateX(-50%)',
|
transform: 'translateX(-50%)',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
aspectRatio: '16 / 9',
|
aspectRatio: '16 / 9',
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
<iframe
|
<iframe
|
||||||
src={toEmbedUrl(activeUrl)}
|
|
||||||
onLoad={() => setLoaded(true)}
|
|
||||||
style={{width: '100%', height: '100%', border: 'none', display: 'block', opacity: loaded ? 1 : 0, transition: 'opacity 0.4s ease'}}
|
|
||||||
allowFullScreen
|
allowFullScreen
|
||||||
|
src={toEmbedUrl(activeUrl)}
|
||||||
|
style={{width: '100%', height: '100%', border: 'none', display: 'block', opacity: loaded ? 1 : 0, transition: 'opacity 0.4s ease'}}
|
||||||
allow='autoplay; fullscreen'
|
allow='autoplay; fullscreen'
|
||||||
sandbox='allow-same-origin allow-scripts allow-popups allow-forms'
|
sandbox='allow-same-origin allow-scripts allow-popups allow-forms'
|
||||||
title='Karaoké'
|
title='Karaoké'
|
||||||
|
onLoad={() => setLoaded(true)}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
) : (
|
) : (
|
||||||
/* Vidéo 16:9 desktop : player remplit exactement le dialog paysage */
|
/* Vidéo 16:9 desktop : player remplit exactement le dialog paysage */
|
||||||
<iframe
|
<iframe
|
||||||
src={toEmbedUrl(activeUrl)}
|
|
||||||
onLoad={() => setLoaded(true)}
|
|
||||||
style={{width: '100%', height: '100%', border: 'none', display: 'block', opacity: loaded ? 1 : 0, transition: 'opacity 0.4s ease'}}
|
|
||||||
allowFullScreen
|
allowFullScreen
|
||||||
|
src={toEmbedUrl(activeUrl)}
|
||||||
|
style={{width: '100%', height: '100%', border: 'none', display: 'block', opacity: loaded ? 1 : 0, transition: 'opacity 0.4s ease'}}
|
||||||
allow='autoplay; fullscreen'
|
allow='autoplay; fullscreen'
|
||||||
sandbox='allow-same-origin allow-scripts allow-popups allow-forms'
|
sandbox='allow-same-origin allow-scripts allow-popups allow-forms'
|
||||||
title='Karaoké'
|
title='Karaoké'
|
||||||
|
onLoad={() => setLoaded(true)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -30,9 +30,10 @@ function createAudio(src) {
|
|||||||
function parseLrc(text) {
|
function parseLrc(text) {
|
||||||
const lines = []
|
const lines = []
|
||||||
for (const raw of text.split('\n')) {
|
for (const raw of text.split('\n')) {
|
||||||
const match = raw.match(/^\[(\d{2}):(\d{2})[.:]\d+\](.*)$/)
|
const match = raw.match(/^\[(\d{2}):(\d{2})[.:]\d+](.*)$/)
|
||||||
if (match) {
|
if (match) {
|
||||||
lines.push({time: parseInt(match[1]) * 60 + parseInt(match[2]), text: match[3].trim()})
|
const time = (Number.parseInt(match[1], 10) * 60) + Number.parseInt(match[2], 10)
|
||||||
|
lines.push({time, text: match[3].trim()})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,6 +146,7 @@ export default function Lekte({audio, url, parole}) {
|
|||||||
setPosition(0)
|
setPosition(0)
|
||||||
el.currentTime = 0
|
el.currentTime = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
el.addEventListener('loadedmetadata', onLoaded)
|
el.addEventListener('loadedmetadata', onLoaded)
|
||||||
el.addEventListener('ended', onEnded)
|
el.addEventListener('ended', onEnded)
|
||||||
return () => {
|
return () => {
|
||||||
@@ -154,7 +156,10 @@ export default function Lekte({audio, url, parole}) {
|
|||||||
}, [audio])
|
}, [audio])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!parole?.pawol?.url) return
|
if (!parole?.pawol?.url) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
fetch(new URL(parole.pawol.url, IMAGE_URL).toString())
|
fetch(new URL(parole.pawol.url, IMAGE_URL).toString())
|
||||||
.then(r => r.text())
|
.then(r => r.text())
|
||||||
.then(text => setLrcLines(parseLrc(text)))
|
.then(text => setLrcLines(parseLrc(text)))
|
||||||
@@ -162,7 +167,7 @@ export default function Lekte({audio, url, parole}) {
|
|||||||
}, [parole?.pawol?.url])
|
}, [parole?.pawol?.url])
|
||||||
|
|
||||||
const activeIndex = lrcLines
|
const activeIndex = lrcLines
|
||||||
? lrcLines.reduce((last, line, i) => line.time <= position ? i : last, -1)
|
? lrcLines.findLastIndex(line => line.time <= position)
|
||||||
: -1
|
: -1
|
||||||
|
|
||||||
const handleChangePosition = value => {
|
const handleChangePosition = value => {
|
||||||
@@ -317,7 +322,10 @@ export default function Lekte({audio, url, parole}) {
|
|||||||
{[-1, 0, 1].map(offset => {
|
{[-1, 0, 1].map(offset => {
|
||||||
const idx = activeIndex + offset
|
const idx = activeIndex + offset
|
||||||
const line = lrcLines[idx]
|
const line = lrcLines[idx]
|
||||||
if (!line) return <Box key={offset} sx={{height: offset === 0 ? 28 : 20}} />
|
if (!line) {
|
||||||
|
return <Box key={offset} sx={{height: offset === 0 ? 28 : 20}} />
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Typography
|
<Typography
|
||||||
key={offset}
|
key={offset}
|
||||||
|
|||||||
@@ -51,9 +51,9 @@ export default function TeksKat({parole}) {
|
|||||||
<Box sx={{position: 'relative', height: 240}}>
|
<Box sx={{position: 'relative', height: 240}}>
|
||||||
{couverture?.url ? (
|
{couverture?.url ? (
|
||||||
<Image
|
<Image
|
||||||
|
fill
|
||||||
src={`${IMAGE_URL}${formatKuveti(couverture, 'thumbnail')?.url}`}
|
src={`${IMAGE_URL}${formatKuveti(couverture, 'thumbnail')?.url}`}
|
||||||
alt={titre}
|
alt={titre}
|
||||||
fill
|
|
||||||
placeholder='blur'
|
placeholder='blur'
|
||||||
blurDataURL={BLUR_DATA_URL}
|
blurDataURL={BLUR_DATA_URL}
|
||||||
sizes='(max-width: 600px) 100vw, (max-width: 900px) 50vw, 33vw'
|
sizes='(max-width: 600px) 100vw, (max-width: 900px) 50vw, 33vw'
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ export default function Teks({parole}) {
|
|||||||
<i>parole soumise par {parole.user.username}</i>
|
<i>parole soumise par {parole.user.username}</i>
|
||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
{parole?.userAdmin&& !parole.user && (
|
{parole?.userAdmin && !parole.user && (
|
||||||
<Typography style={{marginBottom: '1.5em'}} display='block' variant='caption'>
|
<Typography style={{marginBottom: '1.5em'}} display='block' variant='caption'>
|
||||||
<i>parole soumise par {parole.userAdmin.firstname}</i>
|
<i>parole soumise par {parole.userAdmin.firstname}</i>
|
||||||
</Typography>
|
</Typography>
|
||||||
@@ -220,8 +220,8 @@ export default function Teks({parole}) {
|
|||||||
Écouter sur
|
Écouter sur
|
||||||
</Typography>
|
</Typography>
|
||||||
<Box sx={{display: 'flex', flexWrap: 'wrap', justifyContent: 'center', gap: 1}}>
|
<Box sx={{display: 'flex', flexWrap: 'wrap', justifyContent: 'center', gap: 1}}>
|
||||||
{parole.streamAudio.map((lyen, i) => (
|
{parole.streamAudio.map(lyen => (
|
||||||
<StreamButton key={i} lyen={lyen} />
|
<StreamButton key={lyen.url} lyen={lyen} />
|
||||||
))}
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -229,11 +229,10 @@ export default function Teks({parole}) {
|
|||||||
</Box>
|
</Box>
|
||||||
<Box sx={{maxWidth: 700, margin: '0 auto'}} className={classes.gridText}>
|
<Box sx={{maxWidth: 700, margin: '0 auto'}} className={classes.gridText}>
|
||||||
<Tabs
|
<Tabs
|
||||||
value={tab}
|
|
||||||
onChange={(event, value) => setTab(value)}
|
|
||||||
variant='scrollable'
|
|
||||||
scrollButtons
|
scrollButtons
|
||||||
allowScrollButtonsMobile
|
allowScrollButtonsMobile
|
||||||
|
value={tab}
|
||||||
|
variant='scrollable'
|
||||||
centered={langArray.length === 0}
|
centered={langArray.length === 0}
|
||||||
slots={{
|
slots={{
|
||||||
startScrollButtonIcon: ArrowBackIosNewIcon,
|
startScrollButtonIcon: ArrowBackIosNewIcon,
|
||||||
@@ -255,6 +254,7 @@ export default function Teks({parole}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
onChange={(event, value) => setTab(value)}
|
||||||
>
|
>
|
||||||
<Tab label='Transcription' />
|
<Tab label='Transcription' />
|
||||||
{langArray.map(({title}) => (
|
{langArray.map(({title}) => (
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
import NextTopLoader from 'nextjs-toploader'
|
import NextTopLoader from 'nextjs-toploader'
|
||||||
|
|
||||||
export default function TopLoader({color}) {
|
export default function TopLoader({color}) {
|
||||||
return <NextTopLoader color={color} />
|
return <NextTopLoader color={color} />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TopLoader.propTypes = {
|
||||||
|
color: PropTypes.string.isRequired
|
||||||
|
}
|
||||||
|
|||||||
+14
-14
@@ -1,25 +1,25 @@
|
|||||||
import { dirname } from "path";
|
import {dirname} from 'node:path'
|
||||||
import { fileURLToPath } from "url";
|
import {fileURLToPath} from 'node:url'
|
||||||
import { FlatCompat } from "@eslint/eslintrc";
|
import {FlatCompat} from '@eslint/eslintrc'
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url)
|
||||||
const __dirname = dirname(__filename);
|
const __dirname = dirname(__filename)
|
||||||
|
|
||||||
const compat = new FlatCompat({
|
const compat = new FlatCompat({
|
||||||
baseDirectory: __dirname,
|
baseDirectory: __dirname,
|
||||||
});
|
})
|
||||||
|
|
||||||
const eslintConfig = [
|
const eslintConfig = [
|
||||||
...compat.extends("next/core-web-vitals"),
|
...compat.extends('next/core-web-vitals'),
|
||||||
{
|
{
|
||||||
ignores: [
|
ignores: [
|
||||||
"node_modules/**",
|
'node_modules/**',
|
||||||
".next/**",
|
'.next/**',
|
||||||
"out/**",
|
'out/**',
|
||||||
"build/**",
|
'build/**',
|
||||||
"next-env.d.ts",
|
'next-env.d.ts',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
]
|
||||||
|
|
||||||
export default eslintConfig;
|
export default eslintConfig
|
||||||
|
|||||||
+8
-2
@@ -6,10 +6,16 @@ const SIZE_ORDER = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const formatKuveti = (kuveti, preferred = 'large') => {
|
export const formatKuveti = (kuveti, preferred = 'large') => {
|
||||||
if (!kuveti) return null
|
if (!kuveti) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
const order = SIZE_ORDER[preferred] ?? SIZE_ORDER.large
|
const order = SIZE_ORDER[preferred] ?? SIZE_ORDER.large
|
||||||
for (const size of order) {
|
for (const size of order) {
|
||||||
if (kuveti.formats?.[size]) return kuveti.formats[size]
|
if (kuveti.formats?.[size]) {
|
||||||
|
return kuveti.formats[size]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return kuveti
|
return kuveti
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -186,6 +186,7 @@ async function jwennTouSlug(endpoint) {
|
|||||||
encodeValuesOnly: true
|
encodeValuesOnly: true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-await-in-loop -- pagination séquentielle, chaque page dépend du nombre de résultats de la précédente
|
||||||
const {data} = await request(`/${endpoint}?${query}`, headers)
|
const {data} = await request(`/${endpoint}?${query}`, headers)
|
||||||
slugs.push(...data.map(({slug}) => slug))
|
slugs.push(...data.map(({slug}) => slug))
|
||||||
hasMore = data.length === pageSize
|
hasMore = data.length === pageSize
|
||||||
@@ -223,9 +224,9 @@ export async function jwennAnVedette() {
|
|||||||
const query = qs.stringify({
|
const query = qs.stringify({
|
||||||
populate: ['artistes', 'couverture'],
|
populate: ['artistes', 'couverture'],
|
||||||
filters: {
|
filters: {
|
||||||
isNewRelease: { $eq: true }
|
isNewRelease: {$eq: true}
|
||||||
},
|
},
|
||||||
pagination: { limit: 1 }
|
pagination: {limit: 1}
|
||||||
}, {
|
}, {
|
||||||
encodeValuesOnly: true
|
encodeValuesOnly: true
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,16 +1,12 @@
|
|||||||
import YouTubeIcon from '@mui/icons-material/YouTube'
|
import YouTubeIcon from '@mui/icons-material/YouTube'
|
||||||
import TelegramIcon from '@mui/icons-material/Telegram'
|
import TelegramIcon from '@mui/icons-material/Telegram'
|
||||||
|
|
||||||
import PeertubeIcon from './icons/peertube'
|
|
||||||
import XmppIcon from './icons/xmpp'
|
|
||||||
import XIcon from './icons/x'
|
import XIcon from './icons/x'
|
||||||
import GiteaIcon from './icons/gitea'
|
import GiteaIcon from './icons/gitea'
|
||||||
import BlueskyIcon from './icons/bluesky'
|
import BlueskyIcon from './icons/bluesky'
|
||||||
|
|
||||||
const gitURL = process.env.NEXT_PUBLIC_GIT || 'https://labola.o-k-i.net/ORGANISATION-KA-INTERNATIONALE/pawol.nu'
|
const gitURL = process.env.NEXT_PUBLIC_GIT || 'https://labola.o-k-i.net/ORGANISATION-KA-INTERNATIONALE/pawol.nu'
|
||||||
const blueskyUrl = process.env.NEXT_PUBLIC_BLUESKY_URL || 'https://bsky.app/profile/organisationka.bsky.social'
|
const blueskyUrl = process.env.NEXT_PUBLIC_BLUESKY_URL || 'https://bsky.app/profile/organisationka.bsky.social'
|
||||||
const xmppContact = process.env.NEXT_PUBLIC_XMPP || 'oki@xmpp.cz'
|
|
||||||
const gadeUsername = process.env.NEXT_PUBLIC_GADE_USERNAME || 'oki'
|
|
||||||
const youtubeUsername = process.env.NEXT_PUBLIC_YOUTUBE_USERNAME || 'OrganisationKInternationaleOKi'
|
const youtubeUsername = process.env.NEXT_PUBLIC_YOUTUBE_USERNAME || 'OrganisationKInternationaleOKi'
|
||||||
const tiwtterUsername = process.env.NEXT_PUBLIC_TWITTER_USERNAME || 'OrganisationKA'
|
const tiwtterUsername = process.env.NEXT_PUBLIC_TWITTER_USERNAME || 'OrganisationKA'
|
||||||
const telegramGroup = process.env.NEXT_PUBLIC_TELEGRAM_GROUP || 'OrganisationKA'
|
const telegramGroup = process.env.NEXT_PUBLIC_TELEGRAM_GROUP || 'OrganisationKA'
|
||||||
|
|||||||
+10
-3
@@ -11,13 +11,20 @@ function buildRemotePatterns() {
|
|||||||
const [hostname, port] = entry.split(':')
|
const [hostname, port] = entry.split(':')
|
||||||
const isLocal = hostname === 'localhost' || hostname === '127.0.0.1'
|
const isLocal = hostname === 'localhost' || hostname === '127.0.0.1'
|
||||||
const pattern = {protocol: isLocal ? 'http' : 'https', hostname, pathname: '/uploads/**'}
|
const pattern = {protocol: isLocal ? 'http' : 'https', hostname, pathname: '/uploads/**'}
|
||||||
if (port) pattern.port = port
|
if (port) {
|
||||||
|
pattern.port = port
|
||||||
|
}
|
||||||
|
|
||||||
return pattern
|
return pattern
|
||||||
})
|
})
|
||||||
if (!raw.includes('localhost'))
|
if (!raw.includes('localhost')) {
|
||||||
patterns.push({protocol: 'http', hostname: 'localhost', port: '1337', pathname: '/uploads/**'})
|
patterns.push({protocol: 'http', hostname: 'localhost', port: '1337', pathname: '/uploads/**'})
|
||||||
if (!raw.includes('127.0.0.1'))
|
}
|
||||||
|
|
||||||
|
if (!raw.includes('127.0.0.1')) {
|
||||||
patterns.push({protocol: 'http', hostname: '127.0.0.1', port: '1337', pathname: '/uploads/**'})
|
patterns.push({protocol: 'http', hostname: '127.0.0.1', port: '1337', pathname: '/uploads/**'})
|
||||||
|
}
|
||||||
|
|
||||||
return patterns
|
return patterns
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
import '@testing-library/jest-dom/vitest'
|
import '@testing-library/jest-dom/vitest' // eslint-disable-line import/no-unassigned-import
|
||||||
|
|||||||
Reference in New Issue
Block a user