mirror of
https://github.com/sct/overseerr.git
synced 2025-09-17 17:24:35 +02:00
feat: status checker to prompt users to reload their frontend when app version changes
This commit is contained in:
@@ -1,4 +1,7 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
|
env: {
|
||||||
|
commitTag: process.env.COMMIT_TAG || 'local',
|
||||||
|
},
|
||||||
webpack(config) {
|
webpack(config) {
|
||||||
config.module.rules.push({
|
config.module.rules.push({
|
||||||
test: /\.svg$/,
|
test: /\.svg$/,
|
||||||
|
@@ -1102,6 +1102,26 @@ components:
|
|||||||
name: X-Api-Key
|
name: X-Api-Key
|
||||||
|
|
||||||
paths:
|
paths:
|
||||||
|
/status:
|
||||||
|
get:
|
||||||
|
summary: Return Overseerr version
|
||||||
|
description: Returns the current Overseerr version in JSON format
|
||||||
|
security: []
|
||||||
|
tags:
|
||||||
|
- public
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Returned version
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
version:
|
||||||
|
type: string
|
||||||
|
example: 1.0.0
|
||||||
|
commitTag:
|
||||||
|
type: string
|
||||||
/settings/main:
|
/settings/main:
|
||||||
get:
|
get:
|
||||||
summary: Returns main settings
|
summary: Returns main settings
|
||||||
|
@@ -171,7 +171,7 @@
|
|||||||
[
|
[
|
||||||
"@semantic-release/exec",
|
"@semantic-release/exec",
|
||||||
{
|
{
|
||||||
"prepareCmd": "docker build -t sctx/overseerr ."
|
"prepareCmd": "docker build --build-arg COMMIT_TAG=$GITHUB_SHA -t sctx/overseerr ."
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"semantic-release-docker",
|
"semantic-release-docker",
|
||||||
|
@@ -13,10 +13,19 @@ import tvRoutes from './tv';
|
|||||||
import mediaRoutes from './media';
|
import mediaRoutes from './media';
|
||||||
import personRoutes from './person';
|
import personRoutes from './person';
|
||||||
import collectionRoutes from './collection';
|
import collectionRoutes from './collection';
|
||||||
|
import { getAppVersion } from '../utils/appVersion';
|
||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
router.use(checkUser);
|
router.use(checkUser);
|
||||||
|
|
||||||
|
router.get('/status', (req, res) => {
|
||||||
|
return res.status(200).json({
|
||||||
|
version: getAppVersion(),
|
||||||
|
commitTag: process.env.COMMIT_TAG || 'local',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
router.use('/user', isAuthenticated(Permission.MANAGE_USERS), user);
|
router.use('/user', isAuthenticated(Permission.MANAGE_USERS), user);
|
||||||
router.get('/settings/public', (_req, res) => {
|
router.get('/settings/public', (_req, res) => {
|
||||||
const settings = getSettings();
|
const settings = getSettings();
|
||||||
|
@@ -175,11 +175,9 @@ const Sidebar: React.FC<SidebarProps> = ({ open, setClosed }) => {
|
|||||||
>
|
>
|
||||||
<div className="flex-shrink-0 flex items-center px-4">
|
<div className="flex-shrink-0 flex items-center px-4">
|
||||||
<span className="text-xl text-gray-50">
|
<span className="text-xl text-gray-50">
|
||||||
<Link href="/">
|
<a href="/">
|
||||||
<a>
|
|
||||||
<img src="/logo.png" alt="Overseerr Logo" />
|
<img src="/logo.png" alt="Overseerr Logo" />
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<nav className="mt-5 px-2 space-y-1">
|
<nav className="mt-5 px-2 space-y-1">
|
||||||
@@ -239,11 +237,9 @@ const Sidebar: React.FC<SidebarProps> = ({ open, setClosed }) => {
|
|||||||
<div className="flex-1 flex flex-col pt-5 pb-4 overflow-y-auto">
|
<div className="flex-1 flex flex-col pt-5 pb-4 overflow-y-auto">
|
||||||
<div className="flex items-center flex-shrink-0 px-4">
|
<div className="flex items-center flex-shrink-0 px-4">
|
||||||
<span className="text-2xl text-gray-50">
|
<span className="text-2xl text-gray-50">
|
||||||
<Link href="/">
|
<a href="/">
|
||||||
<a>
|
|
||||||
<img src="/logo.png" alt="Overseerr Logo" />
|
<img src="/logo.png" alt="Overseerr Logo" />
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<nav className="mt-5 flex-1 px-2 bg-gray-800 space-y-1">
|
<nav className="mt-5 flex-1 px-2 bg-gray-800 space-y-1">
|
||||||
|
62
src/components/StatusChacker/index.tsx
Normal file
62
src/components/StatusChacker/index.tsx
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import useSWR from 'swr';
|
||||||
|
import Modal from '../Common/Modal';
|
||||||
|
import Transition from '../Transition';
|
||||||
|
|
||||||
|
const StatusChecker: React.FC = () => {
|
||||||
|
const { data, error } = useSWR<{ version: string; commitTag: string }>(
|
||||||
|
'/api/v1/status',
|
||||||
|
{
|
||||||
|
refreshInterval: 60 * 1000,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!data && !error) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Transition
|
||||||
|
enter="opacity-0 transition duration-300"
|
||||||
|
enterFrom="opacity-0"
|
||||||
|
enterTo="opacity-100"
|
||||||
|
leave="opacity-100 transition duration-300"
|
||||||
|
leaveFrom="opacity-100"
|
||||||
|
leaveTo="opacity-0"
|
||||||
|
appear
|
||||||
|
show={data.commitTag !== process.env.commitTag}
|
||||||
|
>
|
||||||
|
<Modal
|
||||||
|
iconSvg={
|
||||||
|
<svg
|
||||||
|
className="w-6 h-6"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth={2}
|
||||||
|
d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
}
|
||||||
|
title="New Version Available"
|
||||||
|
onOk={() => location.reload()}
|
||||||
|
okText="Reload Overseerr"
|
||||||
|
backgroundClickable={false}
|
||||||
|
>
|
||||||
|
An update is now available. Click the button below to reload the
|
||||||
|
application.
|
||||||
|
</Modal>
|
||||||
|
</Transition>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default StatusChecker;
|
@@ -13,6 +13,7 @@ import { LanguageContext, AvailableLocales } from '../context/LanguageContext';
|
|||||||
import Head from 'next/head';
|
import Head from 'next/head';
|
||||||
import Toast from '../components/Toast';
|
import Toast from '../components/Toast';
|
||||||
import { InteractionProvider } from '../context/InteractionContext';
|
import { InteractionProvider } from '../context/InteractionContext';
|
||||||
|
import StatusChecker from '../components/StatusChacker';
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const loadLocaleData = (locale: string): Promise<any> => {
|
const loadLocaleData = (locale: string): Promise<any> => {
|
||||||
@@ -104,6 +105,7 @@ const CoreApp: Omit<NextAppComponentType, 'origGetInitialProps'> = ({
|
|||||||
<Head>
|
<Head>
|
||||||
<title>Overseerr</title>
|
<title>Overseerr</title>
|
||||||
</Head>
|
</Head>
|
||||||
|
<StatusChecker />
|
||||||
<UserContext initialUser={user}>{component}</UserContext>
|
<UserContext initialUser={user}>{component}</UserContext>
|
||||||
</ToastProvider>
|
</ToastProvider>
|
||||||
</InteractionProvider>
|
</InteractionProvider>
|
||||||
|
Reference in New Issue
Block a user