diff --git a/packages/components/src/informative/Kanban/Kanban.js b/packages/components/src/informative/Kanban/Kanban.js index 8117776d5..981812fb9 100644 --- a/packages/components/src/informative/Kanban/Kanban.js +++ b/packages/components/src/informative/Kanban/Kanban.js @@ -9,6 +9,8 @@ import reorder, { reorderQuoteMap } from './helpers/reorder'; export const KANBAN_DEFAULT_PROPS = { itemRender: ({ value }) => <>{value.title}, + showNewOnFirstColumn: true, + newItemLabel: 'Add new item', }; export const KANBAN_PROP_TYPES = { value: PropTypes.shape({ @@ -22,11 +24,22 @@ export const KANBAN_PROP_TYPES = { }), isCombineEnabled: PropTypes.bool, onChange: PropTypes.func, + onNew: PropTypes.func, icon: PropTypes.node, itemRender: PropTypes.oneOfType([PropTypes.node, PropTypes.func]), + showNewOnFirstColumn: PropTypes.bool, + newItemLabel: PropTypes.string, }; -const Kanban = ({ value, onChange, icon, itemRender }) => { +const Kanban = ({ + value, + onChange, + icon, + itemRender, + showNewOnFirstColumn, + onNew, + newItemLabel, +}) => { const { classes } = KanbanStyles({}); const onDragEnd = (result) => { @@ -73,6 +86,9 @@ const Kanban = ({ value, onChange, icon, itemRender }) => { index={index} itemRender={itemRender} icon={icon} + showNew={showNewOnFirstColumn && index === 0} + onNew={onNew} + newItemLabel={newItemLabel} /> ))} {provided.placeholder} diff --git a/packages/components/src/informative/Kanban/Kanban.styles.js b/packages/components/src/informative/Kanban/Kanban.styles.js index 55552c0f4..3874bde72 100644 --- a/packages/components/src/informative/Kanban/Kanban.styles.js +++ b/packages/components/src/informative/Kanban/Kanban.styles.js @@ -1,58 +1,61 @@ import { createStyles } from '@mantine/styles'; -export const KanbanStyles = createStyles((theme, {}) => { - return { - root: { - overflow: 'auto', - whiteSpace: 'nowrap', - height: '100%', - maxHeight: '100%', - padding: theme.spacing[2], - backgroundColor: '#F8F9FB', - gap: theme.spacing[2], - display: 'flex', +const KanbanStyles = createStyles((theme) => ({ + root: { + display: 'flex', + overflow: 'auto', + whiteSpace: 'nowrap', + height: '100%', + maxHeight: '100%', + gap: theme.spacing[2], + alignItems: 'stretch', + padding: theme.spacing[2], + backgroundColor: '#F8F9FB', + }, + column: { + display: 'inline-flex', + position: 'relative', + width: '300px', + minWidth: '300px', + flexDirection: 'column', + backgroundColor: '#F2F4F8', + borderRadius: theme.spacing[1], + }, + columnHeader: { + paddingLeft: theme.spacing[4], + paddingRight: theme.spacing[4], + paddingTop: theme.spacing[3], + color: '#4D5358', + fontSize: '16px', + fontWeight: 600, + lineHeight: '24px', + fontFamily: 'Albert Sans', + display: 'flex', + gap: theme.spacing[2], + alignItems: 'center', + }, + scroll: { + padding: theme.spacing[2], + }, + listDraggingOver: { + backgroundColor: '#EDEFF5', + borderRadius: 4, + }, + list: { + minHeight: '100px', + }, + iconBig: { + position: 'absolute', + bottom: 20, + left: 20, + zIndex: 0, + img: { + filter: 'brightness(0) invert(1)', }, - column: { - height: '100%', - display: 'inline-flex', - position: 'relative', - width: '300px', - minWidth: '300px', - flexDirection: 'column', - backgroundColor: '#F2F4F8', - borderRadius: theme.spacing[1], - }, - columnHeader: { - paddingLeft: theme.spacing[4], - paddingRight: theme.spacing[4], - paddingTop: theme.spacing[3], - color: '#4D5358', - fontSize: '16px', - fontWeight: 600, - lineHeight: '24px', - fontFamily: 'Albert Sans', - display: 'flex', - gap: theme.spacing[2], - alignItems: 'center', - }, - scroll: { - padding: theme.spacing[2], - }, - listDraggingOver: { - backgroundColor: '#EDEFF5', - borderRadius: 4, - }, - list: { - minHeight: '100px', - }, - iconBig: { - position: 'absolute', - bottom: 20, - left: 20, - zIndex: 0, - img: { - filter: 'brightness(0) invert(1)', - }, - }, - }; -}); + }, + newItem: { + padding: theme.spacing[2], + }, +})); + +export { KanbanStyles }; diff --git a/packages/components/src/informative/Kanban/components/Column.js b/packages/components/src/informative/Kanban/components/Column.js index f465f5129..2e59d79af 100644 --- a/packages/components/src/informative/Kanban/components/Column.js +++ b/packages/components/src/informative/Kanban/components/Column.js @@ -1,13 +1,25 @@ import React from 'react'; +import PropTypes from 'prop-types'; +import { ScrollArea } from '@mantine/core'; +import { Draggable } from 'react-beautiful-dnd'; import { Box } from '../../../layout/Box'; import { KanbanStyles } from '../Kanban.styles'; -import { Draggable } from 'react-beautiful-dnd'; import { QuoteList } from './QuoteList'; import { ImageLoader } from '../../../misc'; -import { ScrollArea } from '@mantine/core'; +import { NewItem } from './NewItem'; -const Column = ({ value, index, isScrollable, isCombineEnabled, itemRender, icon, ...props }) => { - const { classes, cx } = KanbanStyles({}); +const Column = ({ + value, + index, + isScrollable, + isCombineEnabled, + itemRender, + icon, + onNew, + showNew, + newItemLabel, +}) => { + const { classes } = KanbanStyles({}); return ( @@ -32,14 +44,20 @@ const Column = ({ value, index, isScrollable, isCombineEnabled, itemRender, icon {value.cards.length} - + {showNew && !value.cards?.length ? ( + + + + ) : ( + + )} )} @@ -47,4 +65,16 @@ const Column = ({ value, index, isScrollable, isCombineEnabled, itemRender, icon ); }; +Column.propTypes = { + value: PropTypes.object, + index: PropTypes.number, + isScrollable: PropTypes.bool, + isCombineEnabled: PropTypes.bool, + itemRender: PropTypes.func, + icon: PropTypes.string, + onNew: PropTypes.func, + showNew: PropTypes.bool, + newItemLabel: PropTypes.string, +}; + export { Column }; diff --git a/packages/components/src/informative/Kanban/components/NewItem.js b/packages/components/src/informative/Kanban/components/NewItem.js new file mode 100644 index 000000000..4d10c1ff4 --- /dev/null +++ b/packages/components/src/informative/Kanban/components/NewItem.js @@ -0,0 +1,50 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { noop, capitalize } from 'lodash'; +import { AddCircleIcon } from '@bubbles-ui/icons/solid'; +import { UnstyledButton, createStyles } from '@mantine/core'; +import { Box } from '../../../layout/Box'; + +const useStyles = createStyles((theme) => ({ + root: { + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + borderRadius: theme.other.global.border.radius.md, + border: `2px dashed ${theme.other.dropzone.border.color.default}`, + cursor: 'pointer', + gap: 4, + width: '100%', + paddingBlock: theme.spacing[7], + '&:hover': { + backgroundColor: theme.other.dropzone.background.color.hover, + }, + }, + label: { + color: theme.other.global.content.color.text.default, + ...theme.other.global.content.typo.body['md--bold'], + }, + icon: { + color: theme.other.global.content.color.icon.default, + }, +})); + +function NewItem({ label, onClick = noop }) { + const { classes } = useStyles({}, { name: 'NewLibraryCardButton' }); + return ( + + + + + {capitalize(label)} + + ); +} + +NewItem.propTypes = { + label: PropTypes.string.isRequired, + onClick: PropTypes.func.isRequired, +}; + +export { NewItem }; diff --git a/packages/components/src/informative/Kanban/mock/mock.js b/packages/components/src/informative/Kanban/mock/mock.js index 250889ab2..a801fc659 100644 --- a/packages/components/src/informative/Kanban/mock/mock.js +++ b/packages/components/src/informative/Kanban/mock/mock.js @@ -39,6 +39,40 @@ export const mock = { deleted_at: null, fromCalendar: true, }, + { + id: '642b7dd7-a219-4792-87f3-5e62c6b223234', + title: 'Next task 3', + calendar: '9c1ec044-beb7-4f86-b1db-0c8b365ee786', + startDate: '2022-01-11T23:00:00.000Z', + endDate: '2022-01-13T22:59:59.000Z', + isAllDay: 1, + repeat: 'dont_repeat', + type: 'plugins.calendar.task', + status: 'active', + data: { column: '734c8a98-ce1b-4d8a-912f-f65eeb850f24' }, + deleted: 0, + created_at: '2022-01-24T09:59:50.000Z', + updated_at: '2022-01-24T09:59:50.000Z', + deleted_at: null, + fromCalendar: true, + }, + { + id: '642b7dd7-a219-4792-87f3-5e62csdfsdfs', + title: 'Next task 4', + calendar: '9c1ec044-beb7-4f86-b1db-0c8b365ee786', + startDate: '2022-01-11T23:00:00.000Z', + endDate: '2022-01-13T22:59:59.000Z', + isAllDay: 1, + repeat: 'dont_repeat', + type: 'plugins.calendar.task', + status: 'active', + data: { column: '734c8a98-ce1b-4d8a-912f-f65eeb850f24' }, + deleted: 0, + created_at: '2022-01-24T09:59:50.000Z', + updated_at: '2022-01-24T09:59:50.000Z', + deleted_at: null, + fromCalendar: true, + }, ], }, {