Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/RocketChat#755' into protocols
Browse files Browse the repository at this point in the history
  • Loading branch information
shedoev committed Nov 5, 2020
2 parents 9beb460 + 65f1590 commit 0013f22
Show file tree
Hide file tree
Showing 30 changed files with 879 additions and 148 deletions.
118 changes: 110 additions & 8 deletions app/councils/client/views/Council.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useMemo, useState } from 'react';
import { Box, Button, Field, Icon, Label, Table, TextInput, TextAreaInput } from '@rocket.chat/fuselage';
import React, { useCallback, useMemo, useState } from 'react';
import { ButtonGroup, Button, Field, Icon, Label, Table, TextInput, TextAreaInput, Modal } from '@rocket.chat/fuselage';

import Page from '../../../../client/components/basic/Page';
import { useTranslation } from '../../../../client/contexts/TranslationContext';
Expand All @@ -11,9 +11,50 @@ import { useMediaQuery } from '@rocket.chat/fuselage-hooks';
import { useMethod } from '../../../../client/contexts/ServerContext';
import { settings } from '../../../../app/settings/client';
import moment from 'moment';
import { useSetModal } from '/client/contexts/ModalContext';
import { useToastMessageDispatch } from '/client/contexts/ToastMessagesContext';

const style = { textOverflow: 'ellipsis', overflow: 'hidden' };

const DeleteWarningModal = ({ title, onDelete, onCancel, ...props }) => {
const t = useTranslation();
return <Modal {...props}>
<Modal.Header>
<Icon color='danger' name='modal-warning' size={20}/>
<Modal.Title>{t('Are_you_sure')}</Modal.Title>
<Modal.Close onClick={onCancel}/>
</Modal.Header>
<Modal.Content fontScale='p1'>
{title}
</Modal.Content>
<Modal.Footer>
<ButtonGroup align='end'>
<Button ghost onClick={onCancel}>{t('Cancel')}</Button>
<Button primary danger onClick={onDelete}>{t('Delete')}</Button>
</ButtonGroup>
</Modal.Footer>
</Modal>;
};

const SuccessModal = ({ title, onClose, ...props }) => {
const t = useTranslation();
return <Modal {...props}>
<Modal.Header>
<Icon color='success' name='checkmark-circled' size={20}/>
<Modal.Title>{t('Deleted')}</Modal.Title>
<Modal.Close onClick={onClose}/>
</Modal.Header>
<Modal.Content fontScale='p1'>
{title}
</Modal.Content>
<Modal.Footer>
<ButtonGroup align='end'>
<Button primary onClick={onClose}>{t('Ok')}</Button>
</ButtonGroup>
</Modal.Footer>
</Modal>;
};

