yuken 4 лет назад
Родитель
Сommit
0e697be088

+ 4 - 1
packages/app/resource/locales/en_US/translation.json

@@ -436,7 +436,10 @@
     "delete_completely": "Delete completely",
     "delete_completely_restriction": "You don't have the authority to delete pages completely.",
     "recursively": "Delete pages under this path recursively.",
-    "completely": "Delete completely instead of putting it into trash."
+    "completely": "Delete completely instead of putting it into trash.",
+    "empty_trash": "Empty trash",
+    "empty_trash_button": "Empty trash",
+    "empty_trash_alert": "These pages have been permanently deleted and this operation cannot be canceled."
   },
   "deleted_pages": "{{path}} has been deleted",
   "deleted_pages_completely": "{{path}} has been deleted completely",

+ 4 - 1
packages/app/resource/locales/ja_JP/translation.json

@@ -435,7 +435,10 @@
     "delete_completely": "完全削除",
     "delete_completely_restriction": "完全削除をするための権限がありません。",
     "recursively": "配下のページも削除します",
-    "completely": "ゴミ箱を経由せず、完全に削除します"
+    "completely": "ゴミ箱を経由せず、完全に削除します",
+    "empty_trash": "ゴミ箱を空にする",
+    "empty_trash_button": "空にする",
+    "empty_trash_alert": "これらのページは完全に削除され、この操作は取り消すことができません"
   },
   "deleted_pages": "{{path}} をゴミ箱に入れました",
   "deleted_pages_completely": "{{path}} を完全に削除しました",

+ 4 - 1
packages/app/resource/locales/zh_CN/translation.json

@@ -414,7 +414,10 @@
 		"delete_completely": "Delete completely",
 		"delete_completely_restriction": "You don't have the authority to delete pages completely.",
 		"recursively": "Delete children of <code>%s</code> recursively.",
-		"completely": "Delete completely instead of putting it into trash."
+		"completely": "Delete completely instead of putting it into trash.",
+    "empty_trash": "清空垃圾",
+    "empty_trash_button": "清空垃圾",
+    "empty_trash_alert": "这些页面已被永久删除,此操作无法撤消"
   },
   "deleted_pages": "将 {{path}} 放入垃圾箱",
   "deleted_pages_completely": "{{path}} 已被完全删除",

+ 11 - 23
packages/app/src/components/CustomNavigation/CustomNav.jsx

@@ -3,10 +3,12 @@ import React, {
 } from 'react';
 
 import PropTypes from 'prop-types';
+import { useTranslation } from 'react-i18next';
 import {
   Nav, NavItem, NavLink,
 } from 'reactstrap';
 
+
 import { toastSuccess } from '~/client/util/apiNotification';
 import { useCurrentPagePath } from '~/stores/context';
 import { usePageDeleteModal } from '~/stores/modal';
@@ -91,6 +93,7 @@ CustomNavDropdown.propTypes = {
 
 
 export const CustomNavTab = (props) => {
+  const { t } = useTranslation();
   const navContainer = useRef();
   const [sliderWidth, setSliderWidth] = useState(0);
   const [sliderMarginLeft, setSliderMarginLeft] = useState(0);
@@ -117,8 +120,6 @@ export const CustomNavTab = (props) => {
     }
   }, [onNavSelected]);
 
-  // ==========================================
-
   const pageIds = pagingResult?.items?.map(page => page._id);
   const { injectTo } = useSWRxPageInfoForList(pageIds, true, true);
 
@@ -128,33 +129,20 @@ export const CustomNavTab = (props) => {
     return { data: page };
   };
 
-  // initial data
   if (pagingResult != null) {
-    // convert without meta at first
-    console.log(pagingResult);
     const dataWithMetas = pagingResult.items.map(page => convertToIDataWithMeta(page));
-    // inject data for listing
     pageWithMetas = injectTo(dataWithMetas);
   }
 
