diff --git a/services/web/frontend/fonts/material-symbols/MaterialSymbolsRoundedUnfilledPartialSlice.woff2 b/services/web/frontend/fonts/material-symbols/MaterialSymbolsRoundedUnfilledPartialSlice.woff2 index 14a5ef1e2b..df942df176 100644 Binary files a/services/web/frontend/fonts/material-symbols/MaterialSymbolsRoundedUnfilledPartialSlice.woff2 and b/services/web/frontend/fonts/material-symbols/MaterialSymbolsRoundedUnfilledPartialSlice.woff2 differ diff --git a/services/web/frontend/fonts/material-symbols/unfilled-symbols.mjs b/services/web/frontend/fonts/material-symbols/unfilled-symbols.mjs index eca63fa035..baefac05aa 100644 --- a/services/web/frontend/fonts/material-symbols/unfilled-symbols.mjs +++ b/services/web/frontend/fonts/material-symbols/unfilled-symbols.mjs @@ -8,6 +8,7 @@ export default /** @type {const} */ ([ 'brush', 'code', 'create_new_folder', + 'delete', 'description', 'experiment', 'forum', diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-root.tsx b/services/web/frontend/js/features/file-tree/components/file-tree-root.tsx index 561e1b5e1d..a6cde94e73 100644 --- a/services/web/frontend/js/features/file-tree/components/file-tree-root.tsx +++ b/services/web/frontend/js/features/file-tree/components/file-tree-root.tsx @@ -6,7 +6,7 @@ import FileTreeContext from './file-tree-context' import FileTreeDraggablePreviewLayer from './file-tree-draggable-preview-layer' import FileTreeFolderList from './file-tree-folder-list' import FileTreeToolbar from './file-tree-toolbar' -import FileTreeToolbarNew from '@/features/ide-redesign/components/file-tree-toolbar' +import FileTreeToolbarNew from '@/features/ide-redesign/components/file-tree/file-tree-toolbar' import FileTreeModalDelete from './modals/file-tree-modal-delete' import FileTreeModalCreateFolder from './modals/file-tree-modal-create-folder' import FileTreeModalError from './modals/file-tree-modal-error' diff --git a/services/web/frontend/js/features/file-tree/contexts/file-tree-actionable.tsx b/services/web/frontend/js/features/file-tree/contexts/file-tree-actionable.tsx index 6b26de3298..54723e3e0d 100644 --- a/services/web/frontend/js/features/file-tree/contexts/file-tree-actionable.tsx +++ b/services/web/frontend/js/features/file-tree/contexts/file-tree-actionable.tsx @@ -57,6 +57,7 @@ const FileTreeActionableContext = createContext< newFileCreateMode: any | null error: any | null canDelete: boolean + canBulkDelete: boolean canRename: boolean canCreate: boolean parentFolderId: string @@ -509,6 +510,8 @@ export const FileTreeActionableProvider: FC = ({ const value = useMemo( () => ({ canDelete: write && selectedEntityIds.size > 0 && !isRootFolderSelected, + canBulkDelete: + write && selectedEntityIds.size > 1 && !isRootFolderSelected, canRename: write && selectedEntityIds.size === 1 && !isRootFolderSelected, canCreate: write && selectedEntityIds.size < 2, ...state, @@ -545,8 +548,8 @@ export const FileTreeActionableProvider: FC = ({ isDuplicate, isRootFolderSelected, parentFolderId, - selectedEntityIds.size, selectedFileName, + selectedEntityIds.size, startCreatingDocOrFile, startCreatingFile, startCreatingFolder, diff --git a/services/web/frontend/js/features/ide-redesign/components/file-tree-toolbar.tsx b/services/web/frontend/js/features/ide-redesign/components/file-tree-toolbar.tsx deleted file mode 100644 index f1d72941f5..0000000000 --- a/services/web/frontend/js/features/ide-redesign/components/file-tree-toolbar.tsx +++ /dev/null @@ -1,149 +0,0 @@ -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 OLTooltip from '@/features/ui/components/ol/ol-tooltip' -import MaterialIcon, { - AvailableUnfilledIcon, -} from '@/shared/components/material-icon' -import React from 'react' -import useCollapsibleFileTree from '../hooks/use-collapsible-file-tree' -import { useCommandProvider } from '@/features/ide-react/hooks/use-command-provider' -import { usePermissionsContext } from '@/features/ide-react/context/permissions-context' - -function FileTreeToolbar() { - const { t } = useTranslation() - const { fileTreeExpanded, toggleFileTreeExpanded } = useCollapsibleFileTree() - - return ( -
- - -
- ) -} - -function FileTreeActionButtons() { - const { t } = useTranslation() - const { fileTreeReadOnly } = useFileTreeData() - const { write } = usePermissionsContext() - - const { - canCreate, - 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 (!canCreate || fileTreeReadOnly) return null - - const createWithAnalytics = () => { - eventTracking.sendMB('new-file-click', { location: 'toolbar' }) - startCreatingDocOrFile() - } - - const uploadWithAnalytics = () => { - eventTracking.sendMB('upload-click', { location: 'toolbar' }) - startUploadingDocOrFile() - } - - return ( -
- - - -
- ) -} - -function FileTreeActionButton({ - id, - description, - onClick, - iconType, -}: { - id: string - description: string - onClick: () => void - iconType: AvailableUnfilledIcon -}) { - return ( - - - - ) -} - -export default FileTreeToolbar diff --git a/services/web/frontend/js/features/ide-redesign/components/file-tree/file-tree-action-button.tsx b/services/web/frontend/js/features/ide-redesign/components/file-tree/file-tree-action-button.tsx new file mode 100644 index 0000000000..5678db58c8 --- /dev/null +++ b/services/web/frontend/js/features/ide-redesign/components/file-tree/file-tree-action-button.tsx @@ -0,0 +1,33 @@ +import OLTooltip from '@/features/ui/components/ol/ol-tooltip' +import MaterialIcon, { + AvailableUnfilledIcon, +} from '@/shared/components/material-icon' +import React from 'react' + +export default function FileTreeActionButton({ + id, + description, + onClick, + iconType, +}: { + id: string + description: string + onClick: () => void + iconType: AvailableUnfilledIcon +}) { + return ( + + + + ) +} diff --git a/services/web/frontend/js/features/ide-redesign/components/file-tree/file-tree-action-buttons.tsx b/services/web/frontend/js/features/ide-redesign/components/file-tree/file-tree-action-buttons.tsx new file mode 100644 index 0000000000..93760b97ab --- /dev/null +++ b/services/web/frontend/js/features/ide-redesign/components/file-tree/file-tree-action-buttons.tsx @@ -0,0 +1,107 @@ +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 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' + +export default function FileTreeActionButtons() { + const { t } = useTranslation() + const { fileTreeReadOnly } = useFileTreeData() + const { write } = usePermissionsContext() + + 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 ( +
+ {canCreate && ( + + )} + {canCreate && ( + + )} + {canCreate && ( + + )} + {canBulkDelete && ( + + )} +
+ ) +} diff --git a/services/web/frontend/js/features/ide-redesign/components/file-tree-outline-panel.tsx b/services/web/frontend/js/features/ide-redesign/components/file-tree/file-tree-outline-panel.tsx similarity index 95% rename from services/web/frontend/js/features/ide-redesign/components/file-tree-outline-panel.tsx rename to services/web/frontend/js/features/ide-redesign/components/file-tree/file-tree-outline-panel.tsx index bf69d40e59..62c228973e 100644 --- a/services/web/frontend/js/features/ide-redesign/components/file-tree-outline-panel.tsx +++ b/services/web/frontend/js/features/ide-redesign/components/file-tree/file-tree-outline-panel.tsx @@ -3,7 +3,7 @@ import { FileTree } from '@/features/ide-react/components/file-tree' import { OutlineContainer } from '@/features/outline/components/outline-container' import { VerticalResizeHandle } from '@/features/ide-react/components/resize/vertical-resize-handle' import { useOutlinePane } from '@/features/ide-react/hooks/use-outline-pane' -import useCollapsibleFileTree from '../hooks/use-collapsible-file-tree' +import useCollapsibleFileTree from '../../hooks/use-collapsible-file-tree' import classNames from 'classnames' function FileTreeOutlinePanel() { diff --git a/services/web/frontend/js/features/ide-redesign/components/file-tree/file-tree-toolbar.tsx b/services/web/frontend/js/features/ide-redesign/components/file-tree/file-tree-toolbar.tsx new file mode 100644 index 0000000000..231f98e7d7 --- /dev/null +++ b/services/web/frontend/js/features/ide-redesign/components/file-tree/file-tree-toolbar.tsx @@ -0,0 +1,32 @@ +import { useTranslation } from 'react-i18next' +import MaterialIcon from '@/shared/components/material-icon' +import React from 'react' +import useCollapsibleFileTree from '../../hooks/use-collapsible-file-tree' +import FileTreeActionButtons from './file-tree-action-buttons' + +function FileTreeToolbar() { + const { t } = useTranslation() + const { fileTreeExpanded, toggleFileTreeExpanded } = useCollapsibleFileTree() + + return ( +
+ + +
+ ) +} + +export default FileTreeToolbar diff --git a/services/web/frontend/js/features/ide-redesign/components/rail.tsx b/services/web/frontend/js/features/ide-redesign/components/rail.tsx index 8f54331630..249b2b1891 100644 --- a/services/web/frontend/js/features/ide-redesign/components/rail.tsx +++ b/services/web/frontend/js/features/ide-redesign/components/rail.tsx @@ -12,7 +12,7 @@ import { RailTabKey, useRailContext, } from '../contexts/rail-context' -import FileTreeOutlinePanel from './file-tree-outline-panel' +import FileTreeOutlinePanel from './file-tree/file-tree-outline-panel' import { ChatIndicator, ChatPane } from './chat/chat' import getMeta from '@/utils/meta' import { HorizontalResizeHandle } from '@/features/ide-react/components/resize/horizontal-resize-handle'