From f18274533edb5a9358e56ff8cd266bcf668a6599 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B4mulo=20Penido?= Date: Thu, 29 May 2025 15:33:23 -0300 Subject: [PATCH] fix: set unit preview readonly on sidebar (#2008) Make the unit preview on the sidebar read-only and add `Truncate` to the `InplaceTextEditor` --- src/generic/inplace-text-editor/index.tsx | 9 ++--- .../containers/UnitInfo.test.tsx | 16 +++++++++ src/library-authoring/containers/UnitInfo.tsx | 6 +++- .../units/LibraryUnitBlocks.tsx | 34 ++++++++++--------- 4 files changed, 44 insertions(+), 21 deletions(-) diff --git a/src/generic/inplace-text-editor/index.tsx b/src/generic/inplace-text-editor/index.tsx index b1bbe531c..89c97a2a0 100644 --- a/src/generic/inplace-text-editor/index.tsx +++ b/src/generic/inplace-text-editor/index.tsx @@ -6,6 +6,7 @@ import { Form, Icon, IconButton, + Truncate, Stack, } from '@openedx/paragon'; import { Edit } from '@openedx/paragon/icons'; @@ -68,9 +69,9 @@ export const InplaceTextEditor: React.FC = ({ // In that case, we show the new text instead of the original in read-only mode as an optimistic update. if (readOnly || pendingSaveText) { return ( - + {pendingSaveText || text} - + ); } @@ -91,9 +92,9 @@ export const InplaceTextEditor: React.FC = ({ /> ) : ( - + {text} - + )} ', () => { expect(await screen.findByTestId('unit-info-menu-toggle')).toBeInTheDocument(); expect(screen.getByText(/text block published 1/i)).toBeInTheDocument(); }); + + it('shows the preview tab by default and the component are readonly', async () => { + render(); + const previewTab = await screen.findByText('Preview'); + expect(previewTab).toBeInTheDocument(); + expect(previewTab).toHaveAttribute('aria-selected', 'true'); + + // Check that there are no edit buttons for components titles + expect(screen.queryAllByRole('button', { name: /edit/i }).length).toBe(0); + + // Check that there are no drag handle for components + expect(screen.queryAllByRole('button', { name: 'Drag to reorder' }).length).toBe(0); + + // Check that there are no menu buttons for components + expect(screen.queryAllByRole('button', { name: /component actions menu/i }).length).toBe(0); + }); }); diff --git a/src/library-authoring/containers/UnitInfo.tsx b/src/library-authoring/containers/UnitInfo.tsx index e143e3ff3..cdf5c2d08 100644 --- a/src/library-authoring/containers/UnitInfo.tsx +++ b/src/library-authoring/containers/UnitInfo.tsx @@ -162,7 +162,11 @@ const UnitInfo = () => { activeKey={tab} onSelect={handleTabChange} > - {renderTab(UNIT_INFO_TABS.Preview, , intl.formatMessage(messages.previewTabTitle))} + {renderTab( + UNIT_INFO_TABS.Preview, + , + intl.formatMessage(messages.previewTabTitle), + )} {renderTab(UNIT_INFO_TABS.Manage, , intl.formatMessage(messages.manageTabTitle))} {renderTab(UNIT_INFO_TABS.Settings, 'Unit Settings', intl.formatMessage(messages.settingsTabTitle))} diff --git a/src/library-authoring/units/LibraryUnitBlocks.tsx b/src/library-authoring/units/LibraryUnitBlocks.tsx index 8486e275b..e4b3af980 100644 --- a/src/library-authoring/units/LibraryUnitBlocks.tsx +++ b/src/library-authoring/units/LibraryUnitBlocks.tsx @@ -49,12 +49,12 @@ interface LibraryBlockMetadataWithUniqueId extends LibraryBlockMetadata { interface ComponentBlockProps { block: LibraryBlockMetadataWithUniqueId; - preview?: boolean; + readOnly?: boolean; isDragging?: boolean; } /** Component header */ -const BlockHeader = ({ block }: ComponentBlockProps) => { +const BlockHeader = ({ block, readOnly }: ComponentBlockProps) => { const intl = useIntl(); const { showOnlyPublished } = useLibraryContext(); const { showToast } = useContext(ToastContext); @@ -98,13 +98,13 @@ const BlockHeader = ({ block }: ComponentBlockProps) => { gap={2} className="font-weight-bold" // Prevent parent card from being clicked. - /* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */ onClick={(e) => e.stopPropagation()} > @@ -112,7 +112,6 @@ const BlockHeader = ({ block }: ComponentBlockProps) => { direction="horizontal" gap={3} // Prevent parent card from being clicked. - /* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */ onClick={(e) => e.stopPropagation()} > {!showOnlyPublished && block.hasUnpublishedChanges && ( @@ -126,15 +125,15 @@ const BlockHeader = ({ block }: ComponentBlockProps) => { )} - - + + {!readOnly && } ); }; /** ComponentBlock to render preview of given component under Unit */ -const ComponentBlock = ({ block, preview, isDragging }: ComponentBlockProps) => { +const ComponentBlock = ({ block, readOnly, isDragging }: ComponentBlockProps) => { const { showOnlyPublished } = useLibraryContext(); const { navigateTo } = useLibraryRoutes(); @@ -193,16 +192,16 @@ const ComponentBlock = ({ block, preview, isDragging }: ComponentBlockProps) => } + actions={} actionStyle={{ borderRadius: '8px 8px 0px 0px', padding: '0.5rem 1rem', background: '#FBFAF9', borderBottom: 'solid 1px #E1DDDB', }} - isClickable - onClick={(e: { detail: number; }) => handleComponentSelection(e.detail)} - disabled={preview} + isClickable={!readOnly} + onClick={!readOnly ? (e: { detail: number; }) => handleComponentSelection(e.detail) : undefined} + disabled={readOnly} cardClassName={selected ? 'selected' : undefined} > {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} @@ -227,12 +226,12 @@ const ComponentBlock = ({ block, preview, isDragging }: ComponentBlockProps) => interface LibraryUnitBlocksProps { /** set to true if it is rendered as preview - * This disables drag and drop + * This disables drag and drop, title edit and menus */ - preview?: boolean; + readOnly?: boolean; } -export const LibraryUnitBlocks = ({ preview }: LibraryUnitBlocksProps) => { +export const LibraryUnitBlocks = ({ readOnly: componentReadOnly }: LibraryUnitBlocksProps) => { const intl = useIntl(); const [orderedBlocks, setOrderedBlocks] = useState([]); const [isAddLibraryContentModalOpen, showAddLibraryContentModal, closeAddLibraryContentModal] = useToggle(); @@ -240,7 +239,9 @@ export const LibraryUnitBlocks = ({ preview }: LibraryUnitBlocksProps) => { const [hidePreviewFor, setHidePreviewFor] = useState(null); const { showToast } = useContext(ToastContext); - const { unitId, readOnly, showOnlyPublished } = useLibraryContext(); + const { unitId, readOnly: libraryReadOnly, showOnlyPublished } = useLibraryContext(); + + const readOnly = componentReadOnly || libraryReadOnly; const { openAddContentSidebar } = useSidebarContext(); @@ -305,10 +306,11 @@ export const LibraryUnitBlocks = ({ preview }: LibraryUnitBlocksProps) => { key={`${block.originalId}-${idx}-${block.modified}`} block={block} isDragging={hidePreviewFor === block.id} + readOnly={readOnly} /> ))} - {!preview && ( + {!readOnly && (