|
|
@@ -1,25 +1,22 @@
|
|
|
import React, {
|
|
|
- memo, useCallback, useEffect, useState,
|
|
|
+ memo, useCallback, useEffect,
|
|
|
} from 'react';
|
|
|
|
|
|
import { isPopulated, type IPageHasId } from '@growi/core';
|
|
|
import { DevidedPagePath } from '@growi/core/dist/models';
|
|
|
import { UserPicture, FootstampIcon } from '@growi/ui/dist/components';
|
|
|
-import { useTranslation } from 'next-i18next';
|
|
|
import Link from 'next/link';
|
|
|
|
|
|
+import FormattedDistanceDate from '~/components/FormattedDistanceDate';
|
|
|
+import InfiniteScroll from '~/components/InfiniteScroll';
|
|
|
import PagePathHierarchicalLink from '~/components/PagePathHierarchicalLink';
|
|
|
import LinkedPagePath from '~/models/linked-page-path';
|
|
|
import { useSWRINFxRecentlyUpdated } from '~/stores/page-listing';
|
|
|
import loggerFactory from '~/utils/logger';
|
|
|
|
|
|
-import FormattedDistanceDate from '../FormattedDistanceDate';
|
|
|
-import InfiniteScroll from '../InfiniteScroll';
|
|
|
+import { SidebarHeaderReloadButton } from '../SidebarHeaderReloadButton';
|
|
|
|
|
|
-import { SidebarHeaderReloadButton } from './SidebarHeaderReloadButton';
|
|
|
-import RecentChangesContentSkeleton from './Skeleton/RecentChangesContentSkeleton';
|
|
|
-
|
|
|
-import styles from './RecentChanges.module.scss';
|
|
|
+import styles from './RecentChangesSubstance.module.scss';
|
|
|
|
|
|
|
|
|
const logger = loggerFactory('growi:History');
|
|
|
@@ -102,29 +99,27 @@ const PageItem = memo(({ page, isSmall }: PageItemProps): JSX.Element => {
|
|
|
});
|
|
|
PageItem.displayName = 'PageItem';
|
|
|
|
|
|
-const RecentChanges = (): JSX.Element => {
|
|
|
|
|
|
- const PER_PAGE = 20;
|
|
|
- const { t } = useTranslation();
|
|
|
- const swrInifinitexRecentlyUpdated = useSWRINFxRecentlyUpdated(PER_PAGE);
|
|
|
- const {
|
|
|
- data, mutate, isLoading,
|
|
|
- } = swrInifinitexRecentlyUpdated;
|
|
|
+type HeaderProps = {
|
|
|
+ isSmall: boolean,
|
|
|
+ onSizeChange: (isSmall: boolean) => void,
|
|
|
+}
|
|
|
|
|
|
- const [isRecentChangesSidebarSmall, setIsRecentChangesSidebarSmall] = useState(false);
|
|
|
- const isEmpty = data?.[0]?.pages.length === 0;
|
|
|
- const isReachingEnd = isEmpty || (data != null && data[data.length - 1]?.pages.length < PER_PAGE);
|
|
|
+const PER_PAGE = 20;
|
|
|
+export const RecentChangesHeader = ({ isSmall, onSizeChange }: HeaderProps): JSX.Element => {
|
|
|
+
|
|
|
+ const { mutate } = useSWRINFxRecentlyUpdated(PER_PAGE, { suspense: true });
|
|
|
|
|
|
const retrieveSizePreferenceFromLocalStorage = useCallback(() => {
|
|
|
if (window.localStorage.isRecentChangesSidebarSmall === 'true') {
|
|
|
- setIsRecentChangesSidebarSmall(true);
|
|
|
+ onSizeChange(true);
|
|
|
}
|
|
|
- }, []);
|
|
|
+ }, [onSizeChange]);
|
|
|
|
|
|
const changeSizeHandler = useCallback((e) => {
|
|
|
- setIsRecentChangesSidebarSmall(e.target.checked);
|
|
|
+ onSizeChange(e.target.checked);
|
|
|
window.localStorage.setItem('isRecentChangesSidebarSmall', e.target.checked);
|
|
|
- }, []);
|
|
|
+ }, [onSizeChange]);
|
|
|
|
|
|
// componentDidMount
|
|
|
useEffect(() => {
|
|
|
@@ -132,44 +127,49 @@ const RecentChanges = (): JSX.Element => {
|
|
|
}, [retrieveSizePreferenceFromLocalStorage]);
|
|
|
|
|
|
return (
|
|
|
- <div className="px-3" data-testid="grw-recent-changes">
|
|
|
- <div className="grw-sidebar-content-header py-3 d-flex">
|
|
|
- <h3 className="mb-0 text-nowrap">{t('Recent Changes')}</h3>
|
|
|
- <SidebarHeaderReloadButton onClick={() => mutate()}/>
|
|
|
- <div className="d-flex align-items-center">
|
|
|
- <div className={`grw-recent-changes-resize-button ${styles['grw-recent-changes-resize-button']} custom-control custom-switch ml-1`}>
|
|
|
- <input
|
|
|
- id="recentChangesResize"
|
|
|
- className="custom-control-input"
|
|
|
- type="checkbox"
|
|
|
- checked={isRecentChangesSidebarSmall}
|
|
|
- onChange={changeSizeHandler}
|
|
|
- />
|
|
|
- <label className="custom-control-label" htmlFor="recentChangesResize">
|
|
|
- </label>
|
|
|
- </div>
|
|
|
+ <>
|
|
|
+ <SidebarHeaderReloadButton onClick={() => mutate()}/>
|
|
|
+ <div className="d-flex align-items-center">
|
|
|
+ <div className={`grw-recent-changes-resize-button ${styles['grw-recent-changes-resize-button']} custom-control custom-switch ml-1`}>
|
|
|
+ <input
|
|
|
+ id="recentChangesResize"
|
|
|
+ className="custom-control-input"
|
|
|
+ type="checkbox"
|
|
|
+ checked={isSmall}
|
|
|
+ onChange={changeSizeHandler}
|
|
|
+ />
|
|
|
+ <label className="custom-control-label" htmlFor="recentChangesResize" />
|
|
|
</div>
|
|
|
</div>
|
|
|
- {
|
|
|
- isLoading ? <RecentChangesContentSkeleton /> : (
|
|
|
- <div className="grw-recent-changes py-3">
|
|
|
- <ul className="list-group list-group-flush">
|
|
|
- <InfiniteScroll
|
|
|
- swrInifiniteResponse={swrInifinitexRecentlyUpdated}
|
|
|
- isReachingEnd={isReachingEnd}
|
|
|
- >
|
|
|
- { data != null && data.map(apiResult => apiResult.pages).flat()
|
|
|
- .map(page => (
|
|
|
- <PageItem key={page._id} page={page} isSmall={isRecentChangesSidebarSmall} />
|
|
|
- ))
|
|
|
- }
|
|
|
- </InfiniteScroll>
|
|
|
- </ul>
|
|
|
- </div>
|
|
|
- )
|
|
|
- }
|
|
|
- </div>
|
|
|
+ </>
|
|
|
);
|
|
|
+};
|
|
|
+
|
|
|
+type ContentProps = {
|
|
|
+ isSmall: boolean,
|
|
|
+}
|
|
|
+
|
|
|
+export const RecentChangesContent = ({ isSmall }: ContentProps): JSX.Element => {
|
|
|
+ const swrInifinitexRecentlyUpdated = useSWRINFxRecentlyUpdated(PER_PAGE, { suspense: true });
|
|
|
+ const { data } = swrInifinitexRecentlyUpdated;
|
|
|
+
|
|
|
+ const isEmpty = data?.[0]?.pages.length === 0;
|
|
|
+ const isReachingEnd = isEmpty || (data != null && data[data.length - 1]?.pages.length < PER_PAGE);
|
|
|
|
|
|
+ return (
|
|
|
+ <div className="grw-recent-changes py-3">
|
|
|
+ <ul className="list-group list-group-flush">
|
|
|
+ <InfiniteScroll
|
|
|
+ swrInifiniteResponse={swrInifinitexRecentlyUpdated}
|
|
|
+ isReachingEnd={isReachingEnd}
|
|
|
+ >
|
|
|
+ { data != null && data.map(apiResult => apiResult.pages).flat()
|
|
|
+ .map(page => (
|
|
|
+ <PageItem key={page._id} page={page} isSmall={isSmall} />
|
|
|
+ ))
|
|
|
+ }
|
|
|
+ </InfiniteScroll>
|
|
|
+ </ul>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
};
|
|
|
-export default RecentChanges;
|