فهرست منبع

Merge pull request #8700 from weseek/imprv/144181-wip-page-behavior

imprv: WIP Page behavior
Yuki Takei 2 سال پیش
والد
کامیت
135cee6978

+ 2 - 0
apps/app/src/components/PageEditor/PageEditor.tsx

@@ -66,6 +66,7 @@ declare global {
 }
 
 export type SaveOptions = {
+  wip: boolean,
   slackChannels: string,
   overwriteScopesOfDescendants?: boolean
 }
@@ -178,6 +179,7 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
       const { page } = await updatePage({
         pageId,
         revisionId,
+        wip: opts?.wip,
         body: markdown ?? '',
         grant: grantData?.grant,
         origin: Origin.Editor,

+ 10 - 33
apps/app/src/components/SavePageControls.tsx

@@ -10,25 +10,20 @@ import {
   DropdownToggle, DropdownMenu, DropdownItem, Modal,
 } from 'reactstrap';
 
-import { toastSuccess, toastError } from '~/client/util/toastr';
 import type { IPageGrantData } from '~/interfaces/page';
 import {
   useIsEditable, useIsAclEnabled,
   useIsSlackConfigured,
 } from '~/stores/context';
 import { useWaitingSaveProcessing, useSWRxSlackChannels, useIsSlackEnabled } from '~/stores/editor';
-import { useSWRMUTxCurrentPage, useSWRxCurrentPage, useCurrentPagePath } from '~/stores/page';
-import { mutatePageTree } from '~/stores/page-listing';
+import { useSWRxCurrentPage, useCurrentPagePath } from '~/stores/page';
 import {
   useSelectedGrant,
   useEditorMode, useIsDeviceLargerThanMd,
-  EditorMode,
+
 } from '~/stores/ui';
 import loggerFactory from '~/utils/logger';
 
-
-import { unpublish } from '../client/services/page-operation';
-
 import { GrantSelector } from './SavePageControls/GrantSelector';
 import { SlackNotification } from './SlackNotification';
 
@@ -45,10 +40,7 @@ const logger = loggerFactory('growi:SavePageControls');
 const SavePageButton = (props: {slackChannels: string, isDeviceLargerThanMd?: boolean}) => {
 
   const { t } = useTranslation();
-  const { data: currentPage } = useSWRxCurrentPage();
   const { data: _isWaitingSaveProcessing } = useWaitingSaveProcessing();
-  const { trigger: mutateCurrentPage } = useSWRMUTxCurrentPage();
-  const { mutate: mutateEditorMode } = useEditorMode();
   const [isSavePageModalShown, setIsSavePageModalShown] = useState<boolean>(false);
 
   const { slackChannels, isDeviceLargerThanMd } = props;
@@ -57,33 +49,18 @@ const SavePageButton = (props: {slackChannels: string, isDeviceLargerThanMd?: bo
 
   const save = useCallback(async(): Promise<void> => {
     // save
-    globalEmitter.emit('saveAndReturnToView', { slackChannels });
+    globalEmitter.emit('saveAndReturnToView', { wip: false, slackChannels });
   }, [slackChannels]);
 
   const saveAndOverwriteScopesOfDescendants = useCallback(() => {
     // save
-    globalEmitter.emit('saveAndReturnToView', { overwriteScopesOfDescendants: true, slackChannels });
+    globalEmitter.emit('saveAndReturnToView', { wip: false, overwriteScopesOfDescendants: true, slackChannels });
   }, [slackChannels]);
 
-  const clickUnpublishButtonHandler = useCallback(async() => {
-    const pageId = currentPage?._id;
-
-    if (pageId == null) {
-      return;
-    }
-
-    try {
-      await unpublish(pageId);
-      await mutateCurrentPage();
-      await mutatePageTree();
-      await mutateEditorMode(EditorMode.View);
-      toastSuccess(t('wip_page.success_save_as_wip'));
-    }
-    catch (err) {
-      logger.error(err);
-      toastError(t('wip_page.fail_save_as_wip'));
-    }
-  }, [currentPage?._id, mutateCurrentPage, mutateEditorMode, t]);
+  const saveAndMakeWip = useCallback(() => {
+    // save
+    globalEmitter.emit('saveAndReturnToView', { wip: true, slackChannels });
+  }, [slackChannels]);
 
   const labelSubmitButton = t('Update');
   const labelOverwriteScopes = t('page_edit.overwrite_scopes', { operation: labelSubmitButton });
@@ -113,7 +90,7 @@ const SavePageButton = (props: {slackChannels: string, isDeviceLargerThanMd?: bo
                 <DropdownItem onClick={saveAndOverwriteScopesOfDescendants}>
                   {labelOverwriteScopes}
                 </DropdownItem>
-                <DropdownItem onClick={clickUnpublishButtonHandler}>
+                <DropdownItem onClick={saveAndMakeWip}>
                   {labelUnpublishPage}
                 </DropdownItem>
               </DropdownMenu>
@@ -130,7 +107,7 @@ const SavePageButton = (props: {slackChannels: string, isDeviceLargerThanMd?: bo
                   <button type="button" className="btn btn-primary" onClick={() => { setIsSavePageModalShown(false); saveAndOverwriteScopesOfDescendants() }}>
                     {labelOverwriteScopes}
                   </button>
-                  <button type="button" className="btn btn-primary" onClick={() => { setIsSavePageModalShown(false); clickUnpublishButtonHandler() }}>
+                  <button type="button" className="btn btn-primary" onClick={() => { setIsSavePageModalShown(false); saveAndMakeWip() }}>
                     {labelUnpublishPage}
                   </button>
                   <button type="button" className="btn btn-outline-neutral-secondary mx-auto mt-1" onClick={() => setIsSavePageModalShown(false)}>

+ 1 - 0
apps/app/src/interfaces/apiv3/page.ts

@@ -32,6 +32,7 @@ export type IApiv3PageUpdateParams = IOptionsForUpdate & {
   origin?: Origin,
   isSlackEnabled?: boolean,
   slackChannels?: string,
+  wip?: boolean
 };
 
 export type IApiv3PageUpdateResponse = {

+ 1 - 0
apps/app/src/interfaces/page.ts

@@ -34,6 +34,7 @@ export type IDeleteManyPageApiv3Result = {
 
 export type IOptionsForUpdate = {
   origin?: Origin
+  wip?: boolean,
   grant?: PageGrant,
   userRelatedGrantUserGroupIds?: IGrantedGroup[],
   // isSyncRevisionToHackmd?: boolean,

+ 5 - 2
apps/app/src/server/routes/apiv3/page/update-page.ts

@@ -76,6 +76,7 @@ export const updatePageHandlersFactory: UpdatePageHandlersFactory = (crowi) => {
     body('isSlackEnabled').optional().isBoolean().withMessage('isSlackEnabled must be boolean'),
     body('slackChannels').optional().isString().withMessage('slackChannels must be string'),
     body('origin').optional().isIn(allOrigin).withMessage('origin must be "view" or "editor"'),
+    body('wip').optional().isBoolean().withMessage('wip must be boolean'),
   ];
 
 
@@ -158,8 +159,10 @@ export const updatePageHandlersFactory: UpdatePageHandlersFactory = (crowi) => {
 
       let updatedPage;
       try {
-        const { grant, userRelatedGrantUserGroupIds, overwriteScopesOfDescendants } = req.body;
-        const options: IOptionsForUpdate = { overwriteScopesOfDescendants, origin };
+        const {
+          grant, userRelatedGrantUserGroupIds, overwriteScopesOfDescendants, wip,
+        } = req.body;
+        const options: IOptionsForUpdate = { overwriteScopesOfDescendants, origin, wip };
         if (grant != null) {
           options.grant = grant;
           options.userRelatedGrantUserGroupIds = userRelatedGrantUserGroupIds;

+ 10 - 3
apps/app/src/server/service/page/index.ts

@@ -4146,9 +4146,16 @@ class PageService implements IPageService {
     const clonedPageData = Page.hydrate(pageData.toObject());
     const newPageData = pageData;
 
-    // If updated at least once, publish
-    pageData.publish();
-
+    // Once updated it's exempt from automatic deletion
+    if (options.wip == null) {
+      newPageData.ttlTimestamp = undefined;
+    }
+    else if (options.wip) {
+      newPageData.unpublish();
+    }
+    else {
+      newPageData.publish();
+    }
 
     // use the previous data if absent
     const grant = options.grant ?? clonedPageData.grant;