@instructure/canvas-rce
Version:
A component wrapping Canvas's usage of Tinymce
154 lines (152 loc) • 5.5 kB
JavaScript
import _pt from "prop-types";
/*
* Copyright (C) 2024 - present Instructure, Inc.
*
* This file is part of Canvas.
*
* Canvas is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, version 3 of the License.
*
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React, { useState } from 'react';
import { Flex } from '@instructure/ui-flex';
import ErrorBoundary from '../ErrorBoundary';
import { useFilterSettings } from '../useFilterSettings';
import PanelFilter from './PanelFilter';
import { FILTER_SETTINGS_BY_PLUGIN, DynamicPanel } from '../canvasContentUtils';
import { useStoreProps } from '../StoreContext';
// TODO: Component is only validated for images, need to validate for other content types
export default function CanvasContentPanel({
trayProps,
canvasOrigin,
plugin,
setFileUrl
}) {
const [filterSettings, setFilterSettings] = useFilterSettings(FILTER_SETTINGS_BY_PLUGIN[plugin]);
const [link, setLink] = useState(null);
const [hasLoaded, setHasLoaded] = useState(false);
// storeProps has functions that collide with what we want to do in a block editor setting
const baseStoreProps = useStoreProps();
const {
onImageEmbed: _,
onMediaEmbed: _m,
...storeProps
} = baseStoreProps;
function handleFilterChange(newFilter, onChangeContext, onChangeSearchString, onChangeSortBy) {
const newFilterSettings = {
...newFilter
};
if (newFilterSettings.sortValue) {
newFilterSettings.sortDir = newFilterSettings.sortValue === 'alphabetical' ? 'asc' : 'desc';
onChangeSortBy({
sort: newFilterSettings.sortValue,
dir: newFilterSettings.sortDir
});
}
if ('searchString' in newFilterSettings && filterSettings.searchString !== newFilterSettings.searchString) {
onChangeSearchString(newFilterSettings.searchString);
}
setFilterSettings(newFilterSettings);
if (newFilterSettings.contentType) {
let contextType, contextId;
switch (newFilterSettings.contentType) {
case 'user_files':
contextType = 'user';
contextId = trayProps.containingContext.userId;
break;
case 'group_files':
contextType = 'group';
contextId = trayProps.containingContext.contextId;
break;
case 'course_files':
contextType = trayProps.contextType;
contextId = trayProps.containingContext.contextId;
break;
case 'links':
contextType = trayProps.containingContext.contextType;
contextId = trayProps.containingContext.contextId;
}
onChangeContext({
contextType,
contextId
});
// context is only changed on load
setHasLoaded(true);
}
}
const handleImageClick = image => {
setFileUrl(image.href);
};
const handleMediaClick = media => {
setFileUrl(`/media_attachments_iframe/${media.id}`);
};
return /*#__PURE__*/React.createElement(Flex, {
as: "div",
direction: "column",
tabIndex: -1
}, /*#__PURE__*/React.createElement(Flex.Item, {
padding: "medium"
}, /*#__PURE__*/React.createElement(PanelFilter, Object.assign({}, filterSettings, {
onChange: newFilter => {
handleFilterChange(newFilter, storeProps.onChangeContext, storeProps.onChangeSearchString, storeProps.onChangeSortBy);
}
}))), /*#__PURE__*/React.createElement(Flex.Item, {
shouldGrow: true,
shouldShrink: true,
margin: "xx-small xxx-small 0"
}, hasLoaded && /*#__PURE__*/React.createElement(Flex, {
justifyItems: "space-between",
direction: "column",
height: "100%"
}, /*#__PURE__*/React.createElement(Flex.Item, {
shouldGrow: true,
shouldShrink: true
}, /*#__PURE__*/React.createElement(ErrorBoundary, null, /*#__PURE__*/React.createElement(DynamicPanel, Object.assign({
contentType: filterSettings.contentType,
contentSubtype: filterSettings.contentSubtype,
sortBy: {
sort: filterSettings.sortValue,
order: filterSettings.sortDir
},
searchString: filterSettings.searchString,
canvasOrigin: canvasOrigin,
context: {
type: trayProps.contextType,
id: trayProps.contextId
},
editing: false,
onEditClick: setLink,
selectedLink: link,
onImageEmbed: handleImageClick,
onMediaEmbed: handleMediaClick
}, storeProps)))))));
}
CanvasContentPanel.propTypes = {
trayProps: _pt.shape({
canUploadFiles: _pt.bool.isRequired,
contextId: _pt.string.isRequired,
contextType: _pt.string.isRequired,
containingContext: _pt.shape({
contextType: _pt.string.isRequired,
contextId: _pt.string.isRequired,
userId: _pt.string.isRequired
}).isRequired,
filesTabDisabled: _pt.bool.isRequired,
host: _pt.string.isRequired,
jwt: _pt.string.isRequired,
source: _pt.shape({}).isRequired,
themeUrl: _pt.string.isRequired,
storeProps: _pt.any.isRequired
}).isRequired,
canvasOrigin: _pt.string.isRequired,
plugin: _pt.any.isRequired,
setFileUrl: _pt.func.isRequired
};