2022-08-02 11:29:40 +02:00
|
|
|
import React, { useCallback, useReducer } from 'react';
|
2022-02-15 01:02:51 +01:00
|
|
|
import PropTypes from 'prop-types';
|
2022-08-02 11:29:40 +02:00
|
|
|
import { produce } from 'immer';
|
|
|
|
import classnames from 'classnames';
|
2022-02-15 01:02:51 +01:00
|
|
|
import { useI18nContext } from '../../../../hooks/useI18nContext';
|
|
|
|
import CheckBox from '../../../ui/check-box/check-box.component';
|
2023-03-17 12:00:05 +01:00
|
|
|
|
|
|
|
import {
|
2023-03-29 21:17:57 +02:00
|
|
|
BackgroundColor,
|
|
|
|
IconColor,
|
2023-03-17 12:00:05 +01:00
|
|
|
TextVariant,
|
2023-05-23 21:29:14 +02:00
|
|
|
TextAlign,
|
2023-03-29 21:17:57 +02:00
|
|
|
Size,
|
|
|
|
JustifyContent,
|
2023-06-08 12:32:47 +02:00
|
|
|
FontWeight,
|
2023-03-17 12:00:05 +01:00
|
|
|
} from '../../../../helpers/constants/design-system';
|
2022-02-15 01:02:51 +01:00
|
|
|
import Popover from '../../../ui/popover';
|
|
|
|
import Button from '../../../ui/button';
|
2023-04-19 23:16:49 +02:00
|
|
|
import { AvatarIcon, Text, IconName } from '../../../component-library';
|
2023-03-29 21:17:57 +02:00
|
|
|
import Box from '../../../ui/box/box';
|
2022-02-15 01:02:51 +01:00
|
|
|
|
2022-08-02 11:29:40 +02:00
|
|
|
/**
|
|
|
|
* a very simple reducer using produce from Immer to keep checkboxes state manipulation
|
|
|
|
* immutable and painless.
|
|
|
|
*/
|
|
|
|
const checkboxStateReducer = produce((state, action) => {
|
|
|
|
switch (action.type) {
|
|
|
|
case 'check':
|
|
|
|
state[action.checkboxId] = state[action.checkboxId]
|
|
|
|
? !state[action.checkboxId]
|
|
|
|
: true;
|
|
|
|
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw new Error(
|
|
|
|
'You must provide a type when dispatching an action for checkboxState',
|
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2023-06-08 12:32:47 +02:00
|
|
|
export default function SnapInstallWarning({
|
|
|
|
onCancel,
|
|
|
|
onSubmit,
|
|
|
|
warnings,
|
|
|
|
snapName,
|
|
|
|
}) {
|
2022-02-15 01:02:51 +01:00
|
|
|
const t = useI18nContext();
|
2022-08-02 11:29:40 +02:00
|
|
|
const [checkboxState, dispatch] = useReducer(checkboxStateReducer, {});
|
2022-02-15 01:02:51 +01:00
|
|
|
|
2022-08-02 11:29:40 +02:00
|
|
|
const isAllChecked = warnings.every((warning) => checkboxState[warning.id]);
|
|
|
|
|
|
|
|
const onCheckboxClicked = useCallback((checkboxId) => {
|
|
|
|
dispatch({ type: 'check', checkboxId });
|
|
|
|
}, []);
|
2022-02-15 01:02:51 +01:00
|
|
|
|
|
|
|
const SnapInstallWarningFooter = () => {
|
|
|
|
return (
|
|
|
|
<div className="snap-install-warning__footer">
|
|
|
|
<Button
|
|
|
|
className="snap-install-warning__footer-button"
|
|
|
|
type="primary"
|
2022-08-02 11:29:40 +02:00
|
|
|
disabled={!isAllChecked}
|
2022-02-15 01:02:51 +01:00
|
|
|
onClick={onSubmit}
|
|
|
|
>
|
|
|
|
{t('confirm')}
|
|
|
|
</Button>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Popover
|
|
|
|
className="snap-install-warning"
|
|
|
|
footer={<SnapInstallWarningFooter />}
|
2022-03-07 16:32:09 +01:00
|
|
|
headerProps={{ padding: [6, 6, 0] }}
|
2023-03-17 12:00:05 +01:00
|
|
|
contentProps={{
|
|
|
|
paddingLeft: [6, 4],
|
|
|
|
paddingRight: [6, 4],
|
|
|
|
paddingTop: 0,
|
|
|
|
paddingBottom: [6, 4],
|
|
|
|
}}
|
2022-03-07 16:32:09 +01:00
|
|
|
footerProps={{ padding: [4, 6] }}
|
2023-03-29 21:17:57 +02:00
|
|
|
onClose={onCancel}
|
2022-02-15 01:02:51 +01:00
|
|
|
>
|
2023-03-29 21:17:57 +02:00
|
|
|
<Box justifyContent={JustifyContent.center} marginBottom={6}>
|
|
|
|
<AvatarIcon
|
2023-04-19 23:16:49 +02:00
|
|
|
iconName={IconName.Danger}
|
2023-03-29 21:17:57 +02:00
|
|
|
backgroundColor={BackgroundColor.warningMuted}
|
|
|
|
color={IconColor.warningDefault}
|
2023-06-08 12:32:47 +02:00
|
|
|
size={Size.XL}
|
2023-03-29 21:17:57 +02:00
|
|
|
/>
|
|
|
|
</Box>
|
|
|
|
<Text
|
|
|
|
paddingBottom={6}
|
2023-05-23 21:29:14 +02:00
|
|
|
textAlign={TextAlign.Center}
|
2023-06-08 12:32:47 +02:00
|
|
|
variant={TextVariant.headingMd}
|
2023-03-29 21:17:57 +02:00
|
|
|
as="h2"
|
|
|
|
>
|
|
|
|
{t('snapInstallWarningHeading')}
|
|
|
|
</Text>
|
2023-05-23 21:29:14 +02:00
|
|
|
<Text paddingBottom={6} textAlign={TextAlign.Center}>
|
2022-08-02 11:29:40 +02:00
|
|
|
{warnings.length > 1
|
2023-06-08 12:32:47 +02:00
|
|
|
? t('snapInstallWarningCheckPlural', [
|
|
|
|
<Text
|
|
|
|
key="snapNameInWarningDescription"
|
|
|
|
fontWeight={FontWeight.Medium}
|
|
|
|
as="span"
|
|
|
|
>
|
|
|
|
{snapName}
|
|
|
|
</Text>,
|
|
|
|
])
|
|
|
|
: t('snapInstallWarningCheck', [
|
|
|
|
<Text
|
|
|
|
key="snapNameInWarningDescription"
|
|
|
|
fontWeight={FontWeight.Medium}
|
|
|
|
as="span"
|
|
|
|
>
|
|
|
|
{snapName}
|
|
|
|
</Text>,
|
|
|
|
])}
|
2023-03-17 12:00:05 +01:00
|
|
|
</Text>
|
2022-08-02 11:29:40 +02:00
|
|
|
{warnings.map((warning, i) => (
|
|
|
|
<div
|
|
|
|
className={classnames('checkbox-label', {
|
|
|
|
'checkbox-label--first': i === 0,
|
|
|
|
})}
|
|
|
|
key={warning.id}
|
|
|
|
>
|
|
|
|
<CheckBox
|
|
|
|
checked={checkboxState[warning.id] ?? false}
|
|
|
|
id={warning.id}
|
|
|
|
onClick={() => onCheckboxClicked(warning.id)}
|
|
|
|
/>
|
2023-03-17 12:00:05 +01:00
|
|
|
<label htmlFor={warning.id}>
|
2023-06-08 12:32:47 +02:00
|
|
|
<Text variant={TextVariant.bodyMd}>{warning.message}</Text>
|
2023-03-17 12:00:05 +01:00
|
|
|
</label>
|
2022-08-02 11:29:40 +02:00
|
|
|
</div>
|
|
|
|
))}
|
2022-02-15 01:02:51 +01:00
|
|
|
</Popover>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
SnapInstallWarning.propTypes = {
|
|
|
|
/**
|
|
|
|
* onCancel handler
|
|
|
|
*/
|
|
|
|
onCancel: PropTypes.func,
|
|
|
|
/**
|
|
|
|
* onSubmit handler
|
|
|
|
*/
|
|
|
|
onSubmit: PropTypes.func,
|
|
|
|
/**
|
2022-08-02 11:29:40 +02:00
|
|
|
* warnings list
|
2022-02-15 01:02:51 +01:00
|
|
|
*/
|
2022-08-02 11:29:40 +02:00
|
|
|
warnings: PropTypes.arrayOf({
|
|
|
|
message: PropTypes.node,
|
|
|
|
id: PropTypes.string,
|
|
|
|
}),
|
2023-06-08 12:32:47 +02:00
|
|
|
/**
|
|
|
|
* Snap name
|
|
|
|
*/
|
|
|
|
snapName: PropTypes.string.isRequired,
|
2022-02-15 01:02:51 +01:00
|
|
|
};
|