diff --git a/app/editor/src/components/layout/DefaultLayout.tsx b/app/editor/src/components/layout/DefaultLayout.tsx index 91a413a3df..1bbe777f16 100644 --- a/app/editor/src/components/layout/DefaultLayout.tsx +++ b/app/editor/src/components/layout/DefaultLayout.tsx @@ -2,7 +2,7 @@ import { UnauthenticatedHome } from 'features/home'; import { UserInfo } from 'features/login'; import { Menu } from 'features/navbar'; import React from 'react'; -import { Link, Outlet, useSearchParams } from 'react-router-dom'; +import { Link, Outlet, useLocation, useSearchParams } from 'react-router-dom'; import { toast } from 'react-toastify'; import { IWorkOrderToast, useApiHub, useToastError } from 'store/hooks'; import { @@ -50,10 +50,12 @@ const DefaultLayout: React.FC = ({ useToastError(); const [searchParams] = useSearchParams({ showNav: 'true' }); const { toggle: toggleSystemMessage, isShowing: showSystemMessage } = useModal(); + const location = useLocation(); const [toastIds, setToastIds] = React.useState([]); const showNav = initShowNav ?? searchParams.get('showNav') === 'true'; const [systemMessage, setSystemMessage] = React.useState(); + const isReportInstanceView = /^\/report\/instances\/.*\/view$/.test(location.pathname); React.useEffect(() => { keycloak.instance.onTokenExpired = () => { @@ -148,13 +150,22 @@ const DefaultLayout: React.FC = ({ - +
+ +
+ +
+ +
+
+
+
{ const { id } = useParams(); const instanceId = parseInt(id ?? ''); const [{ userInfo }] = useApp(); + const { editorUrl, subscriberUrl } = useSettings(); const [isLoading, setIsLoading] = React.useState(true); const [view, setView] = React.useState(); const [report, setReport] = React.useState(); + console.error('ReportInstancePreview '); + const handlePreviewReport = React.useCallback( async (instanceId: number) => { try { @@ -67,14 +70,21 @@ const ReportInstancePreview: React.FC = () => { (v) => v, ); - const htmlBlob = new Blob([email.body], { type: 'text/html' }); - const textBlob = new Blob([email.body], { type: 'text/plain' }); + // Replace the URL so that it points to the external site. + let fixed_body = email.body; + if (editorUrl && subscriberUrl) { + const urlReplaceRegex = new RegExp(editorUrl, 'gi'); + fixed_body = email.body.replace(urlReplaceRegex, subscriberUrl); + } + + const htmlBlob = new Blob([fixed_body], { type: 'text/html' }); + const textBlob = new Blob([fixed_body], { type: 'text/plain' }); const clip = new ClipboardItem({ 'text/html': htmlBlob, 'text/plain': textBlob }); navigator.clipboard.write([clip]); const bcc = subscribers.length ? `bcc=${emails.join('; ')}` : ''; window.location.href = `mailto:${to}?${bcc}&subject=${email.subject}&body=Click Paste - Keep Source Formatting`; }, - [getDistributionListById], + [editorUrl, getDistributionListById, subscriberUrl], ); React.useEffect(() => { diff --git a/app/editor/src/features/reports/ReportInstancesRedirect.tsx b/app/editor/src/features/reports/ReportInstancesRedirect.tsx new file mode 100644 index 0000000000..df1c89c9dd --- /dev/null +++ b/app/editor/src/features/reports/ReportInstancesRedirect.tsx @@ -0,0 +1,32 @@ +import { useKeycloak } from '@react-keycloak/web'; +import React from 'react'; +import { useNavigate, useParams } from 'react-router-dom'; + +import ReportInstancePreview from './ReportInstancePreview'; + +/** + * Temporary redirect component for report/instances view + * Redirects unauthenticated users to external URL + * Authenticated users are redirected to the normal view + */ +export const ReportInstancesRedirect: React.FC = () => { + const { keycloak } = useKeycloak(); + const { id } = useParams<{ id: string }>(); + const navigate = useNavigate(); + + React.useEffect(() => { + if (!keycloak?.authenticated) { + // Redirect unauthenticated users to external URL + // TODO: Replace EXTERNAL_URL_HERE with your actual external URL + const externalUrl = `https://mmi.gov.bc.ca/report/instances/${id}/view`; + window.location.href = externalUrl; + } else { + // Redirect authenticated users to the normal view + navigate(`/report/instances/${id}/view`, { replace: true }); + } + }, [keycloak?.authenticated, id, navigate]); + + return ; // This component just handles the redirect +}; + +export default ReportInstancesRedirect; diff --git a/app/editor/src/features/reports/test.html b/app/editor/src/features/reports/test.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/editor/src/features/router/AppRouter.tsx b/app/editor/src/features/router/AppRouter.tsx index b8c5bb3e37..afe8e96e40 100644 --- a/app/editor/src/features/router/AppRouter.tsx +++ b/app/editor/src/features/router/AppRouter.tsx @@ -1,4 +1,5 @@ import { AdminRouter } from 'features/admin'; +import ReportInstancesRedirect from 'features/reports/ReportInstancesRedirect'; import React, { lazy, Suspense } from 'react'; import { Navigate, Route, Routes, useNavigate } from 'react-router-dom'; import { useApp } from 'store/hooks'; @@ -40,8 +41,10 @@ export const AppRouter: React.FC = ({ name }) => { React.useEffect(() => { // There is a race condition, when keycloak is ready state related to user claims will not be. // Additionally, when the user is not authenticated keycloak also is not initialized (which makes no sense). - if (!authenticated && !window.location.pathname.startsWith('/login')) + const isReportInstanceView = /^\/report\/instances\/.*\/view$/.test(window.location.pathname); + if (!authenticated && !window.location.pathname.startsWith('/login') && !isReportInstanceView) { navigate(`/login?redirectTo=${window.location.pathname}`); + } }, [authenticated, navigate]); return ( @@ -125,6 +128,9 @@ export const AppRouter: React.FC = ({ name }) => { } /> } /> + {/* Temporary redirect for unauthenticated users accessing report instances */} + } /> +