Skip to content

Commit

Permalink
feat: Add Paste from Clipboard to lib sidebar
Browse files Browse the repository at this point in the history
This includes a fix for fetching the initial clipboard data and populating
the redux state on first render.
  • Loading branch information
yusuf-musleh committed Aug 13, 2024
1 parent 0490452 commit 8259b58
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 1 deletion.
22 changes: 21 additions & 1 deletion src/generic/clipboard/hooks/useCopyToClipboard.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// @ts-check
import { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';

import { getClipboard } from '../../data/api';
import { updateClipboardData } from '../../data/slice';
import { CLIPBOARD_STATUS, STRUCTURAL_XBLOCK_TYPES, STUDIO_CLIPBOARD_CHANNEL } from '../../../constants';
import { getClipboardData } from '../../data/selectors';

Expand All @@ -14,6 +17,7 @@ import { getClipboardData } from '../../data/selectors';
* @property {Object} sharedClipboardData - The shared clipboard data object.
*/
const useCopyToClipboard = (canEdit = true) => {
const dispatch = useDispatch();
const [clipboardBroadcastChannel] = useState(() => new BroadcastChannel(STUDIO_CLIPBOARD_CHANNEL));
const [showPasteUnit, setShowPasteUnit] = useState(false);
const [showPasteXBlock, setShowPasteXBlock] = useState(false);
Expand All @@ -30,6 +34,22 @@ const useCopyToClipboard = (canEdit = true) => {
setShowPasteUnit(!!isPasteableUnit);
};

// Called on initial render to fetch and populate the initial clipboard data in redux state.
// Without this, the initial clipboard data redux state is always null.
useEffect(() => {
const fetchInitialClipboardData = async () => {
try {
const userClipboard = await getClipboard();
dispatch(updateClipboardData(userClipboard));
} catch (error) {
// eslint-disable-next-line no-console
console.error(`Failed to fetch initial clipboard data: ${error}`);
}
};

fetchInitialClipboardData();
}, [dispatch]);

useEffect(() => {
// Handle updates to clipboard data
if (canEdit) {
Expand Down
18 changes: 18 additions & 0 deletions src/library-authoring/add-content/AddContentContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useContext } from 'react';
import { useSelector } from 'react-redux';
import {
Stack,
Button,
Expand All @@ -12,10 +13,13 @@ import {
ThumbUpOutline,
Question,
VideoCamera,
ContentPaste,
} from '@openedx/paragon/icons';
import { v4 as uuid4 } from 'uuid';
import { useParams } from 'react-router-dom';
import { ToastContext } from '../../generic/toast-context';
import { useCopyToClipboard } from '../../generic/clipboard';
import { getCanEdit } from '../../course-unit/data/selectors';
import { useCreateLibraryBlock } from '../data/apiHooks';
import messages from './messages';

Expand All @@ -24,6 +28,8 @@ const AddContentContainer = () => {
const { libraryId } = useParams();
const createBlockMutation = useCreateLibraryBlock();
const { showToast } = useContext(ToastContext);
const canEdit = useSelector(getCanEdit);
const { showPasteXBlock } = useCopyToClipboard(canEdit);

const contentTypes = [
{
Expand Down Expand Up @@ -64,6 +70,18 @@ const AddContentContainer = () => {
},
];

// Include the 'Paste from Clipboard' button if there is an Xblock in the clipboard
// that can be pasted
if (showPasteXBlock) {
const pasteButton = {
name: intl.formatMessage(messages.pasteButton),
disabled: false,
icon: ContentPaste,
blockType: 'paste',
};
contentTypes.push(pasteButton);
}

const onCreateContent = (blockType: string) => {
if (libraryId) {
createBlockMutation.mutateAsync({
Expand Down
5 changes: 5 additions & 0 deletions src/library-authoring/add-content/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ const messages = defineMessages({
defaultMessage: 'Advanced / Other',
description: 'Content of button to create a Advanced / Other component.',
},
pasteButton: {
id: 'course-authoring.library-authoring.add-content.buttons.paste',
defaultMessage: 'Paste From Clipboard',
description: 'Content of button to paste from clipboard.',
},
successCreateMessage: {
id: 'course-authoring.library-authoring.add-content.success.text',
defaultMessage: 'Content created successfully.',
Expand Down

0 comments on commit 8259b58

Please sign in to comment.