Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

Notification.js 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. // @flow
  2. import Flag from '@atlaskit/flag';
  3. import EditorErrorIcon from '@atlaskit/icon/glyph/editor/error';
  4. import EditorInfoIcon from '@atlaskit/icon/glyph/editor/info';
  5. import EditorSuccessIcon from '@atlaskit/icon/glyph/editor/success';
  6. import EditorWarningIcon from '@atlaskit/icon/glyph/editor/warning';
  7. import PeopleIcon from '@atlaskit/icon/glyph/people';
  8. import PersonIcon from '@atlaskit/icon/glyph/person';
  9. import QuestionsIcon from '@atlaskit/icon/glyph/questions';
  10. import React from 'react';
  11. import { translate } from '../../../base/i18n';
  12. import Message from '../../../base/react/components/web/Message';
  13. import { colors } from '../../../base/ui/Tokens';
  14. import { NOTIFICATION_ICON, NOTIFICATION_TYPE } from '../../constants';
  15. import AbstractNotification, {
  16. type Props
  17. } from '../AbstractNotification';
  18. declare var interfaceConfig: Object;
  19. /**
  20. * Secondary colors for notification icons.
  21. *
  22. * @type {{error, info, normal, success, warning}}
  23. */
  24. const ICON_COLOR = {
  25. error: colors.error06,
  26. normal: colors.primary06,
  27. warning: colors.warning05
  28. };
  29. /**
  30. * Implements a React {@link Component} to display a notification.
  31. *
  32. * @augments Component
  33. */
  34. class Notification extends AbstractNotification<Props> {
  35. /**
  36. * Implements React's {@link Component#render()}.
  37. *
  38. * @inheritdoc
  39. * @returns {ReactElement}
  40. */
  41. render() {
  42. const {
  43. hideErrorSupportLink,
  44. t,
  45. title,
  46. titleArguments,
  47. titleKey,
  48. uid
  49. } = this.props;
  50. return (
  51. <Flag
  52. actions = { this._mapAppearanceToButtons(hideErrorSupportLink) }
  53. description = { this._renderDescription() }
  54. icon = { this._mapAppearanceToIcon() }
  55. id = { uid }
  56. testId = { titleKey }
  57. title = { title || t(titleKey, titleArguments) } />
  58. );
  59. }
  60. _getDescription: () => Array<string>;
  61. _getDescriptionKey: () => string;
  62. _onDismissed: () => void;
  63. /**
  64. * Creates a {@code ReactElement} for displaying the contents of the
  65. * notification.
  66. *
  67. * @private
  68. * @returns {ReactElement}
  69. */
  70. _renderDescription() {
  71. const description = this._getDescription().join(' ');
  72. // the id is used for testing the UI
  73. return (
  74. <p data-testid = { this._getDescriptionKey() } >
  75. <Message text = { description } />
  76. </p>
  77. );
  78. }
  79. /**
  80. * Opens the support page.
  81. *
  82. * @returns {void}
  83. * @private
  84. */
  85. _onOpenSupportLink() {
  86. window.open(interfaceConfig.SUPPORT_URL, '_blank', 'noopener');
  87. }
  88. /**
  89. * Creates action button configurations for the notification based on
  90. * notification appearance.
  91. *
  92. * @param {boolean} hideErrorSupportLink - Indicates if the support link
  93. * should be hidden in the error messages.
  94. * @private
  95. * @returns {Object[]}
  96. */
  97. _mapAppearanceToButtons(hideErrorSupportLink) {
  98. switch (this.props.appearance) {
  99. case NOTIFICATION_TYPE.ERROR: {
  100. const buttons = [
  101. {
  102. content: this.props.t('dialog.dismiss'),
  103. onClick: this._onDismissed
  104. }
  105. ];
  106. if (!hideErrorSupportLink && interfaceConfig.SUPPORT_URL) {
  107. buttons.push({
  108. content: this.props.t('dialog.contactSupport'),
  109. onClick: this._onOpenSupportLink
  110. });
  111. }
  112. return buttons;
  113. }
  114. case NOTIFICATION_TYPE.WARNING:
  115. return [
  116. {
  117. content: this.props.t('dialog.Ok'),
  118. onClick: this._onDismissed
  119. }
  120. ];
  121. default:
  122. if (this.props.customActionNameKey?.length && this.props.customActionHandler?.length) {
  123. return this.props.customActionNameKey.map((customAction: string, customActionIndex: number) => {
  124. return {
  125. content: this.props.t(customAction),
  126. onClick: () => {
  127. if (this.props.customActionHandler[customActionIndex]()) {
  128. this._onDismissed();
  129. }
  130. }
  131. };
  132. });
  133. }
  134. return [];
  135. }
  136. }
  137. /**
  138. * Returns the Icon type component to be used, based on icon or appearance.
  139. *
  140. * @returns {ReactElement}
  141. */
  142. _getIcon() {
  143. let Icon;
  144. switch (this.props.icon || this.props.appearance) {
  145. case NOTIFICATION_ICON.ERROR:
  146. Icon = EditorErrorIcon;
  147. break;
  148. case NOTIFICATION_ICON.WARNING:
  149. Icon = EditorWarningIcon;
  150. break;
  151. case NOTIFICATION_ICON.SUCCESS:
  152. Icon = EditorSuccessIcon;
  153. break;
  154. case NOTIFICATION_ICON.MESSAGE:
  155. Icon = QuestionsIcon;
  156. break;
  157. case NOTIFICATION_ICON.PARTICIPANT:
  158. Icon = PersonIcon;
  159. break;
  160. case NOTIFICATION_ICON.PARTICIPANTS:
  161. Icon = PeopleIcon;
  162. break;
  163. default:
  164. Icon = EditorInfoIcon;
  165. break;
  166. }
  167. return Icon;
  168. }
  169. /**
  170. * Creates an icon component depending on the configured notification
  171. * appearance.
  172. *
  173. * @private
  174. * @returns {ReactElement}
  175. */
  176. _mapAppearanceToIcon() {
  177. const { appearance, icon } = this.props;
  178. const secIconColor = ICON_COLOR[appearance];
  179. const iconSize = 'medium';
  180. const Icon = this._getIcon();
  181. return (<div className = { icon }>
  182. <div className = { `ribbon ${appearance}` } />
  183. <Icon
  184. label = { appearance }
  185. secondaryColor = { secIconColor }
  186. size = { iconSize } />
  187. </div>);
  188. }
  189. }
  190. export default translate(Notification);