arch: move web folder into api & move api to top level

This commit is contained in:
Jordan Knott
2020-07-04 18:08:37 -05:00
parent eaffaa70df
commit e5d5e6da01
354 changed files with 20 additions and 1557 deletions

View File

@ -0,0 +1,177 @@
import React, { createRef } from 'react';
import { action } from '@storybook/addon-actions';
import Card from 'shared/components/Card';
import CardComposer from 'shared/components/CardComposer';
import LabelColors from 'shared/constants/labelColors';
import List, { ListCards } from '.';
export default {
component: List,
title: 'List',
parameters: {
backgrounds: [
{ name: 'white', value: '#ffffff', default: true },
{ name: 'gray', value: '#f8f8f8' },
],
},
};
const labelData: Array<ProjectLabel> = [
{
id: 'development',
name: 'Development',
createdDate: new Date().toString(),
labelColor: {
id: '1',
colorHex: LabelColors.BLUE,
name: 'blue',
position: 1,
},
},
];
const createCard = () => {
const $ref = createRef<HTMLDivElement>();
return (
<Card
taskID="1"
taskGroupID="1"
description="hello!"
ref={$ref}
title="Hello, world"
onClick={action('on click')}
onContextMenu={action('on context click')}
watched
labels={labelData}
checklists={{ complete: 1, total: 4 }}
dueDate={{ isPastDue: false, formattedDate: 'Oct 26, 2020' }}
/>
);
};
export const Default = () => {
return (
<List
id=""
name="General"
isComposerOpen={false}
onSaveName={action('on save name')}
onOpenComposer={action('on open composer')}
onExtraMenuOpen={action('extra menu open')}
>
<ListCards>
<CardComposer
onClose={() => {
console.log('close!');
}}
onCreateCard={name => {
console.log(name);
}}
isOpen={false}
/>
</ListCards>
</List>
);
};
export const WithCardComposer = () => {
return (
<List
id="1"
name="General"
isComposerOpen
onSaveName={action('on save name')}
onOpenComposer={action('on open composer')}
onExtraMenuOpen={action('extra menu open')}
>
<ListCards>
<CardComposer
onClose={() => {
console.log('close!');
}}
onCreateCard={name => {
console.log(name);
}}
isOpen
/>
</ListCards>
</List>
);
};
export const WithCard = () => {
const $cardRef: any = createRef();
return (
<List
id="1"
name="General"
isComposerOpen={false}
onSaveName={action('on save name')}
onOpenComposer={action('on open composer')}
onExtraMenuOpen={action('extra menu open')}
>
<ListCards>
<Card
taskID="1"
taskGroupID="1"
description="hello!"
ref={$cardRef}
title="Hello, world"
onClick={action('on click')}
onContextMenu={action('on context click')}
watched
labels={labelData}
checklists={{ complete: 1, total: 4 }}
dueDate={{ isPastDue: false, formattedDate: 'Oct 26, 2020' }}
/>
<CardComposer
onClose={() => {
console.log('close!');
}}
onCreateCard={name => {
console.log(name);
}}
isOpen={false}
/>
</ListCards>
</List>
);
};
export const WithCardAndComposer = () => {
const $cardRef: any = createRef();
return (
<List
id="1"
name="General"
isComposerOpen
onSaveName={action('on save name')}
onOpenComposer={action('on open composer')}
onExtraMenuOpen={action('extra menu open')}
>
<ListCards>
<Card
taskID="1"
taskGroupID="1"
description="hello!"
ref={$cardRef}
title="Hello, world"
onClick={action('on click')}
onContextMenu={action('on context click')}
watched
labels={labelData}
checklists={{ complete: 1, total: 4 }}
dueDate={{ isPastDue: false, formattedDate: 'Oct 26, 2020' }}
/>
<CardComposer
onClose={() => {
console.log('close!');
}}
onCreateCard={name => {
console.log(name);
}}
isOpen
/>
</ListCards>
</List>
);
};

View File

