Various fixes on table, board, tasks (#983)
* Misc fixes * Misc fixes * Misc fixes * Fix login
This commit is contained in:
@ -35,6 +35,7 @@ const StyledContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const StyledCheckboxContainer = styled.div`
|
||||
|
||||
@ -6,8 +6,8 @@ import {
|
||||
ChipSize,
|
||||
ChipVariant,
|
||||
} from '@/ui/chip/components/Chip';
|
||||
import { IconPhone } from '@/ui/icon';
|
||||
import { Activity } from '~/generated/graphql';
|
||||
import { IconCheckbox, IconNotes } from '@/ui/icon';
|
||||
import { Activity, ActivityType } from '~/generated/graphql';
|
||||
|
||||
type OwnProps = {
|
||||
activity: Pick<Activity, 'type'>;
|
||||
@ -18,7 +18,13 @@ export function ActivityTypeDropdown({ activity }: OwnProps) {
|
||||
return (
|
||||
<Chip
|
||||
label={activity.type}
|
||||
leftComponent={<IconPhone size={theme.icon.size.md} />}
|
||||
leftComponent={
|
||||
activity.type === ActivityType.Note ? (
|
||||
<IconNotes size={theme.icon.size.md} />
|
||||
) : (
|
||||
<IconCheckbox size={theme.icon.size.md} />
|
||||
)
|
||||
}
|
||||
size={ChipSize.Large}
|
||||
accent={ChipAccent.TextSecondary}
|
||||
variant={ChipVariant.Highlighted}
|
||||
|
||||
@ -1,23 +1,8 @@
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
import React from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { ActivityBodyEditor } from '@/activities/components/ActivityBodyEditor';
|
||||
import { ActivityComments } from '@/activities/components/ActivityComments';
|
||||
import { ActivityRelationPicker } from '@/activities/components/ActivityRelationPicker';
|
||||
import { ActivityTypeDropdown } from '@/activities/components/ActivityTypeDropdown';
|
||||
import { GET_ACTIVITY } from '@/activities/queries';
|
||||
import { PropertyBox } from '@/ui/editable-field/property-box/components/PropertyBox';
|
||||
import { PropertyBoxItem } from '@/ui/editable-field/property-box/components/PropertyBoxItem';
|
||||
import { useIsMobile } from '@/ui/hooks/useIsMobile';
|
||||
import { IconArrowUpRight } from '@/ui/icon/index';
|
||||
import {
|
||||
useGetActivityQuery,
|
||||
useUpdateActivityMutation,
|
||||
} from '~/generated/graphql';
|
||||
import { debounce } from '~/utils/debounce';
|
||||
|
||||
import { ActivityActionBar } from './ActivityActionBar';
|
||||
import { ActivityEditor } from '@/activities/components/ActivityEditor';
|
||||
import { useGetActivityQuery } from '~/generated/graphql';
|
||||
|
||||
import '@blocknote/core/style.css';
|
||||
|
||||
@ -30,59 +15,6 @@ const StyledContainer = styled.div`
|
||||
overflow-y: auto;
|
||||
`;
|
||||
|
||||
const StyledUpperPartContainer = styled.div`
|
||||
align-items: flex-start;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
gap: ${({ theme }) => theme.spacing(4)};
|
||||
justify-content: flex-start;
|
||||
`;
|
||||
|
||||
const StyledTopContainer = styled.div`
|
||||
align-items: flex-start;
|
||||
align-self: stretch;
|
||||
background: ${({ theme }) => theme.background.secondary};
|
||||
border-bottom: ${({ theme }) =>
|
||||
useIsMobile() ? 'none' : `1px solid ${theme.border.color.medium}`};
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
padding: 24px 24px 24px 48px;
|
||||
`;
|
||||
|
||||
const StyledEditableTitleInput = styled.input`
|
||||
background: transparent;
|
||||
|
||||
border: none;
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
display: flex;
|
||||
flex: 1 0 0;
|
||||
|
||||
flex-direction: column;
|
||||
font-family: Inter;
|
||||
font-size: ${({ theme }) => theme.font.size.xl};
|
||||
font-style: normal;
|
||||
font-weight: ${({ theme }) => theme.font.weight.semiBold};
|
||||
justify-content: center;
|
||||
|
||||
line-height: ${({ theme }) => theme.text.lineHeight.md};
|
||||
outline: none;
|
||||
width: calc(100% - ${({ theme }) => theme.spacing(2)});
|
||||
&::placeholder {
|
||||
color: ${({ theme }) => theme.font.color.light};
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledTopActionsContainer = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
type OwnProps = {
|
||||
activityId: string;
|
||||
showComment?: boolean;
|
||||
@ -101,50 +33,6 @@ export function Activity({
|
||||
skip: !activityId,
|
||||
});
|
||||
const activity = data?.findManyActivities[0];
|
||||
const [hasUserManuallySetTitle, setHasUserManuallySetTitle] =
|
||||
useState<boolean>(false);
|
||||
|
||||
const [title, setTitle] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasUserManuallySetTitle) {
|
||||
setTitle(activity?.title ?? '');
|
||||
}
|
||||
}, [setTitle, activity?.title, hasUserManuallySetTitle]);
|
||||
|
||||
const [updateActivityMutation] = useUpdateActivityMutation();
|
||||
|
||||
const debounceUpdateTitle = useMemo(() => {
|
||||
function updateTitle(title: string) {
|
||||
if (activity) {
|
||||
updateActivityMutation({
|
||||
variables: {
|
||||
id: activityId,
|
||||
title: title ?? '',
|
||||
},
|
||||
refetchQueries: [getOperationName(GET_ACTIVITY) ?? ''],
|
||||
optimisticResponse: {
|
||||
__typename: 'Mutation',
|
||||
updateOneActivity: {
|
||||
__typename: 'Activity',
|
||||
id: activityId,
|
||||
title: title,
|
||||
type: activity.type,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
return debounce(updateTitle, 200);
|
||||
}, [activityId, updateActivityMutation, activity]);
|
||||
|
||||
function updateTitleFromBody(body: string) {
|
||||
const parsedTitle = JSON.parse(body)[0]?.content[0]?.text;
|
||||
if (!hasUserManuallySetTitle && autoFillTitle) {
|
||||
setTitle(parsedTitle);
|
||||
debounceUpdateTitle(parsedTitle);
|
||||
}
|
||||
}
|
||||
|
||||
if (!activity) {
|
||||
return <></>;
|
||||
@ -152,50 +40,11 @@ export function Activity({
|
||||
|
||||
return (
|
||||
<StyledContainer>
|
||||
<StyledUpperPartContainer>
|
||||
<StyledTopContainer>
|
||||
<StyledTopActionsContainer>
|
||||
<ActivityTypeDropdown activity={activity} />
|
||||
<ActivityActionBar activityId={activity?.id ?? ''} />
|
||||
</StyledTopActionsContainer>
|
||||
<StyledEditableTitleInput
|
||||
autoFocus
|
||||
placeholder={`${activity.type} title (optional)`}
|
||||
onChange={(event) => {
|
||||
setHasUserManuallySetTitle(true);
|
||||
setTitle(event.target.value);
|
||||
debounceUpdateTitle(event.target.value);
|
||||
}}
|
||||
value={title ?? ''}
|
||||
/>
|
||||
<PropertyBox>
|
||||
<PropertyBoxItem
|
||||
icon={<IconArrowUpRight />}
|
||||
value={
|
||||
<ActivityRelationPicker
|
||||
activity={{
|
||||
id: activity.id,
|
||||
activityTargets: activity.activityTargets ?? [],
|
||||
}}
|
||||
/>
|
||||
}
|
||||
label="Relations"
|
||||
/>
|
||||
</PropertyBox>
|
||||
</StyledTopContainer>
|
||||
<ActivityBodyEditor
|
||||
activity={activity}
|
||||
onChange={updateTitleFromBody}
|
||||
/>
|
||||
</StyledUpperPartContainer>
|
||||
{showComment && (
|
||||
<ActivityComments
|
||||
activity={{
|
||||
id: activity.id,
|
||||
comments: activity.comments ?? [],
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<ActivityEditor
|
||||
activity={activity}
|
||||
showComment={showComment}
|
||||
autoFillTitle={autoFillTitle}
|
||||
/>
|
||||
</StyledContainer>
|
||||
);
|
||||
}
|
||||
|
||||
@ -147,7 +147,7 @@ export function TimelineActivity({ activity }: OwnProps) {
|
||||
</StyledIconContainer>
|
||||
<StyledItemTitleContainer>
|
||||
<span>{activity.author.displayName}</span>
|
||||
created a note created a {activity.type.toLowerCase()}
|
||||
created a {activity.type.toLowerCase()}
|
||||
</StyledItemTitleContainer>
|
||||
<StyledItemTitleDate id={`id-${activity.id}`}>
|
||||
{beautifiedCreatedAt} ago
|
||||
|
||||
@ -12,7 +12,7 @@ const StyledTitleContainer = styled.div`
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
line-height: ${({ theme }) => theme.text.lineHeight.lg};
|
||||
|
||||
width: 100%;
|
||||
width: calc(100% - ${({ theme }) => theme.spacing(6)});
|
||||
`;
|
||||
|
||||
const StyledTitleText = styled.div<{ completed?: boolean }>`
|
||||
@ -24,7 +24,6 @@ const StyledCheckboxContainer = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
type OwnProps = {
|
||||
|
||||
@ -77,7 +77,7 @@ export function useAuth() {
|
||||
const { loginToken } = await handleChallenge(email, password);
|
||||
|
||||
const { user } = await handleVerify(loginToken.token);
|
||||
return { user };
|
||||
return user;
|
||||
},
|
||||
[handleChallenge, handleVerify],
|
||||
);
|
||||
@ -112,7 +112,7 @@ export function useAuth() {
|
||||
signUpResult.data?.signUp.loginToken.token,
|
||||
);
|
||||
|
||||
return { user };
|
||||
return user;
|
||||
},
|
||||
[signUp, handleVerify],
|
||||
);
|
||||
|
||||
@ -105,16 +105,21 @@ export function useSignInUp() {
|
||||
if (!data.email || !data.password) {
|
||||
throw new Error('Email and password are required');
|
||||
}
|
||||
let user;
|
||||
if (signInUpMode === SignInUpMode.SignIn) {
|
||||
await signInWithCredentials(data.email, data.password);
|
||||
user = await signInWithCredentials(data.email, data.password);
|
||||
} else {
|
||||
await signUpWithCredentials(
|
||||
user = await signUpWithCredentials(
|
||||
data.email,
|
||||
data.password,
|
||||
workspaceInviteHash,
|
||||
);
|
||||
}
|
||||
navigate('/create/workspace');
|
||||
if (user?.workspaceMember?.workspace?.displayName) {
|
||||
navigate('/');
|
||||
} else {
|
||||
navigate('/create/workspace');
|
||||
}
|
||||
} catch (err: any) {
|
||||
enqueueSnackBar(err?.message, {
|
||||
variant: 'error',
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { PersonChip } from '@/people/components/PersonChip';
|
||||
import { EditableField } from '@/ui/editable-field/components/EditableField';
|
||||
import { FieldContext } from '@/ui/editable-field/states/FieldContext';
|
||||
import { IconUserCircle } from '@/ui/icon';
|
||||
import { RecoilScope } from '@/ui/recoil-scope/components/RecoilScope';
|
||||
import { RelationPickerHotkeyScope } from '@/ui/relation-picker/types/RelationPickerHotkeyScope';
|
||||
import { UserChip } from '@/users/components/UserChip';
|
||||
import { Company, User } from '~/generated/graphql';
|
||||
|
||||
import { CompanyAccountOwnerPickerFieldEditMode } from './CompanyAccountOwnerPickerFieldEditMode';
|
||||
@ -28,7 +28,7 @@ export function CompanyAccountOwnerEditableField({ company }: OwnProps) {
|
||||
}
|
||||
displayModeContent={
|
||||
company.accountOwner?.displayName ? (
|
||||
<PersonChip
|
||||
<UserChip
|
||||
id={company.accountOwner.id}
|
||||
name={company.accountOwner?.displayName ?? ''}
|
||||
pictureUrl={company.accountOwner?.avatarUrl ?? ''}
|
||||
|
||||
@ -23,14 +23,14 @@ export function EditableCompanyAddressCell() {
|
||||
return (
|
||||
<EditableCellText
|
||||
value={internalValue}
|
||||
onSubmit={() =>
|
||||
onSubmit={(newValue: string) =>
|
||||
updateCompany({
|
||||
variables: {
|
||||
where: {
|
||||
id: currentRowEntityId,
|
||||
},
|
||||
data: {
|
||||
address: internalValue,
|
||||
address: newValue,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@ -2,6 +2,7 @@ import { getOperationName } from '@apollo/client/utilities';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { GET_COMPANIES } from '@/companies/queries';
|
||||
import { GET_PIPELINES } from '@/pipeline/queries';
|
||||
import { IconTrash } from '@/ui/icon/index';
|
||||
import { EntityTableActionBarButton } from '@/ui/table/action-bar/components/EntityTableActionBarButton';
|
||||
import { useResetTableRowSelection } from '@/ui/table/hooks/useResetTableRowSelection';
|
||||
@ -14,7 +15,10 @@ export function TableActionBarButtonDeleteCompanies() {
|
||||
const resetRowSelection = useResetTableRowSelection();
|
||||
|
||||
const [deleteCompanies] = useDeleteManyCompaniesMutation({
|
||||
refetchQueries: [getOperationName(GET_COMPANIES) ?? ''],
|
||||
refetchQueries: [
|
||||
getOperationName(GET_COMPANIES) ?? '',
|
||||
getOperationName(GET_PIPELINES) ?? '',
|
||||
],
|
||||
});
|
||||
|
||||
async function handleDeleteClick() {
|
||||
|
||||
@ -21,6 +21,7 @@ export function PeopleCompanyEditableField({ people }: OwnProps) {
|
||||
<RecoilScope SpecificContext={FieldContext}>
|
||||
<RecoilScope>
|
||||
<EditableField
|
||||
useEditButton
|
||||
customEditHotkeyScope={{
|
||||
scope: RelationPickerHotkeyScope.RelationPicker,
|
||||
}}
|
||||
|
||||
@ -125,6 +125,10 @@ export function EntityBoardColumn({
|
||||
{(draggableProvided) => (
|
||||
<div
|
||||
ref={draggableProvided?.innerRef}
|
||||
{...{
|
||||
...draggableProvided.dragHandleProps,
|
||||
draggable: false,
|
||||
}}
|
||||
{...draggableProvided?.draggableProps}
|
||||
>
|
||||
<StyledNewCardButtonContainer>
|
||||
|
||||
@ -82,6 +82,7 @@ export function PipelineProgressPointOfContactPicker({
|
||||
return (
|
||||
<SingleEntitySelect
|
||||
onCreate={handleCreate}
|
||||
onCancel={onCancel}
|
||||
onEntitySelected={handleEntitySelected}
|
||||
entities={{
|
||||
entitiesToSelect: people.entitiesToSelect,
|
||||
|
||||
@ -21,6 +21,7 @@ export function PipelineProgressPointOfContactEditableField({
|
||||
<RecoilScope SpecificContext={FieldContext}>
|
||||
<RecoilScope>
|
||||
<EditableField
|
||||
useEditButton
|
||||
customEditHotkeyScope={{
|
||||
scope: RelationPickerHotkeyScope.RelationPicker,
|
||||
}}
|
||||
|
||||
@ -36,9 +36,13 @@ const StyledCenteredButton = styled(Button)`
|
||||
|
||||
export const StyledDeleteButton = styled(StyledCenteredButton)`
|
||||
border-color: ${({ theme }) => theme.color.red20};
|
||||
box-shadow: none;
|
||||
color: ${({ theme }) => theme.color.red};
|
||||
font-size: ${({ theme }) => theme.font.size.md};
|
||||
line-height: ${({ theme }) => theme.text.lineHeight.lg};
|
||||
:hover {
|
||||
background-color: ${({ theme }) => theme.color.red10};
|
||||
}
|
||||
`;
|
||||
|
||||
export function DeleteModal({
|
||||
|
||||
@ -31,9 +31,9 @@ export function EntityChip({
|
||||
const navigate = useNavigate();
|
||||
|
||||
function handleLinkClick(event: React.MouseEvent<HTMLDivElement>) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
if (linkToEntity) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
navigate(linkToEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,6 +153,7 @@ export class WorkspaceService {
|
||||
refreshToken.deleteMany({
|
||||
where: { userId },
|
||||
}),
|
||||
// Todo delete all users from this workspace
|
||||
user.delete({
|
||||
where: {
|
||||
id: userId,
|
||||
|
||||
Reference in New Issue
Block a user