Files
Verso/services/web/frontend/js/features/file-tree/components/file-tree-action-buttons.tsx
T
claude eada1e9979
Build and Deploy Verso / deploy (push) Successful in 13m42s
file-tree: show python packages button for all quarto projects
The previous approach (pdfFile?.path === 'output.html') caused a
chicken-and-egg problem: the button only appeared after a successful
RevealJS compile, but you need to add packages before the first compile.

Use compiler === 'quarto' from ProjectSettingsContext instead — this is
set from project metadata and available immediately, before any compile.
Quarto supports Jupyter Python cells in all output formats (RevealJS HTML,
PDF via LaTeX, PDF via Typst), so showing the button for any Quarto project
is the correct behaviour.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 07:41:21 +00:00

141 lines
4.1 KiB
TypeScript

import { useTranslation } from 'react-i18next'
import * as eventTracking from '../../../infrastructure/event-tracking'
import { useFileTreeActionable } from '@/features/file-tree/contexts/file-tree-actionable'
import { useFileTreeData } from '@/shared/context/file-tree-data-context'
import React, { useState } from 'react'
import { useCommandProvider } from '@/features/ide-react/hooks/use-command-provider'
import { usePermissionsContext } from '@/features/ide-react/context/permissions-context'
import FileTreeActionButton from './file-tree-action-button'
import { useRailContext } from '../../ide-react/context/rail-context'
import PythonRequirementsModal from './python-requirements-modal'
import { useProjectSettingsContext } from '@/features/editor-left-menu/context/project-settings-context'
export default function FileTreeActionButtons({
fileTreeExpanded,
}: {
fileTreeExpanded: boolean
}) {
const { t } = useTranslation()
const { fileTreeReadOnly } = useFileTreeData()
const { write } = usePermissionsContext()
const { handlePaneCollapse } = useRailContext()
const [showPythonModal, setShowPythonModal] = useState(false)
const { compiler } = useProjectSettingsContext()
const isQuarto = compiler === 'quarto'
const {
canCreate,
canBulkDelete,
startDeleting,
startCreatingFolder,
startCreatingDocOrFile,
startUploadingDocOrFile,
} = useFileTreeActionable()
useCommandProvider(() => {
if (!canCreate || fileTreeReadOnly || !write) return
return [
{
label: t('new_file'),
id: 'new_file',
handler: ({ location }) => {
eventTracking.sendMB('new-file-click', { location })
startCreatingDocOrFile()
},
},
{
label: t('new_folder'),
id: 'new_folder',
handler: startCreatingFolder,
},
{
label: t('upload_file'),
id: 'upload_file',
handler: ({ location }) => {
eventTracking.sendMB('upload-click', { location })
startUploadingDocOrFile()
},
},
]
}, [
canCreate,
fileTreeReadOnly,
startCreatingDocOrFile,
t,
startCreatingFolder,
startUploadingDocOrFile,
write,
])
if (fileTreeReadOnly) return null
const createWithAnalytics = () => {
eventTracking.sendMB('new-file-click', { location: 'toolbar' })
startCreatingDocOrFile()
}
const uploadWithAnalytics = () => {
eventTracking.sendMB('upload-click', { location: 'toolbar' })
startUploadingDocOrFile()
}
return (
<div className="file-tree-toolbar-action-buttons">
{fileTreeExpanded && (
<>
{canCreate && (
<FileTreeActionButton
id="new-file"
description={t('new_file')}
onClick={createWithAnalytics}
iconType="note_add"
/>
)}
{canCreate && (
<FileTreeActionButton
id="new-folder"
description={t('new_folder')}
onClick={startCreatingFolder}
iconType="create_new_folder"
/>
)}
{canCreate && (
<FileTreeActionButton
id="upload"
description={t('upload')}
onClick={uploadWithAnalytics}
iconType="upload"
/>
)}
{canBulkDelete && (
<FileTreeActionButton
id="delete"
description={t('delete')}
onClick={startDeleting}
iconType="delete"
/>
)}
{write && isQuarto && (
<FileTreeActionButton
id="python-packages"
description={t('python_packages')}
onClick={() => setShowPythonModal(true)}
iconType="deployed_code"
/>
)}
</>
)}
<FileTreeActionButton
id="close"
description={t('close')}
onClick={handlePaneCollapse}
iconType="close"
/>
<PythonRequirementsModal
show={showPythonModal}
onHide={() => setShowPythonModal(false)}
/>
</div>
)
}