export function CouncilPage() {
const t = useTranslation();
const formatDateAndTime = useFormatDateAndTime();
Expand All @@ -30,6 +71,12 @@ export function CouncilPage() {

const invitedUsers = data.invitedUsers || { };

const setModal = useSetModal();

const deleteCouncil = useMethod('deleteCouncil');

const dispatchToastMessage = useToastMessageDispatch();

const mediaQuery = useMediaQuery('(min-width: 768px)');

const downloadCouncilParticipantsMethod = useMethod('downloadCouncilParticipants');
Expand Down Expand Up @@ -58,14 +105,34 @@ export function CouncilPage() {
mediaQuery && <Th key={'contact'} color='default'>{t('Council_Contact_person')}</Th>,
mediaQuery && <Th key={'phone'} color='default'>{t('Phone_number')}</Th>,
mediaQuery && <Th key={'email'} color='default'>{t('Email')}</Th>,
mediaQuery && <Th key={'createdAt'} style={{ width: '190px' }} color='default'>{t('Joined_at')}</Th>
mediaQuery && <Th key={'createdAt'} style={{ width: '190px' }} color='default'>{t('Joined_at')}</Th>,
], [mediaQuery]);

const styleTableRow = { wordWrap: 'break-word' };

const getBackgroundColor = (invitedUser) => {
const index = invitedUsers.findIndex((user) => (
user.firstName === invitedUser.firstName
&& user.lastName === invitedUser.lastName
&& user.patronymic === invitedUser.patronymic
&& user.position === invitedUser.position
&& user.contactPersonFirstName === invitedUser.contactPersonFirstName
&& user.contactPersonLastName === invitedUser.contactPersonLastName
&& user.contactPersonPatronymicName === invitedUser.contactPersonPatronymicName
&& user.phone === invitedUser.phone
&& user.email === invitedUser.email
&& user.ts === invitedUser.ts
));
if (index > 0 && index % 2 === 1) {
return 'var(--color-lighter-blue)';
}

return '';
};

const renderRow = (invitedUser) => {
const iu = invitedUser;
return <Table.Row key={iu._id} style={styleTableRow} tabIndex={0} role='link' action>
return <Table.Row key={iu._id} style={styleTableRow} border={getBackgroundColor(invitedUser)} tabIndex={0} role='link' action>
<Table.Cell fontScale='p1' style={style} color='default'>{iu.lastName} {iu.firstName} {iu.patronymic}</Table.Cell>
<Table.Cell fontScale='p1' style={style} color='default'>{iu.position}</Table.Cell>
{ mediaQuery && <Table.Cell fontScale='p1' style={style} color='default'>{iu.contactPersonLastName} {iu.contactPersonFirstName} {iu.contactPersonPatronymicName}</Table.Cell>}
Expand All @@ -79,6 +146,30 @@ export function CouncilPage() {
window.history.back();
};

const goToCouncils = () => {
FlowRouter.go('councils');
};

const onEdit = (_id) => () => {
FlowRouter.go(`/council/edit/${ _id }`);
};

const onNewParticipantClick = (_id) => () => {
FlowRouter.go(`/council/edit/newParticipant/${ _id }`);
};

const onDeleteCouncilConfirm = useCallback(async () => {
try {
await deleteCouncil(councilId);
setModal(() => <SuccessModal title={'Delete'} onClose={() => { setModal(undefined); }}/>);
goToCouncils();
} catch (error) {
dispatchToastMessage({ type: 'error', message: error });
}
}, [deleteCouncil, dispatchToastMessage]);

const onDeleteCouncilClick = () => setModal(() => <DeleteWarningModal title={t('Council_Delete_Warning')} onDelete={onDeleteCouncilConfirm} onCancel={() => setModal(undefined)}/>);

return <Page flexDirection='row'>
<Page>
<Page.Header>
Expand All @@ -87,7 +178,16 @@ export function CouncilPage() {
<Icon name='back'/>
</Button>
<Label fontScale='h1'>{t('Council')}</Label>

</Field>
<ButtonGroup>
<Button primary danger small aria-label={t('Delete')} onClick={onDeleteCouncilClick}>
{t('Delete')}
</Button>
<Button primary small aria-label={t('Edit')} onClick={onEdit(councilId)}>
{t('Edit')}
</Button>
</ButtonGroup>
</Page.Header>
<Page.Content>
<Field mbe='x8'>
Expand All @@ -99,7 +199,7 @@ export function CouncilPage() {
<Field mbe='x8'>
<Field.Label>{t('Description')}</Field.Label>
<Field.Row>
<TextAreaInput row='3' readOnly is='span' fontScale='p1'>{data.desc}</TextAreaInput>
<TextAreaInput value={data.desc} row='3' readOnly fontScale='p1'/>
</Field.Row>
</Field>
<Field mbe='x8'>
Expand All @@ -109,14 +209,16 @@ export function CouncilPage() {
</Field.Row>
</Field>
<Field mbe='x8'>
<Field.Row>
<Field.Label>{t('Council_Invited_Users')}</Field.Label>
<Field.Row marginInlineStart='auto'>
<Button marginInlineEnd='10px' small primary onClick={onNewParticipantClick(councilId)} aria-label={t('Add')}>
{t('Council_Add_Participant')}
</Button>
<Button small primary onClick={downloadCouncilParticipants(councilId)} aria-label={t('Download')}>
{t('Download_Council_Participant_List')}
</Button>
</Field.Row>
<GenericTable header={header} renderRow={renderRow} results={invitedUsers} total={invitedUsers.length} setParams={setParams} params={params} />
</Field>
<GenericTable header={header} renderRow={renderRow} results={invitedUsers} total={invitedUsers.length} setParams={setParams} params={params} />
</Page.Content>
</Page>
</Page>;
Expand Down
71 changes: 69 additions & 2 deletions app/councils/client/views/Councils.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,72 @@
import React, { useMemo } from 'react';
import { Box, Button, Icon, Table } from '@rocket.chat/fuselage';
import React, { useCallback, useMemo } from 'react';
import { Box, Button, ButtonGroup, Icon, Modal, Table } from '@rocket.chat/fuselage';
import { useMediaQuery } from '@rocket.chat/fuselage-hooks';

import { useTranslation } from '../../../../client/contexts/TranslationContext';
import { GenericTable, Th } from '../../../../client/components/GenericTable';
import { useFormatDateAndTime } from '../../../../client/hooks/useFormatDateAndTime';
import { useMethod } from '../../../../client/contexts/ServerContext';
import moment from 'moment';
import { useSetModal } from '/client/contexts/ModalContext';
import { useToastMessageDispatch } from '/client/contexts/ToastMessagesContext';

const DeleteWarningModal = ({ title, onDelete, onCancel, ...props }) => {
const t = useTranslation();
return <Modal {...props}>
<Modal.Header>
<Icon color='danger' name='modal-warning' size={20}/>
<Modal.Title>{t('Are_you_sure')}</Modal.Title>
<Modal.Close onClick={onCancel}/>
</Modal.Header>
<Modal.Content fontScale='p1'>
{title}
</Modal.Content>
<Modal.Footer>
<ButtonGroup align='end'>
<Button ghost onClick={onCancel}>{t('Cancel')}</Button>
<Button primary danger onClick={onDelete}>{t('Delete')}</Button>
</ButtonGroup>
</Modal.Footer>
</Modal>;
};

const SuccessModal = ({ title, onClose, ...props }) => {
const t = useTranslation();
return <Modal {...props}>
<Modal.Header>
<Icon color='success' name='checkmark-circled' size={20}/>
<Modal.Title>{t('Deleted')}</Modal.Title>
<Modal.Close onClick={onClose}/>
</Modal.Header>
<Modal.Content fontScale='p1'>
{title}
</Modal.Content>
<Modal.Footer>
<ButtonGroup align='end'>
<Button primary onClick={onClose}>{t('Ok')}</Button>
</ButtonGroup>
</Modal.Footer>
</Modal>;
};

export function Councils({
data,
sort,
onClick,
onEditClick,
onHeaderClick,
onChange,
setParams,
params,
}) {
const t = useTranslation();

const setModal = useSetModal();

const deleteCouncil = useMethod('deleteCouncil');

const dispatchToastMessage = useToastMessageDispatch();

const mediaQuery = useMediaQuery('(min-width: 768px)');

const downloadCouncilParticipantsMethod = useMethod('downloadCouncilParticipants');
Expand Down Expand Up @@ -78,13 +126,27 @@ export function Councils({
<Th key={'desc'} color='default'>{t('Description')}</Th>,
mediaQuery && <Th key={'createdAt'} direction={sort[1]} active={sort[0] === 'createdAt'} onClick={onHeaderClick} sort='createdAt' style={{ width: '190px' }} color='default'>{t('Created_at')}</Th>,
<Th w='x40' key='edit'></Th>,
<Th w='x40' key='delete'></Th>,
<Th w='x40' key='download'></Th>
], [sort, mediaQuery]);

const formatDateAndTime = useFormatDateAndTime();

const styleTr = { borderBottomWidth: '10px', borderBottomColor: 'var(--color-white)' };

const onDeleteCouncilConfirm = useCallback(async (_id) => {
try {
await deleteCouncil(_id);
setModal(() => <SuccessModal title={'Delete'} onClose={() => { setModal(undefined); onChange(); }}/>);
} catch (error) {
dispatchToastMessage({ type: 'error', message: error });
}
}, [deleteCouncil, dispatchToastMessage, onChange]);

const onDel = (_id) => () => { onDeleteCouncilConfirm(_id); };

const onDeleteCouncilClick = (_id) => () => setModal(() => <DeleteWarningModal title={t('Council_Delete_Warning')} onDelete={onDel(_id)} onCancel={() => setModal(undefined)}/>);

const renderRow = (council) => {
const { _id, d: date, desc, ts } = council;
return <Table.Row key={_id} tabIndex={0} role='link' action style={styleTr} backgroundColor={colorBackgroundCouncil(date)}>
Expand All @@ -96,6 +158,11 @@ export function Councils({
<Icon name='edit'/>
</Button>
</Table.Cell>
<Table.Cell alignItems={'end'}>
<Button small aria-label={t('Delete')} onClick={onDeleteCouncilClick(_id)} color={colorTextCouncil(date)}>
<Icon name='trash'/>
</Button>
</Table.Cell>
<Table.Cell alignItems={'end'}>
<Button small onClick={downloadCouncilParticipants(_id)} aria-label={t('Download')} color={colorTextCouncil(date)}>
<Icon name='download'/>
Expand Down
Loading

0 comments on commit 0013f22

Please sign in to comment.