Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions cypress/e2e/page/publish-page.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,45 @@ describe('Publish Page Test', () => {
});
});

it('opens publish manage modal from namespace caret and closes share popover first', () => {
cy.on('uncaught:exception', (err: Error) => {
if (err.message.includes('No workspace or service found') ||
err.message.includes('createThemeNoVars_default is not a function') ||
err.message.includes('View not found')) {
return false;
}
return true;
});

cy.visit('/login', { failOnStatusCode: false });
cy.wait(1000);
const authUtils = new AuthTestUtils();
authUtils.signInWithTestUrl(testEmail).then(() => {
cy.url().should('include', '/app');
SidebarSelectors.pageHeader().should('be.visible', { timeout: 30000 });
PageSelectors.names().should('exist', { timeout: 30000 });
cy.wait(2000);

TestTool.openSharePopover();
cy.contains('Publish').should('exist').click({ force: true });
cy.wait(1000);

ShareSelectors.publishConfirmButton().should('be.visible').click({ force: true });
cy.wait(5000);
ShareSelectors.publishNamespace().should('be.visible', { timeout: 10000 });

ShareSelectors.sharePopover().should('exist');
ShareSelectors.openPublishSettingsButton().should('be.visible').click({ force: true });

ShareSelectors.sharePopover().should('not.exist');
ShareSelectors.publishManageModal().should('be.visible');
ShareSelectors.publishManagePanel().should('be.visible').contains('Namespace');

cy.get('body').type('{esc}');
ShareSelectors.publishManageModal().should('not.exist');
});
});

