|
@@ -1,6 +1,12 @@
|
|
|
import React, { useCallback } from 'react';
|
|
import React, { useCallback } from 'react';
|
|
|
import PropTypes from 'prop-types';
|
|
import PropTypes from 'prop-types';
|
|
|
|
|
|
|
|
|
|
+import { useTranslation } from 'react-i18next';
|
|
|
|
|
+
|
|
|
|
|
+import { DropdownItem } from 'reactstrap';
|
|
|
|
|
+
|
|
|
|
|
+import urljoin from 'url-join';
|
|
|
|
|
+
|
|
|
import { withUnstatedContainers } from '../UnstatedUtils';
|
|
import { withUnstatedContainers } from '../UnstatedUtils';
|
|
|
import EditorContainer from '~/client/services/EditorContainer';
|
|
import EditorContainer from '~/client/services/EditorContainer';
|
|
|
import {
|
|
import {
|
|
@@ -13,6 +19,7 @@ import {
|
|
|
} from '~/stores/context';
|
|
} from '~/stores/context';
|
|
|
import { useSWRTagsInfo } from '~/stores/page';
|
|
import { useSWRTagsInfo } from '~/stores/page';
|
|
|
|
|
|
|
|
|
|
+import { AdditionalMenuItemsRendererProps } from '../Common/Dropdown/PageItemControl';
|
|
|
import { SubNavButtons } from './SubNavButtons';
|
|
import { SubNavButtons } from './SubNavButtons';
|
|
|
import PageEditorModeManager from './PageEditorModeManager';
|
|
import PageEditorModeManager from './PageEditorModeManager';
|
|
|
|
|
|
|
@@ -20,6 +27,52 @@ import { toastSuccess, toastError } from '~/client/util/apiNotification';
|
|
|
import { apiPost } from '~/client/util/apiv1-client';
|
|
import { apiPost } from '~/client/util/apiv1-client';
|
|
|
import { IPageHasId } from '~/interfaces/page';
|
|
import { IPageHasId } from '~/interfaces/page';
|
|
|
import { GrowiSubNavigation } from './GrowiSubNavigation';
|
|
import { GrowiSubNavigation } from './GrowiSubNavigation';
|
|
|
|
|
+import PresentationIcon from '../Icons/PresentationIcon';
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+type AdditionalMenuItemsProps = AdditionalMenuItemsRendererProps & {
|
|
|
|
|
+ pageId: string,
|
|
|
|
|
+ revisionId: string,
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const AdditionalMenuItems = (props: AdditionalMenuItemsProps): JSX.Element => {
|
|
|
|
|
+ const { t } = useTranslation();
|
|
|
|
|
+
|
|
|
|
|
+ const { pageInfo, pageId, revisionId } = props;
|
|
|
|
|
+
|
|
|
|
|
+ const exportPageHandler = useCallback(async(format: string): Promise<void> => {
|
|
|
|
|
+ const url = new URL(urljoin(window.location.origin, '_api/v3/page/export', pageId));
|
|
|
|
|
+ url.searchParams.append('format', format);
|
|
|
|
|
+ url.searchParams.append('revisionId', revisionId);
|
|
|
|
|
+ window.location.href = url.href;
|
|
|
|
|
+ }, [pageId, revisionId]);
|
|
|
|
|
+
|
|
|
|
|
+ return (
|
|
|
|
|
+ <>
|
|
|
|
|
+ <DropdownItem divider />
|
|
|
|
|
+
|
|
|
|
|
+ {/* Presentation */}
|
|
|
|
|
+ <DropdownItem onClick={() => { /* TODO: implement in https://redmine.weseek.co.jp/issues/87672 */ }}>
|
|
|
|
|
+ <i className="icon-fw"><PresentationIcon /></i>
|
|
|
|
|
+ { t('Presentation Mode') }
|
|
|
|
|
+ </DropdownItem>
|
|
|
|
|
+
|
|
|
|
|
+ {/* Export markdown */}
|
|
|
|
|
+ <DropdownItem onClick={() => exportPageHandler('md')}>
|
|
|
|
|
+ <i className="icon-fw icon-cloud-download"></i>
|
|
|
|
|
+ {t('export_bulk.export_page_markdown')}
|
|
|
|
|
+ </DropdownItem>
|
|
|
|
|
+
|
|
|
|
|
+ <DropdownItem divider />
|
|
|
|
|
+
|
|
|
|
|
+ {/* Create template */}
|
|
|
|
|
+ <DropdownItem onClick={() => { /* TODO: implement in https://redmine.weseek.co.jp/issues/87673 */ }}>
|
|
|
|
|
+ <i className="icon-fw icon-magic-wand"></i> { t('template.option_label.create/edit') }
|
|
|
|
|
+ </DropdownItem>
|
|
|
|
|
+ </>
|
|
|
|
|
+ );
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
|
|
|
const GrowiContextualSubNavigation = (props) => {
|
|
const GrowiContextualSubNavigation = (props) => {
|
|
|
const { data: isDeviceSmallerThanMd } = useIsDeviceSmallerThanMd();
|
|
const { data: isDeviceSmallerThanMd } = useIsDeviceSmallerThanMd();
|
|
@@ -47,6 +100,7 @@ const GrowiContextualSubNavigation = (props) => {
|
|
|
} = props;
|
|
} = props;
|
|
|
|
|
|
|
|
const isViewMode = editorMode === EditorMode.View;
|
|
const isViewMode = editorMode === EditorMode.View;
|
|
|
|
|
+ const isPageExists = pageId != null;
|
|
|
|
|
|
|
|
const tagsUpdatedHandler = useCallback(async(newTags: string[]) => {
|
|
const tagsUpdatedHandler = useCallback(async(newTags: string[]) => {
|
|
|
// It will not be reflected in the DB until the page is refreshed
|
|
// It will not be reflected in the DB until the page is refreshed
|
|
@@ -78,12 +132,14 @@ const GrowiContextualSubNavigation = (props) => {
|
|
|
return (
|
|
return (
|
|
|
<>
|
|
<>
|
|
|
<div className="h-50 d-flex flex-column align-items-end justify-content-center">
|
|
<div className="h-50 d-flex flex-column align-items-end justify-content-center">
|
|
|
- { isViewMode && (
|
|
|
|
|
|
|
+ { isPageExists && isViewMode && (
|
|
|
<SubNavButtons
|
|
<SubNavButtons
|
|
|
isCompactMode={isCompactMode}
|
|
isCompactMode={isCompactMode}
|
|
|
pageId={pageId}
|
|
pageId={pageId}
|
|
|
|
|
+ revisionId={revisionId}
|
|
|
disableSeenUserInfoPopover={isSharedUser}
|
|
disableSeenUserInfoPopover={isSharedUser}
|
|
|
showPageControlDropdown={isAbleToShowPageManagement}
|
|
showPageControlDropdown={isAbleToShowPageManagement}
|
|
|
|
|
+ additionalMenuItemRenderer={props => <AdditionalMenuItems {...props} pageId={pageId} revisionId={revisionId} />}
|
|
|
/>
|
|
/>
|
|
|
) }
|
|
) }
|
|
|
</div>
|
|
</div>
|
|
@@ -100,7 +156,7 @@ const GrowiContextualSubNavigation = (props) => {
|
|
|
</>
|
|
</>
|
|
|
);
|
|
);
|
|
|
}, [
|
|
}, [
|
|
|
- pageId,
|
|
|
|
|
|
|
+ pageId, revisionId, isPageExists,
|
|
|
editorMode, mutateEditorMode,
|
|
editorMode, mutateEditorMode,
|
|
|
isCompactMode, isDeviceSmallerThanMd, isGuestUser, isSharedUser,
|
|
isCompactMode, isDeviceSmallerThanMd, isGuestUser, isSharedUser,
|
|
|
isViewMode, isAbleToShowPageEditorModeManager, isAbleToShowPageManagement,
|
|
isViewMode, isAbleToShowPageEditorModeManager, isAbleToShowPageManagement,
|