Просмотр исходного кода

impl swicher for recent changes

Shun Miyazawa 2 лет назад
Родитель
Сommit
0040847622

+ 8 - 2
apps/app/src/components/Sidebar/RecentChanges/RecentChanges.tsx

@@ -16,6 +16,7 @@ export const RecentChanges = (): JSX.Element => {
   const { t } = useTranslation();
 
   const [isSmall, setIsSmall] = useState(false);
+  const [isWipPageShown, setIsWipPageShown] = useState(true);
 
   return (
     // TODO : #139425 Match the space specification method to others
@@ -24,12 +25,17 @@ export const RecentChanges = (): JSX.Element => {
       <div className="grw-sidebar-content-header py-3 d-flex">
         <h3 className="mb-0 text-nowrap">{t('Recent Changes')}</h3>
         <Suspense>
-          <RecentChangesHeader isSmall={isSmall} onSizeChange={setIsSmall} />
+          <RecentChangesHeader
+            isSmall={isSmall}
+            onSizeChange={setIsSmall}
+            isWipPageShown={isWipPageShown}
+            onWipPageShownChange={() => { setIsWipPageShown(!isWipPageShown) }}
+          />
         </Suspense>
       </div>
 
       <Suspense fallback={<RecentChangesContentSkeleton />}>
-        <RecentChangesContent isSmall={isSmall} />
+        <RecentChangesContent isWipPageShown={isWipPageShown} isSmall={isSmall} />
       </Suspense>
     </div>
   );

+ 5 - 1
apps/app/src/components/Sidebar/RecentChanges/RecentChangesSubstance.module.scss

@@ -1,7 +1,6 @@
 @use '~/styles/mixins' as *;
 
 .grw-recent-changes-resize-button :global {
-  font-size: 12px;
   line-height: normal;
   transform: translateY(-2px);
 
@@ -46,6 +45,11 @@
   .truncate-text {
     max-width: fit-content;
   }
+
+  .wip-page-badge {
+    height: 0.9rem;
+    font-size: 0.5rem;
+  }
 }
 
 

+ 57 - 17
apps/app/src/components/Sidebar/RecentChanges/RecentChangesSubstance.tsx

@@ -7,6 +7,10 @@ import {
 } from '@growi/core';
 import { DevidedPagePath } from '@growi/core/dist/models';
 import { UserPicture } from '@growi/ui/dist/components';
+import { useTranslation } from 'react-i18next';
+import {
+  DropdownItem, DropdownMenu, DropdownToggle, UncontrolledButtonDropdown,
+} from 'reactstrap';
 
 import { useKeywordManager } from '~/client/services/search-operation';
 import { PagePathHierarchicalLink } from '~/components/Common/PagePathHierarchicalLink';
@@ -47,6 +51,9 @@ const PageItemLower = memo(({ page }: PageItemLowerProps): JSX.Element => {
           <span className="material-symbols-outlined p-0">chat</span>
           <span className="grw-list-counts ms-1">{page.commentCount}</span>
         </div>
+        {/* { page.wip && (
+          <span className="badge rounded-pill text-bg-secondary ms-2" style={{ height: '0.8rem', fontSize: '0.5rem' }}>WIP</span>
+        ) } */}
       </div>
       <div className="grw-formatted-distance-date mt-auto" data-vrt-blackout-datetime>
         <FormattedDistanceDate id={page._id} date={page.updatedAt} />
@@ -116,8 +123,11 @@ const PageItem = memo(({ page, isSmall, onClickTag }: PageItemProps): JSX.Elemen
               { !dPagePath.isRoot && <FormerLink /> }
             </div>
 
-            <h6 className={`col-12 ${isSmall ? 'mb-0 text-truncate' : 'mb-0'}`}>
+            <h6 className={`col-12 d-flex align-items-center ${isSmall ? 'mb-0 text-truncate' : 'mb-0'}`}>
               <PagePathHierarchicalLink linkedPagePath={linkedPagePathLatter} basePath={dPagePath.isRoot ? undefined : dPagePath.former} />
+              { page.wip && (
+                <span className="wip-page-badge badge rounded-pill text-bg-secondary ms-2">WIP</span>
+              ) }
               {locked}
             </h6>
 
@@ -143,12 +153,17 @@ PageItem.displayName = 'PageItem';
 type HeaderProps = {
   isSmall: boolean,
   onSizeChange: (isSmall: boolean) => void,
+  isWipPageShown: boolean,
+  onWipPageShownChange: () => void,
 }
 
 const PER_PAGE = 20;
-export const RecentChangesHeader = ({ isSmall, onSizeChange }: HeaderProps): JSX.Element => {
+export const RecentChangesHeader = ({
+  isSmall, onSizeChange, isWipPageShown, onWipPageShownChange,
+}: HeaderProps): JSX.Element => {
+  const { t } = useTranslation();
 
-  const { mutate } = useSWRINFxRecentlyUpdated(PER_PAGE, { suspense: true });
+  const { mutate } = useSWRINFxRecentlyUpdated(PER_PAGE, isWipPageShown, { suspense: true });
 
   const retrieveSizePreferenceFromLocalStorage = useCallback(() => {
     if (window.localStorage.isRecentChangesSidebarSmall === 'true') {
@@ -169,28 +184,53 @@ export const RecentChangesHeader = ({ isSmall, onSizeChange }: HeaderProps): JSX
   return (
     <>
       <SidebarHeaderReloadButton onClick={() => mutate()} />
-      <div className="d-flex align-items-center">
-        <div className={`grw-recent-changes-resize-button ${styles['grw-recent-changes-resize-button']} form-check form-switch ms-1`}>
-          <input
-            id="recentChangesResize"
-            className="form-check-input"
-            type="checkbox"
-            checked={isSmall}
-            onChange={changeSizeHandler}
-          />
-          <label className="form-label form-check-label" htmlFor="recentChangesResize" />
-        </div>
-      </div>
+
+      <UncontrolledButtonDropdown className="me-1">
+        <DropdownToggle color="transparent" className="p-0 border-0">
+          <span className="material-symbols-outlined">more_horiz</span>
+        </DropdownToggle>
+
+        <DropdownMenu container="body">
+          <DropdownItem onClick={changeSizeHandler}>
+            <div className={`${styles['grw-recent-changes-resize-button']} form-check form-switch`}>
+              <input
+                id="recentChangesResize"
+                className="form-check-input"
+                type="checkbox"
+                checked={isSmall}
+                onChange={() => {}}
+              />
+              <label className="form-label form-check-label text-muted" htmlFor="recentChangesResize" />
+            </div>
+          </DropdownItem>
+
+          <DropdownItem onClick={onWipPageShownChange}>
+            <div className="form-check form-switch">
+              <input
+                id="switchWipPageVisibility"
+                className="form-check-input"
+                type="checkbox"
+                checked={isWipPageShown}
+                onChange={() => {}}
+              />
+              <label className="form-label form-check-label text-muted" htmlFor="switchWipPageVisibility">
+                {t('page_tree_header.show_wip_page')}
+              </label>
+            </div>
+          </DropdownItem>
+        </DropdownMenu>
+      </UncontrolledButtonDropdown>
     </>
   );
 };
 
 type ContentProps = {
   isSmall: boolean,
+  isWipPageShown: boolean,
 }
 
-export const RecentChangesContent = ({ isSmall }: ContentProps): JSX.Element => {
-  const swrInifinitexRecentlyUpdated = useSWRINFxRecentlyUpdated(PER_PAGE, { suspense: true });
+export const RecentChangesContent = ({ isSmall, isWipPageShown }: ContentProps): JSX.Element => {
+  const swrInifinitexRecentlyUpdated = useSWRINFxRecentlyUpdated(PER_PAGE, isWipPageShown, { suspense: true });
   const { data } = swrInifinitexRecentlyUpdated;
 
   const { pushState } = useKeywordManager();

+ 8 - 7
apps/app/src/stores/page-listing.tsx

@@ -8,12 +8,13 @@ import useSWR, {
   mutate, type SWRConfiguration, type SWRResponse, type Arguments,
 } from 'swr';
 import useSWRImmutable from 'swr/immutable';
-import useSWRInfinite, { SWRInfiniteResponse } from 'swr/infinite';
+import type { SWRInfiniteResponse } from 'swr/infinite';
+import useSWRInfinite from 'swr/infinite';
 
-import { IPagingResult } from '~/interfaces/paging-result';
+import type { IPagingResult } from '~/interfaces/paging-result';
 
 import { apiv3Get } from '../client/util/apiv3-client';
-import {
+import type {
   AncestorsChildrenResult, ChildrenResult, V5MigrationStatus, RootPageResult,
 } from '../interfaces/page-listing-results';
 
@@ -32,19 +33,19 @@ type RecentApiResult = {
   totalCount: number,
   offset: number,
 }
-export const useSWRINFxRecentlyUpdated = (limit: number, config?: SWRConfiguration) : SWRInfiniteResponse<RecentApiResult, Error> => {
+export const useSWRINFxRecentlyUpdated = (limit: number, includeWipPage?: boolean, config?: SWRConfiguration) : SWRInfiniteResponse<RecentApiResult, Error> => {
   return useSWRInfinite(
     (pageIndex, previousPageData) => {
       if (previousPageData != null && previousPageData.pages.length === 0) return null;
 
       if (pageIndex === 0 || previousPageData == null) {
-        return ['/pages/recent', undefined, limit];
+        return ['/pages/recent', undefined, limit, includeWipPage];
       }
 
       const offset = previousPageData.offset + limit;
-      return ['/pages/recent', offset, limit];
+      return ['/pages/recent', offset, limit, includeWipPage];
     },
-    ([endpoint, offset, limit]) => apiv3Get<RecentApiResult>(endpoint, { offset, limit }).then(response => response.data),
+    ([endpoint, offset, limit, includeWipPage]) => apiv3Get<RecentApiResult>(endpoint, { offset, limit, includeWipPage }).then(response => response.data),
     {
       ...config,
       revalidateFirstPage: false,