chore: Bump terms

This commit is contained in:
Maksim Eltyshev
2026-02-11 14:03:37 +01:00
parent d84b615815
commit 168776aef8
42 changed files with 456 additions and 155 deletions
@@ -3,10 +3,10 @@
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
*/
import React, { useCallback, useState } from 'react';
import React, { useCallback, useMemo, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useTranslation } from 'react-i18next';
import { Button, Checkbox, Dropdown, Modal } from 'semantic-ui-react';
import { Button, Checkbox, Dropdown, Modal, Segment } from 'semantic-ui-react';
import selectors from '../../../selectors';
import entryActions from '../../../entry-actions';
@@ -18,6 +18,25 @@ import styles from './TermsModal.module.scss';
const LOCALES = TERMS_LANGUAGES.map((language) => localeByLanguage[language]);
const splitTermsAndConfirmations = (content) => {
const separator = '\n---\n';
const index = content.lastIndexOf(separator);
if (index === -1) {
return [content.trim(), []];
}
const terms = content.slice(0, index).trim();
const confirmations = content
.slice(index + separator.length)
.split('\n')
.map((confirmation) => confirmation.replace(/^✔️\s*/, '').replace(/\*\*(.*?)\*\*/, '$1'))
.filter(Boolean);
return [terms, confirmations];
};
const TermsModal = React.memo(() => {
const {
termsForm: { payload: terms, isSubmitting, isCancelling, isLanguageUpdating },
@@ -25,7 +44,12 @@ const TermsModal = React.memo(() => {
const dispatch = useDispatch();
const [t] = useTranslation();
const [isTermsAccepted, setIsTermsAccepted] = useState(false);
const [acceptedConfirmationsSet, setAcceptedConfirmationsSet] = useState(new Set());
const [content, confirmations] = useMemo(
() => splitTermsAndConfirmations(terms.content),
[terms.content],
);
const handleContinueClick = useCallback(() => {
dispatch(entryActions.acceptTerms(terms.signature));
@@ -42,10 +66,22 @@ const TermsModal = React.memo(() => {
[dispatch],
);
const handleToggleAcceptClick = useCallback((_, { checked }) => {
setIsTermsAccepted(checked);
const handleToggleConfirmationAccept = useCallback((index) => {
setAcceptedConfirmationsSet((prevAcceptedConfirmationsSet) => {
const nextAcceptedConfirmationsSet = new Set(prevAcceptedConfirmationsSet);
if (nextAcceptedConfirmationsSet.has(index)) {
nextAcceptedConfirmationsSet.delete(index);
} else {
nextAcceptedConfirmationsSet.add(index);
}
return nextAcceptedConfirmationsSet;
});
}, []);
const isAllConfirmationsAccepted = acceptedConfirmationsSet.size === confirmations.length;
return (
<Modal open centered={false}>
<Modal.Content>
@@ -63,7 +99,20 @@ const TermsModal = React.memo(() => {
className={styles.language}
onChange={handleLanguageChange}
/>
<Markdown>{terms.content}</Markdown>
<Markdown>{content}</Markdown>
{confirmations.length > 0 && (
<Segment size="massive" className={styles.confirmations}>
{confirmations.map((confirmation, index) => (
<Checkbox
key={confirmation}
checked={acceptedConfirmationsSet.has(index)}
label={confirmation}
className={styles.confirmationCheckbox}
onChange={() => handleToggleConfirmationAccept(index)}
/>
))}
</Segment>
)}
</Modal.Content>
<Modal.Actions>
<Button
@@ -74,15 +123,11 @@ const TermsModal = React.memo(() => {
className={styles.cancelButton}
onClick={handleCancelClick}
/>
<Checkbox
label={t('common.iHaveReadAndAgreeToTheseTerms')}
onChange={handleToggleAcceptClick}
/>
<Button
positive
content={t('action.continue')}
loading={isSubmitting}
disabled={!isTermsAccepted || isSubmitting || isCancelling}
disabled={!isAllConfirmationsAccepted || isSubmitting || isCancelling}
onClick={handleContinueClick}
/>
</Modal.Actions>
@@ -8,6 +8,19 @@
margin-left: 0;
}
.confirmations {
border-color: #5aac44;
border-width: 2px;
box-shadow: none;
display: flex;
flex-direction: column;
row-gap: 12px;
}
.confirmationCheckbox {
font-weight: bold;
}
.language {
margin-bottom: 20px;
}