1
0
Fork 0
mirror of https://github.com/plankanban/planka.git synced 2025-07-19 05:09:43 +02:00

Add attachment popup, hide attachments if more than 4

This commit is contained in:
Maksim Eltyshev 2020-04-29 23:55:16 +05:00
parent c2a16459df
commit febc614ce8
8 changed files with 134 additions and 27 deletions

View file

@ -1,23 +0,0 @@
import React, { useCallback } from 'react';
import PropTypes from 'prop-types';
import { FilePicker } from '../../lib/custom-ui';
const AddAttachment = React.memo(({ children, onCreate }) => {
const handleFileSelect = useCallback(
(file) => {
onCreate({
file,
});
},
[onCreate],
);
return <FilePicker onSelect={handleFileSelect}>{children}</FilePicker>;
});
AddAttachment.propTypes = {
children: PropTypes.element.isRequired,
onCreate: PropTypes.func.isRequired,
};
export default AddAttachment;

View file

@ -0,0 +1,54 @@
import React, { useCallback } from 'react';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import { Menu } from 'semantic-ui-react';
import { withPopup } from '../../lib/popup';
import { FilePicker, Popup } from '../../lib/custom-ui';
import styles from './AddAttachmentPopup.module.css';
const AddAttachmentStep = React.memo(({ onCreate, onClose }) => {
const [t] = useTranslation();
const handleFileSelect = useCallback(
(file) => {
onCreate({
file,
});
onClose();
},
[onCreate, onClose],
);
return (
<>
<Popup.Header>
{t('common.addAttachment', {
context: 'title',
})}
</Popup.Header>
<Popup.Content>
<Menu secondary vertical className={styles.menu}>
<FilePicker onSelect={handleFileSelect}>
<Menu.Item className={styles.menuItem}>
{t('common.fromComputer', {
context: 'title',
})}
</Menu.Item>
</FilePicker>
</Menu>
<hr className={styles.divider} />
<div className={styles.tip}>
{t('common.pressPasteShortcutToAddAttachmentFromClipboard')}
</div>
</Popup.Content>
</>
);
});
AddAttachmentStep.propTypes = {
onCreate: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
};
export default withPopup(AddAttachmentStep);

View file

@ -0,0 +1,20 @@
.divider {
background-color: #eee;
border: 0;
height: 1px;
margin-bottom: 8px;
}
.menu {
margin: -7px -12px -5px !important;
width: calc(100% + 24px) !important;
}
.menuItem {
margin: 0 !important;
padding-left: 14px !important;
}
.tip {
opacity: 0.5;
}

View file

