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/),
|
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).
|
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
|
### Added
|
||||||
- Project visibility can now be set to public - meaning anyone can view the project board
|
- Project visibility can now be set to public - meaning anyone can view the project board
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
],
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
"prettier/prettier": "warn",
|
"prettier/prettier": "warn",
|
||||||
|
"no-shadow": "off",
|
||||||
"no-restricted-syntax": ["error", "LabeledStatement", "WithStatement"],
|
"no-restricted-syntax": ["error", "LabeledStatement", "WithStatement"],
|
||||||
"@typescript-eslint/explicit-function-return-type": "off",
|
"@typescript-eslint/explicit-function-return-type": "off",
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
|
@ -62,7 +62,8 @@
|
|||||||
"react-toastify": "^7.0.4",
|
"react-toastify": "^7.0.4",
|
||||||
"rich-markdown-editor": "^11.17.4-0",
|
"rich-markdown-editor": "^11.17.4-0",
|
||||||
"styled-components": "^5.2.3",
|
"styled-components": "^5.2.3",
|
||||||
"typescript": "~4.2.4"
|
"typescript": "~4.2.4",
|
||||||
|
"unist-util-visit": "^4.0.0"
|
||||||
},
|
},
|
||||||
"proxy": "http://localhost:3333",
|
"proxy": "http://localhost:3333",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -223,7 +223,7 @@ TODO: add permision check
|
|||||||
users={data.users}
|
users={data.users}
|
||||||
invitedUsers={data.invitedUsers}
|
invitedUsers={data.invitedUsers}
|
||||||
// canInviteUser={user.roles.org === 'admin'} TODO: add permision check
|
// canInviteUser={user.roles.org === 'admin'} TODO: add permision check
|
||||||
canInviteUser={true}
|
canInviteUser
|
||||||
onInviteUser={NOOP}
|
onInviteUser={NOOP}
|
||||||
onUpdateUserPassword={() => {
|
onUpdateUserPassword={() => {
|
||||||
hidePopup();
|
hidePopup();
|
||||||
|
@ -26,10 +26,10 @@ import useOnOutsideClick from 'shared/hooks/onOutsideClick';
|
|||||||
import DueDateManager from 'shared/components/DueDateManager';
|
import DueDateManager from 'shared/components/DueDateManager';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import useStickyState from 'shared/hooks/useStickyState';
|
import useStickyState from 'shared/hooks/useStickyState';
|
||||||
|
import { StaticContext } from 'react-router';
|
||||||
import MyTasksSortPopup from './MyTasksSort';
|
import MyTasksSortPopup from './MyTasksSort';
|
||||||
import MyTasksStatusPopup from './MyTasksStatus';
|
import MyTasksStatusPopup from './MyTasksStatus';
|
||||||
import TaskEntry from './TaskEntry';
|
import TaskEntry from './TaskEntry';
|
||||||
import { StaticContext } from 'react-router';
|
|
||||||
|
|
||||||
type TaskRouteProps = {
|
type TaskRouteProps = {
|
||||||
taskID: string;
|
taskID: string;
|
||||||
|
@ -44,7 +44,7 @@ const Projects = () => {
|
|||||||
name="file"
|
name="file"
|
||||||
style={{ display: 'none' }}
|
style={{ display: 'none' }}
|
||||||
ref={$fileUpload}
|
ref={$fileUpload}
|
||||||
onChange={e => {
|
onChange={(e) => {
|
||||||
if (e.target.files) {
|
if (e.target.files) {
|
||||||
const fileData = new FormData();
|
const fileData = new FormData();
|
||||||
fileData.append('file', e.target.files[0]);
|
fileData.append('file', e.target.files[0]);
|
||||||
@ -52,7 +52,7 @@ const Projects = () => {
|
|||||||
.post('/users/me/avatar', fileData, {
|
.post('/users/me/avatar', fileData, {
|
||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
})
|
})
|
||||||
.then(res => {
|
.then((res) => {
|
||||||
if ($fileUpload && $fileUpload.current) {
|
if ($fileUpload && $fileUpload.current) {
|
||||||
$fileUpload.current.value = '';
|
$fileUpload.current.value = '';
|
||||||
refetch();
|
refetch();
|
||||||
@ -77,7 +77,7 @@ const Projects = () => {
|
|||||||
}}
|
}}
|
||||||
onChangeUserInfo={(d, done) => {
|
onChangeUserInfo={(d, done) => {
|
||||||
updateUserInfo({
|
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!');
|
toast('User info was saved!');
|
||||||
done();
|
done();
|
||||||
|
@ -31,11 +31,11 @@ import produce from 'immer';
|
|||||||
import NOOP from 'shared/utils/noop';
|
import NOOP from 'shared/utils/noop';
|
||||||
import useStateWithLocalStorage from 'shared/hooks/useStateWithLocalStorage';
|
import useStateWithLocalStorage from 'shared/hooks/useStateWithLocalStorage';
|
||||||
import localStorage from 'shared/utils/localStorage';
|
import localStorage from 'shared/utils/localStorage';
|
||||||
|
import polling from 'shared/utils/polling';
|
||||||
import Board, { BoardLoading } from './Board';
|
import Board, { BoardLoading } from './Board';
|
||||||
import Details from './Details';
|
import Details from './Details';
|
||||||
import LabelManagerEditor from './LabelManagerEditor';
|
import LabelManagerEditor from './LabelManagerEditor';
|
||||||
import UserManagementPopup from './UserManagementPopup';
|
import UserManagementPopup from './UserManagementPopup';
|
||||||
import polling from 'shared/utils/polling';
|
|
||||||
|
|
||||||
type TaskRouteProps = {
|
type TaskRouteProps = {
|
||||||
taskID: string;
|
taskID: string;
|
||||||
|
@ -524,7 +524,7 @@ const Members: React.FC<MembersProps> = ({ teamID }) => {
|
|||||||
members={data.findTeam.members}
|
members={data.findTeam.members}
|
||||||
warning={member.role && member.role.code === 'owner' ? warning : null}
|
warning={member.role && member.role.code === 'owner' ? warning : null}
|
||||||
// canChangeRole={user.isAdmin(PermissionLevel.TEAM, PermissionObjectType.TEAM, teamID)} TODO: add permission check
|
// canChangeRole={user.isAdmin(PermissionLevel.TEAM, PermissionObjectType.TEAM, teamID)} TODO: add permission check
|
||||||
canChangeRole={true}
|
canChangeRole
|
||||||
onChangeRole={(roleCode) => {
|
onChangeRole={(roleCode) => {
|
||||||
updateTeamMemberRole({ variables: { userID: member.id, teamID, 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 NOOP from 'shared/utils/noop';
|
||||||
import { mixin } from 'shared/utils/styles';
|
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)`
|
export const RoleCheckmark = styled(Checkmark)`
|
||||||
padding-left: 4px;
|
padding-left: 4px;
|
||||||
`;
|
`;
|
||||||
@ -54,7 +263,7 @@ export const MiniProfileActionItem = styled.span<{ disabled?: boolean }>`
|
|||||||
position: relative;
|
position: relative;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
||||||
${props =>
|
${(props) =>
|
||||||
props.disabled
|
props.disabled
|
||||||
? css`
|
? css`
|
||||||
user-select: none;
|
user-select: none;
|
||||||
@ -75,7 +284,7 @@ export const Content = styled.div`
|
|||||||
|
|
||||||
export const CurrentPermission = styled.span`
|
export const CurrentPermission = styled.span`
|
||||||
margin-left: 4px;
|
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`
|
export const Separator = styled.div`
|
||||||
@ -86,13 +295,13 @@ export const Separator = styled.div`
|
|||||||
|
|
||||||
export const WarningText = styled.span`
|
export const WarningText = styled.span`
|
||||||
display: flex;
|
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;
|
padding: 6px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const DeleteDescription = styled.div`
|
export const DeleteDescription = styled.div`
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: ${props => props.theme.colors.text.primary};
|
color: ${(props) => props.theme.colors.text.primary};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const RemoveMemberButton = styled(Button)`
|
export const RemoveMemberButton = styled(Button)`
|
||||||
@ -161,8 +370,8 @@ const TeamRoleManagerPopup: React.FC<TeamRoleManagerPopupProps> = ({
|
|||||||
<MiniProfileActions>
|
<MiniProfileActions>
|
||||||
<MiniProfileActionWrapper>
|
<MiniProfileActionWrapper>
|
||||||
{permissions
|
{permissions
|
||||||
.filter(p => (user.role && user.role.code === 'owner') || p.code !== 'owner')
|
.filter((p) => (user.role && user.role.code === 'owner') || p.code !== 'owner')
|
||||||
.map(perm => (
|
.map((perm) => (
|
||||||
<MiniProfileActionItem
|
<MiniProfileActionItem
|
||||||
disabled={user.role && perm.code !== user.role.code && !canChangeRole}
|
disabled={user.role && perm.code !== user.role.code && !canChangeRole}
|
||||||
key={perm.code}
|
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.
|
Choose a new user to take over ownership of the users teams & projects.
|
||||||
</DeleteDescription>
|
</DeleteDescription>
|
||||||
<UserSelect
|
<UserSelect
|
||||||
onChange={v => setDeleteUser(v)}
|
onChange={(v) => setDeleteUser(v)}
|
||||||
value={deleteUser}
|
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.
|
Removing this user from the organzation will remove them from assigned tasks, projects, and teams.
|
||||||
</DeleteDescription>
|
</DeleteDescription>
|
||||||
<DeleteDescription>{`The user is the owner of ${user.owned.projects.length} projects & ${user.owned.teams.length} 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
|
<UserPassConfirmButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
// onDeleteUser();
|
// 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 = {
|
type NavItemProps = {
|
||||||
active: boolean;
|
active: boolean;
|
||||||
name: string;
|
name: string;
|
||||||
@ -591,7 +595,7 @@ const Admin: React.FC<AdminProps> = ({
|
|||||||
<FilterSearch width="250px" variant="alternate" placeholder="Filter by name" />
|
<FilterSearch width="250px" variant="alternate" placeholder="Filter by name" />
|
||||||
{canInviteUser && (
|
{canInviteUser && (
|
||||||
<InviteMemberButton
|
<InviteMemberButton
|
||||||
onClick={$target => {
|
onClick={($target) => {
|
||||||
onAddUser($target);
|
onAddUser($target);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -602,7 +606,7 @@ const Admin: React.FC<AdminProps> = ({
|
|||||||
</ListActions>
|
</ListActions>
|
||||||
</MemberListHeader>
|
</MemberListHeader>
|
||||||
<MemberList>
|
<MemberList>
|
||||||
{users.map(member => {
|
{users.map((member) => {
|
||||||
const projectTotal = member.owned.projects.length + member.member.projects.length;
|
const projectTotal = member.owned.projects.length + member.member.projects.length;
|
||||||
return (
|
return (
|
||||||
<MemberListItem>
|
<MemberListItem>
|
||||||
@ -615,7 +619,7 @@ const Admin: React.FC<AdminProps> = ({
|
|||||||
<MemberItemOption variant="flat">{`On ${projectTotal} projects`}</MemberItemOption>
|
<MemberItemOption variant="flat">{`On ${projectTotal} projects`}</MemberItemOption>
|
||||||
<MemberItemOption
|
<MemberItemOption
|
||||||
variant="outline"
|
variant="outline"
|
||||||
onClick={$target => {
|
onClick={($target) => {
|
||||||
showPopup(
|
showPopup(
|
||||||
$target,
|
$target,
|
||||||
<TeamRoleManagerPopup
|
<TeamRoleManagerPopup
|
||||||
@ -626,7 +630,7 @@ const Admin: React.FC<AdminProps> = ({
|
|||||||
onUpdateUserPassword(user, password);
|
onUpdateUserPassword(user, password);
|
||||||
}}
|
}}
|
||||||
canChangeRole={(member.role && member.role.code !== 'owner') ?? false}
|
canChangeRole={(member.role && member.role.code !== 'owner') ?? false}
|
||||||
onChangeRole={roleCode => {
|
onChangeRole={(roleCode) => {
|
||||||
updateUserRole({ variables: { userID: member.id, roleCode } });
|
updateUserRole({ variables: { userID: member.id, roleCode } });
|
||||||
}}
|
}}
|
||||||
onDeleteUser={onDeleteUser}
|
onDeleteUser={onDeleteUser}
|
||||||
@ -640,7 +644,7 @@ const Admin: React.FC<AdminProps> = ({
|
|||||||
</MemberListItem>
|
</MemberListItem>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
{invitedUsers.map(member => {
|
{invitedUsers.map((member) => {
|
||||||
return (
|
return (
|
||||||
<MemberListItem>
|
<MemberListItem>
|
||||||
<MemberProfile
|
<MemberProfile
|
||||||
@ -664,7 +668,7 @@ const Admin: React.FC<AdminProps> = ({
|
|||||||
<MemberItemOptions>
|
<MemberItemOptions>
|
||||||
<MemberItemOption
|
<MemberItemOption
|
||||||
variant="outline"
|
variant="outline"
|
||||||
onClick={$target => {
|
onClick={($target) => {
|
||||||
showPopup(
|
showPopup(
|
||||||
$target,
|
$target,
|
||||||
<TeamRoleManagerPopup
|
<TeamRoleManagerPopup
|
||||||
|
@ -7,6 +7,8 @@ import 'react-datepicker/dist/react-datepicker.css';
|
|||||||
import { getYear, getMonth } from 'date-fns';
|
import { getYear, getMonth } from 'date-fns';
|
||||||
import { useForm, Controller } from 'react-hook-form';
|
import { useForm, Controller } from 'react-hook-form';
|
||||||
import NOOP from 'shared/utils/noop';
|
import NOOP from 'shared/utils/noop';
|
||||||
|
import { Clock, Cross } from 'shared/icons';
|
||||||
|
import Select from 'react-select/src/Select';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Wrapper,
|
Wrapper,
|
||||||
@ -23,8 +25,6 @@ import {
|
|||||||
ActionClock,
|
ActionClock,
|
||||||
ActionLabel,
|
ActionLabel,
|
||||||
} from './Styles';
|
} from './Styles';
|
||||||
import { Clock, Cross } from 'shared/icons';
|
|
||||||
import Select from 'react-select/src/Select';
|
|
||||||
|
|
||||||
type DueDateManagerProps = {
|
type DueDateManagerProps = {
|
||||||
task: Task;
|
task: Task;
|
||||||
@ -190,21 +190,6 @@ const DueDateManager: React.FC<DueDateManagerProps> = ({ task, onDueDateChange,
|
|||||||
};
|
};
|
||||||
const [isRange, setIsRange] = useState(false);
|
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 (
|
return (
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<DateRangeInputs>
|
<DateRangeInputs>
|
||||||
|
@ -100,7 +100,7 @@ const List = React.forwardRef(
|
|||||||
/>
|
/>
|
||||||
{!isPublic && (
|
{!isPublic && (
|
||||||
<ListExtraMenuButtonWrapper ref={$extraActionsRef} onClick={handleExtraMenuOpen}>
|
<ListExtraMenuButtonWrapper ref={$extraActionsRef} onClick={handleExtraMenuOpen}>
|
||||||
<Ellipsis size={16} color="#c2c6dc" />
|
<Ellipsis vertical={false} size={16} color="#c2c6dc" />
|
||||||
</ListExtraMenuButtonWrapper>
|
</ListExtraMenuButtonWrapper>
|
||||||
)}
|
)}
|
||||||
</Header>
|
</Header>
|
||||||
|
@ -98,8 +98,8 @@ const ProjectName = styled.input`
|
|||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
background: ${props => mixin.darken(props.theme.colors.bg.secondary, 0.15)};
|
background: ${(props) => mixin.darken(props.theme.colors.bg.secondary, 0.15)};
|
||||||
box-shadow: ${props => props.theme.colors.primary} 0px 0px 0px 1px;
|
box-shadow: ${(props) => props.theme.colors.primary} 0px 0px 0px 1px;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
const ProjectNameLabel = styled.label`
|
const ProjectNameLabel = styled.label`
|
||||||
@ -210,8 +210,8 @@ const CreateButton = styled.button`
|
|||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background: ${props => props.theme.colors.primary};
|
background: ${(props) => props.theme.colors.primary};
|
||||||
border-color: ${props => props.theme.colors.primary};
|
border-color: ${(props) => props.theme.colors.primary};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
type NewProjectProps = {
|
type NewProjectProps = {
|
||||||
@ -224,7 +224,7 @@ type NewProjectProps = {
|
|||||||
const NewProject: React.FC<NewProjectProps> = ({ initialTeamID, teams, onClose, onCreateProject }) => {
|
const NewProject: React.FC<NewProjectProps> = ({ initialTeamID, teams, onClose, onCreateProject }) => {
|
||||||
const [projectName, setProjectName] = useState('');
|
const [projectName, setProjectName] = useState('');
|
||||||
const [team, setTeam] = useState<null | string>(initialTeamID);
|
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 (
|
return (
|
||||||
<Overlay>
|
<Overlay>
|
||||||
<Content>
|
<Content>
|
||||||
@ -234,7 +234,7 @@ const NewProject: React.FC<NewProjectProps> = ({ initialTeamID, teams, onClose,
|
|||||||
onClose();
|
onClose();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ArrowLeft color="#c2c6dc" />
|
<ArrowLeft width={16} height={16} color="#c2c6dc" />
|
||||||
</HeaderLeft>
|
</HeaderLeft>
|
||||||
<HeaderRight
|
<HeaderRight
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@ -263,7 +263,7 @@ const NewProject: React.FC<NewProjectProps> = ({ initialTeamID, teams, onClose,
|
|||||||
onChange={(e: any) => {
|
onChange={(e: any) => {
|
||||||
setTeam(e.value);
|
setTeam(e.value);
|
||||||
}}
|
}}
|
||||||
value={options.find(d => d.value === team)}
|
value={options.find((d) => d.value === team)}
|
||||||
styles={colourStyles}
|
styles={colourStyles}
|
||||||
classNamePrefix="teamSelect"
|
classNamePrefix="teamSelect"
|
||||||
options={options}
|
options={options}
|
||||||
|
@ -218,7 +218,7 @@ export const PopupProvider: React.FC = ({ children }) => {
|
|||||||
|
|
||||||
const setTab = (newTab: number, options?: PopupOptions) => {
|
const setTab = (newTab: number, options?: PopupOptions) => {
|
||||||
setState((prevState: PopupState) =>
|
setState((prevState: PopupState) =>
|
||||||
produce(prevState, draftState => {
|
produce(prevState, (draftState) => {
|
||||||
draftState.previousTab = currentState.currentTab;
|
draftState.previousTab = currentState.currentTab;
|
||||||
draftState.currentTab = newTab;
|
draftState.currentTab = newTab;
|
||||||
if (options) {
|
if (options) {
|
||||||
@ -296,7 +296,7 @@ const PopupMenu: React.FC<Props> = ({ width, title, top, left, onClose, noHeader
|
|||||||
<Wrapper padding borders>
|
<Wrapper padding borders>
|
||||||
{onPrevious && (
|
{onPrevious && (
|
||||||
<PreviousButton onClick={onPrevious}>
|
<PreviousButton onClick={onPrevious}>
|
||||||
<AngleLeft color="#c2c6dc" />
|
<AngleLeft size={16} color="#c2c6dc" />
|
||||||
</PreviousButton>
|
</PreviousButton>
|
||||||
)}
|
)}
|
||||||
{noHeader ? (
|
{noHeader ? (
|
||||||
@ -332,7 +332,7 @@ export const Popup: React.FC<PopupProps> = ({ borders = true, padding = true, ti
|
|||||||
setTab(0);
|
setTab(0);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<AngleLeft color="#c2c6dc" />
|
<AngleLeft size={16} color="#c2c6dc" />
|
||||||
</PreviousButton>
|
</PreviousButton>
|
||||||
)}
|
)}
|
||||||
{title && (
|
{title && (
|
||||||
|
@ -311,7 +311,7 @@ const ResetPasswordTab: React.FC<ResetPasswordTabProps> = ({ onResetPassword })
|
|||||||
};
|
};
|
||||||
|
|
||||||
type UserInfoData = {
|
type UserInfoData = {
|
||||||
full_name: string;
|
fullName: string;
|
||||||
bio: string;
|
bio: string;
|
||||||
initials: string;
|
initials: string;
|
||||||
email: string;
|
email: string;
|
||||||
@ -355,12 +355,12 @@ const UserInfoTab: React.FC<UserInfoTabProps> = ({
|
|||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<UserInfoInput
|
<UserInfoInput
|
||||||
{...register('full_name', { required: 'Full name is required' })}
|
{...register('fullName', { required: 'Full name is required' })}
|
||||||
defaultValue={profile.fullName}
|
defaultValue={profile.fullName}
|
||||||
width="100%"
|
width="100%"
|
||||||
label="Name"
|
label="Name"
|
||||||
/>
|
/>
|
||||||
{errors.full_name && <FormError>{errors.full_name.message}</FormError>}
|
{errors.fullName && <FormError>{errors.fullName.message}</FormError>}
|
||||||
<UserInfoInput
|
<UserInfoInput
|
||||||
defaultValue={profile.profileIcon && profile.profileIcon.initials ? profile.profileIcon.initials : ''}
|
defaultValue={profile.profileIcon && profile.profileIcon.initials ? profile.profileIcon.initials : ''}
|
||||||
{...register('initials', {
|
{...register('initials', {
|
||||||
|
@ -13,6 +13,7 @@ import {
|
|||||||
Smile,
|
Smile,
|
||||||
} from 'shared/icons';
|
} from 'shared/icons';
|
||||||
import { toArray } from 'react-emoji-render';
|
import { toArray } from 'react-emoji-render';
|
||||||
|
import { useCurrentUser } from 'App/context';
|
||||||
import DOMPurify from 'dompurify';
|
import DOMPurify from 'dompurify';
|
||||||
import TaskAssignee from 'shared/components/TaskAssignee';
|
import TaskAssignee from 'shared/components/TaskAssignee';
|
||||||
import useOnOutsideClick from 'shared/hooks/onOutsideClick';
|
import useOnOutsideClick from 'shared/hooks/onOutsideClick';
|
||||||
@ -80,11 +81,8 @@ import {
|
|||||||
ActivityItemHeaderTitleName,
|
ActivityItemHeaderTitleName,
|
||||||
ActivityItemComment,
|
ActivityItemComment,
|
||||||
} from './Styles';
|
} from './Styles';
|
||||||
import { useCurrentUser } from 'App/context';
|
|
||||||
|
|
||||||
type TaskDetailsProps = {};
|
const TaskDetailsLoading: React.FC = () => {
|
||||||
|
|
||||||
const TaskDetailsLoading: React.FC<TaskDetailsProps> = () => {
|
|
||||||
const { user } = useCurrentUser();
|
const { user } = useCurrentUser();
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import React, { useState, useRef } from 'react';
|
import React, { useState, useRef } from 'react';
|
||||||
|
import { useCurrentUser } from 'App/context';
|
||||||
import {
|
import {
|
||||||
Plus,
|
Plus,
|
||||||
User,
|
User,
|
||||||
@ -81,9 +82,8 @@ import {
|
|||||||
} from './Styles';
|
} from './Styles';
|
||||||
import Checklist, { ChecklistItem, ChecklistItems } from '../Checklist';
|
import Checklist, { ChecklistItem, ChecklistItems } from '../Checklist';
|
||||||
import onDragEnd from './onDragEnd';
|
import onDragEnd from './onDragEnd';
|
||||||
import { plugin as em } from './remark';
|
import plugin from './remark';
|
||||||
import ActivityMessage from './ActivityMessage';
|
import ActivityMessage from './ActivityMessage';
|
||||||
import { useCurrentUser } from 'App/context';
|
|
||||||
|
|
||||||
const parseEmojis = (value: string) => {
|
const parseEmojis = (value: string) => {
|
||||||
const emojisArray = toArray(value);
|
const emojisArray = toArray(value);
|
||||||
@ -136,7 +136,7 @@ const StreamComment: React.FC<StreamCommentProps> = ({
|
|||||||
onCreateComment={onUpdateComment}
|
onCreateComment={onUpdateComment}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<ReactMarkdown skipHtml plugins={[em]}>
|
<ReactMarkdown skipHtml plugins={[plugin]}>
|
||||||
{DOMPurify.sanitize(comment.message, { FORBID_TAGS: ['style', 'img'] })}
|
{DOMPurify.sanitize(comment.message, { FORBID_TAGS: ['style', 'img'] })}
|
||||||
</ReactMarkdown>
|
</ReactMarkdown>
|
||||||
)}
|
)}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import visit from 'unist-util-visit';
|
import { visit } from 'unist-util-visit';
|
||||||
import emoji from 'node-emoji';
|
import emoji from 'node-emoji';
|
||||||
import { emoticon } from 'emoticon';
|
import { emoticon } from 'emoticon';
|
||||||
import { Emoji } from 'emoji-mart';
|
import { Emoji } from 'emoji-mart';
|
||||||
@ -15,17 +15,17 @@ const DEFAULT_SETTINGS = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function plugin(options) {
|
function plugin(options) {
|
||||||
const settings = Object.assign({}, DEFAULT_SETTINGS, options);
|
const settings = { ...DEFAULT_SETTINGS, ...options };
|
||||||
const pad = !!settings.padSpaceAfter;
|
const pad = !!settings.padSpaceAfter;
|
||||||
const emoticonEnable = !!settings.emoticon;
|
const emoticonEnable = !!settings.emoticon;
|
||||||
|
|
||||||
function getEmojiByShortCode(match) {
|
function getEmojiByShortCode(match) {
|
||||||
// find emoji by shortcode - full match or with-out last char as it could be from text e.g. :-),
|
// 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 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 iconPart = emoticon.find((e) => e.emoticons.includes(match.slice(0, -1))); // second search pattern
|
||||||
const trimmedChar = iconPart ? match.slice(-1) : '';
|
const trimmedChar = iconPart ? match.slice(-1) : '';
|
||||||
const addPad = pad ? ' ' : '';
|
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;
|
return icon || match;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ function plugin(options) {
|
|||||||
console.log(match);
|
console.log(match);
|
||||||
const got = emoji.get(match);
|
const got = emoji.get(match);
|
||||||
if (pad && got !== match) {
|
if (pad && got !== match) {
|
||||||
return got + ' ';
|
return `${got} `;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(got);
|
console.log(got);
|
||||||
@ -41,7 +41,7 @@ function plugin(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function transformer(tree) {
|
function transformer(tree) {
|
||||||
visit(tree, 'paragraph', function(node) {
|
visit(tree, 'paragraph', function (node) {
|
||||||
console.log(tree);
|
console.log(tree);
|
||||||
// node.value = node.value.replace(RE_EMOJI, getEmoji);
|
// node.value = node.value.replace(RE_EMOJI, getEmoji);
|
||||||
// jnode.type = 'html';
|
// jnode.type = 'html';
|
||||||
@ -65,4 +65,4 @@ function plugin(options) {
|
|||||||
return transformer;
|
return transformer;
|
||||||
}
|
}
|
||||||
|
|
||||||
export { plugin };
|
export default plugin;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import React, { useRef, useState, useEffect } from 'react';
|
import React, { useRef, useState, useEffect } from 'react';
|
||||||
import { Home, Star, Bell, AngleDown, BarChart, CheckCircle, ListUnordered } from 'shared/icons';
|
import { Home, Star, Bell, AngleDown, BarChart, CheckCircle, ListUnordered } from 'shared/icons';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
import { RoleCode } from 'shared/generated/graphql';
|
import { RoleCode } from 'shared/generated/graphql';
|
||||||
import * as S from './Styles';
|
import * as S from './Styles';
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
export type MenuItem = {
|
export type MenuItem = {
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -144,7 +144,7 @@ const ProjectHeading: React.FC<ProjectHeadingProps> = ({
|
|||||||
</ProjectSettingsButton>
|
</ProjectSettingsButton>
|
||||||
{onFavorite && (
|
{onFavorite && (
|
||||||
<ProjectSettingsButton onClick={() => onFavorite()}>
|
<ProjectSettingsButton onClick={() => onFavorite()}>
|
||||||
<Star width={16} height={16} color="#c2c6dc" />
|
<Star filled width={16} height={16} color="#c2c6dc" />
|
||||||
</ProjectSettingsButton>
|
</ProjectSettingsButton>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
@ -228,7 +228,7 @@ const NavBar: React.FC<NavBarProps> = ({
|
|||||||
<NavbarWrapper>
|
<NavbarWrapper>
|
||||||
<NavbarHeader>
|
<NavbarHeader>
|
||||||
<ProjectActions>
|
<ProjectActions>
|
||||||
<ProjectSwitch ref={$finder} onClick={e => onOpenProjectFinder($finder)}>
|
<ProjectSwitch ref={$finder} onClick={(e) => onOpenProjectFinder($finder)}>
|
||||||
<ProjectSwitchInner>
|
<ProjectSwitchInner>
|
||||||
<TaskcafeLogo innerColor="#9f46e4" outerColor="#000" width={32} height={32} />
|
<TaskcafeLogo innerColor="#9f46e4" outerColor="#000" width={32} height={32} />
|
||||||
</ProjectSwitchInner>
|
</ProjectSwitchInner>
|
||||||
@ -304,7 +304,7 @@ const NavBar: React.FC<NavBarProps> = ({
|
|||||||
))}
|
))}
|
||||||
{canInviteUser && (
|
{canInviteUser && (
|
||||||
<InviteButton
|
<InviteButton
|
||||||
onClick={$target => {
|
onClick={($target) => {
|
||||||
if (onInviteUser) {
|
if (onInviteUser) {
|
||||||
onInviteUser($target);
|
onInviteUser($target);
|
||||||
}
|
}
|
||||||
|
@ -16,9 +16,4 @@ const AngleLeft = ({ size, color }: Props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
AngleLeft.defaultProps = {
|
|
||||||
size: 16,
|
|
||||||
color: '#000',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AngleLeft;
|
export default AngleLeft;
|
||||||
|
@ -17,10 +17,4 @@ const ArrowLeft = ({ width, height, color }: Props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
ArrowLeft.defaultProps = {
|
|
||||||
width: 16,
|
|
||||||
height: 16,
|
|
||||||
color: '#000',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ArrowLeft;
|
export default ArrowLeft;
|
||||||
|
@ -13,9 +13,4 @@ const Bell = ({ size, color }: Props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Bell.defaultProps = {
|
|
||||||
size: 16,
|
|
||||||
color: '#000',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Bell;
|
export default Bell;
|
||||||
|
@ -14,9 +14,4 @@ const Bin = ({ size, color }: Props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Bin.defaultProps = {
|
|
||||||
size: 16,
|
|
||||||
color: '#000',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Bin;
|
export default Bin;
|
||||||
|
@ -16,9 +16,4 @@ const Cog = ({ size, color }: Props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Cog.defaultProps = {
|
|
||||||
size: 16,
|
|
||||||
color: '#000',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Cog;
|
export default Cog;
|
||||||
|
@ -21,10 +21,4 @@ const Ellipsis = ({ size, color, vertical }: Props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Ellipsis.defaultProps = {
|
|
||||||
size: 16,
|
|
||||||
color: '#000',
|
|
||||||
vertical: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Ellipsis;
|
export default Ellipsis;
|
||||||
|
@ -13,9 +13,4 @@ const Exit = ({ size, color }: Props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Exit.defaultProps = {
|
|
||||||
size: 16,
|
|
||||||
color: '#000',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Exit;
|
export default Exit;
|
||||||
|
@ -13,9 +13,4 @@ const Question = ({ size, color }: Props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Question.defaultProps = {
|
|
||||||
size: 16,
|
|
||||||
color: '#000',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Question;
|
export default Question;
|
||||||
|
@ -13,9 +13,4 @@ const Stack = ({ size, color }: Props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Stack.defaultProps = {
|
|
||||||
size: 16,
|
|
||||||
color: '#000',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Stack;
|
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;
|
export default Star;
|
||||||
|
@ -14,9 +14,4 @@ const Users = ({ size, color }: Props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Users.defaultProps = {
|
|
||||||
size: 16,
|
|
||||||
color: '#000',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Users;
|
export default Users;
|
||||||
|
@ -7,7 +7,7 @@ export function updateApolloCache<T>(
|
|||||||
client: DataProxy,
|
client: DataProxy,
|
||||||
document: DocumentNode,
|
document: DocumentNode,
|
||||||
update: UpdateCacheFn<T>,
|
update: UpdateCacheFn<T>,
|
||||||
variables?: object,
|
variables?: any,
|
||||||
) {
|
) {
|
||||||
let queryArgs: DataProxy.Query<any, any>;
|
let queryArgs: DataProxy.Query<any, any>;
|
||||||
if (variables) {
|
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"
|
resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.1.0.tgz#976e5f462a7a5de73d94b706bac1b90671b57797"
|
||||||
integrity sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==
|
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:
|
unist-util-position@^3.0.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-3.1.0.tgz#1c42ee6301f8d52f47d14f62bbdb796571fa2d47"
|
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"
|
"@types/unist" "^2.0.0"
|
||||||
unist-util-is "^4.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:
|
unist-util-visit@^2.0.0:
|
||||||
version "2.0.3"
|
version "2.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c"
|
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-is "^4.0.0"
|
||||||
unist-util-visit-parents "^3.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:
|
universalify@^0.1.0, universalify@^0.1.2:
|
||||||
version "0.1.2"
|
version "0.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
|
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
|
||||||
|
Loading…
Reference in New Issue
Block a user