@instructure/canvas-rce 5.10.0 → 5.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/Dockerfile +1 -1
  3. package/es/common/mimeClass.js +70 -67
  4. package/es/enhance-user-content/doc_previews.js +1 -1
  5. package/es/enhance-user-content/enhance_user_content.js +9 -1
  6. package/es/getThemeVars.js +3 -4
  7. package/es/rce/RCE.js +1 -3
  8. package/es/rce/RCEWrapper.js +3 -67
  9. package/es/rce/RceHtmlEditor.js +28 -8
  10. package/es/rce/plugins/instructure_links/components/Link.js +3 -9
  11. package/es/rce/plugins/instructure_links/components/LinkSet.js +4 -8
  12. package/es/rce/plugins/instructure_links/components/NoResults.js +5 -10
  13. package/es/rce/plugins/instructure_links/plugin.js +1 -7
  14. package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolDialog/ExternalToolDialog.js +1 -2
  15. package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolDialog/ExternalToolDialogTray.js +6 -12
  16. package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolSelectionDialog/ExternalToolSelectionDialog.js +2 -2
  17. package/es/rce/plugins/instructure_rce_external_tools/lti13-content-items/models/ResourceLinkContentItem.js +1 -1
  18. package/es/rce/plugins/instructure_record/VideoOptionsTray/TrayController.js +7 -2
  19. package/es/rce/plugins/instructure_record/VideoOptionsTray/index.js +3 -9
  20. package/es/rce/plugins/instructure_wordcount/components/WordCountModal.js +8 -16
  21. package/es/rce/plugins/shared/CanvasContentTray.js +7 -1
  22. package/es/rce/plugins/shared/fileTypeUtils.js +14 -6
  23. package/es/rce/plugins/tinymce-a11y-checker/components/{color-field.js → ColorField.js} +9 -7
  24. package/es/rce/plugins/tinymce-a11y-checker/components/checker.js +27 -24
  25. package/es/rce/root.js +1 -3
  26. package/es/rce/transformContent.js +8 -0
  27. package/es/sidebar/actions/upload.js +3 -1
  28. package/jest/jest-setup.js +2 -0
  29. package/lib/common/mimeClass.js +70 -67
  30. package/lib/enhance-user-content/doc_previews.js +1 -1
  31. package/lib/enhance-user-content/enhance_user_content.js +9 -1
  32. package/lib/getThemeVars.js +3 -4
  33. package/lib/rce/RCE.js +1 -3
  34. package/lib/rce/RCEWrapper.js +3 -67
  35. package/lib/rce/RceHtmlEditor.js +28 -8
  36. package/lib/rce/plugins/instructure_links/components/Link.js +3 -9
  37. package/lib/rce/plugins/instructure_links/components/LinkSet.js +4 -8
  38. package/lib/rce/plugins/instructure_links/components/NoResults.js +5 -10
  39. package/lib/rce/plugins/instructure_links/plugin.js +1 -7
  40. package/lib/rce/plugins/instructure_rce_external_tools/components/ExternalToolDialog/ExternalToolDialog.js +1 -2
  41. package/lib/rce/plugins/instructure_rce_external_tools/components/ExternalToolDialog/ExternalToolDialogTray.js +6 -12
  42. package/lib/rce/plugins/instructure_rce_external_tools/components/ExternalToolSelectionDialog/ExternalToolSelectionDialog.js +2 -2
  43. package/lib/rce/plugins/instructure_rce_external_tools/lti13-content-items/models/ResourceLinkContentItem.js +1 -1
  44. package/lib/rce/plugins/instructure_record/VideoOptionsTray/TrayController.js +7 -2
  45. package/lib/rce/plugins/instructure_record/VideoOptionsTray/index.js +3 -9
  46. package/lib/rce/plugins/instructure_wordcount/components/WordCountModal.js +8 -16
  47. package/lib/rce/plugins/shared/CanvasContentTray.js +7 -1
  48. package/lib/rce/plugins/shared/fileTypeUtils.js +14 -6
  49. package/lib/rce/plugins/tinymce-a11y-checker/components/{color-field.js → ColorField.js} +9 -7
  50. package/lib/rce/plugins/tinymce-a11y-checker/components/checker.js +27 -24
  51. package/lib/rce/root.js +1 -3
  52. package/lib/rce/transformContent.js +8 -0
  53. package/lib/sidebar/actions/upload.js +3 -1
  54. package/locales/en.json +1438 -89
  55. package/package.json +52 -51
@@ -216,8 +216,16 @@ export function enhanceUserContent() {
216
216
  iframeElem.setAttribute('src', addParentFrameContextToUrl(src, containingCanvasLtiToolId));
217
217
  }
218
218
  });
