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.

GlobalMessages.tsx 3.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2021 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. import { keyframes } from '@emotion/core';
  21. import * as React from 'react';
  22. import { cutLongWords } from '../../helpers/path';
  23. import { styled, themeGet, themeSize } from '../theme';
  24. import { ClearButton } from './buttons';
  25. interface Message {
  26. id: string;
  27. level: 'ERROR' | 'SUCCESS';
  28. message: string;
  29. }
  30. export interface GlobalMessagesProps {
  31. closeGlobalMessage: (id: string) => void;
  32. messages: Message[];
  33. }
  34. export default function GlobalMessages({ closeGlobalMessage, messages }: GlobalMessagesProps) {
  35. if (messages.length === 0) {
  36. return null;
  37. }
  38. return (
  39. <MessagesContainer>
  40. {messages.map((message) => (
  41. <GlobalMessage closeGlobalMessage={closeGlobalMessage} key={message.id} message={message} />
  42. ))}
  43. </MessagesContainer>
  44. );
  45. }
  46. const MessagesContainer = styled.div`
  47. position: fixed;
  48. z-index: ${themeGet('zIndexes', 'processContainerZIndex')};
  49. top: 0;
  50. left: 50%;
  51. width: 350px;
  52. margin-left: -175px;
  53. `;
  54. export class GlobalMessage extends React.PureComponent<{
  55. closeGlobalMessage: (id: string) => void;
  56. message: Message;
  57. }> {
  58. handleClose = () => {
  59. this.props.closeGlobalMessage(this.props.message.id);
  60. };
  61. render() {
  62. const { message } = this.props;
  63. return (
  64. <Message
  65. data-test={`global-message__${message.level}`}
  66. level={message.level}
  67. role={message.level === 'SUCCESS' ? 'status' : 'alert'}>
  68. {cutLongWords(message.message)}
  69. <CloseButton
  70. className="button-small"
  71. color="#fff"
  72. level={message.level}
  73. onClick={this.handleClose}
  74. />
  75. </Message>
  76. );
  77. }
  78. }
  79. const appearAnim = keyframes`
  80. from {
  81. opacity: 0;
  82. }
  83. to {
  84. opacity: 1;
  85. }
  86. `;
  87. const Message = styled.div<Pick<Message, 'level'>>`
  88. position: relative;
  89. padding: 0 30px 0 10px;
  90. line-height: ${themeSize('controlHeight')};
  91. border-radius: 0 0 3px 3px;
  92. box-sizing: border-box;
  93. color: #ffffff;
  94. background-color: ${({ level, theme }) =>
  95. level === 'SUCCESS' ? theme.colors.green : theme.colors.red};
  96. text-align: center;
  97. opacity: 0;
  98. animation: ${appearAnim} 0.2s ease forwards;
  99. & + & {
  100. margin-top: calc(${themeSize('gridSize')} / 2);
  101. border-radius: 3px;
  102. }
  103. `;
  104. const CloseButton = styled(ClearButton)<Pick<Message, 'level'>>`
  105. position: absolute;
  106. top: calc(${themeSize('gridSize')} / 4);
  107. right: calc(${themeSize('gridSize')} / 4);
  108. &:hover svg,
  109. &:focus svg {
  110. color: ${({ level, theme }) => (level === 'SUCCESS' ? theme.colors.green : theme.colors.red)};
  111. }
  112. `;