fix: unify popup content padding

This commit is contained in:
Jordan Knott 2020-07-16 22:31:33 -05:00
parent c35f63e668
commit 1222111bef
6 changed files with 207 additions and 200 deletions

View File

@ -3,11 +3,11 @@ import Admin from 'shared/components/Admin';
import Select from 'shared/components/Select'; import Select from 'shared/components/Select';
import GlobalTopNavbar from 'App/TopNavbar'; import GlobalTopNavbar from 'App/TopNavbar';
import { import {
useUsersQuery, useUsersQuery,
useDeleteUserAccountMutation, useDeleteUserAccountMutation,
useCreateUserAccountMutation, useCreateUserAccountMutation,
UsersDocument, UsersDocument,
UsersQuery, UsersQuery,
} from 'shared/generated/graphql'; } from 'shared/generated/graphql';
import Input from 'shared/components/Input'; import Input from 'shared/components/Input';
import styled from 'styled-components'; import styled from 'styled-components';
@ -33,29 +33,30 @@ const DeleteUserButton = styled(Button)`
`; `;
type DeleteUserPopupProps = { type DeleteUserPopupProps = {
onDeleteUser: () => void; onDeleteUser: () => void;
}; };
const DeleteUserPopup: React.FC<DeleteUserPopupProps> = ({ onDeleteUser }) => { const DeleteUserPopup: React.FC<DeleteUserPopupProps> = ({ onDeleteUser }) => {
return ( return (
<DeleteUserWrapper> <DeleteUserWrapper>
<DeleteUserDescription>Deleting this user will remove all user related data.</DeleteUserDescription> <DeleteUserDescription>Deleting this user will remove all user related data.</DeleteUserDescription>
<DeleteUserButton onClick={() => onDeleteUser()} color="danger"> <DeleteUserButton onClick={() => onDeleteUser()} color="danger">
Delete user Delete user
</DeleteUserButton> </DeleteUserButton>
</DeleteUserWrapper> </DeleteUserWrapper>
); );
}; };
type CreateUserData = { type CreateUserData = {
email: string; email: string;
username: string; username: string;
fullName: string; fullName: string;
initials: string; initials: string;
password: string; password: string;
roleCode: string; roleCode: string;
}; };
const CreateUserForm = styled.form` const CreateUserForm = styled.form`
display: flex; display: flex;
flex-direction: column; flex-direction: column;
margin: 0 12px;
`; `;
const CreateUserButton = styled(Button)` const CreateUserButton = styled(Button)`
margin-top: 8px; margin-top: 8px;
@ -73,167 +74,167 @@ const InputError = styled.span`
`; `;
type AddUserPopupProps = { type AddUserPopupProps = {
onAddUser: (user: CreateUserData) => void; onAddUser: (user: CreateUserData) => void;
}; };
const AddUserPopup: React.FC<AddUserPopupProps> = ({ onAddUser }) => { const AddUserPopup: React.FC<AddUserPopupProps> = ({ onAddUser }) => {
const { register, handleSubmit, errors, setValue } = useForm<CreateUserData>(); const { register, handleSubmit, errors, setValue } = useForm<CreateUserData>();
const [role, setRole] = useState<string | null>(null); const [role, setRole] = useState<string | null>(null);
register({ name: 'roleCode' }, { required: true }); register({ name: 'roleCode' }, { required: true });
const createUser = (data: CreateUserData) => { const createUser = (data: CreateUserData) => {
onAddUser(data); onAddUser(data);
}; };
return ( return (
<CreateUserForm onSubmit={handleSubmit(createUser)}> <CreateUserForm onSubmit={handleSubmit(createUser)}>
<AddUserInput <AddUserInput
floatingLabel floatingLabel
width="100%" width="100%"
label="Full Name" label="Full Name"
id="fullName" id="fullName"
name="fullName" name="fullName"
variant="alternate" variant="alternate"
ref={register({ required: 'Full name is required' })} ref={register({ required: 'Full name is required' })}
/> />
{errors.fullName && <InputError>{errors.fullName.message}</InputError>} {errors.fullName && <InputError>{errors.fullName.message}</InputError>}
<AddUserInput <AddUserInput
floatingLabel floatingLabel
width="100%" width="100%"
label="Email" label="Email"
id="email" id="email"
name="email" name="email"
variant="alternate" variant="alternate"
ref={register({ required: 'Email is required' })} ref={register({ required: 'Email is required' })}
/> />
<Select <Select
label="Role" label="Role"
value={role} value={role}
options={[ options={[
{ label: 'Admin', value: 'admin' }, { label: 'Admin', value: 'admin' },
{ label: 'Member', value: 'member' }, { label: 'Member', value: 'member' },
]} ]}
onChange={newRole => { onChange={newRole => {
setRole(newRole); setRole(newRole);
setValue('roleCode', newRole.value); setValue('roleCode', newRole.value);
}} }}
/> />
{errors.email && <InputError>{errors.email.message}</InputError>} {errors.email && <InputError>{errors.email.message}</InputError>}
<AddUserInput <AddUserInput
floatingLabel floatingLabel
width="100%" width="100%"
label="Username" label="Username"
id="username" id="username"
name="username" name="username"
variant="alternate" variant="alternate"
ref={register({ required: 'Username is required' })} ref={register({ required: 'Username is required' })}
/> />
{errors.username && <InputError>{errors.username.message}</InputError>} {errors.username && <InputError>{errors.username.message}</InputError>}
<AddUserInput <AddUserInput
floatingLabel floatingLabel
width="100%" width="100%"
label="Initials" label="Initials"
id="initials" id="initials"
name="initials" name="initials"
variant="alternate" variant="alternate"
ref={register({ required: 'Initials is required' })} ref={register({ required: 'Initials is required' })}
/> />
{errors.initials && <InputError>{errors.initials.message}</InputError>} {errors.initials && <InputError>{errors.initials.message}</InputError>}
<AddUserInput <AddUserInput
floatingLabel floatingLabel
width="100%" width="100%"
label="Password" label="Password"
id="password" id="password"
name="password" name="password"
variant="alternate" variant="alternate"
ref={register({ required: 'Password is required' })} ref={register({ required: 'Password is required' })}
/> />
{errors.password && <InputError>{errors.password.message}</InputError>} {errors.password && <InputError>{errors.password.message}</InputError>}
<CreateUserButton type="submit">Create</CreateUserButton> <CreateUserButton type="submit">Create</CreateUserButton>
</CreateUserForm> </CreateUserForm>
); );
}; };
const AdminRoute = () => { const AdminRoute = () => {
useEffect(() => { useEffect(() => {
document.title = 'Citadel | Admin'; document.title = 'Citadel | Admin';
}, []); }, []);
const { loading, data } = useUsersQuery(); const { loading, data } = useUsersQuery();
const { showPopup, hidePopup } = usePopup(); const { showPopup, hidePopup } = usePopup();
const [deleteUser] = useDeleteUserAccountMutation({ const [deleteUser] = useDeleteUserAccountMutation({
update: (client, response) => { update: (client, response) => {
updateApolloCache<UsersQuery>(client, UsersDocument, cache => updateApolloCache<UsersQuery>(client, UsersDocument, cache =>
produce(cache, draftCache => { produce(cache, draftCache => {
draftCache.users = cache.users.filter(u => u.id !== response.data.deleteUserAccount.userAccount.id); draftCache.users = cache.users.filter(u => u.id !== response.data.deleteUserAccount.userAccount.id);
}), }),
); );
}, },
}); });
const [createUser] = useCreateUserAccountMutation({ const [createUser] = useCreateUserAccountMutation({
update: (client, createData) => { update: (client, createData) => {
const cacheData: any = client.readQuery({ const cacheData: any = client.readQuery({
query: UsersDocument, query: UsersDocument,
}); });
console.log(cacheData); console.log(cacheData);
console.log(createData); console.log(createData);
const newData = produce(cacheData, (draftState: any) => { const newData = produce(cacheData, (draftState: any) => {
draftState.users = [...draftState.users, { ...createData.data.createUserAccount }]; draftState.users = [...draftState.users, { ...createData.data.createUserAccount }];
}); });
client.writeQuery({ client.writeQuery({
query: UsersDocument, query: UsersDocument,
data: { data: {
...newData, ...newData,
},
});
}, },
}); });
if (loading) { },
return <GlobalTopNavbar projectID={null} onSaveProjectName={() => { }} name={null} />; });
} if (loading) {
if (data) { return <GlobalTopNavbar projectID={null} onSaveProjectName={() => {}} name={null} />;
return ( }
<> if (data) {
<GlobalTopNavbar projectID={null} onSaveProjectName={() => { }} name={null} /> return (
<Admin <>
initialTab={1} <GlobalTopNavbar projectID={null} onSaveProjectName={() => {}} name={null} />
users={data.users} <Admin
onInviteUser={() => { }} initialTab={1}
onUpdateUserPassword={(user, password) => { users={data.users}
console.log(user) onInviteUser={() => {}}
console.log(password) onUpdateUserPassword={(user, password) => {
hidePopup() console.log(user);
}} console.log(password);
onDeleteUser={($target, userID) => { hidePopup();
showPopup( }}
$target, onDeleteUser={($target, userID) => {
<Popup tab={0} title="Delete user?" onClose={() => hidePopup()}> showPopup(
<DeleteUserPopup $target,
onDeleteUser={() => { <Popup tab={0} title="Delete user?" onClose={() => hidePopup()}>
deleteUser({ variables: { userID } }); <DeleteUserPopup
hidePopup(); onDeleteUser={() => {
}} deleteUser({ variables: { userID } });
/> hidePopup();
</Popup>, }}
);
}}
onAddUser={$target => {
showPopup(
$target,
<Popup tab={0} title="Add member" onClose={() => hidePopup()}>
<AddUserPopup
onAddUser={user => {
createUser({ variables: { ...user } });
hidePopup();
}}
/>
</Popup>,
);
}}
/> />
</> </Popup>,
); );
} }}
return <span>error</span>; onAddUser={$target => {
showPopup(
$target,
<Popup tab={0} title="Add member" onClose={() => hidePopup()}>
<AddUserPopup
onAddUser={user => {
createUser({ variables: { ...user } });
hidePopup();
}}
/>
</Popup>,
);
}}
/>
</>
);
}
return <span>error</span>;
}; };
export default AdminRoute; export default AdminRoute;

