Merge pull request 'Mise à jour de NextJS et Mui' (#4) from adapt-upgrade-strapi into master

Reviewed-on: https://codeberg.org/OKI/oki.re/pulls/4
This commit is contained in:
Cédric Famibelle-Pronzola
2026-04-22 05:45:33 +02:00
47 changed files with 807 additions and 724 deletions
+3 -3
View File
@@ -1,4 +1,4 @@
# Made with [Nextjs 14](https://nextjs.org/) and [Material-UI 6](https://material-ui.com/) # Made with [Nextjs 16](https://nextjs.org/) and [Material-UI 9](https://material-ui.com/)
<p align="center"> <p align="center">
<a href="https://liberapay.com/OKI/donate/"> <a href="https://liberapay.com/OKI/donate/">
@@ -9,7 +9,7 @@
</p> </p>
## Prérequis ## Prérequis
- Node >= 16 - Node >= 20
- [API](https://codeberg.org/OKI/api.oki.re) - [API](https://codeberg.org/OKI/api.oki.re)
## Variables d'environement ## Variables d'environement
@@ -26,7 +26,7 @@ yarn && yarn dev
## License ## License
Copyright (C) 2020 - 2024 Cédric Famibelle-Pronzola & ORGANISATION KA INTERNATIONALE (OKI) Copyright (C) 2020 - 2026 Cédric Famibelle-Pronzola & ORGANISATION KA INTERNATIONALE (OKI)
### FR ### FR
+2 -1
View File
@@ -42,7 +42,8 @@ export const { handlers, auth } = NextAuth({
}) })
], ],
session: { session: {
strategy: "jwt" strategy: "jwt",
trustHost: true
}, },
secret: process.env.NEXT_PUBLIC_JWT_SECRET, secret: process.env.NEXT_PUBLIC_JWT_SECRET,
callbacks: { callbacks: {
+11 -11
View File
@@ -10,13 +10,13 @@ const apiUrl = process.env.NEXT_PUBLIC_API_URL_ROOT || 'http://localhost:1337'
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3000' const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3000'
async function jwennAwtis(slug) { async function jwennAwtis(slug) {
const awtis = await jwennAwtisEpiSlug(slug) const {data} = await jwennAwtisEpiSlug(slug)
if (!awtis) { if (!data) {
notFound() notFound()
} }
return awtis return data
} }
export async function generateMetadata(props) { export async function generateMetadata(props) {
@@ -24,11 +24,11 @@ export async function generateMetadata(props) {
const {slug} = params const {slug} = params
const anAwtis = await jwennAwtis(slug) const anAwtis = await jwennAwtis(slug)
const title = `OKI | ${anAwtis.attributes.alias} - Paroles et Traductions` const title = `OKI | ${anAwtis.alias} - Paroles et Traductions`
const description = `${anAwtis.attributes.alias}${anAwtis?.attributes?.biographie ? ` : ${anAwtis?.attributes?.biographie.slice(0, 100)}...` : ''}` const description = `${anAwtis.alias}${anAwtis?.biographie ? ` : ${anAwtis?.biographie.slice(0, 100)}...` : ''}`
const url = `${siteUrl}/awtis/${slug}` const url = `${siteUrl}/awtis/${slug}`
const {photo} = anAwtis.attributes const {photo} = anAwtis
const kuvetiFormat = formatKuveti(photo) const kuvetiFormat = formatKuveti(photo)
return { return {
@@ -57,7 +57,7 @@ export async function generateMetadata(props) {
creator: '@OrganisationKA', creator: '@OrganisationKA',
images: { images: {
url: `${apiUrl}${kuvetiFormat?.url}`, url: `${apiUrl}${kuvetiFormat?.url}`,
alt: `Photo de ${anAwtis.attributes.alias}`, alt: `Photo de ${anAwtis.alias}`,
} }
} }
} }
@@ -68,14 +68,14 @@ export default async function AwtisPajSlug(props) {
const {slug} = params const {slug} = params
const anAwtis = await jwennAwtis(slug) const anAwtis = await jwennAwtis(slug)
const {photo} = anAwtis.attributes const {photo} = anAwtis
const kuvetiFormat = formatKuveti(photo) const kuvetiFormat = formatKuveti(photo)
const jsonLd = { const jsonLd = {
'@context': 'http://schema.org', '@context': 'http://schema.org',
'@type': 'Person', '@type': 'Person',
'@id': anAwtis.attributes.musicBrainzUrl || undefined, '@id': anAwtis.musicBrainzUrl || undefined,
name: anAwtis.attributes.alias, name: anAwtis.alias,
url: `${siteUrl}/awtis/${slug}`, url: `${siteUrl}/awtis/${slug}`,
image: kuvetiFormat?.url ? `${apiUrl}${kuvetiFormat.url}` : undefined image: kuvetiFormat?.url ? `${apiUrl}${kuvetiFormat.url}` : undefined
} }
@@ -84,7 +84,7 @@ export default async function AwtisPajSlug(props) {
<> <>
<Box sx={{display: 'flex', flexDirection: 'column', minHeight: '100vh'}}> <Box sx={{display: 'flex', flexDirection: 'column', minHeight: '100vh'}}>
<Box sx={{flexGrow: 1}}> <Box sx={{flexGrow: 1}}>
<AwtisDetay anAwtis={anAwtis.attributes} /> <AwtisDetay anAwtis={anAwtis} />
</Box> </Box>
<Footer /> <Footer />
</Box> </Box>
+5 -5
View File
@@ -1,7 +1,7 @@
import {notFound} from 'next/navigation' import {notFound} from 'next/navigation'
import Box from '@mui/material/Box' import Box from '@mui/material/Box'
import Container from '@mui/material/Container' import Container from '@mui/material/Container'
import Grid from '@mui/material/Grid2' import Grid from '@mui/material/Grid'
import ChecheAwtis from '../../components/awtis/cheche-awtis' import ChecheAwtis from '../../components/awtis/cheche-awtis'
import AwtisKat from '../../components/awtis/awtis-kat' import AwtisKat from '../../components/awtis/awtis-kat'
@@ -48,14 +48,14 @@ async function jwennDone(paj) {
notFound() notFound()
} }
const awtisPouChakPaj = await jwennAwtisPajinasyon(pajParsed) const {data, meta} = await jwennAwtisPajinasyon(pajParsed)
const pajTotal = Math.ceil(awtisPouChakPaj.meta.pagination.total / awtisPouChakPaj.meta.pagination.limit) const pajTotal = Math.ceil(meta.pagination.total / meta.pagination.limit)
if (pajParsed > pajTotal || pajParsed < 1) { if (pajParsed > pajTotal || pajParsed < 1) {
notFound() notFound()
} }
return {pajTotal, awtisPouChakPaj, pajParsed} return {pajTotal, awtisPouChakPaj: data, pajParsed}
} }
export default async function AwitsPaj(props) { export default async function AwitsPaj(props) {
@@ -69,7 +69,7 @@ export default async function AwitsPaj(props) {
<ChecheAwtis /> <ChecheAwtis />
<Container sx={{marginBottom: 5, flexGrow: 100}}> <Container sx={{marginBottom: 5, flexGrow: 100}}>
<Grid container spacing={{xs: 2, md: 3}}> <Grid container spacing={{xs: 2, md: 3}}>
{awtisPouChakPaj.data.map(artiste => <AwtisKat key={artiste.id} artiste={artiste.attributes} />)} {awtisPouChakPaj.map(artiste => <AwtisKat key={artiste.id} artiste={artiste} />)}
</Grid> </Grid>
</Container> </Container>
<Footer /> <Footer />
+2 -1
View File
@@ -11,7 +11,8 @@ export default function Error() {
width={192} width={192}
height={192} height={192}
src='/logo-192x192.png' src='/logo-192x192.png'
quality={20} quality={[20, 75]}
loading='eager'
/> />
<Typography variant='h2' align='center' >500 - Erreur du serveur 😭</Typography> <Typography variant='h2' align='center' >500 - Erreur du serveur 😭</Typography>
<Typography style={{marginTop: '1em', color: 'green'}} variant='h3' align='center'>Nous mettons tout en œuvre pour rétablir le site dans les plus brefs délais 💪🏾</Typography> <Typography style={{marginTop: '1em', color: 'green'}} variant='h3' align='center'>Nous mettons tout en œuvre pour rétablir le site dans les plus brefs délais 💪🏾</Typography>
+2 -2
View File
@@ -1,4 +1,4 @@
import NextTopLoader from 'nextjs-toploader' import TopLoader from '../components/top-loader'
import Navigasyon from '../components/navigasyon' import Navigasyon from '../components/navigasyon'
import AuthProvider from './auth-provider' import AuthProvider from './auth-provider'
import ThemeRegistry from './theme-registy' import ThemeRegistry from './theme-registy'
@@ -55,7 +55,7 @@ export default async function RootLayout({children, Session}) {
return ( return (
<html lang='fr' suppressHydrationWarning> <html lang='fr' suppressHydrationWarning>
<body> <body>
<NextTopLoader color='#ffeb3b' /> <TopLoader color='#ffeb3b' />
<AuthProvider session={Session}> <AuthProvider session={Session}>
<ThemeRegistry> <ThemeRegistry>
<Navigasyon /> <Navigasyon />
+2 -1
View File
@@ -11,7 +11,8 @@ export default function NotFound() {
width={192} width={192}
height={192} height={192}
src='/logo-192x192.png' src='/logo-192x192.png'
quality={20} quality={[20, 75]}
loading='eager'
/> />
</Link> </Link>
<Typography variant='h2' align='center' >404 - La page nexiste pas 😔</Typography> <Typography variant='h2' align='center' >404 - La page nexiste pas 😔</Typography>
+14 -15
View File
@@ -26,12 +26,12 @@ export async function generateMetadata(props) {
const anTeks = await jwennAnTeks(slug) const anTeks = await jwennAnTeks(slug)
const awtis = anTeks.attributes.artistes.length === 1 ? anTeks.attributes.artistes[0].data.attributes.alias : getAlias(anTeks.attributes.artistes, anTeks.attributes.prioriteArtistes) const awtis = anTeks?.artistes?.length === 1 ? anTeks?.artistes[0].alias : getAlias(anTeks.artistes, anTeks.prioriteArtistes)
const title = `OKI | ${awtis} - ${anTeks.attributes.titre} | Paroles et Traductions` const title = `OKI | ${awtis} - ${anTeks.titre} | Paroles et Traductions`
const description = `Paroles de « ${anTeks?.attributes?.titre} » : ${anTeks?.attributes?.transcription.slice(0, 100)}...` const description = `Paroles de « ${anTeks?.titre} » : ${anTeks?.transcription.slice(0, 100)}...`
const url = `${siteUrl}/paroles/${slug}` const url = `${siteUrl}/paroles/${slug}`
const {couverture} = anTeks.attributes const {couverture} = anTeks
const kuvetiFormat = formatKuveti(couverture) const kuvetiFormat = formatKuveti(couverture)
return { return {
@@ -71,30 +71,29 @@ export default async function AnPawolPaj(props) {
const {slug} = params const {slug} = params
const anTeks = await jwennAnTeks(slug) const anTeks = await jwennAnTeks(slug)
const {couverture} = anTeks.attributes const {couverture} = anTeks
const teksKuvetiFormat = formatKuveti(couverture) const teksKuvetiFormat = formatKuveti(couverture)
const jsonLd = { const jsonLd = {
'@context': 'http://schema.org', '@context': 'http://schema.org',
'@type': 'MusicRecording', '@type': 'MusicRecording',
'@id': anTeks.attributes.musicBrainzUrl || undefined, '@id': anTeks.musicBrainzUrl || undefined,
name: anTeks.attributes.titre, name: anTeks.titre,
url: `${siteUrl}/paroles/${slug}`, url: `${siteUrl}/paroles/${slug}`,
image: teksKuvetiFormat?.url ? `${apiUrl}${teksKuvetiFormat?.url}` : undefined, image: teksKuvetiFormat?.url ? `${apiUrl}${teksKuvetiFormat?.url}` : undefined,
thumbnailUrl: couverture?.data?.attributes?.formats?.thumbnail?.url ? `${apiUrl}${couverture.data.attributes.formats.thumbnail.url}` : undefined, thumbnailUrl: couverture?.formats?.thumbnail?.url ? `${apiUrl}${couverture.formats.thumbnail.url}` : undefined,
byArtist: anTeks.attributes.artistes.data.map(({attributes}) => { byArtist: anTeks.artistes.map(({photo, musicBrainzUrl, alias, slug}) => {
const {photo} = attributes
const kuvetiFormat = formatKuveti(photo) const kuvetiFormat = formatKuveti(photo)
return { return {
'@type': 'Person', '@type': 'Person',
'@id': attributes.musicBrainzUrl || undefined, '@id': musicBrainzUrl || undefined,
name: attributes.alias, name: alias,
url: `${siteUrl}/awtis/${attributes.slug}`, url: `${siteUrl}/awtis/${slug}`,
image: kuvetiFormat?.url ? `${apiUrl}${kuvetiFormat?.url}` : undefined image: kuvetiFormat?.url ? `${apiUrl}${kuvetiFormat?.url}` : undefined
} }
}), }),
datePublished: anTeks.attributes?.annee datePublished: anTeks?.annee
} }
return ( return (
@@ -104,7 +103,7 @@ export default async function AnPawolPaj(props) {
component='main' component='main'
sx={{flexGrow: 1, p: 2, mt: 2}} sx={{flexGrow: 1, p: 2, mt: 2}}
> >
<AnTeks parole={anTeks.attributes} paroleId={anTeks.id} /> <AnTeks parole={anTeks} paroleId={anTeks.id} />
</Box> </Box>
<Footer /> <Footer />
</Box> </Box>
+2 -2
View File
@@ -11,10 +11,10 @@ export default function Sipote() {
const [paymentMethod, setPaymentMethod] = useState(0) const [paymentMethod, setPaymentMethod] = useState(0)
return ( return (
<Box sx={{display: 'flex', marginTop: 3, 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}}>
+1 -1
View File
@@ -3,7 +3,7 @@ import {Container, Link, Typography} from '@mui/material'
export default function Aso() { export default function Aso() {
return ( return (
<Container sx={{my: 3, textAlign: 'center'}} > <Container sx={{my: 3, textAlign: 'center'}} >
<Typography gutterBottom variant='h5' sx={{fontWeight: 'bold', mb: 2}} textAlign='center' component='h2'> <Typography gutterBottom variant='h5' sx={{fontWeight: 'bold', mb: 2}} textalign='center' component='h2'>
Qui sommes-nous ? Qui sommes-nous ?
</Typography> </Typography>
<Typography gutterBottom component='h3'> <Typography gutterBottom component='h3'>
+5 -4
View File
@@ -2,14 +2,14 @@ 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/Grid2' import Grid from '@mui/material/Grid'
import Button from '@mui/material/Button' import Button from '@mui/material/Button'
import Image from 'next/image' import Image from 'next/image'
import Link from 'next/link' import Link from 'next/link'
export default function Akey({logo}) { export default function Akey({logo}) {
return ( return (
<Box sx={{flexGrow: 1, marginBottom: 3, marginTop: 3}}> <Box sx={{flexGrow: 1, marginBottom: 3, marginTop: 7}}>
<Container align='center'> <Container align='center'>
<Box sx={{display: 'flex', alignItems: 'center', justifyContent: 'center'}}> <Box sx={{display: 'flex', alignItems: 'center', justifyContent: 'center'}}>
@@ -22,6 +22,7 @@ export default function Akey({logo}) {
height={32} height={32}
alt='OKI logo' alt='OKI logo'
src={logo} src={logo}
loading='eager'
/> />
</Box> </Box>
<Typography sx={{fontWeight: 'bold'}} variant='h6' component='h2'> <Typography sx={{fontWeight: 'bold'}} variant='h6' component='h2'>
@@ -32,8 +33,8 @@ export default function Akey({logo}) {
</Typography> </Typography>
</Container> </Container>
<Container sx={{marginTop: 2}}> <Container sx={{marginTop: 2}}>
<Grid container justifyContent='center' spacing={2}> <Grid container sx={{justifyContent: 'center'}} spacing={2}>
<Grid> <Grid textalign='center'>
<Link passHref href='/pwopose'> <Link passHref href='/pwopose'>
<Button color='primary' variant='outlined'> <Button color='primary' variant='outlined'>
<strong>Proposer des paroles</strong> <strong>Proposer des paroles</strong>
+1 -1
View File
@@ -3,7 +3,7 @@
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import {useRouter} from 'next/navigation' import {useRouter} from 'next/navigation'
import {useTheme} from '@mui/material/styles' import {useTheme} from '@mui/material/styles'
import Grid from '@mui/material/Grid2' import Grid from '@mui/material/Grid'
import Card from '@mui/material/Card' import Card from '@mui/material/Card'
import CardActionArea from '@mui/material/CardActionArea' import CardActionArea from '@mui/material/CardActionArea'
import CardContent from '@mui/material/CardContent' import CardContent from '@mui/material/CardContent'
+1 -1
View File
@@ -1,6 +1,6 @@
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import Grid from '@mui/material/Grid2' import Grid from '@mui/material/Grid'
import KatAkey from './kat-akey' import KatAkey from './kat-akey'
export default function Statistik({statistik}) { export default function Statistik({statistik}) {
+17 -17
View File
@@ -11,7 +11,7 @@ import Button from '@mui/material/Button'
import CardActionArea from '@mui/material/CardActionArea' import CardActionArea from '@mui/material/CardActionArea'
import Chip from '@mui/material/Chip' import Chip from '@mui/material/Chip'
import Container from '@mui/material/Container' import Container from '@mui/material/Container'
import Grid from '@mui/material/Grid2' import Grid from '@mui/material/Grid'
import Paper from '@mui/material/Paper' import Paper from '@mui/material/Paper'
import Card from '@mui/material/Card' import Card from '@mui/material/Card'
import CardContent from '@mui/material/CardContent' import CardContent from '@mui/material/CardContent'
@@ -28,12 +28,12 @@ import MizikLyen from './mizik-lyen'
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 noImageUrl = 'https://place-hold.it/140x140?text=Indisponible' const noImageUrl = 'https://place-hold.it/140x140?text=Indisponible'
const sortTeks = paroles => paroles.sort((a, b) => a.attributes.titre.localeCompare(b.attributes.titre, 'fr', {sensitivity: 'base'})) const sortTeks = paroles => paroles.sort((a, b) => a.titre.localeCompare(b.titre, 'fr', {sensitivity: 'base'}))
export default function AwtisDetay({anAwtis}) { export default function AwtisDetay({anAwtis}) {
const [esByografiOuve, meteEsByografiOuve] = useState(false) const [esByografiOuve, meteEsByografiOuve] = useState(false)
const {alias, biographie, paroles, photo} = anAwtis const {alias, biographie, paroles, photo} = anAwtis
const sortedTeks = sortTeks(paroles?.data) const sortedTeks = sortTeks(paroles)
const gwanBiyo = biographie && biographie.length > 100 const gwanBiyo = biographie && biographie.length > 100
const biyo = gwanBiyo ? `${biographie.slice(0, 100)}...` : biographie const biyo = gwanBiyo ? `${biographie.slice(0, 100)}...` : biographie
@@ -44,19 +44,19 @@ export default function AwtisDetay({anAwtis}) {
return ( return (
<Container> <Container>
<Box sx={{marginBlock: 2}}> <Box sx={{marginTop: 8, marginBottom: 2}}>
<Typography textAlign='center' variant='h6' component='h1'> <Typography sx={{textAlign: 'center'}} variant='h6' component='h1'>
{alias} {alias}
</Typography> </Typography>
</Box> </Box>
<Box sx={{justifyContent: 'center', display: 'flex', marginBottom: 2}}> <Box sx={{justifyContent: 'center', display: 'flex', marginBottom: 2}}>
<Avatar <Avatar
src={`${photo?.data?.attributes?.url ? `${IMAGE_URL}${photo?.data?.attributes?.url}` : noImageUrl}`} src={`${photo?.url ? `${IMAGE_URL}${photo?.url}` : noImageUrl}`}
alt={`Photo ${alias}`} alt={`Photo ${alias}`}
sx={{width: 200, height: 200, border: `2px solid ${green[500]}`}} sx={{width: 200, height: 200, border: `2px solid ${green[500]}`}}
/> />
</Box> </Box>
<Grid container direction='column' justifyContent='center' alignItems='center' spacing={3}> <Grid sx={{alignItems:'center'}} container direction='column' spacing={3}>
{biyo && ( {biyo && (
<Grid size={{xs: 12, md: 6}}> <Grid size={{xs: 12, md: 6}}>
<Card sx={{minWidth: 300}}> <Card sx={{minWidth: 300}}>
@@ -65,7 +65,7 @@ export default function AwtisDetay({anAwtis}) {
<Typography gutterBottom variant='body1' component='h2'> <Typography gutterBottom variant='body1' component='h2'>
<strong>Biographie</strong> <strong>Biographie</strong>
</Typography> </Typography>
<Typography textAlign='justify' variant='subtitle1' component='h3'> <Typography textalign='justify' variant='subtitle1' component='h3'>
{biyo} {biyo}
</Typography> </Typography>
</CardContent> </CardContent>
@@ -74,20 +74,20 @@ export default function AwtisDetay({anAwtis}) {
</Grid> </Grid>
)} )}
<Grid size={{xs: 12, md: 6}}> <Grid size={{xs: 12, md: 6}}>
<Box marginBottom={3}> <Box marginbottom={3}>
{paroles.data.length > 1 ? ( {paroles.length > 1 ? (
<Accordion> <Accordion>
<AccordionSummary <AccordionSummary
expandIcon={<ExpandMoreIcon />} expandIcon={<ExpandMoreIcon />}
aria-controls='panel-teks-content' aria-controls='panel-teks-content'
id='panel-teks-header' id='panel-teks-header'
> >
<Typography marginRight={2} textAlign='center' variant='body1' component='h2'><strong>Liste des paroles</strong></Typography> <Typography sx={{marginRight: 2, textAlign:'center' }} variant='body1' component='h2'><strong>Liste des paroles</strong></Typography>
<Chip color='primary' label={paroles.data.length} size='small' variant='contained' /> <Chip color='primary' label={paroles.length} size='small' variant='contained' />
</AccordionSummary> </AccordionSummary>
<AccordionDetails sx={{paddingInline: 0}}> <AccordionDetails sx={{paddingInline: 0}}>
{sortedTeks.map(anPawol => { {sortedTeks.map(anPawol => {
const {couverture} = anPawol.attributes const {couverture} = anPawol
const kuvetiFormat = formatKuveti(couverture) const kuvetiFormat = formatKuveti(couverture)
return ( return (
@@ -99,13 +99,13 @@ export default function AwtisDetay({anAwtis}) {
</AccordionDetails> </AccordionDetails>
</Accordion> </Accordion>
) : ( ) : (
paroles.data.length === 0 ? ( paroles.length === 0 ? (
<Typography gutterBottom textAlign='center' variant='body1' component='h2'><strong>Aucune parole pour le moment</strong></Typography> <Typography gutterBottom textAlign='center' variant='body1' component='h2'><strong>Aucune parole pour le moment</strong></Typography>
) : ( ) : (
<Box> <Box>
<Typography gutterBottom textAlign='center' variant='body1' component='h2'><strong>Parole</strong></Typography> <Typography gutterBottom textalign='center' variant='body1' component='h2'><strong>Parole</strong></Typography>
<Paper sx={{height: '100%', paddingBlock: 2}}> <Paper sx={{height: '100%', paddingBlock: 2}}>
<MizikLyen anPawol={paroles.data[0]} kuveti={formatKuveti(paroles.data[0].attributes.couverture)} /> <MizikLyen anPawol={paroles[0]} kuveti={formatKuveti(paroles[0].couverture)} />
</Paper> </Paper>
</Box> </Box>
) )
@@ -123,7 +123,7 @@ export default function AwtisDetay({anAwtis}) {
{esByografiOuve && ( {esByografiOuve && (
<AwtisBiyografi <AwtisBiyografi
alias={alias} alias={alias}
paroles={paroles.data} paroles={paroles}
biographie={biographie} biographie={biographie}
esByografiOuve={esByografiOuve} esByografiOuve={esByografiOuve}
meteEsByografiOuve={meteEsByografiOuve} meteEsByografiOuve={meteEsByografiOuve}
+4 -4
View File
@@ -5,7 +5,7 @@ import {useRouter} from 'next/navigation'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import CardActionArea from '@mui/material/CardActionArea' import CardActionArea from '@mui/material/CardActionArea'
import Grid from '@mui/material/Grid2' import Grid from '@mui/material/Grid'
import Card from '@mui/material/Card' import Card from '@mui/material/Card'
import CardMedia from '@mui/material/CardMedia' import CardMedia from '@mui/material/CardMedia'
import CardContent from '@mui/material/CardContent' import CardContent from '@mui/material/CardContent'
@@ -66,7 +66,7 @@ export default function AwtisKat({artiste}) {
className={classes.media} className={classes.media}
component='img' component='img'
alt={alias} alt={alias}
image={`${photo?.data?.attributes?.url ? `${IMAGE_URL}${photo?.data?.attributes?.url}` : noImageUrl}`} image={`${photo?.url ? `${IMAGE_URL}${photo?.url}` : noImageUrl}`}
title={alias} title={alias}
/> />
<CardContent> <CardContent>
@@ -74,7 +74,7 @@ export default function AwtisKat({artiste}) {
{alias} {alias}
</Typography> </Typography>
<Typography align='center' variant='body2' color='textSecondary' component='h5'> <Typography align='center' variant='body2' color='textSecondary' component='h5'>
{`${paroles.data.length === 0 ? 'Aucune parole pour le moment' : `${paroles.data.length} ${paroles.data.length > 1 ? 'paroles' : 'parole'}`}`} {`${paroles.length === 0 ? 'Aucune parole pour le moment' : `${paroles.length} ${paroles.length > 1 ? 'paroles' : 'parole'}`}`}
</Typography> </Typography>
</CardContent> </CardContent>
</CardActionArea> </CardActionArea>
@@ -82,7 +82,7 @@ export default function AwtisKat({artiste}) {
{esByografiOuve && ( {esByografiOuve && (
<AwtisBiyografi <AwtisBiyografi
alias={alias} alias={alias}
paroles={paroles.data} paroles={paroles}
biographie={biographie} biographie={biographie}
esByografiOuve={esByografiOuve} esByografiOuve={esByografiOuve}
meteEsByografiOuve={meteEsByografiOuve} meteEsByografiOuve={meteEsByografiOuve}
+37 -30
View File
@@ -1,6 +1,6 @@
'use client' 'use client'
import {useEffect, useState} from 'react' import {useEffect, useState, useMemo} from 'react'
import {useRouter} from 'next/navigation' 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'
@@ -27,12 +27,13 @@ export default function ChecheAwtis() {
(async () => { (async () => {
try { try {
const data = await jwennToutAwtis() const {data} = await jwennToutAwtis()
const filteredData = data.map(artiste => { const filteredData = data.map(artiste => {
const firstLetter = artiste.attributes.alias[0].toUpperCase() const firstLetter = artiste.alias[0].toUpperCase()
return { return {
firstLetter: /\d/.test(firstLetter) ? '0-9' : firstLetter, firstLetter: /\d/.test(firstLetter) ? '0-9' : firstLetter,
...artiste.attributes ...artiste
} }
}) })
if (active) { if (active) {
@@ -48,8 +49,16 @@ export default function ChecheAwtis() {
} }
}, [loading]) }, [loading])
const sortedOptions = useMemo(() => {
return [...options].sort((a, b) =>
-b.firstLetter.localeCompare(a.firstLetter)
);
}, [options]);
return ( return (
<Container sx={{display: 'flex', justifyContent: 'center', marginBottom: 3}}> <Container
sx={{ display: 'flex', justifyContent: 'center', marginBottom: 3 }}
>
<Autocomplete <Autocomplete
autoHighlight autoHighlight
disableClearable disableClearable
@@ -59,42 +68,40 @@ export default function ChecheAwtis() {
loadingText='Chargement...' loadingText='Chargement...'
noOptionsText='Aucun résultat' noOptionsText='Aucun résultat'
id='cheche-awtis' id='cheche-awtis'
options={options.sort((a, b) => -b.firstLetter.localeCompare(a.firstLetter))} options={sortedOptions}
groupBy={option => option?.firstLetter} groupBy={(option) => option?.firstLetter}
getOptionLabel={option => option?.alias} getOptionLabel={(option) => option?.alias}
renderOption={(props, option) => ( renderOption={(props, option) => {
<li {...props}> const {key, ...rest} = props;
<Avatar style={{marginRight: 8}} alt={option?.alias} src={`${IMAGE_URL}${option?.photo?.data?.attributes?.formats?.thumbnail?.url}`} />
return (
<li key={key} {...rest}>
<Avatar
style={{ marginRight: 8 }}
alt={option?.alias}
src={`${IMAGE_URL}${option?.photo?.formats?.thumbnail?.url}`}
/>
{option?.alias} {option?.alias}
</li> </li>
)} );
sx={{width: 300}} }}
renderInput={params => ( sx={{ width: 300 }}
renderInput={(params) => (
<TextField <TextField
{...params} {...params}
label='Rechercher un artiste' label='Rechercher un artiste'
InputProps={{ slotProps={{
...params.InputProps, ...params.slotProps,
endAdornment: ( htmlInput: { ...params.slotProps.htmlInput },
<>
{loading ? <CircularProgress color='primary' size={20} /> : null}
{params.InputProps.endAdornment}
</>
),
}} }}
/> />
)} )}
onChange={(event, newValue) => { onChange={(event, newValue) => {
router.push(`/awtis/${newValue.slug}`) router.push(`/awtis/${newValue.slug}`);
}}
onOpen={() => {
setOpen(true)
}}
onClose={() => {
setOpen(false)
}} }}
onOpen={() => setOpen(true)}
onClose={() => setOpen(false)}
/> />
</Container> </Container>
) )
} }
+1 -1
View File
@@ -105,7 +105,7 @@ export default function MizikBadjMeni({paroles}) {
<Paper> <Paper>
<ClickAwayListener onClickAway={handleClose}> <ClickAwayListener onClickAway={handleClose}>
<MenuList autoFocusItem={open} id='menu-list-grow' onKeyDown={() => handleListKeyDown()}> <MenuList autoFocusItem={open} id='menu-list-grow' onKeyDown={() => handleListKeyDown()}>
{sortedTeks.map(({id, attributes}) => <MenuItem key={id} onClick={() => handleClick(attributes.slug)}>{attributes.titre}</MenuItem>)} {sortedTeks.map(({id, slug, titre}) => <MenuItem key={id} onClick={() => handleClick(slug)}>{titre}</MenuItem>)}
</MenuList> </MenuList>
</ClickAwayListener> </ClickAwayListener>
</Paper> </Paper>
+3 -3
View File
@@ -13,8 +13,8 @@ import {formatKuveti} from '../../lib/kuveti'
import MizikLyen from './mizik-lyen' import MizikLyen from './mizik-lyen'
function grupPawol(pawol) { function grupPawol(pawol) {
const pawolTrie = pawol.sort((a, b) => a.attributes.titre.localeCompare(b.attributes.titre, 'fr', {sensitivity: 'base'})) const pawolTrie = pawol.sort((a, b) => a.titre.localeCompare(b.titre, 'fr', {sensitivity: 'base'}))
const grupPawol = groupBy(pawol, anPawol => anPawol.attributes.titre[0].toUpperCase()) const grupPawol = groupBy(pawol, anPawol => anPawol.titre[0].toUpperCase())
const grupCounts = Object.values(grupPawol).map(anPawol => anPawol.length) const grupCounts = Object.values(grupPawol).map(anPawol => anPawol.length)
const grup = Object.keys(grupPawol) const grup = Object.keys(grupPawol)
grup.sort((a, b) => a[0].localeCompare(b[0], 'fr', {sensitivity: 'base'})) grup.sort((a, b) => a[0].localeCompare(b[0], 'fr', {sensitivity: 'base'}))
@@ -33,7 +33,7 @@ export default function MizikLis({niAwtis, paroles, meteEsMobilOuve}) {
groupContent={index => <div>{grup[index]}</div>} groupContent={index => <div>{grup[index]}</div>}
itemContent={index => { itemContent={index => {
const anPawol = pawol[index] const anPawol = pawol[index]
const {couverture} = anPawol.attributes const {couverture} = anPawol
const kuvetiFormat = formatKuveti(couverture) const kuvetiFormat = formatKuveti(couverture)
return ( return (
+10 -10
View File
@@ -20,23 +20,23 @@ export default function MizikLyen({niAwtis, anPawol, kuveti, slug, meteEsMobilOu
return ( return (
<Link <Link
passHref passHref
href={`/paroles/${anPawol.attributes.slug}#${anPawol.attributes.slug}`} href={`/paroles/${anPawol.slug}#${anPawol.slug}`}
style={{textDecoration: 'none', width: '100%', display: 'flex', alignItems: 'center'}} style={{textDecoration: 'none', width: '100%', display: 'flex', alignItems: 'center'}}
onClick={() => meteEsMobilOuve(false)} onClick={() => meteEsMobilOuve(false)}
> >
<ListItemButton <ListItemButton
sx={{padding: 0}} sx={{padding: 0}}
id={anPawol.attributes.slug} id={anPawol.slug}
selected={slug === anPawol.attributes.slug} selected={slug === anPawol.slug}
> >
<ListItemAvatar sx={{ml: 2.5}}> <ListItemAvatar sx={{ml: 2.5}}>
<Avatar alt={anPawol.attributes.titre} src={`${apiUrl}${kuveti?.url}`} /> <Avatar alt={anPawol.titre} src={`${apiUrl}${kuveti?.url}`} />
</ListItemAvatar> </ListItemAvatar>
<ListItemText <ListItemText
primary={<Typography sx={{fontWeight: 'bold'}} color='info.main'>{anPawol.attributes.titre}</Typography>} primary={<Typography sx={{fontWeight: 'bold', color: 'info.main'}} >{anPawol.titre}</Typography>}
secondary={niAwtis ? getAlias(anPawol.attributes.artistes, anPawol.attributes.prioriteArtistes) : null} /> secondary={niAwtis ? getAlias(anPawol.artistes, anPawol.prioriteArtistes) : null} />
{anPawol.attributes.creativeCommons && ( {anPawol.creativeCommons && (
<Box marginInline={1}> <Box marginInline={1}>
<Image <Image
width={24} width={24}
@@ -48,14 +48,14 @@ export default function MizikLyen({niAwtis, anPawol, kuveti, slug, meteEsMobilOu
</Box> </Box>
)} )}
{esBrandNew(anPawol.attributes.publishedAt) && ( {esBrandNew(anPawol.publishedAt) && (
<FiberNewOutlinedIcon style={{fontSize: 30, marginRight: 5}} color='primary' /> <FiberNewOutlinedIcon style={{fontSize: 30, marginRight: 5}} color='primary' />
)} )}
{anPawol.attributes.explicitLyrics && ( {anPawol.explicitLyrics && (
<ExplicitIcon style={{marginRight: 5}} color='error' /> <ExplicitIcon style={{marginRight: 5}} color='error' />
)} )}
{anPawol.attributes.okiMizikID && ( {anPawol.okiMizikID && (
<LibraryMusicIcon style={{fontSize: 30, marginRight: 5}} color='primary' /> <LibraryMusicIcon style={{fontSize: 30, marginRight: 5}} color='primary' />
)} )}
</ListItemButton> </ListItemButton>
+2 -2
View File
@@ -3,7 +3,7 @@
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import {useRouter} from 'next/navigation' import {useRouter} from 'next/navigation'
import Pagination from '@mui/material/Pagination' import Pagination from '@mui/material/Pagination'
import Grid from '@mui/material/Grid2' import Grid from '@mui/material/Grid'
export default function Pajinasyon({pajTotal, paj}) { export default function Pajinasyon({pajTotal, paj}) {
const router = useRouter() const router = useRouter()
@@ -14,7 +14,7 @@ export default function Pajinasyon({pajTotal, paj}) {
} }
return ( return (
<Grid container sx={{marginBlock: 3}} justifyContent='center'> <Grid container sx={{marginTop: 10, marginBottom: 3, justifyContent: 'center'}}>
<Pagination size='small' page={paj} count={pajTotal} color='primary' onChange={handleChange} /> <Pagination size='small' page={paj} count={pajTotal} color='primary' onChange={handleChange} />
</Grid> </Grid>
) )
+49 -49
View File
@@ -21,25 +21,25 @@ export default function Cgu() {
Définitions Définitions
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
<strong>Prestations et Services </strong>: <Link href='https://oki.re'><strong>oki.re</strong></Link> met à disposition : <strong>Prestations et Services </strong>: <Link href='https://oki.re'><strong>oki.re</strong></Link> met à disposition :
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
<strong>Contenu </strong>: Ensemble des éléments constituants linformation présente sur le site, notamment textes images vidéos. <strong>Contenu </strong>: Ensemble des éléments constituants linformation présente sur le site, notamment textes images vidéos.
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
<strong>Informations utilisateurs </strong>: Ci après dénommé « Information (s) » <strong>Informations utilisateurs </strong>: Ci après dénommé « Information (s) »
qui correspondent à lensemble des données personnelles susceptibles d’être détenues par qui correspondent à lensemble des données personnelles susceptibles d’être détenues par
<Link href='https://oki.re'> <strong>oki.re</strong></Link> pour la gestion de votre compte, et à des fins danalyses et de statistiques. <Link href='https://oki.re'> <strong>oki.re</strong></Link> pour la gestion de votre compte, et à des fins danalyses et de statistiques.
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
<strong>Utilisateur </strong>: Internaute, utilisant le site susnommé. <strong>Utilisateur </strong>: Internaute, utilisant le site susnommé.
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
<strong>Utilisateur enregistré</strong>: Internaute ayant compte utilisateur, utilisant le site susnommé. <strong>Utilisateur enregistré</strong>: Internaute ayant compte utilisateur, utilisant le site susnommé.
</Typography> </Typography>
@@ -47,7 +47,7 @@ export default function Cgu() {
<strong>Informations personnelles </strong>: « Les informations qui permettent, sous quelque forme que ce soit, directement ou non, <strong>Informations personnelles </strong>: « Les informations qui permettent, sous quelque forme que ce soit, directement ou non,
lidentification des personnes physiques auxquelles elles sappliquent » (article 4 de la loi n° 78-17 du 6 janvier 1978). lidentification des personnes physiques auxquelles elles sappliquent » (article 4 de la loi n° 78-17 du 6 janvier 1978).
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Les termes « données à caractère personnel », « personne concernée », « sous traitant » et « données sensibles » ont le sens défini par le Règlement Les termes « données à caractère personnel », « personne concernée », « sous traitant » et « données sensibles » ont le sens défini par le Règlement
Général sur la Protection des Données (RGPD : n° 2016-679) Général sur la Protection des Données (RGPD : n° 2016-679)
</Typography> </Typography>
@@ -56,18 +56,18 @@ export default function Cgu() {
1. Présentation du site internet 1. Présentation du site internet
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
En vertu de larticle 6 de la loi n° 2004-575 du 21 juin 2004 pour la confiance dans léconomie numérique, il est précisé aux utilisateurs du site internet En vertu de larticle 6 de la loi n° 2004-575 du 21 juin 2004 pour la confiance dans léconomie numérique, il est précisé aux utilisateurs du site internet
<Link href='https://oki.re'> <strong>oki.re</strong></Link> lidentité des différents intervenants dans le cadre de sa réalisation et de son suivi : <Link href='https://oki.re'> <strong>oki.re</strong></Link> lidentité des différents intervenants dans le cadre de sa réalisation et de son suivi :
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
<strong>Propriétaire</strong> : ORGANISATION KA INTERNATIONALE (Association loi 1901) <strong>Propriétaire</strong> : ORGANISATION KA INTERNATIONALE (Association loi 1901)
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
<strong>Responsable publication</strong> : ORGANISATION KA INTERNATIONALE <Link href='mailto:kontak@o-k-i.net'><strong>kontak@o-k-i.net</strong></Link> <strong>Responsable publication</strong> : ORGANISATION KA INTERNATIONALE <Link href='mailto:kontak@o-k-i.net'><strong>kontak@o-k-i.net</strong></Link>
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Le responsable publication est une personne morale Le responsable publication est une personne morale
</Typography> </Typography>
<Typography variant='body1'> <Typography variant='body1'>
@@ -114,7 +114,7 @@ export default function Cgu() {
<strong>Délégué à la protection des données</strong> : ORGANISATION KA INTERNATIONALE <Link href='mailto:kontak@o-k-i.net'><strong>kontak@o-k-i.net</strong></Link> <strong>Délégué à la protection des données</strong> : ORGANISATION KA INTERNATIONALE <Link href='mailto:kontak@o-k-i.net'><strong>kontak@o-k-i.net</strong></Link>
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Ces mentions légales RGPD sont issues du <Link target='_blank' rel='noreferrer' href='https://fr.orson.io/1371/generateur-mentions-legales'>générateur gratuit de mentions légales pour un site internet (orson.io)</Link>. Ces mentions légales RGPD sont issues du <Link target='_blank' rel='noreferrer' href='https://fr.orson.io/1371/generateur-mentions-legales'>générateur gratuit de mentions légales pour un site internet (orson.io)</Link>.
</Typography> </Typography>
@@ -122,13 +122,13 @@ export default function Cgu() {
2. Conditions générales dutilisation du site et des services proposés. 2. Conditions générales dutilisation du site et des services proposés.
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Lutilisation du site <Link href='https://oki.re'><strong>oki.re</strong></Link> implique lacceptation pleine et entière des conditions générales dutilisation ci-après décrites. Lutilisation du site <Link href='https://oki.re'><strong>oki.re</strong></Link> implique lacceptation pleine et entière des conditions générales dutilisation ci-après décrites.
Ces conditions dutilisation sont susceptibles dêtre modifiées ou complétées à tout moment, les utilisateurs du site <Link href='https://oki.re'><strong>oki.re </strong></Link> Ces conditions dutilisation sont susceptibles dêtre modifiées ou complétées à tout moment, les utilisateurs du site <Link href='https://oki.re'><strong>oki.re </strong></Link>
sont donc invités à les consulter de manière régulière. sont donc invités à les consulter de manière régulière.
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Ce site internet est normalement accessible à tout moment aux utilisateurs. Une interruption pour raison de maintenance technique peut être toutefois Ce site internet est normalement accessible à tout moment aux utilisateurs. Une interruption pour raison de maintenance technique peut être toutefois
décidée par <Link href='https://oki.re'><strong>oki.re</strong></Link>, qui sefforcera alors de communiquer préalablement aux utilisateurs les dates et heures de lintervention. décidée par <Link href='https://oki.re'><strong>oki.re</strong></Link>, qui sefforcera alors de communiquer préalablement aux utilisateurs les dates et heures de lintervention.
Le site web <Link href='https://oki.re'><strong>oki.re</strong></Link> est mis à jour régulièrement par <strong>ORGANISATION KA INTERNATIONALE</strong>. De la même façon, les mentions légales peuvent être Le site web <Link href='https://oki.re'><strong>oki.re</strong></Link> est mis à jour régulièrement par <strong>ORGANISATION KA INTERNATIONALE</strong>. De la même façon, les mentions légales peuvent être
@@ -139,13 +139,13 @@ export default function Cgu() {
3. Description des services fournis 3. Description des services fournis
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
<Link href='https://oki.re'><strong>oki.re</strong></Link> sefforce de fournir sur le site, des informations <Link href='https://oki.re'><strong>oki.re</strong></Link> sefforce de fournir sur le site, des informations
aussi précises que possible. Toutefois, il ne pourra être tenu responsable des oublis, des inexactitudes et des carences dans la mise à jour, quelles soient de son fait ou du fait aussi précises que possible. Toutefois, il ne pourra être tenu responsable des oublis, des inexactitudes et des carences dans la mise à jour, quelles soient de son fait ou du fait
des tiers partenaires qui lui fournissent ces informations. des tiers partenaires qui lui fournissent ces informations.
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Toutes les informations indiquées sur le site <Link href='https://oki.re'><strong>oki.re</strong></Link> sont données à titre indicatif, Toutes les informations indiquées sur le site <Link href='https://oki.re'><strong>oki.re</strong></Link> sont données à titre indicatif,
et sont susceptibles dévoluer. Par ailleurs, les renseignements figurant sur le site <Link href='https://oki.re'><strong>oki.re</strong></Link> ne sont pas exhaustifs. et sont susceptibles dévoluer. Par ailleurs, les renseignements figurant sur le site <Link href='https://oki.re'><strong>oki.re</strong></Link> ne sont pas exhaustifs.
Ils sont donnés sous réserve de modifications ayant été apportées depuis leur mise en ligne. Ils sont donnés sous réserve de modifications ayant été apportées depuis leur mise en ligne.
@@ -155,7 +155,7 @@ export default function Cgu() {
4. Limitations contractuelles sur les données techniques 4. Limitations contractuelles sur les données techniques
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Le site utilise la technologie JavaScript. Le site utilise la technologie JavaScript.
Le site Internet ne pourra être tenu responsable de dommages matériels liés à lutilisation du site. De plus, lutilisateur du site sengage à accéder au site en utilisant un matériel récent, Le site Internet ne pourra être tenu responsable de dommages matériels liés à lutilisation du site. De plus, lutilisateur du site sengage à accéder au site en utilisant un matériel récent,
ne contenant pas de virus et avec un navigateur de dernière génération mis-à-jour. ne contenant pas de virus et avec un navigateur de dernière génération mis-à-jour.
@@ -163,14 +163,14 @@ export default function Cgu() {
Règlement Général sur la Protection des Données (RGPD : n° 2016-679). Règlement Général sur la Protection des Données (RGPD : n° 2016-679).
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Lobjectif est dapporter une prestation qui assure le meilleur taux daccessibilité. Lobjectif est dapporter une prestation qui assure le meilleur taux daccessibilité.
Lhébergeur assure la continuité de son service 24 Heures sur 24, tous les jours de lannée. Il se réserve néanmoins la possibilité dinterrompre le service dhébergement Lhébergeur assure la continuité de son service 24 Heures sur 24, tous les jours de lannée. Il se réserve néanmoins la possibilité dinterrompre le service dhébergement
pour les durées les plus courtes possibles notamment à des fins de maintenance, damélioration de ses infrastructures, de défaillance de ses infrastructures ou si les pour les durées les plus courtes possibles notamment à des fins de maintenance, damélioration de ses infrastructures, de défaillance de ses infrastructures ou si les
Prestations et Services génèrent un trafic réputé anormal. Prestations et Services génèrent un trafic réputé anormal.
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
<Link href='https://oki.re'><strong>oki.re</strong></Link> et lhébergeur ne pourront être tenus responsables en cas de dysfonctionnement du réseau Internet, <Link href='https://oki.re'><strong>oki.re</strong></Link> et lhébergeur ne pourront être tenus responsables en cas de dysfonctionnement du réseau Internet,
des lignes téléphoniques ou du matériel informatique et de téléphonie lié notamment à lencombrement du réseau empêchant laccès au serveur. des lignes téléphoniques ou du matériel informatique et de téléphonie lié notamment à lencombrement du réseau empêchant laccès au serveur.
</Typography> </Typography>
@@ -179,12 +179,12 @@ export default function Cgu() {
5. Limitations de responsabilité 5. Limitations de responsabilité
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
<Link href='https://oki.re'><strong>oki.re</strong></Link> agit en tant quéditeur du site. <Link href='https://oki.re'><strong>oki.re</strong></Link> est responsable <Link href='https://oki.re'><strong>oki.re</strong></Link> agit en tant quéditeur du site. <Link href='https://oki.re'><strong>oki.re</strong></Link> est responsable
de la qualité et de la véracité du Contenu quil publie. de la qualité et de la véracité du Contenu quil publie.
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
<Link href='https://oki.re'><strong>oki.re</strong></Link> ne pourra être tenu responsable des dommages directs et indirects causés au matériel de lutilisateur, <Link href='https://oki.re'><strong>oki.re</strong></Link> ne pourra être tenu responsable des dommages directs et indirects causés au matériel de lutilisateur,
lors de laccès au site internet <Link href='https://oki.re'><strong>oki.re</strong></Link>, et résultant soit de lutilisation dun matériel lors de laccès au site internet <Link href='https://oki.re'><strong>oki.re</strong></Link>, et résultant soit de lutilisation dun matériel
ne répondant pas aux spécifications indiquées au point 4, soit de lapparition dun bug ou dune incompatibilité. ne répondant pas aux spécifications indiquées au point 4, soit de lapparition dun bug ou dune incompatibilité.
@@ -198,12 +198,12 @@ export default function Cgu() {
6.1 Responsables de la collecte des données personnelles 6.1 Responsables de la collecte des données personnelles
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Pour les données personnelles collectées dans le cadre de la création du compte personnel de lutilisateur et de sa navigation sur le site Pour les données personnelles collectées dans le cadre de la création du compte personnel de lutilisateur et de sa navigation sur le site
le responsable du traitement des données personnelles est : ORGANISATION KA INTERNATIONALE. <Link href='https://oki.re'><strong>oki.re</strong></Link>. le responsable du traitement des données personnelles est : ORGANISATION KA INTERNATIONALE. <Link href='https://oki.re'><strong>oki.re</strong></Link>.
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
En tant que responsable du traitement des données quil collecte, <Link href='https://oki.re'><strong>oki.re</strong></Link> sengage à respecter le cadre des dispositions légales en vigueur. En tant que responsable du traitement des données quil collecte, <Link href='https://oki.re'><strong>oki.re</strong></Link> sengage à respecter le cadre des dispositions légales en vigueur.
Chaque fois que <Link href='https://oki.re'><strong>oki.re</strong></Link> traite des Données Personnelles, <Link href='https://oki.re'><strong>oki.re</strong></Link> prend toutes les mesures raisonnables Chaque fois que <Link href='https://oki.re'><strong>oki.re</strong></Link> traite des Données Personnelles, <Link href='https://oki.re'><strong>oki.re</strong></Link> prend toutes les mesures raisonnables
pour sassurer de lexactitude et de la pertinence des Données Personnelles au regard des finalités pour lesquelles <Link href='https://oki.re'><strong>oki.re</strong></Link> les traite. pour sassurer de lexactitude et de la pertinence des Données Personnelles au regard des finalités pour lesquelles <Link href='https://oki.re'><strong>oki.re</strong></Link> les traite.
@@ -298,22 +298,22 @@ export default function Cgu() {
</ListItem> </ListItem>
</List> </List>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Dès que <Link href='https://oki.re'><strong>oki.re</strong></Link> a connaissance du décès dun Utilisateur et à défaut dinstructions de sa part, <Link href='https://oki.re'><strong>oki.re</strong></Link> sengage à détruire Dès que <Link href='https://oki.re'><strong>oki.re</strong></Link> a connaissance du décès dun Utilisateur et à défaut dinstructions de sa part, <Link href='https://oki.re'><strong>oki.re</strong></Link> sengage à détruire
ses données, sauf si leur conservation savère nécessaire à des fins probatoires ou pour répondre à une obligation légale. ses données, sauf si leur conservation savère nécessaire à des fins probatoires ou pour répondre à une obligation légale.
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Si lUtilisateur souhaite savoir comment <Link href='https://oki.re'><strong>oki.re</strong></Link> utilise ses Données Personnelles, demander à les rectifier ou soppose à leur traitement, Si lUtilisateur souhaite savoir comment <Link href='https://oki.re'><strong>oki.re</strong></Link> utilise ses Données Personnelles, demander à les rectifier ou soppose à leur traitement,
lUtilisateur peut contacter <Link href='https://oki.re'><strong>oki.re</strong></Link> par courriel à ladresse suivante, <Link href='mailto:kontak@o-k-i.net'><strong>kontak@o-k-i.net</strong></Link> ou via XMPP à <Link href='xmpp:oki@xmpp.cz'><strong>oki@xmpp.cz</strong></Link>. lUtilisateur peut contacter <Link href='https://oki.re'><strong>oki.re</strong></Link> par courriel à ladresse suivante, <Link href='mailto:kontak@o-k-i.net'><strong>kontak@o-k-i.net</strong></Link> ou via XMPP à <Link href='xmpp:oki@xmpp.cz'><strong>oki@xmpp.cz</strong></Link>.
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Dans ce cas, lUtilisateur doit indiquer les Données Personnelles quil souhaiterait que <Link href='https://oki.re'><strong>oki.re</strong></Link> corrige, Dans ce cas, lUtilisateur doit indiquer les Données Personnelles quil souhaiterait que <Link href='https://oki.re'><strong>oki.re</strong></Link> corrige,
mette à jour ou supprime, en sidentifiant précisément avec une copie dune pièce didentité (carte didentité ou passeport). mette à jour ou supprime, en sidentifiant précisément avec une copie dune pièce didentité (carte didentité ou passeport).
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Les demandes de suppression de Données Personnelles seront soumises aux obligations qui sont imposées à <Link href='https://oki.re'><strong>oki.re</strong></Link> par la loi, Les demandes de suppression de Données Personnelles seront soumises aux obligations qui sont imposées à <Link href='https://oki.re'><strong>oki.re</strong></Link> par la loi,
notamment en matière de conservation ou darchivage des documents. Enfin, les Utilisateurs de <Link href='https://oki.re'><strong>oki.re</strong></Link> peuvent déposer une réclamation notamment en matière de conservation ou darchivage des documents. Enfin, les Utilisateurs de <Link href='https://oki.re'><strong>oki.re</strong></Link> peuvent déposer une réclamation
auprès des autorités de contrôle, et notamment de la CNIL (https://www.cnil.fr/fr/plaintes). auprès des autorités de contrôle, et notamment de la CNIL (https://www.cnil.fr/fr/plaintes).
@@ -323,14 +323,14 @@ export default function Cgu() {
6.4 Non-communication des données personnelles 6.4 Non-communication des données personnelles
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
<Link href='https://oki.re'><strong>oki.re</strong></Link> sinterdit de traiter, héberger ou transférer les Informations collectées sur ses utilisateurs vers un pays situé en dehors de <Link href='https://oki.re'><strong>oki.re</strong></Link> sinterdit de traiter, héberger ou transférer les Informations collectées sur ses utilisateurs vers un pays situé en dehors de
lUnion européenne ou reconnu comme « non adéquat » par la Commission européenne sans en informer préalablement lutilisateur. Pour autant, <Link href='https://oki.re'><strong>oki.re</strong></Link> reste lUnion européenne ou reconnu comme « non adéquat » par la Commission européenne sans en informer préalablement lutilisateur. Pour autant, <Link href='https://oki.re'><strong>oki.re</strong></Link> reste
libre du choix de ses sous-traitants techniques et commerciaux à la condition quil présentent les garanties suffisantes au regard des exigences du Règlement Général sur la Protection des libre du choix de ses sous-traitants techniques et commerciaux à la condition quil présentent les garanties suffisantes au regard des exigences du Règlement Général sur la Protection des
Données (RGPD : n° 2016-679). Données (RGPD : n° 2016-679).
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
<Link href='https://oki.re'><strong>oki.re</strong></Link> sengage à prendre toutes les précautions nécessaires afin de préserver la sécurité des Informations et notamment quelles ne soient pas communiquées <Link href='https://oki.re'><strong>oki.re</strong></Link> sengage à prendre toutes les précautions nécessaires afin de préserver la sécurité des Informations et notamment quelles ne soient pas communiquées
à des personnes non autorisées. Cependant, si un incident impactant lintégrité ou la confidentialité des Informations de lutilisateur est portée à des personnes non autorisées. Cependant, si un incident impactant lintégrité ou la confidentialité des Informations de lutilisateur est portée
à la connaissance de <Link href='https://oki.re'><strong>oki.re</strong></Link>, celle-ci devra dans les meilleurs délais informer lutilisateur à la connaissance de <Link href='https://oki.re'><strong>oki.re</strong></Link>, celle-ci devra dans les meilleurs délais informer lutilisateur
@@ -341,7 +341,7 @@ export default function Cgu() {
6.5 Inscription et connexion 6.5 Inscription et connexion
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Les utilisateurs peuvent sinscrire sur <Link href='https://oki.re'><strong>oki.re</strong></Link> en renseignant leur adresse e-mail, un nom dutilisateur ainsi quun mot de passe. Les utilisateurs peuvent sinscrire sur <Link href='https://oki.re'><strong>oki.re</strong></Link> en renseignant leur adresse e-mail, un nom dutilisateur ainsi quun mot de passe.
À la suite de linscription, un lien de vérification est envoyé à ladresse utilisée. Ce lien permet dactiver le compte. Sans cette activation, lutilisateur naura pas la possibilité de se connecter au site. À la suite de linscription, un lien de vérification est envoyé à ladresse utilisée. Ce lien permet dactiver le compte. Sans cette activation, lutilisateur naura pas la possibilité de se connecter au site.
Si un utilisateur na pas reçu le lien dactivation, il a la possibilité de demander son renvoi. Si un utilisateur na pas reçu le lien dactivation, il a la possibilité de demander son renvoi.
@@ -358,7 +358,7 @@ export default function Cgu() {
6.6 Proposition de paroles 6.6 Proposition de paroles
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Les utilisateurs connectés ont la possibilité de proposer des paroles depuis un espace dédié. Les utilisateurs connectés ont la possibilité de proposer des paroles depuis un espace dédié.
Il se trouve à ladresse <Link href='https://oki.re/pwopose'><strong>oki.re/pwopose</strong></Link>. Il se trouve à ladresse <Link href='https://oki.re/pwopose'><strong>oki.re/pwopose</strong></Link>.
Les textes soumis ne sont pas directement publiés sur le site. Ils doivent être approuvé par léquipe de vérification. Les textes soumis ne sont pas directement publiés sur le site. Ils doivent être approuvé par léquipe de vérification.
@@ -369,7 +369,7 @@ export default function Cgu() {
7. Notification dincident 7. Notification dincident
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Quels que soient les efforts fournis, aucune méthode de transmission sur Internet et aucune méthode de stockage électronique nest complètement sûre. Quels que soient les efforts fournis, aucune méthode de transmission sur Internet et aucune méthode de stockage électronique nest complètement sûre.
Nous ne pouvons en conséquence pas garantir une sécurité absolue. Nous ne pouvons en conséquence pas garantir une sécurité absolue.
Si nous prenions connaissance dune brèche de la sécurité, nous avertirions les utilisateurs concernés afin quils puissent prendre les mesures appropriées. Si nous prenions connaissance dune brèche de la sécurité, nous avertirions les utilisateurs concernés afin quils puissent prendre les mesures appropriées.
@@ -378,7 +378,7 @@ export default function Cgu() {
obligations réglementaires en matière de reporting. obligations réglementaires en matière de reporting.
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Aucune information personnelle de lutilisateur du site <Link href='https://oki.re'><strong>oki.re</strong></Link> nest publiée à linsu de lutilisateur, échangée, transférée, Aucune information personnelle de lutilisateur du site <Link href='https://oki.re'><strong>oki.re</strong></Link> nest publiée à linsu de lutilisateur, échangée, transférée,
cédée ou vendue sur un support quelconque à des tiers. Seule lhypothèse du rachat de <Link href='https://oki.re'><strong>oki.re</strong></Link> et de ses droits permettrait cédée ou vendue sur un support quelconque à des tiers. Seule lhypothèse du rachat de <Link href='https://oki.re'><strong>oki.re</strong></Link> et de ses droits permettrait
la transmission des dites informations à léventuecodel acquéreur qui serait à son tour tenu de la même obligation de conservation et de modification des données vis à vis de la transmission des dites informations à léventuecodel acquéreur qui serait à son tour tenu de la même obligation de conservation et de modification des données vis à vis de
@@ -389,12 +389,12 @@ export default function Cgu() {
Sécurité Sécurité
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Pour assurer la sécurité et la confidentialité des Données Personnelles et des Données Personnelles de Santé, <Link href='https://oki.re'><strong>oki.re</strong></Link> utilise des réseaux protégés Pour assurer la sécurité et la confidentialité des Données Personnelles et des Données Personnelles de Santé, <Link href='https://oki.re'><strong>oki.re</strong></Link> utilise des réseaux protégés
par des dispositifs standards tels que par pare-feu, la pseudonymisation, lencryption et mot de passe. par des dispositifs standards tels que par pare-feu, la pseudonymisation, lencryption et mot de passe.
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Lors du traitement des Données Personnelles, <Link href='https://oki.re'><strong>oki.re</strong></Link> prend toutes les mesures raisonnables visant à les protéger contre toute perte, Lors du traitement des Données Personnelles, <Link href='https://oki.re'><strong>oki.re</strong></Link> prend toutes les mesures raisonnables visant à les protéger contre toute perte,
utilisation détournée, accès non autorisé, divulgation, altération ou destruction. utilisation détournée, accès non autorisé, divulgation, altération ou destruction.
</Typography> </Typography>
@@ -403,7 +403,7 @@ export default function Cgu() {
8. Liens hypertextes « cookies » et balises (tags) internet 8. Liens hypertextes « cookies » et balises (tags) internet
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Le site <Link href='https://oki.re'><strong>oki.re</strong></Link> contient un certain nombre de liens hypertextes vers dautres sites, Le site <Link href='https://oki.re'><strong>oki.re</strong></Link> contient un certain nombre de liens hypertextes vers dautres sites,
mis en place avec lautorisation de <Link href='https://oki.re'><strong>oki.re</strong></Link>. Cependant, <Link href='https://oki.re'><strong>oki.re</strong></Link> na pas la possibilité de vérifier mis en place avec lautorisation de <Link href='https://oki.re'><strong>oki.re</strong></Link>. Cependant, <Link href='https://oki.re'><strong>oki.re</strong></Link> na pas la possibilité de vérifier
le contenu des sites ainsi visités, et nassumera en conséquence aucune responsabilité de ce fait. le contenu des sites ainsi visités, et nassumera en conséquence aucune responsabilité de ce fait.
@@ -416,18 +416,18 @@ export default function Cgu() {
8.1 « COOKIES » 8.1 « COOKIES »
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Un « cookie » est un petit fichier dinformation envoyé sur le navigateur de lUtilisateur et enregistré au sein du terminal de lUtilisateur (ex : ordinateur, smartphone), Un « cookie » est un petit fichier dinformation envoyé sur le navigateur de lUtilisateur et enregistré au sein du terminal de lUtilisateur (ex : ordinateur, smartphone),
(ci-après « Cookies »). Ce fichier comprend des informations telles que le nom de domaine de lUtilisateur, le fournisseur daccès Internet de lUtilisateur, (ci-après « Cookies »). Ce fichier comprend des informations telles que le nom de domaine de lUtilisateur, le fournisseur daccès Internet de lUtilisateur,
le système dexploitation de lUtilisateur, ainsi que la date et lheure daccès. Les Cookies ne risquent en aucun cas dendommager le terminal de lUtilisateur. le système dexploitation de lUtilisateur, ainsi que la date et lheure daccès. Les Cookies ne risquent en aucun cas dendommager le terminal de lUtilisateur.
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
<Link href='https://oki.re'><strong>oki.re</strong></Link> est susceptible de traiter les informations de lUtilisateur concernant sa visite du Site, telles que les pages consultées, <Link href='https://oki.re'><strong>oki.re</strong></Link> est susceptible de traiter les informations de lUtilisateur concernant sa visite du Site, telles que les pages consultées,
les recherches effectuées. Ces informations permettent à <Link href='https://oki.re'><strong>oki.re</strong></Link> daméliorer le contenu du Site, de la navigation de lUtilisateur. les recherches effectuées. Ces informations permettent à <Link href='https://oki.re'><strong>oki.re</strong></Link> daméliorer le contenu du Site, de la navigation de lUtilisateur.
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Les Cookies facilitant la navigation et/ou la fourniture des services proposés par le Site, lUtilisateur peut configurer son navigateur pour quil lui permette de décider sil souhaite Les Cookies facilitant la navigation et/ou la fourniture des services proposés par le Site, lUtilisateur peut configurer son navigateur pour quil lui permette de décider sil souhaite
ou non les accepter de manière à ce que des Cookies soient enregistrés dans le terminal ou, au contraire, quils soient rejetés, soit systématiquement, soit selon leur émetteur. ou non les accepter de manière à ce que des Cookies soient enregistrés dans le terminal ou, au contraire, quils soient rejetés, soit systématiquement, soit selon leur émetteur.
LUtilisateur peut également configurer son logiciel de navigation de manière à ce que lacceptation ou le refus des Cookies lui soient proposés ponctuellement, avant quun Cookie soit LUtilisateur peut également configurer son logiciel de navigation de manière à ce que lacceptation ou le refus des Cookies lui soient proposés ponctuellement, avant quun Cookie soit
@@ -435,13 +435,13 @@ export default function Cgu() {
de navigation ne soient pas toutes disponibles. de navigation ne soient pas toutes disponibles.
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Si lUtilisateur refuse lenregistrement de Cookies dans son terminal ou son navigateur, ou si lUtilisateur supprime ceux qui y sont enregistrés, Si lUtilisateur refuse lenregistrement de Cookies dans son terminal ou son navigateur, ou si lUtilisateur supprime ceux qui y sont enregistrés,
lUtilisateur est informé que sa navigation et son expérience sur le Site peuvent être limitées. Cela pourrait également être le cas lorsque <Link href='https://oki.re'><strong>oki.re</strong></Link> ne peut pas reconnaître, lUtilisateur est informé que sa navigation et son expérience sur le Site peuvent être limitées. Cela pourrait également être le cas lorsque <Link href='https://oki.re'><strong>oki.re</strong></Link> ne peut pas reconnaître,
à des fins de compatibilité technique, le type de navigateur utilisé par le terminal, les paramètres de langue et daffichage ou le pays depuis lequel le terminal semble connecté à Internet. à des fins de compatibilité technique, le type de navigateur utilisé par le terminal, les paramètres de langue et daffichage ou le pays depuis lequel le terminal semble connecté à Internet.
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Le cas échéant, <Link href='https://oki.re'><strong>oki.re</strong></Link> décline toute responsabilité pour les conséquences liées au fonctionnement dégradé du Site Le cas échéant, <Link href='https://oki.re'><strong>oki.re</strong></Link> décline toute responsabilité pour les conséquences liées au fonctionnement dégradé du Site
et des services éventuellement proposés par <Link href='https://oki.re'><strong>oki.re</strong></Link>, résultant du refus de Cookies par lUtilisateur de limpossibilité et des services éventuellement proposés par <Link href='https://oki.re'><strong>oki.re</strong></Link>, résultant du refus de Cookies par lUtilisateur de limpossibilité
pour <Link href='https://oki.re'><strong>oki.re</strong></Link> denregistrer ou de consulter les Cookies nécessaires à leur fonctionnement du fait du choix de lUtilisateur. pour <Link href='https://oki.re'><strong>oki.re</strong></Link> denregistrer ou de consulter les Cookies nécessaires à leur fonctionnement du fait du choix de lUtilisateur.
@@ -449,13 +449,13 @@ export default function Cgu() {
qui permettra de savoir de quelle manière lUtilisateur peut modifier ses souhaits en matière de Cookies. qui permettra de savoir de quelle manière lUtilisateur peut modifier ses souhaits en matière de Cookies.
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Enfin, en cliquant sur licône dédiée au réseau social Twitter, figurant sur le Site de <Link href='https://oki.re'><strong>oki.re</strong></Link> ou dans son application mobile Enfin, en cliquant sur licône dédiée au réseau social Twitter, figurant sur le Site de <Link href='https://oki.re'><strong>oki.re</strong></Link> ou dans son application mobile
et si lUtilisateur a accepté le dépôt de cookies en poursuivant sa navigation sur le Site Internet ou lapplication mobile de <Link href='https://oki.re'><strong>oki.re</strong></Link>, Twitter, et si lUtilisateur a accepté le dépôt de cookies en poursuivant sa navigation sur le Site Internet ou lapplication mobile de <Link href='https://oki.re'><strong>oki.re</strong></Link>, Twitter,
peut également déposer des cookies sur vos terminaux (ordinateur, tablette, téléphone portable). peut également déposer des cookies sur vos terminaux (ordinateur, tablette, téléphone portable).
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Ces types de cookies ne sont déposés sur vos terminaux quà condition que vous y consentiez, en continuant votre navigation sur le Site Internet ou Ces types de cookies ne sont déposés sur vos terminaux quà condition que vous y consentiez, en continuant votre navigation sur le Site Internet ou
lapplication mobile de <Link href='https://oki.re'><strong>oki.re</strong></Link>. À tout moment, lUtilisateur peut néanmoins revenir sur son consentement à ce lapplication mobile de <Link href='https://oki.re'><strong>oki.re</strong></Link>. À tout moment, lUtilisateur peut néanmoins revenir sur son consentement à ce
que <Link href='https://oki.re'><strong>oki.re</strong></Link> dépose ce type de cookies. que <Link href='https://oki.re'><strong>oki.re</strong></Link> dépose ce type de cookies.
@@ -465,7 +465,7 @@ export default function Cgu() {
9. Les dons 9. Les dons
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Le site dispose dune page permettant de faire des dons à « ORGANISATION KA INTERNATIONALE » de manière sécurisée. Le site dispose dune page permettant de faire des dons à « ORGANISATION KA INTERNATIONALE » de manière sécurisée.
Pour se faire, il faut se rendre sur la page « <Link href='/soutyen'><strong>soutyen</strong></Link> ». Lutilisateur a 2 onglets disponibles : Pour se faire, il faut se rendre sur la page « <Link href='/soutyen'><strong>soutyen</strong></Link> ». Lutilisateur a 2 onglets disponibles :
</Typography> </Typography>
@@ -493,11 +493,11 @@ export default function Cgu() {
9.1 LIBERAPAY / PAYPAL 9.1 LIBERAPAY / PAYPAL
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
La plateforme <Link target='_blank' rel='noreferrer' href='https://liberapay.com/OKi/donate'><strong>Liberapay</strong></Link> est mise à disposition. Elle permet non seulement de personnaliser le montant, mais aussi la récurrence des dons. Cest à dire quavec cet outil, lutilisateur peut effectuer des dons hebdomadaires, mensuels ou annuels. La plateforme <Link target='_blank' rel='noreferrer' href='https://liberapay.com/OKi/donate'><strong>Liberapay</strong></Link> est mise à disposition. Elle permet non seulement de personnaliser le montant, mais aussi la récurrence des dons. Cest à dire quavec cet outil, lutilisateur peut effectuer des dons hebdomadaires, mensuels ou annuels.
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Lutilisateur peut faire un don en passant par la plateforme <Link target='_blank' rel='noreferrer' href='https://www.paypal.com/donate/?hosted_button_id=5Q3KPR79CAZVW'><strong>PayPal</strong></Link>. En cliquant sur le bouton prévu à cet effet, il est redirigé vers la page de don associée à ORGANISATION KA INTERNATIONALE. Il peut ensuite choisir un montant et valider le don en utilisant son compte <Link target='_blank' rel='noreferrer' href='https://www.paypal.com/donate/?hosted_button_id=5Q3KPR79CAZVW'><strong>PayPal</strong></Link> ou une carte bancaire sil nest pas enregistré. Lutilisateur peut faire un don en passant par la plateforme <Link target='_blank' rel='noreferrer' href='https://www.paypal.com/donate/?hosted_button_id=5Q3KPR79CAZVW'><strong>PayPal</strong></Link>. En cliquant sur le bouton prévu à cet effet, il est redirigé vers la page de don associée à ORGANISATION KA INTERNATIONALE. Il peut ensuite choisir un montant et valider le don en utilisant son compte <Link target='_blank' rel='noreferrer' href='https://www.paypal.com/donate/?hosted_button_id=5Q3KPR79CAZVW'><strong>PayPal</strong></Link> ou une carte bancaire sil nest pas enregistré.
</Typography> </Typography>
@@ -505,7 +505,7 @@ export default function Cgu() {
9.2 CARTE BANCAIRE 9.2 CARTE BANCAIRE
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
En cliquant sur le bouton « CARTE BANCAIRE », lutilisateur se voit proposer plusieurs choix. Parmi ces derniers, deux options sont possibles : En cliquant sur le bouton « CARTE BANCAIRE », lutilisateur se voit proposer plusieurs choix. Parmi ces derniers, deux options sont possibles :
<List> <List>
<ListItem> <ListItem>
@@ -527,7 +527,7 @@ export default function Cgu() {
</List> </List>
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Les dons peuvent donc être fait une seule fois ou de manière récurrente. Les dons peuvent donc être fait une seule fois ou de manière récurrente.
Quelque soit le choix, lutilisateur est redirigé vers le sous-domaine don.o-k-i.net suivi de lID du montant choisit. Cette URL est gérée par la plateforme de paiement sécurisée <Link href='https://stripe.com/' target='_blank' rel='noopener noreferrer'> <strong>Stripe</strong></Link>. Quelque soit le choix, lutilisateur est redirigé vers le sous-domaine don.o-k-i.net suivi de lID du montant choisit. Cette URL est gérée par la plateforme de paiement sécurisée <Link href='https://stripe.com/' target='_blank' rel='noopener noreferrer'> <strong>Stripe</strong></Link>.
@@ -538,7 +538,7 @@ export default function Cgu() {
10. Propriété intellectuelle et licence 10. Propriété intellectuelle et licence
</Typography> </Typography>
<Typography paragraph gutterBottom variant='body1'> <Typography paragraph='true' gutterBottom variant='body1'>
Le site internet <Link href='https://oki.re'><strong>oki.re</strong></Link> et les éléments qui y sont accessibles Le site internet <Link href='https://oki.re'><strong>oki.re</strong></Link> et les éléments qui y sont accessibles
(textes, images, graphismes, logos, vidéos, icônes, sons, etc.) sont, sauf mention contraire, (textes, images, graphismes, logos, vidéos, icônes, sons, etc.) sont, sauf mention contraire,
mis à disposition sous la licence <Link href='https://www.gnu.org/licenses/agpl-3.0.html' target='_blank' rel='noopener noreferrer'> <strong>GNU Affero General Public License Version 3 (AGPL-3.0)</strong></Link>. Cette licence garantit aux utilisateurs les libertés suivantes : mis à disposition sous la licence <Link href='https://www.gnu.org/licenses/agpl-3.0.html' target='_blank' rel='noopener noreferrer'> <strong>GNU Affero General Public License Version 3 (AGPL-3.0)</strong></Link>. Cette licence garantit aux utilisateurs les libertés suivantes :
@@ -587,7 +587,7 @@ export default function Cgu() {
11. Droit applicable et attribution de juridiction 11. Droit applicable et attribution de juridiction
</Typography> </Typography>
<Typography paragraph variant='body1'> <Typography paragraph='true' variant='body1'>
Tout litige en relation avec lutilisation du site <Link href='https://oki.re'><strong>oki.re</strong></Link> est soumis au droit français. Tout litige en relation avec lutilisation du site <Link href='https://oki.re'><strong>oki.re</strong></Link> est soumis au droit français.
En dehors des cas la loi ne le permet pas, il est fait attribution exclusive de juridiction aux tribunaux compétents. En dehors des cas la loi ne le permet pas, il est fait attribution exclusive de juridiction aux tribunaux compétents.
</Typography> </Typography>
+11 -11
View File
@@ -50,8 +50,8 @@ export default function FilesList({files}) {
const theme = useTheme() const theme = useTheme()
const {mode} = useColorScheme() const {mode} = useColorScheme()
const musicFiles = files.filter(file => file.attributes.mime.startsWith('audio')) const musicFiles = files.filter(file => file.mime.startsWith('audio'))
const pdfFiles = files.filter(file => file.attributes.mime === 'application/pdf') const pdfFiles = files.filter(file => file.mime === 'application/pdf')
const sortedMusicFiles = musicFiles.sort((a, b) => { const sortedMusicFiles = musicFiles.sort((a, b) => {
const extensionOrder = { const extensionOrder = {
@@ -60,7 +60,7 @@ export default function FilesList({files}) {
'.aac': 2, '.aac': 2,
'.mp3': 3 '.mp3': 3
} }
return extensionOrder[a.attributes.ext.toLowerCase()] - extensionOrder[b.attributes.ext.toLowerCase()] return extensionOrder[a.ext.toLowerCase()] - extensionOrder[b.ext.toLowerCase()]
}) })
const handleClick = (e, url, fileName) => { const handleClick = (e, url, fileName) => {
@@ -170,7 +170,7 @@ export default function FilesList({files}) {
{sortedMusicFiles.map(file => ( {sortedMusicFiles.map(file => (
<StyledTableRow key={file.id}> <StyledTableRow key={file.id}>
<StyledTableCell> <StyledTableCell>
{getQuality(file.attributes.ext.toLowerCase(), file?.attributes?.caption?.toUpperCase())} {getQuality(file.ext.toLowerCase(), file?.caption?.toUpperCase())}
</StyledTableCell> </StyledTableCell>
<StyledTableCell align='left'> <StyledTableCell align='left'>
<Link <Link
@@ -178,11 +178,11 @@ export default function FilesList({files}) {
underline='hover' underline='hover'
sx={{fontWeight: 'bold'}} sx={{fontWeight: 'bold'}}
aria-label='download' aria-label='download'
onClick={e => handleClick(e, `${apiUrl}${file.attributes.url}`, file.attributes.name)} onClick={e => handleClick(e, `${apiUrl}${file.url}`, file.name)}
> >
{file.attributes.name} {file.name}
</Link> </Link>
<small style={{marginLeft: 3}}>({formatSize(file.attributes.size)})</small> <small style={{marginLeft: 3}}>({formatSize(file.size)})</small>
</StyledTableCell> </StyledTableCell>
</StyledTableRow> </StyledTableRow>
))} ))}
@@ -217,7 +217,7 @@ export default function FilesList({files}) {
<StyledTableRow key={file.id}> <StyledTableRow key={file.id}>
<StyledTableCell> <StyledTableCell>
<strong> <strong>
{file.attributes.caption} {file.caption}
</strong> </strong>
</StyledTableCell> </StyledTableCell>
<StyledTableCell align='left'> <StyledTableCell align='left'>
@@ -226,11 +226,11 @@ export default function FilesList({files}) {
underline='hover' underline='hover'
sx={{fontWeight: 'bold'}} sx={{fontWeight: 'bold'}}
aria-label='download' aria-label='download'
onClick={e => handleClick(e, `${apiUrl}${file.attributes.url}`, file.attributes.name)} onClick={e => handleClick(e, `${apiUrl}${file.url}`, file.name)}
> >
{file.attributes.name} {file.name}
</Link> </Link>
<small style={{marginLeft: 3}}>({formatSize(file.attributes.size)})</small> <small style={{marginLeft: 3}}>({formatSize(file.size)})</small>
</StyledTableCell> </StyledTableCell>
</StyledTableRow> </StyledTableRow>
))} ))}
+4 -4
View File
@@ -38,20 +38,20 @@ const StyledList = styled(List)((
export default function KomanteList({commentaires}) { export default function KomanteList({commentaires}) {
return ( return (
<StyledList className={classes.root}> <StyledList className={classes.root}>
{commentaires.map(({id, attributes}) => ( {commentaires.map(({id, user, contenu, datePublication}) => (
<div key={id}> <div key={id}>
<ListItemText <ListItemText
primary={ primary={
<Typography gutterBottom style={{textDecoration: 'underline'}} variant='body1'> <Typography gutterBottom style={{textDecoration: 'underline'}} variant='body1'>
<small>{attributes.user.data.attributes.username}</small> <small>{user.username}</small>
</Typography> </Typography>
} }
/> />
<ListItemText <ListItemText
primary={formatJsonString(attributes.contenu)} primary={formatJsonString(contenu)}
secondary={ secondary={
<Typography gutterBottom style={{marginBlock: 5, fontStyle: 'italic'}} variant='caption' display='block'> <Typography gutterBottom style={{marginBlock: 5, fontStyle: 'italic'}} variant='caption' display='block'>
{format(new Date(attributes.datePublication), 'Pp', {locale: fr})} {format(new Date(datePublication), 'Pp', {locale: fr})}
</Typography> </Typography>
} }
/> />
+2 -1
View File
@@ -106,7 +106,7 @@ 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'>
<Tabs {selectedTab !== undefined && <Tabs
allowScrollButtonsMobile allowScrollButtonsMobile
scrollButtons scrollButtons
centered={Boolean(!isMobile)} centered={Boolean(!isMobile)}
@@ -128,6 +128,7 @@ export default function Navigasyon() {
<Tab icon={<RecordVoiceOverIcon />} aria-label='Artistes' {...a11yProps(3)} /> <Tab icon={<RecordVoiceOverIcon />} aria-label='Artistes' {...a11yProps(3)} />
<Tab icon={<EditNoteIcon />} aria-label='Proposer des paroles' {...a11yProps(4)} /> <Tab icon={<EditNoteIcon />} aria-label='Proposer des paroles' {...a11yProps(4)} />
</Tabs> </Tabs>
}
</AppBar> </AppBar>
<TabPanel value={value} index={0} /> <TabPanel value={value} index={0} />
<TabPanel value={value} index={1} /> <TabPanel value={value} index={1} />
+1 -1
View File
@@ -4,7 +4,7 @@ import Card from '@mui/material/Card'
import CardContent from '@mui/material/CardContent' import CardContent from '@mui/material/CardContent'
import CardActionArea from '@mui/material/CardActionArea' import CardActionArea from '@mui/material/CardActionArea'
import Divider from '@mui/material/Divider' import Divider from '@mui/material/Divider'
import Grid from '@mui/material/Grid2' import Grid from '@mui/material/Grid'
import Typography from '@mui/material/Typography' import Typography from '@mui/material/Typography'
import {CardMedia} from '@mui/material' import {CardMedia} from '@mui/material'
+5 -5
View File
@@ -15,7 +15,7 @@ import Snackbar from '@mui/material/Snackbar'
import Tab from '@mui/material/Tab' import Tab from '@mui/material/Tab'
import Tabs from '@mui/material/Tabs' import Tabs from '@mui/material/Tabs'
import Typography from '@mui/material/Typography' import Typography from '@mui/material/Typography'
import Grid from '@mui/material/Grid2' import Grid from '@mui/material/Grid'
import Visibility from '@mui/icons-material/Visibility' import Visibility from '@mui/icons-material/Visibility'
import VisibilityOff from '@mui/icons-material/VisibilityOff' import VisibilityOff from '@mui/icons-material/VisibilityOff'
import MuiAlert from '@mui/material/Alert' import MuiAlert from '@mui/material/Alert'
@@ -241,7 +241,7 @@ function Koneksyon({chimen}) {
} }
return ( return (
<Container sx={{marginTop: 2}} maxWidth='sm'> <Container sx={{marginTop: 6}} maxWidth='sm'>
<Box sx={{width: '100%'}}> <Box sx={{width: '100%'}}>
<Tabs centered value={value} aria-label='basic tabs example' onChange={handleChange}> <Tabs centered value={value} aria-label='basic tabs example' onChange={handleChange}>
@@ -251,10 +251,10 @@ function Koneksyon({chimen}) {
<TabPanel value={value} index={0}> <TabPanel value={value} index={0}>
<Box sx={{textAlign: 'center', marginBottom: 3}}> <Box sx={{textAlign: 'center', marginBottom: 3}}>
<Typography gutterBottom textAlign='center'>Connectez-vous avec</Typography> <Typography gutterBottom textalign='center'>Connectez-vous avec</Typography>
<Grid container alignItems='center' justifyContent='center' columnSpacing={{xs: 1, sm: 2, md: 3}}> <Grid sx={{justifyContent: 'center'}} container columnSpacing={{xs: 1, sm: 2, md: 3}}>
{PROVIDERS.map(({id, title, width, height}) => ( {PROVIDERS.map(({id, title, width, height}) => (
<Grid key={id} marginTop={1}> <Grid sx={{marginTop: 1}} key={id}>
<LoginProvider id={id} title={title} width={width} height={height} callbackUrl={`${siteUrl}${chimen}`} /> <LoginProvider id={id} title={title} width={width} height={height} callbackUrl={`${siteUrl}${chimen}`} />
</Grid> </Grid>
))} ))}
+2 -2
View File
@@ -8,7 +8,7 @@ import Button from '@mui/material/Button'
import Container from '@mui/material/Container' import Container from '@mui/material/Container'
import FormControl from '@mui/material/FormControl' import FormControl from '@mui/material/FormControl'
import FormHelperText from '@mui/material/FormHelperText' import FormHelperText from '@mui/material/FormHelperText'
import Grid from '@mui/material/Grid2' import Grid from '@mui/material/Grid'
import IconButton from '@mui/material/IconButton' import IconButton from '@mui/material/IconButton'
import InputAdornment from '@mui/material/InputAdornment' import InputAdornment from '@mui/material/InputAdornment'
import InputLabel from '@mui/material/InputLabel' import InputLabel from '@mui/material/InputLabel'
@@ -191,7 +191,7 @@ function EkriTeks({canAutoTranslate, selectedTeks, setSelectedTeks}) {
username: user.username, username: user.username,
email: user.email email: user.email
}, },
artistes: [artiste.data.id], artistes: [artiste.id],
traductionAuto: tradiksyonOtomatik traductionAuto: tradiksyonOtomatik
} }
}, { }, {
+1 -1
View File
@@ -6,7 +6,7 @@ import Button from '@mui/material/Button'
import {Paypal, Liberapay} from '@icons-pack/react-simple-icons' import {Paypal, Liberapay} from '@icons-pack/react-simple-icons'
import Grid from '@mui/material/Grid2' import Grid from '@mui/material/Grid'
import CardMethod from './card-method' import CardMethod from './card-method'
const PAYPAL_ID = process.env.NEXT_PUBLIC_PAYPAL_DONATE_ID const PAYPAL_ID = process.env.NEXT_PUBLIC_PAYPAL_DONATE_ID
+6 -6
View File
@@ -13,17 +13,17 @@ export default function Presantasyon() {
<> <>
<CGUDialog open={open} setOpen={setOpen} /> <CGUDialog open={open} setOpen={setOpen} />
<Paper sx={{padding: 3, textAlign: 'justify', marginTop: 5}}> <Paper sx={{padding: 3, textAlign: 'justify', marginTop: 5}}>
<Typography paragraph variant='subtitle1' component='div'> <Typography paragraph='true' variant='subtitle1' component='div'>
Tous les services que nous proposons sont <strong>gratuits</strong> et ne contiennent <strong>aucune publicité</strong>. Les réseaux que nous utilisons sont hébergés sur <strong>nos serveurs</strong>. <br /> Tous les services que nous proposons sont <strong>gratuits</strong> et ne contiennent <strong>aucune publicité</strong>. Les réseaux que nous utilisons sont hébergés sur <strong>nos serveurs</strong>. <br />
Tout ceci est possible grâce aux <strong>dons</strong> Tout ceci est possible grâce aux <strong>dons</strong>
</Typography> </Typography>
<Typography paragraph variant='subtitle1' component='div'> <Typography paragraph='true' variant='subtitle1' component='div'>
<strong>Toute contribution, aussi modeste soit-elle, nous permet daugmenter nos capacités</strong>. <strong>Toute contribution, aussi modeste soit-elle, nous permet daugmenter nos capacités</strong>.
</Typography> </Typography>
<Typography paragraph variant='subtitle1' component='div'> <Typography paragraph='true' variant='subtitle1' component='div'>
Concernant les dons, ils peuvent s&apos;effectuer via <Link underline='hover' href='https://liberapay.com/OKi/donate' target='_blank' rel='noreferrer'><strong>Liberapay</strong></Link>, <Link underline='hover' href='https://www.paypal.com/donate/?hosted_button_id=5Q3KPR79CAZVW' target='_blank' rel='noreferrer'><strong>PayPal</strong></Link>. Concernant les dons, ils peuvent s&apos;effectuer via <Link underline='hover' href='https://liberapay.com/OKi/donate' target='_blank' rel='noreferrer'><strong>Liberapay</strong></Link>, <Link underline='hover' href='https://www.paypal.com/donate/?hosted_button_id=5Q3KPR79CAZVW' target='_blank' rel='noreferrer'><strong>PayPal</strong></Link>.
</Typography> </Typography>
<Typography paragraph variant='subtitle1' component='div'> <Typography paragraph='true' variant='subtitle1' component='div'>
Veuillez prendre connaissance des <Link underline='hover' href='#' onClick={() => setOpen(true)}><strong>CGU et de la politique de confidentialité</strong></Link> au chapitre 9 &quot;Les dons&quot;. <Link underline='hover' href={CGU_PDF_LINK}><small>Cliquez ici pour la version pdf</small></Link>. Veuillez prendre connaissance des <Link underline='hover' href='#' onClick={() => setOpen(true)}><strong>CGU et de la politique de confidentialité</strong></Link> au chapitre 9 &quot;Les dons&quot;. <Link underline='hover' href={CGU_PDF_LINK}><small>Cliquez ici pour la version pdf</small></Link>.
</Typography> </Typography>
<Typography variant='subtitle1' component='div'> <Typography variant='subtitle1' component='div'>
@@ -55,10 +55,10 @@ export default function Presantasyon() {
</ListItemText> </ListItemText>
</ListItem> </ListItem>
</List> </List>
<Typography paragraph variant='subtitle1' component='div'> <Typography paragraph='true' variant='subtitle1' component='div'>
Pour toute question, nhésitez pas à nous contacter par courriel <Link href='mailto:kontak@o-k-i.net'><strong>kontak@o-k-i.net</strong></Link>. Pour toute question, nhésitez pas à nous contacter par courriel <Link href='mailto:kontak@o-k-i.net'><strong>kontak@o-k-i.net</strong></Link>.
</Typography> </Typography>
<Typography paragraph variant='subtitle1' component='div'> <Typography paragraph='true' variant='subtitle1' component='div'>
<strong>Merci par avance pour votre soutien 🥰</strong> <strong>Merci par avance pour votre soutien 🥰</strong>
</Typography> </Typography>
</Paper> </Paper>
+1 -1
View File
@@ -2,7 +2,7 @@ import PropTypes from 'prop-types'
import Card from '@mui/material/Card' import Card from '@mui/material/Card'
import CardContent from '@mui/material/CardContent' import CardContent from '@mui/material/CardContent'
import Typography from '@mui/material/Typography' import Typography from '@mui/material/Typography'
import Grid from '@mui/material/Grid2' import Grid from '@mui/material/Grid'
import TraductionsStats from './traductions-stats' import TraductionsStats from './traductions-stats'
+1 -1
View File
@@ -1,7 +1,7 @@
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
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/Grid2' import Grid from '@mui/material/Grid'
import BarStats from './bar-stats' import BarStats from './bar-stats'
+1 -1
View File
@@ -8,7 +8,7 @@ export default function AnTeks({parole, paroleId}) {
<Teks <Teks
parole={parole} parole={parole}
paroleId={paroleId} paroleId={paroleId}
commentaires={parole?.commentaires.data} commentaires={parole?.commentaires}
/> />
) )
} }
+2 -2
View File
@@ -2,7 +2,7 @@
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import Container from '@mui/material/Container' import Container from '@mui/material/Container'
import Grid from '@mui/material/Grid2' import Grid from '@mui/material/Grid'
import Typography from '@mui/material/Typography' import Typography from '@mui/material/Typography'
import {styled} from '@mui/material/styles' import {styled} from '@mui/material/styles'
@@ -17,7 +17,7 @@ const classes = {
const Root = styled('div')(() => ({ const Root = styled('div')(() => ({
[`&.${classes.container}`]: { [`&.${classes.container}`]: {
marginTop: '4em', marginTop: '6em',
marginBottom: '2em', marginBottom: '2em',
}, },
+1 -1
View File
@@ -49,7 +49,7 @@ export default function DiferansDialog({difference}) {
<DialogTitle>Liste des modifications</DialogTitle> <DialogTitle>Liste des modifications</DialogTitle>
<List sx={{width: '100%', maxWidth: 360, bgcolor: 'background.paper'}}> <List sx={{width: '100%', maxWidth: 360, bgcolor: 'background.paper'}}>
{difference.map(({id, admin_user, date, jsonDiff}) => { {difference.map(({id, admin_user, date, jsonDiff}) => {
const {firstname} = admin_user.data.attributes const {firstname} = admin_user
const diferansDate = format(new Date(date), 'PPPppp', {locale: fr}) const diferansDate = format(new Date(date), 'PPPppp', {locale: fr})
return ( return (
+4 -4
View File
@@ -17,13 +17,13 @@ import MizikLis from '../awtis/mizik-lis'
const getMizikFiltered = (paroles, filter) => { const getMizikFiltered = (paroles, filter) => {
if (paroles) { if (paroles) {
const filteredTitre = paroles.filter(({attributes}) => { const filteredTitre = paroles.filter(({titre}) => {
const deburredTit = deburr(attributes.titre) const deburredTit = deburr(titre)
return deburredTit.toLowerCase().includes(deburr(filter.toLowerCase())) return deburredTit.toLowerCase().includes(deburr(filter.toLowerCase()))
}) })
const filteredAlias = paroles.filter(({attributes}) => { const filteredAlias = paroles.filter(({artistes}) => {
const aliasLis = attributes.artistes.data.map(({attributes}) => deburr(attributes.alias)).join(', ') const aliasLis = artistes.map(({alias}) => deburr(alias)).join(', ')
return aliasLis.toLowerCase().includes(deburr(filter.toLowerCase())) return aliasLis.toLowerCase().includes(deburr(filter.toLowerCase()))
}) })
+5 -5
View File
@@ -70,7 +70,7 @@ export default function Lekte({audio, url, parole}) {
const minute = Math.floor(value / 60) const minute = Math.floor(value / 60)
const secondLeft = value - (minute * 60) const secondLeft = value - (minute * 60)
if (Number.isNaN(minute) || Number.isNaN(secondLeft)) { if (Number.isNaN(minute) || Number.isNaN(secondLeft)) {
return 'Information indisponible' return '...'
} }
return `${minute}:${secondLeft <= 9 ? `0${secondLeft}` : secondLeft}` return `${minute}:${secondLeft <= 9 ? `0${secondLeft}` : secondLeft}`
@@ -137,9 +137,9 @@ export default function Lekte({audio, url, parole}) {
audioRef.current.volume = value / 100 audioRef.current.volume = value / 100
} }
const imagePath = parole?.couverture?.data?.attributes?.formats?.thumbnail?.url const imagePath = parole?.couverture?.formats?.thumbnail?.url
const width = parole?.couverture?.data?.attributes?.formats?.thumbnail?.width || 192 const width = parole?.couverture?.formats?.thumbnail?.width || 192
const height = parole?.couverture?.data?.attributes?.formats?.thumbnail?.height || 192 const height = parole?.couverture?.formats?.thumbnail?.height || 192
const imageSrc = imagePath const imageSrc = imagePath
? new URL(imagePath, IMAGE_URL).toString() ? new URL(imagePath, IMAGE_URL).toString()
@@ -243,7 +243,7 @@ export default function Lekte({audio, url, parole}) {
)} )}
</IconButton> </IconButton>
</Box> </Box>
<Stack spacing={2} direction='row' sx={{mb: 1, px: 1}} alignItems='center'> <Stack spacing={2} direction='row' sx={{mb: 1, px: 1}} alignitems='center'>
<VolumeDownRounded htmlColor={lightIconColor} /> <VolumeDownRounded htmlColor={lightIconColor} />
<Slider <Slider
aria-label='Volume' aria-label='Volume'
+4 -4
View File
@@ -50,10 +50,10 @@ export default function Pataje({parole, setError, setSuccess}) {
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
const patajeUrl = `${SITE_URL}/paroles/${slug}` const patajeUrl = `${SITE_URL}/paroles/${slug}`
const alias = artistes.data.map(({attributes}) => attributes.alias) const alias = artistes.map(({alias}) => alias)
const renderAwtis = new Intl.ListFormat('fr').format(alias) const renderAwtis = new Intl.ListFormat('fr').format(alias)
const text = parole.user.data || parole.userAdmin.data ? `${renderAwtis} - ${titre} (Paroles et Traductions) - (parole soumise par ${parole?.user?.data?.attributes?.username || parole.userAdmin?.data?.attributes?.username || parole.userAdmin?.data?.attributes?.firstname})` : `${renderAwtis} - ${titre} (Paroles et Traductions)` const text = parole.user || parole.userAdmin ? `${renderAwtis} - ${titre} (Paroles et Traductions) - (parole soumise par ${parole?.user?.username || parole.userAdmin?.username || parole.userAdmin?.firstname})` : `${renderAwtis} - ${titre} (Paroles et Traductions)`
const handleClose = () => { const handleClose = () => {
setOpen(false) setOpen(false)
@@ -114,8 +114,8 @@ export default function Pataje({parole, setError, setSuccess}) {
<SpeedDialAction <SpeedDialAction
key={action.name} key={action.name}
icon={action.icon} icon={action.icon}
tooltipPlacement='right' placement='right'
tooltipTitle={action.name} title={action.name}
onClick={() => handleClick(action.code)} onClick={() => handleClick(action.code)}
/> />
))} ))}
+6 -6
View File
@@ -32,7 +32,7 @@ export default function TeksDrawer({paroles}) {
const [error, setError] = useState('') const [error, setError] = useState('')
const [success, setSuccess] = useState('') const [success, setSuccess] = useState('')
const parole = paroles.find(({attributes}) => attributes.slug === slug) const parole = paroles.find((parole) => parole.slug === slug)
useEffect(() => { useEffect(() => {
if (error || success) { if (error || success) {
@@ -93,17 +93,17 @@ export default function TeksDrawer({paroles}) {
{parole && ( {parole && (
<Box sx={{display: 'flex', position: 'relative', top: '-20px'}}> <Box sx={{display: 'flex', position: 'relative', top: '-20px'}}>
<Box> <Box>
<Pataje parole={parole.attributes} setError={setError} setSuccess={setSuccess} /> <Pataje parole={parole} setError={setError} setSuccess={setSuccess} />
</Box> </Box>
{parole.attributes.streamVideo && parole.attributes.streamVideo.length > 0 && ( {parole.streamVideo && parole.streamVideo.length > 0 && (
<Box> <Box>
<VweKouteAchte niVideyo parole={parole.attributes} /> <VweKouteAchte niVideyo parole={parole} />
</Box> </Box>
)} )}
{parole.attributes.streamAudio && parole.attributes.streamAudio.length > 0 && ( {parole.streamAudio && parole.streamAudio.length > 0 && (
<Box> <Box>
<VweKouteAchte niOdyo parole={parole.attributes} /> <VweKouteAchte niOdyo parole={parole} />
</Box> </Box>
)} )}
</Box> </Box>
+10 -11
View File
@@ -12,7 +12,7 @@ import CardContent from '@mui/material/CardContent'
import CardMedia from '@mui/material/CardMedia' import CardMedia from '@mui/material/CardMedia'
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/Grid2' import Grid from '@mui/material/Grid'
import ExplicitIcon from '@mui/icons-material/Explicit' import ExplicitIcon from '@mui/icons-material/Explicit'
import {styled} from '@mui/material/styles' import {styled} from '@mui/material/styles'
@@ -40,11 +40,10 @@ const noImageUrl = 'https://place-hold.it/140x140?text=Indisponible'
export default function TeksKat({parole}) { export default function TeksKat({parole}) {
const router = useRouter() const router = useRouter()
const {attributes} = parole const {titre, artistes, annee, couverture, publishedAt, slug} = parole
const {titre, artistes, annee, couverture, publishedAt, slug} = attributes
const datPiblikasyon = format(new Date(publishedAt), 'P', {locale: fr}) const datPiblikasyon = format(new Date(publishedAt), 'P', {locale: fr})
const aliases = getAlias(artistes, attributes.prioriteArtistes) const aliases = getAlias(artistes, parole.prioriteArtistes)
const handleClick = slug => { const handleClick = slug => {
router.push(`/paroles/${slug}`)?.then(() => window.scrollTo(0, 0)) router.push(`/paroles/${slug}`)?.then(() => window.scrollTo(0, 0))
@@ -58,7 +57,7 @@ export default function TeksKat({parole}) {
className={classes.media} className={classes.media}
component='img' component='img'
alt={titre} alt={titre}
image={couverture?.data?.attributes?.url ? `${IMAGE_URL}${couverture.data.attributes.url}` : noImageUrl} image={couverture?.url ? `${IMAGE_URL}${couverture.url}` : noImageUrl}
title={titre} title={titre}
/> />
<CardContent> <CardContent>
@@ -66,7 +65,7 @@ export default function TeksKat({parole}) {
<Typography display='inline' style={{marginRight: 5}} variant='h6' component='h2'> <Typography display='inline' style={{marginRight: 5}} variant='h6' component='h2'>
{titre} {titre}
</Typography> </Typography>
{attributes.creativeCommons && ( {parole.creativeCommons && (
<Box marginInline={1}> <Box marginInline={1}>
<Image <Image
width={24} width={24}
@@ -78,7 +77,7 @@ export default function TeksKat({parole}) {
</Box> </Box>
)} )}
{attributes.explicitLyrics && ( {parole.explicitLyrics && (
<ExplicitIcon style={{marginRight: 5}} color='error' fontSize='small' /> <ExplicitIcon style={{marginRight: 5}} color='error' fontSize='small' />
)} )}
</Box> </Box>
@@ -90,14 +89,14 @@ export default function TeksKat({parole}) {
{annee} {annee}
</Typography> </Typography>
<Typography sx={{fontStyle: 'italic'}} variant='caption'> <Typography sx={{fontStyle: 'italic'}} variant='caption'>
{attributes.user && ( {parole.user && (
<> <>
(<i>parole soumise par {attributes.user.username}</i>) (<i>parole soumise par {parole.user.username}</i>)
</> </>
)} )}
{attributes.userAdmin && !attributes.user && ( {parole.userAdmin && !parole.user && (
<> <>
(<i>parole soumise par {attributes.userAdmin}</i>) (<i>parole soumise par {parole.userAdmin}</i>)
</> </>
)} )}
</Typography> </Typography>
+13 -13
View File
@@ -3,7 +3,7 @@
import {useEffect} from 'react' import {useEffect} from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import Box from '@mui/material/Box' import Box from '@mui/material/Box'
import Grid from '@mui/material/Grid2' import Grid from '@mui/material/Grid'
import Typography from '@mui/material/Typography' import Typography from '@mui/material/Typography'
import Tooltip from '@mui/material/Tooltip' import Tooltip from '@mui/material/Tooltip'
import {useMediaQuery} from '@mui/material' import {useMediaQuery} from '@mui/material'
@@ -138,8 +138,8 @@ export default function Teks({parole}) {
return ( return (
<Root className={classes.container}> <Root className={classes.container}>
<Box sx={{textAlign: 'center', marginTop: 1}}> <Box sx={{textAlign: 'center', marginTop: 12}}>
<Typography variant='h4' component='div' display='block' marginBottom={2}> <Typography variant='h4' component='div' display='block' marginbottom={2}>
<Typography gutterBottom color='primary' variant='h6' component='div'> <Typography gutterBottom color='primary' variant='h6' component='div'>
{enhancedAliases.map(({type, value}) => { {enhancedAliases.map(({type, value}) => {
if (type === 'element') { if (type === 'element') {
@@ -151,7 +151,7 @@ export default function Teks({parole}) {
return <span key={value} className={classes.separation}>{value}</span> return <span key={value} className={classes.separation}>{value}</span>
})} })}
</Typography> </Typography>
<Box display='flex' justifyContent='center' alignItems='center'> <Box display='flex' justifycontent='center' alignitems='center'>
<Typography variant='h5' component='div'> <Typography variant='h5' component='div'>
{parole.titre} <small>({parole?.annee})</small> {parole.titre} <small>({parole?.annee})</small>
</Typography> </Typography>
@@ -169,14 +169,14 @@ export default function Teks({parole}) {
</Box> </Box>
</Typography> </Typography>
{parole?.user?.data && ( {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.user.data.attributes.username}</i> <i>parole soumise par {parole.user.username}</i>
</Typography> </Typography>
)} )}
{parole?.userAdmin?.data && !parole.user.data && ( {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.data.attributes.firstname}</i> <i>parole soumise par {parole.userAdmin.firstname}</i>
</Typography> </Typography>
)} )}
{parole.creativeCommons && ( {parole.creativeCommons && (
@@ -184,8 +184,8 @@ export default function Teks({parole}) {
<LicenseModal license={parole.creativeCommons.toLowerCase()} /> <LicenseModal license={parole.creativeCommons.toLowerCase()} />
</Box> </Box>
)} )}
{parole?.files?.data && ( {parole?.files && (
<FilesDialog files={parole.files.data} /> <FilesDialog files={parole.files} />
)} )}
{(parole.okiMizikID || parole.streamAudio.length > 0 || parole.gadeEmbed) && ( {(parole.okiMizikID || parole.streamAudio.length > 0 || parole.gadeEmbed) && (
<Box sx={{textAlign: 'center'}}> <Box sx={{textAlign: 'center'}}>
@@ -199,13 +199,13 @@ export default function Teks({parole}) {
<DiferansDialog difference={parole.difference} /> <DiferansDialog difference={parole.difference} />
)} )}
</Box> </Box>
<Grid container justifyContent='center' spacing={1}> <Grid container justifycontent='center' spacing={1}>
<Grid size={{xs: 12, md: langArray.length > 0 ? 6 : null}}> <Grid size={{xs: 12, md: langArray.length > 0 ? 6 : null}}>
<Box className={classes.gridText}> <Box className={classes.gridText}>
<Typography align='center' sx={{marginBottom: '0.5em'}} variant='h4'> <Typography align='center' sx={{marginBottom: '0.5em'}} variant='h4'>
Transcription Transcription
</Typography> </Typography>
<Typography paragraph align={alignTeks(langArray, isMobile)} component='span'> <Typography paragraph='true' align={alignTeks(langArray, isMobile)} component='span'>
{formatJsonString(parole.transcription)} {formatJsonString(parole.transcription)}
</Typography> </Typography>
</Box> </Box>
@@ -240,7 +240,7 @@ export default function Teks({parole}) {
</span> </span>
)} {title} )} {title}
</Typography> </Typography>
<Typography paragraph align='justify' component='span'> <Typography paragraph='true' align='justify' component='span'>
{formatJsonString(lang)} {formatJsonString(lang)}
</Typography> </Typography>
</Box> </Box>
+2 -2
View File
@@ -96,7 +96,7 @@ export default function VweKouteAchte({parole, niVideyo, niOdyo}) {
<SpeedDialAction <SpeedDialAction
key={action.name} key={action.name}
icon={action.icon} icon={action.icon}
tooltipTitle={action.name} title={action.name}
onClick={() => handleClick(action.link)} onClick={() => handleClick(action.link)}
/> />
))} ))}
@@ -104,7 +104,7 @@ export default function VweKouteAchte({parole, niVideyo, niOdyo}) {
<SpeedDialAction <SpeedDialAction
key={action.name} key={action.name}
icon={action.icon} icon={action.icon}
tooltipTitle={action.name} title={action.name}
onClick={() => handleClick(action.link)} onClick={() => handleClick(action.link)}
/> />
))} ))}
+7
View File
@@ -0,0 +1,7 @@
'use client'
import NextTopLoader from 'nextjs-toploader'
export default function TopLoader({color}) {
return <NextTopLoader color={color} />
}
+8 -8
View File
@@ -1,19 +1,19 @@
export const formatKuveti = kuveti => { export const formatKuveti = kuveti => {
if (!kuveti?.data?.attributes) { if (!kuveti) {
return null return null
} }
if (kuveti.data.attributes && kuveti.data.attributes.formats && kuveti.data.attributes.formats.large) { if (kuveti && kuveti.formats && kuveti.formats.large) {
return kuveti.data.attributes.formats.large return kuveti.formats.large
} }
if (kuveti.data.attributes && kuveti.data.attributes.formats && kuveti.data.attributes.formats.medium) { if (kuveti && kuveti.formats && kuveti.formats.medium) {
return kuveti.data.attributes.formats.medium return kuveti.formats.medium
} }
if (kuveti.data.attributes && kuveti.data.attributes.formats && kuveti.data.attributes.formats.small) { if (kuveti && kuveti.formats && kuveti.formats.small) {
return kuveti.data.attributes.formats.small return kuveti.formats.small
} }
return kuveti.data.attributes return kuveti
} }
+13 -24
View File
@@ -46,12 +46,7 @@ export async function jwennTeksEpiSlug(slug) {
populate: '*' populate: '*'
}, },
artistes: { artistes: {
fields: ['alias', 'slug', 'musicBrainzUrl', 'photo'], fields: ['alias', 'slug', 'musicBrainzUrl'],
populate: {
photo: {
fields: ['name', 'url'],
},
},
}, },
streamAudio: { streamAudio: {
populate: '*' populate: '*'
@@ -61,14 +56,6 @@ export async function jwennTeksEpiSlug(slug) {
}, },
traductions: { traductions: {
populate: '*' populate: '*'
},
difference: {
fileds: ['date', 'id', 'paroles', 'jsonDiff', 'source', 'admin_user'],
populate: {
admin_user: {
fields: ['firstname']
}
}
} }
}, },
filters: { filters: {
@@ -96,8 +83,9 @@ export async function jwennAwtisEpiSlug(slug) {
encodeValuesOnly: true encodeValuesOnly: true
}) })
const {data} = await request(`/artistes?${query}`, headers) const {data, meta} = await request(`/artistes?${query}`, headers)
return data[0]
return {data: data[0], meta}
} }
export async function jwennAwtisPajinasyon(paj) { export async function jwennAwtisPajinasyon(paj) {
@@ -113,8 +101,9 @@ export async function jwennAwtisPajinasyon(paj) {
encodeValuesOnly: true encodeValuesOnly: true
}) })
const data = await request(`/artistes?${query}`, headers) const {data, meta} = await request(`/artistes?${query}`, headers)
return data
return {data, meta}
} }
export async function jwennToutAwtis() { export async function jwennToutAwtis() {
@@ -128,7 +117,7 @@ export async function jwennToutAwtis() {
encodeValuesOnly: true encodeValuesOnly: true
}) })
const {data} = await request(`/artistes?${query}`, headers) const data = await request(`/artistes?${query}`, headers)
return data return data
} }
@@ -188,7 +177,7 @@ export async function jwennAwtisSlug() {
}) })
const {data} = await request(`/artistes?${query}`, headers) const {data} = await request(`/artistes?${query}`, headers)
return data.map(({attributes}) => attributes.slug) return data.map(({slug}) => slug)
} }
export async function jwennTeksSlug() { export async function jwennTeksSlug() {
@@ -202,7 +191,7 @@ export async function jwennTeksSlug() {
}) })
const {data} = await request(`/paroles?${query}`, headers) const {data} = await request(`/paroles?${query}`, headers)
return data.map(({attributes}) => attributes.slug) return data.map(({slug}) => slug)
} }
export async function jwennDenyeTeks() { export async function jwennDenyeTeks() {
@@ -227,7 +216,7 @@ export async function jwennAnTeks(teksId, token) {
Authorization: `Bearer ${token}` Authorization: `Bearer ${token}`
} }
const {data} = await request(`/paroles/${teksId}`, {headers}) const data = await request(`/paroles/${teksId}`, {headers})
return data return data
} }
@@ -246,7 +235,7 @@ export async function jwennKomanteEpiTeksId(teksId) {
encodeValuesOnly: true encodeValuesOnly: true
}) })
const {data} = await request(`/commentaires?${query}`, headers) const data = await request(`/commentaires?${query}`, headers)
return data return data
} }
@@ -292,7 +281,7 @@ export async function jwennUserEpiEmail(email) {
encodeValuesOnly: true encodeValuesOnly: true
}) })
const {data} = await request(`/users?${query}`, headers) const data = await request(`/users?${query}`, headers)
return data[0] return data[0]
} }
+8 -8
View File
@@ -4,14 +4,14 @@ export const formatJsonString = stringToFormat =>
stringToFormat.split('\n').map((string, index) => <div key={index}>{`${string}`}<br /></div>) // eslint-disable-line react/no-array-index-key stringToFormat.split('\n').map((string, index) => <div key={index}>{`${string}`}<br /></div>) // eslint-disable-line react/no-array-index-key
export const getAlias = (artistes, priorite = null, enhanced = false) => { export const getAlias = (artistes, priorite = null, enhanced = false) => {
if (artistes.data.length === 1 && !enhanced) { if (artistes.length === 1 && !enhanced) {
return artistes.data[0].attributes.alias return artistes[0].alias
} }
if (artistes.data.length === 1 && enhanced) { if (artistes.length === 1 && enhanced) {
return [{ return [{
type: 'element', type: 'element',
value: artistes.data[0].attributes.alias value: artistes[0].alias
}] }]
} }
@@ -21,12 +21,12 @@ export const getAlias = (artistes, priorite = null, enhanced = false) => {
if (splittedPriority) { if (splittedPriority) {
for (const element of splittedPriority) { for (const element of splittedPriority) {
const foundedArtistes = artistes.data.find(({id}) => id === element) const foundedArtistes = artistes.find(({id}) => id === element)
alias.push(foundedArtistes.attributes.alias) alias.push(foundedArtistes.alias)
} }
} else { } else {
for (const artiste of artistes.data) { for (const artiste of artistes) {
alias.push(artiste.attributes.alias) alias.push(artiste.alias)
} }
} }
+8 -6
View File
@@ -15,7 +15,7 @@
}, },
"scripts": { "scripts": {
"lint": "xo", "lint": "xo",
"dev": "next dev --turbopack -p 3001", "dev": "next dev -p 3001",
"build": "next build", "build": "next build",
"start": "next start -p 3001" "start": "next start -p 3001"
}, },
@@ -26,10 +26,12 @@
"@emotion/styled": "^11.13.0", "@emotion/styled": "^11.13.0",
"@fontsource/roboto": "^5.0.5", "@fontsource/roboto": "^5.0.5",
"@icons-pack/react-simple-icons": "^3.13.0", "@icons-pack/react-simple-icons": "^3.13.0",
"@mui/icons-material": "^5.16.6", "@mui/icons-material": "^9.0.0",
"@mui/lab": "^5.0.0-alpha.89", "@mui/lab": "^9.0.0-beta.2",
"@mui/material": "^6.1.4", "@mui/material": "^9.0.0",
"@mui/styles": "^5.8.7", "@mui/material-pigment-css": "^9.0.0",
"@mui/styles": "^6.4.8",
"@pigment-css/react": "^0.0.30",
"@svgr/webpack": "^6.5.0", "@svgr/webpack": "^6.5.0",
"axios": "^0.21.0", "axios": "^0.21.0",
"compression": "^1.7.4", "compression": "^1.7.4",
@@ -41,7 +43,7 @@
"next": "16.2.4", "next": "16.2.4",
"next-auth": "^5.0.0-beta.31", "next-auth": "^5.0.0-beta.31",
"next-pwa": "5.6.0", "next-pwa": "5.6.0",
"nextjs-toploader": "^1.4.2", "nextjs-toploader": "^3.9.17",
"nodemailer": "^6.7.2", "nodemailer": "^6.7.2",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"react": "19.2.5", "react": "19.2.5",
+481 -406
View File
File diff suppressed because it is too large Load Diff