Use axios base url.
This commit is contained in:
parent
1e3d62afab
commit
b90deb76ad
ui
package.jsonpnpm-lock.yaml
src
App.tsx
components
ChangeRoleModal.tsxCreateInviteModal.tsxCreatePlaylistModal.tsxEpisodeCard.tsxEpisodeSearch.tsxFeedURLComponent.tsxHiddenAudioPlayer.tsxNotifications.tsxOpmlAdd.tsxPlayerProgressBar.tsxPlayerTimeControls.tsxPlaylistSubmitViewer.tsxPodcastCard.tsxPodcastDetailItem.tsxPodcastInfoModal.tsxProviderImportComponent.tsxSettingsData.tsxSettingsNaming.tsxSettingsOPMLExport.tsxSettingsPodcastDelete.tsxTimelineEpisode.tsxUserAdminInvites.tsxUserAdminUsers.tsx
main.tsxpages
AcceptInvite.tsxHomepage.tsxLogin.tsxPlaylistDetailPage.tsxPlaylistPage.tsxPodcastDetailPage.tsxPodcasts.tsxSystemInfoPage.tsxTimeline.tsxUserManagement.tsx
routing
utils
test
|
@ -53,11 +53,13 @@
|
|||
"@vite-pwa/assets-generator": "^0.2.3",
|
||||
"@vitejs/plugin-react-swc": "^3.6.0",
|
||||
"autoprefixer": "^10.4.17",
|
||||
"jsdom": "^24.0.0",
|
||||
"postcss": "^8.4.35",
|
||||
"sass": "^1.70.0",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"typescript": "^5.3.3",
|
||||
"vite": "^5.1.1",
|
||||
"vite-plugin-pwa": "^0.18.1"
|
||||
"vite-plugin-pwa": "^0.18.1",
|
||||
"vitest": "^1.2.2"
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -5,7 +5,7 @@ import axios, { AxiosResponse } from 'axios'
|
|||
import { enqueueSnackbar } from 'notistack'
|
||||
import useCommon, {LoggedInUser} from './store/CommonSlice'
|
||||
import useOpmlImport from './store/opmlImportSlice'
|
||||
import {apiURL, configWSUrl, decodeHTMLEntities, isJsonString} from './utils/Utilities'
|
||||
import {decodeHTMLEntities, isJsonString} from './utils/Utilities'
|
||||
import {
|
||||
UserAdminViewLazyLoad,
|
||||
EpisodeSearchViewLazyLoad,
|
||||
|
@ -39,6 +39,7 @@ import {SettingsPodcastDelete} from "./components/SettingsPodcastDelete";
|
|||
import {UserAdminUsers} from "./components/UserAdminUsers";
|
||||
import {UserAdminInvites} from "./components/UserAdminInvites";
|
||||
import {UserManagementPage} from "./pages/UserManagement";
|
||||
import {configWSUrl} from "./utils/navigationUtils";
|
||||
|
||||
export const router = createBrowserRouter(createRoutesFromElements(
|
||||
<>
|
||||
|
@ -196,14 +197,14 @@ const App: FC<PropsWithChildren> = ({ children }) => {
|
|||
|
||||
useEffect(() => {
|
||||
if (config?.basicAuth||config?.oidcConfigured||config?.reverseProxy){
|
||||
axios.get(apiURL + '/users/me')
|
||||
axios.get('/users/me')
|
||||
.then((c:AxiosResponse<LoggedInUser>)=>useCommon.getState().setLoggedInUser(c.data))
|
||||
.catch(() => enqueueSnackbar(t('not-admin'), { variant: 'error' }))
|
||||
}
|
||||
}, []);
|
||||
|
||||
const getNotifications = () => {
|
||||
axios.get(apiURL + '/notifications/unread')
|
||||
axios.get( '/notifications/unread')
|
||||
.then((response: AxiosResponse<Notification[]>) => {
|
||||
setNotifications(response.data)
|
||||
})
|
||||
|
|
|
@ -2,7 +2,6 @@ import { useTranslation } from 'react-i18next'
|
|||
import axios from 'axios'
|
||||
import { enqueueSnackbar } from 'notistack'
|
||||
import useCommon from '../store/CommonSlice'
|
||||
import { apiURL } from '../utils/Utilities'
|
||||
import { User } from '../models/User'
|
||||
import { CustomButtonPrimary } from './CustomButtonPrimary'
|
||||
import { CustomSelect } from './CustomSelect'
|
||||
|
@ -26,7 +25,7 @@ export const ChangeRoleModal = () => {
|
|||
|
||||
//setSelectedUser, setUsers
|
||||
const changeRole = () => {
|
||||
axios.put(apiURL + '/users/' + selectedUser?.username + '/role', {
|
||||
axios.put( '/users/' + selectedUser?.username + '/role', {
|
||||
role: selectedUser?.role,
|
||||
explicitConsent: selectedUser?.explicitConsent
|
||||
})
|
||||
|
|
|
@ -4,7 +4,6 @@ import { useTranslation } from 'react-i18next'
|
|||
import axios from 'axios'
|
||||
import { enqueueSnackbar } from 'notistack'
|
||||
import useCommon from '../store/CommonSlice'
|
||||
import { apiURL } from '../utils/Utilities'
|
||||
import { CustomButtonPrimary } from './CustomButtonPrimary'
|
||||
import { CustomSelect } from './CustomSelect'
|
||||
import { Heading2 } from './Heading2'
|
||||
|
@ -61,7 +60,7 @@ export const CreateInviteModal = () => {
|
|||
role: invite.role.toLowerCase(),
|
||||
explicitConsent: invite.explicitConsent
|
||||
} satisfies Invite
|
||||
axios.post(apiURL + '/users/invites', modifiedInvite)
|
||||
axios.post( '/users/invites', modifiedInvite)
|
||||
.then((v) => {
|
||||
enqueueSnackbar(t('invite-created'), { variant: 'success' })
|
||||
setInvites([...invites,v.data])
|
||||
|
|
|
@ -3,7 +3,6 @@ import {createPortal} from "react-dom"
|
|||
import {useTranslation} from "react-i18next"
|
||||
import axios, {AxiosResponse} from "axios"
|
||||
import {enqueueSnackbar} from "notistack"
|
||||
import {apiURL} from "../utils/Utilities"
|
||||
import {Heading2} from "./Heading2"
|
||||
import "material-symbols/outlined.css"
|
||||
import {PlaylistDto, PlaylistDtoPost, PlaylistDtoPut, PlaylistItem} from "../models/Playlist";
|
||||
|
@ -37,7 +36,7 @@ export const CreatePlaylistModal = () => {
|
|||
|
||||
|
||||
if (currentPlaylistToEdit && currentPlaylistToEdit.id !== -1){
|
||||
axios.put(apiURL+"/playlist/"+currentPlaylistToEdit.id, {
|
||||
axios.put("/playlist/"+currentPlaylistToEdit.id, {
|
||||
id: currentPlaylistToEdit.id,
|
||||
name: currentPlaylistToEdit.name,
|
||||
items: itemsMappedToIDs
|
||||
|
@ -50,7 +49,7 @@ export const CreatePlaylistModal = () => {
|
|||
}
|
||||
|
||||
if (currentPlaylistToEdit && currentPlaylistToEdit.id === -1) {
|
||||
axios.post(apiURL + "/playlist", {
|
||||
axios.post( "/playlist", {
|
||||
name: currentPlaylistToEdit.name,
|
||||
items: itemsMappedToIDs
|
||||
} satisfies PlaylistDtoPost)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { FC} from 'react'
|
||||
import axios, { AxiosResponse } from 'axios'
|
||||
import { apiURL, preparePath } from '../utils/Utilities'
|
||||
import {preparePath } from '../utils/Utilities'
|
||||
import {Podcast, PodcastEpisode} from '../store/CommonSlice'
|
||||
import { PodcastWatchedEpisodeModel } from '../models/PodcastWatchedEpisodeModel'
|
||||
import {Episode} from "../models/Episode";
|
||||
|
@ -41,7 +41,7 @@ export const EpisodeCard: FC<EpisodeCardProps> = ({ podcast, podcastEpisode, tot
|
|||
|
||||
return (
|
||||
<div className="group cursor-pointer" key={podcastEpisode.episode_id+"dv"} onClick={()=>{
|
||||
axios.get(apiURL + '/podcast/episode/' + podcastEpisode.episode_id)
|
||||
axios.get( '/podcast/episode/' + podcastEpisode.episode_id)
|
||||
.then((response: AxiosResponse<Episode>) => {
|
||||
handlePlayofEpisode(response, {
|
||||
podcastEpisode: podcastEpisode,
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import { FC, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import axios, { AxiosResponse } from 'axios'
|
||||
import { PodcastEpisode } from '../store/CommonSlice'
|
||||
import {apiURL, formatTime, prependAPIKeyOnAuthEnabled, removeHTML} from '../utils/Utilities'
|
||||
import {formatTime, prependAPIKeyOnAuthEnabled, removeHTML} from '../utils/Utilities'
|
||||
import { useDebounce } from '../utils/useDebounce'
|
||||
import { CustomInput } from './CustomInput'
|
||||
import { Spinner } from './Spinner'
|
||||
|
@ -28,7 +27,7 @@ export const EpisodeSearch: FC<EpisodeSearchProps> = ({ classNameResults = '', o
|
|||
if (searchName.trim().length > 0) {
|
||||
setSearching(true)
|
||||
|
||||
axios.get(apiURL + '/podcasts/' + searchName + '/query')
|
||||
axios.get( '/podcasts/' + searchName + '/query')
|
||||
.then((v: AxiosResponse<PodcastEpisode[]>) => {
|
||||
setSearchResults(v.data)
|
||||
setSearching(false)
|
||||
|
|
|
@ -2,7 +2,6 @@ import { FC } from 'react'
|
|||
import { useForm } from 'react-hook-form'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import axios, { AxiosResponse } from 'axios'
|
||||
import { apiURL } from '../utils/Utilities'
|
||||
import { handleAddPodcast } from '../utils/ErrorSnackBarResponses'
|
||||
import { Podcast } from '../store/CommonSlice'
|
||||
import { CustomButtonPrimary } from './CustomButtonPrimary'
|
||||
|
@ -23,7 +22,7 @@ export const FeedURLComponent: FC = () => {
|
|||
const feedUrlWatched = watch('feedUrl')
|
||||
|
||||
const onSubmit = (data: FeedURLFormData) => {
|
||||
axios.post(apiURL + '/podcast/feed', {
|
||||
axios.post( '/podcast/feed', {
|
||||
rssFeedUrl: data.feedUrl
|
||||
}).then((v: AxiosResponse<Podcast>) => {
|
||||
handleAddPodcast(v.status, v.data.name, t)
|
||||
|
|
|
@ -2,7 +2,6 @@ import { FC, RefObject, useEffect } from 'react'
|
|||
import axios, { AxiosResponse } from 'axios'
|
||||
import useOnMount from '../hooks/useOnMount'
|
||||
import useAudioPlayer from '../store/AudioPlayerSlice'
|
||||
import { apiURL } from '../utils/Utilities'
|
||||
import { AudioAmplifier } from '../models/AudioAmplifier'
|
||||
import { PodcastWatchedModel } from '../models/PodcastWatchedModel'
|
||||
|
||||
|
@ -23,7 +22,7 @@ export const HiddenAudioPlayer: FC<HiddenAudioPlayerProps> = ({ refItem, setAudi
|
|||
|
||||
if (podcastEpisode.time === undefined) {
|
||||
// fetch time from server
|
||||
axios.get(apiURL + '/podcast/episode/' + podcastEpisode.episode_id)
|
||||
axios.get( '/podcast/episode/' + podcastEpisode.episode_id)
|
||||
.then((response: AxiosResponse<PodcastWatchedModel>) => {
|
||||
setCurrentPodcastEpisode({
|
||||
...podcastEpisode,
|
||||
|
|
|
@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'
|
|||
import axios from 'axios'
|
||||
import { AnimatePresence, motion } from 'framer-motion'
|
||||
import * as Popover from '@radix-ui/react-popover'
|
||||
import {apiURL, removeHTML} from '../utils/Utilities'
|
||||
import { removeHTML} from '../utils/Utilities'
|
||||
import useCommon from '../store/CommonSlice'
|
||||
import { Notification } from '../models/Notification'
|
||||
import 'material-symbols/outlined.css'
|
||||
|
@ -38,7 +38,7 @@ export const Notifications: FC = () => {
|
|||
)
|
||||
|
||||
const dismissNotification = (notification: Notification) => {
|
||||
axios.put(apiURL + '/notifications/dismiss', { id: notification.id })
|
||||
axios.put( '/notifications/dismiss', { id: notification.id })
|
||||
.then(() => {
|
||||
removeNotification(notification.id)
|
||||
})
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { FC, useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import axios from 'axios'
|
||||
import { apiURL } from '../utils/Utilities'
|
||||
import { FileItem, readFile } from '../utils/FileUtils'
|
||||
import useOpmlImport from '../store/opmlImportSlice'
|
||||
import { AddTypes } from '../models/AddTypes'
|
||||
|
@ -53,7 +52,7 @@ export const OpmlAdd: FC<OpmlAddProps> = ({}) => {
|
|||
|
||||
setPodcastsToUpload(count)
|
||||
|
||||
axios.post(apiURL + '/podcast/opml', {
|
||||
axios.post( '/podcast/opml', {
|
||||
content: files[0].content
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { createRef, FC, useMemo, useState } from 'react'
|
||||
import useAudioPlayer from '../store/AudioPlayerSlice'
|
||||
import { logCurrentPlaybackTime } from '../utils/Utilities'
|
||||
import {logCurrentPlaybackTime} from "../utils/navigationUtils";
|
||||
|
||||
type PlayerProgressBarProps = {
|
||||
audioplayerRef: React.RefObject<HTMLAudioElement>,
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import {FC, RefObject, useEffect} from 'react'
|
||||
import {
|
||||
apiURL,
|
||||
logCurrentPlaybackTime,
|
||||
prepareOnlinePodcastEpisode,
|
||||
preparePodcastEpisode,
|
||||
SKIPPED_TIME
|
||||
|
@ -13,6 +11,7 @@ import {PodcastWatchedModel} from "../models/PodcastWatchedModel";
|
|||
import useCommon from "../store/CommonSlice";
|
||||
import {EpisodesWithOptionalTimeline} from "../models/EpisodesWithOptionalTimeline";
|
||||
import {Episode} from "../models/Episode";
|
||||
import {logCurrentPlaybackTime} from "../utils/navigationUtils";
|
||||
|
||||
type PlayerTimeControlsProps = {
|
||||
refItem: RefObject<HTMLAudioElement>
|
||||
|
@ -70,7 +69,7 @@ export const PlayerTimeControls: FC<PlayerTimeControlsProps> = ({ refItem }) =>
|
|||
if (refItem === undefined || refItem.current === undefined|| refItem.current === null) return
|
||||
|
||||
const nextEpisode = episodes[index].podcastEpisode
|
||||
axios.get(apiURL + "/podcast/episode/" + nextEpisode.episode_id)
|
||||
axios.get( "/podcast/episode/" + nextEpisode.episode_id)
|
||||
.then((response: AxiosResponse<Episode>) => {
|
||||
setCurrentPodcastEpisode(nextEpisode)
|
||||
nextEpisode.status === 'D'
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import {CustomButtonPrimary} from "./CustomButtonPrimary";
|
||||
import axios, {AxiosResponse} from "axios";
|
||||
import {apiURL} from "../utils/Utilities";
|
||||
import {PlaylistDto, PlaylistDtoPost, PlaylistItem} from "../models/Playlist";
|
||||
import usePlaylist from "../store/PlaylistSlice";
|
||||
import {useTranslation} from "react-i18next";
|
||||
|
@ -18,7 +17,7 @@ export const PlaylistSubmitViewer = ()=>{
|
|||
episode: item.podcastEpisode.id
|
||||
}})
|
||||
|
||||
axios.post(apiURL+'/playlist', {
|
||||
axios.post('/playlist', {
|
||||
name: currentPlaylistToEdit?.name!,
|
||||
items: idsToMap
|
||||
} satisfies PlaylistDtoPost)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { createRef, FC } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import axios from 'axios'
|
||||
import {apiURL, prependAPIKeyOnAuthEnabled} from '../utils/Utilities'
|
||||
import {prependAPIKeyOnAuthEnabled} from '../utils/Utilities'
|
||||
import useCommon, { Podcast } from '../store/CommonSlice'
|
||||
import 'material-symbols/outlined.css'
|
||||
|
||||
|
@ -14,7 +14,7 @@ export const PodcastCard: FC<PodcastCardProps> = ({ podcast }) => {
|
|||
const updateLikePodcast = useCommon(state => state.updateLikePodcast)
|
||||
|
||||
const likePodcast = () => {
|
||||
axios.put(apiURL + '/podcast/favored', {
|
||||
axios.put( '/podcast/favored', {
|
||||
id: podcast.id,
|
||||
favored: !podcast.favorites
|
||||
})
|
||||
|
|
|
@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next'
|
|||
import { Waypoint } from 'react-waypoint'
|
||||
import axios, { AxiosResponse } from 'axios'
|
||||
import { useSnackbar } from 'notistack'
|
||||
import {apiURL, formatTime, prependAPIKeyOnAuthEnabled, removeHTML} from '../utils/Utilities'
|
||||
import {formatTime, prependAPIKeyOnAuthEnabled, removeHTML} from '../utils/Utilities'
|
||||
import 'material-symbols/outlined.css'
|
||||
import {EpisodesWithOptionalTimeline} from "../models/EpisodesWithOptionalTimeline";
|
||||
import useCommon from "../store/CommonSlice";
|
||||
|
@ -81,7 +81,7 @@ export const PodcastDetailItem: FC<PodcastDetailItemProps> = ({ episode, index,e
|
|||
return
|
||||
}
|
||||
|
||||
axios.put(apiURL + "/podcast/" + episode.podcastEpisode.episode_id + "/episodes/download")
|
||||
axios.put( "/podcast/" + episode.podcastEpisode.episode_id + "/episodes/download")
|
||||
.then(()=>{
|
||||
enqueueSnackbar(t('episode-downloaded-to-server'), {variant: "success"})
|
||||
setEpisodeDownloaded(episode.podcastEpisode.episode_id)
|
||||
|
@ -113,7 +113,7 @@ export const PodcastDetailItem: FC<PodcastDetailItemProps> = ({ episode, index,e
|
|||
// Prevent icon click from triggering info modal
|
||||
e.stopPropagation()
|
||||
|
||||
axios.get(apiURL + '/podcast/episode/' + episode.podcastEpisode.episode_id)
|
||||
axios.get( '/podcast/episode/' + episode.podcastEpisode.episode_id)
|
||||
.then((response: AxiosResponse<Episode>) => {
|
||||
handlePlayofEpisode(response, episode)
|
||||
})
|
||||
|
@ -123,7 +123,7 @@ export const PodcastDetailItem: FC<PodcastDetailItemProps> = ({ episode, index,e
|
|||
{/* Infinite scroll */
|
||||
index === (episodesLength - 5) &&
|
||||
<Waypoint key={index + 'waypoint'} onEnter={() => {
|
||||
axios.get(apiURL + '/podcast/' + params.id + '/episodes',{
|
||||
axios.get( '/podcast/' + params.id + '/episodes',{
|
||||
params: {
|
||||
last_podcast_episode: selectedEpisodes[selectedEpisodes.length - 1].podcastEpisode.date_of_recording
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { createPortal } from 'react-dom'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import axios from 'axios'
|
||||
import { apiURL, preparePath, removeHTML } from '../utils/Utilities'
|
||||
import { preparePath, removeHTML } from '../utils/Utilities'
|
||||
import useCommon from '../store/CommonSlice'
|
||||
import { Heading2 } from './Heading2'
|
||||
import 'material-symbols/outlined.css'
|
||||
|
@ -23,7 +23,7 @@ export const PodcastInfoModal = () => {
|
|||
}
|
||||
|
||||
const deleteEpisodeDownloadOnServer = (episodeId: string) => {
|
||||
axios.delete(apiURL + '/episodes/' + episodeId + '/download').then(() => {
|
||||
axios.delete( '/episodes/' + episodeId + '/download').then(() => {
|
||||
setInfoModalPodcastOpen(false)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { FC, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import axios, { AxiosError, AxiosResponse } from 'axios'
|
||||
import { apiURL } from '../utils/Utilities'
|
||||
import { useDebounce } from '../utils/useDebounce'
|
||||
import { handleAddPodcast } from '../utils/ErrorSnackBarResponses'
|
||||
import useCommon from '../store/CommonSlice'
|
||||
|
@ -31,7 +30,7 @@ export const ProviderImportComponent: FC<ProviderImportComponent> = ({ selectedS
|
|||
const setModalOpen = useModal(state => state.setOpenModal)
|
||||
|
||||
const addPodcast = (podcast: AddPostPostModel) => {
|
||||
axios.post(apiURL + '/podcast/' + selectedSearchType, podcast)
|
||||
axios.post( '/podcast/' + selectedSearchType, podcast)
|
||||
.then((err: any) => {
|
||||
setModalOpen(false)
|
||||
err.response.status && handleAddPodcast(err.response.status,
|
||||
|
@ -46,7 +45,7 @@ export const ProviderImportComponent: FC<ProviderImportComponent> = ({ selectedS
|
|||
useDebounce(() => {
|
||||
setLoading(true)
|
||||
selectedSearchType === 'itunes' ?
|
||||
axios.get(apiURL + '/podcasts/0/' + encodeURI(searchText) + '/search')
|
||||
axios.get( '/podcasts/0/' + encodeURI(searchText) + '/search')
|
||||
.then((v: AxiosResponse<GeneralModel>) => {
|
||||
setLoading(false)
|
||||
const agnosticModel: AgnosticPodcastDataModel[] = v.data.results.map((podcast) => {
|
||||
|
@ -60,7 +59,7 @@ export const ProviderImportComponent: FC<ProviderImportComponent> = ({ selectedS
|
|||
|
||||
setSearchedPodcasts(agnosticModel)
|
||||
})
|
||||
: axios.get(apiURL + '/podcasts/1/' + searchText + '/search')
|
||||
: axios.get( '/podcasts/1/' + searchText + '/search')
|
||||
.then((v: AxiosResponse<PodIndexModel>) => {
|
||||
setLoading(false)
|
||||
let agnosticModel: AgnosticPodcastDataModel[] = v.data.feeds.map((podcast) => {
|
||||
|
|
|
@ -2,7 +2,6 @@ import { FC, useEffect, useState } from 'react'
|
|||
import { useTranslation } from 'react-i18next'
|
||||
import axios, { AxiosResponse } from 'axios'
|
||||
import { useSnackbar } from 'notistack'
|
||||
import { apiURL } from '../utils/Utilities'
|
||||
import { Setting } from '../models/Setting'
|
||||
import { CustomButtonPrimary } from './CustomButtonPrimary'
|
||||
import { CustomButtonSecondary } from './CustomButtonSecondary'
|
||||
|
@ -20,7 +19,7 @@ export const SettingsData: FC = () => {
|
|||
|
||||
/* Fetch existing settings */
|
||||
useEffect(()=>{
|
||||
axios.get(apiURL + '/settings').then((res: AxiosResponse<Setting>) => {
|
||||
axios.get( '/settings').then((res: AxiosResponse<Setting>) => {
|
||||
setSettings(res.data)
|
||||
})
|
||||
}, [])
|
||||
|
@ -44,7 +43,7 @@ export const Settings: FC<SettingsProps> = ({ initialSettings }) => {
|
|||
<div>
|
||||
<label className="mr-6" htmlFor="auto-cleanup">{t('auto-cleanup')}</label>
|
||||
<CustomButtonSecondary onClick={() => {
|
||||
axios.put(apiURL+"/settings/runcleanup")
|
||||
axios.put("/settings/runcleanup")
|
||||
}}>{t('run-cleanup')}</CustomButtonSecondary>
|
||||
</div>
|
||||
<Switcher checked={settings.autoCleanup} className="xs:justify-self-end" id="auto-cleanup" setChecked={() => {
|
||||
|
@ -82,7 +81,7 @@ export const Settings: FC<SettingsProps> = ({ initialSettings }) => {
|
|||
</div>
|
||||
|
||||
<CustomButtonPrimary className="float-right" onClick={() => {
|
||||
axios.put(apiURL + '/settings', settings)
|
||||
axios.put( '/settings', settings)
|
||||
.then(() => {
|
||||
enqueueSnackbar(t('settings-saved'), { variant: 'success' })
|
||||
})
|
||||
|
|
|
@ -3,7 +3,6 @@ import { useTranslation } from 'react-i18next'
|
|||
import { Controller, SubmitHandler, useForm } from 'react-hook-form'
|
||||
import axios, { AxiosResponse } from 'axios'
|
||||
import { enqueueSnackbar } from 'notistack'
|
||||
import { apiURL } from '../utils/Utilities'
|
||||
import { Setting } from '../models/Setting'
|
||||
import { UpdateNameSettings } from '../models/UpdateNameSettings'
|
||||
import { CustomButtonPrimary } from './CustomButtonPrimary'
|
||||
|
@ -39,7 +38,7 @@ export const SettingsNaming: FC = () => {
|
|||
|
||||
/* Fetch existing settings */
|
||||
useEffect(() => {
|
||||
axios.get(apiURL + '/settings')
|
||||
axios.get('/settings')
|
||||
.then((res:AxiosResponse<Setting>) => {
|
||||
setSettings(res.data)
|
||||
})
|
||||
|
@ -78,7 +77,7 @@ const Settings: FC<SettingsProps> = ({ intialSettings }) => {
|
|||
const content = {
|
||||
content: episodeFormat
|
||||
}
|
||||
axios.post(apiURL + '/episodes/formatting', content)
|
||||
axios.post( '/episodes/formatting', content)
|
||||
.then((v: AxiosResponse<string>)=>setResultingEpisodeFormat(v.data))
|
||||
.catch(e=>setResultingEpisodeFormat(e.response.data.error))
|
||||
|
||||
|
@ -88,13 +87,13 @@ const Settings: FC<SettingsProps> = ({ intialSettings }) => {
|
|||
const content = {
|
||||
content: podcastFormat
|
||||
}
|
||||
axios.post(apiURL + '/podcasts/formatting', content)
|
||||
axios.post( '/podcasts/formatting', content)
|
||||
.then((v: AxiosResponse<string>)=>setResultingPodcastFormat(v.data))
|
||||
.catch(e=>setResultingPodcastFormat(e.response.data.error))
|
||||
},2000,[podcastFormat])
|
||||
|
||||
const update_settings: SubmitHandler<UpdateNameSettings> = (data) => {
|
||||
axios.put(apiURL + '/settings/name', data satisfies UpdateNameSettings)
|
||||
axios.put( '/settings/name', data satisfies UpdateNameSettings)
|
||||
.then(() => {
|
||||
enqueueSnackbar(t('settings-saved'), { variant: 'success' })
|
||||
})
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import axios from 'axios'
|
||||
import { apiURL } from '../utils/Utilities'
|
||||
import { CustomButtonSecondary } from './CustomButtonSecondary'
|
||||
import 'material-symbols/outlined.css'
|
||||
|
||||
|
@ -10,7 +9,7 @@ export const SettingsOPMLExport: FC = () => {
|
|||
|
||||
const downloadOPML = (exportType: string) => {
|
||||
axios({
|
||||
url: apiURL + '/settings/opml/' + exportType,
|
||||
url: '/settings/opml/' + exportType,
|
||||
method: 'GET',
|
||||
responseType: 'blob'
|
||||
}).then((response) => {
|
||||
|
|
|
@ -3,7 +3,6 @@ import { useTranslation } from 'react-i18next'
|
|||
import axios from 'axios'
|
||||
import { enqueueSnackbar } from 'notistack'
|
||||
import useCommon, { Podcast} from '../store/CommonSlice'
|
||||
import { apiURL } from '../utils/Utilities'
|
||||
import { CustomButtonSecondary } from './CustomButtonSecondary'
|
||||
import useModal from "../store/ModalSlice";
|
||||
|
||||
|
@ -18,7 +17,7 @@ export const SettingsPodcastDelete: FC = () => {
|
|||
|
||||
useEffect(() => {
|
||||
if (podcasts.length === 0) {
|
||||
axios.get(apiURL + '/podcasts')
|
||||
axios.get('/podcasts')
|
||||
.then((v) => {
|
||||
setPodcasts(v.data)
|
||||
})
|
||||
|
@ -26,7 +25,7 @@ export const SettingsPodcastDelete: FC = () => {
|
|||
}, [])
|
||||
|
||||
const deletePodcast = (withFiles: boolean, podcast_id: number, p: Podcast) => {
|
||||
axios.delete(apiURL + '/podcast/' + podcast_id, { data: { delete_files: withFiles }})
|
||||
axios.delete( '/podcast/' + podcast_id, { data: { delete_files: withFiles }})
|
||||
.then(() => {
|
||||
enqueueSnackbar(t('podcast-deleted', { name: p.name }), { variant: 'success' })
|
||||
podcastDeleted(podcast_id)
|
||||
|
|
|
@ -2,10 +2,8 @@ import { FC } from 'react'
|
|||
import { Waypoint } from 'react-waypoint'
|
||||
import axios, { AxiosResponse } from 'axios'
|
||||
import useCommon from '../store/CommonSlice'
|
||||
import { apiURL } from '../utils/Utilities'
|
||||
import { TimelineHATEOASModel, TimeLineModel } from '../models/TimeLineModel'
|
||||
import { EpisodeCard } from './EpisodeCard'
|
||||
import {PodcastWatchedModel} from "../models/PodcastWatchedModel";
|
||||
import {Episode} from "../models/Episode";
|
||||
|
||||
type TimelineEpisodeProps = {
|
||||
|
@ -28,7 +26,7 @@ export const TimelineEpisode: FC<TimelineEpisodeProps> = ({ podcastEpisode,podca
|
|||
{/*Infinite scroll */
|
||||
timeLineEpisodes.data.length === index + 1 &&
|
||||
<Waypoint key={index + 'waypoint'} onEnter={() => {
|
||||
axios.get(apiURL + '/podcasts/timeline', {
|
||||
axios.get('/podcasts/timeline', {
|
||||
params:{
|
||||
lastTimestamp: podcastEpisode.podcast_episode.date_of_recording,
|
||||
favoredOnly: useCommon.getState().filters?.onlyFavored,
|
||||
|
|
|
@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'
|
|||
import axios from 'axios'
|
||||
import { useSnackbar } from 'notistack'
|
||||
import useCommon from '../store/CommonSlice'
|
||||
import { apiURL, formatTime } from '../utils/Utilities'
|
||||
import {formatTime } from '../utils/Utilities'
|
||||
import { CreateInviteModal } from './CreateInviteModal'
|
||||
import { CustomButtonPrimary } from './CustomButtonPrimary'
|
||||
import { CustomSelect, Option } from './CustomSelect'
|
||||
|
@ -75,7 +75,7 @@ export const UserAdminInvites = () => {
|
|||
}, [invites, selectedInviteType])
|
||||
|
||||
useEffect(() => {
|
||||
axios.get(apiURL + '/users/invites')
|
||||
axios.get( '/users/invites')
|
||||
.then(v => {
|
||||
setInvites(v.data)
|
||||
setError(false)
|
||||
|
@ -139,7 +139,7 @@ export const UserAdminInvites = () => {
|
|||
<tr className="border-b border-[--border-color]" key={i.id}>
|
||||
<td className="pr-2 py-4">
|
||||
<button className="text-left text-[--fg-color] hover:text-[--fg-color-hover]" onClick={() => {
|
||||
axios.get(apiURL + '/users/invites/' + i.id + '/link')
|
||||
axios.get( '/users/invites/' + i.id + '/link')
|
||||
.then(v => {
|
||||
navigator.clipboard.writeText(v.data)
|
||||
.then(()=>enqueueSnackbar(t('invite-link-copied'), { autoHideDuration: 2000 }))
|
||||
|
@ -168,7 +168,7 @@ export const UserAdminInvites = () => {
|
|||
</td>
|
||||
<td className="pl-2 py-4">
|
||||
<button className="flex items-center float-right text-[--danger-fg-color] hover:text-[--danger-fg-color-hover]" onClick={() => {
|
||||
axios.delete(apiURL + '/users/invites/' + i.id)
|
||||
axios.delete( '/users/invites/' + i.id)
|
||||
.then(() => {
|
||||
enqueueSnackbar(t('invite-deleted'), { variant: 'success' })
|
||||
setInvites(invites.filter(v => v.id !== i.id))
|
||||
|
|
|
@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'
|
|||
import axios from 'axios'
|
||||
import { useSnackbar } from 'notistack'
|
||||
import useCommon from '../store/CommonSlice'
|
||||
import { apiURL, formatTime} from '../utils/Utilities'
|
||||
import { formatTime} from '../utils/Utilities'
|
||||
import { User } from '../models/User'
|
||||
import { ChangeRoleModal } from './ChangeRoleModal'
|
||||
import { Loading } from './Loading'
|
||||
|
@ -21,7 +21,7 @@ export const UserAdminUsers = () => {
|
|||
const setModalOpen = useModal(state => state.setOpenModal)
|
||||
|
||||
useEffect(() => {
|
||||
axios.get(apiURL + '/users')
|
||||
axios.get( '/users')
|
||||
.then(c => {
|
||||
setUsers(c.data)
|
||||
setError(false)
|
||||
|
@ -30,7 +30,7 @@ export const UserAdminUsers = () => {
|
|||
}, [])
|
||||
|
||||
const deleteUser = (user: User) => {
|
||||
axios.delete(apiURL + '/users/' + user.username)
|
||||
axios.delete( '/users/' + user.username)
|
||||
.then(() => {
|
||||
enqueueSnackbar(t('user-deleted'), { variant: 'success' })
|
||||
setUsers(users.filter(u => u.username !== user.username))
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import "./utils/navigationUtils"
|
||||
import React, { FC, PropsWithChildren, useEffect } from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import { I18nextProvider } from 'react-i18next'
|
||||
|
@ -8,7 +9,6 @@ import { SnackbarProvider } from 'notistack'
|
|||
import { router } from './App'
|
||||
import useCommon from './store/CommonSlice'
|
||||
import i18n from './language/i18n'
|
||||
import { apiURL } from './utils/Utilities'
|
||||
import { ConfigModel } from './models/SysInfo'
|
||||
import { Loading } from './components/Loading'
|
||||
import { OIDCRefresher } from './components/OIDCRefresher'
|
||||
|
@ -24,13 +24,24 @@ import '@fontsource/poppins/700.css'
|
|||
import '@fontsource/poppins/700-italic.css'
|
||||
import './index.css'
|
||||
import './assets/scss/style.scss'
|
||||
export let apiURL: string
|
||||
export let uiURL: string
|
||||
if (window.location.pathname.startsWith("/ui")) {
|
||||
apiURL = window.location.protocol + "//" + window.location.hostname + ":" + window.location.port + "/api/v1"
|
||||
} else {
|
||||
//match everything before /ui
|
||||
const regex = /\/([^/]+)\/ui\//
|
||||
apiURL = window.location.protocol + "//" + window.location.hostname + ":" + window.location.port + "/" + regex.exec(window.location.href)![1] + "/api/v1"
|
||||
}
|
||||
uiURL = window.location.protocol + "//" + window.location.hostname + ":" + window.location.port + "/ui"
|
||||
|
||||
const AuthWrapper: FC<PropsWithChildren> = ({ children }) => {
|
||||
const configModel = useCommon(state => state.configModel)
|
||||
const setConfigModel = useCommon(state => state.setConfigModel)
|
||||
|
||||
useEffect(() => {
|
||||
axios.get(apiURL + '/sys/config').then((v: AxiosResponse<ConfigModel>) => {
|
||||
axios.defaults.baseURL = apiURL
|
||||
axios.get('/sys/config').then((v: AxiosResponse<ConfigModel>) => {
|
||||
setConfigModel(v.data)
|
||||
})
|
||||
}, [])
|
||||
|
|
|
@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next'
|
|||
import { useNavigate, useParams } from 'react-router-dom'
|
||||
import axios from 'axios'
|
||||
import { enqueueSnackbar } from 'notistack'
|
||||
import { apiURL, formatTime } from '../utils/Utilities'
|
||||
import { formatTime } from '../utils/Utilities'
|
||||
import { CustomButtonPrimary } from '../components/CustomButtonPrimary'
|
||||
import { CustomInput } from '../components/CustomInput'
|
||||
import { Heading2 } from '../components/Heading2'
|
||||
|
@ -29,7 +29,7 @@ export const AcceptInvite = () => {
|
|||
}
|
||||
|
||||
useEffect(() => {
|
||||
axios.get(apiURL + '/users/invites/' + params.id)
|
||||
axios.get( '/users/invites/' + params.id)
|
||||
.then((res) => {
|
||||
setInvite(res.data)
|
||||
})
|
||||
|
@ -43,7 +43,7 @@ export const AcceptInvite = () => {
|
|||
}
|
||||
|
||||
const onSubmit: SubmitHandler<LoginData> = (data) => {
|
||||
axios.post(apiURL + '/users/', {
|
||||
axios.post( '/users/', {
|
||||
username: data.username,
|
||||
password: data.password,
|
||||
inviteId: params.id
|
||||
|
|
|
@ -2,7 +2,6 @@ import { useEffect, useState } from 'react'
|
|||
import { Link } from 'react-router-dom'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import axios from 'axios'
|
||||
import { apiURL} from '../utils/Utilities'
|
||||
import { PodcastWatchedEpisodeModel } from '../models/PodcastWatchedEpisodeModel'
|
||||
import { TimeLineModel, TimelineHATEOASModel } from '../models/TimeLineModel'
|
||||
import { EpisodeCard } from '../components/EpisodeCard'
|
||||
|
@ -15,12 +14,12 @@ export const Homepage = () => {
|
|||
const { t } = useTranslation()
|
||||
|
||||
useEffect(()=>{
|
||||
axios.get<PodcastWatchedEpisodeModel[]>(apiURL + '/podcast/episode/lastwatched')
|
||||
axios.get<PodcastWatchedEpisodeModel[]>('/podcast/episode/lastwatched')
|
||||
.then((response) => {
|
||||
setPodcastWatched(response.data)
|
||||
})
|
||||
|
||||
axios.get<TimelineHATEOASModel>(apiURL + '/podcasts/timeline', {
|
||||
axios.get<TimelineHATEOASModel>('/podcasts/timeline', {
|
||||
params: {
|
||||
favoredOnly: false,
|
||||
notListened: false
|
||||
|
|
|
@ -4,7 +4,6 @@ import { useTranslation } from 'react-i18next'
|
|||
import { useNavigate } from 'react-router-dom'
|
||||
import axios, { AxiosError } from 'axios'
|
||||
import useCommon from '../store/CommonSlice'
|
||||
import { apiURL } from '../utils/Utilities'
|
||||
import { CustomButtonPrimary } from '../components/CustomButtonPrimary'
|
||||
import { CustomCheckbox } from '../components/CustomCheckbox'
|
||||
import { CustomInput } from '../components/CustomInput'
|
||||
|
@ -36,7 +35,7 @@ export const Login = () => {
|
|||
const onSubmit: SubmitHandler<LoginData> = (data, p) => {
|
||||
p?.preventDefault()
|
||||
|
||||
axios.post(apiURL + '/login', data)
|
||||
axios.post('/login', data)
|
||||
.then(() => {
|
||||
const basicAuthString = btoa(data.username + ':' + data.password)
|
||||
|
||||
|
|
|
@ -3,12 +3,11 @@ import {PodcastDetailItem} from "../components/PodcastDetailItem";
|
|||
import {useTranslation} from "react-i18next";
|
||||
import {useParams} from "react-router-dom";
|
||||
import axios, {AxiosResponse} from "axios";
|
||||
import {apiURL, prepareOnlinePodcastEpisode, preparePodcastEpisode} from "../utils/Utilities";
|
||||
import {prepareOnlinePodcastEpisode, preparePodcastEpisode} from "../utils/Utilities";
|
||||
import {PlaylistDto} from "../models/Playlist";
|
||||
import usePlaylist from "../store/PlaylistSlice";
|
||||
import {useEffect} from "react";
|
||||
import useAudioPlayer from "../store/AudioPlayerSlice";
|
||||
import {PodcastWatchedModel} from "../models/PodcastWatchedModel";
|
||||
import {PodcastInfoModal} from "../components/PodcastInfoModal";
|
||||
import {PodcastEpisodeAlreadyPlayed} from "../components/PodcastEpisodeAlreadyPlayed";
|
||||
import {Episode} from "../models/Episode";
|
||||
|
@ -26,14 +25,14 @@ export const PlaylistDetailPage = ()=>{
|
|||
useEffect(() => {
|
||||
if(metadata){
|
||||
if(metadata.percentage>99){
|
||||
axios.delete(apiURL+"/playlist/"+params.id+"/episode/"+current_podcast_episode!.id)
|
||||
axios.delete("/playlist/"+params.id+"/episode/"+current_podcast_episode!.id)
|
||||
.then(()=>{
|
||||
const currentIndex = selectedPlaylist!.items.findIndex(i=>i.podcastEpisode.id===current_podcast_episode!.id)
|
||||
if(currentIndex === selectedPlaylist!.items.length-1){
|
||||
return
|
||||
}
|
||||
const nextEpisode = selectedPlaylist!.items[currentIndex+1]
|
||||
axios.get(apiURL + "/podcast/episode/" + nextEpisode.podcastEpisode.episode_id)
|
||||
axios.get("/podcast/episode/" + nextEpisode.podcastEpisode.episode_id)
|
||||
.then((response: AxiosResponse<Episode>) => {
|
||||
nextEpisode.podcastEpisode.status === 'D'
|
||||
? setCurrentPodcastEpisode(preparePodcastEpisode(nextEpisode.podcastEpisode, response.data))
|
||||
|
@ -54,7 +53,7 @@ export const PlaylistDetailPage = ()=>{
|
|||
|
||||
|
||||
useEffect(()=>{
|
||||
axios.get(apiURL+"/playlist/"+params.id)
|
||||
axios.get("/playlist/"+params.id)
|
||||
.then((response:AxiosResponse<PlaylistDto>)=>{
|
||||
setSelectedPlaylist(response.data)
|
||||
})
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import {CustomButtonPrimary} from "../components/CustomButtonPrimary";
|
||||
import axios, {AxiosResponse} from "axios";
|
||||
import {apiURL} from "../utils/Utilities";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {enqueueSnackbar} from "notistack";
|
||||
import usePlaylist from "../store/PlaylistSlice";
|
||||
|
@ -19,7 +18,7 @@ export const PlaylistPage = ()=>{
|
|||
|
||||
useEffect(()=>{
|
||||
if (playlist.length ===0){
|
||||
axios.get(apiURL+"/playlist").then((response:AxiosResponse<PlaylistDto[]>)=>{
|
||||
axios.get("/playlist").then((response:AxiosResponse<PlaylistDto[]>)=>{
|
||||
setPlaylist(response.data)
|
||||
})
|
||||
}
|
||||
|
@ -58,7 +57,7 @@ export const PlaylistPage = ()=>{
|
|||
<button className="flex ml-2" onClick={(e)=>{
|
||||
e.preventDefault()
|
||||
|
||||
axios.get(apiURL+"/playlist/"+i.id).then((response:AxiosResponse<PlaylistDto>)=> {
|
||||
axios.get("/playlist/"+i.id).then((response:AxiosResponse<PlaylistDto>)=> {
|
||||
setCurrentPlaylistToEdit(response.data)
|
||||
setCreatePlaylistOpen(true)
|
||||
})
|
||||
|
@ -80,7 +79,7 @@ export const PlaylistPage = ()=>{
|
|||
</button>
|
||||
<button className="flex float-right text-red-700 hover:text-red-500" onClick={(e)=>{
|
||||
e.preventDefault()
|
||||
axios.delete(apiURL+"/playlist/"+i.id).then(()=>{
|
||||
axios.delete("/playlist/"+i.id).then(()=>{
|
||||
enqueueSnackbar(t('invite-deleted'), {variant: "success"})
|
||||
setPlaylist(playlist.filter(v=>v.id !== i.id))
|
||||
})
|
||||
|
|
|
@ -2,7 +2,7 @@ import {Fragment, useEffect, useState} from 'react'
|
|||
import {useParams} from 'react-router-dom'
|
||||
import {useTranslation} from 'react-i18next'
|
||||
import axios, {AxiosResponse} from 'axios'
|
||||
import {apiURL, prependAPIKeyOnAuthEnabled, removeHTML} from '../utils/Utilities'
|
||||
import {prependAPIKeyOnAuthEnabled, removeHTML} from '../utils/Utilities'
|
||||
import useCommon, {Podcast} from '../store/CommonSlice'
|
||||
import useAudioPlayer from '../store/AudioPlayerSlice'
|
||||
import {Chip} from '../components/Chip'
|
||||
|
@ -33,10 +33,10 @@ export const PodcastDetailPage = () => {
|
|||
setCurrentDetailedPodcastId(Number(params.id))
|
||||
}
|
||||
|
||||
axios.get(apiURL + '/podcast/' + params.id).then((response: AxiosResponse<Podcast>) => {
|
||||
axios.get('/podcast/' + params.id).then((response: AxiosResponse<Podcast>) => {
|
||||
setCurrentPodcast(response.data)
|
||||
}).then(() => {
|
||||
axios.get(apiURL + '/podcast/' + params.id + '/episodes')
|
||||
axios.get('/podcast/' + params.id + '/episodes')
|
||||
.then((response: AxiosResponse<EpisodesWithOptionalTimeline[]>) => {
|
||||
setSelectedEpisodes(response.data)
|
||||
|
||||
|
@ -127,7 +127,7 @@ export const PodcastDetailPage = () => {
|
|||
<span
|
||||
className="material-symbols-outlined inline cursor-pointer align-middle text-[--fg-icon-color] hover:text-[--fg-icon-color-hover]"
|
||||
onClick={() => {
|
||||
axios.post(apiURL + '/podcast/' + params.id + '/refresh')
|
||||
axios.post('/podcast/' + params.id + '/refresh')
|
||||
.then(() => {
|
||||
console.log('Refreshed')
|
||||
})
|
||||
|
@ -176,7 +176,7 @@ export const PodcastDetailPage = () => {
|
|||
<span className="text-xs text-[--fg-secondary-color]">{t('active')}</span>
|
||||
|
||||
<Switcher checked={currentPodcast.active} setChecked={() => {
|
||||
axios.put(apiURL + '/podcast/' + params.id + '/active')
|
||||
axios.put('/podcast/' + params.id + '/active')
|
||||
.then(() => {
|
||||
setCurrentPodcast({...currentPodcast, active: !currentPodcast?.active})
|
||||
})
|
||||
|
|
|
@ -4,7 +4,6 @@ import { useTranslation } from 'react-i18next'
|
|||
import axios, { AxiosResponse } from 'axios'
|
||||
import { useDebounce } from '../utils/useDebounce'
|
||||
import {
|
||||
apiURL,
|
||||
getFiltersDefault,
|
||||
OrderCriteriaSortingType, TIME_ASCENDING, TIME_DESCENDING,
|
||||
TITLE_ASCENDING,
|
||||
|
@ -47,7 +46,7 @@ export const Podcasts: FC<PodcastsProps> = ({ onlyFavorites }) => {
|
|||
}, [filters])
|
||||
|
||||
const refreshAllPodcasts = () => {
|
||||
axios.post(apiURL + '/podcast/all')
|
||||
axios.post( '/podcast/all')
|
||||
}
|
||||
|
||||
const performFilter = () => {
|
||||
|
@ -55,7 +54,7 @@ export const Podcasts: FC<PodcastsProps> = ({ onlyFavorites }) => {
|
|||
return
|
||||
}
|
||||
|
||||
axios.get(apiURL + '/podcasts/search', {
|
||||
axios.get('/podcasts/search', {
|
||||
params: {
|
||||
title: filters?.title,
|
||||
order: filters?.ascending?Order.ASC:Order.DESC,
|
||||
|
@ -73,7 +72,7 @@ export const Podcasts: FC<PodcastsProps> = ({ onlyFavorites }) => {
|
|||
},500, [filters])
|
||||
|
||||
useEffect(() => {
|
||||
axios.get(apiURL + '/podcasts/filter')
|
||||
axios.get('/podcasts/filter')
|
||||
.then((c: AxiosResponse<Filter>) => {
|
||||
if (c.data === null) {
|
||||
setFilters(getFiltersDefault())
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { FC, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import axios, { AxiosResponse } from 'axios'
|
||||
import {apiURL, prependAPIKeyOnAuthEnabled} from '../utils/Utilities'
|
||||
import {prependAPIKeyOnAuthEnabled} from '../utils/Utilities'
|
||||
import { DiskModel } from '../models/DiskModel'
|
||||
import { SysExtraInfo } from '../models/SysExtraInfo'
|
||||
import { CustomGaugeChart } from '../components/CustomGaugeChart'
|
||||
|
@ -30,13 +30,13 @@ export const SystemInfoPage: FC = () => {
|
|||
const megaByte = Math.pow(10,6)
|
||||
|
||||
useEffect(() => {
|
||||
axios.get(apiURL + '/sys/info')
|
||||
axios.get('/sys/info')
|
||||
.then((response: AxiosResponse<SysExtraInfo>) => setSystemInfo(response.data))
|
||||
axios.get(apiURL + '/info')
|
||||
axios.get('/info')
|
||||
.then(c => setVersionInfo(c.data))
|
||||
|
||||
const updateInterval = setInterval(() => {
|
||||
axios.get(apiURL + '/sys/info')
|
||||
axios.get('/sys/info')
|
||||
.then((response: AxiosResponse<SysExtraInfo>) => setSystemInfo(response.data))
|
||||
}, 5000)
|
||||
return () => clearInterval(updateInterval)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {Fragment, useEffect, useState} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import axios, { AxiosResponse } from 'axios'
|
||||
import { apiURL, formatTime, getFiltersDefault } from '../utils/Utilities'
|
||||
import { formatTime, getFiltersDefault } from '../utils/Utilities'
|
||||
import useCommon from '../store/CommonSlice'
|
||||
import { Filter } from '../models/Filter'
|
||||
import { TimelineHATEOASModel } from '../models/TimeLineModel'
|
||||
|
@ -20,7 +20,7 @@ export const Timeline = () => {
|
|||
|
||||
|
||||
useEffect(() => {
|
||||
!filter && axios.get(apiURL + '/podcasts/filter')
|
||||
!filter && axios.get( '/podcasts/filter')
|
||||
.then((filterAxiosResponse: AxiosResponse<Filter>) => {
|
||||
filterAxiosResponse.data == null && setFilters(getFiltersDefault())
|
||||
|
||||
|
@ -32,7 +32,7 @@ export const Timeline = () => {
|
|||
if (filter) {
|
||||
let favoredOnly = filter?.onlyFavored
|
||||
|
||||
axios.get(apiURL + '/podcasts/timeline', {
|
||||
axios.get('/podcasts/timeline', {
|
||||
params: {
|
||||
favoredOnly: favoredOnly === undefined ? false : favoredOnly,
|
||||
notListened: notListened
|
||||
|
|
|
@ -7,7 +7,6 @@ import {Controller, useForm} from "react-hook-form";
|
|||
import {CustomCheckbox} from "../components/CustomCheckbox";
|
||||
import {CustomButtonPrimary} from "../components/CustomButtonPrimary";
|
||||
import axios, {AxiosResponse} from "axios";
|
||||
import {apiURL} from "../utils/Utilities";
|
||||
import {v4} from "uuid";
|
||||
import {enqueueSnackbar} from "notistack";
|
||||
|
||||
|
@ -41,7 +40,7 @@ export const UserManagementPage: FC<UserManagementPageProps> = () => {
|
|||
if (data.password === '') {
|
||||
delete data.password
|
||||
}
|
||||
axios.put(apiURL+'/users/'+loggedInUser?.username, data)
|
||||
axios.put('/users/'+loggedInUser?.username, data)
|
||||
.then((c:AxiosResponse<LoggedInUser>)=>{
|
||||
useCommon.getState().setLoggedInUser(c.data)
|
||||
enqueueSnackbar(t('user-settings-updated'), {variant: 'success'})
|
||||
|
|
|
@ -2,7 +2,6 @@ import { useEffect } from 'react'
|
|||
import { Outlet, useNavigate } from 'react-router-dom'
|
||||
import axios from 'axios'
|
||||
import useCommon from '../store/CommonSlice'
|
||||
import { configWSUrl } from '../utils/Utilities'
|
||||
import App from '../App'
|
||||
import { AudioComponents } from '../components/AudioComponents'
|
||||
import { EpisodeSearchModal } from '../components/EpisodeSearchModal'
|
||||
|
@ -10,6 +9,7 @@ import { Header } from '../components/Header'
|
|||
import { Loading } from '../components/Loading'
|
||||
import { MainContentPanel } from '../components/MainContentPanel'
|
||||
import { Sidebar } from '../components/Sidebar'
|
||||
import {configWSUrl} from "../utils/navigationUtils";
|
||||
|
||||
export const Root = () => {
|
||||
const configModel = useCommon(state => state.configModel)
|
||||
|
|
|
@ -34,31 +34,6 @@ TimeAgo.addLocale(fr)
|
|||
export const SKIPPED_TIME = 30
|
||||
let timeago = new TimeAgo('en-US')
|
||||
|
||||
export let apiURL: string
|
||||
export let uiURL: string
|
||||
if (window.location.pathname.startsWith("/ui")) {
|
||||
apiURL = window.location.protocol + "//" + window.location.hostname + ":" + window.location.port + "/api/v1"
|
||||
} else {
|
||||
//match everything before /ui
|
||||
const regex = /\/([^/]+)\/ui\//
|
||||
apiURL = window.location.protocol + "//" + window.location.hostname + ":" + window.location.port + "/" + regex.exec(window.location.href)![1] + "/api/v1"
|
||||
}
|
||||
uiURL = window.location.protocol + "//" + window.location.hostname + ":" + window.location.port + "/ui"
|
||||
|
||||
const wsEndpoint = "ws"
|
||||
|
||||
export const configWSUrl = (url: string) => {
|
||||
if (url.startsWith("http")) {
|
||||
return url.replace("http", "ws") + wsEndpoint
|
||||
}
|
||||
return url.replace("https", "wss") + wsEndpoint
|
||||
}
|
||||
export const logCurrentPlaybackTime = (episodeId: string, timeInSeconds: number) => {
|
||||
axios.post(apiURL + "/podcast/episode", {
|
||||
podcastEpisodeId: episodeId,
|
||||
time: Number(timeInSeconds.toFixed(0))
|
||||
})
|
||||
}
|
||||
|
||||
export const formatTime = (isoDate: string) => {
|
||||
if(Number.isNaN(Date.parse(isoDate))) return ""
|
||||
|
@ -182,4 +157,8 @@ export const TITLE_DESCENDING:OrderCriteriaSortingType = {
|
|||
ascending: false
|
||||
}
|
||||
|
||||
export const decodeHTMLEntities = (() => { const textArea = document.createElement('textarea'); return (message: string): string => { textArea.innerHTML = message; return textArea.value; }; })();
|
||||
export const decodeHTMLEntities = (() => { const textArea = document.createElement('textarea');
|
||||
return (message: string): string => {
|
||||
textArea.innerHTML = message;
|
||||
return textArea.value;
|
||||
}; })();
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
import axios from "axios";
|
||||
|
||||
|
||||
|
||||
const wsEndpoint = "ws"
|
||||
|
||||
export const configWSUrl = (url: string) => {
|
||||
if (url.startsWith("http")) {
|
||||
return url.replace("http", "ws") + wsEndpoint
|
||||
}
|
||||
return url.replace("https", "wss") + wsEndpoint
|
||||
}
|
||||
export const logCurrentPlaybackTime = (episodeId: string, timeInSeconds: number) => {
|
||||
axios.post("/podcast/episode", {
|
||||
podcastEpisodeId: episodeId,
|
||||
time: Number(timeInSeconds.toFixed(0))
|
||||
})
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
import {describe, it, expect} from "vitest";
|
||||
import {decodeHTMLEntities} from "../src/utils/Utilities";
|
||||
|
||||
describe("Html code replacement", () => {
|
||||
it("should replace the html code", () => {
|
||||
const html = "<div>Pourquoi les ministres n'ont plus le droit d'utilisier</div>";
|
||||
const replacedHtml = decodeHTMLEntities(html);
|
||||
expect(replacedHtml).toBe("<div>Pourquoi les ministres n'ont plus le droit d'utilisier</div>");
|
||||
});
|
||||
})
|
Loading…
Reference in New Issue