Feat/open comment drawer from comment chip (#187)

* wip

* Can open comment right drawer from company name cell
This commit is contained in:
Lucas Bordeau 2023-06-02 17:51:17 +02:00 committed by GitHub
parent 69c1095055
commit a2fe159c2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 154 additions and 34 deletions

View File

@ -16,6 +16,9 @@ const StyledContainer = styled.span`
padding: ${(props) => props.theme.spacing(1)};
gap: ${(props) => props.theme.spacing(1)};
overflow: hidden;
white-space: nowrap;
:hover {
filter: brightness(95%);
}

View File

@ -4,7 +4,7 @@ import { CommentChip, CommentChipProps } from './CommentChip';
const StyledCellWrapper = styled.div`
position: relative;
right: 38px;
top: -14px;
top: -13px;
width: 0;
height: 0;
`;

View File

@ -3,7 +3,7 @@ import { IconComment } from '../icons';
export type CommentChipProps = {
count: number;
onClick?: () => void;
onClick?: (event: React.MouseEvent<HTMLDivElement>) => void;
};
const StyledChip = styled.div`

View File

@ -1,9 +1,13 @@
import { useRecoilState } from 'recoil';
import { RightDrawerBody } from '../../layout/right-drawer/RightDrawerBody';
import { RightDrawerPage } from '../../layout/right-drawer/RightDrawerPage';
import { RightDrawerTopBar } from '../../layout/right-drawer/RightDrawerTopBar';
import { CommentTextInput } from './CommentTextInput';
import { commentableEntityArrayState } from '../../modules/comments/states/commentableEntityArrayState';
export function RightDrawerComments() {
const [commentableEntityArray] = useRecoilState(commentableEntityArrayState);
function handleSendComment(text: string) {
console.log(text);
}
@ -12,6 +16,11 @@ export function RightDrawerComments() {
<RightDrawerPage>
<RightDrawerTopBar title="Comments" />
<RightDrawerBody>
{commentableEntityArray.map((commentableEntity) => (
<div key={commentableEntity.id}>
{commentableEntity.type} - {commentableEntity.id}
</div>
))}
<CommentTextInput onSend={handleSendComment} />
</RightDrawerBody>
</RightDrawerPage>

View File

@ -0,0 +1,40 @@
import { Company } from '../../interfaces/entities/company.interface';
import { useOpenCommentRightDrawer } from '../../modules/comments/hooks/useOpenCommentRightDrawer';
import { updateCompany } from '../../services/api/companies';
import { getLogoUrlFromDomainName } from '../../services/utils';
import CompanyChip from '../chips/CompanyChip';
import EditableChip from '../editable-cell/EditableChip';
type OwnProps = {
company: Company;
};
export function CompanyEditableNameChipCell({ company }: OwnProps) {
const openCommentRightDrawer = useOpenCommentRightDrawer();
function handleCommentClick() {
openCommentRightDrawer([
{
type: 'Company',
id: company.id,
},
]);
}
return (
<EditableChip
value={company.name || ''}
placeholder="Name"
picture={getLogoUrlFromDomainName(company.domainName)}
changeHandler={(value: string) => {
updateCompany({
...company,
name: value,
});
}}
ChipComponent={CompanyChip}
commentCount={12}
onCommentClick={handleCommentClick}
/>
);
}

View File

@ -3,7 +3,7 @@ import styled from '@emotion/styled';
export const CellNormalModeContainer = styled.div`
display: flex;
align-items: center;
width: calc(100% - ${(props) => props.theme.spacing(5)});
width: 100%;
height: 100%;
overflow: hidden;

View File

@ -47,7 +47,9 @@ export function EditableCell({
onOutsideClick={onOutsideClick}
/>
) : (
<CellNormalModeContainer>{nonEditModeContent}</CellNormalModeContainer>
<CellNormalModeContainer>
<>{nonEditModeContent}</>
</CellNormalModeContainer>
)}
</CellBaseContainer>
);

View File

@ -2,6 +2,7 @@ import styled from '@emotion/styled';
import { ChangeEvent, ComponentType, useRef, useState } from 'react';
import { EditableCell } from './EditableCell';
import { textInputStyle } from '../../layout/styles/themes';
import { CellCommentChip } from '../comments/CellCommentChip';
export type EditableChipProps = {
placeholder?: string;
@ -10,6 +11,8 @@ export type EditableChipProps = {
changeHandler: (updated: string) => void;
editModeHorizontalAlign?: 'left' | 'right';
ChipComponent: ComponentType<{ name: string; picture: string }>;
commentCount?: number;
onCommentClick?: (event: React.MouseEvent<HTMLDivElement>) => void;
};
// TODO: refactor
@ -23,8 +26,7 @@ const StyledInplaceInput = styled.input`
const StyledInplaceShow = styled.div`
display: flex;
padding-left: ${(props) => props.theme.spacing(1)};
padding-right: ${(props) => props.theme.spacing(1)};
width: 100%;
&::placeholder {
font-weight: 'bold';
@ -39,11 +41,22 @@ function EditableChip({
picture,
editModeHorizontalAlign,
ChipComponent,
commentCount,
onCommentClick,
}: EditableChipProps) {
const inputRef = useRef<HTMLInputElement>(null);
const [inputValue, setInputValue] = useState(value);
const [isEditMode, setIsEditMode] = useState(false);
const showComment = commentCount ? commentCount > 0 : false;
function handleCommentClick(event: React.MouseEvent<HTMLDivElement>) {
event.preventDefault();
event.stopPropagation();
onCommentClick?.(event);
}
return (
<EditableCell
onOutsideClick={() => setIsEditMode(false)}
@ -63,9 +76,17 @@ function EditableChip({
/>
}
nonEditModeContent={
<StyledInplaceShow>
<ChipComponent name={inputValue} picture={picture} />
</StyledInplaceShow>
<>
<StyledInplaceShow>
<ChipComponent name={inputValue} picture={picture} />
</StyledInplaceShow>
{showComment && (
<CellCommentChip
count={commentCount ?? 0}
onClick={handleCommentClick}
/>
)}
</>
}
></EditableCell>
);

View File

@ -1,6 +1,8 @@
import { useState } from 'react';
import PersonChip from '../chips/PersonChip';
import { EditableDoubleText } from '../editable-cell/EditableDoubleText';
import { CellCommentChip } from '../comments/CellCommentChip';
import styled from '@emotion/styled';
type OwnProps = {
firstname: string;
@ -8,6 +10,13 @@ type OwnProps = {
onChange: (firstname: string, lastname: string) => void;
};
const StyledDiv = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
`;
export function EditablePeopleFullName({
firstname,
lastname,
@ -26,6 +35,12 @@ export function EditablePeopleFullName({
onChange(firstValue, secondValue);
}
function handleCommentClick(event: React.MouseEvent<HTMLDivElement>) {
event.preventDefault();
event.stopPropagation();
console.log('comment clicked');
}
return (
<EditableDoubleText
firstValue={firstnameValue}
@ -33,7 +48,14 @@ export function EditablePeopleFullName({
firstValuePlaceholder="First name"
secondValuePlaceholder="Last name"
onChange={handleDoubleTextChange}
nonEditModeContent={<PersonChip name={firstname + ' ' + lastname} />}
nonEditModeContent={
<>
<StyledDiv>
<PersonChip name={firstname + ' ' + lastname} />
</StyledDiv>
<CellCommentChip count={12} onClick={handleCommentClick} />
</>
}
/>
);
}

View File

@ -3,6 +3,8 @@ import { EntityTableActionBarButton } from './EntityTableActionBarButton';
import { useOpenRightDrawer } from '../../../modules/ui/layout/right-drawer/hooks/useOpenRightDrawer';
export function TableActionBarButtonToggleComments() {
// TODO: here it would be nice to access the table context
// But let's see when we have custom entities and properties
const openRightDrawer = useOpenRightDrawer();
async function handleButtonClick() {

View File

@ -0,0 +1,18 @@
import { useRecoilState } from 'recoil';
import { useOpenRightDrawer } from '../../ui/layout/right-drawer/hooks/useOpenRightDrawer';
import { CommentableEntity } from '../types/CommentableEntity';
import { commentableEntityArrayState } from '../states/commentableEntityArrayState';
export function useOpenCommentRightDrawer() {
const openRightDrawer = useOpenRightDrawer();
const [, setCommentableEntityArray] = useRecoilState(
commentableEntityArrayState,
);
return function openCommentRightDrawer(
commentableEntityArray: CommentableEntity[],
) {
setCommentableEntityArray(commentableEntityArray);
openRightDrawer('comments');
};
}

View File

@ -0,0 +1,7 @@
import { atom } from 'recoil';
import { CommentableEntity } from '../types/CommentableEntity';
export const commentableEntityArrayState = atom<CommentableEntity[]>({
key: 'comments/commentable-entity-array',
default: [],
});

View File

@ -0,0 +1,6 @@
import { CommentableType } from '../../../generated/graphql';
export type CommentableEntity = {
type: keyof typeof CommentableType;
id: string;
};

View File

@ -12,12 +12,10 @@ import ColumnHead from '../../components/table/ColumnHead';
import { SelectAllCheckbox } from '../../components/table/SelectAllCheckbox';
import EditableDate from '../../components/editable-cell/EditableDate';
import EditableRelation from '../../components/editable-cell/EditableRelation';
import EditableChip from '../../components/editable-cell/EditableChip';
import EditableText from '../../components/editable-cell/EditableText';
import PersonChip, {
PersonChipPropsType,
} from '../../components/chips/PersonChip';
import CompanyChip from '../../components/chips/CompanyChip';
import {
TbBuilding,
TbCalendar,
@ -27,8 +25,8 @@ import {
TbUser,
} from 'react-icons/tb';
import { QueryMode } from '../../generated/graphql';
import { getLogoUrlFromDomainName } from '../../services/utils';
import { CheckboxCell } from '../../components/table/CheckboxCell';
import { CompanyEditableNameChipCell } from '../../components/companies/CompanyEditableNameCell';
const columnHelper = createColumnHelper<Company>();
@ -59,17 +57,7 @@ export const useCompaniesColumns = () => {
<ColumnHead viewName="Name" viewIcon={<TbBuilding size={16} />} />
),
cell: (props) => (
<EditableChip
value={props.row.original.name || ''}
placeholder="Name"
picture={getLogoUrlFromDomainName(props.row.original.domainName)}
changeHandler={(value: string) => {
const company = props.row.original;
company.name = value;
updateCompany(company);
}}
ChipComponent={CompanyChip}
/>
<CompanyEditableNameChipCell company={props.row.original} />
),
size: 120,
}),

View File

@ -49,16 +49,18 @@ export const usePeopleColumns = () => {
<ColumnHead viewName="People" viewIcon={<TbUser size={16} />} />
),
cell: (props) => (
<EditablePeopleFullName
firstname={props.row.original.firstname || ''}
lastname={props.row.original.lastname || ''}
onChange={async (firstName: string, lastName: string) => {
const person = props.row.original;
person.firstname = firstName;
person.lastname = lastName;
await updatePerson(person);
}}
/>
<>
<EditablePeopleFullName
firstname={props.row.original.firstname || ''}
lastname={props.row.original.lastname || ''}
onChange={async (firstName: string, lastName: string) => {
const person = props.row.original;
person.firstname = firstName;
person.lastname = lastName;
await updatePerson(person);
}}
/>
</>
),
size: 210,
}),