feat: Revamp navigation bar (#6031)

closes: #4428

Testing for fetchMoreRecords is pending, along with component tests

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
Aditya Pimpalkar
2024-07-16 13:38:17 +01:00
committed by GitHub
parent a8dfff3a6d
commit 4a67cfa1c3
66 changed files with 1056 additions and 365 deletions

View File

@ -1,21 +1,24 @@
import gql from 'graphql-tag';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { isAggregationEnabled } from '@/object-metadata/utils/isAggregationEnabled';
import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObjectMetadataToGraphQLQuery';
import { RecordGqlOperationGqlRecordFields } from '@/object-record/graphql/types/RecordGqlOperationGqlRecordFields';
import { capitalize } from '~/utils/string/capitalize';
export type QueryCursorDirection = 'before' | 'after';
export const generateFindManyRecordsQuery = ({
objectMetadataItem,
objectMetadataItems,
recordGqlFields,
computeReferences,
cursorDirection,
}: {
objectMetadataItem: ObjectMetadataItem;
objectMetadataItems: ObjectMetadataItem[];
recordGqlFields?: RecordGqlOperationGqlRecordFields;
computeReferences?: boolean;
cursorDirection?: QueryCursorDirection;
}) => gql`
query FindMany${capitalize(
objectMetadataItem.namePlural,
@ -24,9 +27,11 @@ query FindMany${capitalize(
)}FilterInput, $orderBy: [${capitalize(
objectMetadataItem.nameSingular,
)}OrderByInput], $lastCursor: String, $limit: Int) {
${
objectMetadataItem.namePlural
}(filter: $filter, orderBy: $orderBy, first: $limit, after: $lastCursor){
${objectMetadataItem.namePlural}(filter: $filter, orderBy: $orderBy, ${
cursorDirection === 'before'
? 'last: $limit, before: $lastCursor'
: 'first: $limit, after: $lastCursor'
} ){
edges {
node ${mapObjectMetadataToGraphQLQuery({
objectMetadataItems,
@ -37,11 +42,12 @@ query FindMany${capitalize(
cursor
}
pageInfo {
${isAggregationEnabled(objectMetadataItem) ? 'hasNextPage' : ''}
hasNextPage
hasPreviousPage
startCursor
endCursor
}
${isAggregationEnabled(objectMetadataItem) ? 'totalCount' : ''}
totalCount
}
}
`;

View File

@ -5,7 +5,12 @@ export const getQueryIdentifier = ({
filter,
orderBy,
limit,
cursorFilter,
}: RecordGqlOperationVariables & {
objectNameSingular: string;
}) =>
objectNameSingular + JSON.stringify(filter) + JSON.stringify(orderBy) + limit;
objectNameSingular +
JSON.stringify(filter) +
JSON.stringify(orderBy) +
limit +
(cursorFilter ? JSON.stringify(cursorFilter) : undefined);

View File

@ -1,116 +0,0 @@
import { ChipGeneratorPerObjectPerField } from '@/object-metadata/context/PreComputedChipGeneratorsContext';
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { getAvatarType } from '@/object-metadata/utils/getAvatarType';
import { getAvatarUrl } from '@/object-metadata/utils/getAvatarUrl';
import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem';
import { getLabelIdentifierFieldValue } from '@/object-metadata/utils/getLabelIdentifierFieldValue';
import { getLinkToShowPage } from '@/object-metadata/utils/getLinkToShowPage';
import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField';
import { isFieldFullName } from '@/object-record/record-field/types/guards/isFieldFullName';
import { isFieldNumber } from '@/object-record/record-field/types/guards/isFieldNumber';
import { isFieldRelation } from '@/object-record/record-field/types/guards/isFieldRelation';
import { isFieldText } from '@/object-record/record-field/types/guards/isFieldText';
import { RecordChipData } from '@/object-record/record-field/types/RecordChipData';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { isDefined } from '~/utils/isDefined';
export const isFieldChipDisplay = (
field: Pick<FieldMetadataItem, 'type'>,
isLabelIdentifier: boolean,
) =>
isLabelIdentifier &&
(isFieldText(field) || isFieldFullName(field) || isFieldNumber(field));
export const getRecordChipGeneratorPerObjectPerField = (
objectMetadataItems: ObjectMetadataItem[],
) => {
const recordChipGeneratorPerObjectPerField: ChipGeneratorPerObjectPerField =
{};
for (const objectMetadataItem of objectMetadataItems) {
const generatorPerField = Object.fromEntries<
(record: ObjectRecord) => RecordChipData
>(
objectMetadataItem.fields
.filter(
(fieldMetadataItem) =>
isLabelIdentifierField({
fieldMetadataItem: fieldMetadataItem,
objectMetadataItem,
}) ||
fieldMetadataItem.type === FieldMetadataType.Relation ||
isFieldChipDisplay(
fieldMetadataItem,
isLabelIdentifierField({
fieldMetadataItem: fieldMetadataItem,
objectMetadataItem,
}),
),
)
.map((fieldMetadataItem) => {
const objectNameSingularToFind = isLabelIdentifierField({
fieldMetadataItem: fieldMetadataItem,
objectMetadataItem: objectMetadataItem,
})
? objectMetadataItem.nameSingular
: isFieldRelation(fieldMetadataItem)
? fieldMetadataItem.relationDefinition?.targetObjectMetadata
.nameSingular ?? undefined
: undefined;
const objectMetadataItemToUse = objectMetadataItems.find(
(objectMetadataItem) =>
objectMetadataItem.nameSingular === objectNameSingularToFind,
);
if (
!isDefined(objectMetadataItemToUse) ||
!isDefined(objectNameSingularToFind)
) {
return ['', () => ({}) as any];
}
const labelIdentifierFieldMetadataItem =
getLabelIdentifierFieldMetadataItem(objectMetadataItemToUse);
const imageIdentifierFieldMetadata =
objectMetadataItemToUse.fields.find(
(field) =>
field.id ===
objectMetadataItemToUse.imageIdentifierFieldMetadataId,
);
const avatarType = getAvatarType(objectNameSingularToFind);
return [
fieldMetadataItem.name,
(record: ObjectRecord) => ({
recordId: record.id,
name: getLabelIdentifierFieldValue(
record,
labelIdentifierFieldMetadataItem,
objectMetadataItemToUse.nameSingular,
),
avatarUrl: getAvatarUrl(
objectMetadataItemToUse.nameSingular,
record,
imageIdentifierFieldMetadata,
),
avatarType,
linkToShowPage: getLinkToShowPage(
objectMetadataItemToUse.nameSingular,
record,
),
}),
];
}),
);
recordChipGeneratorPerObjectPerField[objectMetadataItem.nameSingular] =
generatorPerField;
}
return recordChipGeneratorPerObjectPerField;
};

View File

@ -0,0 +1,120 @@
import {
ChipGeneratorPerObjectNameSingularPerFieldName,
IdentifierChipGeneratorPerObject,
} from '@/object-metadata/context/PreComputedChipGeneratorsContext';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { getAvatarType } from '@/object-metadata/utils/getAvatarType';
import { getAvatarUrl } from '@/object-metadata/utils/getAvatarUrl';
import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem';
import { getLabelIdentifierFieldValue } from '@/object-metadata/utils/getLabelIdentifierFieldValue';
import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField';
import { isFieldChipDisplay } from '@/object-record/record-field/meta-types/display/utils/isFieldChipDisplay';
import { RecordChipData } from '@/object-record/record-field/types/RecordChipData';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { isDefined } from '~/utils/isDefined';
export const getRecordChipGenerators = (
objectMetadataItems: ObjectMetadataItem[],
) => {
const chipGeneratorPerObjectPerField: ChipGeneratorPerObjectNameSingularPerFieldName =
{};
const identifierChipGeneratorPerObject: IdentifierChipGeneratorPerObject = {};
for (const objectMetadataItem of objectMetadataItems) {
const labelIdentifierFieldMetadataItem =
getLabelIdentifierFieldMetadataItem(objectMetadataItem);
const generatorPerField = Object.fromEntries<
(record: ObjectRecord) => RecordChipData
>(
objectMetadataItem.fields
.filter(
(fieldMetadataItem) =>
labelIdentifierFieldMetadataItem?.id === fieldMetadataItem.id ||
fieldMetadataItem.type === FieldMetadataType.Relation ||
isFieldChipDisplay(
fieldMetadataItem,
isLabelIdentifierField({
fieldMetadataItem: fieldMetadataItem,
objectMetadataItem,
}),
),
)
.map((fieldMetadataItem) => {
const isLabelIdentifier =
labelIdentifierFieldMetadataItem?.id === fieldMetadataItem.id;
const currentObjectNameSingular = objectMetadataItem.nameSingular;
const fieldRelationObjectNameSingular =
fieldMetadataItem.relationDefinition?.targetObjectMetadata
.nameSingular ?? undefined;
const objectNameSingularToFind = isLabelIdentifier
? currentObjectNameSingular
: fieldRelationObjectNameSingular;
const objectMetadataItemToUse = objectMetadataItems.find(
(objectMetadataItem) =>
objectMetadataItem.nameSingular === objectNameSingularToFind,
);
if (
!isDefined(objectMetadataItemToUse) ||
!isDefined(objectNameSingularToFind)
) {
return ['', () => ({}) as any];
}
const labelIdentifierFieldMetadataItemToUse =
getLabelIdentifierFieldMetadataItem(objectMetadataItemToUse);
const imageIdentifierFieldMetadataToUse =
objectMetadataItemToUse.fields.find(
(field) =>
field.id ===
objectMetadataItemToUse.imageIdentifierFieldMetadataId,
);
const avatarType = getAvatarType(objectNameSingularToFind);
return [
fieldMetadataItem.name,
(record: ObjectRecord) =>
({
recordId: record.id,
name: getLabelIdentifierFieldValue(
record,
labelIdentifierFieldMetadataItemToUse,
objectMetadataItemToUse.nameSingular,
),
avatarUrl: getAvatarUrl(
objectMetadataItemToUse.nameSingular,
record,
imageIdentifierFieldMetadataToUse,
),
avatarType,
isLabelIdentifier,
objectNameSingular: objectNameSingularToFind,
}) satisfies RecordChipData,
];
}),
);
chipGeneratorPerObjectPerField[objectMetadataItem.nameSingular] =
generatorPerField;
if (isDefined(labelIdentifierFieldMetadataItem)) {
identifierChipGeneratorPerObject[objectMetadataItem.nameSingular] =
chipGeneratorPerObjectPerField[objectMetadataItem.nameSingular]?.[
labelIdentifierFieldMetadataItem.name
];
}
}
return {
chipGeneratorPerObjectPerField,
identifierChipGeneratorPerObject,
};
};