View File

@ -1,9 +1,9 @@
import React, {useState, useContext, useEffect} from 'react'; import React, { useState, useContext, useEffect } from 'react';
import TopNavbar, {MenuItem} from 'shared/components/TopNavbar'; import TopNavbar, { MenuItem } from 'shared/components/TopNavbar';
import styled from 'styled-components/macro'; import styled from 'styled-components/macro';
import DropdownMenu, {ProfileMenu} from 'shared/components/DropdownMenu'; import DropdownMenu, { ProfileMenu } from 'shared/components/DropdownMenu';
import ProjectSettings, {DeleteConfirm, DELETE_INFO} from 'shared/components/ProjectSettings'; import ProjectSettings, { DeleteConfirm, DELETE_INFO } from 'shared/components/ProjectSettings';
import {useHistory} from 'react-router'; import { useHistory } from 'react-router';
import UserIDContext from 'App/context'; import UserIDContext from 'App/context';
import { import {
RoleCode, RoleCode,
@ -12,14 +12,15 @@ import {
useGetProjectsQuery, useGetProjectsQuery,
GetProjectsDocument, GetProjectsDocument,
} from 'shared/generated/graphql'; } from 'shared/generated/graphql';
import {usePopup, Popup} from 'shared/components/PopupMenu'; import { usePopup, Popup } from 'shared/components/PopupMenu';
import {History} from 'history'; import { History } from 'history';
import produce from 'immer'; import produce from 'immer';
import {Link} from 'react-router-dom'; import { Link } from 'react-router-dom';
const TeamContainer = styled.div` const TeamContainer = styled.div`
display: flex; display: flex;
flex-direction: column; flex-direction: column;
margin: 0 8px;
`; `;
const TeamTitle = styled.h3` const TeamTitle = styled.h3`
@ -45,7 +46,7 @@ const TeamProjectLink = styled(Link)`
user-select: none; user-select: none;
`; `;
const TeamProjectBackground = styled.div<{color: string}>` const TeamProjectBackground = styled.div<{ color: string }>`
background-image: url(null); background-image: url(null);
background-color: ${props => props.color}; background-color: ${props => props.color};
@ -68,7 +69,7 @@ const TeamProjectBackground = styled.div<{color: string}>`
} }
`; `;
const TeamProjectAvatar = styled.div<{color: string}>` const TeamProjectAvatar = styled.div<{ color: string }>`
background-image: url(null); background-image: url(null);
background-color: ${props => props.color}; background-color: ${props => props.color};
@ -122,12 +123,12 @@ const TeamProjectContainer = styled.div`
const colors = ['#e362e3', '#7a6ff0', '#37c5ab', '#aa62e3', '#e8384f']; const colors = ['#e362e3', '#7a6ff0', '#37c5ab', '#aa62e3', '#e8384f'];
const ProjectFinder = () => { const ProjectFinder = () => {
const {loading, data} = useGetProjectsQuery(); const { loading, data } = useGetProjectsQuery();
if (loading) { if (loading) {
return <span>loading</span>; return <span>loading</span>;
} }
if (data) { if (data) {
const {projects, teams, organizations} = data; const { projects, teams, organizations } = data;
const projectTeams = teams.map(team => { const projectTeams = teams.map(team => {
return { return {
id: team.id, id: team.id,
@ -166,8 +167,8 @@ type ProjectPopupProps = {
projectID: string; projectID: string;
}; };
export const ProjectPopup: React.FC<ProjectPopupProps> = ({history, name, projectID}) => { export const ProjectPopup: React.FC<ProjectPopupProps> = ({ history, name, projectID }) => {
const {hidePopup, setTab} = usePopup(); const { hidePopup, setTab } = usePopup();
const [deleteProject] = useDeleteProjectMutation({ const [deleteProject] = useDeleteProjectMutation({
update: (client, deleteData) => { update: (client, deleteData) => {
const cacheData: any = client.readQuery({ const cacheData: any = client.readQuery({
@ -206,7 +207,7 @@ export const ProjectPopup: React.FC<ProjectPopupProps> = ({history, name, projec
deletedItems={DELETE_INFO.DELETE_PROJECTS.deletedItems} deletedItems={DELETE_INFO.DELETE_PROJECTS.deletedItems}
onConfirmDelete={() => { onConfirmDelete={() => {
if (projectID) { if (projectID) {
deleteProject({variables: {projectID}}); deleteProject({ variables: { projectID } });
hidePopup(); hidePopup();
history.push('/projects'); history.push('/projects');
} }
@ -249,16 +250,16 @@ const GlobalTopNavbar: React.FC<GlobalTopNavbarProps> = ({
nameOnly, nameOnly,
}) => { }) => {
console.log(popupContent); console.log(popupContent);
const {loading, data} = useMeQuery(); const { loading, data } = useMeQuery();
const {showPopup, hidePopup, setTab} = usePopup(); const { showPopup, hidePopup, setTab } = usePopup();
const history = useHistory(); const history = useHistory();
const {userID, setUserID} = useContext(UserIDContext); const { userID, setUserID } = useContext(UserIDContext);
const onLogout = () => { const onLogout = () => {
fetch('/auth/logout', { fetch('/auth/logout', {
method: 'POST', method: 'POST',
credentials: 'include', credentials: 'include',
}).then(async x => { }).then(async x => {
const {status} = x; const { status } = x;
if (status === 200) { if (status === 200) {
history.replace('/login'); history.replace('/login');
setUserID(null); setUserID(null);

View File

@ -18,13 +18,14 @@ import styled, { css } from 'styled-components/macro';
import { usePopup, Popup } from 'shared/components/PopupMenu'; import { usePopup, Popup } from 'shared/components/PopupMenu';
import TaskAssignee from 'shared/components/TaskAssignee'; import TaskAssignee from 'shared/components/TaskAssignee';
import Member from 'shared/components/Member'; import Member from 'shared/components/Member';
import ControlledInput from 'shared/components/ControlledInput';
const MemberListWrapper = styled.div` const MemberListWrapper = styled.div`
flex: 1 1; flex: 1 1;
`; `;
const SearchInput = styled(Input)` const SearchInput = styled(ControlledInput)`
margin: 0; margin: 0 12px;
`; `;
const UserMember = styled(Member)` const UserMember = styled(Member)`
@ -37,7 +38,7 @@ const UserMember = styled(Member)`
`; `;
const TeamMemberList = styled.div` const TeamMemberList = styled.div`
margin: 8px 0; margin: 8px 12px;
`; `;
type UserManagementPopupProps = { type UserManagementPopupProps = {

View File

@ -33,3 +33,7 @@ export const ListSeparator = styled.hr`
padding: 0; padding: 0;
width: 100%; width: 100%;
`; `;
export const InnerContent = styled.div`
margin: 0 12px;
`;

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { ListActionsWrapper, ListActionItemWrapper, ListActionItem, ListSeparator } from './Styles'; import { InnerContent, ListActionsWrapper, ListActionItemWrapper, ListActionItem, ListSeparator } from './Styles';
type Props = { type Props = {
taskGroupID: string; taskGroupID: string;
@ -8,7 +8,7 @@ type Props = {
}; };
const LabelManager: React.FC<Props> = ({ taskGroupID, onArchiveTaskGroup }) => { const LabelManager: React.FC<Props> = ({ taskGroupID, onArchiveTaskGroup }) => {
return ( return (
<> <InnerContent>
<ListActionsWrapper> <ListActionsWrapper>
<ListActionItemWrapper> <ListActionItemWrapper>
<ListActionItem>Add card...</ListActionItem> <ListActionItem>Add card...</ListActionItem>
@ -44,7 +44,7 @@ const LabelManager: React.FC<Props> = ({ taskGroupID, onArchiveTaskGroup }) => {
<ListActionItem>Archive This List</ListActionItem> <ListActionItem>Archive This List</ListActionItem>
</ListActionItemWrapper> </ListActionItemWrapper>
</ListActionsWrapper> </ListActionsWrapper>
</> </InnerContent>
); );
}; };
export default LabelManager; export default LabelManager;

View File

@ -5,7 +5,7 @@ import Button from 'shared/components/Button';
export const ListActionsWrapper = styled.ul` export const ListActionsWrapper = styled.ul`
list-style-type: none; list-style-type: none;
margin: 0; margin: 0 12px;
padding: 0; padding: 0;
`; `;
@ -40,7 +40,7 @@ export const ListSeparator = styled.hr`
type Props = { type Props = {
onDeleteProject: () => void; onDeleteProject: () => void;
}; };
const ProjectSettings: React.FC<Props> = ({onDeleteProject}) => { const ProjectSettings: React.FC<Props> = ({ onDeleteProject }) => {
return ( return (
<> <>
<ListActionsWrapper> <ListActionsWrapper>
@ -55,7 +55,7 @@ const ProjectSettings: React.FC<Props> = ({onDeleteProject}) => {
type TeamSettingsProps = { type TeamSettingsProps = {
onDeleteTeam: () => void; onDeleteTeam: () => void;
}; };
export const TeamSettings: React.FC<TeamSettingsProps> = ({onDeleteTeam}) => { export const TeamSettings: React.FC<TeamSettingsProps> = ({ onDeleteTeam }) => {
return ( return (
<> <>
<ListActionsWrapper> <ListActionsWrapper>
@ -109,7 +109,7 @@ export const DELETE_INFO = {
}, },
}; };
const DeleteConfirm: React.FC<DeleteConfirmProps> = ({description, deletedItems, onConfirmDelete}) => { const DeleteConfirm: React.FC<DeleteConfirmProps> = ({ description, deletedItems, onConfirmDelete }) => {
return ( return (
<ConfirmWrapper> <ConfirmWrapper>
<ConfirmDescription> <ConfirmDescription>
@ -127,5 +127,5 @@ const DeleteConfirm: React.FC<DeleteConfirmProps> = ({description, deletedItems,
); );
}; };
export {DeleteConfirm}; export { DeleteConfirm };
export default ProjectSettings; export default ProjectSettings;