mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Add build and web versions to dashboard
This commit is contained in:
parent
4a6efbe359
commit
1aabbae3a5
11 changed files with 95 additions and 39 deletions
|
@ -261,7 +261,11 @@ module.exports = {
|
||||||
'ServerNotifications': 'writable',
|
'ServerNotifications': 'writable',
|
||||||
'TaskButton': 'writable',
|
'TaskButton': 'writable',
|
||||||
'UserParentalControlPage': 'writable',
|
'UserParentalControlPage': 'writable',
|
||||||
'Windows': 'readonly'
|
'Windows': 'readonly',
|
||||||
|
// Build time definitions
|
||||||
|
__JF_BUILD_VERSION__: 'readonly',
|
||||||
|
__USE_SYSTEM_FONTS__: 'readonly',
|
||||||
|
__WEBPACK_SERVE__: 'readonly'
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
'@typescript-eslint/prefer-string-starts-ends-with': ['error']
|
'@typescript-eslint/prefer-string-starts-ends-with': ['error']
|
||||||
|
|
|
@ -3,15 +3,13 @@ import ListItemIcon from '@mui/material/ListItemIcon';
|
||||||
import ListItemText from '@mui/material/ListItemText';
|
import ListItemText from '@mui/material/ListItemText';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { useApi } from 'hooks/useApi';
|
|
||||||
import { useSystemInfo } from 'hooks/useSystemInfo';
|
import { useSystemInfo } from 'hooks/useSystemInfo';
|
||||||
import ListItemLink from 'components/ListItemLink';
|
import ListItemLink from 'components/ListItemLink';
|
||||||
|
|
||||||
import appIcon from 'assets/img/icon-transparent.png';
|
import appIcon from 'assets/img/icon-transparent.png';
|
||||||
|
|
||||||
const DrawerHeaderLink = () => {
|
const DrawerHeaderLink = () => {
|
||||||
const { api } = useApi();
|
const { data: systemInfo } = useSystemInfo();
|
||||||
const { data: systemInfo } = useSystemInfo(api);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ListItemLink to='/'>
|
<ListItemLink to='/'>
|
||||||
|
|
|
@ -8,16 +8,22 @@
|
||||||
<span class="material-icons chevron_right" aria-hidden="true"></span>
|
<span class="material-icons chevron_right" aria-hidden="true"></span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div class="paperList" style="padding: 1em;">
|
<div class="serverInfo paperList">
|
||||||
<p id="serverName"></p>
|
<div>${LabelServerName}</div>
|
||||||
<p id="versionNumber"></p>
|
<div id="serverName"></div>
|
||||||
|
<div>${LabelServerVersion}</div>
|
||||||
|
<div id="versionNumber"></div>
|
||||||
|
<div>${LabelWebVersion}</div>
|
||||||
|
<div id="webVersion"></div>
|
||||||
|
<div>${LabelBuildVersion}</div>
|
||||||
|
<div id="buildVersion"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="dashboardActionsContainer">
|
<div class="dashboardActionsContainer">
|
||||||
<button is="emby-button" type="button" class="raised btnRefresh">
|
<button is="emby-button" type="button" class="raised btnRefresh">
|
||||||
<span>${ButtonScanAllLibraries}</span>
|
<span>${ButtonScanAllLibraries}</span>
|
||||||
</button>
|
</button>
|
||||||
<button is="emby-button" type="button" id="btnRestartServer" class="raised hide" onclick="DashboardPage.restart(this);">
|
<button is="emby-button" type="button" id="btnRestartServer" class="raised" onclick="DashboardPage.restart(this);">
|
||||||
<span>${Restart}</span>
|
<span>${Restart}</span>
|
||||||
</button>
|
</button>
|
||||||
<button is="emby-button" type="button" id="btnShutdown" class="raised" onclick="DashboardPage.shutdown(this);">
|
<button is="emby-button" type="button" id="btnShutdown" class="raised" onclick="DashboardPage.shutdown(this);">
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import escapeHtml from 'escape-html';
|
import escapeHtml from 'escape-html';
|
||||||
|
|
||||||
import datetime from '../../scripts/datetime';
|
import datetime from '../../scripts/datetime';
|
||||||
import Events from '../../utils/events.ts';
|
import Events from '../../utils/events.ts';
|
||||||
import itemHelper from '../../components/itemHelper';
|
import itemHelper from '../../components/itemHelper';
|
||||||
|
@ -14,10 +15,6 @@ import imageLoader from '../../components/images/imageLoader';
|
||||||
import ActivityLog from '../../components/activitylog';
|
import ActivityLog from '../../components/activitylog';
|
||||||
import imageHelper from '../../utils/image';
|
import imageHelper from '../../utils/image';
|
||||||
import indicators from '../../components/indicators/indicators';
|
import indicators from '../../components/indicators/indicators';
|
||||||
import '../../components/listview/listview.scss';
|
|
||||||
import '../../elements/emby-button/emby-button';
|
|
||||||
import '../../styles/flexstyles.scss';
|
|
||||||
import '../../elements/emby-itemscontainer/emby-itemscontainer';
|
|
||||||
import taskButton from '../../scripts/taskbutton';
|
import taskButton from '../../scripts/taskbutton';
|
||||||
import Dashboard from '../../utils/dashboard';
|
import Dashboard from '../../utils/dashboard';
|
||||||
import ServerConnections from '../../components/ServerConnections';
|
import ServerConnections from '../../components/ServerConnections';
|
||||||
|
@ -25,6 +22,19 @@ import alert from '../../components/alert';
|
||||||
import confirm from '../../components/confirm/confirm';
|
import confirm from '../../components/confirm/confirm';
|
||||||
import { getDefaultBackgroundClass } from '../../components/cardbuilder/cardBuilderUtils';
|
import { getDefaultBackgroundClass } from '../../components/cardbuilder/cardBuilderUtils';
|
||||||
|
|
||||||
|
import { getSystemInfoQuery } from 'hooks/useSystemInfo';
|
||||||
|
import { toApi } from 'utils/jellyfin-apiclient/compat';
|
||||||
|
import { queryClient } from 'utils/query/queryClient';
|
||||||
|
|
||||||
|
import { version as WEB_VERSION } from '../../../package.json';
|
||||||
|
|
||||||
|
import '../../elements/emby-button/emby-button';
|
||||||
|
import '../../elements/emby-itemscontainer/emby-itemscontainer';
|
||||||
|
|
||||||
|
import '../../components/listview/listview.scss';
|
||||||
|
import '../../styles/flexstyles.scss';
|
||||||
|
import './dashboard.scss';
|
||||||
|
|
||||||
function showPlaybackInfo(btn, session) {
|
function showPlaybackInfo(btn, session) {
|
||||||
let title;
|
let title;
|
||||||
const text = [];
|
const text = [];
|
||||||
|
@ -199,22 +209,21 @@ function refreshActiveRecordings(view, apiClient) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function reloadSystemInfo(view, apiClient) {
|
function reloadSystemInfo(view, apiClient) {
|
||||||
apiClient.getSystemInfo().then(function (systemInfo) {
|
view.querySelector('#buildVersion').innerText = __JF_BUILD_VERSION__;
|
||||||
view.querySelector('#serverName').innerText = globalize.translate('DashboardServerName', systemInfo.ServerName);
|
view.querySelector('#webVersion').innerText = WEB_VERSION;
|
||||||
view.querySelector('#versionNumber').innerText = globalize.translate('DashboardVersionNumber', systemInfo.Version);
|
|
||||||
|
|
||||||
if (systemInfo.CanSelfRestart) {
|
queryClient
|
||||||
view.querySelector('#btnRestartServer').classList.remove('hide');
|
.fetchQuery(getSystemInfoQuery(toApi(apiClient)))
|
||||||
} else {
|
.then(systemInfo => {
|
||||||
view.querySelector('#btnRestartServer').classList.add('hide');
|
view.querySelector('#serverName').innerText = systemInfo.ServerName;
|
||||||
}
|
view.querySelector('#versionNumber').innerText = systemInfo.Version;
|
||||||
|
|
||||||
view.querySelector('#cachePath').innerText = systemInfo.CachePath;
|
view.querySelector('#cachePath').innerText = systemInfo.CachePath;
|
||||||
view.querySelector('#logPath').innerText = systemInfo.LogPath;
|
view.querySelector('#logPath').innerText = systemInfo.LogPath;
|
||||||
view.querySelector('#transcodePath').innerText = systemInfo.TranscodingTempPath;
|
view.querySelector('#transcodePath').innerText = systemInfo.TranscodingTempPath;
|
||||||
view.querySelector('#metadataPath').innerText = systemInfo.InternalMetadataPath;
|
view.querySelector('#metadataPath').innerText = systemInfo.InternalMetadataPath;
|
||||||
view.querySelector('#webPath').innerText = systemInfo.WebPath;
|
view.querySelector('#webPath').innerText = systemInfo.WebPath;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderInfo(view, sessions) {
|
function renderInfo(view, sessions) {
|
||||||
|
|
17
src/controllers/dashboard/dashboard.scss
Normal file
17
src/controllers/dashboard/dashboard.scss
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
.serverInfo {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 1em;
|
||||||
|
padding: 1em;
|
||||||
|
|
||||||
|
> *:nth-child(odd) {
|
||||||
|
flex: 1 0 20%;
|
||||||
|
min-width: 7.5em;
|
||||||
|
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
> *:nth-child(even) {
|
||||||
|
flex: 1 0 70%;
|
||||||
|
}
|
||||||
|
}
|
4
src/global.d.ts
vendored
4
src/global.d.ts
vendored
|
@ -14,4 +14,8 @@ export declare global {
|
||||||
interface DocumentEventMap {
|
interface DocumentEventMap {
|
||||||
'viewshow': CustomEvent;
|
'viewshow': CustomEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const __JF_BUILD_VERSION__: string;
|
||||||
|
const __USE_SYSTEM_FONTS__: string;
|
||||||
|
const __WEBPACK_SERVE__: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,21 +3,34 @@ import type { Api } from '@jellyfin/sdk';
|
||||||
import { getSystemApi } from '@jellyfin/sdk/lib/utils/api/system-api';
|
import { getSystemApi } from '@jellyfin/sdk/lib/utils/api/system-api';
|
||||||
import type { AxiosRequestConfig } from 'axios';
|
import type { AxiosRequestConfig } from 'axios';
|
||||||
|
|
||||||
|
import { useApi } from './useApi';
|
||||||
|
import { queryOptions } from 'utils/query/queryOptions';
|
||||||
|
|
||||||
const fetchSystemInfo = async (
|
const fetchSystemInfo = async (
|
||||||
api: Api | undefined,
|
api?: Api,
|
||||||
options: AxiosRequestConfig
|
options?: AxiosRequestConfig
|
||||||
) => {
|
) => {
|
||||||
if (!api) throw new Error('No API instance available');
|
if (!api) {
|
||||||
|
console.warn('[fetchSystemInfo] No API instance available');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const response = await getSystemApi(api)
|
const response = await getSystemApi(api)
|
||||||
.getSystemInfo(options);
|
.getSystemInfo(options);
|
||||||
return response.data;
|
return response.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useSystemInfo = (api: Api | undefined) => {
|
export const getSystemInfoQuery = (
|
||||||
return useQuery({
|
api?: Api
|
||||||
queryKey: [ 'SystemInfo' ],
|
) => queryOptions({
|
||||||
queryFn: ({ signal }) => fetchSystemInfo(api, { signal }),
|
queryKey: [ 'SystemInfo' ],
|
||||||
enabled: !!api
|
queryFn: ({ signal }) => fetchSystemInfo(api, { signal }),
|
||||||
});
|
// Allow for query reuse in legacy javascript.
|
||||||
|
staleTime: 1000, // 1 second
|
||||||
|
enabled: !!api
|
||||||
|
});
|
||||||
|
|
||||||
|
export const useSystemInfo = () => {
|
||||||
|
const { api } = useApi();
|
||||||
|
return useQuery(getSystemInfoQuery(api));
|
||||||
};
|
};
|
||||||
|
|
|
@ -94,7 +94,7 @@ function onGlobalizeInit() {
|
||||||
if (browser.tv && !browser.android) {
|
if (browser.tv && !browser.android) {
|
||||||
console.debug('using system fonts with explicit sizes');
|
console.debug('using system fonts with explicit sizes');
|
||||||
import('./styles/fonts.sized.scss');
|
import('./styles/fonts.sized.scss');
|
||||||
} else if (__USE_SYSTEM_FONTS__) { // eslint-disable-line no-undef
|
} else if (__USE_SYSTEM_FONTS__) {
|
||||||
console.debug('using system fonts');
|
console.debug('using system fonts');
|
||||||
import('./styles/fonts.scss');
|
import('./styles/fonts.scss');
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -35,7 +35,7 @@ export function getIncludeCorsCredentials() {
|
||||||
|
|
||||||
export function getMultiServer() {
|
export function getMultiServer() {
|
||||||
// Enable multi-server support when served by webpack
|
// Enable multi-server support when served by webpack
|
||||||
if (__WEBPACK_SERVE__) { // eslint-disable-line no-undef
|
if (__WEBPACK_SERVE__) {
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -167,8 +167,6 @@
|
||||||
"Cursive": "Cursive",
|
"Cursive": "Cursive",
|
||||||
"CustomDlnaProfilesHelp": "Create a custom profile to target a new device or override a system profile.",
|
"CustomDlnaProfilesHelp": "Create a custom profile to target a new device or override a system profile.",
|
||||||
"DailyAt": "Daily at {0}",
|
"DailyAt": "Daily at {0}",
|
||||||
"DashboardServerName": "Server: {0}",
|
|
||||||
"DashboardVersionNumber": "Version: {0}",
|
|
||||||
"Data": "Data",
|
"Data": "Data",
|
||||||
"DateAdded": "Date added",
|
"DateAdded": "Date added",
|
||||||
"DatePlayed": "Date played",
|
"DatePlayed": "Date played",
|
||||||
|
@ -582,6 +580,7 @@
|
||||||
"LabelBlastMessageInterval": "Alive message interval",
|
"LabelBlastMessageInterval": "Alive message interval",
|
||||||
"LabelBlastMessageIntervalHelp": "Determine the duration in seconds between blast alive messages.",
|
"LabelBlastMessageIntervalHelp": "Determine the duration in seconds between blast alive messages.",
|
||||||
"LabelBlockContentWithTags": "Block items with tags",
|
"LabelBlockContentWithTags": "Block items with tags",
|
||||||
|
"LabelBuildVersion": "Build version",
|
||||||
"LabelBurnSubtitles": "Burn subtitles",
|
"LabelBurnSubtitles": "Burn subtitles",
|
||||||
"LabelCache": "Cache",
|
"LabelCache": "Cache",
|
||||||
"LabelCachePath": "Cache path",
|
"LabelCachePath": "Cache path",
|
||||||
|
@ -869,6 +868,7 @@
|
||||||
"LabelServerHostHelp": "192.168.1.100:8096 or https://myserver.com",
|
"LabelServerHostHelp": "192.168.1.100:8096 or https://myserver.com",
|
||||||
"LabelServerName": "Server name",
|
"LabelServerName": "Server name",
|
||||||
"LabelServerNameHelp": "This name will be used to identify the server and will default to the server's hostname.",
|
"LabelServerNameHelp": "This name will be used to identify the server and will default to the server's hostname.",
|
||||||
|
"LabelServerVersion": "Server version",
|
||||||
"LabelSimultaneousConnectionLimit": "Simultaneous stream limit",
|
"LabelSimultaneousConnectionLimit": "Simultaneous stream limit",
|
||||||
"LabelSize": "Size",
|
"LabelSize": "Size",
|
||||||
"LabelSkipBackLength": "Skip back length",
|
"LabelSkipBackLength": "Skip back length",
|
||||||
|
@ -989,6 +989,7 @@
|
||||||
"LabelVideoRange": "Video range",
|
"LabelVideoRange": "Video range",
|
||||||
"LabelVideoResolution": "Video resolution",
|
"LabelVideoResolution": "Video resolution",
|
||||||
"LabelWeb": "Web",
|
"LabelWeb": "Web",
|
||||||
|
"LabelWebVersion": "Web version",
|
||||||
"LabelXDlnaCap": "Device Capability ID",
|
"LabelXDlnaCap": "Device Capability ID",
|
||||||
"LabelXDlnaCapHelp": "Determine the content of the 'X_DLNACAP' element in the 'urn:schemas-dlna-org:device-1-0' namespace.",
|
"LabelXDlnaCapHelp": "Determine the content of the 'X_DLNACAP' element in the 'urn:schemas-dlna-org:device-1-0' namespace.",
|
||||||
"LabelXDlnaDoc": "Device Class ID",
|
"LabelXDlnaDoc": "Device Class ID",
|
||||||
|
|
|
@ -47,6 +47,10 @@ const config = {
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new DefinePlugin({
|
new DefinePlugin({
|
||||||
|
__JF_BUILD_VERSION__: JSON.stringify(
|
||||||
|
process.env.WEBPACK_SERVE ?
|
||||||
|
'Dev Server' :
|
||||||
|
process.env.JELLYFIN_VERSION || 'Release'),
|
||||||
__USE_SYSTEM_FONTS__: JSON.stringify(!!process.env.USE_SYSTEM_FONTS),
|
__USE_SYSTEM_FONTS__: JSON.stringify(!!process.env.USE_SYSTEM_FONTS),
|
||||||
__WEBPACK_SERVE__: JSON.stringify(!!process.env.WEBPACK_SERVE)
|
__WEBPACK_SERVE__: JSON.stringify(!!process.env.WEBPACK_SERVE)
|
||||||
}),
|
}),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue