Various cosmetic fixes for 0.4.0 (#4844)

In this PR:
- fix empty list placeholder positionning
- prevent user from erasing custom address field as composite types
removal is not supported yet @ijreilly FYI
- fix show page relation error
- Implement address filter
This commit is contained in:
Charles Bochet
2024-04-05 17:32:14 +02:00
committed by GitHub
parent f8da8f9805
commit f4017119ab
8 changed files with 93 additions and 12 deletions

View File

@ -2,6 +2,7 @@ import { useLazyQuery } from '@apollo/client';
import { useObjectMetadataItemOnly } from '@/object-metadata/hooks/useObjectMetadataItemOnly';
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
import { getRecordFromRecordNode } from '@/object-record/cache/utils/getRecordFromRecordNode';
import { useGenerateFindOneRecordQuery } from '@/object-record/hooks/useGenerateFindOneRecordQuery';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
@ -31,7 +32,8 @@ export const useLazyFindOneRecord = <T extends ObjectRecord = ObjectRecord>({
findOneRecord: ({ objectRecordId, onCompleted }: FindOneRecordParams<T>) =>
findOneRecord({
variables: { objectRecordId },
onCompleted: (data) => onCompleted?.(data[objectNameSingular]),
onCompleted: (data) =>
onCompleted?.(getRecordFromRecordNode(data[objectNameSingular])),
}),
called,
error,

View File

@ -48,9 +48,16 @@ export const MultipleFiltersDropdownContent = ({
<>
<ObjectFilterDropdownOperandButton />
<DropdownMenuSeparator />
{['TEXT', 'EMAIL', 'PHONE', 'FULL_NAME', 'LINK'].includes(
filterDefinitionUsedInDropdown.type,
) && <ObjectFilterDropdownTextSearchInput />}
{[
'TEXT',
'EMAIL',
'PHONE',
'FULL_NAME',
'LINK',
'ADDRESS',
].includes(filterDefinitionUsedInDropdown.type) && (
<ObjectFilterDropdownTextSearchInput />
)}
{['NUMBER', 'CURRENCY'].includes(
filterDefinitionUsedInDropdown.type,
) && <ObjectFilterDropdownNumberInput />}

View File

@ -11,6 +11,7 @@ describe('getOperandsForFilterType', () => {
'FULL_NAME',
[ViewFilterOperand.Contains, ViewFilterOperand.DoesNotContain],
],
['ADDRESS', [ViewFilterOperand.Contains, ViewFilterOperand.DoesNotContain]],
['LINK', [ViewFilterOperand.Contains, ViewFilterOperand.DoesNotContain]],
['CURRENCY', [ViewFilterOperand.GreaterThan, ViewFilterOperand.LessThan]],
['NUMBER', [ViewFilterOperand.GreaterThan, ViewFilterOperand.LessThan]],

View File

@ -9,6 +9,7 @@ export const getOperandsForFilterType = (
case 'TEXT':
case 'EMAIL':
case 'FULL_NAME':
case 'ADDRESS':
case 'LINK':
return [ViewFilterOperand.Contains, ViewFilterOperand.DoesNotContain];
case 'CURRENCY':

View File

@ -1,6 +1,7 @@
import { isNonEmptyString } from '@sniptt/guards';
import {
AddressFilter,
CurrencyFilter,
DateFilter,
FloatFilter,
@ -254,6 +255,74 @@ export const turnObjectDropdownFilterIntoQueryFilter = (
);
}
break;
case 'ADDRESS':
switch (rawUIFilter.operand) {
case ViewFilterOperand.Contains:
objectRecordFilters.push({
or: [
{
[correspondingField.name]: {
addressStreet1: {
ilike: `%${rawUIFilter.value}%`,
},
} as AddressFilter,
},
{
[correspondingField.name]: {
addressStreet2: {
ilike: `%${rawUIFilter.value}%`,
},
} as AddressFilter,
},
{
[correspondingField.name]: {
addressCity: {
ilike: `%${rawUIFilter.value}%`,
},
} as AddressFilter,
},
],
});
break;
case ViewFilterOperand.DoesNotContain:
objectRecordFilters.push({
and: [
{
not: {
[correspondingField.name]: {
addressStreet1: {
ilike: `%${rawUIFilter.value}%`,
},
} as AddressFilter,
},
},
{
not: {
[correspondingField.name]: {
addressStreet2: {
ilike: `%${rawUIFilter.value}%`,
},
} as AddressFilter,
},
},
{
not: {
[correspondingField.name]: {
addressCity: {
ilike: `%${rawUIFilter.value}%`,
},
} as AddressFilter,
},
},
],
});
break;
default:
throw new Error(
`Unknown operand ${rawUIFilter.operand} for ${rawUIFilter.definition.type} filter`,
);
}
break;
case 'SELECT': {
const stringifiedSelectValues = rawUIFilter.value;
let parsedOptionValues: string[] = [];

View File

@ -33,6 +33,7 @@ const StyledTableWithHeader = styled.div`
flex: 1;
flex-direction: column;
width: 100%;
height: 100%;
`;
const StyledTableContainer = styled.div`

View File

@ -6,10 +6,11 @@ import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
import { FieldMetadataType } from '~/generated-metadata/graphql';
type SettingsObjectFieldInactiveActionDropdownProps = {
isCustomField?: boolean;
isRelationType?: boolean;
fieldType?: FieldMetadataType;
onActivate: () => void;
onErase: () => void;
scopeKey: string;
@ -20,7 +21,7 @@ export const SettingsObjectFieldInactiveActionDropdown = ({
scopeKey,
onErase,
isCustomField,
isRelationType,
fieldType,
}: SettingsObjectFieldInactiveActionDropdownProps) => {
const dropdownId = `${scopeKey}-settings-field-disabled-action-dropdown`;
@ -36,7 +37,10 @@ export const SettingsObjectFieldInactiveActionDropdown = ({
closeDropdown();
};
const isErasable = isCustomField && !isRelationType;
const isErasable =
isCustomField &&
fieldType !== FieldMetadataType.Relation &&
fieldType !== FieldMetadataType.Address;
return (
<Dropdown

View File

@ -32,7 +32,6 @@ import { Table } from '@/ui/layout/table/components/Table';
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
import { TableSection } from '@/ui/layout/table/components/TableSection';
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
import { FieldMetadataType } from '~/generated-metadata/graphql';
const StyledDiv = styled.div`
display: flex;
@ -192,10 +191,7 @@ export const SettingsObjectDetail = () => {
ActionIcon={
<SettingsObjectFieldInactiveActionDropdown
isCustomField={!!disabledMetadataField.isCustom}
isRelationType={
disabledMetadataField.type ===
FieldMetadataType.Relation
}
fieldType={disabledMetadataField.type}
scopeKey={disabledMetadataField.id}
onActivate={() =>
activateMetadataField(disabledMetadataField)