You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Notification.web.js 7.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. import Flag from '@atlaskit/flag';
  2. import EditorInfoIcon from '@atlaskit/icon/glyph/editor/info';
  3. import PropTypes from 'prop-types';
  4. import ErrorIcon from '@atlaskit/icon/glyph/error';
  5. import WarningIcon from '@atlaskit/icon/glyph/warning';
  6. import { colors } from '@atlaskit/theme';
  7. import React, { Component } from 'react';
  8. import { translate } from '../../base/i18n';
  9. import { NOTIFICATION_TYPE } from '../constants';
  10. declare var interfaceConfig: Object;
  11. /**
  12. * Secondary colors for notification icons.
  13. *
  14. * @type {{error, info, normal, success, warning}}
  15. */
  16. const ICON_COLOR = {
  17. error: colors.R400,
  18. info: colors.N500,
  19. normal: colors.N0,
  20. success: colors.G400,
  21. warning: colors.Y200
  22. };
  23. /**
  24. * Implements a React {@link Component} to display a notification.
  25. *
  26. * @extends Component
  27. */
  28. class Notification extends Component {
  29. /**
  30. * Default values for {@code Notification} component's properties.
  31. *
  32. * @static
  33. */
  34. static defaultProps = {
  35. appearance: NOTIFICATION_TYPE.NORMAL
  36. };
  37. /**
  38. * {@code Notification} component's property types.
  39. *
  40. * @static
  41. */
  42. static propTypes = {
  43. /**
  44. * Display appearance for the component, passed directly to
  45. * {@code Flag}.
  46. */
  47. appearance: PropTypes.string,
  48. /**
  49. * The text to display in the body of the notification. If not passed
  50. * in, the passed in descriptionKey will be used.
  51. */
  52. defaultTitleKey: PropTypes.string,
  53. /**
  54. * The description string.
  55. */
  56. description: PropTypes.string,
  57. /**
  58. * The translation arguments that may be necessary for the description.
  59. */
  60. descriptionArguments: PropTypes.object,
  61. /**
  62. * The translation key to use as the body of the notification.
  63. */
  64. descriptionKey: PropTypes.string,
  65. /**
  66. * Whether the support link should be hidden in the case of an error
  67. * message.
  68. */
  69. hideErrorSupportLink: PropTypes.bool,
  70. /**
  71. * Whether or not the dismiss button should be displayed. This is passed
  72. * in by {@code FlagGroup}.
  73. */
  74. isDismissAllowed: PropTypes.bool,
  75. /**
  76. * Callback invoked when the user clicks to dismiss the notification.
  77. * this is passed in by {@code FlagGroup}.
  78. */
  79. onDismissed: PropTypes.func,
  80. /**
  81. * Invoked to obtain translated strings.
  82. */
  83. t: PropTypes.func,
  84. /**
  85. * The text to display at the top of the notification. If not passed in,
  86. * the passed in titleKey will be used.
  87. */
  88. title: PropTypes.string,
  89. /**
  90. * The translation key to display as the title of the notification if
  91. * no title is provided.
  92. */
  93. titleKey: PropTypes.string,
  94. /**
  95. * The unique identifier for the notification. Passed back by the
  96. * {@code Flag} component in the onDismissed callback.
  97. */
  98. uid: PropTypes.number
  99. };
  100. /**
  101. * Initializes a new {@code Notification} instance.
  102. *
  103. * @param {Object} props - The read-only properties with which the new
  104. * instance is to be initialized.
  105. */
  106. constructor(props) {
  107. super(props);
  108. // Bind event handler so it is only bound once for every instance.
  109. this._onDismissed = this._onDismissed.bind(this);
  110. }
  111. /**
  112. * Implements React's {@link Component#render()}.
  113. *
  114. * @inheritdoc
  115. * @returns {ReactElement}
  116. */
  117. render() {
  118. const {
  119. hideErrorSupportLink,
  120. appearance,
  121. titleKey,
  122. descriptionArguments,
  123. descriptionKey,
  124. description,
  125. isDismissAllowed,
  126. onDismissed,
  127. t,
  128. title,
  129. uid
  130. } = this.props;
  131. return (
  132. <Flag
  133. actions = { this._mapAppearanceToButtons(hideErrorSupportLink) }
  134. appearance = { appearance }
  135. description = { description
  136. || t(descriptionKey, descriptionArguments) }
  137. icon = { this._mapAppearanceToIcon() }
  138. id = { uid }
  139. isDismissAllowed = { isDismissAllowed }
  140. onDismissed = { onDismissed }
  141. title = { title || t(titleKey) } />
  142. );
  143. }
  144. /**
  145. * Calls back into {@code FlagGroup} to dismiss the notification.
  146. *
  147. * @private
  148. * @returns {void}
  149. */
  150. _onDismissed() {
  151. this.props.onDismissed(this.props.uid);
  152. }
  153. /**
  154. * Opens the support page.
  155. *
  156. * @returns {void}
  157. * @private
  158. */
  159. _onOpenSupportLink() {
  160. window.open(interfaceConfig.SUPPORT_URL, '_blank', 'noopener');
  161. }
  162. /**
  163. * Creates action button configurations for the notification based on
  164. * notification appearance.
  165. *
  166. * @param {boolean} hideErrorSupportLink - Indicates if the support link
  167. * should be hidden in the error messages.
  168. * @private
  169. * @returns {Object[]}
  170. */
  171. _mapAppearanceToButtons(hideErrorSupportLink) {
  172. switch (this.props.appearance) {
  173. case NOTIFICATION_TYPE.ERROR: {
  174. const buttons = [
  175. {
  176. content: this.props.t('dialog.dismiss'),
  177. onClick: this._onDismissed
  178. }
  179. ];
  180. if (!hideErrorSupportLink) {
  181. buttons.push({
  182. content: this.props.t('dialog.contactSupport'),
  183. onClick: this._onOpenSupportLink
  184. });
  185. }
  186. return buttons;
  187. }
  188. case NOTIFICATION_TYPE.WARNING:
  189. return [
  190. {
  191. content: this.props.t('dialog.Ok'),
  192. onClick: this._onDismissed
  193. }
  194. ];
  195. default:
  196. return [];
  197. }
  198. }
  199. /**
  200. * Creates an icon component depending on the configured notification
  201. * appearance.
  202. *
  203. * @private
  204. * @returns {ReactElement}
  205. */
  206. _mapAppearanceToIcon() {
  207. const appearance = this.props.appearance;
  208. const secIconColor = ICON_COLOR[this.props.appearance];
  209. const iconSize = 'medium';
  210. switch (appearance) {
  211. case NOTIFICATION_TYPE.ERROR:
  212. return (
  213. <ErrorIcon
  214. label = { appearance }
  215. secondaryColor = { secIconColor }
  216. size = { iconSize } />
  217. );
  218. case NOTIFICATION_TYPE.WARNING:
  219. return (
  220. <WarningIcon
  221. label = { appearance }
  222. secondaryColor = { secIconColor }
  223. size = { iconSize } />
  224. );
  225. default:
  226. return (
  227. <EditorInfoIcon
  228. label = { appearance }
  229. secondaryColor = { secIconColor }
  230. size = { iconSize } />
  231. );
  232. }
  233. }
  234. }
  235. export default translate(Notification);