-  const deonDeleteHandler = (...args) => {
-    // alert(pagingResult.items.length);
-    toastSuccess(args[2] ? 'あいうえお' : 'かきくけこ');
-
-    advancePt();
-
-    if (mutate != null) {
-      mutate(...args);
-    }
+  const onDeletedHandler = (...args) => {
+    // process after multipe pages delete api
+    alert(currentPath);
   };
 
-  const allDeleteButtonClickHandler = () => {
-
-    openDeleteModal(pageWithMetas, { onDeleted: mutate });
+  const emptyTrashClickHandler = () => {
+    openDeleteModal(pageWithMetas, { onDeleted: onDeletedHandler, emptyTrash: true });
   };
 
-  // ==========================================
-
   function registerNavLink(key, elm) {
     if (elm != null) {
       navTabRefs[key] = elm;
@@ -199,7 +187,7 @@ export const CustomNavTab = (props) => {
   }
 
   // trash page flag
-  const isTrash = isTrashPage(currentPath);
+  const isTrash = currentPath === '/trash';
 
   return (
     <div className="grw-custom-nav-tab">
@@ -228,10 +216,10 @@ export const CustomNavTab = (props) => {
             <button
               type="button"
               className="btn btn-outline-secondary rounded-pill text-danger d-flex align-items-center"
-              onClick={() => allDeleteButtonClickHandler()}
+              onClick={() => emptyTrashClickHandler()}
             >
               <i className="icon-fw icon-trash"></i>
-              <div>全て削除</div>
+              <div>{t('modal_delete.empty_trash')}</div>
             </button>
           </div>
         )}

+ 21 - 11
packages/app/src/components/PageDeleteModal.tsx

@@ -1,22 +1,24 @@
 import React, { useState, FC, useMemo } from 'react';
+
+import { useTranslation } from 'react-i18next';
 import {
   Modal, ModalHeader, ModalBody, ModalFooter,
 } from 'reactstrap';
-import { useTranslation } from 'react-i18next';
 
 import { apiPost } from '~/client/util/apiv1-client';
 import { apiv3Post } from '~/client/util/apiv3-client';
-import { usePageDeleteModal } from '~/stores/modal';
-import loggerFactory from '~/utils/logger';
-
+import { HasObjectId } from '~/interfaces/has-object-id';
 import {
   IDeleteSinglePageApiv1Result, IDeleteManyPageApiv3Result, IPageToDeleteWithMeta, IDataWithMeta, isIPageInfoForEntity, IPageInfoForEntity,
 } from '~/interfaces/page';
-import { HasObjectId } from '~/interfaces/has-object-id';
+import { usePageDeleteModal } from '~/stores/modal';
+import { useSWRxPageInfoForList } from '~/stores/page';
+import loggerFactory from '~/utils/logger';
+
 
 import ApiErrorMessageList from './PageManagement/ApiErrorMessageList';
+
 import { isTrashPage } from '^/../core/src/utils/page-path-utils';
-import { useSWRxPageInfoForList } from '~/stores/page';
 
 
 const logger = loggerFactory('growi:cli:PageDeleteModal');
@@ -41,6 +43,7 @@ const PageDeleteModal: FC = () => {
   const { data: deleteModalData, close: closeDeleteModal } = usePageDeleteModal();
 
   const isOpened = deleteModalData?.isOpened ?? false;
+  const emptyTrash = deleteModalData?.opts?.emptyTrash ?? false;
 
   const notOperatablePages: IPageToDeleteWithMeta[] = (deleteModalData?.pages ?? [])
     .filter(p => !isIPageInfoForEntity(p.meta));
@@ -207,6 +210,12 @@ const PageDeleteModal: FC = () => {
     );
   }
 
+  const renderCompletelyDeleteAlert = () => {
+    return (
+      <p className="form-text mt-0">{t('modal_delete.empty_trash_alert')}</p>
+    );
+  };
+
   const renderPagePathsToDelete = () => {
     const pages = injectedPages != null && injectedPages.length > 0 ? injectedPages : deleteModalData?.pages;
 
@@ -225,7 +234,7 @@ const PageDeleteModal: FC = () => {
     <Modal size="lg" isOpen={isOpened} toggle={closeDeleteModal} data-testid="page-delete-modal" className="grw-create-page">
       <ModalHeader tag="h4" toggle={closeDeleteModal} className={`bg-${deleteIconAndKey[deleteMode].color} text-light`}>
         <i className={`icon-fw icon-${deleteIconAndKey[deleteMode].icon}`}></i>
-        { t(`modal_delete.delete_${deleteIconAndKey[deleteMode].translationKey}`) }
+        { emptyTrash ? t('modal_delete.empty_trash') : t(`modal_delete.delete_${deleteIconAndKey[deleteMode].translationKey}`) }
       </ModalHeader>
       <ModalBody>
         <div className="form-group grw-scrollable-modal-body pb-1">
@@ -234,8 +243,9 @@ const PageDeleteModal: FC = () => {
           {/* https://redmine.weseek.co.jp/issues/82787 */}
           {renderPagePathsToDelete()}
         </div>
-        { isDeletable && renderDeleteRecursivelyForm()}
-        { isDeletable && !forceDeleteCompletelyMode && renderDeleteCompletelyForm() }
+        { isDeletable && !emptyTrash && renderDeleteRecursivelyForm()}
+        { isDeletable && !forceDeleteCompletelyMode && !emptyTrash && renderDeleteCompletelyForm() }
+        { emptyTrash && renderCompletelyDeleteAlert() }
       </ModalBody>
       <ModalFooter>
         <ApiErrorMessageList errs={errs} />
@@ -245,8 +255,8 @@ const PageDeleteModal: FC = () => {
           disabled={!isDeletable}
           onClick={deleteButtonHandler}
         >
-          <i className={`icon-${deleteIconAndKey[deleteMode].icon}`} aria-hidden="true"></i>
-          { t(`modal_delete.delete_${deleteIconAndKey[deleteMode].translationKey}`) }
+          <i className={`mr-1 icon-${deleteIconAndKey[deleteMode].icon}`} aria-hidden="true"></i>
+          { emptyTrash ? t('modal_delete.empty_trash_button') : t(`modal_delete.delete_${deleteIconAndKey[deleteMode].translationKey}`) }
         </button>
       </ModalFooter>
     </Modal>

+ 5 - 2
packages/app/src/stores/modal.tsx

@@ -1,11 +1,13 @@
 import { SWRResponse } from 'swr';
-import { useStaticSWR } from './use-static-swr';
+
+import { IPageToDeleteWithMeta, IPageToRenameWithMeta } from '~/interfaces/page';
 import {
   OnDuplicatedFunction, OnRenamedFunction, OnDeletedFunction, OnPutBackedFunction,
 } from '~/interfaces/ui';
-import { IPageToDeleteWithMeta, IPageToRenameWithMeta } from '~/interfaces/page';
 import { IUserGroupHasId } from '~/interfaces/user';
 
+import { useStaticSWR } from './use-static-swr';
+
 
 /*
 * PageCreateModal
@@ -33,6 +35,7 @@ export const usePageCreateModal = (status?: CreateModalStatus): SWRResponse<Crea
 
 export type IDeleteModalOption = {
   onDeleted?: OnDeletedFunction,
+  emptyTrash?: true,
 }
 
 type DeleteModalStatus = {