RevisionPath.jsx 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import { withTranslation } from 'react-i18next';
  4. import CopyDropdown from './CopyDropdown';
  5. class RevisionPath extends React.Component {
  6. constructor(props) {
  7. super(props);
  8. this.state = {
  9. pages: [],
  10. isListPage: false,
  11. isLinkToListPage: true,
  12. };
  13. // retrieve xss library from window
  14. this.xss = window.xss;
  15. }
  16. componentWillMount() {
  17. // whether list page or not
  18. const isListPage = this.props.pagePath.match(/\/$/);
  19. this.setState({ isListPage });
  20. // whether set link to '/'
  21. const behaviorType = this.props.crowi.getConfig().behaviorType;
  22. const isLinkToListPage = (!behaviorType || behaviorType === 'crowi');
  23. this.setState({ isLinkToListPage });
  24. // generate pages obj
  25. const splitted = this.props.pagePath.split(/\//);
  26. splitted.shift(); // omit first element with shift()
  27. if (splitted[splitted.length - 1] === '') {
  28. splitted.pop(); // omit last element with unshift()
  29. }
  30. const pages = [];
  31. let parentPath = '/';
  32. splitted.forEach((pageName) => {
  33. pages.push({
  34. pagePath: parentPath + encodeURIComponent(pageName),
  35. pageName: this.xss.process(pageName),
  36. });
  37. parentPath += `${pageName}/`;
  38. });
  39. this.setState({ pages });
  40. }
  41. showToolTip() {
  42. const buttonId = '#copyPagePathDropdown';
  43. $(buttonId).tooltip('show');
  44. setTimeout(() => {
  45. $(buttonId).tooltip('hide');
  46. }, 1000);
  47. }
  48. generateLinkElementToListPage(pagePath, isLinkToListPage, isLastElement) {
  49. /* eslint-disable no-else-return */
  50. if (isLinkToListPage) {
  51. return <a href={`${pagePath}/`} className={(isLastElement && !this.state.isListPage) ? 'last-path' : ''}>/</a>;
  52. }
  53. else if (!isLastElement) {
  54. return <span>/</span>;
  55. }
  56. else {
  57. return <span></span>;
  58. }
  59. /* eslint-enable no-else-return */
  60. }
  61. render() {
  62. // define styles
  63. const rootStyle = {
  64. marginRight: '0.2em',
  65. };
  66. const separatorStyle = {
  67. marginLeft: '0.2em',
  68. marginRight: '0.2em',
  69. };
  70. const buttonStyle = {
  71. marginLeft: '0.5em',
  72. padding: '0 2px',
  73. };
  74. const pageLength = this.state.pages.length;
  75. const afterElements = [];
  76. this.state.pages.forEach((page, index) => {
  77. const isLastElement = (index === pageLength - 1);
  78. // add elements for page
  79. afterElements.push(
  80. <span key={page.pagePath} className="path-segment">
  81. <a href={page.pagePath}>{page.pageName}</a>
  82. </span>,
  83. );
  84. // add elements for '/'
  85. afterElements.push(
  86. <span key={`${page.pagePath}/`} className="separator" style={separatorStyle}>
  87. {this.generateLinkElementToListPage(page.pagePath, this.state.isLinkToListPage, isLastElement)}
  88. </span>,
  89. );
  90. });
  91. return (
  92. <span className="d-flex align-items-center">
  93. <span className="separator" style={rootStyle}>
  94. <a href="/">/</a>
  95. </span>
  96. {afterElements}
  97. <CopyDropdown t={this.props.t} pagePath={this.props.pagePath} pageId={this.props.pageId} buttonStyle={buttonStyle}></CopyDropdown>
  98. <a href="#edit" className="btn btn-default btn-edit" style={buttonStyle}>
  99. <i className="icon-note" />
  100. </a>
  101. </span>
  102. );
  103. }
  104. }
  105. RevisionPath.propTypes = {
  106. t: PropTypes.func.isRequired, // i18next
  107. crowi: PropTypes.object.isRequired,
  108. pagePath: PropTypes.string.isRequired,
  109. pageId: PropTypes.string,
  110. };
  111. export default withTranslation()(RevisionPath);