mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-19 22:24:11 +00:00
feat: app settings (#658)
* feat: app settings * refactor: cleanup routes * style: smaller base font * chore: migrate about modal * fix: import links
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
@use '../../../theme/ontimeColours' as *;
|
||||
@use '../../../theme/v2Styles' as *;
|
||||
|
||||
.header {
|
||||
font-size: 2rem;
|
||||
padding-bottom: 0.5rem;
|
||||
border-bottom: 1px solid $white-10;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.subheader {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin: 2rem 0;
|
||||
font-size: calc(1rem - 1px);
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
.paragraph {
|
||||
padding: 0.5rem 0;
|
||||
}
|
||||
|
||||
.card {
|
||||
padding: 1rem;
|
||||
background-color: $white-1;
|
||||
border: 1px solid $gray-1100;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
.error {
|
||||
font-size: $inner-section-text-size;
|
||||
display: block;
|
||||
color: $error-red;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
import style from './Panel.module.scss';
|
||||
|
||||
export function Header({ children }: { children: ReactNode }) {
|
||||
return <h2 className={style.header}>{children}</h2>;
|
||||
}
|
||||
|
||||
export function SubHeader({ children }: { children: ReactNode }) {
|
||||
return <h3 className={style.subheader}>{children}</h3>;
|
||||
}
|
||||
|
||||
export function Section({ children }: { children: ReactNode }) {
|
||||
return <p className={style.section}>{children}</p>;
|
||||
}
|
||||
|
||||
export function Paragraph({ children }: { children: ReactNode }) {
|
||||
return <p className={style.paragraph}>{children}</p>;
|
||||
}
|
||||
|
||||
export function Card({ children }: { children: ReactNode }) {
|
||||
return <div className={style.card}>{children}</div>;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { version } from '../../../../../package.json';
|
||||
import ExternalLink from '../../../../common/components/external-link/ExternalLink';
|
||||
import { gitbookUrl, githubUrl, websiteUrl } from '../../../../externals';
|
||||
import * as Panel from '../PanelUtils';
|
||||
|
||||
import CheckUpdatesButton from './CheckUpdatesButton';
|
||||
|
||||
export default function AboutPanel() {
|
||||
return (
|
||||
<>
|
||||
<Panel.Header>About Ontime</Panel.Header>
|
||||
<Panel.Section>
|
||||
<Panel.SubHeader>Ontime</Panel.SubHeader>
|
||||
<Panel.Paragraph>
|
||||
Free, open-source software for managing rundowns and event timers
|
||||
<ExternalLink href={websiteUrl}>www.getontime.no</ExternalLink>
|
||||
</Panel.Paragraph>
|
||||
</Panel.Section>
|
||||
<Panel.Section>
|
||||
<Panel.Card>
|
||||
<Panel.SubHeader>Links</Panel.SubHeader>
|
||||
<ExternalLink href={gitbookUrl}>Read the docs over at GitBook</ExternalLink>
|
||||
<ExternalLink href={githubUrl}>Follow the project on GitHub</ExternalLink>
|
||||
</Panel.Card>
|
||||
</Panel.Section>
|
||||
<Panel.Section>
|
||||
<Panel.Card>
|
||||
<Panel.SubHeader>Current version</Panel.SubHeader>
|
||||
<Panel.Paragraph>{`You are currently using Ontime ${version}`}</Panel.Paragraph>
|
||||
<CheckUpdatesButton version={version} />
|
||||
</Panel.Card>
|
||||
</Panel.Section>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import { useState } from 'react';
|
||||
import { Button } from '@chakra-ui/react';
|
||||
|
||||
import { getLatestVersion, HasUpdate } from '../../../../common/api/ontimeApi';
|
||||
import ExternalLink from '../../../../common/components/external-link/ExternalLink';
|
||||
|
||||
import style from '../Panel.module.scss';
|
||||
|
||||
type CheckFail = {
|
||||
error: string;
|
||||
};
|
||||
|
||||
type CheckIsLatest = {
|
||||
latest: true;
|
||||
};
|
||||
|
||||
type CheckRemote = CheckFail | CheckIsLatest | HasUpdate;
|
||||
|
||||
interface CheckUpdatesButtonProps {
|
||||
version: string;
|
||||
}
|
||||
|
||||
export default function CheckUpdatesButton(props: CheckUpdatesButtonProps) {
|
||||
const { version } = props;
|
||||
|
||||
const [updateMessage, setUpdateMessage] = useState<CheckRemote | null>(null);
|
||||
const [isFetching, setIsFetching] = useState(false);
|
||||
|
||||
/**
|
||||
* Handles version comparison and returns component with message
|
||||
*/
|
||||
const versionCheck = async () => {
|
||||
setIsFetching(true);
|
||||
|
||||
try {
|
||||
const latest = await getLatestVersion();
|
||||
|
||||
if (!latest.version.includes(version)) {
|
||||
// new version, pass data to component
|
||||
setUpdateMessage(latest);
|
||||
} else {
|
||||
setUpdateMessage({ latest: true });
|
||||
}
|
||||
} catch {
|
||||
setUpdateMessage({ error: 'Error reaching server' });
|
||||
} finally {
|
||||
setIsFetching(false);
|
||||
}
|
||||
};
|
||||
|
||||
const disableButton = Boolean(updateMessage && 'version' in updateMessage);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button onClick={versionCheck} variant='ontime-filled' isLoading={isFetching} isDisabled={disableButton}>
|
||||
Check for updates
|
||||
</Button>
|
||||
<ResolveUpdateMessage updateMessage={updateMessage} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function ResolveUpdateMessage(props: { updateMessage: CheckRemote | null }) {
|
||||
const { updateMessage } = props;
|
||||
|
||||
if (updateMessage && 'error' in updateMessage) {
|
||||
return <span className={style.error}>{updateMessage.error}</span>;
|
||||
}
|
||||
if (updateMessage && 'url' in updateMessage) {
|
||||
return <ExternalLink href={updateMessage?.url}>{`New version available: ${updateMessage.version}`}</ExternalLink>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user