RevisionPath.js 3.3 KB

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