|
|
@@ -1,15 +1,17 @@
|
|
|
import React, {
|
|
|
- FC,
|
|
|
- useCallback, useEffect, useState,
|
|
|
+ memo, useCallback, useEffect, useState,
|
|
|
} from 'react';
|
|
|
|
|
|
import { DevidedPagePath } from '@growi/core';
|
|
|
import { UserPicture, FootstampIcon } from '@growi/ui';
|
|
|
import { useTranslation } from 'next-i18next';
|
|
|
+import Link from 'next/link';
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
|
|
|
|
|
import PagePathHierarchicalLink from '~/components/PagePathHierarchicalLink';
|
|
|
+import { isPopulated } from '~/interfaces/common';
|
|
|
+import { IPageHasId } from '~/interfaces/page';
|
|
|
import LinkedPagePath from '~/models/linked-page-path';
|
|
|
import { useSWRInifinitexRecentlyUpdated } from '~/stores/page-listing';
|
|
|
import loggerFactory from '~/utils/logger';
|
|
|
@@ -21,7 +23,11 @@ import InfiniteScroll from './InfiniteScroll';
|
|
|
|
|
|
const logger = loggerFactory('growi:History');
|
|
|
|
|
|
-function PageItemLower({ page }) {
|
|
|
+type PageItemProps = {
|
|
|
+ page: IPageHasId,
|
|
|
+}
|
|
|
+
|
|
|
+const PageItemLower = memo(({ page }: PageItemProps): JSX.Element => {
|
|
|
return (
|
|
|
<div className="d-flex justify-content-between grw-recent-changes-item-lower pt-1">
|
|
|
<div className="d-flex">
|
|
|
@@ -35,11 +41,11 @@ function PageItemLower({ page }) {
|
|
|
</div>
|
|
|
</div>
|
|
|
);
|
|
|
-}
|
|
|
-PageItemLower.propTypes = {
|
|
|
- page: PropTypes.any,
|
|
|
-};
|
|
|
-function LargePageItem({ page }) {
|
|
|
+});
|
|
|
+PageItemLower.displayName = 'PageItemLower';
|
|
|
+
|
|
|
+
|
|
|
+const LargePageItem = memo(({ page }: PageItemProps): JSX.Element => {
|
|
|
const dPagePath = new DevidedPagePath(page.path, false, true);
|
|
|
const linkedPagePathFormer = new LinkedPagePath(dPagePath.former);
|
|
|
const linkedPagePathLatter = new LinkedPagePath(dPagePath.latter);
|
|
|
@@ -56,10 +62,15 @@ function LargePageItem({ page }) {
|
|
|
|
|
|
const tags = page.tags;
|
|
|
const tagElements = tags.map((tag) => {
|
|
|
+ if (!isPopulated(tag)) {
|
|
|
+ return <></>;
|
|
|
+ }
|
|
|
return (
|
|
|
- <a key={tag.name} href={`/_search?q=tag:${tag.name}`} className="grw-tag-label badge badge-secondary mr-2 small">
|
|
|
- {tag.name}
|
|
|
- </a>
|
|
|
+ <Link key={tag.name} href={`/_search?q=tag:${tag.name}`}>
|
|
|
+ <a className="grw-tag-label badge badge-secondary mr-2 small">
|
|
|
+ {tag.name}
|
|
|
+ </a>
|
|
|
+ </Link>
|
|
|
);
|
|
|
});
|
|
|
|
|
|
@@ -81,12 +92,11 @@ function LargePageItem({ page }) {
|
|
|
</div>
|
|
|
</li>
|
|
|
);
|
|
|
-}
|
|
|
-LargePageItem.propTypes = {
|
|
|
- page: PropTypes.any,
|
|
|
-};
|
|
|
+});
|
|
|
+LargePageItem.displayName = 'LargePageItem';
|
|
|
|
|
|
-function SmallPageItem({ page }) {
|
|
|
+
|
|
|
+const SmallPageItem = memo(({ page }: PageItemProps): JSX.Element => {
|
|
|
const dPagePath = new DevidedPagePath(page.path, false, true);
|
|
|
const linkedPagePathFormer = new LinkedPagePath(dPagePath.former);
|
|
|
const linkedPagePathLatter = new LinkedPagePath(dPagePath.latter);
|
|
|
@@ -116,10 +126,8 @@ function SmallPageItem({ page }) {
|
|
|
</div>
|
|
|
</li>
|
|
|
);
|
|
|
-}
|
|
|
-SmallPageItem.propTypes = {
|
|
|
- page: PropTypes.any,
|
|
|
-};
|
|
|
+});
|
|
|
+SmallPageItem.displayName = 'SmallPageItem';
|
|
|
|
|
|
const RecentChanges = (): JSX.Element => {
|
|
|
const PER_PAGE = 20;
|