feat: add pre commit hook to lint frontend & fix warnings

This commit is contained in:
Jordan Knott
2020-08-23 17:29:06 -05:00
committed by Jordan Knott
parent 8ce19a1ceb
commit 46e724e731
46 changed files with 256 additions and 730 deletions
@@ -1,10 +1,10 @@
import React, { useRef } from 'react';
import Admin from '.';
import { theme } from 'App/ThemeStyles';
import NormalizeStyles from 'App/NormalizeStyles';
import BaseStyles from 'App/BaseStyles';
import React from 'react';
import { ThemeProvider } from 'styled-components';
import { action } from '@storybook/addon-actions';
import theme from 'App/ThemeStyles';
import NormalizeStyles from 'App/NormalizeStyles';
import BaseStyles from 'App/BaseStyles';
import Admin from '.';
export default {
component: Admin,
+14 -109
View File
@@ -1,15 +1,13 @@
import React, { useState, useRef } from 'react';
import { UserPlus, Checkmark } from 'shared/icons';
import styled, { css } from 'styled-components';
import TaskAssignee from 'shared/components/TaskAssignee';
import Select from 'shared/components/Select';
import { User, Plus, Lock, Pencil, Trash } from 'shared/icons';
import { User, UserPlus, Checkmark } from 'shared/icons';
import { usePopup, Popup } from 'shared/components/PopupMenu';
import { RoleCode, useUpdateUserRoleMutation } from 'shared/generated/graphql';
import Input from 'shared/components/Input';
import Member from 'shared/components/Member';
import Button from 'shared/components/Button';
import NOOP from 'shared/utils/noop';
export const RoleCheckmark = styled(Checkmark)`
padding-left: 4px;
@@ -69,6 +67,7 @@ export const MiniProfileActionItem = styled.span<{ disabled?: boolean }>`
}
`}
`;
export const Content = styled.div`
padding: 0 12px 12px;
`;
@@ -100,6 +99,7 @@ export const RemoveMemberButton = styled(Button)`
padding: 6px 12px;
width: 100%;
`;
type TeamRoleManagerPopupProps = {
user: User;
users: Array<User>;
@@ -120,7 +120,7 @@ const TeamRoleManagerPopup: React.FC<TeamRoleManagerPopupProps> = ({
onChangeRole,
}) => {
const { hidePopup, setTab } = usePopup();
const [userPass, setUserPass] = useState({ pass: '', passConfirm: '' });
const [userPass] = useState({ pass: '', passConfirm: '' });
const [deleteUser, setDeleteUser] = useState<{ label: string; value: string } | null>(null);
const hasOwned = user.owned.projects.length !== 0 || user.owned.teams.length !== 0;
return (
@@ -195,7 +195,7 @@ const TeamRoleManagerPopup: React.FC<TeamRoleManagerPopupProps> = ({
{user.role && user.role.code === 'owner' && (
<>
<Separator />
<WarningText>You can't change roles because there must be an owner.</WarningText>
<WarningText>You can not change roles because there must be an owner.</WarningText>
</>
)}
</MiniProfileActions>
@@ -209,7 +209,7 @@ const TeamRoleManagerPopup: React.FC<TeamRoleManagerPopupProps> = ({
<>
<DeleteDescription>{`The user is the owner of ${user.owned.projects.length} projects & ${user.owned.teams.length} teams.`}</DeleteDescription>
<DeleteDescription>
Choose a new user to take over ownership of this user's teams & projects.
Choose a new user to take over ownership of the users teams & projects.
</DeleteDescription>
<UserSelect
onChange={v => setDeleteUser(v)}
@@ -239,7 +239,7 @@ const TeamRoleManagerPopup: React.FC<TeamRoleManagerPopupProps> = ({
Removing this user from the organzation will remove them from assigned tasks, projects, and teams.
</DeleteDescription>
<DeleteDescription>{`The user is the owner of ${user.owned.projects.length} projects & ${user.owned.teams.length} teams.`}</DeleteDescription>
<UserSelect onChange={() => {}} value={null} options={users.map(u => ({ label: u.fullName, value: u.id }))} />
<UserSelect onChange={NOOP} value={null} options={users.map(u => ({ label: u.fullName, value: u.id }))} />
<UserPassConfirmButton
onClick={() => {
// onDeleteUser();
@@ -253,7 +253,7 @@ const TeamRoleManagerPopup: React.FC<TeamRoleManagerPopupProps> = ({
<Popup title="Reset password?" onClose={() => hidePopup()} tab={3}>
<Content>
<DeleteDescription>
You can either set the user's new password directly or send the user an email allowing them to reset their
You can either set the users new password directly or send the user an email allowing them to reset their
own password.
</DeleteDescription>
<UserPassBar>
@@ -291,6 +291,7 @@ const TeamRoleManagerPopup: React.FC<TeamRoleManagerPopupProps> = ({
</>
);
};
const UserSelect = styled(Select)`
margin: 8px 0;
padding: 8px 0;
@@ -299,6 +300,7 @@ const UserSelect = styled(Select)`
const NewUserPassInput = styled(Input)`
margin: 8px 0;
`;
const InviteMemberButton = styled(Button)`
padding: 7px 12px;
`;
@@ -307,6 +309,7 @@ const UserPassBar = styled.div`
display: flex;
padding-top: 8px;
`;
const UserPassConfirmButton = styled(Button)`
width: 100%;
padding: 7px 12px;
@@ -397,104 +400,6 @@ const MemberListWrapper = styled.div`
flex: 1 1;
`;
const Root = styled.div`
.ag-theme-material {
--ag-foreground-color: #c2c6dc;
--ag-secondary-foreground-color: #c2c6dc;
--ag-background-color: transparent;
--ag-header-background-color: transparent;
--ag-header-foreground-color: #c2c6dc;
--ag-border-color: #414561;
--ag-row-hover-color: #262c49;
--ag-header-cell-hover-background-color: #262c49;
--ag-checkbox-unchecked-color: #c2c6dc;
--ag-checkbox-indeterminate-color: rgba(115, 103, 240);
--ag-selected-row-background-color: #262c49;
--ag-material-primary-color: rgba(115, 103, 240);
--ag-material-accent-color: rgba(115, 103, 240);
}
.ag-theme-material ::-webkit-scrollbar {
width: 12px;
}
.ag-theme-material ::-webkit-scrollbar-track {
background: #262c49;
border-radius: 20px;
}
.ag-theme-material ::-webkit-scrollbar-thumb {
background: #7367f0;
border-radius: 20px;
}
.ag-header-cell-text {
color: #fff;
font-weight: 700;
}
`;
const Header = styled.div`
border-bottom: 1px solid #e2e2e2;
flex-direction: row;
box-sizing: border-box;
display: flex;
white-space: nowrap;
width: 100%;
overflow: hidden;
background: transparent;
border-bottom-color: #414561;
color: #fff;
height: 112px;
min-height: 112px;
`;
const EditUserIcon = styled(Pencil)``;
const LockUserIcon = styled(Lock)``;
const DeleteUserIcon = styled(Trash)``;
type ActionButtonProps = {
onClick: ($target: React.RefObject<HTMLElement>) => void;
};
const ActionButtonWrapper = styled.div`
margin-right: 8px;
cursor: pointer;
display: inline-flex;
`;
const ActionButton: React.FC<ActionButtonProps> = ({ onClick, children }) => {
const $wrapper = useRef<HTMLDivElement>(null);
return (
<ActionButtonWrapper onClick={() => onClick($wrapper)} ref={$wrapper}>
{children}
</ActionButtonWrapper>
);
};
const ActionButtons = (params: any) => {
return (
<>
<ActionButton onClick={() => {}}>
<EditUserIcon width={16} height={16} />
</ActionButton>
<ActionButton onClick={$target => params.onDeleteUser($target, params.value)}>
<DeleteUserIcon width={16} height={16} />
</ActionButton>
</>
);
};
const Wrapper = styled.div`
background: #eff2f7;
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
`;
const Container = styled.div`
padding: 2.2rem;
display: flex;
@@ -637,7 +542,7 @@ const Admin: React.FC<AdminProps> = ({
'You cant leave because you are the only admin. To make another user an admin, click their avatar, select “Change permissions…”, and select “Admin”.';
const [currentTop, setTop] = useState(initialTab * 48);
const [currentTab, setTab] = useState(initialTab);
const { showPopup, hidePopup } = usePopup();
const { showPopup } = usePopup();
const $tabNav = useRef<HTMLDivElement>(null);
const [updateUserRole] = useUpdateUserRoleMutation();
@@ -690,7 +595,7 @@ const Admin: React.FC<AdminProps> = ({
const projectTotal = member.owned.projects.length + member.member.projects.length;
return (
<MemberListItem>
<MemberProfile showRoleIcons size={32} onMemberProfile={() => {}} member={member} />
<MemberProfile showRoleIcons size={32} onMemberProfile={NOOP} member={member} />
<MemberListItemDetails>
<MemberItemName>{member.fullName}</MemberItemName>
<MemberItemUsername>{`@${member.username}`}</MemberItemUsername>
@@ -2,7 +2,7 @@ import React from 'react';
import { action } from '@storybook/addon-actions';
import BaseStyles from 'App/BaseStyles';
import NormalizeStyles from 'App/NormalizeStyles';
import { theme } from 'App/ThemeStyles';
import theme from 'App/ThemeStyles';
import styled, { ThemeProvider } from 'styled-components';
import Button from '.';
@@ -1,7 +1,7 @@
import React, { useState, useRef, useEffect } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faPencilAlt, faList } from '@fortawesome/free-solid-svg-icons';
import { faClock, faCheckSquare, faEye } from '@fortawesome/free-regular-svg-icons';
import { faClock, faEye } from '@fortawesome/free-regular-svg-icons';
import {
EditorTextarea,
CardMember,
@@ -24,7 +24,6 @@ import {
CardTitle,
CardMembers,
} from './Styles';
import { CheckSquare } from 'shared/icons';
type DueDate = {
isPastDue: boolean;
@@ -209,7 +208,7 @@ const Card = React.forwardRef(
) : (
<CardTitle>
{complete && <CompleteIcon width={16} height={16} />}
{`${title}${position ? ' - ' + position : ''}`}
{`${title}${position ? ` - ${position}` : ''}`}
</CardTitle>
)}
<ListCardBadges>
@@ -236,9 +235,9 @@ const Card = React.forwardRef(
width={8}
height={8}
/>
<ListCardBadgeText
color={checklists.complete === checklists.total ? 'success' : 'normal'}
>{`${checklists.complete}/${checklists.total}`}</ListCardBadgeText>
<ListCardBadgeText color={checklists.complete === checklists.total ? 'success' : 'normal'}>
{`${checklists.complete}/${checklists.total}`}
</ListCardBadgeText>
</ListCardBadge>
)}
</ListCardBadges>
@@ -2,9 +2,10 @@ import React, { useState } from 'react';
import { action } from '@storybook/addon-actions';
import BaseStyles from 'App/BaseStyles';
import NormalizeStyles from 'App/NormalizeStyles';
import { theme } from 'App/ThemeStyles';
import theme from 'App/ThemeStyles';
import produce from 'immer';
import styled, { ThemeProvider } from 'styled-components';
import NOOP from 'shared/utils/noop';
import Checklist, { ChecklistItem } from '.';
export default {
@@ -132,7 +133,7 @@ export const Default = () => {
}}
onToggleItem={onToggleItem}
>
{items.map((item, idx) => (
{items.map(item => (
<ChecklistItem
key={item.id}
wrapperProps={{}}
@@ -141,9 +142,9 @@ export const Default = () => {
itemID={item.id}
name={item.name}
complete={item.complete}
onDeleteItem={() => {}}
onChangeName={() => {}}
onToggleItem={() => {}}
onDeleteItem={NOOP}
onChangeName={NOOP}
onToggleItem={NOOP}
/>
))}
</Checklist>
@@ -1,11 +1,11 @@
import React from 'react';
import BaseStyles from 'App/BaseStyles';
import NormalizeStyles from 'App/NormalizeStyles';
import { theme } from 'App/ThemeStyles';
import theme from 'App/ThemeStyles';
import styled, { ThemeProvider } from 'styled-components';
import { User } from 'shared/icons';
import Input from '.';
import { User } from 'shared/icons';
export default {
component: Input,
@@ -1,8 +1,8 @@
import React, { useRef } from 'react';
import React from 'react';
import { action } from '@storybook/addon-actions';
import BaseStyles from 'App/BaseStyles';
import NormalizeStyles from 'App/NormalizeStyles';
import { theme } from 'App/ThemeStyles';
import theme from 'App/ThemeStyles';
import styled, { ThemeProvider } from 'styled-components';
import { Popup } from '../PopupMenu';
import DueDateManager from '.';
@@ -2,22 +2,13 @@ import React, { useState, useEffect, forwardRef } from 'react';
import moment from 'moment';
import styled from 'styled-components';
import DatePicker from 'react-datepicker';
import { Cross } from 'shared/icons';
import _ from 'lodash';
import {
Wrapper,
ActionWrapper,
RemoveDueDate,
DueDateInput,
DueDatePickerWrapper,
ConfirmAddDueDate,
CancelDueDate,
} from './Styles';
import 'react-datepicker/dist/react-datepicker.css';
import { getYear, getMonth } from 'date-fns';
import { useForm, Controller } from 'react-hook-form';
import NOOP from 'shared/utils/noop';
import { Wrapper, ActionWrapper, RemoveDueDate, DueDateInput, DueDatePickerWrapper, ConfirmAddDueDate } from './Styles';
type DueDateManagerProps = {
task: Task;
@@ -220,7 +211,10 @@ const DueDateManager: React.FC<DueDateManagerProps> = ({ task, onDueDateChange,
</HeaderButton>
<HeaderSelectLabel>
{months[date.getMonth()]}
<HeaderSelect value={getYear(date)} onChange={({ target: { value } }) => changeYear(parseInt(value))}>
<HeaderSelect
value={getYear(date)}
onChange={({ target: { value } }) => changeYear(parseInt(value, 10))}
>
{years.map(option => (
<option key={option} value={option}>
{option}
@@ -255,7 +249,7 @@ const DueDateManager: React.FC<DueDateManagerProps> = ({ task, onDueDateChange,
/>
</DueDatePickerWrapper>
<ActionWrapper>
<ConfirmAddDueDate type="submit" onClick={() => {}}>
<ConfirmAddDueDate type="submit" onClick={NOOP}>
Save
</ConfirmAddDueDate>
<RemoveDueDate
@@ -1,11 +1,11 @@
import React from 'react';
import BaseStyles from 'App/BaseStyles';
import NormalizeStyles from 'App/NormalizeStyles';
import { theme } from 'App/ThemeStyles';
import theme from 'App/ThemeStyles';
import styled, { ThemeProvider } from 'styled-components';
import { User } from 'shared/icons';
import Input from '.';
import { User } from 'shared/icons';
export default {
component: Input,
@@ -3,6 +3,7 @@ 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 NOOP from 'shared/utils/noop';
import List, { ListCards } from '.';
export default {
@@ -60,7 +61,7 @@ export const Default = () => {
onExtraMenuOpen={action('extra menu open')}
>
<ListCards>
<CardComposer onClose={() => {}} onCreateCard={name => {}} isOpen={false} />
<CardComposer onClose={NOOP} onCreateCard={NOOP} isOpen={false} />
</ListCards>
</List>
);
@@ -77,7 +78,7 @@ export const WithCardComposer = () => {
onExtraMenuOpen={action('extra menu open')}
>
<ListCards>
<CardComposer onClose={() => {}} onCreateCard={name => {}} isOpen />
<CardComposer onClose={NOOP} onCreateCard={NOOP} isOpen />
</ListCards>
</List>
);
@@ -108,7 +109,7 @@ export const WithCard = () => {
checklists={{ complete: 1, total: 4 }}
dueDate={{ isPastDue: false, formattedDate: 'Oct 26, 2020' }}
/>
<CardComposer onClose={() => {}} onCreateCard={name => {}} isOpen={false} />
<CardComposer onClose={NOOP} onCreateCard={NOOP} isOpen={false} />
</ListCards>
</List>
);
@@ -138,7 +139,7 @@ export const WithCardAndComposer = () => {
checklists={{ complete: 1, total: 4 }}
dueDate={{ isPastDue: false, formattedDate: 'Oct 26, 2020' }}
/>
<CardComposer onClose={() => {}} onCreateCard={name => {}} isOpen />
<CardComposer onClose={NOOP} onCreateCard={NOOP} isOpen />
</ListCards>
</List>
);
@@ -81,7 +81,7 @@ const SimpleLists: React.FC<SimpleProps> = ({
position: newPosition,
});
} else {
throw { error: 'task group can not be found' };
throw new Error('task group can not be found');
}
} else {
const curTaskGroup = taskGroups.findIndex(
@@ -2,6 +2,7 @@ import React, { useRef } from 'react';
import styled from 'styled-components';
import TaskAssignee from 'shared/components/TaskAssignee';
import { Checkmark } from 'shared/icons';
import NOOP from 'shared/utils/noop';
const CardCheckmark = styled(Checkmark)`
position: absolute;
@@ -76,7 +77,7 @@ const Member: React.FC<MemberProps> = ({
}
}}
>
<TaskAssignee onMemberProfile={() => {}} size={28} member={member} />
<TaskAssignee onMemberProfile={NOOP} size={28} member={member} />
{showName && <CardMemberName>{member.fullName}</CardMemberName>}
{showCheckmark && <CardCheckmark width={12} height={12} />}
</CardMemberWrapper>
@@ -1,5 +1,6 @@
import React, { useState } from 'react';
import { Checkmark } from 'shared/icons';
import Member from 'shared/components/Member';
import {
MemberName,
ProfileIcon,
@@ -12,8 +13,6 @@ import {
BoardMemberListItemContent,
ActiveIconWrapper,
} from './Styles';
import { Checkmark } from 'shared/icons';
import Member from 'shared/components/Member';
type MemberManagerProps = {
availableMembers: Array<TaskUser>;
@@ -160,7 +160,7 @@ const MiniProfile: React.FC<MiniProfileProps> = ({
{user.role && user.role.code === 'owner' && (
<>
<Separator />
<WarningText>You can't change roles because there must be an owner.</WarningText>
<WarningText>You can not change roles because there must be an owner.</WarningText>
</>
)}
</MiniProfileActions>
@@ -1,9 +1,8 @@
import React, { useState, useRef, createRef } from 'react';
import React from 'react';
import { action } from '@storybook/addon-actions';
import styled from 'styled-components';
import NormalizeStyles from 'App/NormalizeStyles';
import BaseStyles from 'App/BaseStyles';
import NOOP from 'shared/utils/noop';
import NewProject from '.';
export default {
@@ -26,7 +25,7 @@ export const Default = () => {
initialTeamID={null}
onCreateProject={action('create project')}
teams={[{ name: 'General', id: 'general', createdAt: '' }]}
onClose={() => {}}
onClose={NOOP}
/>
</>
);
@@ -4,6 +4,19 @@ import { mixin } from 'shared/utils/styles';
import Select from 'react-select';
import { ArrowLeft, Cross } from 'shared/icons';
function getBackgroundColor(isDisabled: boolean, isSelected: boolean, isFocused: boolean) {
if (isDisabled) {
return null;
}
if (isSelected) {
return mixin.darken('#262c49', 0.25);
}
if (isFocused) {
return mixin.darken('#262c49', 0.15);
}
return null;
}
const Overlay = styled.div`
z-index: 10000;
background: #262c49;
@@ -149,14 +162,8 @@ const colourStyles = {
option: (styles: any, { data, isDisabled, isFocused, isSelected }: any) => {
return {
...styles,
backgroundColor: isDisabled
? null
: isSelected
? mixin.darken('#262c49', 0.25)
: isFocused
? mixin.darken('#262c49', 0.15)
: null,
color: isDisabled ? '#ccc' : isSelected ? '#fff' : '#c2c6dc',
backgroundColor: getBackgroundColor(isDisabled, isSelected, isFocused),
color: isDisabled ? '#ccc' : isSelected ? '#fff' : '#c2c6dc', // eslint-disable-line
cursor: isDisabled ? 'not-allowed' : 'default',
':active': {
...styles[':active'],
@@ -1,381 +0,0 @@
import React, { useState, useRef, createRef } from 'react';
import { action } from '@storybook/addon-actions';
import LabelColors from 'shared/constants/labelColors';
import LabelManager from 'shared/components/PopupMenu/LabelManager';
import LabelEditor from 'shared/components/PopupMenu/LabelEditor';
import ListActions from 'shared/components/ListActions';
import MemberManager from 'shared/components/MemberManager';
import DueDateManager from 'shared/components/DueDateManager';
import MiniProfile from 'shared/components/MiniProfile';
import styled from 'styled-components';
import produce from 'immer';
import NormalizeStyles from 'App/NormalizeStyles';
import BaseStyles from 'App/BaseStyles';
import PopupMenu, { PopupProvider, usePopup, Popup } from '.';
export default {
component: PopupMenu,
title: 'PopupMenu',
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 OpenLabelBtn = styled.span``;
type TabProps = {
tab: number;
};
const LabelManagerEditor = () => {
const [labels, setLabels] = useState(labelData);
const [currentLabel, setCurrentLabel] = useState('');
const { setTab } = usePopup();
return (
<>
<Popup title="Labels" tab={0} onClose={action('on close')}>
<LabelManager
labels={labels}
onLabelCreate={() => {
setTab(2);
}}
onLabelEdit={labelId => {
setCurrentLabel(labelId);
setTab(1);
}}
onLabelToggle={labelId => {
setLabels(
produce(labels, draftState => {
const idx = labels.findIndex(label => label.id === labelId);
if (idx !== -1) {
draftState[idx] = { ...draftState[idx] };
}
}),
);
}}
/>
</Popup>
<Popup onClose={action('on close')} title="Edit label" tab={1}>
<LabelEditor
labelColors={[{ id: '1', colorHex: '#c2c6dc', position: 1, name: 'gray' }]}
label={labels.find(label => label.id === currentLabel) ?? null}
onLabelEdit={(_labelId, name, color) => {
setLabels(
produce(labels, draftState => {
const idx = labels.findIndex(label => label.id === currentLabel);
if (idx !== -1) {
draftState[idx] = {
...draftState[idx],
name,
labelColor: {
...draftState[idx].labelColor,
name: color.name ?? '',
colorHex: color.colorHex,
},
};
}
}),
);
setTab(0);
}}
/>
</Popup>
<Popup onClose={action('on close')} title="Create new label" tab={2}>
<LabelEditor
label={null}
labelColors={[{ id: '1', colorHex: '#c2c6dc', position: 1, name: 'gray' }]}
onLabelEdit={(_labelId, name, color) => {
setLabels([
...labels,
{
id: name,
name,
createdDate: new Date().toString(),
labelColor: {
id: color.id,
colorHex: color.colorHex,
name: color.name ?? '',
position: 1,
},
},
]);
setTab(0);
}}
/>
</Popup>
</>
);
};
const OpenLabelsButton = () => {
const $buttonRef = createRef<HTMLButtonElement>();
const [currentLabel, setCurrentLabel] = useState('');
const [labels, setLabels] = useState(labelData);
const { showPopup, setTab } = usePopup();
return (
<OpenLabelBtn
ref={$buttonRef}
onClick={() => {
showPopup($buttonRef, <LabelManagerEditor />);
}}
>
Open
</OpenLabelBtn>
);
};
export const LabelsPopup = () => {
const [isPopupOpen, setPopupOpen] = useState(false);
return (
<PopupProvider>
<OpenLabelsButton />
</PopupProvider>
);
};
export const LabelsLabelEditor = () => {
const [isPopupOpen, setPopupOpen] = useState(false);
return (
<>
{isPopupOpen && (
<PopupMenu
onPrevious={action('on previous')}
title="Change Label"
top={10}
onClose={() => setPopupOpen(false)}
left={10}
>
<LabelEditor
label={labelData[0]}
onLabelEdit={action('label edit')}
labelColors={[{ id: '1', colorHex: '#c2c6dc', position: 1, name: 'gray' }]}
/>
</PopupMenu>
)}
<button type="submit" onClick={() => setPopupOpen(true)}>
Open
</button>
</>
);
};
const initalState = { left: 0, top: 0, isOpen: false };
export const ListActionsPopup = () => {
const $buttonRef = useRef<HTMLButtonElement>(null);
const [popupData, setPopupData] = useState(initalState);
return (
<>
{popupData.isOpen && (
<PopupMenu
title="List Actions"
top={popupData.top}
onClose={() => setPopupData(initalState)}
left={popupData.left}
>
<ListActions taskGroupID="1" onArchiveTaskGroup={action('archive task group')} />
</PopupMenu>
)}
<button
ref={$buttonRef}
type="submit"
onClick={() => {
if ($buttonRef && $buttonRef.current) {
const pos = $buttonRef.current.getBoundingClientRect();
setPopupData({
isOpen: true,
left: pos.left,
top: pos.top + pos.height + 10,
});
}
}}
>
Open
</button>
</>
);
};
export const MemberManagerPopup = () => {
const $buttonRef = useRef<HTMLButtonElement>(null);
const [popupData, setPopupData] = useState(initalState);
return (
<>
<NormalizeStyles />
<BaseStyles />
{popupData.isOpen && (
<PopupMenu title="Members" top={popupData.top} onClose={() => setPopupData(initalState)} left={popupData.left}>
<MemberManager
availableMembers={[
{
id: '1',
fullName: 'Jordan Knott',
profileIcon: { bgColor: null, url: null, initials: null },
},
]}
activeMembers={[]}
onMemberChange={action('member change')}
/>
</PopupMenu>
)}
<span
ref={$buttonRef}
onClick={() => {
if ($buttonRef && $buttonRef.current) {
const pos = $buttonRef.current.getBoundingClientRect();
setPopupData({
isOpen: true,
left: pos.left,
top: pos.top + pos.height + 10,
});
}
}}
>
Open
</span>
</>
);
};
export const DueDateManagerPopup = () => {
const $buttonRef = useRef<HTMLButtonElement>(null);
const [popupData, setPopupData] = useState(initalState);
return (
<>
<NormalizeStyles />
<BaseStyles />
{popupData.isOpen && (
<PopupMenu title="Due Date" top={popupData.top} onClose={() => setPopupData(initalState)} left={popupData.left}>
<DueDateManager
onRemoveDueDate={action('remove due date')}
task={{
id: '1',
taskGroup: { name: 'General', id: '1', position: 1 },
name: 'Hello, world',
position: 1,
labels: [
{
id: 'soft-skills',
assignedDate: new Date().toString(),
projectLabel: {
createdDate: new Date().toString(),
id: 'label-soft-skills',
name: 'Soft Skills',
labelColor: {
id: '1',
name: 'white',
colorHex: '#fff',
position: 1,
},
},
},
],
description: 'hello!',
assigned: [
{
id: '1',
profileIcon: { bgColor: null, url: null, initials: null },
fullName: 'Jordan Knott',
},
],
}}
onCancel={action('cancel')}
onDueDateChange={action('due date change')}
/>
</PopupMenu>
)}
<span
style={{
width: '60px',
textAlign: 'center',
margin: '25px auto',
cursor: 'pointer',
}}
ref={$buttonRef}
onClick={() => {
if ($buttonRef && $buttonRef.current) {
const pos = $buttonRef.current.getBoundingClientRect();
setPopupData({
isOpen: true,
left: pos.left,
top: pos.top + pos.height + 10,
});
}
}}
>
Open
</span>
</>
);
};
export const MiniProfilePopup = () => {
const $buttonRef = useRef<HTMLButtonElement>(null);
const [popupData, setPopupData] = useState(initalState);
return (
<>
<NormalizeStyles />
<BaseStyles />
{popupData.isOpen && (
<PopupMenu
noHeader
title="Due Date"
top={popupData.top}
onClose={() => setPopupData(initalState)}
left={popupData.left}
>
<MiniProfile
user={{
id: '1',
fullName: 'Jordan Knott',
username: 'jordanthedev',
profileIcon: { url: null, bgColor: '#000', initials: 'JK' },
}}
bio="Stuff and things"
onRemoveFromTask={action('mini profile')}
/>
</PopupMenu>
)}
<span
style={{
width: '60px',
textAlign: 'center',
margin: '25px auto',
cursor: 'pointer',
color: '#fff',
background: '#f00',
}}
ref={$buttonRef}
onClick={() => {
if ($buttonRef && $buttonRef.current) {
const pos = $buttonRef.current.getBoundingClientRect();
setPopupData({
isOpen: true,
left: pos.left,
top: pos.top + pos.height + 10,
});
}
}}
>
Open
</span>
</>
);
};
@@ -1,6 +1,5 @@
import styled, { css } from 'styled-components';
import { mixin } from 'shared/utils/styles';
import Input from '../Input';
import ControlledInput from 'shared/components/ControlledInput';
export const Container = styled.div<{
@@ -2,6 +2,7 @@ import React, { useRef, createContext, RefObject, useState, useContext, useEffec
import { Cross, AngleLeft } from 'shared/icons';
import useOnOutsideClick from 'shared/hooks/onOutsideClick';
import { createPortal } from 'react-dom';
import NOOP from 'shared/utils/noop';
import produce from 'immer';
import {
Container,
@@ -52,10 +53,10 @@ PopupContainer.defaultProps = {
};
const PopupContext = createContext<PopupContextState>({
show: () => {},
setTab: () => {},
show: NOOP,
setTab: NOOP,
getCurrentTab: () => 0,
hide: () => {},
hide: NOOP,
});
export const usePopup = () => {
@@ -5,6 +5,7 @@ import CardComposer from 'shared/components/CardComposer';
import LabelColors from 'shared/constants/labelColors';
import List, { ListCards } from 'shared/components/List';
import QuickCardEditor from 'shared/components/QuickCardEditor';
import NOOP from 'shared/utils/noop';
export default {
component: QuickCardEditor,
@@ -71,7 +72,7 @@ export const Default = () => {
isComposerOpen={false}
onSaveName={action('on save name')}
onOpenComposer={action('on open composer')}
onExtraMenuOpen={(taskGroupID, $targetRef) => {}}
onExtraMenuOpen={NOOP}
>
<ListCards>
<Card
@@ -81,7 +82,7 @@ export const Default = () => {
ref={$cardRef}
title={task.name}
onClick={action('on click')}
onContextMenu={e => {
onContextMenu={() => {
setTarget($cardRef);
setEditorOpen(true);
}}
@@ -90,7 +91,7 @@ export const Default = () => {
checklists={{ complete: 1, total: 4 }}
dueDate={{ isPastDue: false, formattedDate: 'Oct 26, 2020' }}
/>
<CardComposer onClose={() => {}} onCreateCard={name => {}} isOpen={false} />
<CardComposer onClose={NOOP} onCreateCard={NOOP} isOpen={false} />
</ListCards>
</List>
</>
@@ -3,6 +3,19 @@ import Select from 'react-select';
import styled from 'styled-components';
import { mixin } from 'shared/utils/styles';
function getBackgroundColor(isDisabled: boolean, isSelected: boolean, isFocused: boolean) {
if (isDisabled) {
return null;
}
if (isSelected) {
return mixin.darken('#262c49', 0.25);
}
if (isFocused) {
return mixin.darken('#262c49', 0.15);
}
return null;
}
const colourStyles = {
control: (styles: any, data: any) => {
return {
@@ -43,14 +56,8 @@ const colourStyles = {
option: (styles: any, { data, isDisabled, isFocused, isSelected }: any) => {
return {
...styles,
backgroundColor: isDisabled
? null
: isSelected
? mixin.darken('#262c49', 0.25)
: isFocused
? mixin.darken('#262c49', 0.15)
: null,
color: isDisabled ? '#ccc' : isSelected ? '#fff' : '#c2c6dc',
backgroundColor: getBackgroundColor(isDisabled, isSelected, isFocused),
color: isDisabled ? '#ccc' : isSelected ? '#fff' : '#c2c6dc', // eslint-disable-line
cursor: isDisabled ? 'not-allowed' : 'default',
':active': {
...styles[':active'],
@@ -2,6 +2,7 @@ import React, { useState, useRef, useEffect } from 'react';
import { Bin, Cross, Plus } from 'shared/icons';
import useOnOutsideClick from 'shared/hooks/onOutsideClick';
import ReactMarkdown from 'react-markdown';
import styled from 'styled-components';
import {
isPositionChanged,
@@ -56,7 +57,6 @@ import {
MetaDetailContent,
} from './Styles';
import Checklist, { ChecklistItem, ChecklistItems } from '../Checklist';
import styled from 'styled-components';
const ChecklistContainer = styled.div``;
@@ -254,7 +254,7 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
const newPosition = getNewDraggablePosition(afterDropDraggables, destination.index);
onChecklistDrop({ ...droppedGroup, position: newPosition });
} else {
throw { error: 'task group can not be found' };
throw new Error('task group can not be found');
}
} else {
const targetChecklist = task.checklists.findIndex(
@@ -314,7 +314,7 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
<TaskMeta>
{task.taskGroup.name && (
<TaskGroupLabel>
in list <TaskGroupLabelName>{task.taskGroup.name}</TaskGroupLabelName>
{`in list ${(<TaskGroupLabelName>{task.taskGroup.name}</TaskGroupLabelName>)}`}
</TaskGroupLabel>
)}
</TaskMeta>
@@ -442,9 +442,9 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
complete={item.complete}
onDeleteItem={onDeleteItem}
onChangeName={onChangeItemName}
onToggleItem={(itemID, complete) =>
onToggleChecklistItem(item.id, complete)
}
onToggleItem={(itemID, complete) => {
onToggleChecklistItem(item.id, complete);
}}
/>
)}
</Draggable>
@@ -5,6 +5,7 @@ import Button from 'shared/components/Button';
import { Taskcafe } from 'shared/icons';
import { NavLink, Link } from 'react-router-dom';
import TaskAssignee from 'shared/components/TaskAssignee';
export const ProjectMember = styled(TaskAssignee)<{ zIndex: number }>`
z-index: ${props => props.zIndex};
position: relative;
@@ -1,5 +1,6 @@
import React, { useRef, useState, useEffect } from 'react';
import { Home, Star, Bell, AngleDown, BarChart, CheckCircle } from 'shared/icons';
import { Link } from 'react-router-dom';
import styled from 'styled-components';
import ProfileIcon from 'shared/components/ProfileIcon';
import TaskAssignee from 'shared/components/TaskAssignee';
@@ -31,7 +32,6 @@ import {
ProjectMember,
ProjectMembers,
} from './Styles';
import { Link } from 'react-router-dom';
const HomeDashboard = styled(Home)``;
@@ -1,17 +1,17 @@
import gql from 'graphql-tag';
export const UPDATE_USER_ROLE_MUTATION = gql`
mutation updateUserRole($userID: UUID!, $roleCode: RoleCode!) {
updateUserRole(input:{userID: $userID, roleCode:$roleCode}) {
user {
id
role {
code
name
mutation updateUserRole($userID: UUID!, $roleCode: RoleCode!) {
updateUserRole(input: { userID: $userID, roleCode: $roleCode }) {
user {
id
role {
code
name
}
}
}
}
}
`;
export default UPDATE_USER_ROLE_MUTATION;
+3 -3
View File
@@ -18,9 +18,9 @@ const AccessAccount = ({ width, height }: Props) => {
gradientTransform="translate(-3.62 1.57)"
gradientUnits="userSpaceOnUse"
>
<stop offset="0" stop-color="gray" stop-opacity=".25" />
<stop offset=".54" stop-color="gray" stop-opacity=".12" />
<stop offset="1" stop-color="gray" stop-opacity=".1" />
<stop offset="0" stopColor="gray" stopOpacity=".25" />
<stop offset=".54" stopColor="gray" stopOpacity=".12" />
<stop offset="1" stopColor="gray" stopOpacity=".1" />
</linearGradient>
<linearGradient
id="b"
+1
View File
@@ -0,0 +1 @@
export default function NOOP() {} // eslint-disable-line @typescript-eslint/no-empty-function