mirror of
https://github.com/plankanban/planka.git
synced 2025-07-18 20:59:44 +02:00
ref: Creating popups with hook, fix translation keys passing
This commit is contained in:
parent
6fd42e3b62
commit
d975b2d07a
69 changed files with 309 additions and 332 deletions
|
@ -1,11 +1,12 @@
|
||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { usePopup } from '../../lib/popup';
|
||||||
|
|
||||||
import User from '../User';
|
import User from '../User';
|
||||||
import Label from '../Label';
|
import Label from '../Label';
|
||||||
import BoardMembershipsPopup from '../BoardMembershipsPopup';
|
import BoardMembershipsStep from '../BoardMembershipsStep';
|
||||||
import LabelsPopup from '../LabelsPopup';
|
import LabelsStep from '../LabelsStep';
|
||||||
|
|
||||||
import styles from './Filters.module.scss';
|
import styles from './Filters.module.scss';
|
||||||
|
|
||||||
|
@ -41,15 +42,16 @@ const Filters = React.memo(
|
||||||
[onLabelRemove],
|
[onLabelRemove],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const BoardMembershipsPopup = usePopup(BoardMembershipsStep);
|
||||||
|
const LabelsPopup = usePopup(LabelsStep);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<span className={styles.filter}>
|
<span className={styles.filter}>
|
||||||
<BoardMembershipsPopup
|
<BoardMembershipsPopup
|
||||||
items={allBoardMemberships}
|
items={allBoardMemberships}
|
||||||
currentUserIds={users.map((user) => user.id)}
|
currentUserIds={users.map((user) => user.id)}
|
||||||
title={t('common.filterByMembers', {
|
title="common.filterByMembers"
|
||||||
context: 'title',
|
|
||||||
})}
|
|
||||||
onUserSelect={onUserAdd}
|
onUserSelect={onUserAdd}
|
||||||
onUserDeselect={onUserRemove}
|
onUserDeselect={onUserRemove}
|
||||||
>
|
>
|
||||||
|
@ -73,9 +75,7 @@ const Filters = React.memo(
|
||||||
<LabelsPopup
|
<LabelsPopup
|
||||||
items={allLabels}
|
items={allLabels}
|
||||||
currentIds={labels.map((label) => label.id)}
|
currentIds={labels.map((label) => label.id)}
|
||||||
title={t('common.filterByLabels', {
|
title="common.filterByLabels"
|
||||||
context: 'title',
|
|
||||||
})}
|
|
||||||
canEdit={canEdit}
|
canEdit={canEdit}
|
||||||
onSelect={onLabelAdd}
|
onSelect={onLabelAdd}
|
||||||
onDeselect={onLabelRemove}
|
onDeselect={onLabelRemove}
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
import { withPopup } from '../lib/popup';
|
|
||||||
|
|
||||||
import BoardMembershipsStep from './BoardMembershipsStep';
|
|
||||||
|
|
||||||
export default withPopup(BoardMembershipsStep);
|
|
|
@ -1,3 +0,0 @@
|
||||||
import AddPopup from './AddPopup';
|
|
||||||
|
|
||||||
export default AddPopup;
|
|
|
@ -3,13 +3,12 @@ import PropTypes from 'prop-types';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Button, Form, Icon } from 'semantic-ui-react';
|
import { Button, Form, Icon } from 'semantic-ui-react';
|
||||||
import { useDidUpdate, useToggle } from '../../../lib/hooks';
|
import { useDidUpdate, useToggle } from '../../../lib/hooks';
|
||||||
import { withPopup } from '../../../lib/popup';
|
|
||||||
import { Input, Popup } from '../../../lib/custom-ui';
|
import { Input, Popup } from '../../../lib/custom-ui';
|
||||||
|
|
||||||
import { useForm, useSteps } from '../../../hooks';
|
import { useForm, useSteps } from '../../../hooks';
|
||||||
import ImportStep from './ImportStep';
|
import ImportStep from './ImportStep';
|
||||||
|
|
||||||
import styles from './AddPopup.module.scss';
|
import styles from './AddStep.module.scss';
|
||||||
|
|
||||||
const StepTypes = {
|
const StepTypes = {
|
||||||
IMPORT: 'IMPORT',
|
IMPORT: 'IMPORT',
|
||||||
|
@ -114,4 +113,4 @@ AddStep.propTypes = {
|
||||||
onClose: PropTypes.func.isRequired,
|
onClose: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withPopup(AddStep);
|
export default AddStep;
|
3
client/src/components/Boards/AddStep/index.js
Normal file
3
client/src/components/Boards/AddStep/index.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import AddStep from './AddStep';
|
||||||
|
|
||||||
|
export default AddStep;
|
|
@ -5,12 +5,12 @@ import classNames from 'classnames';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd';
|
import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd';
|
||||||
import { Button, Icon } from 'semantic-ui-react';
|
import { Button, Icon } from 'semantic-ui-react';
|
||||||
import { closePopup } from '../../lib/popup';
|
import { closePopup, usePopup } from '../../lib/popup';
|
||||||
|
|
||||||
import Paths from '../../constants/Paths';
|
import Paths from '../../constants/Paths';
|
||||||
import DroppableTypes from '../../constants/DroppableTypes';
|
import DroppableTypes from '../../constants/DroppableTypes';
|
||||||
import AddPopup from './AddPopup';
|
import AddStep from './AddStep';
|
||||||
import EditPopup from './EditPopup';
|
import EditStep from './EditStep';
|
||||||
|
|
||||||
import styles from './Boards.module.scss';
|
import styles from './Boards.module.scss';
|
||||||
|
|
||||||
|
@ -52,6 +52,9 @@ const Boards = React.memo(({ items, currentId, canEdit, onCreate, onUpdate, onMo
|
||||||
[onDelete],
|
[onDelete],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const AddPopup = usePopup(AddStep);
|
||||||
|
const EditPopup = usePopup(EditStep);
|
||||||
|
|
||||||
const itemsNode = items.map((item, index) => (
|
const itemsNode = items.map((item, index) => (
|
||||||
<Draggable
|
<Draggable
|
||||||
key={item.id}
|
key={item.id}
|
||||||
|
|
|
@ -3,13 +3,12 @@ import React, { useCallback, useEffect, useRef } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Button, Form } from 'semantic-ui-react';
|
import { Button, Form } from 'semantic-ui-react';
|
||||||
import { withPopup } from '../../lib/popup';
|
|
||||||
import { Input, Popup } from '../../lib/custom-ui';
|
import { Input, Popup } from '../../lib/custom-ui';
|
||||||
|
|
||||||
import { useForm, useSteps } from '../../hooks';
|
import { useForm, useSteps } from '../../hooks';
|
||||||
import DeleteStep from '../DeleteStep';
|
import DeleteStep from '../DeleteStep';
|
||||||
|
|
||||||
import styles from './EditPopup.module.scss';
|
import styles from './EditStep.module.scss';
|
||||||
|
|
||||||
const StepTypes = {
|
const StepTypes = {
|
||||||
DELETE: 'DELETE',
|
DELETE: 'DELETE',
|
||||||
|
@ -56,11 +55,9 @@ const EditStep = React.memo(({ defaultData, onUpdate, onDelete, onClose }) => {
|
||||||
if (step && step.type === StepTypes.DELETE) {
|
if (step && step.type === StepTypes.DELETE) {
|
||||||
return (
|
return (
|
||||||
<DeleteStep
|
<DeleteStep
|
||||||
title={t('common.deleteBoard', {
|
title="common.deleteBoard"
|
||||||
context: 'title',
|
content="common.areYouSureYouWantToDeleteThisBoard"
|
||||||
})}
|
buttonContent="action.deleteBoard"
|
||||||
content={t('common.areYouSureYouWantToDeleteThisBoard')}
|
|
||||||
buttonContent={t('action.deleteBoard')}
|
|
||||||
onConfirm={onDelete}
|
onConfirm={onDelete}
|
||||||
onBack={handleBack}
|
onBack={handleBack}
|
||||||
/>
|
/>
|
||||||
|
@ -104,4 +101,4 @@ EditStep.propTypes = {
|
||||||
onClose: PropTypes.func.isRequired,
|
onClose: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withPopup(EditStep);
|
export default EditStep;
|
|
@ -3,7 +3,6 @@ import React, { useCallback } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Menu } from 'semantic-ui-react';
|
import { Menu } from 'semantic-ui-react';
|
||||||
import { withPopup } from '../../lib/popup';
|
|
||||||
import { Popup } from '../../lib/custom-ui';
|
import { Popup } from '../../lib/custom-ui';
|
||||||
|
|
||||||
import { useSteps } from '../../hooks';
|
import { useSteps } from '../../hooks';
|
||||||
|
@ -14,7 +13,7 @@ import TimerEditStep from '../TimerEditStep';
|
||||||
import CardMoveStep from '../CardMoveStep';
|
import CardMoveStep from '../CardMoveStep';
|
||||||
import DeleteStep from '../DeleteStep';
|
import DeleteStep from '../DeleteStep';
|
||||||
|
|
||||||
import styles from './ActionsPopup.module.scss';
|
import styles from './ActionsStep.module.scss';
|
||||||
|
|
||||||
const StepTypes = {
|
const StepTypes = {
|
||||||
USERS: 'USERS',
|
USERS: 'USERS',
|
||||||
|
@ -158,11 +157,9 @@ const ActionsStep = React.memo(
|
||||||
case StepTypes.DELETE:
|
case StepTypes.DELETE:
|
||||||
return (
|
return (
|
||||||
<DeleteStep
|
<DeleteStep
|
||||||
title={t('common.deleteCard', {
|
title="common.deleteCard"
|
||||||
context: 'title',
|
content="common.areYouSureYouWantToDeleteThisCard"
|
||||||
})}
|
buttonContent="action.deleteCard"
|
||||||
content={t('common.areYouSureYouWantToDeleteThisCard')}
|
|
||||||
buttonContent={t('action.deleteCard')}
|
|
||||||
onConfirm={onDelete}
|
onConfirm={onDelete}
|
||||||
onBack={handleBack}
|
onBack={handleBack}
|
||||||
/>
|
/>
|
||||||
|
@ -248,4 +245,4 @@ ActionsStep.propTypes = {
|
||||||
onClose: PropTypes.func.isRequired,
|
onClose: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withPopup(ActionsStep);
|
export default ActionsStep;
|
|
@ -4,12 +4,13 @@ import classNames from 'classnames';
|
||||||
import { Button, Icon } from 'semantic-ui-react';
|
import { Button, Icon } from 'semantic-ui-react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Draggable } from 'react-beautiful-dnd';
|
import { Draggable } from 'react-beautiful-dnd';
|
||||||
|
import { usePopup } from '../../lib/popup';
|
||||||
|
|
||||||
import { startTimer, stopTimer } from '../../utils/timer';
|
import { startTimer, stopTimer } from '../../utils/timer';
|
||||||
import Paths from '../../constants/Paths';
|
import Paths from '../../constants/Paths';
|
||||||
import Tasks from './Tasks';
|
import Tasks from './Tasks';
|
||||||
import NameEdit from './NameEdit';
|
import NameEdit from './NameEdit';
|
||||||
import ActionsPopup from './ActionsPopup';
|
import ActionsStep from './ActionsStep';
|
||||||
import User from '../User';
|
import User from '../User';
|
||||||
import Label from '../Label';
|
import Label from '../Label';
|
||||||
import DueDate from '../DueDate';
|
import DueDate from '../DueDate';
|
||||||
|
@ -83,6 +84,8 @@ const Card = React.memo(
|
||||||
nameEdit.current.open();
|
nameEdit.current.open();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const ActionsPopup = usePopup(ActionsStep);
|
||||||
|
|
||||||
const contentNode = (
|
const contentNode = (
|
||||||
<>
|
<>
|
||||||
{coverUrl && <img src={coverUrl} alt="" className={styles.cover} />}
|
{coverUrl && <img src={coverUrl} alt="" className={styles.cover} />}
|
||||||
|
|
|
@ -3,11 +3,12 @@ import PropTypes from 'prop-types';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Comment } from 'semantic-ui-react';
|
import { Comment } from 'semantic-ui-react';
|
||||||
|
import { usePopup } from '../../../lib/popup';
|
||||||
import { Markdown } from '../../../lib/custom-ui';
|
import { Markdown } from '../../../lib/custom-ui';
|
||||||
|
|
||||||
import CommentEdit from './CommentEdit';
|
import CommentEdit from './CommentEdit';
|
||||||
import User from '../../User';
|
import User from '../../User';
|
||||||
import DeletePopup from '../../DeletePopup';
|
import DeleteStep from '../../DeleteStep';
|
||||||
|
|
||||||
import styles from './ItemComment.module.scss';
|
import styles from './ItemComment.module.scss';
|
||||||
|
|
||||||
|
@ -21,6 +22,8 @@ const ItemComment = React.memo(
|
||||||
commentEdit.current.open();
|
commentEdit.current.open();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const DeletePopup = usePopup(DeleteStep);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Comment>
|
<Comment>
|
||||||
<span className={styles.user}>
|
<span className={styles.user}>
|
||||||
|
@ -50,11 +53,9 @@ const ItemComment = React.memo(
|
||||||
onClick={handleEditClick}
|
onClick={handleEditClick}
|
||||||
/>
|
/>
|
||||||
<DeletePopup
|
<DeletePopup
|
||||||
title={t('common.deleteComment', {
|
title="common.deleteComment"
|
||||||
context: 'title',
|
content="common.areYouSureYouWantToDeleteThisComment"
|
||||||
})}
|
buttonContent="action.deleteComment"
|
||||||
content={t('common.areYouSureYouWantToDeleteThisComment')}
|
|
||||||
buttonContent={t('action.deleteComment')}
|
|
||||||
onConfirm={onDelete}
|
onConfirm={onDelete}
|
||||||
>
|
>
|
||||||
<Comment.Action
|
<Comment.Action
|
||||||
|
|
|
@ -2,10 +2,9 @@ import React, { useCallback } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Menu } from 'semantic-ui-react';
|
import { Menu } from 'semantic-ui-react';
|
||||||
import { withPopup } from '../../lib/popup';
|
|
||||||
import { FilePicker, Popup } from '../../lib/custom-ui';
|
import { FilePicker, Popup } from '../../lib/custom-ui';
|
||||||
|
|
||||||
import styles from './AttachmentAddPopup.module.scss';
|
import styles from './AttachmentAddStep.module.scss';
|
||||||
|
|
||||||
const AttachmentAddStep = React.memo(({ onCreate, onClose }) => {
|
const AttachmentAddStep = React.memo(({ onCreate, onClose }) => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
@ -51,4 +50,4 @@ AttachmentAddStep.propTypes = {
|
||||||
onClose: PropTypes.func.isRequired,
|
onClose: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withPopup(AttachmentAddStep);
|
export default AttachmentAddStep;
|
|
@ -3,13 +3,12 @@ import React, { useCallback, useEffect, useRef } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Button, Form } from 'semantic-ui-react';
|
import { Button, Form } from 'semantic-ui-react';
|
||||||
import { withPopup } from '../../../lib/popup';
|
|
||||||
import { Input, Popup } from '../../../lib/custom-ui';
|
import { Input, Popup } from '../../../lib/custom-ui';
|
||||||
|
|
||||||
import { useForm, useSteps } from '../../../hooks';
|
import { useForm, useSteps } from '../../../hooks';
|
||||||
import DeleteStep from '../../DeleteStep';
|
import DeleteStep from '../../DeleteStep';
|
||||||
|
|
||||||
import styles from './EditPopup.module.scss';
|
import styles from './EditStep.module.scss';
|
||||||
|
|
||||||
const StepTypes = {
|
const StepTypes = {
|
||||||
DELETE: 'DELETE',
|
DELETE: 'DELETE',
|
||||||
|
@ -56,11 +55,9 @@ const EditStep = React.memo(({ defaultData, onUpdate, onDelete, onClose }) => {
|
||||||
if (step && step.type === StepTypes.DELETE) {
|
if (step && step.type === StepTypes.DELETE) {
|
||||||
return (
|
return (
|
||||||
<DeleteStep
|
<DeleteStep
|
||||||
title={t('common.deleteAttachment', {
|
title="common.deleteAttachment"
|
||||||
context: 'title',
|
content="common.areYouSureYouWantToDeleteThisAttachment"
|
||||||
})}
|
buttonContent="action.deleteAttachment"
|
||||||
content={t('common.areYouSureYouWantToDeleteThisAttachment')}
|
|
||||||
buttonContent={t('action.deleteAttachment')}
|
|
||||||
onConfirm={onDelete}
|
onConfirm={onDelete}
|
||||||
onBack={handleBack}
|
onBack={handleBack}
|
||||||
/>
|
/>
|
||||||
|
@ -104,4 +101,4 @@ EditStep.propTypes = {
|
||||||
onClose: PropTypes.func.isRequired,
|
onClose: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withPopup(EditStep);
|
export default EditStep;
|
|
@ -3,8 +3,9 @@ import PropTypes from 'prop-types';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Button, Icon, Label, Loader } from 'semantic-ui-react';
|
import { Button, Icon, Label, Loader } from 'semantic-ui-react';
|
||||||
|
import { usePopup } from '../../../lib/popup';
|
||||||
|
|
||||||
import EditPopup from './EditPopup';
|
import EditStep from './EditStep';
|
||||||
|
|
||||||
import styles from './Item.module.scss';
|
import styles from './Item.module.scss';
|
||||||
|
|
||||||
|
@ -49,6 +50,8 @@ const Item = React.forwardRef(
|
||||||
[isCover, onCoverSelect, onCoverDeselect],
|
[isCover, onCoverSelect, onCoverDeselect],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const EditPopup = usePopup(EditStep);
|
||||||
|
|
||||||
if (!isPersisted) {
|
if (!isPersisted) {
|
||||||
return (
|
return (
|
||||||
<div className={classNames(styles.wrapper, styles.wrapperSubmitting)}>
|
<div className={classNames(styles.wrapper, styles.wrapperSubmitting)}>
|
||||||
|
|
|
@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Button, Grid, Icon, Modal } from 'semantic-ui-react';
|
import { Button, Grid, Icon, Modal } from 'semantic-ui-react';
|
||||||
|
import { usePopup } from '../../lib/popup';
|
||||||
import { Markdown } from '../../lib/custom-ui';
|
import { Markdown } from '../../lib/custom-ui';
|
||||||
|
|
||||||
import { startTimer, stopTimer } from '../../utils/timer';
|
import { startTimer, stopTimer } from '../../utils/timer';
|
||||||
|
@ -11,18 +12,18 @@ import DescriptionEdit from './DescriptionEdit';
|
||||||
import Tasks from './Tasks';
|
import Tasks from './Tasks';
|
||||||
import Attachments from './Attachments';
|
import Attachments from './Attachments';
|
||||||
import AttachmentAddZone from './AttachmentAddZone';
|
import AttachmentAddZone from './AttachmentAddZone';
|
||||||
import AttachmentAddPopup from './AttachmentAddPopup';
|
import AttachmentAddStep from './AttachmentAddStep';
|
||||||
import Activities from './Activities';
|
import Activities from './Activities';
|
||||||
import User from '../User';
|
import User from '../User';
|
||||||
import Label from '../Label';
|
import Label from '../Label';
|
||||||
import DueDate from '../DueDate';
|
import DueDate from '../DueDate';
|
||||||
import Timer from '../Timer';
|
import Timer from '../Timer';
|
||||||
import BoardMembershipsPopup from '../BoardMembershipsPopup';
|
import BoardMembershipsStep from '../BoardMembershipsStep';
|
||||||
import LabelsPopup from '../LabelsPopup';
|
import LabelsStep from '../LabelsStep';
|
||||||
import DueDateEditPopup from '../DueDateEditPopup';
|
import DueDateEditStep from '../DueDateEditStep';
|
||||||
import TimerEditPopup from '../TimerEditPopup';
|
import TimerEditStep from '../TimerEditStep';
|
||||||
import CardMovePopup from '../CardMovePopup';
|
import CardMoveStep from '../CardMoveStep';
|
||||||
import DeletePopup from '../DeletePopup';
|
import DeleteStep from '../DeleteStep';
|
||||||
|
|
||||||
import styles from './CardModal.module.scss';
|
import styles from './CardModal.module.scss';
|
||||||
|
|
||||||
|
@ -155,6 +156,14 @@ const CardModal = React.memo(
|
||||||
onClose();
|
onClose();
|
||||||
}, [onClose]);
|
}, [onClose]);
|
||||||
|
|
||||||
|
const AttachmentAddPopup = usePopup(AttachmentAddStep);
|
||||||
|
const BoardMembershipsPopup = usePopup(BoardMembershipsStep);
|
||||||
|
const LabelsPopup = usePopup(LabelsStep);
|
||||||
|
const DueDateEditPopup = usePopup(DueDateEditStep);
|
||||||
|
const TimerEditPopup = usePopup(TimerEditStep);
|
||||||
|
const CardMovePopup = usePopup(CardMoveStep);
|
||||||
|
const DeletePopup = usePopup(DeleteStep);
|
||||||
|
|
||||||
const userIds = users.map((user) => user.id);
|
const userIds = users.map((user) => user.id);
|
||||||
const labelIds = labels.map((label) => label.id);
|
const labelIds = labels.map((label) => label.id);
|
||||||
|
|
||||||
|
@ -482,11 +491,9 @@ const CardModal = React.memo(
|
||||||
</Button>
|
</Button>
|
||||||
</CardMovePopup>
|
</CardMovePopup>
|
||||||
<DeletePopup
|
<DeletePopup
|
||||||
title={t('common.deleteCard', {
|
title="common.deleteCard"
|
||||||
context: 'title',
|
content="common.areYouSureYouWantToDeleteThisCard"
|
||||||
})}
|
buttonContent="action.deleteCard"
|
||||||
content={t('common.areYouSureYouWantToDeleteThisCard')}
|
|
||||||
buttonContent={t('action.deleteCard')}
|
|
||||||
onConfirm={onDelete}
|
onConfirm={onDelete}
|
||||||
>
|
>
|
||||||
<Button fluid className={styles.actionButton}>
|
<Button fluid className={styles.actionButton}>
|
||||||
|
|
|
@ -2,13 +2,12 @@ import React, { useCallback } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Menu } from 'semantic-ui-react';
|
import { Menu } from 'semantic-ui-react';
|
||||||
import { withPopup } from '../../../lib/popup';
|
|
||||||
import { Popup } from '../../../lib/custom-ui';
|
import { Popup } from '../../../lib/custom-ui';
|
||||||
|
|
||||||
import { useSteps } from '../../../hooks';
|
import { useSteps } from '../../../hooks';
|
||||||
import DeleteStep from '../../DeleteStep';
|
import DeleteStep from '../../DeleteStep';
|
||||||
|
|
||||||
import styles from './ActionsPopup.module.scss';
|
import styles from './ActionsStep.module.scss';
|
||||||
|
|
||||||
const StepTypes = {
|
const StepTypes = {
|
||||||
DELETE: 'DELETE',
|
DELETE: 'DELETE',
|
||||||
|
@ -30,11 +29,9 @@ const ActionsStep = React.memo(({ onNameEdit, onDelete, onClose }) => {
|
||||||
if (step && step.type === StepTypes.DELETE) {
|
if (step && step.type === StepTypes.DELETE) {
|
||||||
return (
|
return (
|
||||||
<DeleteStep
|
<DeleteStep
|
||||||
title={t('common.deleteTask', {
|
title="common.deleteTask"
|
||||||
context: 'title',
|
content="common.areYouSureYouWantToDeleteThisTask"
|
||||||
})}
|
buttonContent="action.deleteTask"
|
||||||
content={t('common.areYouSureYouWantToDeleteThisTask')}
|
|
||||||
buttonContent={t('action.deleteTask')}
|
|
||||||
onConfirm={onDelete}
|
onConfirm={onDelete}
|
||||||
onBack={handleBack}
|
onBack={handleBack}
|
||||||
/>
|
/>
|
||||||
|
@ -72,4 +69,4 @@ ActionsStep.propTypes = {
|
||||||
onClose: PropTypes.func.isRequired,
|
onClose: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withPopup(ActionsStep);
|
export default ActionsStep;
|
|
@ -4,9 +4,10 @@ import PropTypes from 'prop-types';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Draggable } from 'react-beautiful-dnd';
|
import { Draggable } from 'react-beautiful-dnd';
|
||||||
import { Button, Checkbox, Icon } from 'semantic-ui-react';
|
import { Button, Checkbox, Icon } from 'semantic-ui-react';
|
||||||
|
import { usePopup } from '../../../lib/popup';
|
||||||
|
|
||||||
import NameEdit from './NameEdit';
|
import NameEdit from './NameEdit';
|
||||||
import ActionsPopup from './ActionsPopup';
|
import ActionsStep from './ActionsStep';
|
||||||
|
|
||||||
import styles from './Item.module.scss';
|
import styles from './Item.module.scss';
|
||||||
|
|
||||||
|
@ -39,6 +40,8 @@ const Item = React.memo(
|
||||||
nameEdit.current.open();
|
nameEdit.current.open();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const ActionsPopup = usePopup(ActionsStep);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Draggable draggableId={id} index={index} isDragDisabled={!isPersisted || !canEdit}>
|
<Draggable draggableId={id} index={index} isDragDisabled={!isPersisted || !canEdit}>
|
||||||
{({ innerRef, draggableProps, dragHandleProps }, { isDragging }) => {
|
{({ innerRef, draggableProps, dragHandleProps }, { isDragging }) => {
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
import { withPopup } from '../lib/popup';
|
|
||||||
|
|
||||||
import CardMoveStep from './CardMoveStep';
|
|
||||||
|
|
||||||
export default withPopup(CardMoveStep);
|
|
|
@ -1,5 +0,0 @@
|
||||||
import { withPopup } from '../lib/popup';
|
|
||||||
|
|
||||||
import DeleteStep from './DeleteStep';
|
|
||||||
|
|
||||||
export default withPopup(DeleteStep);
|
|
|
@ -1,19 +1,28 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Button } from 'semantic-ui-react';
|
import { Button } from 'semantic-ui-react';
|
||||||
import { Popup } from '../../lib/custom-ui';
|
import { Popup } from '../../lib/custom-ui';
|
||||||
|
|
||||||
import styles from './DeleteStep.module.scss';
|
import styles from './DeleteStep.module.scss';
|
||||||
|
|
||||||
const DeleteStep = React.memo(({ title, content, buttonContent, onConfirm, onBack }) => (
|
const DeleteStep = React.memo(({ title, content, buttonContent, onConfirm, onBack }) => {
|
||||||
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
<>
|
<>
|
||||||
<Popup.Header onBack={onBack}>{title}</Popup.Header>
|
<Popup.Header onBack={onBack}>
|
||||||
|
{t(title, {
|
||||||
|
context: 'title',
|
||||||
|
})}
|
||||||
|
</Popup.Header>
|
||||||
<Popup.Content>
|
<Popup.Content>
|
||||||
<div className={styles.content}>{content}</div>
|
<div className={styles.content}>{t(content)}</div>
|
||||||
<Button fluid negative content={buttonContent} onClick={onConfirm} />
|
<Button fluid negative content={t(buttonContent)} onClick={onConfirm} />
|
||||||
</Popup.Content>
|
</Popup.Content>
|
||||||
</>
|
</>
|
||||||
));
|
);
|
||||||
|
});
|
||||||
|
|
||||||
DeleteStep.propTypes = {
|
DeleteStep.propTypes = {
|
||||||
title: PropTypes.string.isRequired,
|
title: PropTypes.string.isRequired,
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
import { withPopup } from '../lib/popup';
|
|
||||||
|
|
||||||
import DueDateEditStep from './DueDateEditStep';
|
|
||||||
|
|
||||||
export default withPopup(DueDateEditStep);
|
|
|
@ -3,13 +3,18 @@ import PropTypes from 'prop-types';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Icon, Menu } from 'semantic-ui-react';
|
import { Icon, Menu } from 'semantic-ui-react';
|
||||||
|
import { usePopup } from '../../lib/popup';
|
||||||
|
|
||||||
import Paths from '../../constants/Paths';
|
import Paths from '../../constants/Paths';
|
||||||
import NotificationsPopup from './NotificationsPopup';
|
import NotificationsStep from './NotificationsStep';
|
||||||
import UserPopup from '../UserPopup';
|
import UserStep from '../UserStep';
|
||||||
|
|
||||||
import styles from './Header.module.scss';
|
import styles from './Header.module.scss';
|
||||||
|
|
||||||
|
const POPUP_PROPS = {
|
||||||
|
position: 'bottom right',
|
||||||
|
};
|
||||||
|
|
||||||
const Header = React.memo(
|
const Header = React.memo(
|
||||||
({
|
({
|
||||||
project,
|
project,
|
||||||
|
@ -30,6 +35,9 @@ const Header = React.memo(
|
||||||
}
|
}
|
||||||
}, [canEditProject, onProjectSettingsClick]);
|
}, [canEditProject, onProjectSettingsClick]);
|
||||||
|
|
||||||
|
const NotificationsPopup = usePopup(NotificationsStep, POPUP_PROPS);
|
||||||
|
const UserPopup = usePopup(UserStep, POPUP_PROPS);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.wrapper}>
|
<div className={styles.wrapper}>
|
||||||
{!project && (
|
{!project && (
|
||||||
|
|
|
@ -4,14 +4,13 @@ import PropTypes from 'prop-types';
|
||||||
import { useTranslation, Trans } from 'react-i18next';
|
import { useTranslation, Trans } from 'react-i18next';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Button } from 'semantic-ui-react';
|
import { Button } from 'semantic-ui-react';
|
||||||
import { withPopup } from '../../lib/popup';
|
|
||||||
import { Popup } from '../../lib/custom-ui';
|
import { Popup } from '../../lib/custom-ui';
|
||||||
|
|
||||||
import Paths from '../../constants/Paths';
|
import Paths from '../../constants/Paths';
|
||||||
import { ActivityTypes } from '../../constants/Enums';
|
import { ActivityTypes } from '../../constants/Enums';
|
||||||
import User from '../User';
|
import User from '../User';
|
||||||
|
|
||||||
import styles from './NotificationsPopup.module.scss';
|
import styles from './NotificationsStep.module.scss';
|
||||||
|
|
||||||
const NotificationsStep = React.memo(({ items, onDelete, onClose }) => {
|
const NotificationsStep = React.memo(({ items, onDelete, onClose }) => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
@ -123,6 +122,4 @@ NotificationsStep.propTypes = {
|
||||||
onClose: PropTypes.func.isRequired,
|
onClose: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withPopup(NotificationsStep, {
|
export default NotificationsStep;
|
||||||
position: 'bottom right',
|
|
||||||
});
|
|
|
@ -1,5 +0,0 @@
|
||||||
import { withPopup } from '../lib/popup';
|
|
||||||
|
|
||||||
import LabelsStep from './LabelsStep';
|
|
||||||
|
|
||||||
export default withPopup(LabelsStep);
|
|
|
@ -47,11 +47,9 @@ const EditStep = React.memo(({ defaultData, onUpdate, onDelete, onBack }) => {
|
||||||
if (step && step.type === StepTypes.DELETE) {
|
if (step && step.type === StepTypes.DELETE) {
|
||||||
return (
|
return (
|
||||||
<DeleteStep
|
<DeleteStep
|
||||||
title={t('common.deleteLabel', {
|
title="common.deleteLabel"
|
||||||
context: 'title',
|
content="common.areYouSureYouWantToDeleteThisLabel"
|
||||||
})}
|
buttonContent="action.deleteLabel"
|
||||||
content={t('common.areYouSureYouWantToDeleteThisLabel')}
|
|
||||||
buttonContent={t('action.deleteLabel')}
|
|
||||||
onConfirm={onDelete}
|
onConfirm={onDelete}
|
||||||
onBack={handleBack}
|
onBack={handleBack}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -2,13 +2,12 @@ import React, { useCallback } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Menu } from 'semantic-ui-react';
|
import { Menu } from 'semantic-ui-react';
|
||||||
import { withPopup } from '../../lib/popup';
|
|
||||||
import { Popup } from '../../lib/custom-ui';
|
import { Popup } from '../../lib/custom-ui';
|
||||||
|
|
||||||
import { useSteps } from '../../hooks';
|
import { useSteps } from '../../hooks';
|
||||||
import DeleteStep from '../DeleteStep';
|
import DeleteStep from '../DeleteStep';
|
||||||
|
|
||||||
import styles from './ActionsPopup.module.scss';
|
import styles from './ActionsStep.module.scss';
|
||||||
|
|
||||||
const StepTypes = {
|
const StepTypes = {
|
||||||
DELETE: 'DELETE',
|
DELETE: 'DELETE',
|
||||||
|
@ -35,11 +34,9 @@ const ActionsStep = React.memo(({ onNameEdit, onCardAdd, onDelete, onClose }) =>
|
||||||
if (step && step.type === StepTypes.DELETE) {
|
if (step && step.type === StepTypes.DELETE) {
|
||||||
return (
|
return (
|
||||||
<DeleteStep
|
<DeleteStep
|
||||||
title={t('common.deleteList', {
|
title="common.deleteList"
|
||||||
context: 'title',
|
content="common.areYouSureYouWantToDeleteThisList"
|
||||||
})}
|
buttonContent="action.deleteList"
|
||||||
content={t('common.areYouSureYouWantToDeleteThisList')}
|
|
||||||
buttonContent={t('action.deleteList')}
|
|
||||||
onConfirm={onDelete}
|
onConfirm={onDelete}
|
||||||
onBack={handleBack}
|
onBack={handleBack}
|
||||||
/>
|
/>
|
||||||
|
@ -83,4 +80,4 @@ ActionsStep.propTypes = {
|
||||||
onClose: PropTypes.func.isRequired,
|
onClose: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withPopup(ActionsStep);
|
export default ActionsStep;
|
|
@ -4,12 +4,13 @@ import classNames from 'classnames';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Draggable, Droppable } from 'react-beautiful-dnd';
|
import { Draggable, Droppable } from 'react-beautiful-dnd';
|
||||||
import { Button, Icon } from 'semantic-ui-react';
|
import { Button, Icon } from 'semantic-ui-react';
|
||||||
|
import { usePopup } from '../../lib/popup';
|
||||||
|
|
||||||
import DroppableTypes from '../../constants/DroppableTypes';
|
import DroppableTypes from '../../constants/DroppableTypes';
|
||||||
import CardContainer from '../../containers/CardContainer';
|
import CardContainer from '../../containers/CardContainer';
|
||||||
import NameEdit from './NameEdit';
|
import NameEdit from './NameEdit';
|
||||||
import CardAdd from './CardAdd';
|
import CardAdd from './CardAdd';
|
||||||
import ActionsPopup from './ActionsPopup';
|
import ActionsStep from './ActionsStep';
|
||||||
import { ReactComponent as PlusMathIcon } from '../../assets/images/plus-math-icon.svg';
|
import { ReactComponent as PlusMathIcon } from '../../assets/images/plus-math-icon.svg';
|
||||||
|
|
||||||
import styles from './List.module.scss';
|
import styles from './List.module.scss';
|
||||||
|
@ -59,6 +60,8 @@ const List = React.memo(
|
||||||
}
|
}
|
||||||
}, [cardIds, isAddCardOpened]);
|
}, [cardIds, isAddCardOpened]);
|
||||||
|
|
||||||
|
const ActionsPopup = usePopup(ActionsStep);
|
||||||
|
|
||||||
const cardsNode = (
|
const cardsNode = (
|
||||||
<Droppable
|
<Droppable
|
||||||
droppableId={`list:${id}`}
|
droppableId={`list:${id}`}
|
||||||
|
|
|
@ -3,13 +3,12 @@ import React, { useCallback } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Button } from 'semantic-ui-react';
|
import { Button } from 'semantic-ui-react';
|
||||||
import { withPopup } from '../../lib/popup';
|
|
||||||
|
|
||||||
import { useSteps } from '../../hooks';
|
import { useSteps } from '../../hooks';
|
||||||
import User from '../User';
|
import User from '../User';
|
||||||
import DeleteStep from '../DeleteStep';
|
import DeleteStep from '../DeleteStep';
|
||||||
|
|
||||||
import styles from './ActionsPopup.module.scss';
|
import styles from './ActionsStep.module.scss';
|
||||||
|
|
||||||
const StepTypes = {
|
const StepTypes = {
|
||||||
EDIT_PERMISSIONS: 'EDIT_PERMISSIONS',
|
EDIT_PERMISSIONS: 'EDIT_PERMISSIONS',
|
||||||
|
@ -73,20 +72,15 @@ const ActionsStep = React.memo(
|
||||||
case StepTypes.DELETE:
|
case StepTypes.DELETE:
|
||||||
return (
|
return (
|
||||||
<DeleteStep
|
<DeleteStep
|
||||||
title={t(
|
title={membership.user.isCurrent ? leaveConfirmationTitle : deleteConfirmationTitle}
|
||||||
membership.user.isCurrent ? leaveConfirmationTitle : deleteConfirmationTitle,
|
content={
|
||||||
{
|
membership.user.isCurrent ? leaveConfirmationContent : deleteConfirmationContent
|
||||||
context: 'title',
|
}
|
||||||
},
|
buttonContent={
|
||||||
)}
|
|
||||||
content={t(
|
|
||||||
membership.user.isCurrent ? leaveConfirmationContent : deleteConfirmationContent,
|
|
||||||
)}
|
|
||||||
buttonContent={t(
|
|
||||||
membership.user.isCurrent
|
membership.user.isCurrent
|
||||||
? leaveConfirmationButtonContent
|
? leaveConfirmationButtonContent
|
||||||
: deleteConfirmationButtonContent,
|
: deleteConfirmationButtonContent
|
||||||
)}
|
}
|
||||||
onConfirm={onDelete}
|
onConfirm={onDelete}
|
||||||
onBack={handleBack}
|
onBack={handleBack}
|
||||||
/>
|
/>
|
||||||
|
@ -165,4 +159,4 @@ ActionsStep.defaultProps = {
|
||||||
onUpdate: undefined,
|
onUpdate: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withPopup(ActionsStep);
|
export default ActionsStep;
|
|
@ -1,3 +0,0 @@
|
||||||
import AddPopup from './AddPopup';
|
|
||||||
|
|
||||||
export default AddPopup;
|
|
|
@ -1,13 +1,12 @@
|
||||||
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
|
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { withPopup } from '../../../lib/popup';
|
|
||||||
import { Input, Popup } from '../../../lib/custom-ui';
|
import { Input, Popup } from '../../../lib/custom-ui';
|
||||||
|
|
||||||
import { useField, useSteps } from '../../../hooks';
|
import { useField, useSteps } from '../../../hooks';
|
||||||
import UserItem from './UserItem';
|
import UserItem from './UserItem';
|
||||||
|
|
||||||
import styles from './AddPopup.module.scss';
|
import styles from './AddStep.module.scss';
|
||||||
|
|
||||||
const StepTypes = {
|
const StepTypes = {
|
||||||
SELECT_PERMISSIONS: 'SELECT_PERMISSIONS',
|
SELECT_PERMISSIONS: 'SELECT_PERMISSIONS',
|
||||||
|
@ -143,4 +142,4 @@ AddStep.defaultProps = {
|
||||||
title: 'common.addMember',
|
title: 'common.addMember',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withPopup(AddStep);
|
export default AddStep;
|
3
client/src/components/Memberships/AddStep/index.js
Normal file
3
client/src/components/Memberships/AddStep/index.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import AddStep from './AddStep';
|
||||||
|
|
||||||
|
export default AddStep;
|
|
@ -1,9 +1,10 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Button } from 'semantic-ui-react';
|
import { Button } from 'semantic-ui-react';
|
||||||
|
import { usePopup } from '../../lib/popup';
|
||||||
|
|
||||||
import AddPopup from './AddPopup';
|
import AddStep from './AddStep';
|
||||||
import ActionsPopup from './ActionsPopup';
|
import ActionsStep from './ActionsStep';
|
||||||
import User from '../User';
|
import User from '../User';
|
||||||
|
|
||||||
import styles from './Memberships.module.scss';
|
import styles from './Memberships.module.scss';
|
||||||
|
@ -28,6 +29,9 @@ const Memberships = React.memo(
|
||||||
onUpdate,
|
onUpdate,
|
||||||
onDelete,
|
onDelete,
|
||||||
}) => {
|
}) => {
|
||||||
|
const AddPopup = usePopup(AddStep);
|
||||||
|
const ActionsPopup = usePopup(ActionsStep);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<span className={styles.users}>
|
<span className={styles.users}>
|
||||||
|
|
|
@ -2,15 +2,18 @@ import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Button, Divider, Header, Tab } from 'semantic-ui-react';
|
import { Button, Divider, Header, Tab } from 'semantic-ui-react';
|
||||||
|
import { usePopup } from '../../../lib/popup';
|
||||||
|
|
||||||
import InformationEdit from './InformationEdit';
|
import InformationEdit from './InformationEdit';
|
||||||
import DeletePopup from '../../DeletePopup';
|
import DeleteStep from '../../DeleteStep';
|
||||||
|
|
||||||
import styles from './GeneralPane.module.scss';
|
import styles from './GeneralPane.module.scss';
|
||||||
|
|
||||||
const GeneralPane = React.memo(({ name, onUpdate, onDelete }) => {
|
const GeneralPane = React.memo(({ name, onUpdate, onDelete }) => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
const DeletePopup = usePopup(DeleteStep);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tab.Pane attached={false} className={styles.wrapper}>
|
<Tab.Pane attached={false} className={styles.wrapper}>
|
||||||
<InformationEdit
|
<InformationEdit
|
||||||
|
@ -28,11 +31,9 @@ const GeneralPane = React.memo(({ name, onUpdate, onDelete }) => {
|
||||||
</Divider>
|
</Divider>
|
||||||
<div className={styles.action}>
|
<div className={styles.action}>
|
||||||
<DeletePopup
|
<DeletePopup
|
||||||
title={t('common.deleteProject', {
|
title="common.deleteProject"
|
||||||
context: 'title',
|
content="common.areYouSureYouWantToDeleteThisProject"
|
||||||
})}
|
buttonContent="action.deleteProject"
|
||||||
content={t('common.areYouSureYouWantToDeleteThisProject')}
|
|
||||||
buttonContent={t('action.deleteProject')}
|
|
||||||
onConfirm={onDelete}
|
onConfirm={onDelete}
|
||||||
>
|
>
|
||||||
<Button className={styles.actionButton}>
|
<Button className={styles.actionButton}>
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
import { withPopup } from '../lib/popup';
|
|
||||||
|
|
||||||
import TimerEditStep from './TimerEditStep';
|
|
||||||
|
|
||||||
export default withPopup(TimerEditStep);
|
|
|
@ -1,3 +0,0 @@
|
||||||
import UserAddPopup from './UserAddPopup';
|
|
||||||
|
|
||||||
export default UserAddPopup;
|
|
|
@ -4,13 +4,12 @@ import PropTypes from 'prop-types';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Button, Form, Message } from 'semantic-ui-react';
|
import { Button, Form, Message } from 'semantic-ui-react';
|
||||||
import { usePrevious } from '../../lib/hooks';
|
import { usePrevious } from '../../lib/hooks';
|
||||||
import { withPopup } from '../../lib/popup';
|
|
||||||
import { Input, Popup } from '../../lib/custom-ui';
|
import { Input, Popup } from '../../lib/custom-ui';
|
||||||
|
|
||||||
import { useForm } from '../../hooks';
|
import { useForm } from '../../hooks';
|
||||||
import { isPassword, isUsername } from '../../utils/validator';
|
import { isPassword, isUsername } from '../../utils/validator';
|
||||||
|
|
||||||
import styles from './UserAddPopup.module.scss';
|
import styles from './UserAddStep.module.scss';
|
||||||
|
|
||||||
const createMessage = (error) => {
|
const createMessage = (error) => {
|
||||||
if (!error) {
|
if (!error) {
|
||||||
|
@ -206,4 +205,4 @@ UserAddStep.defaultProps = {
|
||||||
error: undefined,
|
error: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withPopup(UserAddStep);
|
export default UserAddStep;
|
3
client/src/components/UserAddStep/index.js
Normal file
3
client/src/components/UserAddStep/index.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import UserAddStep from './UserAddStep';
|
||||||
|
|
||||||
|
export default UserAddStep;
|
|
@ -1,5 +0,0 @@
|
||||||
import { withPopup } from '../lib/popup';
|
|
||||||
|
|
||||||
import UserEmailEditStep from './UserEmailEditStep';
|
|
||||||
|
|
||||||
export default withPopup(UserEmailEditStep);
|
|
|
@ -1,5 +0,0 @@
|
||||||
import { withPopup } from '../lib/popup';
|
|
||||||
|
|
||||||
import UserPasswordEditStep from './UserPasswordEditStep';
|
|
||||||
|
|
||||||
export default withPopup(UserPasswordEditStep);
|
|
|
@ -1,3 +0,0 @@
|
||||||
import UserPopup from './UserPopup';
|
|
||||||
|
|
||||||
export default UserPopup;
|
|
|
@ -2,14 +2,15 @@ import React, { useCallback } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Button, Divider, Dropdown, Header, Tab } from 'semantic-ui-react';
|
import { Button, Divider, Dropdown, Header, Tab } from 'semantic-ui-react';
|
||||||
|
import { usePopup } from '../../../lib/popup';
|
||||||
|
|
||||||
import locales from '../../../locales';
|
import locales from '../../../locales';
|
||||||
import AvatarEditPopup from './AvatarEditPopup';
|
import AvatarEditStep from './AvatarEditStep';
|
||||||
import User from '../../User';
|
import User from '../../User';
|
||||||
import UserInformationEdit from '../../UserInformationEdit';
|
import UserInformationEdit from '../../UserInformationEdit';
|
||||||
import UserUsernameEditPopup from '../../UserUsernameEditPopup';
|
import UserUsernameEditStep from '../../UserUsernameEditStep';
|
||||||
import UserEmailEditPopup from '../../UserEmailEditPopup';
|
import UserEmailEditStep from '../../UserEmailEditStep';
|
||||||
import UserPasswordEditPopup from '../../UserPasswordEditPopup';
|
import UserPasswordEditStep from '../../UserPasswordEditStep';
|
||||||
|
|
||||||
import styles from './AccountPane.module.scss';
|
import styles from './AccountPane.module.scss';
|
||||||
|
|
||||||
|
@ -51,6 +52,11 @@ const AccountPane = React.memo(
|
||||||
[onLanguageUpdate],
|
[onLanguageUpdate],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const AvatarEditPopup = usePopup(AvatarEditStep);
|
||||||
|
const UserUsernameEditPopup = usePopup(UserUsernameEditStep);
|
||||||
|
const UserEmailEditPopup = usePopup(UserEmailEditStep);
|
||||||
|
const UserPasswordEditPopup = usePopup(UserPasswordEditStep);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tab.Pane attached={false} className={styles.wrapper}>
|
<Tab.Pane attached={false} className={styles.wrapper}>
|
||||||
<AvatarEditPopup
|
<AvatarEditPopup
|
||||||
|
|
|
@ -2,10 +2,9 @@ import React, { useCallback, useEffect, useRef } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Button } from 'semantic-ui-react';
|
import { Button } from 'semantic-ui-react';
|
||||||
import { withPopup } from '../../../lib/popup';
|
|
||||||
import { FilePicker, Popup } from '../../../lib/custom-ui';
|
import { FilePicker, Popup } from '../../../lib/custom-ui';
|
||||||
|
|
||||||
import styles from './AvatarEditPopup.module.scss';
|
import styles from './AvatarEditStep.module.scss';
|
||||||
|
|
||||||
const AvatarEditStep = React.memo(({ defaultValue, onUpdate, onDelete, onClose }) => {
|
const AvatarEditStep = React.memo(({ defaultValue, onUpdate, onDelete, onClose }) => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
@ -68,4 +67,4 @@ AvatarEditStep.defaultProps = {
|
||||||
defaultValue: undefined,
|
defaultValue: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withPopup(AvatarEditStep);
|
export default AvatarEditStep;
|
|
@ -2,10 +2,9 @@ import React, { useCallback } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Button, Menu } from 'semantic-ui-react';
|
import { Button, Menu } from 'semantic-ui-react';
|
||||||
import { withPopup } from '../../lib/popup';
|
|
||||||
import { Popup } from '../../lib/custom-ui';
|
import { Popup } from '../../lib/custom-ui';
|
||||||
|
|
||||||
import styles from './UserPopup.module.scss';
|
import styles from './UserStep.module.scss';
|
||||||
|
|
||||||
const UserStep = React.memo(({ isLogouting, onSettingsClick, onLogout, onClose }) => {
|
const UserStep = React.memo(({ isLogouting, onSettingsClick, onLogout, onClose }) => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
@ -62,6 +61,4 @@ UserStep.propTypes = {
|
||||||
onClose: PropTypes.func.isRequired,
|
onClose: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withPopup(UserStep, {
|
export default UserStep;
|
||||||
position: 'bottom right',
|
|
||||||
});
|
|
3
client/src/components/UserStep/index.js
Executable file
3
client/src/components/UserStep/index.js
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
import UserStep from './UserStep';
|
||||||
|
|
||||||
|
export default UserStep;
|
|
@ -1,5 +0,0 @@
|
||||||
import { withPopup } from '../lib/popup';
|
|
||||||
|
|
||||||
import UserUsernameEditStep from './UserUsernameEditStep';
|
|
||||||
|
|
||||||
export default withPopup(UserUsernameEditStep);
|
|
|
@ -3,7 +3,6 @@ import React, { useCallback } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Menu } from 'semantic-ui-react';
|
import { Menu } from 'semantic-ui-react';
|
||||||
import { withPopup } from '../../../lib/popup';
|
|
||||||
import { Popup } from '../../../lib/custom-ui';
|
import { Popup } from '../../../lib/custom-ui';
|
||||||
|
|
||||||
import { useSteps } from '../../../hooks';
|
import { useSteps } from '../../../hooks';
|
||||||
|
@ -13,7 +12,7 @@ import UserEmailEditStep from '../../UserEmailEditStep';
|
||||||
import UserPasswordEditStep from '../../UserPasswordEditStep';
|
import UserPasswordEditStep from '../../UserPasswordEditStep';
|
||||||
import DeleteStep from '../../DeleteStep';
|
import DeleteStep from '../../DeleteStep';
|
||||||
|
|
||||||
import styles from './ActionsPopup.module.scss';
|
import styles from './ActionsStep.module.scss';
|
||||||
|
|
||||||
const StepTypes = {
|
const StepTypes = {
|
||||||
EDIT_INFORMATION: 'EDIT_INFORMATION',
|
EDIT_INFORMATION: 'EDIT_INFORMATION',
|
||||||
|
@ -111,11 +110,9 @@ const ActionsStep = React.memo(
|
||||||
case StepTypes.DELETE:
|
case StepTypes.DELETE:
|
||||||
return (
|
return (
|
||||||
<DeleteStep
|
<DeleteStep
|
||||||
title={t('common.deleteUser', {
|
title="common.deleteUser"
|
||||||
context: 'title',
|
content="common.areYouSureYouWantToDeleteThisUser"
|
||||||
})}
|
buttonContent="action.deleteUser"
|
||||||
content={t('common.areYouSureYouWantToDeleteThisUser')}
|
|
||||||
buttonContent={t('action.deleteUser')}
|
|
||||||
onConfirm={onDelete}
|
onConfirm={onDelete}
|
||||||
onBack={handleBack}
|
onBack={handleBack}
|
||||||
/>
|
/>
|
||||||
|
@ -178,4 +175,4 @@ ActionsStep.propTypes = {
|
||||||
onClose: PropTypes.func.isRequired,
|
onClose: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withPopup(ActionsStep);
|
export default ActionsStep;
|
|
@ -1,8 +1,9 @@
|
||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Button, Icon, Radio, Table } from 'semantic-ui-react';
|
import { Button, Icon, Radio, Table } from 'semantic-ui-react';
|
||||||
|
import { usePopup } from '../../../lib/popup';
|
||||||
|
|
||||||
import ActionsPopup from './ActionsPopup';
|
import ActionsStep from './ActionsStep';
|
||||||
import User from '../../User';
|
import User from '../../User';
|
||||||
|
|
||||||
import styles from './Item.module.scss';
|
import styles from './Item.module.scss';
|
||||||
|
@ -34,6 +35,8 @@ const Item = React.memo(
|
||||||
});
|
});
|
||||||
}, [isAdmin, onUpdate]);
|
}, [isAdmin, onUpdate]);
|
||||||
|
|
||||||
|
const ActionsPopup = usePopup(ActionsStep);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Table.Row>
|
<Table.Row>
|
||||||
<Table.Cell>
|
<Table.Cell>
|
||||||
|
|
|
@ -2,8 +2,9 @@ import React, { useCallback } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Button, Modal, Table } from 'semantic-ui-react';
|
import { Button, Modal, Table } from 'semantic-ui-react';
|
||||||
|
import { usePopup } from '../../lib/popup';
|
||||||
|
|
||||||
import UserAddPopupContainer from '../../containers/UserAddPopupContainer';
|
import UserAddStepContainer from '../../containers/UserAddStepContainer';
|
||||||
import Item from './Item';
|
import Item from './Item';
|
||||||
|
|
||||||
const UsersModal = React.memo(
|
const UsersModal = React.memo(
|
||||||
|
@ -77,6 +78,8 @@ const UsersModal = React.memo(
|
||||||
[onDelete],
|
[onDelete],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const UserAddPopupContainer = usePopup(UserAddStepContainer);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal open closeIcon size="large" centered={false} onClose={onClose}>
|
<Modal open closeIcon size="large" centered={false} onClose={onClose}>
|
||||||
<Modal.Header>
|
<Modal.Header>
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import entryActions from '../entry-actions';
|
import entryActions from '../entry-actions';
|
||||||
import UserAddPopup from '../components/UserAddPopup';
|
import UserAddStep from '../components/UserAddStep';
|
||||||
|
|
||||||
const mapStateToProps = ({
|
const mapStateToProps = ({
|
||||||
ui: {
|
ui: {
|
||||||
|
@ -23,4 +23,4 @@ const mapDispatchToProps = (dispatch) =>
|
||||||
dispatch,
|
dispatch,
|
||||||
);
|
);
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(UserAddPopup);
|
export default connect(mapStateToProps, mapDispatchToProps)(UserAddStep);
|
|
@ -1,4 +1,4 @@
|
||||||
import withPopup from './with-popup';
|
import usePopup from './use-popup';
|
||||||
import closePopup from './close-popup';
|
import closePopup from './close-popup';
|
||||||
|
|
||||||
export { withPopup, closePopup };
|
export { usePopup, closePopup };
|
||||||
|
|
122
client/src/lib/popup/use-popup.jsx
Normal file
122
client/src/lib/popup/use-popup.jsx
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
import { ResizeObserver } from '@juggle/resize-observer';
|
||||||
|
import React, { useCallback, useMemo, useRef, useState } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { Button, Popup as SemanticUIPopup } from 'semantic-ui-react';
|
||||||
|
|
||||||
|
import styles from './Popup.module.css';
|
||||||
|
|
||||||
|
export default (Step, props) => {
|
||||||
|
return useMemo(() => {
|
||||||
|
const Popup = React.memo(({ children, onClose, ...stepProps }) => {
|
||||||
|
const [isOpened, setIsOpened] = useState(false);
|
||||||
|
|
||||||
|
const wrapper = useRef(null);
|
||||||
|
const resizeObserver = useRef(null);
|
||||||
|
|
||||||
|
const handleOpen = useCallback(() => {
|
||||||
|
setIsOpened(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleClose = useCallback(() => {
|
||||||
|
setIsOpened(false);
|
||||||
|
|
||||||
|
if (onClose) {
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
}, [onClose]);
|
||||||
|
|
||||||
|
const handleMouseDown = useCallback((event) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleClick = useCallback((event) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleTriggerClick = useCallback(
|
||||||
|
(event) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
const { onClick } = children;
|
||||||
|
|
||||||
|
if (onClick) {
|
||||||
|
onClick(event);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[children],
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleContentRef = useCallback((element) => {
|
||||||
|
if (resizeObserver.current) {
|
||||||
|
resizeObserver.current.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!element) {
|
||||||
|
resizeObserver.current = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resizeObserver.current = new ResizeObserver(() => {
|
||||||
|
if (resizeObserver.current.isInitial) {
|
||||||
|
resizeObserver.current.isInitial = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapper.current.positionUpdate();
|
||||||
|
});
|
||||||
|
|
||||||
|
resizeObserver.current.isInitial = true;
|
||||||
|
resizeObserver.current.observe(element);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const tigger = React.cloneElement(children, {
|
||||||
|
onClick: handleTriggerClick,
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SemanticUIPopup
|
||||||
|
basic
|
||||||
|
wide
|
||||||
|
ref={wrapper}
|
||||||
|
trigger={tigger}
|
||||||
|
on="click"
|
||||||
|
open={isOpened}
|
||||||
|
position="bottom left"
|
||||||
|
popperModifiers={[
|
||||||
|
{
|
||||||
|
name: 'preventOverflow',
|
||||||
|
enabled: true,
|
||||||
|
options: {
|
||||||
|
altAxis: true,
|
||||||
|
padding: 20,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
className={styles.wrapper}
|
||||||
|
onOpen={handleOpen}
|
||||||
|
onClose={handleClose}
|
||||||
|
onMouseDown={handleMouseDown}
|
||||||
|
onClick={handleClick}
|
||||||
|
{...props} // eslint-disable-line react/jsx-props-no-spreading
|
||||||
|
>
|
||||||
|
<div ref={handleContentRef}>
|
||||||
|
<Button icon="close" onClick={handleClose} className={styles.closeButton} />
|
||||||
|
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
|
||||||
|
<Step {...stepProps} onClose={handleClose} />
|
||||||
|
</div>
|
||||||
|
</SemanticUIPopup>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Popup.propTypes = {
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
|
onClose: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
|
Popup.defaultProps = {
|
||||||
|
onClose: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
return Popup;
|
||||||
|
}, [props]);
|
||||||
|
};
|
|
@ -1,120 +0,0 @@
|
||||||
import { ResizeObserver } from '@juggle/resize-observer';
|
|
||||||
import React, { useCallback, useRef, useState } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { Button, Popup as SemanticUIPopup } from 'semantic-ui-react';
|
|
||||||
|
|
||||||
import styles from './Popup.module.css';
|
|
||||||
|
|
||||||
export default (WrappedComponent, defaultProps) => {
|
|
||||||
const Popup = React.memo(({ children, onClose, ...props }) => {
|
|
||||||
const [isOpened, setIsOpened] = useState(false);
|
|
||||||
|
|
||||||
const wrapper = useRef(null);
|
|
||||||
const resizeObserver = useRef(null);
|
|
||||||
|
|
||||||
const handleOpen = useCallback(() => {
|
|
||||||
setIsOpened(true);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleClose = useCallback(() => {
|
|
||||||
setIsOpened(false);
|
|
||||||
|
|
||||||
if (onClose) {
|
|
||||||
onClose();
|
|
||||||
}
|
|
||||||
}, [onClose]);
|
|
||||||
|
|
||||||
const handleMouseDown = useCallback((event) => {
|
|
||||||
event.stopPropagation();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleClick = useCallback((event) => {
|
|
||||||
event.stopPropagation();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleTriggerClick = useCallback(
|
|
||||||
(event) => {
|
|
||||||
event.stopPropagation();
|
|
||||||
|
|
||||||
const { onClick } = children;
|
|
||||||
|
|
||||||
if (onClick) {
|
|
||||||
onClick(event);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[children],
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleContentRef = useCallback((element) => {
|
|
||||||
if (resizeObserver.current) {
|
|
||||||
resizeObserver.current.disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!element) {
|
|
||||||
resizeObserver.current = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
resizeObserver.current = new ResizeObserver(() => {
|
|
||||||
if (resizeObserver.current.isInitial) {
|
|
||||||
resizeObserver.current.isInitial = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
wrapper.current.positionUpdate();
|
|
||||||
});
|
|
||||||
|
|
||||||
resizeObserver.current.isInitial = true;
|
|
||||||
resizeObserver.current.observe(element);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const tigger = React.cloneElement(children, {
|
|
||||||
onClick: handleTriggerClick,
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SemanticUIPopup
|
|
||||||
basic
|
|
||||||
wide
|
|
||||||
ref={wrapper}
|
|
||||||
trigger={tigger}
|
|
||||||
on="click"
|
|
||||||
open={isOpened}
|
|
||||||
position="bottom left"
|
|
||||||
popperModifiers={[
|
|
||||||
{
|
|
||||||
name: 'preventOverflow',
|
|
||||||
enabled: true,
|
|
||||||
options: {
|
|
||||||
altAxis: true,
|
|
||||||
padding: 20,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
className={styles.wrapper}
|
|
||||||
onOpen={handleOpen}
|
|
||||||
onClose={handleClose}
|
|
||||||
onMouseDown={handleMouseDown}
|
|
||||||
onClick={handleClick}
|
|
||||||
{...defaultProps} // eslint-disable-line react/jsx-props-no-spreading
|
|
||||||
>
|
|
||||||
<div ref={handleContentRef}>
|
|
||||||
<Button icon="close" onClick={handleClose} className={styles.closeButton} />
|
|
||||||
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
|
|
||||||
<WrappedComponent {...props} onClose={handleClose} />
|
|
||||||
</div>
|
|
||||||
</SemanticUIPopup>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
Popup.propTypes = {
|
|
||||||
children: PropTypes.node.isRequired,
|
|
||||||
onClose: PropTypes.func,
|
|
||||||
};
|
|
||||||
|
|
||||||
Popup.defaultProps = {
|
|
||||||
onClose: undefined,
|
|
||||||
};
|
|
||||||
|
|
||||||
return Popup;
|
|
||||||
};
|
|
Loading…
Add table
Add a link
Reference in a new issue