mirror of
https://github.com/BreizhHardware/Jellystat.git
synced 2026-01-18 16:27:20 +01:00
add external url settings
This commit is contained in:
@@ -312,6 +312,45 @@ router.post("/setconfig", async (req, res) => {
|
||||
console.log(error);
|
||||
}
|
||||
});
|
||||
|
||||
router.post("/setExternalUrl", async (req, res) => {
|
||||
try {
|
||||
const { ExternalUrl } = req.body;
|
||||
|
||||
if (ExternalUrl === undefined) {
|
||||
res.status(400);
|
||||
res.send("ExternalUrl is required for configuration");
|
||||
return;
|
||||
}
|
||||
|
||||
const config = await new configClass().getConfig();
|
||||
const validation = await API.validateSettings(ExternalUrl, config.JF_API_KEY);
|
||||
if (validation.isValid === false) {
|
||||
res.status(validation.status);
|
||||
res.send(validation);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const settings = config.settings || {};
|
||||
settings.EXTERNAL_URL = ExternalUrl;
|
||||
|
||||
const query = 'UPDATE app_config SET settings=$1 where "ID"=1';
|
||||
|
||||
await db.query(query, [settings]);
|
||||
config.settings = settings;
|
||||
res.send(config);
|
||||
} catch (error) {
|
||||
res.status(503);
|
||||
res.send({ error: "Error: " + error });
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
res.status(503);
|
||||
res.send({ error: "Error: " + error });
|
||||
}
|
||||
});
|
||||
|
||||
router.post("/setPreferredAdmin", async (req, res) => {
|
||||
try {
|
||||
const { userid, username } = req.body;
|
||||
|
||||
@@ -177,6 +177,7 @@
|
||||
"SIZE": "Size",
|
||||
"JELLYFIN_URL": "Jellyfin URL",
|
||||
"EMBY_URL": "Emby URL",
|
||||
"EXTERNAL_URL": "External URL",
|
||||
"API_KEY": "API Key",
|
||||
"API_KEYS": "API Keys",
|
||||
"KEY_NAME": "Key Name",
|
||||
|
||||
@@ -177,6 +177,7 @@
|
||||
"SIZE": "Taille",
|
||||
"JELLYFIN_URL": "URL du serveur Jellyfin",
|
||||
"EMBY_URL": "URL du serveur Emby",
|
||||
"EXTERNAL_URL": "External URL",
|
||||
"API_KEY": "Clé API",
|
||||
"API_KEYS": "Clés API",
|
||||
"KEY_NAME": "Nom de la clé",
|
||||
|
||||
@@ -177,6 +177,7 @@
|
||||
"SIZE": "大小",
|
||||
"JELLYFIN_URL": "Jellyfin URL",
|
||||
"EMBY_URL": "Emby URL",
|
||||
"EXTERNAL_URL": "External URL",
|
||||
"API_KEY": "API 密钥",
|
||||
"API_KEYS": "API 密钥",
|
||||
"KEY_NAME": "密钥名称",
|
||||
|
||||
@@ -257,7 +257,7 @@ function ItemInfo() {
|
||||
<Link
|
||||
className="px-2"
|
||||
to={
|
||||
config.hostUrl +
|
||||
(config.settings?.EXTERNAL_URL ?? config.hostUrl) +
|
||||
`/web/index.html#!/${config.IS_JELLYFIN ? "details" : "item"}?id=` +
|
||||
(data.EpisodeId || data.Id) +
|
||||
(config.settings.ServerID ? "&serverId=" + config.settings.ServerID : "")
|
||||
|
||||
@@ -71,7 +71,7 @@ function MoreItems(props) {
|
||||
<div className="last-played-container">
|
||||
|
||||
{data.sort((a,b) => a.IndexNumber-b.IndexNumber).map((item) => (
|
||||
<MoreItemCards data={item} base_url={config.hostUrl} key={item.Id}/>
|
||||
<MoreItemCards data={item} base_url={config.settings?.EXTERNAL_URL ?? config.hostUrl} key={item.Id}/>
|
||||
))}
|
||||
|
||||
</div>
|
||||
|
||||
@@ -62,7 +62,7 @@ function LibraryLastWatched(props) {
|
||||
<h1 className="my-3"><Trans i18nKey="LAST_WATCHED"/></h1>
|
||||
<div className="last-played-container">
|
||||
{data.map((item) => (
|
||||
<LastWatchedCard data={item} base_url={config.hostUrl} key={item.Id+item.SeasonNumber+item.EpisodeNumber}/>
|
||||
<LastWatchedCard data={item} base_url={config.settings?.EXTERNAL_URL ?? config.hostUrl} key={item.Id+item.SeasonNumber+item.EpisodeNumber}/>
|
||||
))}
|
||||
|
||||
</div>
|
||||
|
||||
@@ -212,7 +212,7 @@ function LibraryItems(props) {
|
||||
}
|
||||
})
|
||||
.map((item) => (
|
||||
<MoreItemCards data={item} base_url={config.hostUrl} key={item.Id + item.SeasonNumber + item.EpisodeNumber} />
|
||||
<MoreItemCards data={item} base_url={config.settings?.EXTERNAL_URL ?? config.hostUrl} key={item.Id + item.SeasonNumber + item.EpisodeNumber} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -26,9 +26,12 @@ export default function SettingsConfig() {
|
||||
const [selectedLanguage, setSelectedLanguage] = useState(localStorage.getItem("i18nextLng") ?? "en-US");
|
||||
const [showKey, setKeyState] = useState(false);
|
||||
const [formValues, setFormValues] = useState({});
|
||||
const [formValuesExternal, setFormValuesExternal] = useState({});
|
||||
const [isSubmitted, setisSubmitted] = useState("");
|
||||
const [isSubmittedExternal, setisSubmittedExternal] = useState("");
|
||||
const [loadSate, setloadSate] = useState("Loading");
|
||||
const [submissionMessage, setsubmissionMessage] = useState("");
|
||||
const [submissionMessageExternal, setsubmissionMessageExternal] = useState("");
|
||||
const token = localStorage.getItem("token");
|
||||
const [twelve_hr, set12hr] = useState(localStorage.getItem("12hr") === "true");
|
||||
|
||||
@@ -45,6 +48,7 @@ export default function SettingsConfig() {
|
||||
Config.getConfig()
|
||||
.then((config) => {
|
||||
setFormValues({ JF_HOST: config.hostUrl });
|
||||
setFormValuesExternal({ ExternalUrl: config.settings?.EXTERNAL_URL });
|
||||
setConfig(config);
|
||||
setSelectedAdmin(config.settings?.preferred_admin);
|
||||
setloadSate("Loaded");
|
||||
@@ -94,13 +98,42 @@ export default function SettingsConfig() {
|
||||
setisSubmitted("Failed");
|
||||
setsubmissionMessage(`Error Updating Configuration: ${errorMessage}`);
|
||||
});
|
||||
Config.setConfig();
|
||||
Config.setConfig();
|
||||
}
|
||||
|
||||
async function handleFormSubmitExternal(event) {
|
||||
event.preventDefault();
|
||||
|
||||
setisSubmittedExternal("");
|
||||
axios
|
||||
.post("/api/setExternalUrl/", formValuesExternal, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${config.token}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
})
|
||||
.then((response) => {
|
||||
console.log("Config updated successfully:", response.data);
|
||||
setisSubmittedExternal("Success");
|
||||
setsubmissionMessageExternal("Successfully updated configuration");
|
||||
})
|
||||
.catch((error) => {
|
||||
let errorMessage = error.response.data.errorMessage;
|
||||
console.log("Error updating config:", errorMessage);
|
||||
setisSubmittedExternal("Failed");
|
||||
setsubmissionMessageExternal(`Error Updating Configuration: ${errorMessage}`);
|
||||
});
|
||||
Config.setConfig();
|
||||
}
|
||||
|
||||
function handleFormChange(event) {
|
||||
setFormValues({ ...formValues, [event.target.name]: event.target.value });
|
||||
}
|
||||
|
||||
function handleFormChangeExternal(event) {
|
||||
setFormValuesExternal({ ...formValuesExternal, [event.target.name]: event.target.value });
|
||||
}
|
||||
|
||||
function updateAdmin(event) {
|
||||
const username = event.target.textContent;
|
||||
const userid = event.target.getAttribute("value");
|
||||
@@ -130,7 +163,7 @@ export default function SettingsConfig() {
|
||||
setisSubmitted("Failed");
|
||||
setsubmissionMessage("Error Updating Configuration: ", error);
|
||||
});
|
||||
Config.setConfig();
|
||||
Config.setConfig();
|
||||
}
|
||||
|
||||
function updateLanguage(event) {
|
||||
@@ -160,8 +193,11 @@ export default function SettingsConfig() {
|
||||
<Form onSubmit={handleFormSubmit} className="settings-form">
|
||||
<Form.Group as={Row} className="mb-3">
|
||||
<Form.Label column className="">
|
||||
{config.settings?.IS_JELLYFIN ? <Trans i18nKey={"SETTINGS_PAGE.JELLYFIN_URL"} /> : <Trans i18nKey={"SETTINGS_PAGE.EMBY_URL"} /> }
|
||||
|
||||
{config.settings?.IS_JELLYFIN ? (
|
||||
<Trans i18nKey={"SETTINGS_PAGE.JELLYFIN_URL"} />
|
||||
) : (
|
||||
<Trans i18nKey={"SETTINGS_PAGE.EMBY_URL"} />
|
||||
)}
|
||||
</Form.Label>
|
||||
<Col sm="10">
|
||||
<Form.Control
|
||||
@@ -208,6 +244,39 @@ export default function SettingsConfig() {
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
|
||||
<Form onSubmit={handleFormSubmitExternal} className="settings-form">
|
||||
<Form.Group as={Row} className="mb-3">
|
||||
<Form.Label column className="">
|
||||
<Trans i18nKey={"SETTINGS_PAGE.EXTERNAL_URL"} />
|
||||
</Form.Label>
|
||||
<Col sm="10">
|
||||
<Form.Control
|
||||
id="ExternalUrl"
|
||||
name="ExternalUrl"
|
||||
value={formValuesExternal.ExternalUrl || ""}
|
||||
onChange={handleFormChangeExternal}
|
||||
placeholder="http://example.jellyfin.server"
|
||||
/>
|
||||
</Col>
|
||||
</Form.Group>
|
||||
|
||||
{isSubmittedExternal !== "" ? (
|
||||
isSubmittedExternal === "Failed" ? (
|
||||
<Alert variant="danger">{submissionMessageExternal}</Alert>
|
||||
) : (
|
||||
<Alert variant="success">{submissionMessageExternal}</Alert>
|
||||
)
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
<div className="d-flex flex-column flex-md-row justify-content-end align-items-md-center">
|
||||
<Button variant="outline-success" type="submit">
|
||||
<Trans i18nKey={"SETTINGS_PAGE.UPDATE"} />
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
|
||||
<Form className="settings-form">
|
||||
<Form.Group as={Row} className="mb-3">
|
||||
<Form.Label column className="">
|
||||
|
||||
@@ -76,7 +76,7 @@ function MPMovies(props) {
|
||||
}
|
||||
|
||||
return (
|
||||
<ItemStatComponent base_url={config.hostUrl} data={data} heading={<Trans i18nKey="STAT_CARDS.MOST_POPULAR_MOVIES" />} units={<Trans i18nKey="USERS" />}/>
|
||||
<ItemStatComponent base_url={config.settings?.EXTERNAL_URL ?? config.hostUrl} data={data} heading={<Trans i18nKey="STAT_CARDS.MOST_POPULAR_MOVIES" />} units={<Trans i18nKey="USERS" />}/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ function MPMusic(props) {
|
||||
|
||||
|
||||
return (
|
||||
<ItemStatComponent base_url={config.hostUrl} data={data} heading={<Trans i18nKey="STAT_CARDS.MOST_POPULAR_MUSIC" />} units={<Trans i18nKey="USERS" />} isAudio={true}/>
|
||||
<ItemStatComponent base_url={config.settings?.EXTERNAL_URL ?? config.hostUrl} data={data} heading={<Trans i18nKey="STAT_CARDS.MOST_POPULAR_MUSIC" />} units={<Trans i18nKey="USERS" />} isAudio={true}/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ function MPSeries(props) {
|
||||
|
||||
|
||||
return (
|
||||
<ItemStatComponent base_url={config.hostUrl} data={data} heading={<Trans i18nKey="STAT_CARDS.MOST_POPULAR_SERIES" />} units={<Trans i18nKey="USERS" />}/>
|
||||
<ItemStatComponent base_url={config.settings?.EXTERNAL_URL ?? config.hostUrl} data={data} heading={<Trans i18nKey="STAT_CARDS.MOST_POPULAR_SERIES" />} units={<Trans i18nKey="USERS" />}/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ function MVMusic(props) {
|
||||
|
||||
|
||||
return (
|
||||
<ItemStatComponent base_url={config.hostUrl} data={data} heading={<Trans i18nKey="STAT_CARDS.MOST_VIEWED_MOVIES" />} units={<Trans i18nKey="UNITS.PLAYS" />}/>
|
||||
<ItemStatComponent base_url={config.settings?.EXTERNAL_URL ?? config.hostUrl} data={data} heading={<Trans i18nKey="STAT_CARDS.MOST_VIEWED_MOVIES" />} units={<Trans i18nKey="UNITS.PLAYS" />}/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ function MVMovies(props) {
|
||||
|
||||
|
||||
return (
|
||||
<ItemStatComponent base_url={config.hostUrl} data={data} heading={<Trans i18nKey="STAT_CARDS.MOST_LISTENED_MUSIC" />} units={<Trans i18nKey="UNITS.PLAYS" />} isAudio={true}/>
|
||||
<ItemStatComponent base_url={config.settings?.EXTERNAL_URL ?? config.hostUrl} data={data} heading={<Trans i18nKey="STAT_CARDS.MOST_LISTENED_MUSIC" />} units={<Trans i18nKey="UNITS.PLAYS" />} isAudio={true}/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ function MVSeries(props) {
|
||||
|
||||
|
||||
return (
|
||||
<ItemStatComponent base_url={config.hostUrl} data={data} heading={<Trans i18nKey="STAT_CARDS.MOST_VIEWED_SERIES" />} units={<Trans i18nKey="UNITS.PLAYS" />}/>
|
||||
<ItemStatComponent base_url={config.settings?.EXTERNAL_URL ?? config.hostUrl} data={data} heading={<Trans i18nKey="STAT_CARDS.MOST_VIEWED_SERIES" />} units={<Trans i18nKey="UNITS.PLAYS" />}/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ function PlaybackMethodStats(props) {
|
||||
|
||||
return (
|
||||
<ItemStatComponent
|
||||
base_url={config.hostUrl}
|
||||
base_url={config.settings?.EXTERNAL_URL ?? config.hostUrl}
|
||||
data={data.map((stream) =>
|
||||
stream.Name == "DirectPlay" ? { ...stream, Name: translations.DirectPlay } : { ...stream, Name: translations.Transocde }
|
||||
)}
|
||||
|
||||
@@ -67,7 +67,7 @@ function LastPlayed(props) {
|
||||
<div className="last-played-container">
|
||||
{data.map((item, index) => (
|
||||
<ErrorBoundary key={item.Id + item.EpisodeNumber + index}>
|
||||
<LastWatchedCard data={item} base_url={config.hostUrl} />
|
||||
<LastWatchedCard data={item} base_url={config.settings?.EXTERNAL_URL ?? config.hostUrl} />
|
||||
</ErrorBoundary>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -107,7 +107,11 @@ function Libraries() {
|
||||
.sort((a, b) => a.Name - b.Name)
|
||||
.map((item) => (
|
||||
<ErrorBoundary key={item.Id}>
|
||||
<LibraryCard data={item} metadata={metadata.find((data) => data.Id === item.Id)} base_url={config.hostUrl} />
|
||||
<LibraryCard
|
||||
data={item}
|
||||
metadata={metadata.find((data) => data.Id === item.Id)}
|
||||
base_url={config.settings?.EXTERNAL_URL ?? config.hostUrl}
|
||||
/>
|
||||
</ErrorBoundary>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -75,7 +75,7 @@ function LibrarySelector() {
|
||||
{data &&
|
||||
data.map((item) => (
|
||||
<ErrorBoundary key={item.Id}>
|
||||
<SelectionCard data={item} base_url={config.hostUrl} />
|
||||
<SelectionCard data={item} base_url={config.settings?.EXTERNAL_URL ?? config.hostUrl} />
|
||||
</ErrorBoundary>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -454,7 +454,7 @@ function Users() {
|
||||
<EnhancedTableHead order={order} orderBy={orderBy} onRequestSort={handleRequestSort} rowCount={rowsPerPage} />
|
||||
<TableBody>
|
||||
{filteredData.map((row) => (
|
||||
<Row key={row.UserId} data={row} updateTrackedState={updateTrackedState} hostUrl={config.hostUrl} />
|
||||
<Row key={row.UserId} data={row} updateTrackedState={updateTrackedState} hostUrl={config.settings?.EXTERNAL_URL ?? config.hostUrl} />
|
||||
))}
|
||||
{data.length === 0 ? (
|
||||
<tr>
|
||||
|
||||
Reference in New Issue
Block a user