PageListMeta.tsx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import type { FC } from 'react';
  2. import assert from 'assert';
  3. import type { IPageHasId } from '@growi/core';
  4. import { templateChecker, pagePathUtils } from '@growi/core/dist/utils';
  5. import { FootstampIcon } from '../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 ? 'me-2' : ''} ${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 bg-info ${shouldSpaceOutIcon ? 'me-2' : ''} top-label`}>TOP</span>;
  52. }
  53. // template check
  54. let templateLabel;
  55. if (checkTemplatePath(page.path)) {
  56. templateLabel = <span className={`badge bg-info ${shouldSpaceOutIcon ? 'me-2' : ''}`}>TMPL</span>;
  57. }
  58. let commentCount;
  59. if (page.commentCount > 0) {
  60. commentCount = <span className={`${shouldSpaceOutIcon ? 'me-2' : ''}`}><span className="material-symbols-outlined">comment</span>{page.commentCount}</span>;
  61. }
  62. let likerCount;
  63. if (props.likerCount != null && props.likerCount > 0) {
  64. likerCount = <span className={`${shouldSpaceOutIcon ? 'me-2' : ''}`}><span className="material-symbols-outlined">favorite</span>{props.likerCount}</span>;
  65. }
  66. let locked;
  67. if (page.grant !== 1) {
  68. locked = <span className={`${shouldSpaceOutIcon ? 'me-2' : ''}`}><span className="material-symbols-outlined">lock</span></span>;
  69. }
  70. let bookmarkCount;
  71. if (props.bookmarkCount != null && props.bookmarkCount > 0) {
  72. bookmarkCount = (
  73. <span className={`${shouldSpaceOutIcon ? 'me-2' : ''}`}>
  74. <span className="material-symbols-outlined">bookmark</span>
  75. {props.bookmarkCount}
  76. </span>
  77. );
  78. }
  79. return (
  80. <span className="page-list-meta">
  81. {topLabel}
  82. {templateLabel}
  83. <SeenUsersCount count={page.seenUsers.length} basisViewersCount={basisViewersCount} shouldSpaceOutIcon={shouldSpaceOutIcon} />
  84. {commentCount}
  85. {likerCount}
  86. {locked}
  87. {bookmarkCount}
  88. </span>
  89. );
  90. };