Skip to content

Commit

Permalink
Replace beta info popover in preview button with alert info panel in …
Browse files Browse the repository at this point in the history
…preview page (#11307)

* Remove beta info popover from preview button and add test for info alert being shown in preview

* Add alert info to preview in ux-editor

* Change text by request from UX

* Add popover and session saving for preview limitations info

* fix review-comments and failing tests

* Use grid to avoid dynamically setting the height

* use grid on preview for 'lage'

* Add test to check if popover opens on close-click in alert in preview

* Delete previewContext
  • Loading branch information
standeren authored and nkylstad committed Nov 5, 2023
1 parent 0cac230 commit 1bada94
Show file tree
Hide file tree
Showing 16 changed files with 255 additions and 182 deletions.
10 changes: 0 additions & 10 deletions backend/src/Designer/Controllers/PreviewController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,6 @@ public IActionResult Index(string org, string app)
return View();
}

/// <summary>
/// Get status if app is ready for preview
/// </summary>
[HttpGet]
[Route("preview/preview-status")]
public ActionResult<string> PreviewStatus()
{
return Ok();
}

/// <summary>
/// Action for getting local app-images
/// </summary>
Expand Down

This file was deleted.

1 change: 0 additions & 1 deletion frontend/app-development/layout/PageHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ export const buttonActions = (org: string, app: string): AltinnButtonActionItem[
buttonColor: 'inverted',
headerButtonsClasses: undefined,
handleClick: () => (window.location.href = previewPath(org, app)),
inBeta: true,
},
{
title: 'top_menu.deploy',
Expand Down
5 changes: 5 additions & 0 deletions frontend/app-preview/src/PreviewApp.module.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
:root {
--font-family: 'Inter', sans-serif;
}

.previewContainer {
--toolbar-height: 80px;
--subtoolbar-height: 60px;
Expand All @@ -7,6 +11,7 @@
);
--left-menu-width: 68px;

background-color: #efefef;
min-height: 100vh;
width: 100%;
display: flex;
Expand Down
25 changes: 0 additions & 25 deletions frontend/app-preview/src/PreviewContext.tsx

This file was deleted.

36 changes: 26 additions & 10 deletions frontend/app-preview/src/views/LandingPage.module.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.header {
font-family: Inter, 'San Fransisco', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-family: var(--font-family);
align-items: center;
height: var(--header-height);
width: 100vw;
Expand All @@ -15,7 +15,13 @@
border: none;
}

.iframeMobileViewContainer {
.previewLimitationsInfo {
max-width: 1000px;
width: 100%;
margin: 10px auto;
}

.iframeContainer {
display: flex;
justify-content: center;
background-color: #efefef;
Expand All @@ -30,12 +36,22 @@
margin: 0;
}

/* Mobile View Overlay to cover devtools in the middle of the screen */
.iframeMobileViewOverlay {
position: absolute;
bottom: 0;
height: 100px;
width: 100%;
background-color: #efefef;
z-index: 1;
.alert {
display: flex;
flex-direction: row;
align-self: center;
align-items: center;
width: fit-content;
font-family: var(--font-family);
}

.row {
display: flex;
flex-direction: row;
gap: 1rem;
}

.gridContainer {
display: grid;
grid-template-rows: max-content max-content;
}
84 changes: 84 additions & 0 deletions frontend/app-preview/src/views/LandingPage.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import React from 'react';
import { act, screen, queryByAttribute, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { LandingPage } from './LandingPage';
import { renderWithMockStore } from '../../../../frontend/packages/ux-editor/src/testing/mocks';
import { textMock } from '../../../testing/mocks/i18nMock';

describe('LandingPage', () => {

it('should render an iframe', () => {
const { renderResult } = renderWithMockStore()(<LandingPage variant={'preview'} />);

const getById = queryByAttribute.bind(null, 'id');

const iframe = getById(renderResult.container, 'app-frontend-react-iframe');
expect(iframe).toBeInTheDocument();
});

it('should render the information alert with preview being limited', () => {
renderWithMockStore()(<LandingPage variant={'preview'} />);

const previewLimitationsAlert = screen.getByText(textMock('preview.limitations_info'));
expect(previewLimitationsAlert).toBeInTheDocument();
});

it('should render a popover with options for remembering closing-choice in session or not when clicking cross-button in alert', async () => {
renderWithMockStore()(<LandingPage variant={'preview'} />);

const user = userEvent.setup();

const previewLimitationsAlert = screen.getByText(textMock('preview.limitations_info'));
const alert = within(previewLimitationsAlert);
const hidePreviewLimitationsAlertButton = alert.getByRole('button');
await act(() => user.click(hidePreviewLimitationsAlertButton));
const hidePreviewLimitationsPopover = screen.getByText(textMock('session.reminder'));
expect(hidePreviewLimitationsPopover).toBeInTheDocument();
const hidePreviewLimitationsTemporaryButton = screen.getByRole('button', { name: textMock('session.do_show_again') });
const hidePreviewLimitationsForSessionButton = screen.getByRole('button', { name: textMock('session.dont_show_again') });
expect(hidePreviewLimitationsTemporaryButton).toBeInTheDocument();
expect(hidePreviewLimitationsForSessionButton).toBeInTheDocument();
});

it('should close popover and not set value in session storage when hidePreviewLimitationsTemporaryButton is clicked', async () => {
renderWithMockStore()(<LandingPage variant={'preview'} />);

const user = userEvent.setup();

// Open popover
const previewLimitationsAlert = screen.getByText(textMock('preview.limitations_info'));
const alert = within(previewLimitationsAlert);
const hidePreviewLimitationsAlertButton = alert.getByRole('button');
await act(() => user.click(hidePreviewLimitationsAlertButton));
const hidePreviewLimitationsPopover = screen.getByText(textMock('session.reminder'));
expect(hidePreviewLimitationsPopover).toBeInTheDocument();
const hidePreviewLimitationsTemporaryButton = screen.getByRole('button', { name: textMock('session.do_show_again') });

// Click hide temporary button
await act(() => user.click(hidePreviewLimitationsTemporaryButton));

expect(hidePreviewLimitationsPopover).not.toBeInTheDocument();
expect(window.sessionStorage.getItem('showPreviewLimitationsInfo')).toBeNull();
});

it('should close popover and set value in session storage when hidePreviewLimitationsForSessionButton is clicked', async () => {
renderWithMockStore()(<LandingPage variant={'preview'} />);

const user = userEvent.setup();

// Open popover
const previewLimitationsAlert = screen.getByText(textMock('preview.limitations_info'));
const alert = within(previewLimitationsAlert);
const hidePreviewLimitationsAlertButton = alert.getByRole('button');
await act(() => user.click(hidePreviewLimitationsAlertButton));
const hidePreviewLimitationsPopover = screen.getByText(textMock('session.reminder'));
expect(hidePreviewLimitationsPopover).toBeInTheDocument();
const hidePreviewLimitationsForSessionButton = screen.getByRole('button', { name: textMock('session.dont_show_again') });

// Click hide forever button
await act(() => user.click(hidePreviewLimitationsForSessionButton));

expect(hidePreviewLimitationsPopover).not.toBeInTheDocument();
expect(window.sessionStorage.getItem('showPreviewLimitationsInfo')).toBe('false');
});
});
93 changes: 62 additions & 31 deletions frontend/app-preview/src/views/LandingPage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React from 'react';
import React, { useState } from 'react';
import classes from './LandingPage.module.css';
import { PreviewContext } from '../PreviewContext';
import { useTranslation } from 'react-i18next';
import { usePreviewConnection } from 'app-shared/providers/PreviewConnectionContext';
import { useInstanceIdQuery, useRepoMetadataQuery, useUserQuery } from 'app-shared/hooks/queries';
Expand All @@ -14,8 +13,11 @@ import {
} from '../components/AppBarConfig/AppPreviewBarConfig';
import { appPreviewButtonActions } from '../components/AppBarConfig/AppPreviewBarConfig';
import { AppPreviewSubMenu } from '../components/AppPreviewSubMenu';
import { Alert, Button, LegacyPopover } from '@digdir/design-system-react';
import { XMarkIcon } from '@navikt/aksel-icons';
import { useStudioUrlParams } from 'app-shared/hooks/useStudioUrlParams';
import { previewPage } from 'app-shared/api/paths';
import { typedSessionStorage } from 'app-shared/utils/webStorage';

export interface LandingPageProps {
variant?: AltinnHeaderVariant;
Expand All @@ -30,15 +32,19 @@ export const LandingPage = ({ variant = 'preview' }: LandingPageProps) => {
const { data: user } = useUserQuery();
const { data: repository } = useRepoMetadataQuery(org, app);
const { data: instanceId } = useInstanceIdQuery(org, app);
const repoType = getRepositoryType(org, app);
const menu = getTopBarAppPreviewMenu(org, app, repoType, t);
const [openSaveChoiceInSession, setOpenShowSaveChoiceInSession] = useState<boolean>(false);
const showPreviewLimitationsInfoSession: boolean = typedSessionStorage.getItem('showPreviewLimitationsInfo');
const [showPreviewLimitationsInfo, setShowPreviewLimitationsInfo] = useState<boolean>(showPreviewLimitationsInfoSession ?? true);
const [selectedLayoutSetInEditor, setSelectedLayoutSetInEditor] = useLocalStorage<string>(
'layoutSet/' + app,
);
const [previewViewSize, setPreviewViewSize] = useLocalStorage<PreviewAsViewSize>(
'viewSize',
'desktop',
);

const repoType = getRepositoryType(org, app);
const menu = getTopBarAppPreviewMenu(org, app, repoType, t);
const isIFrame = (input: HTMLElement | null): input is HTMLIFrameElement =>
input !== null && input.tagName === 'IFRAME';

Expand All @@ -48,6 +54,16 @@ export const LandingPage = ({ variant = 'preview' }: LandingPageProps) => {
window.location.reload();
};

const handleHidePreviewLimitations = () => {
setShowPreviewLimitationsInfo(false);
setOpenShowSaveChoiceInSession(false);
};

const handleRememberChoiceForSession = () => {
typedSessionStorage.setItem('showPreviewLimitationsInfo', false);
handleHidePreviewLimitations();
};

if (previewConnection) {
previewConnection.on('ReceiveMessage', function (message) {
const frame = document.getElementById('app-frontend-react-iframe');
Expand All @@ -62,39 +78,54 @@ export const LandingPage = ({ variant = 'preview' }: LandingPageProps) => {
}

return (
<PreviewContext>
<>
<div className={classes.header}>
<AltinnHeader
menu={menu}
showSubMenu={true}
activeMenuSelection={TopBarAppPreviewMenu.Preview}
org={org}
app={app}
user={user}
repository={repository}
buttonActions={appPreviewButtonActions(org, app, instanceId)}
variant={variant}
subMenuContent={
<AppPreviewSubMenu
setViewSize={setPreviewViewSize}
viewSize={previewViewSize}
selectedLayoutSet={selectedLayoutSetInEditor}
handleChangeLayoutSet={handleChangeLayoutSet}
/>
}
/>
</div>
<div className={classes.iframeMobileViewContainer}>
<>
<div className={classes.header}>
<AltinnHeader
menu={menu}
showSubMenu={true}
activeMenuSelection={TopBarAppPreviewMenu.Preview}
org={org}
app={app}
user={user}
repository={repository}
buttonActions={appPreviewButtonActions(org, app, instanceId)}
variant={variant}
subMenuContent={
<AppPreviewSubMenu
setViewSize={setPreviewViewSize}
viewSize={previewViewSize}
selectedLayoutSet={selectedLayoutSetInEditor}
handleChangeLayoutSet={handleChangeLayoutSet}
/>
}
/>
</div>
<div className={classes.gridContainer}>
{showPreviewLimitationsInfo &&
<Alert severity='info' className={classes.previewLimitationsInfo}>
<div className={classes.alert}>
{t('preview.limitations_info')}
<LegacyPopover
trigger={<Button onClick={() => setOpenShowSaveChoiceInSession(!openSaveChoiceInSession)} size='small' variant='tertiary' icon={<XMarkIcon />}/>}
open={openSaveChoiceInSession}
>
{t('session.reminder')}
<span className={classes.row}>
<Button onClick={handleHidePreviewLimitations} size='small' variant='secondary'>{t('session.do_show_again')}</Button>
<Button onClick={handleRememberChoiceForSession} size='small' variant='secondary'>{t('session.dont_show_again')}</Button>
</span>
</LegacyPopover>
</div>
</Alert>}
<div className={classes.iframeContainer}>
<iframe
title={t('preview.iframe_title')}
id='app-frontend-react-iframe'
src={previewPage(org, app, selectedLayoutSetInEditor)}
className={previewViewSize === 'desktop' ? classes.iframeDesktop : classes.iframeMobile}
/>
{previewViewSize === 'mobile' && <div className={classes.iframeMobileViewOverlay}></div>}
</div>
</>
</PreviewContext>
</div>
</>
);
};
1 change: 0 additions & 1 deletion frontend/language/src/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -917,7 +917,6 @@
"top_menu.policy-editor": "Policy",
"top_menu.preview": "Preview",
"top_menu.preview_back_to_editing": "Back to editing",
"top_menu.preview_is_beta_message": "This functionality is in beta. We are working to improve it.",
"top_menu.process-editor": "Process",
"top_menu.texts": "Texts",
"top_menu.texts_old": "Texts *",
Expand Down
Loading

0 comments on commit 1bada94

Please sign in to comment.