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

Merge pull request #6417 from weseek/feat/redner-page-redirect-alert

feat: Redner page redirect alert
Yohei Shiina 3 лет назад
Родитель
Сommit
49f3a7dfed

+ 1 - 0
packages/app/public/static/locales/en_US/translation.json

@@ -19,6 +19,7 @@
   "Move/Rename": "Move/Rename",
   "Redirected": "Redirected",
   "Unlinked": "Unlinked",
+  "unlink_redirection": "Unlink redirection",
   "Done": "Done",
   "Cancel": "Cancel",
   "Create": "Create",

+ 1 - 0
packages/app/public/static/locales/ja_JP/translation.json

@@ -19,6 +19,7 @@
   "Move/Rename": "移動/名前変更",
   "Redirected": "リダイレクトされました",
   "Unlinked": "リダイレクト削除",
+  "unlink_redirection": "リダイレクト削除",
   "Done": "完了",
   "Cancel": "キャンセル",
   "Create": "作成",

+ 1 - 0
packages/app/public/static/locales/zh_CN/translation.json

@@ -20,6 +20,7 @@
 	"Move/Rename": "移动/重命名",
 	"Redirected": "重定向",
 	"Unlinked": "Unlinked",
+  "unlink_redirection": "取消链接重定向",
   "Done": "Done",
   "Cancel": "取消",
 	"Create": "创建",

+ 0 - 18
packages/app/src/components/Page/RedirectedAlert.tsx

@@ -1,18 +0,0 @@
-import React from 'react';
-
-import { useTranslation } from 'next-i18next';
-
-const RedirectedAlert = React.memo((): JSX.Element => {
-  const { t } = useTranslation();
-  const urlParams = new URLSearchParams(window.location.search);
-  const fromPath = urlParams.get('redirectFrom');
-
-  return (
-    <>
-      <strong>{ t('Redirected') }:</strong> { t('page_page.notice.redirected')} <code>{fromPath}</code> {t('page_page.notice.redirected_period')}
-    </>
-  );
-});
-RedirectedAlert.displayName = 'RedirectedAlert';
-
-export default RedirectedAlert;

+ 2 - 0
packages/app/src/components/PageAlert/PageAlerts.tsx

@@ -7,6 +7,7 @@ import { useIsNotFound } from '~/stores/context';
 import { FixPageGrantAlert } from './FixPageGrantAlert';
 import { OldRevisionAlert } from './OldRevisionAlert';
 import { PageGrantAlert } from './PageGrantAlert';
+import { PageRedirectedAlert } from './PageRedirectedAlert';
 import { PageStaleAlert } from './PageStaleAlert';
 
 // dynamic import because TrashPageAlert uses localStorageMiddleware
@@ -25,6 +26,7 @@ export const PageAlerts = (): JSX.Element => {
         <TrashPageAlert />
         <PageStaleAlert />
         <OldRevisionAlert />
+        <PageRedirectedAlert />
       </div>
     </div>
   );

+ 46 - 0
packages/app/src/components/PageAlert/PageRedirectedAlert.tsx

@@ -0,0 +1,46 @@
+import React, { useState, useCallback } from 'react';
+
+import { useTranslation } from 'next-i18next';
+
+import { toastError } from '~/client/util/apiNotification';
+import { useRedirectFrom } from '~/stores/page-redirect';
+
+export const PageRedirectedAlert = React.memo((): JSX.Element => {
+  const { t } = useTranslation();
+  const { data: redirectFrom, unlink } = useRedirectFrom();
+
+  const [isUnlinked, setIsUnlinked] = useState(false);
+
+  const unlinkButtonClickHandler = useCallback(async() => {
+    try {
+      await unlink();
+      setIsUnlinked(true);
+    }
+    catch (err) {
+      toastError(err);
+    }
+  }, [unlink]);
+
+  if (redirectFrom == null) {
+    return <></>;
+  }
+
+  if (isUnlinked) {
+    return (<div className="alert alert-info d-edit-none py-3 px-4">
+      <strong>{ t('Unlinked') }: </strong> { t('page_page.notice.unlinked') }
+    </div>);
+  }
+
+  return (
+    <div className="alert alert-pink d-edit-none py-3 px-4 d-flex align-items-center justify-content-between">
+      <span>
+        <strong>{ t('Redirected') }:</strong> { t('page_page.notice.redirected')} <code>{redirectFrom}</code> {t('page_page.notice.redirected_period')}
+      </span>
+      <button type="button" id="unlink-page-button" onClick={unlinkButtonClickHandler} className="btn btn-outline-dark btn-sm float-right">
+        <i className="ti ti-unlink" aria-hidden="true"></i>
+        {t('unlink_redirection')}
+      </button>
+    </div>
+  );
+});
+PageRedirectedAlert.displayName = 'PageRedirectedAlert';

+ 2 - 1
packages/app/src/pages/[[...path]].page.tsx

@@ -34,6 +34,7 @@ import { PageModel, PageDocument } from '~/server/models/page';
 import { PageRedirectModel } from '~/server/models/page-redirect';
 import { UserUISettingsModel } from '~/server/models/user-ui-settings';
 import { useSWRxCurrentPage, useSWRxIsGrantNormalized, useSWRxPageInfo } from '~/stores/page';
+import { useRedirectFrom } from '~/stores/page-redirect';
 import {
   usePreferDrawerModeByUser, usePreferDrawerModeOnEditByUser, useSidebarCollapsed, useCurrentSidebarContents, useCurrentProductNavWidth, useSelectedGrant,
 } from '~/stores/ui';
@@ -187,12 +188,12 @@ const GrowiPage: NextPage<Props> = (props: Props) => {
   useCurrentProductNavWidth(props.userUISettings?.currentProductNavWidth);
 
   // page
-  useCurrentPagePath(props.currentPathname);
   useIsLatestRevision(props.isLatestRevision);
   // useOwnerOfCurrentPage(props.pageUser != null ? JSON.parse(props.pageUser) : null);
   useIsForbidden(props.isForbidden);
   useIsNotFound(props.isNotFound);
   useIsNotCreatable(props.IsNotCreatable);
+  useRedirectFrom(props.redirectFrom);
   // useIsTrashPage(_isTrashPage(props.currentPagePath));
   // useShared();
   // useShareLinkId(props.shareLinkId);

+ 30 - 0
packages/app/src/stores/page-redirect.tsx

@@ -0,0 +1,30 @@
+import { SWRResponseWithUtils, withUtils } from '@growi/core/src/utils/with-utils';
+import { SWRResponse } from 'swr';
+
+import { apiPost } from '~/client/util/apiv1-client';
+
+import { useCurrentPagePath } from './context';
+import { useStaticSWR } from './use-static-swr';
+
+type RedirectFromUtil = {
+  unlink(): Promise<void>
+}
+export const useRedirectFrom = (initialData?: string): SWRResponseWithUtils<RedirectFromUtil, string> => {
+  const { data: currentPagePath } = useCurrentPagePath();
+  const swrResponse: SWRResponse<string, Error> = useStaticSWR('redirectFrom', initialData);
+  const utils = {
+    unlink: async() => {
+      if (currentPagePath == null) {
+        return;
+      }
+      try {
+        await apiPost('/pages.unlink', { path: currentPagePath });
+        swrResponse.mutate('');
+      }
+      catch (err) {
+        throw err;
+      }
+    },
+  };
+  return withUtils(swrResponse, utils);
+};