PageListMeta.tsx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import React, { FC } from 'react';
  2. import assert from 'assert';
  3. import { IPageHasId } from '@growi/app/src/interfaces/page';
  4. import { templateChecker, pagePathUtils } from '@growi/core';
  5. import { FootstampIcon } from '../SearchPage/FootstampIcon';
  6. const { isTopPage } = pagePathUtils;
  7. const { checkTemplatePath } = templateChecker;
  8. const SEEN_USERS_HIDE_THRES__ACTIVE_USERS_COUNT = 5;
  9. const MAX_STRENGTH_LEVEL = 4;
  10. type SeenUsersCountProps = {
  11. count: number,
  12. basisViewersCount?: number,
  13. shouldSpaceOutIcon?: boolean,
  14. }
  15. const SeenUsersCount = (props: SeenUsersCountProps): JSX.Element => {
  16. const { count, shouldSpaceOutIcon, basisViewersCount } = props;
  17. if (count === 0) {
  18. return <></>;
  19. }
  20. if (basisViewersCount != null && basisViewersCount <= SEEN_USERS_HIDE_THRES__ACTIVE_USERS_COUNT) {
  21. return <></>;
  22. }
  23. const strengthLevel = Math.ceil(
  24. Math.min(0, Math.log(count / (basisViewersCount ?? count))) // Max: 0
  25. * 2 * -1,
  26. );
  27. if (strengthLevel > MAX_STRENGTH_LEVEL) {
  28. return <></>;
  29. }
  30. assert(strengthLevel >= 0 && strengthLevel <= MAX_STRENGTH_LEVEL); // [0, MAX_STRENGTH_LEVEL)
  31. const strengthClass = `strength-${strengthLevel}`; // strength-{0, 1, 2, 3, 4}
  32. return (
  33. <span className={`seen-users-count ${shouldSpaceOutIcon ? 'mr-3' : ''} ${strengthClass}`}>
  34. <i className="footstamp-icon"><FootstampIcon /></i>
  35. {count}
  36. </span>
  37. );
  38. };
  39. type PageListMetaProps = {
  40. page: IPageHasId,
  41. likerCount?: number,
  42. bookmarkCount?: number,
  43. shouldSpaceOutIcon?: boolean,
  44. basisViewersCount?: number,
  45. }
  46. export const PageListMeta: FC<PageListMetaProps> = (props: PageListMetaProps) => {
  47. const { page, shouldSpaceOutIcon, basisViewersCount } = props;
  48. // top check
  49. let topLabel;
  50. if (isTopPage(page.path)) {
  51. topLabel = <span className={`badge badge-info ${shouldSpaceOutIcon ? 'mr-3' : ''} top-label`}>TOP</span>;
  52. }
  53. // template check
  54. let templateLabel;
  55. if (checkTemplatePath(page.path)) {
  56. templateLabel = <span className={`badge badge-info ${shouldSpaceOutIcon ? 'mr-3' : ''}`}>TMPL</span>;
  57. }
  58. let commentCount;
  59. if (page.commentCount > 0) {
  60. commentCount = <span className={`${shouldSpaceOutIcon ? 'mr-3' : ''}`}><i className="icon-bubble" />{page.commentCount}</span>;
  61. }
  62. let likerCount;
  63. if (props.likerCount != null && props.likerCount > 0) {
  64. likerCount = <span className={`${shouldSpaceOutIcon ? 'mr-3' : ''}`}><i className="fa fa-heart-o" />{props.likerCount}</span>;
  65. }
  66. let locked;
  67. if (page.grant !== 1) {
  68. locked = <span className={`${shouldSpaceOutIcon ? 'mr-3' : ''}`}><i className="icon-lock" /></span>;
  69. }
  70. let bookmarkCount;
  71. if (props.bookmarkCount != null && props.bookmarkCount > 0) {
  72. bookmarkCount = <span className={`${shouldSpaceOutIcon ? 'mr-3' : ''}`}><i className="fa fa-bookmark-o" />{props.bookmarkCount}</span>;
  73. }
  74. return (
  75. <span className="page-list-meta">
  76. {topLabel}
  77. {templateLabel}
  78. <SeenUsersCount count={page.seenUsers.length} basisViewersCount={basisViewersCount} />
  79. {commentCount}
  80. {likerCount}
  81. {locked}
  82. {bookmarkCount}
  83. </span>
  84. );
  85. };