mirror of
https://git.vectorsigma.ru/public/tubearchivist.git
synced 2026-08-05 00:29:40 +00:00
Add custom.css #884
This commit is contained in:
@@ -231,7 +231,7 @@ def ta_host_parser(ta_host: str) -> tuple[list[str], list[str]]:
|
|||||||
def get_stylesheets() -> list:
|
def get_stylesheets() -> list:
|
||||||
"""Get all valid stylesheets from /static/css"""
|
"""Get all valid stylesheets from /static/css"""
|
||||||
|
|
||||||
stylesheets = ["dark.css", "light.css", "matrix.css", "midnight.css"]
|
stylesheets = ["dark.css", "light.css", "matrix.css", "midnight.css", "custom.css"]
|
||||||
return stylesheets
|
return stylesheets
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
16
frontend/public/css/dark.css
Normal file
16
frontend/public/css/dark.css
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
:root {
|
||||||
|
--main-bg: #00202f;
|
||||||
|
--highlight-bg: #00293b;
|
||||||
|
--highlight-error: #990202;
|
||||||
|
--highlight-error-light: #c44343;
|
||||||
|
--highlight-bg-transparent: #00293baf;
|
||||||
|
--main-font: #eeeeee;
|
||||||
|
--accent-font-dark: #259485;
|
||||||
|
--accent-font-light: #97d4c8;
|
||||||
|
--img-filter: invert(50%) sepia(9%) saturate(2940%) hue-rotate(122deg) brightness(94%)
|
||||||
|
contrast(90%);
|
||||||
|
--img-filter-error: invert(16%) sepia(60%) saturate(3717%) hue-rotate(349deg) brightness(86%)
|
||||||
|
contrast(120%);
|
||||||
|
--banner: url('/img/banner-tube-archivist-dark.png');
|
||||||
|
--logo: url('/img/logo-tube-archivist-dark.png');
|
||||||
|
}
|
||||||
@@ -1,7 +1,12 @@
|
|||||||
import { SortByType, SortOrderType, ViewLayoutType } from '../../pages/Home';
|
import { SortByType, SortOrderType, ViewLayoutType } from '../../pages/Home';
|
||||||
import APIClient from '../../functions/APIClient';
|
import APIClient from '../../functions/APIClient';
|
||||||
|
|
||||||
export type ColourVariants = 'dark.css' | 'light.css' | 'matrix.css' | 'midnight.css';
|
export type ColourVariants =
|
||||||
|
| 'dark.css'
|
||||||
|
| 'light.css'
|
||||||
|
| 'matrix.css'
|
||||||
|
| 'midnight.css'
|
||||||
|
| 'custom.css';
|
||||||
|
|
||||||
export const FileSizeUnits = {
|
export const FileSizeUnits = {
|
||||||
Binary: 'binary',
|
Binary: 'binary',
|
||||||
|
|||||||
34
frontend/src/configuration/colours/Colours.tsx
Normal file
34
frontend/src/configuration/colours/Colours.tsx
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { useUserConfigStore } from '../../stores/UserConfigStore';
|
||||||
|
import { ColourConstant } from './colourConstant';
|
||||||
|
import CustomStylesheet from './components/Custom';
|
||||||
|
import DarkStylesheet from './components/Dark';
|
||||||
|
import LightStylesheet from './components/Light';
|
||||||
|
import MatrixStylesheet from './components/Matrix';
|
||||||
|
import MidnightStylesheet from './components/Midnight';
|
||||||
|
|
||||||
|
const Colours = () => {
|
||||||
|
const { userConfig } = useUserConfigStore();
|
||||||
|
const stylesheet = userConfig?.stylesheet;
|
||||||
|
|
||||||
|
switch (stylesheet) {
|
||||||
|
case ColourConstant.Dark:
|
||||||
|
return <DarkStylesheet />;
|
||||||
|
|
||||||
|
case ColourConstant.Matrix:
|
||||||
|
return <MatrixStylesheet />;
|
||||||
|
|
||||||
|
case ColourConstant.Midnight:
|
||||||
|
return <MidnightStylesheet />;
|
||||||
|
|
||||||
|
case ColourConstant.Light:
|
||||||
|
return <LightStylesheet />;
|
||||||
|
|
||||||
|
case ColourConstant.Custom:
|
||||||
|
return <CustomStylesheet />;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return <DarkStylesheet />;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Colours;
|
||||||
7
frontend/src/configuration/colours/colourConstant.ts
Normal file
7
frontend/src/configuration/colours/colourConstant.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export const ColourConstant = {
|
||||||
|
Dark: 'dark.css',
|
||||||
|
Light: 'light.css',
|
||||||
|
Matrix: 'matrix.css',
|
||||||
|
Midnight: 'midnight.css',
|
||||||
|
Custom: 'custom.css',
|
||||||
|
};
|
||||||
9
frontend/src/configuration/colours/components/Custom.tsx
Normal file
9
frontend/src/configuration/colours/components/Custom.tsx
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
const CustomStylesheet = () => {
|
||||||
|
return (
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="/css/custom.css" />
|
||||||
|
</head>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CustomStylesheet;
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
import './css/dark.css';
|
|
||||||
|
|
||||||
const DarkStylesheet = () => {
|
const DarkStylesheet = () => {
|
||||||
return <></>;
|
return (
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="/css/dark.css" />
|
||||||
|
</head>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DarkStylesheet;
|
export default DarkStylesheet;
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import './css/light.css';
|
|
||||||
|
|
||||||
const LightStylesheet = () => {
|
const LightStylesheet = () => {
|
||||||
return <></>;
|
return (
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="/css/light.css" />
|
||||||
|
</head>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LightStylesheet;
|
export default LightStylesheet;
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import './css/matrix.css';
|
|
||||||
|
|
||||||
const MatrixStylesheet = () => {
|
const MatrixStylesheet = () => {
|
||||||
return <></>;
|
return (
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="/css/matrix.css" />
|
||||||
|
</head>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MatrixStylesheet;
|
export default MatrixStylesheet;
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import './css/midnight.css';
|
|
||||||
|
|
||||||
const MidnightStylesheet = () => {
|
const MidnightStylesheet = () => {
|
||||||
return <></>;
|
return (
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="/css/midnight.css" />
|
||||||
|
</head>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MidnightStylesheet;
|
export default MidnightStylesheet;
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
import { useUserConfigStore } from '../../stores/UserConfigStore';
|
|
||||||
|
|
||||||
export const ColourConstant = {
|
|
||||||
Dark: 'dark.css',
|
|
||||||
Light: 'light.css',
|
|
||||||
Matrix: 'matrix.css',
|
|
||||||
Midnight: 'midnight.css',
|
|
||||||
};
|
|
||||||
|
|
||||||
const useColours = () => {
|
|
||||||
const { userConfig } = useUserConfigStore();
|
|
||||||
const stylesheet = userConfig?.stylesheet;
|
|
||||||
|
|
||||||
switch (stylesheet) {
|
|
||||||
case ColourConstant.Dark:
|
|
||||||
return import('./components/Dark');
|
|
||||||
|
|
||||||
case ColourConstant.Matrix:
|
|
||||||
return import('./components/Matrix');
|
|
||||||
|
|
||||||
case ColourConstant.Midnight:
|
|
||||||
return import('./components/Midnight');
|
|
||||||
|
|
||||||
case ColourConstant.Light:
|
|
||||||
return import('./components/Light');
|
|
||||||
|
|
||||||
default:
|
|
||||||
return import('./components/Dark');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useColours;
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Outlet, useLoaderData, useLocation, useSearchParams } from 'react-router-dom';
|
import { Outlet, useLoaderData, useLocation, useSearchParams } from 'react-router-dom';
|
||||||
import Footer from '../components/Footer';
|
import Footer from '../components/Footer';
|
||||||
import useColours from '../configuration/colours/useColours';
|
import Colours from '../configuration/colours/Colours';
|
||||||
import { UserConfigType } from '../api/actions/updateUserConfig';
|
import { UserConfigType } from '../api/actions/updateUserConfig';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import Navigation from '../components/Navigation';
|
import Navigation from '../components/Navigation';
|
||||||
@@ -94,10 +94,9 @@ const Base = () => {
|
|||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [currentPage]);
|
}, [currentPage]);
|
||||||
|
|
||||||
useColours();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<Colours />
|
||||||
<div className="main-content">
|
<div className="main-content">
|
||||||
<Navigation />
|
<Navigation />
|
||||||
{/** Outlet: https://reactrouter.com/en/main/components/outlet */}
|
{/** Outlet: https://reactrouter.com/en/main/components/outlet */}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useRouteError } from 'react-router-dom';
|
import { useRouteError } from 'react-router-dom';
|
||||||
import useColours from '../configuration/colours/useColours';
|
import Colours from '../configuration/colours/Colours';
|
||||||
|
|
||||||
// This is not always the correct response
|
// This is not always the correct response
|
||||||
type ErrorType = {
|
type ErrorType = {
|
||||||
@@ -9,13 +9,13 @@ type ErrorType = {
|
|||||||
|
|
||||||
const ErrorPage = () => {
|
const ErrorPage = () => {
|
||||||
const error = useRouteError() as ErrorType;
|
const error = useRouteError() as ErrorType;
|
||||||
useColours();
|
|
||||||
|
|
||||||
console.error('ErrorPage', error);
|
console.error('ErrorPage', error);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<title>TA | Oops!</title>
|
<title>TA | Oops!</title>
|
||||||
|
<Colours />
|
||||||
|
|
||||||
<div id="error-page" style={{ margin: '10%' }}>
|
<div id="error-page" style={{ margin: '10%' }}>
|
||||||
<h1>Oops!</h1>
|
<h1>Oops!</h1>
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import Routes from '../configuration/routes/RouteList';
|
import Routes from '../configuration/routes/RouteList';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import useColours from '../configuration/colours/useColours';
|
import Colours from '../configuration/colours/Colours';
|
||||||
import Button from '../components/Button';
|
import Button from '../components/Button';
|
||||||
import signIn from '../api/actions/signIn';
|
import signIn from '../api/actions/signIn';
|
||||||
import loadAuth from '../api/loader/loadAuth';
|
import loadAuth from '../api/loader/loadAuth';
|
||||||
|
|
||||||
const Login = () => {
|
const Login = () => {
|
||||||
useColours();
|
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const [username, setUsername] = useState('');
|
const [username, setUsername] = useState('');
|
||||||
@@ -76,6 +74,7 @@ const Login = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<title>TA | Welcome</title>
|
<title>TA | Welcome</title>
|
||||||
|
<Colours />
|
||||||
<div className="boxed-content login-page">
|
<div className="boxed-content login-page">
|
||||||
<img alt="tube-archivist-logo" />
|
<img alt="tube-archivist-logo" />
|
||||||
<h1>Tube Archivist</h1>
|
<h1>Tube Archivist</h1>
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import useColours from '../configuration/colours/useColours';
|
import Colours from '../configuration/colours/Colours';
|
||||||
import Routes from '../configuration/routes/RouteList';
|
import Routes from '../configuration/routes/RouteList';
|
||||||
|
|
||||||
const NotFound = ({ failType = 'page' }) => {
|
const NotFound = ({ failType = 'page' }) => {
|
||||||
useColours();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<title>404 | Not found</title>
|
<title>404 | Not found</title>
|
||||||
|
<Colours />
|
||||||
<div id="error-page" style={{ margin: '10%' }}>
|
<div id="error-page" style={{ margin: '10%' }}>
|
||||||
<h1>Oops!</h1>
|
<h1>Oops!</h1>
|
||||||
<p>
|
<p>
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
import { useNavigate } from 'react-router-dom';
|
|
||||||
import updateUserConfig, {
|
import updateUserConfig, {
|
||||||
ColourVariants,
|
ColourVariants,
|
||||||
FileSizeUnits,
|
FileSizeUnits,
|
||||||
UserConfigType,
|
UserConfigType,
|
||||||
} from '../api/actions/updateUserConfig';
|
} from '../api/actions/updateUserConfig';
|
||||||
import { ColourConstant } from '../configuration/colours/useColours';
|
|
||||||
import SettingsNavigation from '../components/SettingsNavigation';
|
import SettingsNavigation from '../components/SettingsNavigation';
|
||||||
import Notifications from '../components/Notifications';
|
import Notifications from '../components/Notifications';
|
||||||
import Button from '../components/Button';
|
import Button from '../components/Button';
|
||||||
@@ -12,14 +10,13 @@ import useIsAdmin from '../functions/useIsAdmin';
|
|||||||
import { useUserConfigStore } from '../stores/UserConfigStore';
|
import { useUserConfigStore } from '../stores/UserConfigStore';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import ToggleConfig from '../components/ToggleConfig';
|
import ToggleConfig from '../components/ToggleConfig';
|
||||||
|
import { ColourConstant } from '../configuration/colours/colourConstant';
|
||||||
|
|
||||||
const SettingsUser = () => {
|
const SettingsUser = () => {
|
||||||
const { userConfig, setUserConfig } = useUserConfigStore();
|
const { userConfig, setUserConfig } = useUserConfigStore();
|
||||||
const isAdmin = useIsAdmin();
|
const isAdmin = useIsAdmin();
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
const [styleSheet, setStyleSheet] = useState<ColourVariants>(userConfig.stylesheet);
|
const [styleSheet, setStyleSheet] = useState<ColourVariants>(userConfig.stylesheet);
|
||||||
const [styleSheetRefresh, setStyleSheetRefresh] = useState(false);
|
|
||||||
const [pageSize, setPageSize] = useState<number>(userConfig.page_size);
|
const [pageSize, setPageSize] = useState<number>(userConfig.page_size);
|
||||||
const [showHelpText, setShowHelpText] = useState(userConfig.show_help_text);
|
const [showHelpText, setShowHelpText] = useState(userConfig.show_help_text);
|
||||||
const [selectedFileSizeUnit, setSelectedFileSizeUnit] = useState(FileSizeUnits.Binary);
|
const [selectedFileSizeUnit, setSelectedFileSizeUnit] = useState(FileSizeUnits.Binary);
|
||||||
@@ -41,7 +38,6 @@ const SettingsUser = () => {
|
|||||||
const handleStyleSheetChange = async (selectedStyleSheet: ColourVariants) => {
|
const handleStyleSheetChange = async (selectedStyleSheet: ColourVariants) => {
|
||||||
handleUserConfigUpdate({ stylesheet: selectedStyleSheet });
|
handleUserConfigUpdate({ stylesheet: selectedStyleSheet });
|
||||||
setStyleSheet(selectedStyleSheet);
|
setStyleSheet(selectedStyleSheet);
|
||||||
setStyleSheetRefresh(true);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePageSizeChange = async () => {
|
const handlePageSizeChange = async () => {
|
||||||
@@ -65,11 +61,6 @@ const SettingsUser = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePageRefresh = () => {
|
|
||||||
navigate(0);
|
|
||||||
setStyleSheetRefresh(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<title>TA | User Settings</title>
|
<title>TA | User Settings</title>
|
||||||
@@ -104,7 +95,6 @@ const SettingsUser = () => {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</select>
|
</select>
|
||||||
{styleSheetRefresh && <button onClick={handlePageRefresh}>Refresh</button>}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user