|
@@ -1,4 +1,4 @@
|
|
|
-import React, { useState, useCallback } from 'react';
|
|
|
|
|
|
|
+import React, { useState, useEffect, useCallback } from 'react';
|
|
|
|
|
|
|
|
import PropTypes from 'prop-types';
|
|
import PropTypes from 'prop-types';
|
|
|
import { useTranslation } from 'react-i18next';
|
|
import { useTranslation } from 'react-i18next';
|
|
@@ -8,17 +8,20 @@ import EditorContainer from '~/client/services/EditorContainer';
|
|
|
import { exportAsMarkdown } from '~/client/services/page-operation';
|
|
import { exportAsMarkdown } from '~/client/services/page-operation';
|
|
|
import { toastSuccess, toastError } from '~/client/util/apiNotification';
|
|
import { toastSuccess, toastError } from '~/client/util/apiNotification';
|
|
|
import { apiPost } from '~/client/util/apiv1-client';
|
|
import { apiPost } from '~/client/util/apiv1-client';
|
|
|
-import { IPageHasId, IPageToRenameWithMeta, IPageWithMeta } from '~/interfaces/page';
|
|
|
|
|
|
|
+import {
|
|
|
|
|
+ IPageHasId, IPageToRenameWithMeta, IPageWithMeta,
|
|
|
|
|
+} from '~/interfaces/page';
|
|
|
import { OnDuplicatedFunction, OnRenamedFunction, OnDeletedFunction } from '~/interfaces/ui';
|
|
import { OnDuplicatedFunction, OnRenamedFunction, OnDeletedFunction } from '~/interfaces/ui';
|
|
|
import {
|
|
import {
|
|
|
useCurrentCreatedAt, useCurrentUpdatedAt, useCurrentPageId, useRevisionId, useCurrentPagePath,
|
|
useCurrentCreatedAt, useCurrentUpdatedAt, useCurrentPageId, useRevisionId, useCurrentPagePath,
|
|
|
useCreator, useRevisionAuthor, useCurrentUser, useIsGuestUser, useIsSharedUser, useShareLinkId,
|
|
useCreator, useRevisionAuthor, useCurrentUser, useIsGuestUser, useIsSharedUser, useShareLinkId,
|
|
|
} from '~/stores/context';
|
|
} from '~/stores/context';
|
|
|
|
|
+import { usePageTagsForEditors } from '~/stores/editor';
|
|
|
import {
|
|
import {
|
|
|
usePageAccessoriesModal, PageAccessoriesModalContents, IPageForPageDuplicateModal,
|
|
usePageAccessoriesModal, PageAccessoriesModalContents, IPageForPageDuplicateModal,
|
|
|
usePageDuplicateModal, usePageRenameModal, usePageDeleteModal, usePagePresentationModal,
|
|
usePageDuplicateModal, usePageRenameModal, usePageDeleteModal, usePagePresentationModal,
|
|
|
} from '~/stores/modal';
|
|
} from '~/stores/modal';
|
|
|
-import { useSWRTagsInfo } from '~/stores/page';
|
|
|
|
|
|
|
+import { useSWRxTagsInfo } from '~/stores/page';
|
|
|
import {
|
|
import {
|
|
|
EditorMode, useDrawerMode, useEditorMode, useIsDeviceSmallerThanMd, useIsAbleToShowPageManagement, useIsAbleToShowTagLabel,
|
|
EditorMode, useDrawerMode, useEditorMode, useIsDeviceSmallerThanMd, useIsAbleToShowPageManagement, useIsAbleToShowTagLabel,
|
|
|
useIsAbleToShowPageEditorModeManager, useIsAbleToShowPageAuthors,
|
|
useIsAbleToShowPageEditorModeManager, useIsAbleToShowPageAuthors,
|
|
@@ -165,41 +168,48 @@ const GrowiContextualSubNavigation = (props) => {
|
|
|
const { data: isAbleToShowPageEditorModeManager } = useIsAbleToShowPageEditorModeManager();
|
|
const { data: isAbleToShowPageEditorModeManager } = useIsAbleToShowPageEditorModeManager();
|
|
|
const { data: isAbleToShowPageAuthors } = useIsAbleToShowPageAuthors();
|
|
const { data: isAbleToShowPageAuthors } = useIsAbleToShowPageAuthors();
|
|
|
|
|
|
|
|
- const { mutate: mutateSWRTagsInfo, data: tagsInfoData } = useSWRTagsInfo(pageId);
|
|
|
|
|
|
|
+ const { mutate: mutateSWRTagsInfo, data: tagsInfoData } = useSWRxTagsInfo(pageId);
|
|
|
|
|
+ const { data: tagsForEditors, mutate: mutatePageTagsForEditors, sync: syncPageTagsForEditors } = usePageTagsForEditors(pageId);
|
|
|
|
|
|
|
|
const { open: openDuplicateModal } = usePageDuplicateModal();
|
|
const { open: openDuplicateModal } = usePageDuplicateModal();
|
|
|
const { open: openRenameModal } = usePageRenameModal();
|
|
const { open: openRenameModal } = usePageRenameModal();
|
|
|
const { open: openDeleteModal } = usePageDeleteModal();
|
|
const { open: openDeleteModal } = usePageDeleteModal();
|
|
|
|
|
|
|
|
|
|
+ useEffect(() => {
|
|
|
|
|
+ // Run only when tagsInfoData has been updated
|
|
|
|
|
+ syncPageTagsForEditors();
|
|
|
|
|
+ // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
|
+ }, [tagsInfoData?.tags]);
|
|
|
|
|
+
|
|
|
const [isPageTemplateModalShown, setIsPageTempleteModalShown] = useState(false);
|
|
const [isPageTemplateModalShown, setIsPageTempleteModalShown] = useState(false);
|
|
|
|
|
|
|
|
const {
|
|
const {
|
|
|
- editorContainer, isCompactMode, isLinkSharingDisabled,
|
|
|
|
|
|
|
+ isCompactMode, isLinkSharingDisabled,
|
|
|
} = props;
|
|
} = props;
|
|
|
|
|
|
|
|
const isViewMode = editorMode === EditorMode.View;
|
|
const isViewMode = editorMode === EditorMode.View;
|
|
|
|
|
|
|
|
- const tagsUpdatedHandler = useCallback(async(newTags: string[]) => {
|
|
|
|
|
- // It will not be reflected in the DB until the page is refreshed
|
|
|
|
|
- if (editorMode === EditorMode.Editor) {
|
|
|
|
|
- return editorContainer.setState({ tags: newTags });
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
|
|
+ const tagsUpdatedHandlerForViewMode = useCallback(async(newTags: string[]) => {
|
|
|
try {
|
|
try {
|
|
|
- const { tags } = await apiPost('/tags.update', { pageId, revisionId, tags: newTags }) as { tags };
|
|
|
|
|
|
|
+ await apiPost('/tags.update', { pageId, revisionId, tags: newTags }) as { tags };
|
|
|
|
|
|
|
|
// revalidate SWRTagsInfo
|
|
// revalidate SWRTagsInfo
|
|
|
mutateSWRTagsInfo();
|
|
mutateSWRTagsInfo();
|
|
|
- // update editorContainer.state
|
|
|
|
|
- editorContainer.setState({ tags });
|
|
|
|
|
|
|
+ mutatePageTagsForEditors(newTags);
|
|
|
|
|
|
|
|
toastSuccess('updated tags successfully');
|
|
toastSuccess('updated tags successfully');
|
|
|
}
|
|
}
|
|
|
catch (err) {
|
|
catch (err) {
|
|
|
toastError(err, 'fail to update tags');
|
|
toastError(err, 'fail to update tags');
|
|
|
}
|
|
}
|
|
|
- // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
|
- }, [pageId]);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ }, [pageId, revisionId, mutateSWRTagsInfo, mutatePageTagsForEditors]);
|
|
|
|
|
+
|
|
|
|
|
+ const tagsUpdatedHandlerForEditMode = useCallback((newTags: string[]): void => {
|
|
|
|
|
+ // It will not be reflected in the DB until the page is refreshed
|
|
|
|
|
+ mutatePageTagsForEditors(newTags);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }, [mutatePageTagsForEditors]);
|
|
|
|
|
|
|
|
const duplicateItemClickedHandler = useCallback(async(page: IPageForPageDuplicateModal) => {
|
|
const duplicateItemClickedHandler = useCallback(async(page: IPageForPageDuplicateModal) => {
|
|
|
const duplicatedHandler: OnDuplicatedFunction = (fromPath, toPath) => {
|
|
const duplicatedHandler: OnDuplicatedFunction = (fromPath, toPath) => {
|
|
@@ -322,8 +332,8 @@ const GrowiContextualSubNavigation = (props) => {
|
|
|
isGuestUser={isGuestUser}
|
|
isGuestUser={isGuestUser}
|
|
|
isDrawerMode={isDrawerMode}
|
|
isDrawerMode={isDrawerMode}
|
|
|
isCompactMode={isCompactMode}
|
|
isCompactMode={isCompactMode}
|
|
|
- tags={tagsInfoData?.tags || []}
|
|
|
|
|
- tagsUpdatedHandler={tagsUpdatedHandler}
|
|
|
|
|
|
|
+ tags={isViewMode ? tagsInfoData?.tags : tagsForEditors}
|
|
|
|
|
+ tagsUpdatedHandler={isViewMode ? tagsUpdatedHandlerForViewMode : tagsUpdatedHandlerForEditMode}
|
|
|
controls={ControlComponents}
|
|
controls={ControlComponents}
|
|
|
additionalClasses={['container-fluid']}
|
|
additionalClasses={['container-fluid']}
|
|
|
/>
|
|
/>
|