diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e3aa66..4782112 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/frontend/.eslintrc.json b/frontend/.eslintrc.json index 1876fb8..e6c790c 100644 --- a/frontend/.eslintrc.json +++ b/frontend/.eslintrc.json @@ -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", diff --git a/frontend/package.json b/frontend/package.json index 3f36069..416f5dd 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -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": { diff --git a/frontend/src/Admin/index.tsx b/frontend/src/Admin/index.tsx index cd9c44d..940a171 100644 --- a/frontend/src/Admin/index.tsx +++ b/frontend/src/Admin/index.tsx @@ -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(); diff --git a/frontend/src/MyTasks/index.tsx b/frontend/src/MyTasks/index.tsx index f23c086..f4a304e 100644 --- a/frontend/src/MyTasks/index.tsx +++ b/frontend/src/MyTasks/index.tsx @@ -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; diff --git a/frontend/src/Profile/index.tsx b/frontend/src/Profile/index.tsx index 522930b..4751882 100644 --- a/frontend/src/Profile/index.tsx +++ b/frontend/src/Profile/index.tsx @@ -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(); diff --git a/frontend/src/Projects/Project/index.tsx b/frontend/src/Projects/Project/index.tsx index a4385e8..8ec33d1 100644 --- a/frontend/src/Projects/Project/index.tsx +++ b/frontend/src/Projects/Project/index.tsx @@ -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; diff --git a/frontend/src/Teams/Members/index.tsx b/frontend/src/Teams/Members/index.tsx index b19e1b5..32f1a15 100644 --- a/frontend/src/Teams/Members/index.tsx +++ b/frontend/src/Teams/Members/index.tsx @@ -524,7 +524,7 @@ const Members: React.FC = ({ 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 } }); }} diff --git a/frontend/src/shared/components/Admin/index.tsx b/frontend/src/shared/components/Admin/index.tsx index 0903043..deb9705 100644 --- a/frontend/src/shared/components/Admin/index.tsx +++ b/frontend/src/shared/components/Admin/index.tsx @@ -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 = ({ {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) => ( = ({ Choose a new user to take over ownership of the users teams & projects. 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 = ({ Removing this user from the organzation will remove them from assigned tasks, projects, and teams. {`The user is the owner of ${user.owned.projects.length} projects & ${user.owned.teams.length} teams.`} - ({ label: u.fullName, value: u.id }))} /> + ({ label: u.fullName, value: u.id }))} /> { // onDeleteUser(); @@ -293,211 +502,6 @@ const TeamRoleManagerPopup: React.FC = ({ ); }; -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 = ({ {canInviteUser && ( { + onClick={($target) => { onAddUser($target); }} > @@ -602,7 +606,7 @@ const Admin: React.FC = ({ - {users.map(member => { + {users.map((member) => { const projectTotal = member.owned.projects.length + member.member.projects.length; return ( @@ -615,7 +619,7 @@ const Admin: React.FC = ({ {`On ${projectTotal} projects`} { + onClick={($target) => { showPopup( $target, = ({ 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 = ({ ); })} - {invitedUsers.map(member => { + {invitedUsers.map((member) => { return ( = ({ { + onClick={($target) => { showPopup( $target, = ({ task, onDueDateChange, }; const [isRange, setIsRange] = useState(false); - const CustomTimeInput = forwardRef(({ value, onClick, onChange, onBlur, onFocus }: any, $ref: any) => { - return ( - - ); - }); - return ( diff --git a/frontend/src/shared/components/List/index.tsx b/frontend/src/shared/components/List/index.tsx index 7d6eff0..75110da 100644 --- a/frontend/src/shared/components/List/index.tsx +++ b/frontend/src/shared/components/List/index.tsx @@ -100,7 +100,7 @@ const List = React.forwardRef( /> {!isPublic && ( - + )} diff --git a/frontend/src/shared/components/NewProject/index.tsx b/frontend/src/shared/components/NewProject/index.tsx index 26e5f4f..0fece2c 100644 --- a/frontend/src/shared/components/NewProject/index.tsx +++ b/frontend/src/shared/components/NewProject/index.tsx @@ -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 = ({ initialTeamID, teams, onClose, onCreateProject }) => { const [projectName, setProjectName] = useState(''); const [team, setTeam] = useState(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 ( @@ -234,7 +234,7 @@ const NewProject: React.FC = ({ initialTeamID, teams, onClose, onClose(); }} > - + { @@ -263,7 +263,7 @@ const NewProject: React.FC = ({ 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} diff --git a/frontend/src/shared/components/PopupMenu/index.tsx b/frontend/src/shared/components/PopupMenu/index.tsx index ce07fbc..229ad95 100644 --- a/frontend/src/shared/components/PopupMenu/index.tsx +++ b/frontend/src/shared/components/PopupMenu/index.tsx @@ -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 = ({ width, title, top, left, onClose, noHeader {onPrevious && ( - + )} {noHeader ? ( @@ -332,7 +332,7 @@ export const Popup: React.FC = ({ borders = true, padding = true, ti setTab(0); }} > - + )} {title && ( diff --git a/frontend/src/shared/components/Settings/index.tsx b/frontend/src/shared/components/Settings/index.tsx index c0fd433..a9384b2 100644 --- a/frontend/src/shared/components/Settings/index.tsx +++ b/frontend/src/shared/components/Settings/index.tsx @@ -311,7 +311,7 @@ const ResetPasswordTab: React.FC = ({ onResetPassword }) }; type UserInfoData = { - full_name: string; + fullName: string; bio: string; initials: string; email: string; @@ -355,12 +355,12 @@ const UserInfoTab: React.FC = ({ })} > - {errors.full_name && {errors.full_name.message}} + {errors.fullName && {errors.fullName.message}} = () => { +const TaskDetailsLoading: React.FC = () => { const { user } = useCurrentUser(); return ( diff --git a/frontend/src/shared/components/TaskDetails/index.tsx b/frontend/src/shared/components/TaskDetails/index.tsx index 8bbbd16..c91c1bd 100644 --- a/frontend/src/shared/components/TaskDetails/index.tsx +++ b/frontend/src/shared/components/TaskDetails/index.tsx @@ -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 = ({ onCreateComment={onUpdateComment} /> ) : ( - + {DOMPurify.sanitize(comment.message, { FORBID_TAGS: ['style', 'img'] })} )} diff --git a/frontend/src/shared/components/TaskDetails/remark.js b/frontend/src/shared/components/TaskDetails/remark.js index f151344..2dc42d3 100644 --- a/frontend/src/shared/components/TaskDetails/remark.js +++ b/frontend/src/shared/components/TaskDetails/remark.js @@ -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); @@ -41,7 +41,7 @@ function plugin(options) { } function transformer(tree) { - visit(tree, 'paragraph', function(node) { + visit(tree, 'paragraph', function (node) { console.log(tree); // node.value = node.value.replace(RE_EMOJI, getEmoji); // jnode.type = 'html'; @@ -65,4 +65,4 @@ function plugin(options) { return transformer; } -export { plugin }; +export default plugin; diff --git a/frontend/src/shared/components/TopNavbar/LoggedOut.tsx b/frontend/src/shared/components/TopNavbar/LoggedOut.tsx index 65ce3cb..4edf813 100644 --- a/frontend/src/shared/components/TopNavbar/LoggedOut.tsx +++ b/frontend/src/shared/components/TopNavbar/LoggedOut.tsx @@ -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; diff --git a/frontend/src/shared/components/TopNavbar/index.tsx b/frontend/src/shared/components/TopNavbar/index.tsx index 3fcedf7..88b2e66 100644 --- a/frontend/src/shared/components/TopNavbar/index.tsx +++ b/frontend/src/shared/components/TopNavbar/index.tsx @@ -144,7 +144,7 @@ const ProjectHeading: React.FC = ({ {onFavorite && ( onFavorite()}> - + )} @@ -228,7 +228,7 @@ const NavBar: React.FC = ({ - onOpenProjectFinder($finder)}> + onOpenProjectFinder($finder)}> @@ -304,7 +304,7 @@ const NavBar: React.FC = ({ ))} {canInviteUser && ( { + onClick={($target) => { if (onInviteUser) { onInviteUser($target); } diff --git a/frontend/src/shared/icons/AngleLeft.tsx b/frontend/src/shared/icons/AngleLeft.tsx index f821e1d..8142e28 100644 --- a/frontend/src/shared/icons/AngleLeft.tsx +++ b/frontend/src/shared/icons/AngleLeft.tsx @@ -16,9 +16,4 @@ const AngleLeft = ({ size, color }: Props) => { ); }; -AngleLeft.defaultProps = { - size: 16, - color: '#000', -}; - export default AngleLeft; diff --git a/frontend/src/shared/icons/ArrowLeft.tsx b/frontend/src/shared/icons/ArrowLeft.tsx index 9a1d9c0..04634fd 100644 --- a/frontend/src/shared/icons/ArrowLeft.tsx +++ b/frontend/src/shared/icons/ArrowLeft.tsx @@ -17,10 +17,4 @@ const ArrowLeft = ({ width, height, color }: Props) => { ); }; -ArrowLeft.defaultProps = { - width: 16, - height: 16, - color: '#000', -}; - export default ArrowLeft; diff --git a/frontend/src/shared/icons/Bell.tsx b/frontend/src/shared/icons/Bell.tsx index 11a8073..a319b23 100644 --- a/frontend/src/shared/icons/Bell.tsx +++ b/frontend/src/shared/icons/Bell.tsx @@ -13,9 +13,4 @@ const Bell = ({ size, color }: Props) => { ); }; -Bell.defaultProps = { - size: 16, - color: '#000', -}; - export default Bell; diff --git a/frontend/src/shared/icons/Bin.tsx b/frontend/src/shared/icons/Bin.tsx index 31b3637..fca56a7 100644 --- a/frontend/src/shared/icons/Bin.tsx +++ b/frontend/src/shared/icons/Bin.tsx @@ -14,9 +14,4 @@ const Bin = ({ size, color }: Props) => { ); }; -Bin.defaultProps = { - size: 16, - color: '#000', -}; - export default Bin; diff --git a/frontend/src/shared/icons/Cog.tsx b/frontend/src/shared/icons/Cog.tsx index 9b260e6..ef0ee66 100644 --- a/frontend/src/shared/icons/Cog.tsx +++ b/frontend/src/shared/icons/Cog.tsx @@ -16,9 +16,4 @@ const Cog = ({ size, color }: Props) => { ); }; -Cog.defaultProps = { - size: 16, - color: '#000', -}; - export default Cog; diff --git a/frontend/src/shared/icons/Ellipsis.tsx b/frontend/src/shared/icons/Ellipsis.tsx index c3d57de..ca9988a 100644 --- a/frontend/src/shared/icons/Ellipsis.tsx +++ b/frontend/src/shared/icons/Ellipsis.tsx @@ -21,10 +21,4 @@ const Ellipsis = ({ size, color, vertical }: Props) => { ); }; -Ellipsis.defaultProps = { - size: 16, - color: '#000', - vertical: false, -}; - export default Ellipsis; diff --git a/frontend/src/shared/icons/Exit.tsx b/frontend/src/shared/icons/Exit.tsx index 473643c..a573d28 100644 --- a/frontend/src/shared/icons/Exit.tsx +++ b/frontend/src/shared/icons/Exit.tsx @@ -13,9 +13,4 @@ const Exit = ({ size, color }: Props) => { ); }; -Exit.defaultProps = { - size: 16, - color: '#000', -}; - export default Exit; diff --git a/frontend/src/shared/icons/Question.tsx b/frontend/src/shared/icons/Question.tsx index 71ca200..6f557d5 100644 --- a/frontend/src/shared/icons/Question.tsx +++ b/frontend/src/shared/icons/Question.tsx @@ -13,9 +13,4 @@ const Question = ({ size, color }: Props) => { ); }; -Question.defaultProps = { - size: 16, - color: '#000', -}; - export default Question; diff --git a/frontend/src/shared/icons/Stack.tsx b/frontend/src/shared/icons/Stack.tsx index e26af53..5558eaa 100644 --- a/frontend/src/shared/icons/Stack.tsx +++ b/frontend/src/shared/icons/Stack.tsx @@ -13,9 +13,4 @@ const Stack = ({ size, color }: Props) => { ); }; -Stack.defaultProps = { - size: 16, - color: '#000', -}; - export default Stack; diff --git a/frontend/src/shared/icons/Star.tsx b/frontend/src/shared/icons/Star.tsx index 85e96f2..0cf365b 100644 --- a/frontend/src/shared/icons/Star.tsx +++ b/frontend/src/shared/icons/Star.tsx @@ -25,11 +25,4 @@ const Star = ({ width, height, color, filled }: Props) => { ); }; -Star.defaultProps = { - width: 24, - height: 16, - color: '#000', - filled: false, -}; - export default Star; diff --git a/frontend/src/shared/icons/Users.tsx b/frontend/src/shared/icons/Users.tsx index 1473aff..3282e41 100644 --- a/frontend/src/shared/icons/Users.tsx +++ b/frontend/src/shared/icons/Users.tsx @@ -14,9 +14,4 @@ const Users = ({ size, color }: Props) => { ); }; -Users.defaultProps = { - size: 16, - color: '#000', -}; - export default Users; diff --git a/frontend/src/shared/utils/cache.ts b/frontend/src/shared/utils/cache.ts index a1105a8..f934a11 100644 --- a/frontend/src/shared/utils/cache.ts +++ b/frontend/src/shared/utils/cache.ts @@ -7,7 +7,7 @@ export function updateApolloCache( client: DataProxy, document: DocumentNode, update: UpdateCacheFn, - variables?: object, + variables?: any, ) { let queryArgs: DataProxy.Query; if (variables) { diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 0dff722..97025ff 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -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"