@ -1,9 +1,21 @@
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 { Button } from 'semantic-ui-react';
import { useToggle } from '../../../lib/hooks';
import Item from './Item'; import Item from './Item';
import styles from './Attachments.module.css';
const Attachments = React.memo(({ items, onUpdate, onDelete, onCoverUpdate }) => { const Attachments = React.memo(({ items, onUpdate, onDelete, onCoverUpdate }) => {
const [t] = useTranslation();
const [isOpened, toggleOpened] = useToggle();
const handleToggleClick = useCallback(() => {
toggleOpened();
}, [toggleOpened]);
const handleCoverSelect = useCallback( const handleCoverSelect = useCallback(
(id) => { (id) => {
onCoverUpdate(id); onCoverUpdate(id);
@ -29,9 +41,11 @@ const Attachments = React.memo(({ items, onUpdate, onDelete, onCoverUpdate }) =>
[onDelete], [onDelete],
); );
const visibleItems = isOpened ? items : items.slice(0, 4);
return ( return (
<> <>
{items.map((item) => ( {visibleItems.map((item) => (
<Item <Item
key={item.id} key={item.id}
name={item.name} name={item.name}
@ -46,6 +60,20 @@ const Attachments = React.memo(({ items, onUpdate, onDelete, onCoverUpdate }) =>
onDelete={() => handleDelete(item.id)} onDelete={() => handleDelete(item.id)}
/> />
))} ))}
{items.length > 4 && (
<Button
fluid
content={
isOpened
? t('action.showFewerAttachments')
: t('action.showAllAttachments', {
hidden: items.length - visibleItems.length,
})
}
className={styles.toggleButton}
onClick={handleToggleClick}
/>
)}
</> </>
); );
}); });

View file

@ -0,0 +1,16 @@
.toggleButton {
background: transparent !important;
box-shadow: none !important;
color: #6b808c !important;
font-weight: normal !important;
margin-top: 8px !important;
padding: 6px 11px !important;
text-align: left !important;
text-decoration: underline !important;
transition: none;
}
.toggleButton:hover {
background: rgba(9, 30, 66, 0.08) !important;
color: #092d42 !important;
}

View file

@ -9,8 +9,8 @@ import NameField from './NameField';
import EditDescription from './EditDescription'; import EditDescription from './EditDescription';
import Tasks from './Tasks'; import Tasks from './Tasks';
import Attachments from './Attachments'; import Attachments from './Attachments';
import AddAttachment from './AddAttachment';
import AddAttachmentZone from './AddAttachmentZone'; import AddAttachmentZone from './AddAttachmentZone';
import AddAttachmentPopup from './AddAttachmentPopup';
import Actions from './Actions'; import Actions from './Actions';
import User from '../User'; import User from '../User';
import Label from '../Label'; import Label from '../Label';
@ -337,12 +337,12 @@ const CardModal = React.memo(
{t('common.timer')} {t('common.timer')}
</Button> </Button>
</EditTimerPopup> </EditTimerPopup>
<AddAttachment onCreate={onAttachmentCreate}> <AddAttachmentPopup onCreate={onAttachmentCreate}>
<Button fluid className={styles.actionButton}> <Button fluid className={styles.actionButton}>
<Icon name="attach" className={styles.actionIcon} /> <Icon name="attach" className={styles.actionIcon} />
{t('common.attachment')} {t('common.attachment')}
</Button> </Button>
</AddAttachment> </AddAttachmentPopup>
</div> </div>
<div className={styles.actions}> <div className={styles.actions}>
<span className={styles.actionsTitle}>{t('common.actions')}</span> <span className={styles.actionsTitle}>{t('common.actions')}</span>

View file

@ -11,6 +11,7 @@ export default {
common: { common: {
account: 'Account', account: 'Account',
actions: 'Actions', actions: 'Actions',
addAttachment_title: 'Add Attachment',
addComment: 'Add comment', addComment: 'Add comment',
addMember_title: 'Add Member', addMember_title: 'Add Member',
addUser_title: 'Add User', addUser_title: 'Add User',
@ -77,6 +78,7 @@ export default {
enterTaskDescription: 'Enter task description...', enterTaskDescription: 'Enter task description...',
filterByLabels_title: 'Filter By Labels', filterByLabels_title: 'Filter By Labels',
filterByMembers_title: 'Filter By Members', filterByMembers_title: 'Filter By Members',
fromComputer_title: 'From Computer',
hours: 'Hours', hours: 'Hours',
invalidCurrentPassword: 'Invalid current password', invalidCurrentPassword: 'Invalid current password',
labels: 'Labels', labels: 'Labels',
@ -95,6 +97,8 @@ export default {
organization: 'Organization', organization: 'Organization',
phone: 'Phone', phone: 'Phone',
preferences: 'Preferences', preferences: 'Preferences',
pressPasteShortcutToAddAttachmentFromClipboard:
'Tip: press Ctrl-V (Cmd-V on Mac) to add an attachment from the clipboard.',
projectNotFound_title: 'Project Not Found', projectNotFound_title: 'Project Not Found',
refreshPageToLoadLastDataAndReceiveUpdates: refreshPageToLoadLastDataAndReceiveUpdates:
'<0>Refresh the page</0> to load last data<br />and receive updates', '<0>Refresh the page</0> to load last data<br />and receive updates',
@ -166,6 +170,8 @@ export default {
removeFromProject: 'Remove from project', removeFromProject: 'Remove from project',
removeMember: 'Remove member', removeMember: 'Remove member',
save: 'Save', save: 'Save',
showAllAttachments: 'Show all attachments ({{hidden}} hidden)',
showFewerAttachments: 'Show fewer attachments',
start: 'Start', start: 'Start',
stop: 'Stop', stop: 'Stop',
subscribe: 'Subscribe', subscribe: 'Subscribe',

View file

@ -15,6 +15,7 @@ export default {
common: { common: {
account: 'Учетная запись', account: 'Учетная запись',
actions: 'Действия', actions: 'Действия',
addAttachment: 'Добавление вложения',
addComment: 'Добавление комментария', addComment: 'Добавление комментария',
addMember: 'Добавление участника', addMember: 'Добавление участника',
addUser: 'Добавление пользователя', addUser: 'Добавление пользователя',
@ -81,6 +82,7 @@ export default {
enterTaskDescription: 'Введите описание задачи...', enterTaskDescription: 'Введите описание задачи...',
filterByLabels: 'Фильтр по меткам', filterByLabels: 'Фильтр по меткам',
filterByMembers: 'Фильтр по участникам', filterByMembers: 'Фильтр по участникам',
fromComputer: 'С компьютера',
hours: 'Часы', hours: 'Часы',
invalidCurrentPassword: 'Неверный текущий пароль', invalidCurrentPassword: 'Неверный текущий пароль',
labels: 'Метки', labels: 'Метки',
@ -99,6 +101,8 @@ export default {
organization: 'Организация', organization: 'Организация',
phone: 'Телефон', phone: 'Телефон',
preferences: 'Предпочтения', preferences: 'Предпочтения',
pressPasteShortcutToAddAttachmentFromClipboard:
'Совет: нажмите Ctrl-V (Cmd-V на Mac), чтобы добавить вложение из буфера обмена.',
projectNotFound: 'Доска не найдена', projectNotFound: 'Доска не найдена',
refreshPageToLoadLastDataAndReceiveUpdates: refreshPageToLoadLastDataAndReceiveUpdates:
'<0>Обновите страницу</0>, чтобы загрузить<br />актуальные данные и получать обновления', '<0>Обновите страницу</0>, чтобы загрузить<br />актуальные данные и получать обновления',
@ -167,6 +171,8 @@ export default {
removeFromProject: 'Удалить из проекта', removeFromProject: 'Удалить из проекта',
removeMember: 'Удалить участника', removeMember: 'Удалить участника',
save: 'Сохранить', save: 'Сохранить',
showAllAttachments: 'Показать все вложения ({{hidden}} скрыто)',
showFewerAttachments: 'Показать меньше вложений',
start: 'Начать', start: 'Начать',
stop: 'Остановить', stop: 'Остановить',
subscribe: 'Подписаться', subscribe: 'Подписаться',