AssignmentRowCell.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /*
  2. * Copyright (C) 2017 - present Instructure, Inc.
  3. *
  4. * This file is part of Canvas.
  5. *
  6. * Canvas is free software: you can redistribute it and/or modify it under
  7. * the terms of the GNU Affero General Public License as published by the Free
  8. * Software Foundation, version 3 of the License.
  9. *
  10. * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
  11. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  13. * details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License along
  16. * with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. import React from 'react';
  19. import { bool, func, shape, string } from 'prop-types';
  20. import Button from 'instructure-ui/lib/components/Button';
  21. import SubmissionCell from 'compiled/gradezilla/SubmissionCell';
  22. import IconExpandLeftLine from 'instructure-icons/lib/Line/IconExpandLeftLine';
  23. import I18n from 'i18n!gradebook';
  24. function renderSubmissionCell (options) {
  25. const assignment = options.column.object;
  26. if (assignment.grading_type === 'points' && assignment.points_possible != null) {
  27. return new SubmissionCell.out_of(options); // eslint-disable-line new-cap
  28. }
  29. return new (SubmissionCell[assignment.grading_type] || SubmissionCell)(options);
  30. }
  31. class AssignmentRowCell extends React.Component {
  32. static propTypes = {
  33. isSubmissionTrayOpen: bool.isRequired,
  34. editorOptions: shape({
  35. column: shape({
  36. assignmentId: string.isRequired
  37. }).isRequired,
  38. grid: shape({}).isRequired,
  39. item: shape({
  40. id: string.isRequired
  41. }).isRequired,
  42. }).isRequired,
  43. onToggleSubmissionTrayOpen: func.isRequired
  44. };
  45. constructor (props) {
  46. super(props);
  47. this.bindContainerRef = (ref) => { this.container = ref };
  48. this.bindToggleTrayButtonRef = (ref) => { this.trayButton = ref };
  49. }
  50. componentDidMount () {
  51. this.submissionCell = renderSubmissionCell({ ...this.props.editorOptions, container: this.container });
  52. }
  53. componentDidUpdate (prevProps) {
  54. if (prevProps.isSubmissionTrayOpen && !this.props.isSubmissionTrayOpen) {
  55. this.focusToggleTrayButton();
  56. }
  57. }
  58. componentWillUnmount () {
  59. this.submissionCell.destroy();
  60. }
  61. handleKeyDown = (event) => {
  62. const submissionCellHasFocus = this.container.contains(document.activeElement);
  63. const popoverTriggerHasFocus = this.trayButton.focused;
  64. if (event.which === 9) { // Tab
  65. if (!event.shiftKey && submissionCellHasFocus) {
  66. // browser will set focus on the tray button
  67. return false; // prevent Grid behavior
  68. } else if (event.shiftKey && popoverTriggerHasFocus) {
  69. // browser will set focus on the submission cell
  70. return false; // prevent Grid behavior
  71. }
  72. }
  73. if (event.which === 13 && popoverTriggerHasFocus) { // Enter
  74. // browser will activate the tray button
  75. return false; // prevent Grid behavior
  76. }
  77. return undefined;
  78. }
  79. handleToggleTrayButtonClick = () => {
  80. const options = this.props.editorOptions;
  81. this.props.onToggleSubmissionTrayOpen(options.item.id, options.column.assignmentId);
  82. }
  83. applyValue (item, state) {
  84. this.submissionCell.applyValue(item, state);
  85. }
  86. focus () {
  87. this.submissionCell.focus();
  88. }
  89. focusToggleTrayButton = () => {
  90. if (this.trayButton) {
  91. this.trayButton.focus();
  92. }
  93. }
  94. isValueChanged () {
  95. return this.submissionCell.isValueChanged();
  96. }
  97. loadValue (item) {
  98. this.submissionCell.loadValue(item);
  99. }
  100. serializeValue () {
  101. return this.submissionCell.serializeValue();
  102. }
  103. validate () {
  104. return this.submissionCell.validate();
  105. }
  106. render () {
  107. return (
  108. <div className="Grid__AssignmentRowCell">
  109. <div className="Grid__AssignmentRowCell__Notifications" />
  110. <div className="Grid__AssignmentRowCell__Content" ref={this.bindContainerRef} />
  111. <div className="Grid__AssignmentRowCell__Options">
  112. <Button
  113. ref={this.bindToggleTrayButtonRef}
  114. onClick={this.handleToggleTrayButtonClick}
  115. size="small"
  116. variant="icon"
  117. >
  118. <IconExpandLeftLine title={I18n.t('Open submission tray')} />
  119. </Button>
  120. </div>
  121. </div>
  122. );
  123. }
  124. }
  125. export default AssignmentRowCell;