Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/signing cta #2890

Merged
merged 29 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
17eb90c
Signing panel scaffolding
cammiida Jan 4, 2025
7abe0f5
fixes tests
cammiida Jan 5, 2025
031b47d
updates eslint rules for test files
cammiida Jan 5, 2025
2234c76
fixes function name casing
cammiida Jan 5, 2025
340194a
makes panel full width by default and moves full width and conditiona…
cammiida Jan 5, 2025
f6275e7
implements functions and cleans up code
cammiida Jan 9, 2025
52ecdcb
removes reject button in mvp
cammiida Jan 9, 2025
9f39fe4
renames waiting status in current user status
cammiida Jan 9, 2025
c800a8e
replaces signee list staleTime with refetchInterval and added padding…
cammiida Jan 13, 2025
636ed54
adds deprecated warning to getDataValidationUrl
cammiida Jan 13, 2025
f8f3fa8
uses css classes instead of inline css
cammiida Jan 13, 2025
742bf48
adds text resource defaults
cammiida Jan 13, 2025
7e838c2
fixes spacing in panel and alignment of checkbox and label
cammiida Jan 14, 2025
5af4e37
adds checkbox label and description config to layout component
cammiida Jan 14, 2025
9f64a4c
fixes signing document list component test
cammiida Jan 14, 2025
3ccee67
adds all text resources as props for override capability
cammiida Jan 15, 2025
db8756a
renames go_to_inbox -> no_action_required
cammiida Jan 15, 2025
24f6e50
adds reject button to panel if user has reject rights
cammiida Jan 15, 2025
447ada6
adds text resource binding props and text resource defaults for rejec…
cammiida Jan 15, 2025
a1e94fc
ignore layout config.ts files for sonarcloud
cammiida Jan 15, 2025
b4d5325
renames SubmitPanel -> PanelSubmit
cammiida Jan 15, 2025
a19b9e7
splits submit panel in awaiting other signatures panel and submit pan…
cammiida Jan 15, 2025
8829f31
returns no action required panel
cammiida Jan 15, 2025
719aafe
fixes inverted logic error
cammiida Jan 16, 2025
dbf5d99
QA fixes
cammiida Jan 17, 2025
8ebd32a
Merge branch 'feature/signing' into feature/signing-cta
cammiida Jan 17, 2025
c64fd97
removes redundant tests
cammiida Jan 20, 2025
43e68c8
Merge branch 'feature/signing' into feature/signing-cta
cammiida Jan 20, 2025
49909d3
fixes document list test
cammiida Jan 20, 2025
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
1 change: 1 addition & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ export default tseslint.config(
rules: {
'testing-library/await-async-queries': ['warn'],
'jsx-a11y/label-has-associated-control': ['off'],
'@typescript-eslint/consistent-type-imports': ['off'],
},
},
{
Expand Down
2 changes: 1 addition & 1 deletion sonar-project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ sonar.projectKey=Altinn_app-frontend-react
sonar.organization=altinn

sonar.sources=src/
sonar.exclusions=src/**/*.test.ts*,src/language/texts/**
sonar.exclusions=src/**/*.test.ts*,src/language/texts/**,src/layout/**/config.ts

sonar.tests=src/,test/
sonar.test.inclusions=src/**/*.test.tsx,src/**/*.test.ts
Expand Down
24 changes: 16 additions & 8 deletions src/app-components/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export type ButtonProps = {
| 'aria-labelledby'
| 'aria-describedby'
| 'onKeyUp'
| 'asChild'
>;

export const Button = forwardRef<HTMLButtonElement, PropsWithChildren<ButtonProps>>(function Button(
Expand All @@ -54,6 +55,7 @@ export const Button = forwardRef<HTMLButtonElement, PropsWithChildren<ButtonProp
tabIndex,
onMouseDown,
onKeyUp,
asChild,
'aria-label': ariaLabel,
'aria-busy': ariaBusy,
'aria-controls': ariaControls,
Expand All @@ -65,6 +67,7 @@ export const Button = forwardRef<HTMLButtonElement, PropsWithChildren<ButtonProp
ref,
) {
const { langAsString } = useLanguage();

return (
<DesignSystemButton
id={id}
Expand All @@ -82,6 +85,7 @@ export const Button = forwardRef<HTMLButtonElement, PropsWithChildren<ButtonProp
tabIndex={tabIndex}
onMouseDown={onMouseDown}
onKeyUp={onKeyUp}
asChild={asChild}
aria-label={ariaLabel}
aria-busy={ariaBusy}
aria-controls={ariaControls}
Expand All @@ -90,15 +94,19 @@ export const Button = forwardRef<HTMLButtonElement, PropsWithChildren<ButtonProp
aria-labelledby={ariaLabelledBy}
aria-describedby={ariaDescribedBy}
>
{isLoading && (
<Spinner
aria-hidden='true'
color={color}
size={size === 'lg' ? 'sm' : 'xs'}
title={langAsString('general.loading')}
/>
{isLoading ? (
<>
<Spinner
aria-hidden='true'
color={color}
size={size === 'lg' ? 'sm' : 'xs'}
title={langAsString('general.loading')}
/>
{children}
</>
) : (
children
)}
{children}
</DesignSystemButton>
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from 'react';
import { jest } from '@jest/globals';
import { render as rtlRender, screen } from '@testing-library/react';

import { ConditionalWrapper } from 'src/components/ConditionalWrapper';
import { ConditionalWrapper } from 'src/app-components/ConditionalWrapper/ConditionalWrapper';

describe('ConditionalWrapper', () => {
it('should pass children to wrapper callback when condition is true', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { HTMLProps } from 'react';

import cn from 'classnames';

import classes from 'src/components/form/FullWidthWrapper.module.css';
import classes from 'src/app-components/FullWidthWrapper/FullWidthWrapper.module.css';

export interface IFullWidthWrapperProps extends HTMLProps<HTMLDivElement> {
children?: React.ReactNode;
Expand Down
76 changes: 51 additions & 25 deletions src/app-components/Panel/Panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,24 @@ import {
} from '@navikt/aksel-icons';
import cn from 'classnames';

import { ConditionalWrapper } from 'src/app-components/ConditionalWrapper/ConditionalWrapper';
import { FullWidthWrapper } from 'src/app-components/FullWidthWrapper/FullWidthWrapper';
import { PANEL_VARIANT } from 'src/app-components/Panel/constants';
import classes from 'src/app-components/Panel/Panel.module.css';
import { useIsMobile } from 'src/hooks/useDeviceWidths';

export type PanelVariant = (typeof PANEL_VARIANT)[keyof typeof PANEL_VARIANT];

type PanelProps = PropsWithChildren<{
export type PanelProps = PropsWithChildren<{
variant: PanelVariant;
showIcon?: boolean;
forceMobileLayout?: boolean;
title?: JSX.Element;
style?: React.CSSProperties;
className?: string;
fullWidth?: boolean;
isOnBottom?: boolean;
isOnTop?: boolean;
}>;

type PanelIconProps = {
Expand Down Expand Up @@ -68,42 +74,62 @@ export const Panel: React.FC<PanelProps> = ({
variant,
showIcon = false,
forceMobileLayout = false,
fullWidth = true,
isOnBottom,
isOnTop,
title,
style,
className,
children,
}) => {
const isMobile = useIsMobile();
const isMobileLayout = forceMobileLayout || isMobile;

return (
<div
className={cn(classes.panel, {
[classes.panelMobileLayout]: isMobileLayout,
})}
style={style}
<ConditionalWrapper
condition={fullWidth}
wrapper={(child) => (
<FullWidthWrapper
isOnBottom={isOnBottom}
isOnTop={isOnTop}
>
{child}
</FullWidthWrapper>
)}
>
<div className={cn(classes.panelContentWrapper, classes[`panelContentWrapper_${variant}`])}>
{showIcon && (
<div className={cn(classes.panelIconWrapper, classes[`panelIconWrapper_${variant}`])}>
<PanelIcon
isMobileLayout={isMobileLayout}
variant={variant}
/>
</div>
<div
className={cn(
classes.panel,
{
[classes.panelMobileLayout]: isMobileLayout,
},
className,
)}
<div className={classes.panelContent}>
{title && (
<Heading
level={2}
size={isMobileLayout ? 'xs' : 'sm'}
className={classes.panelHeader}
>
{title}
</Heading>
style={style}
>
<div className={cn(classes.panelContentWrapper, classes[`panelContentWrapper_${variant}`])}>
{showIcon && (
<div className={cn(classes.panelIconWrapper, classes[`panelIconWrapper_${variant}`])}>
<PanelIcon
isMobileLayout={isMobileLayout}
variant={variant}
/>
</div>
)}
<div>{children}</div>
<div className={classes.panelContent}>
{title && (
<Heading
level={2}
size={isMobileLayout ? 'xs' : 'sm'}
className={classes.panelHeader}
>
{title}
</Heading>
)}
<div>{children}</div>
</div>
</div>
</div>
</div>
</ConditionalWrapper>
);
};
4 changes: 2 additions & 2 deletions src/components/altinnAppHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { LandmarkShortcuts } from 'src/components/LandmarkShortcuts';
import { AltinnLogo, LogoColor } from 'src/components/logo/AltinnLogo';
import { Lang } from 'src/features/language/Lang';
import { renderParty } from 'src/utils/party';
import { returnUrlToAllSchemas, returnUrlToMessagebox, returnUrlToProfile } from 'src/utils/urls/urlHelper';
import { returnUrlToAllSchemas, returnUrlToMessageBox, returnUrlToProfile } from 'src/utils/urls/urlHelper';
import type { IProfile } from 'src/types/shared';

export interface IHeaderProps {
Expand Down Expand Up @@ -49,7 +49,7 @@ export const AltinnAppHeader = ({ profile }: IHeaderProps) => {
<li className={classes.headerLink}>
<a
className='altinnLink'
href={returnUrlToMessagebox(window.location.origin, party?.partyId) || '#'}
href={returnUrlToMessageBox(window.location.origin, party?.partyId) || '#'}
>
<Lang id='instantiate.inbox' />
</a>
Expand Down
2 changes: 1 addition & 1 deletion src/components/form/RadioButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { HelpText, Radio } from '@digdir/designsystemet-react';
import cn from 'classnames';
import type { RadioProps } from '@digdir/designsystemet-react';

import { ConditionalWrapper } from 'src/components/ConditionalWrapper';
import { ConditionalWrapper } from 'src/app-components/ConditionalWrapper/ConditionalWrapper';
import classes from 'src/components/form/RadioButton.module.css';
import { DeleteWarningPopover } from 'src/features/alertOnChange/DeleteWarningPopover';
import { useAlertOnChange } from 'src/features/alertOnChange/useAlertOnChange';
Expand Down
76 changes: 37 additions & 39 deletions src/components/message/ErrorReport.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import React from 'react';
import { Flex } from 'src/app-components/Flex/Flex';
import { PANEL_VARIANT } from 'src/app-components/Panel/constants';
import { Panel } from 'src/app-components/Panel/Panel';
import { FullWidthWrapper } from 'src/components/form/FullWidthWrapper';
import classes from 'src/components/message/ErrorReport.module.css';
import { useNavigateToNode } from 'src/features/form/layout/NavigateToNode';
import { Lang } from 'src/features/language/Lang';
Expand Down Expand Up @@ -33,50 +32,49 @@ export const ErrorReport = ({ renderIds, formErrors, taskErrors }: IErrorReportP

return (
<div data-testid='ErrorReport'>
<FullWidthWrapper isOnBottom={true}>
<Panel
title={<Lang id='form_filler.error_report_header' />}
variant={PANEL_VARIANT.Error}
<Panel
title={<Lang id='form_filler.error_report_header' />}
variant={PANEL_VARIANT.Error}
isOnBottom
>
<Flex
container
item
spacing={6}
alignItems='flex-start'
>
<Flex
container
item
spacing={6}
alignItems='flex-start'
size={{ xs: 12 }}
>
<Flex
item
size={{ xs: 12 }}
>
<ul className={classes.errorList}>
{taskErrors.map((error) => (
<li
key={getUniqueKeyFromObject(error)}
style={{ listStyleImage: listStyleImg }}
>
<Lang
id={error.message.key}
params={error.message.params}
/>
</li>
))}
{formErrors.map((error) => (
<Error
key={getUniqueKeyFromObject(error)}
error={error}
<ul className={classes.errorList}>
{taskErrors.map((error) => (
<li
key={getUniqueKeyFromObject(error)}
style={{ listStyleImage: listStyleImg }}
>
<Lang
id={error.message.key}
params={error.message.params}
/>
))}
</ul>
</Flex>
{renderIds.map((id) => (
<GenericComponentById
key={id}
id={id}
/>
))}
</li>
))}
{formErrors.map((error) => (
<Error
key={getUniqueKeyFromObject(error)}
error={error}
/>
))}
</ul>
</Flex>
</Panel>
</FullWidthWrapper>
{renderIds.map((id) => (
<GenericComponentById
key={id}
id={id}
/>
))}
</Flex>
</Panel>
</div>
);
};
Expand Down
4 changes: 2 additions & 2 deletions src/components/presentation/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { useNavigatePage, usePreviousPageKey } from 'src/hooks/useNavigatePage';
import { PresentationType, ProcessTaskType } from 'src/types';
import { httpGet } from 'src/utils/network/networking';
import { getRedirectUrl } from 'src/utils/urls/appUrlHelper';
import { returnUrlToMessagebox } from 'src/utils/urls/urlHelper';
import { returnUrlToMessageBox } from 'src/utils/urls/urlHelper';

export interface INavBarProps {
type: PresentationType | ProcessTaskType;
Expand Down Expand Up @@ -43,7 +43,7 @@ export const NavBar = ({ type }: INavBarProps) => {
const handleModalCloseButton = async () => {
const queryParameterReturnUrl = new URLSearchParams(window.location.search).get('returnUrl');

const messageBoxUrl = returnUrlToMessagebox(window.location.origin, party?.partyId);
const messageBoxUrl = returnUrlToMessageBox(window.location.origin, party?.partyId);

if (queryParameterReturnUrl) {
const returnUrl =
Expand Down
6 changes: 3 additions & 3 deletions src/components/presentation/Presentation.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { renderWithInstanceAndLayout } from 'src/test/renderWithProviders';
import { AltinnPalette } from 'src/theme/altinnAppTheme';
import { ProcessTaskType } from 'src/types';
import { HttpStatusCodes } from 'src/utils/network/networking';
import { returnUrlToMessagebox } from 'src/utils/urls/urlHelper';
import { returnUrlToMessageBox } from 'src/utils/urls/urlHelper';
import type { IPresentationProvidedProps } from 'src/components/presentation/Presentation';

jest.mock('axios');
Expand Down Expand Up @@ -59,7 +59,7 @@ describe('Presentation', () => {
const returnUrl = 'https://altinn.cloud.no';
const mockedLocation = { ...realLocation, search: `?returnUrl=${returnUrl}`, assign: assignMock, origin };
jest.spyOn(window, 'location', 'get').mockReturnValue(mockedLocation);
const messageBoxUrl = returnUrlToMessagebox(origin, getPartyMock().partyId);
const messageBoxUrl = returnUrlToMessageBox(origin, getPartyMock().partyId);

mockedAxios.get.mockRejectedValue({
data: 'Error',
Expand All @@ -83,7 +83,7 @@ describe('Presentation', () => {
it('should change window.location.href to default messagebox url if query parameter returnUrl is not found', async () => {
const origin = 'https://local.altinn.cloud';
const partyId = getPartyMock().partyId;
const messageBoxUrl = returnUrlToMessagebox(origin, partyId);
const messageBoxUrl = returnUrlToMessageBox(origin, partyId);
const mockedLocation = { ...realLocation, assign: assignMock, origin, search: '' };

jest.spyOn(window, 'location', 'get').mockReturnValue(mockedLocation);
Expand Down
1 change: 1 addition & 0 deletions src/features/expressions/expression-functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ export const ExprFunctions = {
confirm: true,
sign: true,
reject: true,
complete: true,
};

if (key === null || authContextKeys[key] !== true) {
Expand Down
Loading
Loading