@ -0,0 +1,128 @@
import styled, { css } from 'styled-components';
import TextareaAutosize from 'react-autosize-textarea';
import { mixin } from 'shared/utils/styles';
export const Container = styled.div`
width: 272px;
margin: 0 4px;
height: 100%;
box-sizing: border-box;
display: inline-block;
vertical-align: top;
white-space: nowrap;
`;
export const AddCardContainer = styled.div`
min-height: 38px;
max-height: 38px;
display: ${props => (props.hidden ? 'none' : 'flex')};
justify-content: space-between;
`;
export const AddCardButton = styled.a`
border-radius: 3px;
color: #c2c6dc;
display: flex;
align-items: center;
cursor: pointer;
flex: 1 0 auto;
margin: 2px 8px 8px 8px;
padding: 4px 8px;
position: relative;
text-decoration: none;
user-select: none;
&:hover {
color: #c2c6dc;
text-decoration: none;
background: rgb(115, 103, 240);
}
`;
export const Wrapper = styled.div`
// background-color: #ebecf0;
// background: rgb(244, 245, 247);
background: #10163a;
color: #c2c6dc;
border-radius: 5px;
box-sizing: border-box;
display: flex;
flex-direction: column;
max-height: 100%;
position: relative;
white-space: normal;
`;
export const HeaderEditTarget = styled.div<{ isHidden: boolean }>`
cursor: pointer;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: ${props => (props.isHidden ? 'none' : 'block')};
`;
export const HeaderName = styled(TextareaAutosize)`
font-family: 'Droid Sans';
font-size: 14px;
border: none;
resize: none;
overflow: hidden;
overflow-wrap: break-word;
background: transparent;
border-radius: 3px;
box-shadow: none;
font-weight: 600;
margin: -4px 0;
padding: 4px 8px;
letter-spacing: normal;
word-spacing: normal;
text-transform: none;
text-indent: 0px;
text-shadow: none;
flex-direction: column;
text-align: start;
color: #c2c6dc;
`;
export const Header = styled.div<{ isEditing: boolean }>`
flex: 0 0 auto;
padding: 10px 8px;
position: relative;
min-height: 20px;
padding-right: 36px;
${props =>
props.isEditing &&
css`
& ${HeaderName} {
box-shadow: rgb(115, 103, 240) 0px 0px 0px 1px;
}
`}
`;
export const AddCardButtonText = styled.span`
padding-left: 5px;
font-family: 'Droid Sans';
`;
export const ListCards = styled.div`
margin: 0 4px;
padding: 0 4px;
flex: 1 1 auto;
min-height: 45px;
overflow-y: auto;
overflow-x: hidden;
`;
export const ListExtraMenuButtonWrapper = styled.div`
cursor: pointer;
position: absolute;
right: 4px;
top: 4px;
z-index: 1;
padding: 6px;
padding-bottom: 0;
`;

View File

@ -0,0 +1,125 @@
import React, { useState, useRef } from 'react';
import useOnEscapeKeyDown from 'shared/hooks/onEscapeKeyDown';
import { Plus, Ellipsis } from 'shared/icons';
import {
Container,
Wrapper,
Header,
HeaderName,
HeaderEditTarget,
AddCardContainer,
AddCardButton,
AddCardButtonText,
ListCards,
ListExtraMenuButtonWrapper,
} from './Styles';
type Props = {
children: React.ReactNode;
id: string;
name: string;
onSaveName: (name: string) => void;
isComposerOpen: boolean;
onOpenComposer: (id: string) => void;
wrapperProps?: any;
headerProps?: any;
index?: number;
onExtraMenuOpen: (taskGroupID: string, $targetRef: React.RefObject<HTMLElement>) => void;
};
const List = React.forwardRef(
(
{
id,
name,
onSaveName,
isComposerOpen,
onOpenComposer,
children,
wrapperProps,
headerProps,
onExtraMenuOpen,
}: Props,
$wrapperRef: any,
) => {
const [listName, setListName] = useState(name);
const [isEditingTitle, setEditingTitle] = useState(false);
const $listNameRef = useRef<HTMLTextAreaElement>(null);
const $extraActionsRef = useRef<HTMLDivElement>(null);
const onClick = () => {
setEditingTitle(true);
if ($listNameRef && $listNameRef.current) {
$listNameRef.current.select();
}
};
const onBlur = () => {
setEditingTitle(false);
onSaveName(listName);
};
const onEscape = () => {
if ($listNameRef && $listNameRef.current) {
$listNameRef.current.blur();
}
};
const onChange = (event: React.FormEvent<HTMLTextAreaElement>): void => {
setListName(event.currentTarget.value);
};
const onKeyDown = (e: React.KeyboardEvent) => {
if (e.key === 'Enter') {
e.preventDefault();
if ($listNameRef && $listNameRef.current) {
$listNameRef.current.blur();
}
}
};
const handleExtraMenuOpen = () => {
if ($extraActionsRef && $extraActionsRef.current) {
onExtraMenuOpen(id, $extraActionsRef);
}
};
useOnEscapeKeyDown(isEditingTitle, onEscape);
return (
<Container ref={$wrapperRef} {...wrapperProps}>
<Wrapper>
<Header {...headerProps} isEditing={isEditingTitle}>
<HeaderEditTarget onClick={onClick} isHidden={isEditingTitle} />
<HeaderName
ref={$listNameRef}
onBlur={onBlur}
onChange={onChange}
onKeyDown={onKeyDown}
spellCheck={false}
value={listName}
/>
<ListExtraMenuButtonWrapper ref={$extraActionsRef} onClick={handleExtraMenuOpen}>
<Ellipsis size={16} color="#c2c6dc" />
</ListExtraMenuButtonWrapper>
</Header>
{children && children}
<AddCardContainer hidden={isComposerOpen}>
<AddCardButton onClick={() => onOpenComposer(id)}>
<Plus size={12} color="#c2c6dc" />
<AddCardButtonText>Add another card</AddCardButtonText>
</AddCardButton>
</AddCardContainer>
</Wrapper>
</Container>
);
},
);
List.defaultProps = {
children: null,
isComposerOpen: false,
wrapperProps: {},
headerProps: {},
};
List.displayName = 'List';
export default List;
export { ListCards };