fix: clean up component to fix lint warnings preventing frontend build
This commit is contained in:
parent
3bfce1825c
commit
a188c4b0ca
@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.4.0] - 2021-09-04
|
||||
## [0.3.5] - 2021-09-04
|
||||
|
||||
### Added
|
||||
- Project visibility can now be set to public - meaning anyone can view the project board
|
||||
|
@ -25,6 +25,7 @@
|
||||
],
|
||||
"rules": {
|
||||
"prettier/prettier": "warn",
|
||||
"no-shadow": "off",
|
||||
"no-restricted-syntax": ["error", "LabeledStatement", "WithStatement"],
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
|
@ -62,7 +62,8 @@
|
||||
"react-toastify": "^7.0.4",
|
||||
"rich-markdown-editor": "^11.17.4-0",
|
||||
"styled-components": "^5.2.3",
|
||||
"typescript": "~4.2.4"
|
||||
"typescript": "~4.2.4",
|
||||
"unist-util-visit": "^4.0.0"
|
||||
},
|
||||
"proxy": "http://localhost:3333",
|
||||
"scripts": {
|
||||
|
@ -223,7 +223,7 @@ TODO: add permision check
|
||||
users={data.users}
|
||||
invitedUsers={data.invitedUsers}
|
||||
// canInviteUser={user.roles.org === 'admin'} TODO: add permision check
|
||||
canInviteUser={true}
|
||||
canInviteUser
|
||||
onInviteUser={NOOP}
|
||||
onUpdateUserPassword={() => {
|
||||
hidePopup();
|
||||
|
@ -26,10 +26,10 @@ import useOnOutsideClick from 'shared/hooks/onOutsideClick';
|
||||
import DueDateManager from 'shared/components/DueDateManager';
|
||||
import dayjs from 'dayjs';
|
||||
import useStickyState from 'shared/hooks/useStickyState';
|
||||
import { StaticContext } from 'react-router';
|
||||
import MyTasksSortPopup from './MyTasksSort';
|
||||
import MyTasksStatusPopup from './MyTasksStatus';
|
||||
import TaskEntry from './TaskEntry';
|
||||
import { StaticContext } from 'react-router';
|
||||
|
||||
type TaskRouteProps = {
|
||||
taskID: string;
|
||||
|
@ -44,7 +44,7 @@ const Projects = () => {
|
||||
name="file"
|
||||
style={{ display: 'none' }}
|
||||
ref={$fileUpload}
|
||||
onChange={e => {
|
||||
onChange={(e) => {
|
||||
if (e.target.files) {
|
||||
const fileData = new FormData();
|
||||
fileData.append('file', e.target.files[0]);
|
||||
@ -52,7 +52,7 @@ const Projects = () => {
|
||||
.post('/users/me/avatar', fileData, {
|
||||
withCredentials: true,
|
||||
})
|
||||
.then(res => {
|
||||
.then((res) => {
|
||||
if ($fileUpload && $fileUpload.current) {
|
||||
$fileUpload.current.value = '';
|
||||
refetch();
|
||||
@ -77,7 +77,7 @@ const Projects = () => {
|
||||
}}
|
||||
onChangeUserInfo={(d, done) => {
|
||||
updateUserInfo({
|
||||
variables: { name: d.full_name, bio: d.bio, email: d.email, initials: d.initials },
|
||||
variables: { name: d.fullName, bio: d.bio, email: d.email, initials: d.initials },
|
||||
});
|
||||
toast('User info was saved!');
|
||||
done();
|
||||
|
@ -31,11 +31,11 @@ import produce from 'immer';
|
||||
import NOOP from 'shared/utils/noop';
|
||||
import useStateWithLocalStorage from 'shared/hooks/useStateWithLocalStorage';
|
||||
import localStorage from 'shared/utils/localStorage';
|
||||
import polling from 'shared/utils/polling';
|
||||
import Board, { BoardLoading } from './Board';
|
||||
import Details from './Details';
|
||||
import LabelManagerEditor from './LabelManagerEditor';
|
||||
import UserManagementPopup from './UserManagementPopup';
|
||||
import polling from 'shared/utils/polling';
|
||||
|
||||
type TaskRouteProps = {
|
||||
taskID: string;
|
||||
|
@ -524,7 +524,7 @@ const Members: React.FC<MembersProps> = ({ teamID }) => {
|
||||
members={data.findTeam.members}
|
||||
warning={member.role && member.role.code === 'owner' ? warning : null}
|
||||
// canChangeRole={user.isAdmin(PermissionLevel.TEAM, PermissionObjectType.TEAM, teamID)} TODO: add permission check
|
||||
canChangeRole={true}
|
||||
canChangeRole
|
||||
onChangeRole={(roleCode) => {
|
||||
updateTeamMemberRole({ variables: { userID: member.id, teamID, roleCode } });
|
||||
}}
|
||||
|
@ -10,6 +10,215 @@ import Button from 'shared/components/Button';
|
||||
import NOOP from 'shared/utils/noop';
|
||||
import { mixin } from 'shared/utils/styles';
|
||||
|
||||
const UserSelect = styled(Select)`
|
||||
margin: 8px 0;
|
||||
padding: 8px 0;
|
||||
`;
|
||||
|
||||
const NewUserPassInput = styled(Input)`
|
||||
margin: 8px 0;
|
||||
`;
|
||||
|
||||
const InviteMemberButton = styled(Button)`
|
||||
padding: 7px 12px;
|
||||
`;
|
||||
|
||||
const UserPassBar = styled.div`
|
||||
display: flex;
|
||||
padding-top: 8px;
|
||||
`;
|
||||
|
||||
const UserPassConfirmButton = styled(Button)`
|
||||
width: 100%;
|
||||
padding: 7px 12px;
|
||||
`;
|
||||
|
||||
const UserPassButton = styled(Button)`
|
||||
width: 50%;
|
||||
padding: 7px 12px;
|
||||
& ~ & {
|
||||
margin-left: 6px;
|
||||
}
|
||||
`;
|
||||
|
||||
const MemberItemOptions = styled.div``;
|
||||
|
||||
const MemberItemOption = styled(Button)`
|
||||
padding: 7px 9px;
|
||||
margin: 4px 0 4px 8px;
|
||||
float: left;
|
||||
min-width: 95px;
|
||||
`;
|
||||
|
||||
const MemberList = styled.div`
|
||||
border-top: 1px solid ${(props) => props.theme.colors.border};
|
||||
`;
|
||||
|
||||
const MemberListItem = styled.div`
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid ${(props) => props.theme.colors.border};
|
||||
min-height: 40px;
|
||||
padding: 12px 0 12px 40px;
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
const MemberListItemDetails = styled.div`
|
||||
float: left;
|
||||
flex: 1 0 auto;
|
||||
padding-left: 8px;
|
||||
`;
|
||||
|
||||
const InviteIcon = styled(UserPlus)`
|
||||
padding-right: 4px;
|
||||
`;
|
||||
|
||||
const MemberProfile = styled(TaskAssignee)`
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
left: 0;
|
||||
margin: 0;
|
||||
`;
|
||||
|
||||
const MemberItemName = styled.p`
|
||||
color: ${(props) => props.theme.colors.text.secondary};
|
||||
`;
|
||||
|
||||
const MemberItemUsername = styled.p`
|
||||
color: ${(props) => props.theme.colors.text.primary};
|
||||
`;
|
||||
|
||||
const MemberListHeader = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`;
|
||||
const ListTitle = styled.h3`
|
||||
font-size: 18px;
|
||||
color: ${(props) => props.theme.colors.text.secondary};
|
||||
margin-bottom: 12px;
|
||||
`;
|
||||
const ListDesc = styled.span`
|
||||
font-size: 16px;
|
||||
color: ${(props) => props.theme.colors.text.primary};
|
||||
`;
|
||||
const FilterSearch = styled(Input)`
|
||||
margin: 0;
|
||||
`;
|
||||
|
||||
const ListActions = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 18px;
|
||||
`;
|
||||
|
||||
const MemberListWrapper = styled.div`
|
||||
flex: 1 1;
|
||||
`;
|
||||
|
||||
const Container = styled.div`
|
||||
padding: 2.2rem;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
max-width: 1400px;
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
`;
|
||||
|
||||
const TabNav = styled.div`
|
||||
float: left;
|
||||
width: 220px;
|
||||
height: 100%;
|
||||
display: block;
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
const TabNavContent = styled.ul`
|
||||
display: block;
|
||||
width: auto;
|
||||
border-bottom: 0 !important;
|
||||
border-right: 1px solid rgba(0, 0, 0, 0.05);
|
||||
`;
|
||||
|
||||
const TabNavItem = styled.li`
|
||||
padding: 0.35rem 0.3rem;
|
||||
height: 48px;
|
||||
display: block;
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
const TabNavItemButton = styled.button<{ active: boolean }>`
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
padding-top: 10px !important;
|
||||
padding-bottom: 10px !important;
|
||||
padding-left: 12px !important;
|
||||
padding-right: 8px !important;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
|
||||
color: ${(props) => (props.active ? `${props.theme.colors.secondary}` : props.theme.colors.text.primary)};
|
||||
&:hover {
|
||||
color: ${(props) => `${props.theme.colors.primary}`};
|
||||
}
|
||||
&:hover svg {
|
||||
fill: ${(props) => props.theme.colors.primary};
|
||||
}
|
||||
`;
|
||||
const TabItemUser = styled(User)<{ active: boolean }>`
|
||||
fill: ${(props) => (props.active ? `${props.theme.colors.primary}` : props.theme.colors.text.primary)}
|
||||
stroke: ${(props) => (props.active ? `${props.theme.colors.primary}` : props.theme.colors.text.primary)}
|
||||
`;
|
||||
|
||||
const TabNavItemSpan = styled.span`
|
||||
text-align: left;
|
||||
padding-left: 9px;
|
||||
font-size: 14px;
|
||||
`;
|
||||
|
||||
const TabNavLine = styled.span<{ top: number }>`
|
||||
left: auto;
|
||||
right: 0;
|
||||
width: 2px;
|
||||
height: 48px;
|
||||
transform: scaleX(1);
|
||||
top: ${(props) => props.top}px;
|
||||
|
||||
background: linear-gradient(
|
||||
30deg,
|
||||
${(props) => props.theme.colors.primary},
|
||||
${(props) => props.theme.colors.primary}
|
||||
);
|
||||
box-shadow: 0 0 8px 0 ${(props) => props.theme.colors.primary};
|
||||
display: block;
|
||||
position: absolute;
|
||||
transition: all 0.2s ease;
|
||||
`;
|
||||
|
||||
const TabContentWrapper = styled.div`
|
||||
position: relative;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
margin-left: 1rem;
|
||||
`;
|
||||
|
||||
const TabContent = styled.div`
|
||||
position: relative;
|
||||
width: 100%;
|
||||
display: block;
|
||||
padding: 0;
|
||||
padding: 1.5rem;
|
||||
background-color: #10163a;
|
||||
border-radius: 0.5rem;
|
||||
`;
|
||||
|
||||
const items = [{ name: 'Members' }];
|
||||
|
||||
export const RoleCheckmark = styled(Checkmark)`
|
||||
padding-left: 4px;
|
||||
`;
|
||||
@ -54,7 +263,7 @@ export const MiniProfileActionItem = styled.span<{ disabled?: boolean }>`
|
||||
position: relative;
|
||||
text-decoration: none;
|
||||
|
||||
${props =>
|
||||
${(props) =>
|
||||
props.disabled
|
||||
? css`
|
||||
user-select: none;
|
||||
@ -75,7 +284,7 @@ export const Content = styled.div`
|
||||
|
||||
export const CurrentPermission = styled.span`
|
||||
margin-left: 4px;
|
||||
color: ${props => mixin.rgba(props.theme.colors.text.secondary, 0.4)};
|
||||
color: ${(props) => mixin.rgba(props.theme.colors.text.secondary, 0.4)};
|
||||
`;
|
||||
|
||||
export const Separator = styled.div`
|
||||
@ -86,13 +295,13 @@ export const Separator = styled.div`
|
||||
|
||||
export const WarningText = styled.span`
|
||||
display: flex;
|
||||
color: ${props => mixin.rgba(props.theme.colors.text.primary, 0.4)};
|
||||
color: ${(props) => mixin.rgba(props.theme.colors.text.primary, 0.4)};
|
||||
padding: 6px;
|
||||
`;
|
||||
|
||||
export const DeleteDescription = styled.div`
|
||||
font-size: 14px;
|
||||
color: ${props => props.theme.colors.text.primary};
|
||||
color: ${(props) => props.theme.colors.text.primary};
|
||||
`;
|
||||
|
||||
export const RemoveMemberButton = styled(Button)`
|
||||
@ -161,8 +370,8 @@ const TeamRoleManagerPopup: React.FC<TeamRoleManagerPopupProps> = ({
|
||||
<MiniProfileActions>
|
||||
<MiniProfileActionWrapper>
|
||||
{permissions
|
||||
.filter(p => (user.role && user.role.code === 'owner') || p.code !== 'owner')
|
||||
.map(perm => (
|
||||
.filter((p) => (user.role && user.role.code === 'owner') || p.code !== 'owner')
|
||||
.map((perm) => (
|
||||
<MiniProfileActionItem
|
||||
disabled={user.role && perm.code !== user.role.code && !canChangeRole}
|
||||
key={perm.code}
|
||||
@ -213,9 +422,9 @@ const TeamRoleManagerPopup: React.FC<TeamRoleManagerPopupProps> = ({
|
||||
Choose a new user to take over ownership of the users teams & projects.
|
||||
</DeleteDescription>
|
||||
<UserSelect
|
||||
onChange={v => setDeleteUser(v)}
|
||||
onChange={(v) => setDeleteUser(v)}
|
||||
value={deleteUser}
|
||||
options={users.map(u => ({ label: u.fullName, value: u.id }))}
|
||||
options={users.map((u) => ({ label: u.fullName, value: u.id }))}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
@ -240,7 +449,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={NOOP} 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();
|
||||
@ -293,211 +502,6 @@ const TeamRoleManagerPopup: React.FC<TeamRoleManagerPopupProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
const UserSelect = styled(Select)`
|
||||
margin: 8px 0;
|
||||
padding: 8px 0;
|
||||
`;
|
||||
|
||||
const NewUserPassInput = styled(Input)`
|
||||
margin: 8px 0;
|
||||
`;
|
||||
|
||||
const InviteMemberButton = styled(Button)`
|
||||
padding: 7px 12px;
|
||||
`;
|
||||
|
||||
const UserPassBar = styled.div`
|
||||
display: flex;
|
||||
padding-top: 8px;
|
||||
`;
|
||||
|
||||
const UserPassConfirmButton = styled(Button)`
|
||||
width: 100%;
|
||||
padding: 7px 12px;
|
||||
`;
|
||||
|
||||
const UserPassButton = styled(Button)`
|
||||
width: 50%;
|
||||
padding: 7px 12px;
|
||||
& ~ & {
|
||||
margin-left: 6px;
|
||||
}
|
||||
`;
|
||||
|
||||
const MemberItemOptions = styled.div``;
|
||||
|
||||
const MemberItemOption = styled(Button)`
|
||||
padding: 7px 9px;
|
||||
margin: 4px 0 4px 8px;
|
||||
float: left;
|
||||
min-width: 95px;
|
||||
`;
|
||||
|
||||
const MemberList = styled.div`
|
||||
border-top: 1px solid ${props => props.theme.colors.border};
|
||||
`;
|
||||
|
||||
const MemberListItem = styled.div`
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid ${props => props.theme.colors.border};
|
||||
min-height: 40px;
|
||||
padding: 12px 0 12px 40px;
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
const MemberListItemDetails = styled.div`
|
||||
float: left;
|
||||
flex: 1 0 auto;
|
||||
padding-left: 8px;
|
||||
`;
|
||||
|
||||
const InviteIcon = styled(UserPlus)`
|
||||
padding-right: 4px;
|
||||
`;
|
||||
|
||||
const MemberProfile = styled(TaskAssignee)`
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
left: 0;
|
||||
margin: 0;
|
||||
`;
|
||||
|
||||
const MemberItemName = styled.p`
|
||||
color: ${props => props.theme.colors.text.secondary};
|
||||
`;
|
||||
|
||||
const MemberItemUsername = styled.p`
|
||||
color: ${props => props.theme.colors.text.primary};
|
||||
`;
|
||||
|
||||
const MemberListHeader = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`;
|
||||
const ListTitle = styled.h3`
|
||||
font-size: 18px;
|
||||
color: ${props => props.theme.colors.text.secondary};
|
||||
margin-bottom: 12px;
|
||||
`;
|
||||
const ListDesc = styled.span`
|
||||
font-size: 16px;
|
||||
color: ${props => props.theme.colors.text.primary};
|
||||
`;
|
||||
const FilterSearch = styled(Input)`
|
||||
margin: 0;
|
||||
`;
|
||||
|
||||
const ListActions = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 18px;
|
||||
`;
|
||||
|
||||
const MemberListWrapper = styled.div`
|
||||
flex: 1 1;
|
||||
`;
|
||||
|
||||
const Container = styled.div`
|
||||
padding: 2.2rem;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
max-width: 1400px;
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
`;
|
||||
|
||||
const TabNav = styled.div`
|
||||
float: left;
|
||||
width: 220px;
|
||||
height: 100%;
|
||||
display: block;
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
const TabNavContent = styled.ul`
|
||||
display: block;
|
||||
width: auto;
|
||||
border-bottom: 0 !important;
|
||||
border-right: 1px solid rgba(0, 0, 0, 0.05);
|
||||
`;
|
||||
|
||||
const TabNavItem = styled.li`
|
||||
padding: 0.35rem 0.3rem;
|
||||
height: 48px;
|
||||
display: block;
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
const TabNavItemButton = styled.button<{ active: boolean }>`
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
padding-top: 10px !important;
|
||||
padding-bottom: 10px !important;
|
||||
padding-left: 12px !important;
|
||||
padding-right: 8px !important;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
|
||||
color: ${props => (props.active ? `${props.theme.colors.secondary}` : props.theme.colors.text.primary)};
|
||||
&:hover {
|
||||
color: ${props => `${props.theme.colors.primary}`};
|
||||
}
|
||||
&:hover svg {
|
||||
fill: ${props => props.theme.colors.primary};
|
||||
}
|
||||
`;
|
||||
const TabItemUser = styled(User)<{ active: boolean }>`
|
||||
fill: ${props => (props.active ? `${props.theme.colors.primary}` : props.theme.colors.text.primary)}
|
||||
stroke: ${props => (props.active ? `${props.theme.colors.primary}` : props.theme.colors.text.primary)}
|
||||
`;
|
||||
|
||||
const TabNavItemSpan = styled.span`
|
||||
text-align: left;
|
||||
padding-left: 9px;
|
||||
font-size: 14px;
|
||||
`;
|
||||
|
||||
const TabNavLine = styled.span<{ top: number }>`
|
||||
left: auto;
|
||||
right: 0;
|
||||
width: 2px;
|
||||
height: 48px;
|
||||
transform: scaleX(1);
|
||||
top: ${props => props.top}px;
|
||||
|
||||
background: linear-gradient(30deg, ${props => props.theme.colors.primary}, ${props => props.theme.colors.primary});
|
||||
box-shadow: 0 0 8px 0 ${props => props.theme.colors.primary};
|
||||
display: block;
|
||||
position: absolute;
|
||||
transition: all 0.2s ease;
|
||||
`;
|
||||
|
||||
const TabContentWrapper = styled.div`
|
||||
position: relative;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
margin-left: 1rem;
|
||||
`;
|
||||
|
||||
const TabContent = styled.div`
|
||||
position: relative;
|
||||
width: 100%;
|
||||
display: block;
|
||||
padding: 0;
|
||||
padding: 1.5rem;
|
||||
background-color: #10163a;
|
||||
border-radius: 0.5rem;
|
||||
`;
|
||||
|
||||
const items = [{ name: 'Members' }];
|
||||
|
||||
type NavItemProps = {
|
||||
active: boolean;
|
||||
name: string;
|
||||
@ -591,7 +595,7 @@ const Admin: React.FC<AdminProps> = ({
|
||||
<FilterSearch width="250px" variant="alternate" placeholder="Filter by name" />
|
||||
{canInviteUser && (
|
||||
<InviteMemberButton
|
||||
onClick={$target => {
|
||||
onClick={($target) => {
|
||||
onAddUser($target);
|
||||
}}
|
||||
>
|
||||
@ -602,7 +606,7 @@ const Admin: React.FC<AdminProps> = ({
|
||||
</ListActions>
|
||||
</MemberListHeader>
|
||||
<MemberList>
|
||||
{users.map(member => {
|
||||
{users.map((member) => {
|
||||
const projectTotal = member.owned.projects.length + member.member.projects.length;
|
||||
return (
|
||||
<MemberListItem>
|
||||
@ -615,7 +619,7 @@ const Admin: React.FC<AdminProps> = ({
|
||||
<MemberItemOption variant="flat">{`On ${projectTotal} projects`}</MemberItemOption>
|
||||
<MemberItemOption
|
||||
variant="outline"
|
||||
onClick={$target => {
|
||||
onClick={($target) => {
|
||||
showPopup(
|
||||
$target,
|
||||
<TeamRoleManagerPopup
|
||||
@ -626,7 +630,7 @@ const Admin: React.FC<AdminProps> = ({
|
||||
onUpdateUserPassword(user, password);
|
||||
}}
|
||||
canChangeRole={(member.role && member.role.code !== 'owner') ?? false}
|
||||
onChangeRole={roleCode => {
|
||||
onChangeRole={(roleCode) => {
|
||||
updateUserRole({ variables: { userID: member.id, roleCode } });
|
||||
}}
|
||||
onDeleteUser={onDeleteUser}
|
||||
@ -640,7 +644,7 @@ const Admin: React.FC<AdminProps> = ({
|
||||
</MemberListItem>
|
||||
);
|
||||
})}
|
||||
{invitedUsers.map(member => {
|
||||
{invitedUsers.map((member) => {
|
||||
return (
|
||||
<MemberListItem>
|
||||
<MemberProfile
|
||||
@ -664,7 +668,7 @@ const Admin: React.FC<AdminProps> = ({
|
||||
<MemberItemOptions>
|
||||
<MemberItemOption
|
||||
variant="outline"
|
||||
onClick={$target => {
|
||||
onClick={($target) => {
|
||||
showPopup(
|
||||
$target,
|
||||
<TeamRoleManagerPopup
|
||||
|
@ -7,6 +7,8 @@ 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 { Clock, Cross } from 'shared/icons';
|
||||
import Select from 'react-select/src/Select';
|
||||
|
||||
import {
|
||||
Wrapper,
|
||||
@ -23,8 +25,6 @@ import {
|
||||
ActionClock,
|
||||
ActionLabel,
|
||||
} from './Styles';
|
||||
import { Clock, Cross } from 'shared/icons';
|
||||
import Select from 'react-select/src/Select';
|
||||
|
||||
type DueDateManagerProps = {
|
||||
task: Task;
|
||||
@ -190,21 +190,6 @@ const DueDateManager: React.FC<DueDateManagerProps> = ({ task, onDueDateChange,
|
||||
};
|
||||
const [isRange, setIsRange] = useState(false);
|
||||
|
||||
const CustomTimeInput = forwardRef(({ value, onClick, onChange, onBlur, onFocus }: any, $ref: any) => {
|
||||
return (
|
||||
<DueDateInput
|
||||
id="endTime"
|
||||
value={value}
|
||||
name="endTime"
|
||||
onChange={onChange}
|
||||
width="100%"
|
||||
variant="alternate"
|
||||
label="Time"
|
||||
onClick={onClick}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<DateRangeInputs>
|
||||
|
@ -100,7 +100,7 @@ const List = React.forwardRef(
|
||||
/>
|
||||
{!isPublic && (
|
||||
<ListExtraMenuButtonWrapper ref={$extraActionsRef} onClick={handleExtraMenuOpen}>
|
||||
<Ellipsis size={16} color="#c2c6dc" />
|
||||
<Ellipsis vertical={false} size={16} color="#c2c6dc" />
|
||||
</ListExtraMenuButtonWrapper>
|
||||
)}
|
||||
</Header>
|
||||
|
@ -98,8 +98,8 @@ const ProjectName = styled.input`
|
||||
font-weight: 400;
|
||||
|
||||
&:focus {
|
||||
background: ${props => mixin.darken(props.theme.colors.bg.secondary, 0.15)};
|
||||
box-shadow: ${props => props.theme.colors.primary} 0px 0px 0px 1px;
|
||||
background: ${(props) => mixin.darken(props.theme.colors.bg.secondary, 0.15)};
|
||||
box-shadow: ${(props) => props.theme.colors.primary} 0px 0px 0px 1px;
|
||||
}
|
||||
`;
|
||||
const ProjectNameLabel = styled.label`
|
||||
@ -210,8 +210,8 @@ const CreateButton = styled.button`
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
background: ${props => props.theme.colors.primary};
|
||||
border-color: ${props => props.theme.colors.primary};
|
||||
background: ${(props) => props.theme.colors.primary};
|
||||
border-color: ${(props) => props.theme.colors.primary};
|
||||
}
|
||||
`;
|
||||
type NewProjectProps = {
|
||||
@ -224,7 +224,7 @@ type NewProjectProps = {
|
||||
const NewProject: React.FC<NewProjectProps> = ({ initialTeamID, teams, onClose, onCreateProject }) => {
|
||||
const [projectName, setProjectName] = useState('');
|
||||
const [team, setTeam] = useState<null | string>(initialTeamID);
|
||||
const options = [{ label: 'No team', value: 'no-team' }, ...teams.map(t => ({ label: t.name, value: t.id }))];
|
||||
const options = [{ label: 'No team', value: 'no-team' }, ...teams.map((t) => ({ label: t.name, value: t.id }))];
|
||||
return (
|
||||
<Overlay>
|
||||
<Content>
|
||||
@ -234,7 +234,7 @@ const NewProject: React.FC<NewProjectProps> = ({ initialTeamID, teams, onClose,
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
<ArrowLeft color="#c2c6dc" />
|
||||
<ArrowLeft width={16} height={16} color="#c2c6dc" />
|
||||
</HeaderLeft>
|
||||
<HeaderRight
|
||||
onClick={() => {
|
||||
@ -263,7 +263,7 @@ const NewProject: React.FC<NewProjectProps> = ({ initialTeamID, teams, onClose,
|
||||
onChange={(e: any) => {
|
||||
setTeam(e.value);
|
||||
}}
|
||||
value={options.find(d => d.value === team)}
|
||||
value={options.find((d) => d.value === team)}
|
||||
styles={colourStyles}
|
||||
classNamePrefix="teamSelect"
|
||||
options={options}
|
||||
|
@ -218,7 +218,7 @@ export const PopupProvider: React.FC = ({ children }) => {
|
||||
|
||||
const setTab = (newTab: number, options?: PopupOptions) => {
|
||||
setState((prevState: PopupState) =>
|
||||
produce(prevState, draftState => {
|
||||
produce(prevState, (draftState) => {
|
||||
draftState.previousTab = currentState.currentTab;
|
||||
draftState.currentTab = newTab;
|
||||
if (options) {
|
||||
@ -296,7 +296,7 @@ const PopupMenu: React.FC<Props> = ({ width, title, top, left, onClose, noHeader
|
||||
<Wrapper padding borders>
|
||||
{onPrevious && (
|
||||
<PreviousButton onClick={onPrevious}>
|
||||
<AngleLeft color="#c2c6dc" />
|
||||
<AngleLeft size={16} color="#c2c6dc" />
|
||||
</PreviousButton>
|
||||
)}
|
||||
{noHeader ? (
|
||||
@ -332,7 +332,7 @@ export const Popup: React.FC<PopupProps> = ({ borders = true, padding = true, ti
|
||||
setTab(0);
|
||||
}}
|
||||
>
|
||||
<AngleLeft color="#c2c6dc" />
|
||||
<AngleLeft size={16} color="#c2c6dc" />
|
||||
</PreviousButton>
|
||||
)}
|
||||
{title && (
|
||||
|
@ -311,7 +311,7 @@ const ResetPasswordTab: React.FC<ResetPasswordTabProps> = ({ onResetPassword })
|
||||
};
|
||||
|
||||
type UserInfoData = {
|
||||
full_name: string;
|
||||
fullName: string;
|
||||
bio: string;
|
||||
initials: string;
|
||||
email: string;
|
||||
@ -355,12 +355,12 @@ const UserInfoTab: React.FC<UserInfoTabProps> = ({
|
||||
})}
|
||||
>
|
||||
<UserInfoInput
|
||||
{...register('full_name', { required: 'Full name is required' })}
|
||||
{...register('fullName', { required: 'Full name is required' })}
|
||||
defaultValue={profile.fullName}
|
||||
width="100%"
|
||||
label="Name"
|
||||
/>
|
||||
{errors.full_name && <FormError>{errors.full_name.message}</FormError>}
|
||||
{errors.fullName && <FormError>{errors.fullName.message}</FormError>}
|
||||
<UserInfoInput
|
||||
defaultValue={profile.profileIcon && profile.profileIcon.initials ? profile.profileIcon.initials : ''}
|
||||
{...register('initials', {
|
||||
|
@ -13,6 +13,7 @@ import {
|
||||
Smile,
|
||||
} from 'shared/icons';
|
||||
import { toArray } from 'react-emoji-render';
|
||||
import { useCurrentUser } from 'App/context';
|
||||
import DOMPurify from 'dompurify';
|
||||
import TaskAssignee from 'shared/components/TaskAssignee';
|
||||
import useOnOutsideClick from 'shared/hooks/onOutsideClick';
|
||||
@ -80,11 +81,8 @@ import {
|
||||
ActivityItemHeaderTitleName,
|
||||
ActivityItemComment,
|
||||
} from './Styles';
|
||||
import { useCurrentUser } from 'App/context';
|
||||
|
||||
type TaskDetailsProps = {};
|
||||
|
||||
const TaskDetailsLoading: React.FC<TaskDetailsProps> = () => {
|
||||
const TaskDetailsLoading: React.FC = () => {
|
||||
const { user } = useCurrentUser();
|
||||
return (
|
||||
<Container>
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React, { useState, useRef } from 'react';
|
||||
import { useCurrentUser } from 'App/context';
|
||||
import {
|
||||
Plus,
|
||||
User,
|
||||
@ -81,9 +82,8 @@ import {
|
||||
} from './Styles';
|
||||
import Checklist, { ChecklistItem, ChecklistItems } from '../Checklist';
|
||||
import onDragEnd from './onDragEnd';
|
||||
import { plugin as em } from './remark';
|
||||
import plugin from './remark';
|
||||
import ActivityMessage from './ActivityMessage';
|
||||
import { useCurrentUser } from 'App/context';
|
||||
|
||||
const parseEmojis = (value: string) => {
|
||||
const emojisArray = toArray(value);
|
||||
@ -136,7 +136,7 @@ const StreamComment: React.FC<StreamCommentProps> = ({
|
||||
onCreateComment={onUpdateComment}
|
||||
/>
|
||||
) : (
|
||||
<ReactMarkdown skipHtml plugins={[em]}>
|
||||
<ReactMarkdown skipHtml plugins={[plugin]}>
|
||||
{DOMPurify.sanitize(comment.message, { FORBID_TAGS: ['style', 'img'] })}
|
||||
</ReactMarkdown>
|
||||
)}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import visit from 'unist-util-visit';
|
||||
import { visit } from 'unist-util-visit';
|
||||
import emoji from 'node-emoji';
|
||||
import { emoticon } from 'emoticon';
|
||||
import { Emoji } from 'emoji-mart';
|
||||
@ -15,17 +15,17 @@ const DEFAULT_SETTINGS = {
|
||||
};
|
||||
|
||||
function plugin(options) {
|
||||
const settings = Object.assign({}, DEFAULT_SETTINGS, options);
|
||||
const settings = { ...DEFAULT_SETTINGS, ...options };
|
||||
const pad = !!settings.padSpaceAfter;
|
||||
const emoticonEnable = !!settings.emoticon;
|
||||
|
||||
function getEmojiByShortCode(match) {
|
||||
// find emoji by shortcode - full match or with-out last char as it could be from text e.g. :-),
|
||||
const iconFull = emoticon.find(e => e.emoticons.includes(match)); // full match
|
||||
const iconPart = emoticon.find(e => e.emoticons.includes(match.slice(0, -1))); // second search pattern
|
||||
const iconFull = emoticon.find((e) => e.emoticons.includes(match)); // full match
|
||||
const iconPart = emoticon.find((e) => e.emoticons.includes(match.slice(0, -1))); // second search pattern
|
||||
const trimmedChar = iconPart ? match.slice(-1) : '';
|
||||
const addPad = pad ? ' ' : '';
|
||||
let icon = iconFull ? iconFull.emoji + addPad : iconPart && iconPart.emoji + addPad + trimmedChar;
|
||||
const icon = iconFull ? iconFull.emoji + addPad : iconPart && iconPart.emoji + addPad + trimmedChar;
|
||||
return icon || match;
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ function plugin(options) {
|
||||
console.log(match);
|
||||
const got = emoji.get(match);
|
||||
if (pad && got !== match) {
|
||||
return got + ' ';
|
||||
return `${got} `;
|
||||
}
|
||||
|
||||
console.log(got);
|
||||
@ -65,4 +65,4 @@ function plugin(options) {
|
||||
return transformer;
|
||||
}
|
||||
|
||||
export { plugin };
|
||||
export default plugin;
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React, { useRef, useState, useEffect } from 'react';
|
||||
import { Home, Star, Bell, AngleDown, BarChart, CheckCircle, ListUnordered } from 'shared/icons';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { RoleCode } from 'shared/generated/graphql';
|
||||
import * as S from './Styles';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
export type MenuItem = {
|
||||
name: string;
|
||||
|
@ -144,7 +144,7 @@ const ProjectHeading: React.FC<ProjectHeadingProps> = ({
|
||||
</ProjectSettingsButton>
|
||||
{onFavorite && (
|
||||
<ProjectSettingsButton onClick={() => onFavorite()}>
|
||||
<Star width={16} height={16} color="#c2c6dc" />
|
||||
<Star filled width={16} height={16} color="#c2c6dc" />
|
||||
</ProjectSettingsButton>
|
||||
)}
|
||||
</>
|
||||
@ -228,7 +228,7 @@ const NavBar: React.FC<NavBarProps> = ({
|
||||
<NavbarWrapper>
|
||||
<NavbarHeader>
|
||||
<ProjectActions>
|
||||
<ProjectSwitch ref={$finder} onClick={e => onOpenProjectFinder($finder)}>
|
||||
<ProjectSwitch ref={$finder} onClick={(e) => onOpenProjectFinder($finder)}>
|
||||
<ProjectSwitchInner>
|
||||
<TaskcafeLogo innerColor="#9f46e4" outerColor="#000" width={32} height={32} />
|
||||
</ProjectSwitchInner>
|
||||
@ -304,7 +304,7 @@ const NavBar: React.FC<NavBarProps> = ({
|
||||
))}
|
||||
{canInviteUser && (
|
||||
<InviteButton
|
||||
onClick={$target => {
|
||||
onClick={($target) => {
|
||||
if (onInviteUser) {
|
||||
onInviteUser($target);
|
||||
}
|
||||
|
@ -16,9 +16,4 @@ const AngleLeft = ({ size, color }: Props) => {
|
||||
);
|
||||
};
|
||||
|
||||
AngleLeft.defaultProps = {
|
||||
size: 16,
|
||||
color: '#000',
|
||||
};
|
||||
|
||||
export default AngleLeft;
|
||||
|
@ -17,10 +17,4 @@ const ArrowLeft = ({ width, height, color }: Props) => {
|
||||
);
|
||||
};
|
||||
|
||||
ArrowLeft.defaultProps = {
|
||||
width: 16,
|
||||
height: 16,
|
||||
color: '#000',
|
||||
};
|
||||
|
||||
export default ArrowLeft;
|
||||
|
@ -13,9 +13,4 @@ const Bell = ({ size, color }: Props) => {
|
||||
);
|
||||
};
|
||||
|
||||
Bell.defaultProps = {
|
||||
size: 16,
|
||||
color: '#000',
|
||||
};
|
||||
|
||||
export default Bell;
|
||||
|
@ -14,9 +14,4 @@ const Bin = ({ size, color }: Props) => {
|
||||
);
|
||||
};
|
||||
|
||||
Bin.defaultProps = {
|
||||
size: 16,
|
||||
color: '#000',
|
||||
};
|
||||
|
||||
export default Bin;
|
||||
|
@ -16,9 +16,4 @@ const Cog = ({ size, color }: Props) => {
|
||||
);
|
||||
};
|
||||
|
||||
Cog.defaultProps = {
|
||||
size: 16,
|
||||
color: '#000',
|
||||
};
|
||||
|
||||
export default Cog;
|
||||
|
@ -21,10 +21,4 @@ const Ellipsis = ({ size, color, vertical }: Props) => {
|
||||
);
|
||||
};
|
||||
|
||||
Ellipsis.defaultProps = {
|
||||
size: 16,
|
||||
color: '#000',
|
||||
vertical: false,
|
||||
};
|
||||
|
||||
export default Ellipsis;
|
||||
|
@ -13,9 +13,4 @@ const Exit = ({ size, color }: Props) => {
|
||||
);
|
||||
};
|
||||
|
||||
Exit.defaultProps = {
|
||||
size: 16,
|
||||
color: '#000',
|
||||
};
|
||||
|
||||
export default Exit;
|
||||
|
@ -13,9 +13,4 @@ const Question = ({ size, color }: Props) => {
|
||||
);
|
||||
};
|
||||
|
||||
Question.defaultProps = {
|
||||
size: 16,
|
||||
color: '#000',
|
||||
};
|
||||
|
||||
export default Question;
|
||||
|
@ -13,9 +13,4 @@ const Stack = ({ size, color }: Props) => {
|
||||
);
|
||||
};
|
||||
|
||||
Stack.defaultProps = {
|
||||
size: 16,
|
||||
color: '#000',
|
||||
};
|
||||
|
||||
export default Stack;
|
||||
|
@ -25,11 +25,4 @@ const Star = ({ width, height, color, filled }: Props) => {
|
||||
);
|
||||
};
|
||||
|
||||
Star.defaultProps = {
|
||||
width: 24,
|
||||
height: 16,
|
||||
color: '#000',
|
||||
filled: false,
|
||||
};
|
||||
|
||||
export default Star;
|
||||
|
@ -14,9 +14,4 @@ const Users = ({ size, color }: Props) => {
|
||||
);
|
||||
};
|
||||
|
||||
Users.defaultProps = {
|
||||
size: 16,
|
||||
color: '#000',
|
||||
};
|
||||
|
||||
export default Users;
|
||||
|
@ -7,7 +7,7 @@ export function updateApolloCache<T>(
|
||||
client: DataProxy,
|
||||
document: DocumentNode,
|
||||
update: UpdateCacheFn<T>,
|
||||
variables?: object,
|
||||
variables?: any,
|
||||
) {
|
||||
let queryArgs: DataProxy.Query<any, any>;
|
||||
if (variables) {
|
||||
|
@ -13989,6 +13989,11 @@ unist-util-is@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.1.0.tgz#976e5f462a7a5de73d94b706bac1b90671b57797"
|
||||
integrity sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==
|
||||
|
||||
unist-util-is@^5.0.0:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-5.1.1.tgz#e8aece0b102fa9bc097b0fef8f870c496d4a6236"
|
||||
integrity sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ==
|
||||
|
||||
unist-util-position@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-3.1.0.tgz#1c42ee6301f8d52f47d14f62bbdb796571fa2d47"
|
||||
@ -14009,6 +14014,14 @@ unist-util-visit-parents@^3.0.0:
|
||||
"@types/unist" "^2.0.0"
|
||||
unist-util-is "^4.0.0"
|
||||
|
||||
unist-util-visit-parents@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-5.0.0.tgz#5ae2440f8710a0c18a2b4ba0c4471d18e1090494"
|
||||
integrity sha512-CVaLOYPM/EaFTYMytbaju3Tw4QI3DHnHFnL358FkEu0hZOzSm/hqBdVwOQDR60jF5ZzhB1tlZlRH0ll/yekZIQ==
|
||||
dependencies:
|
||||
"@types/unist" "^2.0.0"
|
||||
unist-util-is "^5.0.0"
|
||||
|
||||
unist-util-visit@^2.0.0:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c"
|
||||
@ -14018,6 +14031,15 @@ unist-util-visit@^2.0.0:
|
||||
unist-util-is "^4.0.0"
|
||||
unist-util-visit-parents "^3.0.0"
|
||||
|
||||
unist-util-visit@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-4.0.0.tgz#6e1f7e8e163921d20281354c38bfd3244b64580a"
|
||||
integrity sha512-3HWTvrtU10/E7qgPznBfiOyG0TXj9W8c1GSfaI8L9GkaG1pLePiQPZ7E35a0R3ToQ/zcy4Im6aZ9WBgOTnv1MQ==
|
||||
dependencies:
|
||||
"@types/unist" "^2.0.0"
|
||||
unist-util-is "^5.0.0"
|
||||
unist-util-visit-parents "^5.0.0"
|
||||
|
||||
universalify@^0.1.0, universalify@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
|
||||
|
Loading…
Reference in New Issue
Block a user