user-nav.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. import React from "react"
  2. import { connect } from "react-redux"
  3. import Avatar from "misago/components/avatar"
  4. import ChangeAvatarModal, { select } from "misago/components/change-avatar/root"
  5. import NavbarSearch from "misago/components/navbar-search"
  6. import misago from "misago"
  7. import dropdown from "misago/services/mobile-navbar-dropdown"
  8. import modal from "misago/services/modal"
  9. export class UserMenu extends React.Component {
  10. logout() {
  11. let decision = confirm(gettext("Are you sure you want to sign out?"))
  12. if (decision) {
  13. $("#hidden-logout-form").submit()
  14. }
  15. }
  16. changeAvatar() {
  17. modal.show(connect(select)(ChangeAvatarModal))
  18. }
  19. render() {
  20. const { user } = this.props
  21. return (
  22. <ul
  23. className="dropdown-menu user-dropdown dropdown-menu-right"
  24. role="menu"
  25. >
  26. <li className="dropdown-header">
  27. <strong>{user.username}</strong>
  28. <ul className="list-unstyled list-inline user-stats">
  29. <li>
  30. <span className="material-icon">message</span>
  31. {user.posts}
  32. </li>
  33. <li>
  34. <span className="material-icon">forum</span>
  35. {user.threads}
  36. </li>
  37. <li>
  38. <span className="material-icon">favorite</span>
  39. {user.followers}
  40. </li>
  41. <li>
  42. <span className="material-icon">favorite_outline</span>
  43. {user.following}
  44. </li>
  45. </ul>
  46. </li>
  47. <li className="divider" />
  48. <li>
  49. <a href={user.url}>
  50. <span className="material-icon">account_circle</span>
  51. {gettext("See your profile")}
  52. </a>
  53. </li>
  54. <li>
  55. <a href={misago.get("USERCP_URL")}>
  56. <span className="material-icon">done_all</span>
  57. {gettext("Change options")}
  58. </a>
  59. </li>
  60. <li>
  61. <button
  62. className="btn-link"
  63. onClick={this.changeAvatar}
  64. type="button"
  65. >
  66. <span className="material-icon">portrait</span>
  67. {gettext("Change avatar")}
  68. </button>
  69. </li>
  70. {!!user.acl.can_use_private_threads && (
  71. <li>
  72. <a href={misago.get("PRIVATE_THREADS_URL")}>
  73. <span className="material-icon">message</span>
  74. {gettext("Private threads")}
  75. <PrivateThreadsBadge user={user} />
  76. </a>
  77. </li>
  78. )}
  79. <li className="divider" />
  80. <li className="dropdown-buttons">
  81. <button
  82. className="btn btn-default btn-block"
  83. onClick={this.logout}
  84. type="button"
  85. >
  86. {gettext("Log out")}
  87. </button>
  88. </li>
  89. </ul>
  90. )
  91. }
  92. }
  93. export function PrivateThreadsBadge({ user }) {
  94. if (!user.unread_private_threads) return null
  95. return <span className="badge">{user.unread_private_threads}</span>
  96. }
  97. export function UserNav({ user }) {
  98. return (
  99. <ul className="ul nav navbar-nav nav-user">
  100. <li>
  101. <NavbarSearch />
  102. </li>
  103. <UserPrivateThreadsLink user={user} />
  104. <li className="dropdown">
  105. <a
  106. aria-haspopup="true"
  107. aria-expanded="false"
  108. className="dropdown-toggle"
  109. data-toggle="dropdown"
  110. href={user.url}
  111. role="button"
  112. >
  113. <Avatar user={user} size="64" />
  114. </a>
  115. <UserMenu user={user} />
  116. </li>
  117. </ul>
  118. )
  119. }
  120. export function UserPrivateThreadsLink({ user }) {
  121. if (!user.acl.can_use_private_threads) return null
  122. let title = null
  123. if (user.unread_private_threads) {
  124. title = gettext("You have unread private threads!")
  125. } else {
  126. title = gettext("Private threads")
  127. }
  128. return (
  129. <li>
  130. <a
  131. className="navbar-icon"
  132. href={misago.get("PRIVATE_THREADS_URL")}
  133. title={title}
  134. >
  135. <span className="material-icon">message</span>
  136. {user.unread_private_threads > 0 && (
  137. <span className="badge">{user.unread_private_threads}</span>
  138. )}
  139. </a>
  140. </li>
  141. )
  142. }
  143. export function selectUserMenu(state) {
  144. return {
  145. user: state.auth.user
  146. }
  147. }
  148. export class CompactUserNav extends React.Component {
  149. showUserMenu() {
  150. dropdown.showConnected("user-menu", connect(selectUserMenu)(UserMenu))
  151. }
  152. render() {
  153. return (
  154. <button type="button" onClick={this.showUserMenu}>
  155. <Avatar user={this.props.user} size="50" />
  156. </button>
  157. )
  158. }
  159. }