UsersListRow.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /*
  2. * Copyright (C) 2015 - 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 PropTypes from 'prop-types'
  20. import I18n from 'i18n!account_course_user_search'
  21. import $ from 'jquery'
  22. import EditUserDetailsDialog from 'jsx/shared/EditUserDetailsDialog'
  23. import 'jquery.instructure_date_and_time'
  24. const { object, string, func, shape, bool } = PropTypes
  25. export default class UsersListRow extends React.Component {
  26. static propTypes = {
  27. accountId: string,
  28. timezones: object.isRequired,
  29. user: shape({
  30. id: string.isRequired,
  31. name: string.isRequired,
  32. avatar_url: string,
  33. }).isRequired,
  34. handlers: shape({
  35. handleOpenEditUserDialog: func,
  36. handleSubmitEditUserForm: func,
  37. handleCloseEditUserDialog: func
  38. }).isRequired,
  39. permissions: shape({
  40. can_masquerade: bool,
  41. can_message_users: bool,
  42. can_edit_users: bool
  43. }).isRequired
  44. }
  45. renderLinks () {
  46. const links = [];
  47. const { id, name } = this.props.user;
  48. const { handleOpenEditUserDialog } = this.props.handlers;
  49. if (this.props.permissions.can_masquerade) {
  50. links.push(
  51. <a
  52. className="Button Button--icon-action user_actions_js_test"
  53. key="masqueradeLink"
  54. href={`/users/${id}/masquerade`}
  55. >
  56. <span className="screenreader-only">{I18n.t('Act as %{name}', {name})}</span>
  57. <i className="icon-masquerade" aria-hidden="true"></i>
  58. </a>
  59. );
  60. }
  61. if (this.props.permissions.can_message_users) {
  62. links.push(
  63. <a
  64. className="Button Button--icon-action user_actions_js_test"
  65. key="messageUserLink"
  66. href={`/conversations?user_name=${name}&user_id=${id}`}
  67. >
  68. <span className="screenreader-only">{I18n.t("Send message to %{name}", {name})}</span>
  69. <i className="icon-message" aria-hidden="true"></i>
  70. </a>
  71. );
  72. }
  73. if (this.props.permissions.can_edit_users) {
  74. links.push(
  75. <button
  76. className="Button Button--icon-action user_actions_js_test"
  77. key="canEditUserLink"
  78. onClick={handleOpenEditUserDialog.bind(null, this.props.user)}
  79. type="button"
  80. >
  81. <span className="screenreader-only">{I18n.t("Edit %{name}", {name})}</span>
  82. <i className="icon-edit" aria-hidden="true"></i>
  83. </button>
  84. );
  85. }
  86. return (
  87. <div className="courses-user-list-actions">
  88. {links}
  89. </div>
  90. );
  91. }
  92. render () {
  93. const { id, name, sis_user_id, email, avatar_url, last_login, editUserDialogOpen } = this.props.user;
  94. const { handleSubmitEditUserForm, handleCloseEditUserDialog } = this.props.handlers;
  95. const url = `/accounts/${this.props.accountId}/users/${id}`;
  96. return (
  97. <div role='row' className="grid-row middle-xs pad-box-mini border border-b">
  98. <div className="col-xs-3" role="gridcell">
  99. <div className="grid-row middle-xs">
  100. <span className="userAvatar">
  101. <span className="userUrl">
  102. {!!avatar_url &&
  103. <span className="ic-avatar UserListRow__Avatar">
  104. <img src={avatar_url} alt={`User avatar for ${name}`} />
  105. </span>
  106. }
  107. <a href={url}>{name}</a>
  108. </span>
  109. </span>
  110. </div>
  111. </div>
  112. <div className="col-xs-3" role='gridcell'>
  113. {email}
  114. </div>
  115. <div className="col-xs-1" role='gridcell'>
  116. {sis_user_id}
  117. </div>
  118. <div className="col-xs-2" role='gridcell'>
  119. {$.datetimeString(last_login)}
  120. </div>
  121. <div className="col-xs-2" role='gridcell'>
  122. {this.renderLinks()}
  123. <EditUserDetailsDialog
  124. submitEditUserForm={handleSubmitEditUserForm}
  125. user={this.props.user}
  126. timezones={this.props.timezones}
  127. isOpen={editUserDialogOpen}
  128. contentLabel={I18n.t('Edit User')}
  129. onRequestClose={handleCloseEditUserDialog.bind(null, this.props.user)}
  130. />
  131. </div>
  132. </div>
  133. );
  134. }
  135. }