mirror of
https://github.com/cpvalente/ontime.git
synced 2026-09-07 07:19:16 +00:00
feat: UI access for custom views (#2020)
* style: consistent casing on menu * refactor: bundle demo from code * feat: allow uploading custom views
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
import { useState } from 'react';
|
||||
import { IoAdd } from 'react-icons/io5';
|
||||
|
||||
import { restoreDemoView } from '../../../../common/api/customViews';
|
||||
import { maybeAxiosError } from '../../../../common/api/utils';
|
||||
import Button from '../../../../common/components/buttons/Button';
|
||||
import Info from '../../../../common/components/info/Info';
|
||||
import ExternalLink from '../../../../common/components/link/external-link/ExternalLink';
|
||||
import useCustomViews from '../../../../common/hooks-query/useCustomViews';
|
||||
import * as Panel from '../../panel-utils/PanelUtils';
|
||||
import CustomViewForm from './CustomViewForm';
|
||||
import CustomViewsList from './CustomViewsList';
|
||||
import { customViewsDocs } from './customViews.utils';
|
||||
|
||||
export default function CustomViews() {
|
||||
const { data, refetch, status } = useCustomViews();
|
||||
const [isUploadOpen, setIsUploadOpen] = useState(false);
|
||||
const [actionError, setActionError] = useState<string | null>(null);
|
||||
|
||||
const hasDemoView = data.views.some((view) => view.slug === 'demo');
|
||||
|
||||
const handleUploadComplete = async () => {
|
||||
setIsUploadOpen(false);
|
||||
await refetch();
|
||||
};
|
||||
|
||||
const handleRestoreDemo = async () => {
|
||||
try {
|
||||
setActionError(null);
|
||||
await restoreDemoView();
|
||||
await refetch();
|
||||
} catch (error) {
|
||||
setActionError(maybeAxiosError(error));
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Panel.Section>
|
||||
<Panel.Card>
|
||||
<Panel.SubHeader>
|
||||
Custom views
|
||||
<Panel.InlineElements>
|
||||
<Button variant='ghosted' onClick={handleRestoreDemo} disabled={hasDemoView}>
|
||||
Restore demo
|
||||
</Button>
|
||||
<Button onClick={() => setIsUploadOpen(true)} disabled={isUploadOpen}>
|
||||
New <IoAdd />
|
||||
</Button>
|
||||
</Panel.InlineElements>
|
||||
</Panel.SubHeader>
|
||||
<Panel.Divider />
|
||||
|
||||
<Panel.Section>
|
||||
<Info>
|
||||
Upload one <strong>index.html</strong> per view to <strong>/external/<name>/</strong>.
|
||||
<br />
|
||||
External imports are not allowed, include all assets inside the html file.
|
||||
<ExternalLink href={customViewsDocs}>See the docs</ExternalLink>
|
||||
</Info>
|
||||
</Panel.Section>
|
||||
|
||||
<Panel.Section>
|
||||
<Panel.Loader isLoading={status === 'pending'} />
|
||||
|
||||
{isUploadOpen && <CustomViewForm onComplete={handleUploadComplete} onClose={() => setIsUploadOpen(false)} />}
|
||||
|
||||
{actionError && <Panel.Error>{actionError}</Panel.Error>}
|
||||
|
||||
<CustomViewsList
|
||||
views={data.views}
|
||||
onOpenUpload={() => setIsUploadOpen(true)}
|
||||
onMutate={() => refetch()}
|
||||
onError={setActionError}
|
||||
/>
|
||||
|
||||
</Panel.Section>
|
||||
</Panel.Card>
|
||||
</Panel.Section>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user