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.

ProductNewsMenuItem.tsx 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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 * as React from 'react';
  21. import { connect } from 'react-redux';
  22. import ChevronRightIcon from 'sonar-ui-common/components/icons/ChevronRightIcon';
  23. import DateFormatter from 'sonar-ui-common/components/intl/DateFormatter';
  24. import { translate } from 'sonar-ui-common/helpers/l10n';
  25. import { fetchPrismicNews, fetchPrismicRefs, PrismicNews } from '../../../api/news';
  26. import PlaceholderBar from '../../../components/ui/PlaceholderBar';
  27. import { getGlobalSettingValue, Store } from '../../../store/rootReducer';
  28. interface OwnProps {
  29. tag?: string;
  30. }
  31. interface StateProps {
  32. accessToken?: string;
  33. }
  34. type Props = OwnProps & StateProps;
  35. interface State {
  36. loading: boolean;
  37. news?: PrismicNews;
  38. }
  39. export class ProductNewsMenuItem extends React.PureComponent<Props, State> {
  40. mounted = false;
  41. state: State = { loading: false };
  42. componentDidMount() {
  43. this.mounted = true;
  44. this.fetchProductNews();
  45. }
  46. componentWillUnmount() {
  47. this.mounted = false;
  48. }
  49. fetchProductNews = () => {
  50. const { accessToken, tag } = this.props;
  51. if (accessToken) {
  52. this.setState({ loading: true });
  53. fetchPrismicRefs()
  54. .then(({ ref }) => fetchPrismicNews({ accessToken, ref, tag }))
  55. .then(
  56. news => {
  57. if (this.mounted) {
  58. this.setState({ news: news[0], loading: false });
  59. }
  60. },
  61. () => {
  62. if (this.mounted) {
  63. this.setState({ loading: false });
  64. }
  65. }
  66. );
  67. }
  68. };
  69. renderPlaceholder() {
  70. return (
  71. <a className="rich-item new-loading">
  72. <div className="flex-1">
  73. <div className="display-inline-flex-center">
  74. <h4>{translate('embed_docs.latest_blog')}</h4>
  75. <span className="note spacer-left">
  76. <PlaceholderBar color="#aaa" width={60} />
  77. </span>
  78. </div>
  79. <p className="little-spacer-bottom">
  80. <PlaceholderBar color="#aaa" width={84} /> <PlaceholderBar color="#aaa" width={48} />{' '}
  81. <PlaceholderBar color="#aaa" width={24} /> <PlaceholderBar color="#aaa" width={72} />{' '}
  82. <PlaceholderBar color="#aaa" width={24} /> <PlaceholderBar color="#aaa" width={48} />
  83. </p>
  84. </div>
  85. <ChevronRightIcon className="flex-0" />
  86. </a>
  87. );
  88. }
  89. render() {
  90. const link = 'https://blog.sonarsource.com/';
  91. const { loading, news } = this.state;
  92. if (loading) {
  93. return this.renderPlaceholder();
  94. }
  95. if (!news) {
  96. return null;
  97. }
  98. return (
  99. <a className="rich-item" href={link + news.uid} rel="noopener noreferrer" target="_blank">
  100. <div className="flex-1">
  101. <div className="display-inline-flex-center">
  102. <h4>{translate('embed_docs.latest_blog')}</h4>
  103. <DateFormatter date={news.last_publication_date}>
  104. {formattedDate => <span className="note spacer-left">{formattedDate}</span>}
  105. </DateFormatter>
  106. </div>
  107. <p className="little-spacer-bottom">{news.data.title}</p>
  108. </div>
  109. <ChevronRightIcon className="flex-0" />
  110. </a>
  111. );
  112. }
  113. }
  114. const mapStateToProps = (state: Store): StateProps => {
  115. const accessToken = getGlobalSettingValue(state, 'sonar.prismic.accessToken');
  116. return {
  117. accessToken: accessToken && accessToken.value
  118. };
  119. };
  120. export default connect(mapStateToProps)(ProductNewsMenuItem);