From 07a8f68ef180984de2ce8df9671dce18d51143c2 Mon Sep 17 00:00:00 2001 From: Weiko Date: Thu, 10 Aug 2023 11:26:27 -0700 Subject: [PATCH 01/10] Add FieldDefinition (#1162) * add fieldDefinition * update naming * use a unique contextProvider for editable fields * remove EntityUpdateMutationHookContext.Provider usage in CompanyBoardCard * add fieldDefinitionState * remove unnecessary refetchQueries to avoid re-render * add FieldMetadata * add type guards and update useUpdateGenericEntityField * restore refetchQueries --- .../activities/hooks/useCompleteTask.ts | 2 - .../companies/components/CompanyBoardCard.tsx | 90 ++++---- .../components/HooksCompanyBoard.tsx | 6 +- .../ui/board/components/EntityBoard.tsx | 2 +- .../ui/board/states/FieldDefinitionContext.ts | 17 +- ...State.ts => viewFieldsDefinitionsState.ts} | 4 +- .../components/GenericEditableDateField.tsx | 29 ++- .../GenericEditableDateFieldEditMode.tsx | 30 +-- .../components/GenericEditableField.tsx | 39 ++-- .../components/GenericEditableNumberField.tsx | 29 ++- .../GenericEditableNumberFieldEditMode.tsx | 32 +-- .../GenericEditableRelationField.tsx | 37 +-- .../GenericEditableRelationFieldEditMode.tsx | 30 ++- .../components/ProbabilityEditableField.tsx | 21 +- .../ProbabilityEditableFieldEditMode.tsx | 32 +-- .../hooks/useUpdateGenericEntityField.ts | 215 ++++++++---------- .../states/EditableFieldContext.ts | 16 ++ .../editable-field/types/FieldDefinition.ts | 9 + .../ui/editable-field/types/FieldMetadata.ts | 113 +++++++++ .../types/guards/isFieldChip.ts | 8 + .../types/guards/isFieldChipValue.ts | 12 + .../types/guards/isFieldDate.ts | 8 + .../types/guards/isFieldDateValue.ts | 12 + .../types/guards/isFieldDoubleText.ts | 8 + .../types/guards/isFieldDoubleTextChip.ts | 8 + .../guards/isFieldDoubleTextChipValue.ts | 12 + .../types/guards/isFieldDoubleTextValue.ts | 12 + .../types/guards/isFieldNumber.ts | 8 + .../types/guards/isFieldNumberValue.ts | 12 + .../types/guards/isFieldPhone.ts | 8 + .../types/guards/isFieldPhoneValue.ts | 12 + .../types/guards/isFieldProbability.ts | 8 + .../types/guards/isFieldProbabilityValue.ts | 12 + .../types/guards/isFieldRelation.ts | 8 + .../types/guards/isFieldRelationValue.ts | 12 + .../types/guards/isFieldText.ts | 8 + .../types/guards/isFieldTextValue.ts | 12 + .../editable-field/types/guards/isFieldURL.ts | 8 + .../types/guards/isFieldURLValue.ts | 12 + 39 files changed, 644 insertions(+), 309 deletions(-) rename front/src/modules/ui/board/states/{fieldsDefinitionsState.ts => viewFieldsDefinitionsState.ts} (70%) create mode 100644 front/src/modules/ui/editable-field/states/EditableFieldContext.ts create mode 100644 front/src/modules/ui/editable-field/types/FieldDefinition.ts create mode 100644 front/src/modules/ui/editable-field/types/FieldMetadata.ts create mode 100644 front/src/modules/ui/editable-field/types/guards/isFieldChip.ts create mode 100644 front/src/modules/ui/editable-field/types/guards/isFieldChipValue.ts create mode 100644 front/src/modules/ui/editable-field/types/guards/isFieldDate.ts create mode 100644 front/src/modules/ui/editable-field/types/guards/isFieldDateValue.ts create mode 100644 front/src/modules/ui/editable-field/types/guards/isFieldDoubleText.ts create mode 100644 front/src/modules/ui/editable-field/types/guards/isFieldDoubleTextChip.ts create mode 100644 front/src/modules/ui/editable-field/types/guards/isFieldDoubleTextChipValue.ts create mode 100644 front/src/modules/ui/editable-field/types/guards/isFieldDoubleTextValue.ts create mode 100644 front/src/modules/ui/editable-field/types/guards/isFieldNumber.ts create mode 100644 front/src/modules/ui/editable-field/types/guards/isFieldNumberValue.ts create mode 100644 front/src/modules/ui/editable-field/types/guards/isFieldPhone.ts create mode 100644 front/src/modules/ui/editable-field/types/guards/isFieldPhoneValue.ts create mode 100644 front/src/modules/ui/editable-field/types/guards/isFieldProbability.ts create mode 100644 front/src/modules/ui/editable-field/types/guards/isFieldProbabilityValue.ts create mode 100644 front/src/modules/ui/editable-field/types/guards/isFieldRelation.ts create mode 100644 front/src/modules/ui/editable-field/types/guards/isFieldRelationValue.ts create mode 100644 front/src/modules/ui/editable-field/types/guards/isFieldText.ts create mode 100644 front/src/modules/ui/editable-field/types/guards/isFieldTextValue.ts create mode 100644 front/src/modules/ui/editable-field/types/guards/isFieldURL.ts create mode 100644 front/src/modules/ui/editable-field/types/guards/isFieldURLValue.ts diff --git a/front/src/modules/activities/hooks/useCompleteTask.ts b/front/src/modules/activities/hooks/useCompleteTask.ts index 9b535c259..ecf6973e2 100644 --- a/front/src/modules/activities/hooks/useCompleteTask.ts +++ b/front/src/modules/activities/hooks/useCompleteTask.ts @@ -16,8 +16,6 @@ export function useCompleteTask(task: Task) { fragment: ACTIVITY_UPDATE_FRAGMENT, }); - console.log('cachedTask', cachedTask); - const completeTask = useCallback( (value: boolean) => { const completedAt = value ? new Date().toISOString() : null; diff --git a/front/src/modules/companies/components/CompanyBoardCard.tsx b/front/src/modules/companies/components/CompanyBoardCard.tsx index e92ecd150..8e4b620aa 100644 --- a/front/src/modules/companies/components/CompanyBoardCard.tsx +++ b/front/src/modules/companies/components/CompanyBoardCard.tsx @@ -3,16 +3,15 @@ import styled from '@emotion/styled'; import { useRecoilState, useRecoilValue } from 'recoil'; import { BoardCardIdContext } from '@/ui/board/states/BoardCardIdContext'; -import { fieldsDefinitionsState } from '@/ui/board/states/fieldsDefinitionsState'; import { selectedBoardCardIdsState } from '@/ui/board/states/selectedBoardCardIdsState'; +import { viewFieldsDefinitionsState } from '@/ui/board/states/viewFieldsDefinitionsState'; import { EntityChipVariant } from '@/ui/chip/components/EntityChip'; import { GenericEditableField } from '@/ui/editable-field/components/GenericEditableField'; -import { EditableFieldEntityIdContext } from '@/ui/editable-field/states/EditableFieldEntityIdContext'; +import { EditableFieldContext } from '@/ui/editable-field/states/EditableFieldContext'; import { Checkbox, CheckboxVariant, } from '@/ui/input/checkbox/components/Checkbox'; -import { EntityUpdateMutationHookContext } from '@/ui/table/states/EntityUpdateMutationHookContext'; import { useUpdateOnePipelineProgressMutation } from '~/generated/graphql'; import { getLogoUrlFromDomainName } from '~/utils'; @@ -111,7 +110,7 @@ export function CompanyBoardCard() { const [selectedBoardCards, setSelectedBoardCards] = useRecoilState( selectedBoardCardIdsState, ); - const fieldsDefinitions = useRecoilValue(fieldsDefinitionsState); + const viewFieldsDefinitions = useRecoilValue(viewFieldsDefinitionsState); const selected = selectedBoardCards.includes(boardCardId ?? ''); @@ -125,7 +124,8 @@ export function CompanyBoardCard() { } } - if (!company || !pipelineProgress) { + // boardCardId check can be moved to a wrapper to avoid unnecessary logic above + if (!company || !pipelineProgress || !boardCardId) { return null; } @@ -146,42 +146,50 @@ export function CompanyBoardCard() { } return ( - - - setSelected(!selected)} - > - - + setSelected(!selected)} + > + + + + setSelected(!selected)} + variant={CheckboxVariant.Secondary} /> - - setSelected(!selected)} - variant={CheckboxVariant.Secondary} - /> - - - - {fieldsDefinitions.map((viewField) => { - return ( - - - - - - ); - })} - - - - + + + + {viewFieldsDefinitions.map((viewField) => { + return ( + + + + + + ); + })} + + + ); } diff --git a/front/src/modules/companies/components/HooksCompanyBoard.tsx b/front/src/modules/companies/components/HooksCompanyBoard.tsx index 0bde12d68..ffda2cf6e 100644 --- a/front/src/modules/companies/components/HooksCompanyBoard.tsx +++ b/front/src/modules/companies/components/HooksCompanyBoard.tsx @@ -2,8 +2,8 @@ import { useEffect, useMemo } from 'react'; import { useRecoilState, useSetRecoilState } from 'recoil'; import { pipelineViewFields } from '@/pipeline/constants/pipelineViewFields'; -import { fieldsDefinitionsState } from '@/ui/board/states/fieldsDefinitionsState'; import { isBoardLoadedState } from '@/ui/board/states/isBoardLoadedState'; +import { viewFieldsDefinitionsState } from '@/ui/board/states/viewFieldsDefinitionsState'; import { filtersScopedState } from '@/ui/filter-n-sort/states/filtersScopedState'; import { turnFilterIntoWhereClause } from '@/ui/filter-n-sort/utils/turnFilterIntoWhereClause'; import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue'; @@ -27,7 +27,9 @@ export function HooksCompanyBoard({ }: { orderBy: PipelineProgresses_Order_By[]; }) { - const setFieldsDefinitionsState = useSetRecoilState(fieldsDefinitionsState); + const setFieldsDefinitionsState = useSetRecoilState( + viewFieldsDefinitionsState, + ); useEffect(() => { setFieldsDefinitionsState(pipelineViewFields); diff --git a/front/src/modules/ui/board/components/EntityBoard.tsx b/front/src/modules/ui/board/components/EntityBoard.tsx index 6f3090887..d681c0e62 100644 --- a/front/src/modules/ui/board/components/EntityBoard.tsx +++ b/front/src/modules/ui/board/components/EntityBoard.tsx @@ -7,6 +7,7 @@ import { IconList } from '@tabler/icons-react'; import { useRecoilState } from 'recoil'; import { CompanyBoardContext } from '@/companies/states/CompanyBoardContext'; +import { GET_PIPELINE_PROGRESS } from '@/pipeline/queries'; import { BoardHeader } from '@/ui/board/components/BoardHeader'; import { StyledBoard } from '@/ui/board/components/StyledBoard'; import { useUpdateBoardCardIds } from '@/ui/board/hooks/useUpdateBoardCardIds'; @@ -21,7 +22,6 @@ import { useUpdateOnePipelineProgressStageMutation, } from '~/generated/graphql'; -import { GET_PIPELINE_PROGRESS } from '../../../pipeline/queries'; import { BoardColumnContext } from '../states/BoardColumnContext'; import { boardColumnsState } from '../states/boardColumnsState'; import { selectedBoardCardIdsState } from '../states/selectedBoardCardIdsState'; diff --git a/front/src/modules/ui/board/states/FieldDefinitionContext.ts b/front/src/modules/ui/board/states/FieldDefinitionContext.ts index c5fb7dc36..0a7fb8b2a 100644 --- a/front/src/modules/ui/board/states/FieldDefinitionContext.ts +++ b/front/src/modules/ui/board/states/FieldDefinitionContext.ts @@ -1,9 +1,14 @@ import { createContext } from 'react'; -import { - ViewFieldDefinition, - ViewFieldMetadata, -} from '../../editable-field/types/ViewField'; +import { FieldDefinition } from '@/ui/editable-field/types/FieldDefinition'; +import { FieldMetadata } from '@/ui/editable-field/types/FieldMetadata'; -export const FieldDefinitionContext = - createContext | null>(null); +export const FieldDefinitionContext = createContext< + FieldDefinition +>({ + id: '', + label: '', + icon: undefined, + type: '', + metadata: {} as FieldMetadata, +}); diff --git a/front/src/modules/ui/board/states/fieldsDefinitionsState.ts b/front/src/modules/ui/board/states/viewFieldsDefinitionsState.ts similarity index 70% rename from front/src/modules/ui/board/states/fieldsDefinitionsState.ts rename to front/src/modules/ui/board/states/viewFieldsDefinitionsState.ts index 6fd293646..c3f40224a 100644 --- a/front/src/modules/ui/board/states/fieldsDefinitionsState.ts +++ b/front/src/modules/ui/board/states/viewFieldsDefinitionsState.ts @@ -5,9 +5,9 @@ import type { ViewFieldMetadata, } from '../../editable-field/types/ViewField'; -export const fieldsDefinitionsState = atom< +export const viewFieldsDefinitionsState = atom< ViewFieldDefinition[] >({ - key: 'fieldsDefinitionState', + key: 'viewFieldsDefinitionState', default: [], }); diff --git a/front/src/modules/ui/editable-field/components/GenericEditableDateField.tsx b/front/src/modules/ui/editable-field/components/GenericEditableDateField.tsx index 5d9c56155..10a095c4b 100644 --- a/front/src/modules/ui/editable-field/components/GenericEditableDateField.tsx +++ b/front/src/modules/ui/editable-field/components/GenericEditableDateField.tsx @@ -1,32 +1,31 @@ import { useContext } from 'react'; import { useRecoilValue } from 'recoil'; -import { - ViewFieldDateMetadata, - ViewFieldDefinition, -} from '@/ui/editable-field/types/ViewField'; import { DateInputDisplay } from '@/ui/input/date/components/DateInputDisplay'; import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; import { parseDate } from '~/utils/date-utils'; -import { EditableFieldEntityIdContext } from '../states/EditableFieldEntityIdContext'; +import { EditableFieldContext } from '../states/EditableFieldContext'; import { FieldContext } from '../states/FieldContext'; import { genericEntityFieldFamilySelector } from '../states/genericEntityFieldFamilySelector'; +import { FieldDefinition } from '../types/FieldDefinition'; +import { FieldDateMetadata } from '../types/FieldMetadata'; import { EditableField } from './EditableField'; import { GenericEditableDateFieldEditMode } from './GenericEditableDateFieldEditMode'; -type OwnProps = { - viewField: ViewFieldDefinition; -}; - -export function GenericEditableDateField({ viewField }: OwnProps) { - const currentEditableFieldEntityId = useContext(EditableFieldEntityIdContext); +export function GenericEditableDateField() { + const currentEditableField = useContext(EditableFieldContext); + const currentEditableFieldEntityId = currentEditableField.entityId; + const currentEditableFieldDefinition = + currentEditableField.fieldDefinition as FieldDefinition; const fieldValue = useRecoilValue( genericEntityFieldFamilySelector({ entityId: currentEditableFieldEntityId ?? '', - fieldName: viewField.metadata.fieldName, + fieldName: currentEditableFieldDefinition + ? currentEditableFieldDefinition.metadata.fieldName + : '', }), ); @@ -37,10 +36,8 @@ export function GenericEditableDateField({ viewField }: OwnProps) { return ( - } + iconLabel={currentEditableFieldDefinition.icon} + editModeContent={} displayModeContent={} isDisplayModeContentEmpty={!fieldValue} /> diff --git a/front/src/modules/ui/editable-field/components/GenericEditableDateFieldEditMode.tsx b/front/src/modules/ui/editable-field/components/GenericEditableDateFieldEditMode.tsx index 8d3b256d7..7163105c9 100644 --- a/front/src/modules/ui/editable-field/components/GenericEditableDateFieldEditMode.tsx +++ b/front/src/modules/ui/editable-field/components/GenericEditableDateFieldEditMode.tsx @@ -1,28 +1,26 @@ import { useContext } from 'react'; import { useRecoilState } from 'recoil'; -import { - ViewFieldDateMetadata, - ViewFieldDefinition, -} from '@/ui/editable-field/types/ViewField'; - import { useUpdateGenericEntityField } from '../hooks/useUpdateGenericEntityField'; -import { EditableFieldEntityIdContext } from '../states/EditableFieldEntityIdContext'; +import { EditableFieldContext } from '../states/EditableFieldContext'; import { genericEntityFieldFamilySelector } from '../states/genericEntityFieldFamilySelector'; +import { FieldDefinition } from '../types/FieldDefinition'; +import { FieldDateMetadata } from '../types/FieldMetadata'; import { EditableFieldEditModeDate } from '../variants/components/EditableFieldEditModeDate'; -type OwnProps = { - viewField: ViewFieldDefinition; -}; - -export function GenericEditableDateFieldEditMode({ viewField }: OwnProps) { - const currentEditableFieldEntityId = useContext(EditableFieldEntityIdContext); +export function GenericEditableDateFieldEditMode() { + const currentEditableField = useContext(EditableFieldContext); + const currentEditableFieldEntityId = currentEditableField.entityId; + const currentEditableFieldDefinition = + currentEditableField.fieldDefinition as FieldDefinition; // TODO: we could use a hook that would return the field value with the right type const [fieldValue, setFieldValue] = useRecoilState( genericEntityFieldFamilySelector({ entityId: currentEditableFieldEntityId ?? '', - fieldName: viewField.metadata.fieldName, + fieldName: currentEditableFieldDefinition + ? currentEditableFieldDefinition.metadata.fieldName + : '', }), ); @@ -34,7 +32,11 @@ export function GenericEditableDateFieldEditMode({ viewField }: OwnProps) { setFieldValue(newDateISO); if (currentEditableFieldEntityId && updateField) { - updateField(currentEditableFieldEntityId, viewField, newDateISO); + updateField( + currentEditableFieldEntityId, + currentEditableFieldDefinition, + newDateISO, + ); } } diff --git a/front/src/modules/ui/editable-field/components/GenericEditableField.tsx b/front/src/modules/ui/editable-field/components/GenericEditableField.tsx index 70d639a80..af1fa5943 100644 --- a/front/src/modules/ui/editable-field/components/GenericEditableField.tsx +++ b/front/src/modules/ui/editable-field/components/GenericEditableField.tsx @@ -1,34 +1,31 @@ -import { - ViewFieldDefinition, - ViewFieldMetadata, -} from '@/ui/editable-field/types/ViewField'; +import { useContext } from 'react'; -import { isViewFieldDate } from '../types/guards/isViewFieldDate'; -import { isViewFieldNumber } from '../types/guards/isViewFieldNumber'; -import { isViewFieldProbability } from '../types/guards/isViewFieldProbability'; -import { isViewFieldRelation } from '../types/guards/isViewFieldRelation'; +import { EditableFieldContext } from '../states/EditableFieldContext'; +import { isFieldDate } from '../types/guards/isFieldDate'; +import { isFieldNumber } from '../types/guards/isFieldNumber'; +import { isFieldProbability } from '../types/guards/isFieldProbability'; +import { isFieldRelation } from '../types/guards/isFieldRelation'; import { GenericEditableDateField } from './GenericEditableDateField'; import { GenericEditableNumberField } from './GenericEditableNumberField'; import { GenericEditableRelationField } from './GenericEditableRelationField'; import { ProbabilityEditableField } from './ProbabilityEditableField'; -type OwnProps = { - viewField: ViewFieldDefinition; -}; +export function GenericEditableField() { + const currentEditableField = useContext(EditableFieldContext); + const fieldDefinition = currentEditableField.fieldDefinition; -export function GenericEditableField({ viewField: fieldDefinition }: OwnProps) { - if (isViewFieldDate(fieldDefinition)) { - return ; - } else if (isViewFieldNumber(fieldDefinition)) { - return ; - } else if (isViewFieldRelation(fieldDefinition)) { - return ; - } else if (isViewFieldProbability(fieldDefinition)) { - return ; + if (isFieldRelation(fieldDefinition)) { + return ; + } else if (isFieldDate(fieldDefinition)) { + return ; + } else if (isFieldNumber(fieldDefinition)) { + return ; + } else if (isFieldProbability(fieldDefinition)) { + return ; } else { console.warn( - `Unknown field metadata type: ${fieldDefinition.metadata.type} in GenericEditableField`, + `Unknown field metadata type: ${fieldDefinition.metadata.type} in GenericEditableCell`, ); return <>; } diff --git a/front/src/modules/ui/editable-field/components/GenericEditableNumberField.tsx b/front/src/modules/ui/editable-field/components/GenericEditableNumberField.tsx index 252352e4b..8ef7c6023 100644 --- a/front/src/modules/ui/editable-field/components/GenericEditableNumberField.tsx +++ b/front/src/modules/ui/editable-field/components/GenericEditableNumberField.tsx @@ -1,40 +1,37 @@ import { useContext } from 'react'; import { useRecoilValue } from 'recoil'; -import { - ViewFieldDefinition, - ViewFieldNumberMetadata, -} from '@/ui/editable-field/types/ViewField'; import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; -import { EditableFieldEntityIdContext } from '../states/EditableFieldEntityIdContext'; +import { EditableFieldContext } from '../states/EditableFieldContext'; import { FieldContext } from '../states/FieldContext'; import { genericEntityFieldFamilySelector } from '../states/genericEntityFieldFamilySelector'; +import { FieldDefinition } from '../types/FieldDefinition'; +import { FieldNumberMetadata } from '../types/FieldMetadata'; import { EditableField } from './EditableField'; import { GenericEditableNumberFieldEditMode } from './GenericEditableNumberFieldEditMode'; -type OwnProps = { - viewField: ViewFieldDefinition; -}; - -export function GenericEditableNumberField({ viewField }: OwnProps) { - const currentEditableFieldEntityId = useContext(EditableFieldEntityIdContext); +export function GenericEditableNumberField() { + const currentEditableField = useContext(EditableFieldContext); + const currentEditableFieldEntityId = currentEditableField.entityId; + const currentEditableFieldDefinition = + currentEditableField.fieldDefinition as FieldDefinition; const fieldValue = useRecoilValue( genericEntityFieldFamilySelector({ entityId: currentEditableFieldEntityId ?? '', - fieldName: viewField.metadata.fieldName, + fieldName: currentEditableFieldDefinition + ? currentEditableFieldDefinition.metadata.fieldName + : '', }), ); return ( - } + iconLabel={currentEditableFieldDefinition.icon} + editModeContent={} displayModeContent={fieldValue} isDisplayModeContentEmpty={!fieldValue} /> diff --git a/front/src/modules/ui/editable-field/components/GenericEditableNumberFieldEditMode.tsx b/front/src/modules/ui/editable-field/components/GenericEditableNumberFieldEditMode.tsx index 35afc59c5..905e9fd61 100644 --- a/front/src/modules/ui/editable-field/components/GenericEditableNumberFieldEditMode.tsx +++ b/front/src/modules/ui/editable-field/components/GenericEditableNumberFieldEditMode.tsx @@ -1,10 +1,6 @@ import { useContext, useRef, useState } from 'react'; import { useRecoilState } from 'recoil'; -import { - ViewFieldDefinition, - ViewFieldNumberMetadata, -} from '@/ui/editable-field/types/ViewField'; import { TextInputEdit } from '@/ui/input/text/components/TextInputEdit'; import { canBeCastAsIntegerOrNull, @@ -13,21 +9,24 @@ import { import { useRegisterCloseFieldHandlers } from '../hooks/useRegisterCloseFieldHandlers'; import { useUpdateGenericEntityField } from '../hooks/useUpdateGenericEntityField'; -import { EditableFieldEntityIdContext } from '../states/EditableFieldEntityIdContext'; +import { EditableFieldContext } from '../states/EditableFieldContext'; import { genericEntityFieldFamilySelector } from '../states/genericEntityFieldFamilySelector'; +import { FieldDefinition } from '../types/FieldDefinition'; +import { FieldNumberMetadata } from '../types/FieldMetadata'; -type OwnProps = { - viewField: ViewFieldDefinition; -}; - -export function GenericEditableNumberFieldEditMode({ viewField }: OwnProps) { - const currentEditableFieldEntityId = useContext(EditableFieldEntityIdContext); +export function GenericEditableNumberFieldEditMode() { + const currentEditableField = useContext(EditableFieldContext); + const currentEditableFieldEntityId = currentEditableField.entityId; + const currentEditableFieldDefinition = + currentEditableField.fieldDefinition as FieldDefinition; // TODO: we could use a hook that would return the field value with the right type const [fieldValue, setFieldValue] = useRecoilState( genericEntityFieldFamilySelector({ entityId: currentEditableFieldEntityId ?? '', - fieldName: viewField.metadata.fieldName, + fieldName: currentEditableFieldDefinition + ? currentEditableFieldDefinition.metadata.fieldName + : '', }), ); const [internalValue, setInternalValue] = useState( @@ -36,6 +35,10 @@ export function GenericEditableNumberFieldEditMode({ viewField }: OwnProps) { const updateField = useUpdateGenericEntityField(); + const wrapperRef = useRef(null); + + useRegisterCloseFieldHandlers(wrapperRef, handleSubmit, onCancel); + function handleSubmit() { if (!canBeCastAsIntegerOrNull(internalValue)) { return; @@ -47,7 +50,7 @@ export function GenericEditableNumberFieldEditMode({ viewField }: OwnProps) { if (currentEditableFieldEntityId && updateField) { updateField( currentEditableFieldEntityId, - viewField, + currentEditableFieldDefinition, castAsIntegerOrNull(internalValue), ); } @@ -60,9 +63,6 @@ export function GenericEditableNumberFieldEditMode({ viewField }: OwnProps) { function handleChange(newValue: string) { setInternalValue(newValue); } - const wrapperRef = useRef(null); - - useRegisterCloseFieldHandlers(wrapperRef, handleSubmit, onCancel); return (
diff --git a/front/src/modules/ui/editable-field/components/GenericEditableRelationField.tsx b/front/src/modules/ui/editable-field/components/GenericEditableRelationField.tsx index a52f9ecf3..1b2c63220 100644 --- a/front/src/modules/ui/editable-field/components/GenericEditableRelationField.tsx +++ b/front/src/modules/ui/editable-field/components/GenericEditableRelationField.tsx @@ -2,30 +2,25 @@ import { useContext } from 'react'; import { useRecoilValue } from 'recoil'; import { PersonChip } from '@/people/components/PersonChip'; -import { - ViewFieldDefinition, - ViewFieldRelationMetadata, -} from '@/ui/editable-field/types/ViewField'; +import { ViewFieldRelationMetadata } from '@/ui/editable-field/types/ViewField'; import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect'; import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope'; import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; -import { EditableFieldEntityIdContext } from '../states/EditableFieldEntityIdContext'; +import { EditableFieldContext } from '../states/EditableFieldContext'; import { FieldContext } from '../states/FieldContext'; import { genericEntityFieldFamilySelector } from '../states/genericEntityFieldFamilySelector'; +import { FieldDefinition } from '../types/FieldDefinition'; +import { FieldRelationMetadata } from '../types/FieldMetadata'; import { EditableField } from './EditableField'; import { GenericEditableRelationFieldEditMode } from './GenericEditableRelationFieldEditMode'; -type OwnProps = { - viewField: ViewFieldDefinition; -}; - function RelationChip({ fieldDefinition, fieldValue, }: { - fieldDefinition: ViewFieldDefinition; + fieldDefinition: FieldDefinition; fieldValue: any | null; }) { switch (fieldDefinition.metadata.relationType) { @@ -46,13 +41,18 @@ function RelationChip({ } } -export function GenericEditableRelationField({ viewField }: OwnProps) { - const currentEditableFieldEntityId = useContext(EditableFieldEntityIdContext); +export function GenericEditableRelationField() { + const currentEditableField = useContext(EditableFieldContext); + const currentEditableFieldEntityId = currentEditableField.entityId; + const currentEditableFieldDefinition = + currentEditableField.fieldDefinition as FieldDefinition; const fieldValue = useRecoilValue( genericEntityFieldFamilySelector({ entityId: currentEditableFieldEntityId ?? '', - fieldName: viewField.metadata.fieldName, + fieldName: currentEditableFieldDefinition + ? currentEditableFieldDefinition.metadata.fieldName + : '', }), ); @@ -64,12 +64,13 @@ export function GenericEditableRelationField({ viewField }: OwnProps) { customEditHotkeyScope={{ scope: RelationPickerHotkeyScope.RelationPicker, }} - iconLabel={viewField.columnIcon} - editModeContent={ - - } + iconLabel={currentEditableFieldDefinition.icon} + editModeContent={} displayModeContent={ - + } isDisplayModeContentEmpty={!fieldValue} isDisplayModeFixHeight diff --git a/front/src/modules/ui/editable-field/components/GenericEditableRelationFieldEditMode.tsx b/front/src/modules/ui/editable-field/components/GenericEditableRelationFieldEditMode.tsx index ce00ba74b..a05303135 100644 --- a/front/src/modules/ui/editable-field/components/GenericEditableRelationFieldEditMode.tsx +++ b/front/src/modules/ui/editable-field/components/GenericEditableRelationFieldEditMode.tsx @@ -4,7 +4,6 @@ import { useRecoilState } from 'recoil'; import { PeoplePicker } from '@/people/components/PeoplePicker'; import { - ViewFieldDefinition, ViewFieldRelationMetadata, ViewFieldRelationValue, } from '@/ui/editable-field/types/ViewField'; @@ -13,8 +12,10 @@ import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect'; import { useEditableField } from '../hooks/useEditableField'; import { useUpdateGenericEntityField } from '../hooks/useUpdateGenericEntityField'; -import { EditableFieldEntityIdContext } from '../states/EditableFieldEntityIdContext'; +import { EditableFieldContext } from '../states/EditableFieldContext'; import { genericEntityFieldFamilySelector } from '../states/genericEntityFieldFamilySelector'; +import { FieldDefinition } from '../types/FieldDefinition'; +import { FieldRelationMetadata } from '../types/FieldMetadata'; const RelationPickerContainer = styled.div` left: 0px; @@ -22,17 +23,13 @@ const RelationPickerContainer = styled.div` top: -8px; `; -type OwnProps = { - viewField: ViewFieldDefinition; -}; - function RelationPicker({ fieldDefinition, fieldValue, handleEntitySubmit, handleCancel, }: { - fieldDefinition: ViewFieldDefinition; + fieldDefinition: FieldDefinition; fieldValue: ViewFieldRelationValue; handleEntitySubmit: (newRelationId: EntityForSelect | null) => void; handleCancel: () => void; @@ -55,14 +52,19 @@ function RelationPicker({ } } -export function GenericEditableRelationFieldEditMode({ viewField }: OwnProps) { - const currentEditableFieldEntityId = useContext(EditableFieldEntityIdContext); +export function GenericEditableRelationFieldEditMode() { + const currentEditableField = useContext(EditableFieldContext); + const currentEditableFieldEntityId = currentEditableField.entityId; + const currentEditableFieldDefinition = + currentEditableField.fieldDefinition as FieldDefinition; // TODO: we could use a hook that would return the field value with the right type const [fieldValue, setFieldValue] = useRecoilState( genericEntityFieldFamilySelector({ entityId: currentEditableFieldEntityId ?? '', - fieldName: viewField.metadata.fieldName, + fieldName: currentEditableFieldDefinition + ? currentEditableFieldDefinition.metadata.fieldName + : '', }), ); @@ -79,7 +81,11 @@ export function GenericEditableRelationFieldEditMode({ viewField }: OwnProps) { }); if (currentEditableFieldEntityId && updateField) { - updateField(currentEditableFieldEntityId, viewField, newRelation); + updateField( + currentEditableFieldEntityId, + currentEditableFieldDefinition, + newRelation, + ); } closeEditableField(); @@ -92,7 +98,7 @@ export function GenericEditableRelationFieldEditMode({ viewField }: OwnProps) { return ( ; -}; +export function ProbabilityEditableField() { + const currentEditableField = useContext(EditableFieldContext); + const currentEditableFieldDefinition = currentEditableField.fieldDefinition; -export function ProbabilityEditableField({ viewField }: OwnProps) { return ( - } + iconLabel={currentEditableFieldDefinition.icon} + displayModeContent={} displayModeContentOnly disableHoverEffect /> diff --git a/front/src/modules/ui/editable-field/components/ProbabilityEditableFieldEditMode.tsx b/front/src/modules/ui/editable-field/components/ProbabilityEditableFieldEditMode.tsx index e41c01088..03873ecd6 100644 --- a/front/src/modules/ui/editable-field/components/ProbabilityEditableFieldEditMode.tsx +++ b/front/src/modules/ui/editable-field/components/ProbabilityEditableFieldEditMode.tsx @@ -5,12 +5,10 @@ import { useRecoilState } from 'recoil'; import { useEditableField } from '@/ui/editable-field/hooks/useEditableField'; import { useUpdateGenericEntityField } from '../hooks/useUpdateGenericEntityField'; -import { EditableFieldEntityIdContext } from '../states/EditableFieldEntityIdContext'; +import { EditableFieldContext } from '../states/EditableFieldContext'; import { genericEntityFieldFamilySelector } from '../states/genericEntityFieldFamilySelector'; -import { - ViewFieldDefinition, - ViewFieldProbabilityMetadata, -} from '../types/ViewField'; +import { FieldDefinition } from '../types/FieldDefinition'; +import { FieldProbabilityMetadata } from '../types/FieldMetadata'; const StyledContainer = styled.div` align-items: center; @@ -60,10 +58,6 @@ const StyledLabel = styled.div` width: ${({ theme }) => theme.spacing(12)}; `; -type OwnProps = { - viewField: ViewFieldDefinition; -}; - const PROBABILITY_VALUES = [ { label: '0%', value: 0 }, { label: '25%', value: 25 }, @@ -72,28 +66,38 @@ const PROBABILITY_VALUES = [ { label: '100%', value: 100 }, ]; -export function ProbabilityEditableFieldEditMode({ viewField }: OwnProps) { +export function ProbabilityEditableFieldEditMode() { const [nextProbabilityIndex, setNextProbabilityIndex] = useState< number | null >(null); - const currentEditableFieldEntityId = useContext(EditableFieldEntityIdContext); + const currentEditableField = useContext(EditableFieldContext); + const currentEditableFieldEntityId = currentEditableField.entityId; + const currentEditableFieldDefinition = + currentEditableField.fieldDefinition as FieldDefinition; const [fieldValue, setFieldValue] = useRecoilState( genericEntityFieldFamilySelector({ entityId: currentEditableFieldEntityId ?? '', - fieldName: viewField.metadata.fieldName, + fieldName: currentEditableFieldDefinition + ? currentEditableFieldDefinition.metadata.fieldName + : '', }), ); - const probabilityIndex = Math.ceil(fieldValue / 25); const { closeEditableField } = useEditableField(); const updateField = useUpdateGenericEntityField(); + const probabilityIndex = Math.ceil(fieldValue / 25); + function handleChange(newValue: number) { setFieldValue(newValue); if (currentEditableFieldEntityId && updateField) { - updateField(currentEditableFieldEntityId, viewField, newValue); + updateField( + currentEditableFieldEntityId, + currentEditableFieldDefinition, + newValue, + ); } closeEditableField(); } diff --git a/front/src/modules/ui/editable-field/hooks/useUpdateGenericEntityField.ts b/front/src/modules/ui/editable-field/hooks/useUpdateGenericEntityField.ts index 87165dd9f..16a2f903e 100644 --- a/front/src/modules/ui/editable-field/hooks/useUpdateGenericEntityField.ts +++ b/front/src/modules/ui/editable-field/hooks/useUpdateGenericEntityField.ts @@ -1,100 +1,98 @@ import { useContext } from 'react'; -import { isViewFieldChip } from '@/ui/editable-field/types/guards/isViewFieldChip'; -import { EntityUpdateMutationHookContext } from '@/ui/table/states/EntityUpdateMutationHookContext'; +import { isFieldChip } from '@/ui/editable-field/types/guards/isFieldChip'; -import { isViewFieldChipValue } from '../types/guards/isViewFieldChipValue'; -import { isViewFieldDate } from '../types/guards/isViewFieldDate'; -import { isViewFieldDateValue } from '../types/guards/isViewFieldDateValue'; -import { isViewFieldDoubleText } from '../types/guards/isViewFieldDoubleText'; -import { isViewFieldDoubleTextChip } from '../types/guards/isViewFieldDoubleTextChip'; -import { isViewFieldDoubleTextChipValue } from '../types/guards/isViewFieldDoubleTextChipValue'; -import { isViewFieldDoubleTextValue } from '../types/guards/isViewFieldDoubleTextValue'; -import { isViewFieldNumber } from '../types/guards/isViewFieldNumber'; -import { isViewFieldNumberValue } from '../types/guards/isViewFieldNumberValue'; -import { isViewFieldPhone } from '../types/guards/isViewFieldPhone'; -import { isViewFieldPhoneValue } from '../types/guards/isViewFieldPhoneValue'; -import { isViewFieldProbability } from '../types/guards/isViewFieldProbability'; -import { isViewFieldProbabilityValue } from '../types/guards/isViewFieldProbabilityValue'; -import { isViewFieldRelation } from '../types/guards/isViewFieldRelation'; -import { isViewFieldRelationValue } from '../types/guards/isViewFieldRelationValue'; -import { isViewFieldText } from '../types/guards/isViewFieldText'; -import { isViewFieldTextValue } from '../types/guards/isViewFieldTextValue'; -import { isViewFieldURL } from '../types/guards/isViewFieldURL'; -import { isViewFieldURLValue } from '../types/guards/isViewFieldURLValue'; +import { EditableFieldContext } from '../states/EditableFieldContext'; +import { FieldDefinition } from '../types/FieldDefinition'; import { - ViewFieldChipMetadata, - ViewFieldChipValue, - ViewFieldDateMetadata, - ViewFieldDateValue, - ViewFieldDefinition, - ViewFieldDoubleTextChipMetadata, - ViewFieldDoubleTextChipValue, - ViewFieldDoubleTextMetadata, - ViewFieldDoubleTextValue, - ViewFieldMetadata, - ViewFieldNumberMetadata, - ViewFieldNumberValue, - ViewFieldPhoneMetadata, - ViewFieldPhoneValue, - ViewFieldProbabilityMetadata, - ViewFieldProbabilityValue, - ViewFieldRelationMetadata, - ViewFieldRelationValue, - ViewFieldTextMetadata, - ViewFieldTextValue, - ViewFieldURLMetadata, - ViewFieldURLValue, -} from '../types/ViewField'; + FieldChipMetadata, + FieldChipValue, + FieldDateMetadata, + FieldDateValue, + FieldDoubleTextChipMetadata, + FieldDoubleTextChipValue, + FieldDoubleTextMetadata, + FieldDoubleTextValue, + FieldMetadata, + FieldNumberMetadata, + FieldNumberValue, + FieldPhoneMetadata, + FieldPhoneValue, + FieldProbabilityMetadata, + FieldProbabilityValue, + FieldRelationMetadata, + FieldRelationValue, + FieldTextMetadata, + FieldTextValue, + FieldURLMetadata, + FieldURLValue, +} from '../types/FieldMetadata'; +import { isFieldChipValue } from '../types/guards/isFieldChipValue'; +import { isFieldDate } from '../types/guards/isFieldDate'; +import { isFieldDateValue } from '../types/guards/isFieldDateValue'; +import { isFieldDoubleText } from '../types/guards/isFieldDoubleText'; +import { isFieldDoubleTextChip } from '../types/guards/isFieldDoubleTextChip'; +import { isFieldDoubleTextChipValue } from '../types/guards/isFieldDoubleTextChipValue'; +import { isFieldDoubleTextValue } from '../types/guards/isFieldDoubleTextValue'; +import { isFieldNumber } from '../types/guards/isFieldNumber'; +import { isFieldNumberValue } from '../types/guards/isFieldNumberValue'; +import { isFieldPhone } from '../types/guards/isFieldPhone'; +import { isFieldPhoneValue } from '../types/guards/isFieldPhoneValue'; +import { isFieldProbability } from '../types/guards/isFieldProbability'; +import { isFieldProbabilityValue } from '../types/guards/isFieldProbabilityValue'; +import { isFieldRelation } from '../types/guards/isFieldRelation'; +import { isFieldRelationValue } from '../types/guards/isFieldRelationValue'; +import { isFieldText } from '../types/guards/isFieldText'; +import { isFieldTextValue } from '../types/guards/isFieldTextValue'; +import { isFieldURL } from '../types/guards/isFieldURL'; +import { isFieldURLValue } from '../types/guards/isFieldURLValue'; export function useUpdateGenericEntityField() { - const useUpdateEntityMutation = useContext(EntityUpdateMutationHookContext); + const currentEditableField = useContext(EditableFieldContext); + const useUpdateEntityMutation = currentEditableField?.mutation; const [updateEntity] = useUpdateEntityMutation(); - return function updatePeopleField< - MetadataType extends ViewFieldMetadata, - ValueType extends MetadataType extends ViewFieldDoubleTextMetadata - ? ViewFieldDoubleTextValue - : MetadataType extends ViewFieldTextMetadata - ? ViewFieldTextValue - : MetadataType extends ViewFieldPhoneMetadata - ? ViewFieldPhoneValue - : MetadataType extends ViewFieldURLMetadata - ? ViewFieldURLValue - : MetadataType extends ViewFieldNumberMetadata - ? ViewFieldNumberValue - : MetadataType extends ViewFieldDateMetadata - ? ViewFieldDateValue - : MetadataType extends ViewFieldChipMetadata - ? ViewFieldChipValue - : MetadataType extends ViewFieldDoubleTextChipMetadata - ? ViewFieldDoubleTextChipValue - : MetadataType extends ViewFieldRelationMetadata - ? ViewFieldRelationValue - : MetadataType extends ViewFieldProbabilityMetadata - ? ViewFieldProbabilityValue + return function updateEntityField< + MetadataType extends FieldMetadata, + ValueType extends MetadataType extends FieldDoubleTextMetadata + ? FieldDoubleTextValue + : MetadataType extends FieldTextMetadata + ? FieldTextValue + : MetadataType extends FieldPhoneMetadata + ? FieldPhoneValue + : MetadataType extends FieldURLMetadata + ? FieldURLValue + : MetadataType extends FieldNumberMetadata + ? FieldNumberValue + : MetadataType extends FieldDateMetadata + ? FieldDateValue + : MetadataType extends FieldChipMetadata + ? FieldChipValue + : MetadataType extends FieldDoubleTextChipMetadata + ? FieldDoubleTextChipValue + : MetadataType extends FieldRelationMetadata + ? FieldRelationValue + : MetadataType extends FieldProbabilityMetadata + ? FieldProbabilityValue : unknown, >( currentEntityId: string, - viewField: ViewFieldDefinition, + field: FieldDefinition, newFieldValue: ValueType, ) { const newFieldValueUnknown = newFieldValue as unknown; - // TODO: improve type guards organization, maybe with a common typeguard for all view fields - // taking an object of options as parameter ? + // TODO: improve type guards organization, maybe with a common typeguard for all fields + // taking an object of options as parameter ? // - // The goal would be to check that the view field value not only is valid, - // but also that it is validated against the corresponding view field type + // The goal would be to check that the field value not only is valid, + // but also that it is validated against the corresponding field type // Relation - if ( - isViewFieldRelation(viewField) && - isViewFieldRelationValue(newFieldValueUnknown) - ) { + if (isFieldRelation(field) && isFieldRelationValue(newFieldValueUnknown)) { const newSelectedEntity = newFieldValueUnknown; - const fieldName = viewField.metadata.fieldName; + const fieldName = field.metadata.fieldName; if (!newSelectedEntity) { updateEntity({ @@ -120,35 +118,29 @@ export function useUpdateGenericEntityField() { }); } // Chip - } else if ( - isViewFieldChip(viewField) && - isViewFieldChipValue(newFieldValueUnknown) - ) { + } else if (isFieldChip(field) && isFieldChipValue(newFieldValueUnknown)) { const newContent = newFieldValueUnknown; updateEntity({ variables: { where: { id: currentEntityId }, - data: { [viewField.metadata.contentFieldName]: newContent }, + data: { [field.metadata.contentFieldName]: newContent }, }, }); // Text - } else if ( - isViewFieldText(viewField) && - isViewFieldTextValue(newFieldValueUnknown) - ) { + } else if (isFieldText(field) && isFieldTextValue(newFieldValueUnknown)) { const newContent = newFieldValueUnknown; updateEntity({ variables: { where: { id: currentEntityId }, - data: { [viewField.metadata.fieldName]: newContent }, + data: { [field.metadata.fieldName]: newContent }, }, }); // Double text } else if ( - isViewFieldDoubleText(viewField) && - isViewFieldDoubleTextValue(newFieldValueUnknown) + isFieldDoubleText(field) && + isFieldDoubleTextValue(newFieldValueUnknown) ) { const newContent = newFieldValueUnknown; @@ -156,15 +148,15 @@ export function useUpdateGenericEntityField() { variables: { where: { id: currentEntityId }, data: { - [viewField.metadata.firstValueFieldName]: newContent.firstValue, - [viewField.metadata.secondValueFieldName]: newContent.secondValue, + [field.metadata.firstValueFieldName]: newContent.firstValue, + [field.metadata.secondValueFieldName]: newContent.secondValue, }, }, }); // Double Text Chip } else if ( - isViewFieldDoubleTextChip(viewField) && - isViewFieldDoubleTextChipValue(newFieldValueUnknown) + isFieldDoubleTextChip(field) && + isFieldDoubleTextChipValue(newFieldValueUnknown) ) { const newContent = newFieldValueUnknown; @@ -172,73 +164,64 @@ export function useUpdateGenericEntityField() { variables: { where: { id: currentEntityId }, data: { - [viewField.metadata.firstValueFieldName]: newContent.firstValue, - [viewField.metadata.secondValueFieldName]: newContent.secondValue, + [field.metadata.firstValueFieldName]: newContent.firstValue, + [field.metadata.secondValueFieldName]: newContent.secondValue, }, }, }); // Phone - } else if ( - isViewFieldPhone(viewField) && - isViewFieldPhoneValue(newFieldValueUnknown) - ) { + } else if (isFieldPhone(field) && isFieldPhoneValue(newFieldValueUnknown)) { const newContent = newFieldValueUnknown; updateEntity({ variables: { where: { id: currentEntityId }, - data: { [viewField.metadata.fieldName]: newContent }, + data: { [field.metadata.fieldName]: newContent }, }, }); // URL - } else if ( - isViewFieldURL(viewField) && - isViewFieldURLValue(newFieldValueUnknown) - ) { + } else if (isFieldURL(field) && isFieldURLValue(newFieldValueUnknown)) { const newContent = newFieldValueUnknown; updateEntity({ variables: { where: { id: currentEntityId }, - data: { [viewField.metadata.fieldName]: newContent }, + data: { [field.metadata.fieldName]: newContent }, }, }); // Number } else if ( - isViewFieldNumber(viewField) && - isViewFieldNumberValue(newFieldValueUnknown) + isFieldNumber(field) && + isFieldNumberValue(newFieldValueUnknown) ) { const newContent = newFieldValueUnknown; updateEntity({ variables: { where: { id: currentEntityId }, - data: { [viewField.metadata.fieldName]: newContent }, + data: { [field.metadata.fieldName]: newContent }, }, }); // Date - } else if ( - isViewFieldDate(viewField) && - isViewFieldDateValue(newFieldValueUnknown) - ) { + } else if (isFieldDate(field) && isFieldDateValue(newFieldValueUnknown)) { const newContent = newFieldValueUnknown; updateEntity({ variables: { where: { id: currentEntityId }, - data: { [viewField.metadata.fieldName]: newContent }, + data: { [field.metadata.fieldName]: newContent }, }, }); } else if ( - isViewFieldProbability(viewField) && - isViewFieldProbabilityValue(newFieldValueUnknown) + isFieldProbability(field) && + isFieldProbabilityValue(newFieldValueUnknown) ) { const newContent = newFieldValueUnknown; updateEntity({ variables: { where: { id: currentEntityId }, - data: { [viewField.metadata.fieldName]: newContent }, + data: { [field.metadata.fieldName]: newContent }, }, }); } diff --git a/front/src/modules/ui/editable-field/states/EditableFieldContext.ts b/front/src/modules/ui/editable-field/states/EditableFieldContext.ts new file mode 100644 index 000000000..818256007 --- /dev/null +++ b/front/src/modules/ui/editable-field/states/EditableFieldContext.ts @@ -0,0 +1,16 @@ +import { createContext } from 'react'; + +import { FieldDefinition } from '../types/FieldDefinition'; +import { ViewFieldMetadata } from '../types/ViewField'; + +type EditableFieldContextValue = { + entityId: string; + fieldDefinition: FieldDefinition; + mutation: any; +}; + +export const EditableFieldContext = createContext({ + entityId: '', + fieldDefinition: {} as FieldDefinition, + mutation: undefined, +}); diff --git a/front/src/modules/ui/editable-field/types/FieldDefinition.ts b/front/src/modules/ui/editable-field/types/FieldDefinition.ts new file mode 100644 index 000000000..0cb858308 --- /dev/null +++ b/front/src/modules/ui/editable-field/types/FieldDefinition.ts @@ -0,0 +1,9 @@ +import { FieldMetadata } from './FieldMetadata'; + +export type FieldDefinition = { + id: string; + label: string; + icon?: JSX.Element; + type: string; + metadata: T; +}; diff --git a/front/src/modules/ui/editable-field/types/FieldMetadata.ts b/front/src/modules/ui/editable-field/types/FieldMetadata.ts new file mode 100644 index 000000000..0b2e598b3 --- /dev/null +++ b/front/src/modules/ui/editable-field/types/FieldMetadata.ts @@ -0,0 +1,113 @@ +import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect'; +import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect'; + +export type FieldType = + | 'text' + | 'relation' + | 'chip' + | 'double-text-chip' + | 'double-text' + | 'number' + | 'date' + | 'phone' + | 'url' + | 'probability'; + +export type FieldTextMetadata = { + type: 'text'; + placeHolder: string; + fieldName: string; +}; + +export type FieldPhoneMetadata = { + type: 'phone'; + placeHolder: string; + fieldName: string; +}; + +export type FieldURLMetadata = { + type: 'url'; + placeHolder: string; + fieldName: string; +}; + +export type FieldDateMetadata = { + type: 'date'; + fieldName: string; +}; + +export type FieldNumberMetadata = { + type: 'number'; + fieldName: string; +}; + +export type FieldRelationMetadata = { + type: 'relation'; + relationType: Entity; + fieldName: string; +}; + +export type FieldChipMetadata = { + type: 'chip'; + relationType: Entity; + contentFieldName: string; + urlFieldName: string; + placeHolder: string; +}; + +export type FieldDoubleTextMetadata = { + type: 'double-text'; + firstValueFieldName: string; + firstValuePlaceholder: string; + secondValueFieldName: string; + secondValuePlaceholder: string; +}; + +export type FieldDoubleTextChipMetadata = { + type: 'double-text-chip'; + firstValueFieldName: string; + firstValuePlaceholder: string; + secondValueFieldName: string; + secondValuePlaceholder: string; + avatarUrlFieldName: string; + entityType: Entity; +}; + +export type FieldProbabilityMetadata = { + type: 'probability'; + fieldName: string; +}; + +export type FieldMetadata = { type: FieldType } & ( + | FieldTextMetadata + | FieldRelationMetadata + | FieldChipMetadata + | FieldDoubleTextChipMetadata + | FieldDoubleTextMetadata + | FieldPhoneMetadata + | FieldURLMetadata + | FieldNumberMetadata + | FieldDateMetadata + | FieldProbabilityMetadata +); + +export type FieldTextValue = string; + +export type FieldChipValue = string; +export type FieldDateValue = string; +export type FieldPhoneValue = string; +export type FieldURLValue = string; +export type FieldNumberValue = number | null; +export type FieldProbabilityValue = number; + +export type FieldDoubleTextValue = { + firstValue: string; + secondValue: string; +}; + +export type FieldDoubleTextChipValue = { + firstValue: string; + secondValue: string; +}; + +export type FieldRelationValue = EntityForSelect | null; diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldChip.ts b/front/src/modules/ui/editable-field/types/guards/isFieldChip.ts new file mode 100644 index 000000000..b7e2eac37 --- /dev/null +++ b/front/src/modules/ui/editable-field/types/guards/isFieldChip.ts @@ -0,0 +1,8 @@ +import { FieldDefinition } from '../FieldDefinition'; +import { FieldChipMetadata, FieldMetadata } from '../FieldMetadata'; + +export function isFieldChip( + field: FieldDefinition, +): field is FieldDefinition { + return field.type === 'chip'; +} diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldChipValue.ts b/front/src/modules/ui/editable-field/types/guards/isFieldChipValue.ts new file mode 100644 index 000000000..649a08fa4 --- /dev/null +++ b/front/src/modules/ui/editable-field/types/guards/isFieldChipValue.ts @@ -0,0 +1,12 @@ +import { FieldChipValue } from '../FieldMetadata'; + +// TODO: add yup +export function isFieldChipValue( + fieldValue: unknown, +): fieldValue is FieldChipValue { + return ( + fieldValue !== null && + fieldValue !== undefined && + typeof fieldValue === 'string' + ); +} diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldDate.ts b/front/src/modules/ui/editable-field/types/guards/isFieldDate.ts new file mode 100644 index 000000000..e6258847e --- /dev/null +++ b/front/src/modules/ui/editable-field/types/guards/isFieldDate.ts @@ -0,0 +1,8 @@ +import { FieldDefinition } from '../FieldDefinition'; +import { FieldDateMetadata, FieldMetadata } from '../FieldMetadata'; + +export function isFieldDate( + field: FieldDefinition, +): field is FieldDefinition { + return field.type === 'date'; +} diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldDateValue.ts b/front/src/modules/ui/editable-field/types/guards/isFieldDateValue.ts new file mode 100644 index 000000000..1d7bdfd88 --- /dev/null +++ b/front/src/modules/ui/editable-field/types/guards/isFieldDateValue.ts @@ -0,0 +1,12 @@ +import { FieldDateValue } from '../FieldMetadata'; + +// TODO: add yup +export function isFieldDateValue( + fieldValue: unknown, +): fieldValue is FieldDateValue { + return ( + fieldValue !== null && + fieldValue !== undefined && + typeof fieldValue === 'string' + ); +} diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldDoubleText.ts b/front/src/modules/ui/editable-field/types/guards/isFieldDoubleText.ts new file mode 100644 index 000000000..b30c0c6a0 --- /dev/null +++ b/front/src/modules/ui/editable-field/types/guards/isFieldDoubleText.ts @@ -0,0 +1,8 @@ +import { FieldDefinition } from '../FieldDefinition'; +import { FieldDoubleTextMetadata, FieldMetadata } from '../FieldMetadata'; + +export function isFieldDoubleText( + field: FieldDefinition, +): field is FieldDefinition { + return field.type === 'double-text'; +} diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldDoubleTextChip.ts b/front/src/modules/ui/editable-field/types/guards/isFieldDoubleTextChip.ts new file mode 100644 index 000000000..73bc0c545 --- /dev/null +++ b/front/src/modules/ui/editable-field/types/guards/isFieldDoubleTextChip.ts @@ -0,0 +1,8 @@ +import { FieldDefinition } from '../FieldDefinition'; +import { FieldDoubleTextChipMetadata, FieldMetadata } from '../FieldMetadata'; + +export function isFieldDoubleTextChip( + field: FieldDefinition, +): field is FieldDefinition { + return field.type === 'double-text-chip'; +} diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldDoubleTextChipValue.ts b/front/src/modules/ui/editable-field/types/guards/isFieldDoubleTextChipValue.ts new file mode 100644 index 000000000..b5d7812a3 --- /dev/null +++ b/front/src/modules/ui/editable-field/types/guards/isFieldDoubleTextChipValue.ts @@ -0,0 +1,12 @@ +import { FieldDoubleTextChipValue } from '../FieldMetadata'; + +// TODO: add yup +export function isFieldDoubleTextChipValue( + fieldValue: unknown, +): fieldValue is FieldDoubleTextChipValue { + return ( + fieldValue !== null && + fieldValue !== undefined && + typeof fieldValue === 'object' + ); +} diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldDoubleTextValue.ts b/front/src/modules/ui/editable-field/types/guards/isFieldDoubleTextValue.ts new file mode 100644 index 000000000..9e5047676 --- /dev/null +++ b/front/src/modules/ui/editable-field/types/guards/isFieldDoubleTextValue.ts @@ -0,0 +1,12 @@ +import { FieldDoubleTextValue } from '../FieldMetadata'; + +// TODO: add yup +export function isFieldDoubleTextValue( + fieldValue: unknown, +): fieldValue is FieldDoubleTextValue { + return ( + fieldValue !== null && + fieldValue !== undefined && + typeof fieldValue === 'object' + ); +} diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldNumber.ts b/front/src/modules/ui/editable-field/types/guards/isFieldNumber.ts new file mode 100644 index 000000000..7c23d6167 --- /dev/null +++ b/front/src/modules/ui/editable-field/types/guards/isFieldNumber.ts @@ -0,0 +1,8 @@ +import { FieldDefinition } from '../FieldDefinition'; +import { FieldMetadata, FieldNumberMetadata } from '../FieldMetadata'; + +export function isFieldNumber( + field: FieldDefinition, +): field is FieldDefinition { + return field.type === 'number'; +} diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldNumberValue.ts b/front/src/modules/ui/editable-field/types/guards/isFieldNumberValue.ts new file mode 100644 index 000000000..452bdbede --- /dev/null +++ b/front/src/modules/ui/editable-field/types/guards/isFieldNumberValue.ts @@ -0,0 +1,12 @@ +import { FieldNumberValue } from '../FieldMetadata'; + +// TODO: add yup +export function isFieldNumberValue( + fieldValue: unknown, +): fieldValue is FieldNumberValue { + return ( + fieldValue !== null && + fieldValue !== undefined && + typeof fieldValue === 'number' + ); +} diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldPhone.ts b/front/src/modules/ui/editable-field/types/guards/isFieldPhone.ts new file mode 100644 index 000000000..e886b9bbc --- /dev/null +++ b/front/src/modules/ui/editable-field/types/guards/isFieldPhone.ts @@ -0,0 +1,8 @@ +import { FieldDefinition } from '../FieldDefinition'; +import { FieldMetadata, FieldPhoneMetadata } from '../FieldMetadata'; + +export function isFieldPhone( + field: FieldDefinition, +): field is FieldDefinition { + return field.type === 'phone'; +} diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldPhoneValue.ts b/front/src/modules/ui/editable-field/types/guards/isFieldPhoneValue.ts new file mode 100644 index 000000000..1337385a7 --- /dev/null +++ b/front/src/modules/ui/editable-field/types/guards/isFieldPhoneValue.ts @@ -0,0 +1,12 @@ +import { FieldPhoneValue } from '../FieldMetadata'; + +// TODO: add yup +export function isFieldPhoneValue( + fieldValue: unknown, +): fieldValue is FieldPhoneValue { + return ( + fieldValue !== null && + fieldValue !== undefined && + typeof fieldValue === 'string' + ); +} diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldProbability.ts b/front/src/modules/ui/editable-field/types/guards/isFieldProbability.ts new file mode 100644 index 000000000..97c12661e --- /dev/null +++ b/front/src/modules/ui/editable-field/types/guards/isFieldProbability.ts @@ -0,0 +1,8 @@ +import { FieldDefinition } from '../FieldDefinition'; +import { FieldMetadata, FieldProbabilityMetadata } from '../FieldMetadata'; + +export function isFieldProbability( + field: FieldDefinition, +): field is FieldDefinition { + return field.type === 'probability'; +} diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldProbabilityValue.ts b/front/src/modules/ui/editable-field/types/guards/isFieldProbabilityValue.ts new file mode 100644 index 000000000..d4dad6eb3 --- /dev/null +++ b/front/src/modules/ui/editable-field/types/guards/isFieldProbabilityValue.ts @@ -0,0 +1,12 @@ +import { FieldProbabilityValue } from '../FieldMetadata'; + +// TODO: add yup +export function isFieldProbabilityValue( + fieldValue: unknown, +): fieldValue is FieldProbabilityValue { + return ( + fieldValue !== null && + fieldValue !== undefined && + typeof fieldValue === 'number' + ); +} diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldRelation.ts b/front/src/modules/ui/editable-field/types/guards/isFieldRelation.ts new file mode 100644 index 000000000..bb24ecac2 --- /dev/null +++ b/front/src/modules/ui/editable-field/types/guards/isFieldRelation.ts @@ -0,0 +1,8 @@ +import { FieldDefinition } from '../FieldDefinition'; +import { FieldMetadata, FieldRelationMetadata } from '../FieldMetadata'; + +export function isFieldRelation( + field: FieldDefinition, +): field is FieldDefinition { + return field.type === 'relation'; +} diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldRelationValue.ts b/front/src/modules/ui/editable-field/types/guards/isFieldRelationValue.ts new file mode 100644 index 000000000..5624e0c25 --- /dev/null +++ b/front/src/modules/ui/editable-field/types/guards/isFieldRelationValue.ts @@ -0,0 +1,12 @@ +import { FieldRelationValue } from '../FieldMetadata'; + +// TODO: add yup +export function isFieldRelationValue( + fieldValue: unknown, +): fieldValue is FieldRelationValue { + return ( + fieldValue !== null && + fieldValue !== undefined && + typeof fieldValue === 'object' + ); +} diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldText.ts b/front/src/modules/ui/editable-field/types/guards/isFieldText.ts new file mode 100644 index 000000000..d616dd595 --- /dev/null +++ b/front/src/modules/ui/editable-field/types/guards/isFieldText.ts @@ -0,0 +1,8 @@ +import { FieldDefinition } from '../FieldDefinition'; +import { FieldMetadata, FieldTextMetadata } from '../FieldMetadata'; + +export function isFieldText( + field: FieldDefinition, +): field is FieldDefinition { + return field.type === 'text'; +} diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldTextValue.ts b/front/src/modules/ui/editable-field/types/guards/isFieldTextValue.ts new file mode 100644 index 000000000..19f958249 --- /dev/null +++ b/front/src/modules/ui/editable-field/types/guards/isFieldTextValue.ts @@ -0,0 +1,12 @@ +import { FieldTextValue } from '../FieldMetadata'; + +// TODO: add yup +export function isFieldTextValue( + fieldValue: unknown, +): fieldValue is FieldTextValue { + return ( + fieldValue !== null && + fieldValue !== undefined && + typeof fieldValue === 'string' + ); +} diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldURL.ts b/front/src/modules/ui/editable-field/types/guards/isFieldURL.ts new file mode 100644 index 000000000..5092c760a --- /dev/null +++ b/front/src/modules/ui/editable-field/types/guards/isFieldURL.ts @@ -0,0 +1,8 @@ +import { FieldDefinition } from '../FieldDefinition'; +import { FieldMetadata, FieldURLMetadata } from '../FieldMetadata'; + +export function isFieldURL( + field: FieldDefinition, +): field is FieldDefinition { + return field.type === 'url'; +} diff --git a/front/src/modules/ui/editable-field/types/guards/isFieldURLValue.ts b/front/src/modules/ui/editable-field/types/guards/isFieldURLValue.ts new file mode 100644 index 000000000..96afe4154 --- /dev/null +++ b/front/src/modules/ui/editable-field/types/guards/isFieldURLValue.ts @@ -0,0 +1,12 @@ +import { FieldURLValue } from '../FieldMetadata'; + +// TODO: add yup +export function isFieldURLValue( + fieldValue: unknown, +): fieldValue is FieldURLValue { + return ( + fieldValue !== null && + fieldValue !== undefined && + typeof fieldValue === 'string' + ); +} From a12b6c4bdaa79d8f6d245fd4d38d5ca1d53d7a2a Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Thu, 10 Aug 2023 21:17:40 +0200 Subject: [PATCH 02/10] Force 404 on static folder when a file is not found (#1165) --- infra/prod/front/Dockerfile | 4 +++- infra/prod/front/serve.json | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 infra/prod/front/serve.json diff --git a/infra/prod/front/Dockerfile b/infra/prod/front/Dockerfile index d5f353d84..28b9ccc3b 100644 --- a/infra/prod/front/Dockerfile +++ b/infra/prod/front/Dockerfile @@ -13,6 +13,8 @@ COPY ./front . RUN yarn install RUN yarn build +COPY ./infra/prod/front/serve.json ./build + FROM node:18.16.0-alpine as front WORKDIR /app/front @@ -20,4 +22,4 @@ COPY --from=build /app/front/build ./build RUN yarn global add serve -CMD ["serve", "-s", "build"] +CMD ["serve", "build"] diff --git a/infra/prod/front/serve.json b/infra/prod/front/serve.json new file mode 100644 index 000000000..cd8879807 --- /dev/null +++ b/infra/prod/front/serve.json @@ -0,0 +1,6 @@ +{ + "rewrites": [ + { "source": "!static/**", "destination": "/index.html" } + ], + "directoryListing": false +} \ No newline at end of file From 4288cef0968af89b8a30cb47730898de916a45b5 Mon Sep 17 00:00:00 2001 From: Weiko Date: Thu, 10 Aug 2023 12:26:05 -0700 Subject: [PATCH 03/10] refactoring editableFieldContext to match with table implementation (#1164) --- .../companies/components/CompanyBoardCard.tsx | 48 ++++++++++--------- .../components/GenericEditableDateField.tsx | 20 ++++---- .../GenericEditableDateFieldDisplayMode.tsx | 33 +++++++++++++ .../GenericEditableDateFieldEditMode.tsx | 11 +++-- .../components/GenericEditableField.tsx | 5 +- .../components/GenericEditableNumberField.tsx | 11 +++-- .../GenericEditableNumberFieldEditMode.tsx | 11 +++-- .../GenericEditableRelationField.tsx | 47 ++++-------------- ...enericEditableRelationFieldDisplayMode.tsx | 45 +++++++++++++++++ .../GenericEditableRelationFieldEditMode.tsx | 16 +++---- .../components/ProbabilityEditableField.tsx | 9 ++-- .../ProbabilityEditableFieldEditMode.tsx | 11 +++-- .../hooks/useUpdateGenericEntityField.ts | 5 +- .../states/EditableFieldContext.ts | 16 ------- .../states/EditableFieldDefinitionContext.ts | 8 ++++ .../states/EditableFieldEntityIdContext.ts | 2 +- .../states/EditableFieldMutationContext.ts | 3 ++ 17 files changed, 173 insertions(+), 128 deletions(-) create mode 100644 front/src/modules/ui/editable-field/components/GenericEditableDateFieldDisplayMode.tsx create mode 100644 front/src/modules/ui/editable-field/components/GenericEditableRelationFieldDisplayMode.tsx delete mode 100644 front/src/modules/ui/editable-field/states/EditableFieldContext.ts create mode 100644 front/src/modules/ui/editable-field/states/EditableFieldDefinitionContext.ts create mode 100644 front/src/modules/ui/editable-field/states/EditableFieldMutationContext.ts diff --git a/front/src/modules/companies/components/CompanyBoardCard.tsx b/front/src/modules/companies/components/CompanyBoardCard.tsx index 8e4b620aa..9becd2c03 100644 --- a/front/src/modules/companies/components/CompanyBoardCard.tsx +++ b/front/src/modules/companies/components/CompanyBoardCard.tsx @@ -7,7 +7,9 @@ import { selectedBoardCardIdsState } from '@/ui/board/states/selectedBoardCardId import { viewFieldsDefinitionsState } from '@/ui/board/states/viewFieldsDefinitionsState'; import { EntityChipVariant } from '@/ui/chip/components/EntityChip'; import { GenericEditableField } from '@/ui/editable-field/components/GenericEditableField'; -import { EditableFieldContext } from '@/ui/editable-field/states/EditableFieldContext'; +import { EditableFieldDefinitionContext } from '@/ui/editable-field/states/EditableFieldDefinitionContext'; +import { EditableFieldEntityIdContext } from '@/ui/editable-field/states/EditableFieldEntityIdContext'; +import { EditableFieldMutationContext } from '@/ui/editable-field/states/EditableFieldMutationContext'; import { Checkbox, CheckboxVariant, @@ -167,27 +169,29 @@ export function CompanyBoardCard() { - {viewFieldsDefinitions.map((viewField) => { - return ( - - - - - - ); - })} + + + {viewFieldsDefinitions.map((viewField) => { + return ( + + + + + + ); + })} + + diff --git a/front/src/modules/ui/editable-field/components/GenericEditableDateField.tsx b/front/src/modules/ui/editable-field/components/GenericEditableDateField.tsx index 10a095c4b..ca1d779c9 100644 --- a/front/src/modules/ui/editable-field/components/GenericEditableDateField.tsx +++ b/front/src/modules/ui/editable-field/components/GenericEditableDateField.tsx @@ -1,24 +1,24 @@ import { useContext } from 'react'; import { useRecoilValue } from 'recoil'; -import { DateInputDisplay } from '@/ui/input/date/components/DateInputDisplay'; import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; -import { parseDate } from '~/utils/date-utils'; -import { EditableFieldContext } from '../states/EditableFieldContext'; +import { EditableFieldDefinitionContext } from '../states/EditableFieldDefinitionContext'; +import { EditableFieldEntityIdContext } from '../states/EditableFieldEntityIdContext'; import { FieldContext } from '../states/FieldContext'; import { genericEntityFieldFamilySelector } from '../states/genericEntityFieldFamilySelector'; import { FieldDefinition } from '../types/FieldDefinition'; import { FieldDateMetadata } from '../types/FieldMetadata'; import { EditableField } from './EditableField'; +import { GenericEditableDateFieldDisplayMode } from './GenericEditableDateFieldDisplayMode'; import { GenericEditableDateFieldEditMode } from './GenericEditableDateFieldEditMode'; export function GenericEditableDateField() { - const currentEditableField = useContext(EditableFieldContext); - const currentEditableFieldEntityId = currentEditableField.entityId; - const currentEditableFieldDefinition = - currentEditableField.fieldDefinition as FieldDefinition; + const currentEditableFieldEntityId = useContext(EditableFieldEntityIdContext); + const currentEditableFieldDefinition = useContext( + EditableFieldDefinitionContext, + ) as FieldDefinition; const fieldValue = useRecoilValue( genericEntityFieldFamilySelector({ @@ -29,16 +29,12 @@ export function GenericEditableDateField() { }), ); - const internalDateValue = fieldValue - ? parseDate(fieldValue).toJSDate() - : null; - return ( } - displayModeContent={} + displayModeContent={} isDisplayModeContentEmpty={!fieldValue} /> diff --git a/front/src/modules/ui/editable-field/components/GenericEditableDateFieldDisplayMode.tsx b/front/src/modules/ui/editable-field/components/GenericEditableDateFieldDisplayMode.tsx new file mode 100644 index 000000000..603bfe316 --- /dev/null +++ b/front/src/modules/ui/editable-field/components/GenericEditableDateFieldDisplayMode.tsx @@ -0,0 +1,33 @@ +import { useContext } from 'react'; +import { useRecoilValue } from 'recoil'; + +import { DateInputDisplay } from '@/ui/input/date/components/DateInputDisplay'; +import { parseDate } from '~/utils/date-utils'; + +import { EditableFieldDefinitionContext } from '../states/EditableFieldDefinitionContext'; +import { EditableFieldEntityIdContext } from '../states/EditableFieldEntityIdContext'; +import { genericEntityFieldFamilySelector } from '../states/genericEntityFieldFamilySelector'; +import { FieldDefinition } from '../types/FieldDefinition'; +import { FieldDateMetadata } from '../types/FieldMetadata'; + +export function GenericEditableDateFieldDisplayMode() { + const currentEditableFieldEntityId = useContext(EditableFieldEntityIdContext); + const currentEditableFieldDefinition = useContext( + EditableFieldDefinitionContext, + ) as FieldDefinition; + + const fieldValue = useRecoilValue( + genericEntityFieldFamilySelector({ + entityId: currentEditableFieldEntityId ?? '', + fieldName: currentEditableFieldDefinition + ? currentEditableFieldDefinition.metadata.fieldName + : '', + }), + ); + + const internalDateValue = fieldValue + ? parseDate(fieldValue).toJSDate() + : null; + + return ; +} diff --git a/front/src/modules/ui/editable-field/components/GenericEditableDateFieldEditMode.tsx b/front/src/modules/ui/editable-field/components/GenericEditableDateFieldEditMode.tsx index 7163105c9..ed7042669 100644 --- a/front/src/modules/ui/editable-field/components/GenericEditableDateFieldEditMode.tsx +++ b/front/src/modules/ui/editable-field/components/GenericEditableDateFieldEditMode.tsx @@ -2,17 +2,18 @@ import { useContext } from 'react'; import { useRecoilState } from 'recoil'; import { useUpdateGenericEntityField } from '../hooks/useUpdateGenericEntityField'; -import { EditableFieldContext } from '../states/EditableFieldContext'; +import { EditableFieldDefinitionContext } from '../states/EditableFieldDefinitionContext'; +import { EditableFieldEntityIdContext } from '../states/EditableFieldEntityIdContext'; import { genericEntityFieldFamilySelector } from '../states/genericEntityFieldFamilySelector'; import { FieldDefinition } from '../types/FieldDefinition'; import { FieldDateMetadata } from '../types/FieldMetadata'; import { EditableFieldEditModeDate } from '../variants/components/EditableFieldEditModeDate'; export function GenericEditableDateFieldEditMode() { - const currentEditableField = useContext(EditableFieldContext); - const currentEditableFieldEntityId = currentEditableField.entityId; - const currentEditableFieldDefinition = - currentEditableField.fieldDefinition as FieldDefinition; + const currentEditableFieldEntityId = useContext(EditableFieldEntityIdContext); + const currentEditableFieldDefinition = useContext( + EditableFieldDefinitionContext, + ) as FieldDefinition; // TODO: we could use a hook that would return the field value with the right type const [fieldValue, setFieldValue] = useRecoilState( diff --git a/front/src/modules/ui/editable-field/components/GenericEditableField.tsx b/front/src/modules/ui/editable-field/components/GenericEditableField.tsx index af1fa5943..c70881722 100644 --- a/front/src/modules/ui/editable-field/components/GenericEditableField.tsx +++ b/front/src/modules/ui/editable-field/components/GenericEditableField.tsx @@ -1,6 +1,6 @@ import { useContext } from 'react'; -import { EditableFieldContext } from '../states/EditableFieldContext'; +import { EditableFieldDefinitionContext } from '../states/EditableFieldDefinitionContext'; import { isFieldDate } from '../types/guards/isFieldDate'; import { isFieldNumber } from '../types/guards/isFieldNumber'; import { isFieldProbability } from '../types/guards/isFieldProbability'; @@ -12,8 +12,7 @@ import { GenericEditableRelationField } from './GenericEditableRelationField'; import { ProbabilityEditableField } from './ProbabilityEditableField'; export function GenericEditableField() { - const currentEditableField = useContext(EditableFieldContext); - const fieldDefinition = currentEditableField.fieldDefinition; + const fieldDefinition = useContext(EditableFieldDefinitionContext); if (isFieldRelation(fieldDefinition)) { return ; diff --git a/front/src/modules/ui/editable-field/components/GenericEditableNumberField.tsx b/front/src/modules/ui/editable-field/components/GenericEditableNumberField.tsx index 8ef7c6023..c59f1e501 100644 --- a/front/src/modules/ui/editable-field/components/GenericEditableNumberField.tsx +++ b/front/src/modules/ui/editable-field/components/GenericEditableNumberField.tsx @@ -3,7 +3,8 @@ import { useRecoilValue } from 'recoil'; import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; -import { EditableFieldContext } from '../states/EditableFieldContext'; +import { EditableFieldDefinitionContext } from '../states/EditableFieldDefinitionContext'; +import { EditableFieldEntityIdContext } from '../states/EditableFieldEntityIdContext'; import { FieldContext } from '../states/FieldContext'; import { genericEntityFieldFamilySelector } from '../states/genericEntityFieldFamilySelector'; import { FieldDefinition } from '../types/FieldDefinition'; @@ -13,10 +14,10 @@ import { EditableField } from './EditableField'; import { GenericEditableNumberFieldEditMode } from './GenericEditableNumberFieldEditMode'; export function GenericEditableNumberField() { - const currentEditableField = useContext(EditableFieldContext); - const currentEditableFieldEntityId = currentEditableField.entityId; - const currentEditableFieldDefinition = - currentEditableField.fieldDefinition as FieldDefinition; + const currentEditableFieldEntityId = useContext(EditableFieldEntityIdContext); + const currentEditableFieldDefinition = useContext( + EditableFieldDefinitionContext, + ) as FieldDefinition; const fieldValue = useRecoilValue( genericEntityFieldFamilySelector({ diff --git a/front/src/modules/ui/editable-field/components/GenericEditableNumberFieldEditMode.tsx b/front/src/modules/ui/editable-field/components/GenericEditableNumberFieldEditMode.tsx index 905e9fd61..4ce2ec326 100644 --- a/front/src/modules/ui/editable-field/components/GenericEditableNumberFieldEditMode.tsx +++ b/front/src/modules/ui/editable-field/components/GenericEditableNumberFieldEditMode.tsx @@ -9,16 +9,17 @@ import { import { useRegisterCloseFieldHandlers } from '../hooks/useRegisterCloseFieldHandlers'; import { useUpdateGenericEntityField } from '../hooks/useUpdateGenericEntityField'; -import { EditableFieldContext } from '../states/EditableFieldContext'; +import { EditableFieldDefinitionContext } from '../states/EditableFieldDefinitionContext'; +import { EditableFieldEntityIdContext } from '../states/EditableFieldEntityIdContext'; import { genericEntityFieldFamilySelector } from '../states/genericEntityFieldFamilySelector'; import { FieldDefinition } from '../types/FieldDefinition'; import { FieldNumberMetadata } from '../types/FieldMetadata'; export function GenericEditableNumberFieldEditMode() { - const currentEditableField = useContext(EditableFieldContext); - const currentEditableFieldEntityId = currentEditableField.entityId; - const currentEditableFieldDefinition = - currentEditableField.fieldDefinition as FieldDefinition; + const currentEditableFieldEntityId = useContext(EditableFieldEntityIdContext); + const currentEditableFieldDefinition = useContext( + EditableFieldDefinitionContext, + ) as FieldDefinition; // TODO: we could use a hook that would return the field value with the right type const [fieldValue, setFieldValue] = useRecoilState( diff --git a/front/src/modules/ui/editable-field/components/GenericEditableRelationField.tsx b/front/src/modules/ui/editable-field/components/GenericEditableRelationField.tsx index 1b2c63220..ae2c42ec2 100644 --- a/front/src/modules/ui/editable-field/components/GenericEditableRelationField.tsx +++ b/front/src/modules/ui/editable-field/components/GenericEditableRelationField.tsx @@ -1,51 +1,25 @@ import { useContext } from 'react'; import { useRecoilValue } from 'recoil'; -import { PersonChip } from '@/people/components/PersonChip'; -import { ViewFieldRelationMetadata } from '@/ui/editable-field/types/ViewField'; -import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect'; import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope'; import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; -import { EditableFieldContext } from '../states/EditableFieldContext'; +import { EditableFieldDefinitionContext } from '../states/EditableFieldDefinitionContext'; +import { EditableFieldEntityIdContext } from '../states/EditableFieldEntityIdContext'; import { FieldContext } from '../states/FieldContext'; import { genericEntityFieldFamilySelector } from '../states/genericEntityFieldFamilySelector'; import { FieldDefinition } from '../types/FieldDefinition'; import { FieldRelationMetadata } from '../types/FieldMetadata'; import { EditableField } from './EditableField'; +import { GenericEditableRelationFieldDisplayMode } from './GenericEditableRelationFieldDisplayMode'; import { GenericEditableRelationFieldEditMode } from './GenericEditableRelationFieldEditMode'; -function RelationChip({ - fieldDefinition, - fieldValue, -}: { - fieldDefinition: FieldDefinition; - fieldValue: any | null; -}) { - switch (fieldDefinition.metadata.relationType) { - case Entity.Person: { - return ( - - ); - } - default: - console.warn( - `Unknown relation type: "${fieldDefinition.metadata.relationType}" in GenericEditableRelationField`, - ); - return <> ; - } -} - export function GenericEditableRelationField() { - const currentEditableField = useContext(EditableFieldContext); - const currentEditableFieldEntityId = currentEditableField.entityId; - const currentEditableFieldDefinition = - currentEditableField.fieldDefinition as FieldDefinition; + const currentEditableFieldEntityId = useContext(EditableFieldEntityIdContext); + const currentEditableFieldDefinition = useContext( + EditableFieldDefinitionContext, + ) as FieldDefinition; const fieldValue = useRecoilValue( genericEntityFieldFamilySelector({ @@ -66,12 +40,7 @@ export function GenericEditableRelationField() { }} iconLabel={currentEditableFieldDefinition.icon} editModeContent={} - displayModeContent={ - - } + displayModeContent={} isDisplayModeContentEmpty={!fieldValue} isDisplayModeFixHeight /> diff --git a/front/src/modules/ui/editable-field/components/GenericEditableRelationFieldDisplayMode.tsx b/front/src/modules/ui/editable-field/components/GenericEditableRelationFieldDisplayMode.tsx new file mode 100644 index 000000000..67d6b9369 --- /dev/null +++ b/front/src/modules/ui/editable-field/components/GenericEditableRelationFieldDisplayMode.tsx @@ -0,0 +1,45 @@ +import { useContext } from 'react'; +import { useRecoilValue } from 'recoil'; + +import { PersonChip } from '@/people/components/PersonChip'; +import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect'; + +import { EditableFieldDefinitionContext } from '../states/EditableFieldDefinitionContext'; +import { EditableFieldEntityIdContext } from '../states/EditableFieldEntityIdContext'; +import { genericEntityFieldFamilySelector } from '../states/genericEntityFieldFamilySelector'; +import { FieldDefinition } from '../types/FieldDefinition'; +import { FieldRelationMetadata } from '../types/FieldMetadata'; + +export function GenericEditableRelationFieldDisplayMode() { + const currentEditableFieldEntityId = useContext(EditableFieldEntityIdContext); + const currentEditableFieldDefinition = useContext( + EditableFieldDefinitionContext, + ) as FieldDefinition; + + const fieldValue = useRecoilValue( + genericEntityFieldFamilySelector({ + entityId: currentEditableFieldEntityId ?? '', + fieldName: currentEditableFieldDefinition + ? currentEditableFieldDefinition.metadata.fieldName + : '', + }), + ); + + switch (currentEditableFieldDefinition.metadata.relationType) { + case Entity.Person: { + return ( + + ); + } + default: + console.warn( + `Unknown relation type: "${currentEditableFieldDefinition.metadata.relationType}" + in GenericEditableRelationField`, + ); + return <> ; + } +} diff --git a/front/src/modules/ui/editable-field/components/GenericEditableRelationFieldEditMode.tsx b/front/src/modules/ui/editable-field/components/GenericEditableRelationFieldEditMode.tsx index a05303135..9b4c08c4f 100644 --- a/front/src/modules/ui/editable-field/components/GenericEditableRelationFieldEditMode.tsx +++ b/front/src/modules/ui/editable-field/components/GenericEditableRelationFieldEditMode.tsx @@ -3,16 +3,14 @@ import styled from '@emotion/styled'; import { useRecoilState } from 'recoil'; import { PeoplePicker } from '@/people/components/PeoplePicker'; -import { - ViewFieldRelationMetadata, - ViewFieldRelationValue, -} from '@/ui/editable-field/types/ViewField'; +import { ViewFieldRelationValue } from '@/ui/editable-field/types/ViewField'; import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect'; import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect'; import { useEditableField } from '../hooks/useEditableField'; import { useUpdateGenericEntityField } from '../hooks/useUpdateGenericEntityField'; -import { EditableFieldContext } from '../states/EditableFieldContext'; +import { EditableFieldDefinitionContext } from '../states/EditableFieldDefinitionContext'; +import { EditableFieldEntityIdContext } from '../states/EditableFieldEntityIdContext'; import { genericEntityFieldFamilySelector } from '../states/genericEntityFieldFamilySelector'; import { FieldDefinition } from '../types/FieldDefinition'; import { FieldRelationMetadata } from '../types/FieldMetadata'; @@ -53,10 +51,10 @@ function RelationPicker({ } export function GenericEditableRelationFieldEditMode() { - const currentEditableField = useContext(EditableFieldContext); - const currentEditableFieldEntityId = currentEditableField.entityId; - const currentEditableFieldDefinition = - currentEditableField.fieldDefinition as FieldDefinition; + const currentEditableFieldEntityId = useContext(EditableFieldEntityIdContext); + const currentEditableFieldDefinition = useContext( + EditableFieldDefinitionContext, + ) as FieldDefinition; // TODO: we could use a hook that would return the field value with the right type const [fieldValue, setFieldValue] = useRecoilState( diff --git a/front/src/modules/ui/editable-field/components/ProbabilityEditableField.tsx b/front/src/modules/ui/editable-field/components/ProbabilityEditableField.tsx index 161372ce2..a32eee432 100644 --- a/front/src/modules/ui/editable-field/components/ProbabilityEditableField.tsx +++ b/front/src/modules/ui/editable-field/components/ProbabilityEditableField.tsx @@ -4,13 +4,16 @@ import { EditableField } from '@/ui/editable-field/components/EditableField'; import { FieldContext } from '@/ui/editable-field/states/FieldContext'; import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; -import { EditableFieldContext } from '../states/EditableFieldContext'; +import { EditableFieldDefinitionContext } from '../states/EditableFieldDefinitionContext'; +import { FieldDefinition } from '../types/FieldDefinition'; +import { FieldProbabilityMetadata } from '../types/FieldMetadata'; import { ProbabilityEditableFieldEditMode } from './ProbabilityEditableFieldEditMode'; export function ProbabilityEditableField() { - const currentEditableField = useContext(EditableFieldContext); - const currentEditableFieldDefinition = currentEditableField.fieldDefinition; + const currentEditableFieldDefinition = useContext( + EditableFieldDefinitionContext, + ) as FieldDefinition; return ( diff --git a/front/src/modules/ui/editable-field/components/ProbabilityEditableFieldEditMode.tsx b/front/src/modules/ui/editable-field/components/ProbabilityEditableFieldEditMode.tsx index 03873ecd6..dd91c4b2d 100644 --- a/front/src/modules/ui/editable-field/components/ProbabilityEditableFieldEditMode.tsx +++ b/front/src/modules/ui/editable-field/components/ProbabilityEditableFieldEditMode.tsx @@ -5,7 +5,8 @@ import { useRecoilState } from 'recoil'; import { useEditableField } from '@/ui/editable-field/hooks/useEditableField'; import { useUpdateGenericEntityField } from '../hooks/useUpdateGenericEntityField'; -import { EditableFieldContext } from '../states/EditableFieldContext'; +import { EditableFieldDefinitionContext } from '../states/EditableFieldDefinitionContext'; +import { EditableFieldEntityIdContext } from '../states/EditableFieldEntityIdContext'; import { genericEntityFieldFamilySelector } from '../states/genericEntityFieldFamilySelector'; import { FieldDefinition } from '../types/FieldDefinition'; import { FieldProbabilityMetadata } from '../types/FieldMetadata'; @@ -70,10 +71,10 @@ export function ProbabilityEditableFieldEditMode() { const [nextProbabilityIndex, setNextProbabilityIndex] = useState< number | null >(null); - const currentEditableField = useContext(EditableFieldContext); - const currentEditableFieldEntityId = currentEditableField.entityId; - const currentEditableFieldDefinition = - currentEditableField.fieldDefinition as FieldDefinition; + const currentEditableFieldEntityId = useContext(EditableFieldEntityIdContext); + const currentEditableFieldDefinition = useContext( + EditableFieldDefinitionContext, + ) as FieldDefinition; const [fieldValue, setFieldValue] = useRecoilState( genericEntityFieldFamilySelector({ diff --git a/front/src/modules/ui/editable-field/hooks/useUpdateGenericEntityField.ts b/front/src/modules/ui/editable-field/hooks/useUpdateGenericEntityField.ts index 16a2f903e..545bc86d7 100644 --- a/front/src/modules/ui/editable-field/hooks/useUpdateGenericEntityField.ts +++ b/front/src/modules/ui/editable-field/hooks/useUpdateGenericEntityField.ts @@ -2,7 +2,7 @@ import { useContext } from 'react'; import { isFieldChip } from '@/ui/editable-field/types/guards/isFieldChip'; -import { EditableFieldContext } from '../states/EditableFieldContext'; +import { EditableFieldMutationContext } from '../states/EditableFieldMutationContext'; import { FieldDefinition } from '../types/FieldDefinition'; import { FieldChipMetadata, @@ -48,8 +48,7 @@ import { isFieldURL } from '../types/guards/isFieldURL'; import { isFieldURLValue } from '../types/guards/isFieldURLValue'; export function useUpdateGenericEntityField() { - const currentEditableField = useContext(EditableFieldContext); - const useUpdateEntityMutation = currentEditableField?.mutation; + const useUpdateEntityMutation = useContext(EditableFieldMutationContext); const [updateEntity] = useUpdateEntityMutation(); diff --git a/front/src/modules/ui/editable-field/states/EditableFieldContext.ts b/front/src/modules/ui/editable-field/states/EditableFieldContext.ts deleted file mode 100644 index 818256007..000000000 --- a/front/src/modules/ui/editable-field/states/EditableFieldContext.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { createContext } from 'react'; - -import { FieldDefinition } from '../types/FieldDefinition'; -import { ViewFieldMetadata } from '../types/ViewField'; - -type EditableFieldContextValue = { - entityId: string; - fieldDefinition: FieldDefinition; - mutation: any; -}; - -export const EditableFieldContext = createContext({ - entityId: '', - fieldDefinition: {} as FieldDefinition, - mutation: undefined, -}); diff --git a/front/src/modules/ui/editable-field/states/EditableFieldDefinitionContext.ts b/front/src/modules/ui/editable-field/states/EditableFieldDefinitionContext.ts new file mode 100644 index 000000000..2ce04ca7b --- /dev/null +++ b/front/src/modules/ui/editable-field/states/EditableFieldDefinitionContext.ts @@ -0,0 +1,8 @@ +import { createContext } from 'react'; + +import { FieldDefinition } from '../types/FieldDefinition'; +import { ViewFieldMetadata } from '../types/ViewField'; + +export const EditableFieldDefinitionContext = createContext< + FieldDefinition +>({} as FieldDefinition); diff --git a/front/src/modules/ui/editable-field/states/EditableFieldEntityIdContext.ts b/front/src/modules/ui/editable-field/states/EditableFieldEntityIdContext.ts index bf6875085..0f1116746 100644 --- a/front/src/modules/ui/editable-field/states/EditableFieldEntityIdContext.ts +++ b/front/src/modules/ui/editable-field/states/EditableFieldEntityIdContext.ts @@ -1,3 +1,3 @@ import { createContext } from 'react'; -export const EditableFieldEntityIdContext = createContext(null); +export const EditableFieldEntityIdContext = createContext(''); diff --git a/front/src/modules/ui/editable-field/states/EditableFieldMutationContext.ts b/front/src/modules/ui/editable-field/states/EditableFieldMutationContext.ts new file mode 100644 index 000000000..6d7b54992 --- /dev/null +++ b/front/src/modules/ui/editable-field/states/EditableFieldMutationContext.ts @@ -0,0 +1,3 @@ +import { createContext } from 'react'; + +export const EditableFieldMutationContext = createContext(undefined); From 5300952b1af79ccefe9902ae02a27e43dfbe5269 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Thu, 10 Aug 2023 12:55:40 -0700 Subject: [PATCH 04/10] Remove breaking change foreign key --- .../migrations/20230809143432_add_views_table/migration.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/database/migrations/20230809143432_add_views_table/migration.sql b/server/src/database/migrations/20230809143432_add_views_table/migration.sql index 17ff87f2e..af100b941 100644 --- a/server/src/database/migrations/20230809143432_add_views_table/migration.sql +++ b/server/src/database/migrations/20230809143432_add_views_table/migration.sql @@ -28,10 +28,10 @@ CREATE UNIQUE INDEX "views_workspaceId_type_objectId_name_key" ON "views"("works CREATE UNIQUE INDEX "viewFields_workspaceId_viewId_objectName_fieldName_key" ON "viewFields"("workspaceId", "viewId", "objectName", "fieldName"); -- AddForeignKey -ALTER TABLE "pipeline_progresses" ADD CONSTRAINT "pipeline_progresses_companyId_fkey" FOREIGN KEY ("companyId") REFERENCES "companies"("id") ON DELETE SET NULL ON UPDATE CASCADE; +-- ALTER TABLE "pipeline_progresses" ADD CONSTRAINT "pipeline_progresses_companyId_fkey" FOREIGN KEY ("companyId") REFERENCES "companies"("id") ON DELETE SET NULL ON UPDATE CASCADE; -- AddForeignKey -ALTER TABLE "pipeline_progresses" ADD CONSTRAINT "pipeline_progresses_personId_fkey" FOREIGN KEY ("personId") REFERENCES "people"("id") ON DELETE SET NULL ON UPDATE CASCADE; +-- ALTER TABLE "pipeline_progresses" ADD CONSTRAINT "pipeline_progresses_personId_fkey" FOREIGN KEY ("personId") REFERENCES "people"("id") ON DELETE SET NULL ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "views" ADD CONSTRAINT "views_workspaceId_fkey" FOREIGN KEY ("workspaceId") REFERENCES "workspaces"("id") ON DELETE RESTRICT ON UPDATE CASCADE; From fb0f9b78075abb58fc32f5a4504d4fa1cabbd2c4 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Fri, 11 Aug 2023 00:09:52 +0200 Subject: [PATCH 05/10] Fixes before deploy (#1167) --- front/src/modules/auth/components/Logo.tsx | 58 +++++++++++++------ .../sign-in-up/components/SignInUpForm.tsx | 2 +- .../companies/components/CompanyTeam.tsx | 2 +- .../ui/board/components/EntityBoardColumn.tsx | 15 ++--- .../ui/input/checkbox/components/Checkbox.tsx | 11 ++-- .../ui/layout/components/DefaultLayout.tsx | 13 +++++ .../components/ShowPageLeftContainer.tsx | 1 + infra/dev/postgres/init.sql | 1 + .../migration.sql | 6 -- server/src/database/schema.prisma | 10 ++-- 10 files changed, 75 insertions(+), 44 deletions(-) diff --git a/front/src/modules/auth/components/Logo.tsx b/front/src/modules/auth/components/Logo.tsx index 0d60d69bc..d12b997a0 100644 --- a/front/src/modules/auth/components/Logo.tsx +++ b/front/src/modules/auth/components/Logo.tsx @@ -6,40 +6,62 @@ type Props = React.ComponentProps<'div'> & { workspaceLogo?: string | null; }; -const StyledLogo = styled.div` +const StyledContainer = styled.div` height: 48px; margin-bottom: ${({ theme }) => theme.spacing(4)}; margin-top: ${({ theme }) => theme.spacing(4)}; - img { - height: 100%; - width: 100%; - } - position: relative; width: 48px; `; -type StyledWorkspaceLogoProps = { +const StyledTwentyLogo = styled.img` + border-radius: ${({ theme }) => theme.border.radius.xs}; + height: 24px; + width: 24px; +`; + +const StyledTwentyLogoContainer = styled.div` + align-items: center; + background-color: ${({ theme }) => theme.background.primary}; + border-radius: ${({ theme }) => theme.border.radius.sm}; + bottom: ${({ theme }) => `-${theme.spacing(3)}`}; + display: flex; + height: 28px; + justify-content: center; + + position: absolute; + right: ${({ theme }) => `-${theme.spacing(3)}`}; + width: 28px; +`; + +type StyledMainLogoProps = { logo?: string | null; }; -const StyledWorkspaceLogo = styled.div` +const StyledMainLogo = styled.div` background: url(${(props) => props.logo}); background-size: cover; - border-radius: ${({ theme }) => theme.border.radius.xs}; - bottom: ${({ theme }) => `-${theme.spacing(3)}`}; - height: ${({ theme }) => theme.spacing(6)}; - position: absolute; - right: ${({ theme }) => `-${theme.spacing(3)}`}; - width: ${({ theme }) => theme.spacing(6)}; + height: 100%; + + width: 100%; `; export function Logo({ workspaceLogo, ...props }: Props) { + if (!workspaceLogo) { + return ( + + + + ); + } + return ( - - - logo - + + + + + + ); } diff --git a/front/src/modules/auth/sign-in-up/components/SignInUpForm.tsx b/front/src/modules/auth/sign-in-up/components/SignInUpForm.tsx index 614893a8d..489b2b188 100644 --- a/front/src/modules/auth/sign-in-up/components/SignInUpForm.tsx +++ b/front/src/modules/auth/sign-in-up/components/SignInUpForm.tsx @@ -76,7 +76,7 @@ export function SignInUpForm() { const title = useMemo(() => { if (signInUpMode === SignInUpMode.Invite) { - return `Join ${workspace?.displayName ?? ''} Team`; + return `Join ${workspace?.displayName ?? ''} team`; } return signInUpMode === SignInUpMode.SignIn diff --git a/front/src/modules/companies/components/CompanyTeam.tsx b/front/src/modules/companies/components/CompanyTeam.tsx index eb7e057b2..a65d7e081 100644 --- a/front/src/modules/companies/components/CompanyTeam.tsx +++ b/front/src/modules/companies/components/CompanyTeam.tsx @@ -12,6 +12,7 @@ const StyledContainer = styled.div` display: flex; flex-direction: column; gap: ${({ theme }) => theme.spacing(2)}; + margin-bottom: ${({ theme }) => theme.spacing(2)}; `; const StyledTitleContainer = styled.div` @@ -32,7 +33,6 @@ const StyledListContainer = styled.div` border-radius: ${({ theme }) => theme.spacing(1)}; display: flex; flex-direction: column; - max-height: ${({ theme }) => theme.spacing(35)}; overflow: auto; width: 100%; `; diff --git a/front/src/modules/ui/board/components/EntityBoardColumn.tsx b/front/src/modules/ui/board/components/EntityBoardColumn.tsx index 1c3202f64..2bd8ab7bf 100644 --- a/front/src/modules/ui/board/components/EntityBoardColumn.tsx +++ b/front/src/modules/ui/board/components/EntityBoardColumn.tsx @@ -91,16 +91,13 @@ export function EntityBoardColumn({ /> ))} - + {(draggableProvided) => ( -
+
{boardOptions.newCardComponent} diff --git a/front/src/modules/ui/input/checkbox/components/Checkbox.tsx b/front/src/modules/ui/input/checkbox/components/Checkbox.tsx index 4caec5717..82c2ed4b3 100644 --- a/front/src/modules/ui/input/checkbox/components/Checkbox.tsx +++ b/front/src/modules/ui/input/checkbox/components/Checkbox.tsx @@ -38,6 +38,7 @@ const StyledInput = styled.input<{ variant: CheckboxVariant; indeterminate?: boolean; shape?: CheckboxShape; + isChecked: boolean; }>` cursor: pointer; margin: 0; @@ -79,9 +80,11 @@ const StyledInput = styled.input<{ width: var(--size); } - &:checked + label:before { - background: ${({ theme }) => theme.color.blue}; - border-color: ${({ theme }) => theme.color.blue}; + & + label:before { + background: ${({ theme, isChecked }) => + isChecked ? theme.color.blue : 'inherit'}; + border-color: ${({ theme, isChecked }) => + isChecked ? theme.color.blue : 'inherit'}; } & + label > svg { @@ -112,7 +115,6 @@ export function Checkbox({ React.useEffect(() => { setIsInternalChecked(checked); }, [checked]); - function handleChange(value: boolean) { onChange?.(value); setIsInternalChecked(!isInternalChecked); @@ -130,6 +132,7 @@ export function Checkbox({ variant={variant} checkboxSize={size} shape={shape} + isChecked={isInternalChecked} onChange={(event) => handleChange(event.target.checked)} />