Enable column edition, and fix ordering (#683)

* Enable column edition, and fix ordering

* Move queries to services

* Add total amounts for board columns

* Refactor totals selector as a family

* Fix 0-index issue

* Lint

* Rename selector

* Remove useless header

* Address PR comments

* Optimistically update board column names
This commit is contained in:
Emilien Chauvet
2023-07-15 19:32:16 -07:00
committed by GitHub
parent be21392737
commit 91c8068db1
43 changed files with 299 additions and 88 deletions

View File

@ -12,6 +12,7 @@ export const StyledBoard = styled.div`
export type BoardPipelineStageColumn = {
pipelineStageId: string;
title: string;
index: number;
colorCode?: string;
pipelineProgressIds: string[];
};

View File

@ -1,6 +1,10 @@
import React from 'react';
import React, { ChangeEvent } from 'react';
import styled from '@emotion/styled';
import { debounce } from '@/utils/debounce';
import { EditColumnTitleInput } from './EditColumnTitleInput';
export const StyledColumn = styled.div`
background-color: ${({ theme }) => theme.background.primary};
display: flex;
@ -26,21 +30,53 @@ export const StyledColumnTitle = styled.h3`
margin-bottom: ${({ theme }) => theme.spacing(2)};
`;
export const StyledAmount = styled.div`
const StyledAmount = styled.div`
color: ${({ theme }) => theme.font.color.light};
`;
type OwnProps = {
colorCode?: string;
title: string;
pipelineStageId?: string;
onTitleEdit: (title: string) => void;
totalAmount?: number;
children: React.ReactNode;
};
export function BoardColumn({ colorCode, title, children }: OwnProps) {
export function BoardColumn({
colorCode,
title,
onTitleEdit,
totalAmount,
children,
}: OwnProps) {
const [isEditing, setIsEditing] = React.useState(false);
const [internalValue, setInternalValue] = React.useState(title);
function toggleEditMode() {
setIsEditing(!isEditing);
}
const debouncedOnUpdate = debounce(onTitleEdit, 200);
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
setInternalValue(event.target.value);
debouncedOnUpdate(event.target.value);
};
return (
<StyledColumn>
<StyledHeader>
<StyledColumnTitle color={colorCode}> {title}</StyledColumnTitle>
<StyledHeader onClick={toggleEditMode}>
{isEditing ? (
<EditColumnTitleInput
color={colorCode}
toggleEditMode={toggleEditMode}
value={internalValue}
onChange={handleChange}
/>
) : (
<StyledColumnTitle color={colorCode}> {title}</StyledColumnTitle>
)}
{!!totalAmount && <StyledAmount>${totalAmount}</StyledAmount>}
</StyledHeader>
{children}
</StyledColumn>

View File

@ -0,0 +1,3 @@
export enum ColumnHotkeyScope {
EditColumnName = 'EditColumnNameHotkeyScope',
}

View File

@ -0,0 +1,53 @@
import styled from '@emotion/styled';
import { useScopedHotkeys } from '@/lib/hotkeys/hooks/useScopedHotkeys';
import { useSetHotkeyScope } from '@/lib/hotkeys/hooks/useSetHotkeyScope';
import { ColumnHotkeyScope } from './ColumnHotkeyScope';
const StyledEditTitleInput = styled.input`
background-color: transparent;
border: none;
&::placeholder,
&::-webkit-input-placeholder {
color: ${({ theme }) => theme.font.color.light};
font-family: ${({ theme }) => theme.font.family};
font-weight: ${({ theme }) => theme.font.weight.medium};
}
color: ${({ color }) => color};
&:focus {
color: ${({ color }) => color};
font-weight: ${({ theme }) => theme.font.weight.medium};
line-height: ${({ theme }) => theme.text.lineHeight};
}
margin: 0;
margin-bottom: ${({ theme }) => theme.spacing(2)};
outline: none;
`;
export function EditColumnTitleInput({
color,
value,
onChange,
toggleEditMode,
}: {
color?: string;
value: string;
onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
toggleEditMode: () => void;
}) {
const setHotkeyScope = useSetHotkeyScope();
setHotkeyScope(ColumnHotkeyScope.EditColumnName, { goto: false });
useScopedHotkeys('enter', toggleEditMode, ColumnHotkeyScope.EditColumnName);
useScopedHotkeys('esc', toggleEditMode, ColumnHotkeyScope.EditColumnName);
return (
<StyledEditTitleInput
placeholder={'Enter column name'}
color={color}
autoFocus
value={value}
onChange={onChange}
/>
);
}