import React, { useEffect, useState } from 'react'; import getFileContents from '@/api/server/files/getFileContents'; import { httpErrorToHuman } from '@/api/http'; import SpinnerOverlay from '@/components/elements/SpinnerOverlay'; import saveFileContents from '@/api/server/files/saveFileContents'; import FileManagerBreadcrumbs from '@/components/server/files/FileManagerBreadcrumbs'; import { useHistory, useLocation, useParams } from 'react-router'; import FileNameModal from '@/components/server/files/FileNameModal'; import Can from '@/components/elements/Can'; import FlashMessageRender from '@/components/FlashMessageRender'; import PageContentBlock from '@/components/elements/PageContentBlock'; import { ServerError } from '@/components/elements/ScreenBlock'; import tw from 'twin.macro'; import Button from '@/components/elements/Button'; import Select from '@/components/elements/Select'; import modes from '@/modes'; import useFlash from '@/plugins/useFlash'; import { ServerContext } from '@/state/server'; import ErrorBoundary from '@/components/elements/ErrorBoundary'; import { encodePathSegments, hashToPath } from '@/helpers'; import { dirname } from 'path'; import CodemirrorEditor from '@/components/elements/CodemirrorEditor'; import BeforeEdit from '@/blueprint/components/Server/Files/Edit/BeforeEdit'; import AfterEdit from '@/blueprint/components/Server/Files/Edit/AfterEdit'; export default () => { const [error, setError] = useState(''); const { action } = useParams<{ action: 'new' | string }>(); const [loading, setLoading] = useState(action === 'edit'); const [content, setContent] = useState(''); const [modalVisible, setModalVisible] = useState(false); const [mode, setMode] = useState('text/plain'); const history = useHistory(); const { hash } = useLocation(); const id = ServerContext.useStoreState((state) => state.server.data!.id); const uuid = ServerContext.useStoreState((state) => state.server.data!.uuid); const setDirectory = ServerContext.useStoreActions((actions) => actions.files.setDirectory); const { addError, clearFlashes } = useFlash(); let fetchFileContent: null | (() => Promise) = null; useEffect(() => { if (action === 'new') return; setError(''); setLoading(true); const path = hashToPath(hash); setDirectory(dirname(path)); getFileContents(uuid, path) .then(setContent) .catch((error) => { console.error(error); setError(httpErrorToHuman(error)); }) .then(() => setLoading(false)); }, [action, uuid, hash]); const save = (name?: string) => { if (!fetchFileContent) { return; } setLoading(true); clearFlashes('files:view'); fetchFileContent() .then((content) => saveFileContents(uuid, name || hashToPath(hash), content)) .then(() => { if (name) { history.push(`/server/${id}/files/edit#/${encodePathSegments(name)}`); return; } return Promise.resolve(); }) .catch((error) => { console.error(error); addError({ message: httpErrorToHuman(error), key: 'files:view' }); }) .then(() => setLoading(false)); }; if (error) { return history.goBack()} />; } return (
{hash.replace(/^#/, '').endsWith('.pteroignore') && (

You're editing a .pteroignore{' '} file. Any files or directories listed in here will be excluded from backups. Wildcards are supported by using an asterisk (*). You can negate a prior rule by prepending an exclamation point ( !).

)} setModalVisible(false)} onFileNamed={(name) => { setModalVisible(false); save(name); }} />
{ fetchFileContent = value; }} onContentSaved={() => { if (action !== 'edit') { setModalVisible(true); } else { save(); } }} />
{action === 'edit' ? ( ) : ( )}
); };