Add "show company / people" view and "Notes" concept (#528)

* Begin adding show view and refactoring threads to become notes

* Progress on design

* Progress redesign timeline

* Dropdown button, design improvement

* Open comment thread edit mode in drawer

* Autosave local storage and commentThreadcount

* Improve display and fix missing key issue

* Remove some hardcoded CSS properties

* Create button

* Split company show into ui/business + fix eslint

* Fix font weight

* Begin auto-save on edit mode

* Save server-side query result to Apollo cache

* Fix save behavior

* Refetch timeline after creating note

* Rename createCommentThreadWithComment

* Improve styling

* Revert "Improve styling"

This reverts commit 9fbbf2db006e529330edc64f3eb8ff9ecdde6bb0.

* Improve CSS styling

* Bring back border radius inadvertently removed

* padding adjustment

* Improve blocknote design

* Improve edit mode display

* Remove Comments.tsx

* Remove irrelevant comment stories

* Removed un-necessary panel component

* stop using fragment, move trash icon

* Add a basic story for CompanyShow

* Add a basic People show view

* Fix storybook tests

* Add very basic Person story

* Refactor PR1

* Refactor part 2

* Refactor part 3

* Refactor part 4

* Fix tests

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Félix Malfait
2023-07-10 07:25:34 +02:00
committed by GitHub
parent ca180acf9f
commit 94a913a41f
191 changed files with 5390 additions and 721 deletions
@@ -0,0 +1,94 @@
import React, { useState } from 'react';
import styled from '@emotion/styled';
import { IconChevronDown } from '@/ui/icons/index';
type ButtonProps = React.ComponentProps<'button'>;
export type DropdownOptionType = {
label: string;
icon: React.ReactNode;
};
type Props = {
options: DropdownOptionType[];
onSelection: (value: DropdownOptionType) => void;
} & ButtonProps;
const StyledButton = styled.button<ButtonProps>`
align-items: center;
background: ${({ theme }) => theme.background.tertiary};
border: 1px solid ${({ theme }) => theme.border.color.medium};
border-radius: 4px;
color: ${({ theme }) => theme.font.color.secondary};
display: flex;
font-size: ${({ theme }) => theme.font.size.md};
font-weight: ${({ theme }) => theme.font.weight.medium};
gap: 8px;
height: 24px;
line-height: ${({ theme }) => theme.text.lineHeight.lg};
padding: 3px 8px;
svg {
align-items: center;
display: flex;
height: 14px;
justify-content: center;
width: 14px;
}
`;
const DropdownContainer = styled.div`
position: relative;
`;
const DropdownMenu = styled.div`
display: flex;
flex-direction: column;
margin-top: -2px;
position: absolute;
`;
export function DropdownButton({
options,
onSelection,
...buttonProps
}: Props) {
const [isOpen, setIsOpen] = useState(false);
const [selectedOption, setSelectedOption] = useState(options[0]);
if (!options.length) {
throw new Error('You must provide at least one option.');
}
const handleSelect =
(option: DropdownOptionType) =>
(event: React.MouseEvent<HTMLButtonElement>) => {
event.preventDefault();
onSelection(option);
setSelectedOption(option);
setIsOpen(false);
};
return (
<DropdownContainer>
<StyledButton onClick={() => setIsOpen(!isOpen)} {...buttonProps}>
{selectedOption.icon}
{selectedOption.label}
{options.length > 1 && <IconChevronDown />}
</StyledButton>
{isOpen && (
<DropdownMenu>
{options
.filter((option) => option.label !== selectedOption.label)
.map((option, index) => (
<StyledButton key={index} onClick={handleSelect(option)}>
{option.icon}
{option.label}
</StyledButton>
))}
</DropdownMenu>
)}
</DropdownContainer>
);
}