219
- }
219
+ } // tell LTI tools that they are launching from within the active RCE
220
+
221
+
222
+ unenhanced_elem.querySelectorAll('iframe[src]').forEach(iframeElem => {
223
+ const src = iframeElem.getAttribute('src');
220
224
 
225
+ if (src.startsWith(canvasOrigin)) {
226
+ iframeElem.setAttribute('src', src.replace('display=in_rce', 'display=borderless'));
227
+ }
228
+ });
221
229
  unenhanced_elem.querySelectorAll('a:not(.not_external, .external)').forEach(childLink => {
222
230
  if (!isExternalLink(childLink, canvasOrigin)) return;
223
231
  if (childLink.tagName === 'IMG' || childLink.querySelectorAll('img').length > 0) return;
@@ -15,8 +15,7 @@
15
15
  * You should have received a copy of the GNU Affero General Public License along
16
16
  * with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
- import { ThemeRegistry } from '@instructure/ui-themeable'; // ^^ at InstUI 8, just directly import getRegistry directly from @instructure/theme-registry
19
-
18
+ import { getRegistry } from '@instructure/theme-registry';
20
19
  import { merge, cloneDeep } from 'lodash'; // The running theme is the running theme for this page load, and it never
21
20
  // changes, so there's no point in doing the work more than once.
22
21
 
@@ -28,13 +27,13 @@ function getThemeVars() {
28
27
  defaultThemeKey,
29
28
  overrides,
30
29
  themes
31
- } = ThemeRegistry.getRegistry(); // Just assume the "canvas" theme if the default key is null. This will
30
+ } = getRegistry(); // Just assume the "canvas" theme if the default key is null. This will
32
31
  // never happen in the live app because one way or another a theme gets
33
32
  // used, but unit tests don't always do that.
34
33
  // Also we have to cloneDeep this because the merge below is about to
35
34
  // mutate the whole thing.
36
35
 
37
- const variables = cloneDeep(themes[defaultThemeKey !== null && defaultThemeKey !== void 0 ? defaultThemeKey : 'canvas'].variables);
36
+ const variables = cloneDeep(themes[defaultThemeKey !== null && defaultThemeKey !== void 0 ? defaultThemeKey : 'canvas']);
38
37
  merge(variables, overrides);
39
38
  memoizedVariables = {
40
39
  variables,
package/lib/rce/RCE.js CHANGED
@@ -1,5 +1,3 @@
1
- var _process, _process$env;
2
-
3
1
  // @ts-nocheck
4
2
 
5
3
  /*
@@ -29,7 +27,7 @@ import tinyRCE from './tinyRCE';
29
27
  import getTranslations from '../getTranslations';
30
28
  import '@instructure/canvas-theme';
31
29
 
32
- if (!((_process = process) !== null && _process !== void 0 && (_process$env = _process.env) !== null && _process$env !== void 0 && _process$env.BUILD_LOCALE)) {
30
+ if (!process || !process.env || !undefined) {
33
31
  formatMessage.setup({
34
32
  locale: 'en',
35
33
  generateId: require('format-message-generate-id/underscored_crc32'),
@@ -2714,67 +2714,9 @@ class RCEWrapper extends React.Component {
2714
2714
 
2715
2715
  this.checkAccessibility();
2716
2716
  this.fixToolbarKeyboardNavigation();
2717
- this.forwardPostMessages();
2718
2717
  (_this$props$onInitted = (_this$props = this.props).onInitted) === null || _this$props$onInitted === void 0 ? void 0 : _this$props$onInitted.call(_this$props, editor);
2719
2718
  };
2720
2719
 
2721
- this.forwardPostMessages = () => {
2722
- const windowReferences = [];
2723
- const rceWindow = this.editor.getWin(); // explicitly assign name for reference by parent window
2724
-
2725
- rceWindow.name = `${RCEWrapper.editorFrameName}_${this.id}`;
2726
- rceWindow.addEventListener('message', this.forwardPostMessagesHandler(rceWindow, windowReferences));
2727
- };
2728
-
2729
- this.forwardPostMessagesHandler = (rceWindow, windowReferences) => e => {
2730
- let message;
2731
-
2732
- try {
2733
- message = typeof e.data === 'string' ? JSON.parse(e.data) : e.data;
2734
- } catch (err) {
2735
- // unparseable message may not be meant for our handlers
2736
- return false;
2737
- } // NOTE: the code to encode/decode `sourceToolInfo` is duplicated in
2738
- // the ui/features/post_message_forwarding/index.ts, and
2739
- // cannot be DRY'd because RCE is in a package
2740
-
2741
-
2742
- if (e.origin === rceWindow.origin) {
2743
- const {
2744
- sourceToolInfo,
2745
- ...messageWithoutSourceToolInfo
2746
- } = message;
2747
- const targetOrigin = sourceToolInfo === null || sourceToolInfo === void 0 ? void 0 : sourceToolInfo.origin;
2748
- const targetWindow = windowReferences[sourceToolInfo === null || sourceToolInfo === void 0 ? void 0 : sourceToolInfo.windowId];
2749
-
2750
- if (!targetOrigin || !targetWindow) {
2751
- return false;
2752
- }
2753
-
2754
- targetWindow === null || targetWindow === void 0 ? void 0 : targetWindow.postMessage(messageWithoutSourceToolInfo, targetOrigin);
2755
- } else {
2756
- // message is from tool, forward to Canvas window
2757
- // We can't forward the whole `e.source` window in the postMessage,
2758
- // so we keep a list (`windowReferences`) of all windows we've received
2759
- // messages from, and include the index into that list as `windowId`
2760
- let windowId = windowReferences.indexOf(e.source);
2761
-
2762
- if (windowId === -1) {
2763
- windowReferences.push(e.source);
2764
- windowId = windowReferences.length - 1;
2765
- }
2766
-
2767
- const newMessage = { ...message,
2768
- sourceToolInfo: {
2769
- origin: e.origin,
2770
- windowId
2771
- },
2772
- frameName: rceWindow.name
2773
- };
2774
- rceWindow.parent.postMessage(newMessage, rceWindow.origin);
2775
- }
2776
- };
2777
-
2778
2720
  this.fixToolbarKeyboardNavigation = () => {
2779
2721
  var _this$_elementRef$cur2;
2780
2722
 
@@ -3200,19 +3142,15 @@ class RCEWrapper extends React.Component {
3200
3142
  getRequiredFeatureStatuses() {
3201
3143
  const {
3202
3144
  new_math_equation_handling = false,
3203
- rce_ux_improvements = false,
3204
3145
  explicit_latex_typesetting = false,
3205
3146
  rce_transform_loaded_content = false,
3206
- media_links_use_attachment_id = false,
3207
- improved_no_results_messaging = false
3147
+ media_links_use_attachment_id = false
3208
3148
  } = this.props.features;
3209
3149
  return {
3210
3150
  new_math_equation_handling,
3211
- rce_ux_improvements,
3212
3151
  explicit_latex_typesetting,
3213
3152
  rce_transform_loaded_content,
3214
- media_links_use_attachment_id,
3215
- improved_no_results_messaging
3153
+ media_links_use_attachment_id
3216
3154
  };
3217
3155
  }
3218
3156
 
@@ -3220,8 +3158,7 @@ class RCEWrapper extends React.Component {
3220
3158
  return {
3221
3159
  locale: normalizeLocale(this.props.language),
3222
3160
  flashAlertTimeout: this.props.flashAlertTimeout,
3223
- timezone: this.props.timezone,
3224
- lockedAttachments: this.props.lockedAttachments
3161
+ timezone: this.props.timezone
3225
3162
  };
3226
3163
  }
3227
3164
 
@@ -4257,7 +4194,6 @@ RCEWrapper.defaultProps = {
4257
4194
  canvasOrigin: ''
4258
4195
  };
4259
4196
  RCEWrapper.skinCssInjected = false;
4260
- RCEWrapper.editorFrameName = 'active_rce_frame';
4261
4197
 
4262
4198
  function mergeMenuItems(standard, custom) {
4263
4199
  var _custom$trim;
@@ -28,6 +28,28 @@ const RceHtmlEditor = /*#__PURE__*/React.forwardRef((_ref, editorRef) => {
28
28
  const [code, setCode] = useState(props.code);
29
29
  const label = formatMessage('html code editor');
30
30
  const [dir, setDir] = useState(getComputedStyle(document.body, null).direction);
31
+ const [codeMirrorEditorDiv, setCodeMirrorEditorDiv] = useState(null);
32
+ useEffect(() => {
33
+ ;
34
+
35
+ (async () => {
36
+ const p = new Promise(resolve => {
37
+ const timerid = setInterval(() => {
38
+ // scoping querySelector to the container div makes sure we're targeting this CodeEditor
39
+ // The CodeMirror docs (https://codemirror.net/doc/manual.html#styling)
40
+ // say this is the element we use to set the editor's height
41
+ const editor = editorRef.current.querySelector('.CodeMirror');
42
+
43
+ if (editor) {
44
+ clearInterval(timerid);
45
+ setCodeMirrorEditorDiv(editor);
46
+ resolve();
47
+ }
48
+ }, 60);
49
+ });
50
+ await p;
51
+ })();
52
+ }, [editorRef]);
31
53
  useEffect(() => {
32
54
  setCode(beautify.html(props.code)); // eslint-disable-next-line react-hooks/exhaustive-deps
33
55
  }, []);
@@ -57,14 +79,12 @@ const RceHtmlEditor = /*#__PURE__*/React.forwardRef((_ref, editorRef) => {
57
79
  setDir(getComputedStyle(editorRef.current || document.body, null).direction);
58
80
  }, [dir, editorRef]);
59
81
  useEffect(() => {
60
- // scoping querySelector to the container div makes sure we're targeting this CodeEditor
61
- // The CodeMirror docs (https://codemirror.net/doc/manual.html#styling)
62
- // say this is the element we use to set the editor's height
63
- const editor = editorRef.current.querySelector('.CodeMirror');
64
- editor.CodeMirror.setSize(null, props.height);
65
- editor.style.margin = '0';
66
- editor.style.border = '0';
67
- }, [props.height, editorRef]);
82
+ if (codeMirrorEditorDiv) {
83
+ codeMirrorEditorDiv.CodeMirror.setSize(null, props.height);
84
+ codeMirrorEditorDiv.style.margin = '0';
85
+ codeMirrorEditorDiv.style.border = '0';
86
+ }
87
+ }, [codeMirrorEditorDiv, props.height]);
68
88
  const isFocused = useRef(false); // move cursor to the top of the html code when the editor is focused for the first time
69
89
 
70
90
  const handleFocus = useCallback((editor, event) => {
@@ -31,8 +31,6 @@ import { IconDragHandleLine, IconPublishSolid, IconUnpublishedSolid } from '@ins
31
31
  import RCEGlobals from '../../../RCEGlobals';
32
32
  import { getIcon } from '../../shared/linkUtils';
33
33
  export default function Link(props) {
34
- var _RCEGlobals$getFeatur;
35
-
36
34
  const internalLink = { ...props.link
37
35
  };
38
36
  const [isHovering, setIsHovering] = useState(false);
@@ -43,14 +41,10 @@ export default function Link(props) {
43
41
  date_type
44
42
  } = props.link;
45
43
  const type = props.type === 'quizzes' && props.link.quiz_type === 'quizzes.next' ? 'quizzes.next' : props.type;
44
+ internalLink['data-course-type'] = type; // Only included published attr if it makes sense for the link type
46
45
 
47
- if ((_RCEGlobals$getFeatur = RCEGlobals.getFeatures()) !== null && _RCEGlobals$getFeatur !== void 0 && _RCEGlobals$getFeatur.rce_ux_improvements) {
48
- internalLink['data-course-type'] = type; // Only included published attr if it makes sense for the link type
49
-
50
- const publishable = !['navigation', 'announcements'].includes(type);
51
- internalLink['data-published'] = publishable ? published : null;
52
- }
53
-
46
+ const publishable = !['navigation', 'announcements'].includes(type);
47
+ internalLink['data-published'] = publishable ? published : null;
54
48
  const Icon = getIcon(type);
55
49
  const color = published ? 'success' : 'primary';
56
50
  let dateString = null;
@@ -113,7 +113,7 @@ class LinkSet extends Component {
113
113
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ScreenReaderContent, {
114
114
  id: this.describedByID
115
115
  }, formatMessage('Click to insert a link into the editor.')), /*#__PURE__*/React.createElement(List, {
116
- variant: "unstyled",
116
+ isUnstyled: true,
117
117
  as: "ul",
118
118
  margin: "0"
119
119
  }, this.props.collection.links.map((link, index, array) => {
@@ -137,18 +137,14 @@ class LinkSet extends Component {
137
137
  }
138
138
 
139
139
  renderEmptyIndicator() {
140
- var _RCEGlobals$getFeatur, _this$props$searchStr;
140
+ var _this$props$searchStr;
141
141
 
142
- return (_RCEGlobals$getFeatur = RCEGlobals.getFeatures()) !== null && _RCEGlobals$getFeatur !== void 0 && _RCEGlobals$getFeatur.improved_no_results_messaging ? /*#__PURE__*/React.createElement(NoResults, {
142
+ return /*#__PURE__*/React.createElement(NoResults, {
143
143
  contextType: this.props.contextType,
144
144
  contextId: this.props.contextId,
145
145
  collectionType: this.props.type,
146
146
  isSearchResult: ((_this$props$searchStr = this.props.searchString) === null || _this$props$searchStr === void 0 ? void 0 : _this$props$searchStr.length) >= 3
147
- }) : /*#__PURE__*/React.createElement(View, {
148
- as: "div",
149
- role: "alert",
150
- padding: "medium"
151
- }, formatMessage('No results.'));
147
+ });
152
148
  }
153
149
 
154
150
  renderLoadingError() {
@@ -23,11 +23,7 @@ import { Flex } from '@instructure/ui-flex';
23
23
  import { Text } from '@instructure/ui-text';
24
24
  import { Link } from '@instructure/ui-link';
25
25
  import formatMessage from '../../../../format-message';
26
- import { getIcon } from '../../shared/linkUtils'; // Doing this to avoid TS2339 errors-- remove once we're on InstUI 8
27
-
28
- const {
29
- Item: FlexItem
30
- } = Flex;
26
+ import { getIcon } from '../../shared/linkUtils';
31
27
  export function buildUrl(contextType, contextId, collectionType) {
32
28
  var _typeMap$collectionTy;
33
29
 
@@ -72,15 +68,14 @@ export const NoResults = _ref => {
72
68
  justifyItems: "center",
73
69
  alignItems: "center",
74
70
  direction: "column"
75
- }, /*#__PURE__*/React.createElement(FlexItem, null, /*#__PURE__*/React.createElement(Icon, {
71
+ }, /*#__PURE__*/React.createElement(Flex.Item, null, /*#__PURE__*/React.createElement(Icon, {
76
72
  size: "large",
77
73
  color: "secondary",
78
74
  padding: "large"
79
- })), /*#__PURE__*/React.createElement(FlexItem, {
75
+ })), /*#__PURE__*/React.createElement(Flex.Item, {
80
76
  margin: "small 0 0"
81
- }, /*#__PURE__*/React.createElement(Text, null, getMessage(collectionType, isSearchResult))), !isSearchResult && /*#__PURE__*/React.createElement(FlexItem, null, /*#__PURE__*/React.createElement(Link, {
82
- href: buildUrl(contextType, contextId, collectionType) // @ts-expect-error
83
- ,
77
+ }, /*#__PURE__*/React.createElement(Text, null, getMessage(collectionType, isSearchResult))), !isSearchResult && /*#__PURE__*/React.createElement(Flex.Item, null, /*#__PURE__*/React.createElement(Link, {
78
+ href: buildUrl(contextType, contextId, collectionType),
84
79
  target: "_blank"
85
80
  }, formatMessage('Add one!')))));
86
81
  };
@@ -68,20 +68,14 @@ import bridge from '../../../bridge';
68
68
  import { getAnchorElement, isOKToLink } from '../../contentInsertionUtils';
69
69
  import LinkOptionsTrayController from './components/LinkOptionsTray/LinkOptionsTrayController';
70
70
  import { CREATE_LINK, EDIT_LINK } from './components/LinkOptionsDialog/LinkOptionsDialogController';
71
- import RCEGlobals from '../../RCEGlobals';
72
71
  import tinymce from 'tinymce';
73
72
  const trayController = new LinkOptionsTrayController();
74
73
  const COURSE_PLUGIN_KEY = 'course_links';
75
74
  const GROUP_PLUGIN_KEY = 'group_links';
76
75
 
77
76
  function getCommandName(selectedNode) {
78
- var _RCEGlobals$getFeatur;
79
-
80
- // show the Course Tray if it's a course link and the ux improvement flag is on,
81
- // otherwise show the default Link Tray
82
- const showCourseLinkTray = !!((_RCEGlobals$getFeatur = RCEGlobals.getFeatures()) !== null && _RCEGlobals$getFeatur !== void 0 && _RCEGlobals$getFeatur.rce_ux_improvements);
83
77
  const isCourseLink = selectedNode.getAttribute('data-course-type');
84
- return showCourseLinkTray && isCourseLink ? 'instructureTrayForCourseLinks' : 'instructureTrayToEditLink';
78
+ return isCourseLink ? 'instructureTrayForCourseLinks' : 'instructureTrayToEditLink';
85
79
  }
86
80
 
87
81
  function selectedAnchorCount(ed) {
@@ -31,7 +31,6 @@ import { ExternalToolDialogTray } from './ExternalToolDialogTray';
31
31
  import { ExternalToolDialogModal } from './ExternalToolDialogModal';
32
32
  import { showFlashAlert } from '../../../../../common/FlashAlert';
33
33
  import { parseUrlOrNull } from '../../../../../util/url-util';
34
- const FlexItem = Flex.Item;
35
34
  export default class ExternalToolDialog extends React.Component {
36
35
  constructor() {
37
36
  super(...arguments);
@@ -246,7 +245,7 @@ export default class ExternalToolDialog extends React.Component {
246
245
  }, formatMessage('The following content is partner provided'))), !state.iframeLoaded && /*#__PURE__*/React.createElement(Flex, {
247
246
  alignItems: "center",
248
247
  justifyItems: "center"
249
- }, /*#__PURE__*/React.createElement(FlexItem, null, /*#__PURE__*/React.createElement(Spinner, {
248
+ }, /*#__PURE__*/React.createElement(Flex.Item, null, /*#__PURE__*/React.createElement(Spinner, {
250
249
  renderTitle: formatMessage('Loading External Tool'),
251
250
  size: "large",
252
251
  margin: "0 0 0 medium"
@@ -1,3 +1,5 @@
1
+ import _pt from "prop-types";
2
+
1
3
  /*
2
4
  * Copyright (C) 2019 - present Instructure, Inc.
3
5
  *
@@ -16,14 +18,12 @@
16
18
  * with this program. If not, see <http://www.gnu.org/licenses/>.
17
19
  */
18
20
  import React from 'react';
19
- import PropTypes from 'prop-types';
20
21
  import { Tray } from '@instructure/ui-tray';
21
22
  import { View } from '@instructure/ui-view';
22
23
  import { Flex } from '@instructure/ui-flex';
23
24
  import { Heading } from '@instructure/ui-heading';
24
25
  import { CloseButton } from '@instructure/ui-buttons';
25
26
  import formatMessage from 'format-message';
26
- const FlexItem = Flex.Item;
27
27
  export function ExternalToolDialogTray(props) {
28
28
  const {
29
29
  label,
@@ -56,9 +56,9 @@ export function ExternalToolDialogTray(props) {
56
56
  }, /*#__PURE__*/React.createElement(Flex, {
57
57
  as: "div",
58
58
  padding: "small"
59
- }, /*#__PURE__*/React.createElement(FlexItem, {
59
+ }, /*#__PURE__*/React.createElement(Flex.Item, {
60
60
  shouldGrow: true
61
- }, /*#__PURE__*/React.createElement(Heading, null, name)), /*#__PURE__*/React.createElement(FlexItem, null, /*#__PURE__*/React.createElement(CloseButton, {
61
+ }, /*#__PURE__*/React.createElement(Heading, null, name)), /*#__PURE__*/React.createElement(Flex.Item, null, /*#__PURE__*/React.createElement(CloseButton, {
62
62
  onClick: onCloseButton,
63
63
  size: "small",
64
64
  screenReaderLabel: formatMessage('Close')
@@ -74,12 +74,6 @@ export function ExternalToolDialogTray(props) {
74
74
  }, children)))));
75
75
  }
76
76
  ExternalToolDialogTray.propTypes = {
77
- open: PropTypes.bool,
78
- label: PropTypes.string.isRequired,
79
- mountNode: PropTypes.oneOfType([PropTypes.element, PropTypes.func]),
80
- onOpen: PropTypes.func,
81
- onClose: PropTypes.func,
82
- onCloseButton: PropTypes.func,
83
- name: PropTypes.string.isRequired,
84
- children: PropTypes.node
77
+ onCloseButton: _pt.func,
78
+ name: _pt.string.isRequired
85
79
  };
@@ -70,7 +70,7 @@ export function ExternalToolSelectionDialog(props) {
70
70
  "data-mce-component": true,
71
71
  liveRegion: getLiveRegion,
72
72
  size: "medium",
73
- theme: {
73
+ themeOverride: {
74
74
  mediumMaxWidth: '42rem'
75
75
  },
76
76
  label: formatMessage('Apps'),
@@ -79,7 +79,7 @@ export function ExternalToolSelectionDialog(props) {
79
79
  open: true,
80
80
  shouldCloseOnDocumentClick: false
81
81
  }, /*#__PURE__*/React.createElement(Modal.Header, {
82
- theme: {
82
+ themeOverride: {
83
83
  padding: '0.5rem'
84
84
  }
85
85
  }, /*#__PURE__*/React.createElement(CloseButton, {
@@ -35,7 +35,7 @@ export default class ResourceLinkContentItem extends BaseLinkContentItem {
35
35
 
36
36
  buildUrl() {
37
37
  return addQueryParamsToUrl(this.context.ltiEndpoint, {
38
- display: 'borderless',
38
+ display: 'in_rce',
39
39
  resource_link_lookup_uuid: this.lookup_uuid,
40
40
  [PARENT_FRAME_CONTEXT_PARAM]: this.context.containingCanvasLtiToolId
41
41
  });
@@ -146,7 +146,7 @@ export default class TrayController {
146
146
  // If not, we can't update the MediaObject in the canvas db.
147
147
 
148
148
 
149
- if (videoOptions.media_object_id && videoOptions.media_object_id !== 'undefined' && !videoOptions.isLocked) {
149
+ if (videoOptions.media_object_id && videoOptions.media_object_id !== 'undefined') {
150
150
  videoOptions.updateMediaObject(data).then(_r => {
151
151
  if (this.$videoContainer && videoOptions.displayAs === 'embed') {
152
152
  this.$videoContainer.contentWindow.postMessage({
@@ -181,10 +181,15 @@ export default class TrayController {
181
181
  let vo = {};
182
182
 
183
183
  if (this._shouldOpen) {
184
+ /*
185
+ * When the tray is being opened again, it should be rendered fresh
186
+ * (clearing the internal state) so that the currently-selected video can
187
+ * be used for initial video options.
188
+ */
184
189
  this._renderId++;
190
+ vo = asVideoElement(this.$videoContainer) || {};
185
191
  }
186
192
 
187
- vo = asVideoElement(this.$videoContainer) || {};
188
193
  const element = /*#__PURE__*/React.createElement(VideoOptionsTray, {
189
194
  id: "video-options-tray",
190
195
  key: this._renderId,
@@ -38,13 +38,10 @@ import DimensionsInput, { useDimensionsState } from '../../shared/DimensionsInpu
38
38
  import { getTrayHeight } from '../../shared/trayUtils';
39
39
  import { instuiPopupMountNode } from '../../../../util/fullscreenHelpers';
40
40
  import { parsedStudioOptionsPropType } from '../../shared/StudioLtiSupportUtils';
41
- import RCEGlobals from '../../../RCEGlobals';
42
41
 
43
42
  const getLiveRegion = () => document.getElementById('flash_screenreader_holder');
44
43
 
45
44
  export default function VideoOptionsTray(_ref) {
46
- var _RCEGlobals$getConfig;
47
-
48
45
  let {
49
46
  videoOptions,
50
47
  onRequestClose,
@@ -71,9 +68,7 @@ export default function VideoOptionsTray(_ref) {
71
68
  const [minWidth] = useState(MIN_WIDTH_VIDEO);
72
69
  const [minHeight] = useState(Math.round(videoHeight / videoWidth * MIN_WIDTH_VIDEO));
73
70
  const [minPercentage] = useState(MIN_PERCENTAGE);
74
- const lock_statuses = (_RCEGlobals$getConfig = RCEGlobals.getConfig()) === null || _RCEGlobals$getConfig === void 0 ? void 0 : _RCEGlobals$getConfig.lockedAttachments;
75
71
  const isStudio = !!studioOptions;
76
- const isLocked = !!lock_statuses && !!lock_statuses[videoOptions.attachmentId];
77
72
  const showDisplayOptions = !isStudio || studioOptions.convertibleToLink;
78
73
  const showSizeControls = !isStudio || studioOptions.resizable;
79
74
  const dimensionsState = useDimensionsState(videoOptions, {
@@ -129,8 +124,7 @@ export default function VideoOptionsTray(_ref) {
129
124
  appliedWidth,
130
125
  displayAs,
131
126
  subtitles,
132
- updateMediaObject,
133
- isLocked
127
+ updateMediaObject
134
128
  });
135
129
  }
136
130
 
@@ -213,7 +207,7 @@ export default function VideoOptionsTray(_ref) {
213
207
  shouldShrink: true
214
208
  }, /*#__PURE__*/React.createElement(Flex, {
215
209
  direction: "column"
216
- }, !isLocked && /*#__PURE__*/React.createElement(Flex.Item, {
210
+ }, /*#__PURE__*/React.createElement(Flex.Item, {
217
211
  padding: "small"
218
212
  }, isStudio ? /*#__PURE__*/React.createElement(Flex, {
219
213
  direction: "column"
@@ -272,7 +266,7 @@ export default function VideoOptionsTray(_ref) {
272
266
  minWidth: minWidth,
273
267
  minPercentage: minPercentage,
274
268
  hidePercentage: true
275
- }))), !isStudio && !isLocked && /*#__PURE__*/React.createElement(Flex.Item, {
269
+ }))), !isStudio && /*#__PURE__*/React.createElement(Flex.Item, {
276
270
  padding: "small"
277
271
  }, /*#__PURE__*/React.createElement(FormFieldGroup, {
278
272
  description: formatMessage('Closed Captions/Subtitles')
@@ -24,41 +24,33 @@ import { BaseButton, CloseButton } from '@instructure/ui-buttons';
24
24
  import { Heading } from '@instructure/ui-heading';
25
25
  import { Table } from '@instructure/ui-table';
26
26
  import formatMessage from '../../../../format-message';
27
- import { instuiPopupMountNode } from '../../../../util/fullscreenHelpers'; // Doing this to avoid TS2339 errors -- TODO: remove once we're on InstUI 8
28
-
29
- const {
30
- Head,
31
- Row,
32
- ColHeader,
33
- Body,
34
- Cell
35
- } = Table;
27
+ import { instuiPopupMountNode } from '../../../../util/fullscreenHelpers';
36
28
 
37
29
  const renderBody = (headers, rows) => {
38
30
  return /*#__PURE__*/React.createElement(Table, {
39
31
  caption: formatMessage('Word Count')
40
- }, /*#__PURE__*/React.createElement(Head, null, /*#__PURE__*/React.createElement(Row, null, headers.map(_ref => {
32
+ }, /*#__PURE__*/React.createElement(Table.Head, null, /*#__PURE__*/React.createElement(Table.Row, null, headers.map(_ref => {
41
33
  let {
42
34
  id,
43
35
  getLabel
44
36
  } = _ref;
45
- return /*#__PURE__*/React.createElement(ColHeader, {
37
+ return /*#__PURE__*/React.createElement(Table.ColHeader, {
46
38
  key: id,
47
39
  id: id
48
40
  }, getLabel());
49
- }))), /*#__PURE__*/React.createElement(Body, null, rows.map(_ref2 => {
41
+ }))), /*#__PURE__*/React.createElement(Table.Body, null, rows.map(_ref2 => {
50
42
  let {
51
43
  label,
52
44
  documentCount,
53
45
  selectionCount
54
46
  } = _ref2;
55
- return /*#__PURE__*/React.createElement(Row, {
47
+ return /*#__PURE__*/React.createElement(Table.Row, {
56
48
  key: label
57
- }, /*#__PURE__*/React.createElement(Cell, {
49
+ }, /*#__PURE__*/React.createElement(Table.Cell, {
58
50
  key: "label"
59
- }, label), /*#__PURE__*/React.createElement(Cell, {
51
+ }, label), /*#__PURE__*/React.createElement(Table.Cell, {
60
52
  key: "document"
61
- }, documentCount), /*#__PURE__*/React.createElement(Cell, {
53
+ }, documentCount), /*#__PURE__*/React.createElement(Table.Cell, {
62
54
  key: "selection"
63
55
  }, selectionCount));
64
56
  })));
@@ -241,6 +241,7 @@ export default function CanvasContentTray(props) {
241
241
  const [hidingTrayOnAction, setHidingTrayOnAction] = useState(true);
242
242
  const trayRef = useRef(null);
243
243
  const scrollingAreaRef = useRef(null);
244
+ const closeButtonRef = useRef(null);
244
245
  const [filterSettings, setFilterSettings] = useFilterSettings();
245
246
  const [isEditTray, setIsEditTray] = useState(false);
246
247
  const [link, setLink] = useState(null);
@@ -267,6 +268,8 @@ export default function CanvasContentTray(props) {
267
268
  useEffect(() => {
268
269
  const controller = {
269
270
  showTrayForPlugin(plugin) {
271
+ var _closeButtonRef$curre;
272
+
270
273
  // increment a counter that's used as the key when rendering
271
274
  // this gets us a new instance everytime, which is necessary
272
275
  // to get the queries run so we have up to date data.
@@ -294,6 +297,8 @@ export default function CanvasContentTray(props) {
294
297
  } else {
295
298
  setIsEditTray(false);
296
299
  }
300
+
301
+ (_closeButtonRef$curre = closeButtonRef.current) === null || _closeButtonRef$curre === void 0 ? void 0 : _closeButtonRef$curre.focus();
297
302
  },
298
303
 
299
304
  hideTray(forceClose) {
@@ -474,7 +479,8 @@ export default function CanvasContentTray(props) {
474
479
  offset: "medium",
475
480
  onClick: handleDismissTray,
476
481
  "data-testid": "CloseButton_ContentTray",
477
- screenReaderLabel: formatMessage('Close')
482
+ screenReaderLabel: formatMessage('Close'),
483
+ elementRef: el => closeButtonRef.current = el
478
484
  })), isEditTray && /*#__PURE__*/React.createElement(LinkDisplay, {
479
485
  linkText: linkText,
480
486
  placeholderText: (link === null || link === void 0 ? void 0 : link.title) || placeholderText,
@@ -15,7 +15,7 @@
15
15
  * You should have received a copy of the GNU Affero General Public License along
16
16
  * with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
- import { parse } from 'url';
18
+ import { format, parse } from 'url';
19
19
  import { absoluteToRelativeUrl } from '../../../common/fileUrl';
20
20
  import { IconAudioLine, IconDocumentLine, IconMsExcelLine, IconMsPptLine, IconMsWordLine, IconPdfLine, IconVideoLine } from '@instructure/ui-icons';
21
21
  import RCEGlobals from '../../RCEGlobals';
@@ -94,13 +94,21 @@ export function mediaPlayerURLFromFile(file, canvasOrigin) {
94
94
  const type = content_type.replace(/\/.*$/, '');
95
95
 
96
96
  if ((_RCEGlobals$getFeatur = RCEGlobals.getFeatures()) !== null && _RCEGlobals$getFeatur !== void 0 && _RCEGlobals$getFeatur.media_links_use_attachment_id && isAudioOrVideo(content_type) && file.id) {
97
- if (!file.url && !file.href) {
98
- return `/media_attachments_iframe/${file.id}?type=${type}&embedded=true`;
97
+ const url = parse(`/media_attachments_iframe/${file.id}`, true);
98
+ url.query.type = type;
99
+ url.query.embedded = true;
100
+
101
+ if (file.uuid && file.contextType == 'User') {
102
+ url.query.verifier = file.uuid;
103
+ } else if (file.url || file.href) {
104
+ const parsed_url = parse(file.url || file.href, true);
105
+
106
+ if (parsed_url.query.verifier) {
107
+ url.query.verifier = parsed_url.query.verifier;
108
+ }
99
109
  }
100
110
 
101
- const parsed_url = parse(file.url || file.href, true);
102
- const verifier = parsed_url.query.verifier ? `&verifier=${parsed_url.query.verifier}` : '';
103
- return `/media_attachments_iframe/${file.id}?type=${type}${verifier}&embedded=true`;
111
+ return format(url);
104
112
  }
105
113
 
106
114
  if (file.embedded_iframe_url) {