it('publish database (To-dos) and visit published link', () => {
cy.on('uncaught:exception', (err: Error) => {
if (err.message.includes('No workspace or service found') ||
Expand Down
3 changes: 3 additions & 0 deletions cypress/support/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ export const ShareSelectors = {
// Publish namespace and name inputs
publishNamespace: () => cy.get(byTestId('publish-namespace')),
publishNameInput: () => cy.get(byTestId('publish-name-input')),
openPublishSettingsButton: () => cy.get(byTestId('open-publish-settings')),

// Page settings button
pageSettingsButton: () => cy.get(byTestId('page-settings-button')),
Expand All @@ -195,6 +196,8 @@ export const ShareSelectors = {

// Visit Site button
visitSiteButton: () => cy.get(byTestId('visit-site-button')),
publishManageModal: () => cy.get(byTestId('publish-manage-modal')),
publishManagePanel: () => cy.get(byTestId('publish-manage-panel')),
};

/**
Expand Down
28 changes: 19 additions & 9 deletions deploy/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,9 @@ const logger = pino({
options: {
colorize: true,
translateTime: 'SYS:standard',
destination: `${__dirname}/pino-logger.log`,
},
},
level: 'info',
level: process.env.LOG_LEVEL || 'info',
});

const logRequestTimer = (req: Request) => {
Expand All @@ -51,7 +50,7 @@ const fetchMetaData = async (namespace: string, publishName?: string) => {
url = `${baseURL}/api/workspace/v1/published/${namespace}/${publishName}`;
}

logger.info(`Fetching meta data from ${url}`);
logger.debug(`Fetching meta data from ${url}`);
try {
const response = await fetch(url, {
verbose: true,
Expand All @@ -63,11 +62,11 @@ const fetchMetaData = async (namespace: string, publishName?: string) => {

const data = await response.json();

logger.info(`Fetched meta data from ${url}: ${JSON.stringify(data)}`);
logger.debug(`Fetched meta data from ${url}: ${JSON.stringify(data)}`);

return data;
} catch (error) {
logger.error(`Error fetching meta data ${error}`);
logger.error(`Failed to fetch meta data from ${url}: ${error}`);
return null;
}
};
Expand Down Expand Up @@ -130,31 +129,36 @@ const createServer = async (req: Request) => {
}

let metaData;
let redirectAttempted = false;

try {
const data = await fetchMetaData(namespace, publishName);

if (publishName) {
if (data.code === 0) {
if (data && data.code === 0) {
metaData = data.data;
} else {
logger.error(`Error fetching meta data: ${JSON.stringify(data)}`);
logger.error(
`Publish view lookup failed for namespace="${namespace}" publishName="${publishName}" response=${JSON.stringify(data)}`
);
}
} else {

const publishInfo = data?.data?.info;

if (publishInfo) {
if (publishInfo?.namespace && publishInfo?.publish_name) {
const newURL = `/${encodeURIComponent(publishInfo.namespace)}/${encodeURIComponent(publishInfo.publish_name)}`;

logger.info(`Redirecting to default page in: ${JSON.stringify(publishInfo)}`);
redirectAttempted = true;
timer();
return new Response(null, {
status: 302,
headers: {
Location: newURL,
},
});
} else {
logger.warn(`Namespace "${namespace}" has no default publish page. response=${JSON.stringify(data)}`);
}
}
} catch (error) {
Expand Down Expand Up @@ -219,6 +223,12 @@ const createServer = async (req: Request) => {
logger.error(`Error injecting meta data: ${error}`);
}

if (!metaData) {
logger.warn(
`Serving fallback landing page for namespace="${namespace}" publishName="${publishName ?? ''}". redirectAttempted=${redirectAttempted}`
);
}

$('title').text(title);
$('link[rel="icon"]').attr('href', favicon);
$('link[rel="canonical"]').attr('href', url);
Expand Down
2 changes: 1 addition & 1 deletion src/components/app/publish-manage/PublishManage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ export function PublishManage({ onClose }: { onClose?: () => void }) {
const url = `${window.location.origin}/${namespace}`;

return (
<div className={'flex flex-col gap-2'}>
<div className={'flex flex-col gap-2'} data-testid='publish-manage-panel'>
<div className={'px-1 text-base font-medium'}>{t('namespace')}</div>
<div className={'px-1 text-xs text-text-secondary'}>{t('manageNamespaceDescription')}</div>
<Divider className={'mb-2'} />
Expand Down
33 changes: 3 additions & 30 deletions src/components/app/share/PublishLinkPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ import { useTranslation } from 'react-i18next';
import { UpdatePublishConfigPayload } from '@/application/types';
import { ReactComponent as LinkIcon } from '@/assets/icons/link.svg';
import { ReactComponent as DownIcon } from '@/assets/icons/toggle_list.svg';
import { NormalModal } from '@/components/_shared/modal';
import { notify } from '@/components/_shared/notify';
import { PublishManage } from '@/components/app/publish-manage';
import { PublishNameSetting } from '@/components/app/publish-manage/PublishNameSetting';
import { copyTextToClipboard } from '@/utils/copy';

Expand All @@ -20,6 +18,7 @@ function PublishLinkPreview({
isOwner,
isPublisher,
onClose,
onOpenPublishManage,
}: {
viewId: string;
publishInfo: { namespace: string; publishName: string };
Expand All @@ -29,8 +28,8 @@ function PublishLinkPreview({
isOwner: boolean;
isPublisher: boolean;
onClose?: () => void;
onOpenPublishManage?: () => void;
}) {
const [siteOpen, setSiteOpen] = React.useState<boolean>(false);
const [renameOpen, setRenameOpen] = React.useState<boolean>(false);
const { t } = useTranslation();
const [publishName, setPublishName] = React.useState<string>(publishInfo.publishName);
Expand Down Expand Up @@ -78,8 +77,8 @@ function PublishLinkPreview({
<IconButton
size={'small'}
onClick={() => {
setSiteOpen(true);
onClose?.();
onOpenPublishManage?.();
}}
data-testid={'open-publish-settings'}
>
Expand Down Expand Up @@ -161,32 +160,6 @@ function PublishLinkPreview({
url={url}
/>
)}
<NormalModal
okButtonProps={{
className: 'hidden',
}}
cancelButtonProps={{
className: 'hidden',
}}
classes={{
paper: 'w-[700px] appflowy-scroller max-w-[90vw] max-h-[90vh] h-[600px] overflow-hidden',
}}
overflowHidden
onClose={() => {
setSiteOpen(false);
}}
scroll={'paper'}
open={siteOpen}
title={<div className={'flex items-center justify-start'}>{t('settings.sites.title')}</div>}
>
<div className={'h-full w-full overflow-y-auto overflow-x-hidden'}>
<PublishManage
onClose={() => {
setSiteOpen(false);
}}
/>
</div>
</NormalModal>
</div>
</>
);
Expand Down
14 changes: 13 additions & 1 deletion src/components/app/share/PublishPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,17 @@ import { useAppHandlers } from '@/components/app/app.hooks';
import { useLoadPublishInfo } from '@/components/app/share/publish.hooks';
import PublishLinkPreview from '@/components/app/share/PublishLinkPreview';

function PublishPanel({ viewId, opened, onClose }: { viewId: string; onClose: () => void; opened: boolean }) {
function PublishPanel({
viewId,
opened,
onClose,
onOpenPublishManage,
}: {
viewId: string;
onClose: () => void;
opened: boolean;
onOpenPublishManage?: () => void;
}) {
const { t } = useTranslation();
const { publish, unpublish } = useAppHandlers();
const { url, loadPublishInfo, view, publishInfo, loading, isOwner, isPublisher, updatePublishConfig } =
Expand Down Expand Up @@ -92,6 +102,7 @@ function PublishPanel({ viewId, opened, onClose }: { viewId: string; onClose: ()
isOwner={isOwner}
isPublisher={isPublisher}
onClose={onClose}
onOpenPublishManage={onOpenPublishManage}
/>
<div className={'flex w-full items-center justify-end gap-4'}>
<Button
Expand Down Expand Up @@ -157,6 +168,7 @@ function PublishPanel({ viewId, opened, onClose }: { viewId: string; onClose: ()
duplicateEnabled,
updatePublishConfig,
viewId,
onOpenPublishManage,
]);

const layout = view?.layout;
Expand Down
64 changes: 49 additions & 15 deletions src/components/app/share/ShareButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,69 @@ import { useTranslation } from 'react-i18next';
import { ViewLayout } from '@/application/types';
import { useAppView } from '@/components/app/app.hooks';
import ShareTabs from '@/components/app/share/ShareTabs';
import { PublishManage } from '@/components/app/publish-manage';
import { Button } from '@/components/ui/button';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { NormalModal } from '@/components/_shared/modal';

export function ShareButton({ viewId }: { viewId: string }) {
const { t } = useTranslation();

const view = useAppView(viewId);
const layout = view?.layout;
const [opened, setOpened] = React.useState(false);
const [publishManageOpen, setPublishManageOpen] = React.useState(false);

if (layout === ViewLayout.AIChat) return null;

return (
<Popover open={opened} onOpenChange={setOpened}>
<PopoverTrigger asChild>
<Button className={'mx-2'} data-testid={'share-button'} size={'sm'} variant={'default'}>
{t('shareAction.buttonText')}
</Button>
</PopoverTrigger>
<PopoverContent
side='bottom'
align='end'
alignOffset={-20}
className={'h-fit min-w-[480px] max-w-[480px]'}
data-testid={'share-popover'}
<>
<Popover open={opened} onOpenChange={setOpened}>
<PopoverTrigger asChild>
<Button className={'mx-2'} data-testid={'share-button'} size={'sm'} variant={'default'}>
{t('shareAction.buttonText')}
</Button>
</PopoverTrigger>
<PopoverContent
side='bottom'
align='end'
alignOffset={-20}
className={'h-fit min-w-[480px] max-w-[480px]'}
data-testid={'share-popover'}
>
<ShareTabs
opened={opened}
viewId={viewId}
onClose={() => setOpened(false)}
onOpenPublishManage={() => {
setOpened(false);
setPublishManageOpen(true);
}}
/>
</PopoverContent>
</Popover>
<NormalModal
data-testid='publish-manage-modal'
open={publishManageOpen}
onClose={() => setPublishManageOpen(false)}
scroll='paper'
overflowHidden
okButtonProps={{
className: 'hidden',
}}
cancelButtonProps={{
className: 'hidden',
}}
classes={{
paper: 'w-[700px] appflowy-scroller max-w-[90vw] max-h-[90vh] h-[600px] overflow-hidden',
}}
title={<div className={'flex items-center justify-start'}>{t('settings.sites.title')}</div>}
>
<ShareTabs opened={opened} viewId={viewId} onClose={() => setOpened(false)} />
</PopoverContent>
</Popover>
<div className={'h-full w-full overflow-y-auto overflow-x-hidden'}>
<PublishManage onClose={() => setPublishManageOpen(false)} />
</div>
</NormalModal>
</>
);
}

Expand Down
Loading