Feat/front metadata request (#1977)
* wip * Wip * Wip * Finished v1 * Fix from PR * Removed unused fragment masking feature
This commit is contained in:
@ -2,9 +2,12 @@ import { DateTime } from 'luxon';
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import { currentUserState } from '@/auth/states/currentUserState';
|
||||
import { FilterOperand } from '@/ui/view-bar/types/FilterOperand';
|
||||
import { turnFilterIntoWhereClause } from '@/ui/view-bar/utils/turnFilterIntoWhereClause';
|
||||
import { ActivityType, useGetActivitiesQuery } from '~/generated/graphql';
|
||||
import {
|
||||
ActivityType,
|
||||
useGetActivitiesQuery,
|
||||
ViewFilterOperand,
|
||||
} from '~/generated/graphql';
|
||||
import { parseDate } from '~/utils/date-utils';
|
||||
|
||||
export const useCurrentUserTaskCount = () => {
|
||||
@ -20,7 +23,7 @@ export const useCurrentUserTaskCount = () => {
|
||||
key: 'assigneeId',
|
||||
type: 'entity',
|
||||
value: currentUser.id,
|
||||
operand: FilterOperand.Is,
|
||||
operand: ViewFilterOperand.Is,
|
||||
displayValue: currentUser.displayName,
|
||||
displayAvatarUrl: currentUser.avatarUrl ?? undefined,
|
||||
})
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
/* eslint-disable no-console */
|
||||
import { useMemo } from 'react';
|
||||
import { ApolloClient, InMemoryCache } from '@apollo/client';
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import { tokenPairState } from '@/auth/states/tokenPairState';
|
||||
|
||||
import { ApolloClientMetadataContext } from '../context/ApolloClientMetadataContext';
|
||||
|
||||
export const ApolloClientMetadataProvider = ({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) => {
|
||||
const [tokenPair] = useRecoilState(tokenPairState);
|
||||
|
||||
const apolloClientMetadata = useMemo(() => {
|
||||
if (tokenPair?.accessToken.token) {
|
||||
return new ApolloClient({
|
||||
uri: `${process.env.REACT_APP_SERVER_BASE_URL}/metadata`,
|
||||
cache: new InMemoryCache(),
|
||||
headers: {
|
||||
Authorization: `Bearer ${tokenPair.accessToken.token}`,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}, [tokenPair]);
|
||||
|
||||
return (
|
||||
<ApolloClientMetadataContext.Provider value={apolloClientMetadata}>
|
||||
{children}
|
||||
</ApolloClientMetadataContext.Provider>
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,37 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import { ObjectsQuery } from '~/generated-metadata/graphql';
|
||||
|
||||
import { GET_ALL_OBJECTS } from '../graphql/queries';
|
||||
import { useApolloClientMetadata } from '../hooks/useApolloClientMetadata';
|
||||
import { metadataObjectsState } from '../states/metadataObjectsState';
|
||||
import { MetadataObject } from '../types/MetadataObject';
|
||||
|
||||
export const FetchMetadataEffect = () => {
|
||||
const [metadataObjects, setMetadataObjects] =
|
||||
useRecoilState(metadataObjectsState);
|
||||
|
||||
const apolloClientMetadata = useApolloClientMetadata();
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
if (apolloClientMetadata && metadataObjects.length === 0) {
|
||||
const objects = await apolloClientMetadata.query<ObjectsQuery>({
|
||||
query: GET_ALL_OBJECTS,
|
||||
});
|
||||
|
||||
if (objects.data.objects.edges.length > 0) {
|
||||
const formattedObjects: MetadataObject[] =
|
||||
objects.data.objects.edges.map((object) => ({
|
||||
...object.node,
|
||||
fields: object.node.fields.edges.map((field) => field.node),
|
||||
}));
|
||||
setMetadataObjects(formattedObjects);
|
||||
}
|
||||
}
|
||||
})();
|
||||
}, [metadataObjects, setMetadataObjects, apolloClientMetadata]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
@ -0,0 +1,5 @@
|
||||
import { createContext } from 'react';
|
||||
import { ApolloClient, NormalizedCacheObject } from '@apollo/client';
|
||||
|
||||
export const ApolloClientMetadataContext =
|
||||
createContext<ApolloClient<NormalizedCacheObject> | null>(null);
|
||||
58
front/src/modules/metadata/graphql/queries.ts
Normal file
58
front/src/modules/metadata/graphql/queries.ts
Normal file
@ -0,0 +1,58 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const GET_ALL_OBJECTS = gql`
|
||||
query Objects {
|
||||
objects(paging: { first: 100 }) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
dataSourceId
|
||||
nameSingular
|
||||
namePlural
|
||||
labelSingular
|
||||
labelPlural
|
||||
description
|
||||
icon
|
||||
isCustom
|
||||
isActive
|
||||
createdAt
|
||||
updatedAt
|
||||
fields(paging: { first: 100 }) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
type
|
||||
nameSingular
|
||||
namePlural
|
||||
labelSingular
|
||||
labelPlural
|
||||
description
|
||||
icon
|
||||
placeholder
|
||||
isCustom
|
||||
isActive
|
||||
isNullable
|
||||
createdAt
|
||||
updatedAt
|
||||
}
|
||||
}
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
hasPreviousPage
|
||||
startCursor
|
||||
endCursor
|
||||
}
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
}
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
hasPreviousPage
|
||||
startCursor
|
||||
endCursor
|
||||
}
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -0,0 +1,7 @@
|
||||
import { useContext } from 'react';
|
||||
|
||||
import { ApolloClientMetadataContext } from '../context/ApolloClientMetadataContext';
|
||||
|
||||
export const useApolloClientMetadata = () => {
|
||||
return useContext(ApolloClientMetadataContext);
|
||||
};
|
||||
@ -0,0 +1,8 @@
|
||||
import { atom } from 'recoil';
|
||||
|
||||
import { MetadataObject } from '../types/MetadataObject';
|
||||
|
||||
export const metadataObjectsState = atom<MetadataObject[]>({
|
||||
key: 'metadataObjectsState',
|
||||
default: [],
|
||||
});
|
||||
5
front/src/modules/metadata/types/MetadataObject.ts
Normal file
5
front/src/modules/metadata/types/MetadataObject.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { Field, Object as GeneratedObject } from '~/generated-metadata/graphql';
|
||||
|
||||
export type MetadataObject = Omit<GeneratedObject, 'fields'> & {
|
||||
fields: Field[];
|
||||
};
|
||||
@ -10,10 +10,10 @@ import { useUpsertFilter } from '@/ui/view-bar/hooks/useUpsertFilter';
|
||||
import { filterDefinitionUsedInDropdownScopedState } from '@/ui/view-bar/states/filterDefinitionUsedInDropdownScopedState';
|
||||
import { filterDropdownSelectedEntityIdScopedState } from '@/ui/view-bar/states/filterDropdownSelectedEntityIdScopedState';
|
||||
import { selectedOperandInDropdownScopedState } from '@/ui/view-bar/states/selectedOperandInDropdownScopedState';
|
||||
import { ViewFilterOperand } from '~/generated/graphql';
|
||||
|
||||
import { useViewBarContext } from '../hooks/useViewBarContext';
|
||||
import { filterDropdownSearchInputScopedState } from '../states/filterDropdownSearchInputScopedState';
|
||||
import { FilterOperand } from '../types/FilterOperand';
|
||||
|
||||
export const FilterDropdownEntitySearchSelect = ({
|
||||
entitiesForSelect,
|
||||
@ -113,7 +113,7 @@ export const FilterDropdownEntitySearchSelect = ({
|
||||
upsertFilter({
|
||||
displayValue: filterDefinitionUsedInDropdown.selectAllLabel,
|
||||
key: filterDefinitionUsedInDropdown.key,
|
||||
operand: FilterOperand.IsNotNull,
|
||||
operand: ViewFilterOperand.IsNotNull,
|
||||
type: filterDefinitionUsedInDropdown.type,
|
||||
value: '',
|
||||
});
|
||||
@ -126,7 +126,7 @@ export const FilterDropdownEntitySearchSelect = ({
|
||||
} else {
|
||||
setFilterDropdownSelectedEntityId(filterCurrentlyEdited.value);
|
||||
setIsAllEntitySelected(
|
||||
filterCurrentlyEdited.operand === FilterOperand.IsNotNull,
|
||||
filterCurrentlyEdited.operand === ViewFilterOperand.IsNotNull,
|
||||
);
|
||||
}
|
||||
}, [
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { DropdownMenuItemsContainer } from '@/ui/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { MenuItem } from '@/ui/menu-item/components/MenuItem';
|
||||
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
||||
import { ViewFilterOperand } from '~/generated/graphql';
|
||||
|
||||
import { useFilterCurrentlyEdited } from '../hooks/useFilterCurrentlyEdited';
|
||||
import { useUpsertFilter } from '../hooks/useUpsertFilter';
|
||||
@ -8,7 +9,6 @@ import { useViewBarContext } from '../hooks/useViewBarContext';
|
||||
import { filterDefinitionUsedInDropdownScopedState } from '../states/filterDefinitionUsedInDropdownScopedState';
|
||||
import { isFilterDropdownOperandSelectUnfoldedScopedState } from '../states/isFilterDropdownOperandSelectUnfoldedScopedState';
|
||||
import { selectedOperandInDropdownScopedState } from '../states/selectedOperandInDropdownScopedState';
|
||||
import { FilterOperand } from '../types/FilterOperand';
|
||||
import { getOperandLabel } from '../utils/getOperandLabel';
|
||||
import { getOperandsForFilterType } from '../utils/getOperandsForFilterType';
|
||||
|
||||
@ -41,7 +41,7 @@ export const FilterDropdownOperandSelect = () => {
|
||||
|
||||
const upsertFilter = useUpsertFilter();
|
||||
|
||||
const handleOperangeChange = (newOperand: FilterOperand) => {
|
||||
const handleOperangeChange = (newOperand: ViewFilterOperand) => {
|
||||
setSelectedOperandInDropdown(newOperand);
|
||||
setIsFilterDropdownOperandSelectUnfolded(false);
|
||||
|
||||
|
||||
@ -10,11 +10,11 @@ import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
||||
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
||||
import { filterDefinitionUsedInDropdownScopedState } from '@/ui/view-bar/states/filterDefinitionUsedInDropdownScopedState';
|
||||
import { selectedOperandInDropdownScopedState } from '@/ui/view-bar/states/selectedOperandInDropdownScopedState';
|
||||
import { ViewFilterOperand } from '~/generated/graphql';
|
||||
|
||||
import { useViewBarContext } from '../hooks/useViewBarContext';
|
||||
import { availableFiltersScopedState } from '../states/availableFiltersScopedState';
|
||||
import { filtersScopedState } from '../states/filtersScopedState';
|
||||
import { FilterOperand } from '../types/FilterOperand';
|
||||
import { getOperandsForFilterType } from '../utils/getOperandsForFilterType';
|
||||
|
||||
import { FilterDropdownEntitySearchInput } from './FilterDropdownEntitySearchInput';
|
||||
@ -72,7 +72,7 @@ export const SingleEntityFilterDropdownButton = ({
|
||||
<GenericEntityFilterChip
|
||||
filter={filters[0]}
|
||||
Icon={
|
||||
filters[0].operand === FilterOperand.IsNotNull
|
||||
filters[0].operand === ViewFilterOperand.IsNotNull
|
||||
? availableFilter.SelectAllIcon
|
||||
: undefined
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { atomFamily } from 'recoil';
|
||||
|
||||
import { FilterOperand } from '../types/FilterOperand';
|
||||
import { ViewFilterOperand } from '~/generated/graphql';
|
||||
|
||||
export const selectedOperandInDropdownScopedState = atomFamily<
|
||||
FilterOperand | null,
|
||||
ViewFilterOperand | null,
|
||||
string
|
||||
>({
|
||||
key: 'selectedOperandInDropdownScopedState',
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { FilterOperand } from './FilterOperand';
|
||||
import { ViewFilterOperand } from '~/generated/graphql';
|
||||
|
||||
import { FilterType } from './FilterType';
|
||||
|
||||
export type Filter = {
|
||||
@ -7,5 +8,5 @@ export type Filter = {
|
||||
value: string;
|
||||
displayValue: string;
|
||||
displayAvatarUrl?: string;
|
||||
operand: FilterOperand;
|
||||
operand: ViewFilterOperand;
|
||||
};
|
||||
|
||||
@ -1 +0,0 @@
|
||||
export { ViewFilterOperand as FilterOperand } from '~/generated/graphql';
|
||||
@ -1,20 +1,22 @@
|
||||
import { FilterOperand } from '../types/FilterOperand';
|
||||
import { ViewFilterOperand } from '~/generated/graphql';
|
||||
|
||||
export const getOperandLabel = (operand: FilterOperand | null | undefined) => {
|
||||
export const getOperandLabel = (
|
||||
operand: ViewFilterOperand | null | undefined,
|
||||
) => {
|
||||
switch (operand) {
|
||||
case FilterOperand.Contains:
|
||||
case ViewFilterOperand.Contains:
|
||||
return 'Contains';
|
||||
case FilterOperand.DoesNotContain:
|
||||
case ViewFilterOperand.DoesNotContain:
|
||||
return "Doesn't contain";
|
||||
case FilterOperand.GreaterThan:
|
||||
case ViewFilterOperand.GreaterThan:
|
||||
return 'Greater than';
|
||||
case FilterOperand.LessThan:
|
||||
case ViewFilterOperand.LessThan:
|
||||
return 'Less than';
|
||||
case FilterOperand.Is:
|
||||
case ViewFilterOperand.Is:
|
||||
return 'Is';
|
||||
case FilterOperand.IsNot:
|
||||
case ViewFilterOperand.IsNot:
|
||||
return 'Is not';
|
||||
case FilterOperand.IsNotNull:
|
||||
case ViewFilterOperand.IsNotNull:
|
||||
return 'Is not null';
|
||||
default:
|
||||
return '';
|
||||
@ -22,20 +24,20 @@ export const getOperandLabel = (operand: FilterOperand | null | undefined) => {
|
||||
};
|
||||
|
||||
export const getOperandLabelShort = (
|
||||
operand: FilterOperand | null | undefined,
|
||||
operand: ViewFilterOperand | null | undefined,
|
||||
) => {
|
||||
switch (operand) {
|
||||
case FilterOperand.Is:
|
||||
case FilterOperand.Contains:
|
||||
case ViewFilterOperand.Is:
|
||||
case ViewFilterOperand.Contains:
|
||||
return ': ';
|
||||
case FilterOperand.IsNot:
|
||||
case FilterOperand.DoesNotContain:
|
||||
case ViewFilterOperand.IsNot:
|
||||
case ViewFilterOperand.DoesNotContain:
|
||||
return ': Not';
|
||||
case FilterOperand.IsNotNull:
|
||||
case ViewFilterOperand.IsNotNull:
|
||||
return ': NotNull';
|
||||
case FilterOperand.GreaterThan:
|
||||
case ViewFilterOperand.GreaterThan:
|
||||
return '\u00A0> ';
|
||||
case FilterOperand.LessThan:
|
||||
case ViewFilterOperand.LessThan:
|
||||
return '\u00A0< ';
|
||||
default:
|
||||
return ': ';
|
||||
|
||||
@ -1,17 +1,18 @@
|
||||
import { FilterOperand } from '../types/FilterOperand';
|
||||
import { ViewFilterOperand } from '~/generated/graphql';
|
||||
|
||||
import { FilterType } from '../types/FilterType';
|
||||
|
||||
export const getOperandsForFilterType = (
|
||||
filterType: FilterType | null | undefined,
|
||||
): FilterOperand[] => {
|
||||
): ViewFilterOperand[] => {
|
||||
switch (filterType) {
|
||||
case 'text':
|
||||
return [FilterOperand.Contains, FilterOperand.DoesNotContain];
|
||||
return [ViewFilterOperand.Contains, ViewFilterOperand.DoesNotContain];
|
||||
case 'number':
|
||||
case 'date':
|
||||
return [FilterOperand.GreaterThan, FilterOperand.LessThan];
|
||||
return [ViewFilterOperand.GreaterThan, ViewFilterOperand.LessThan];
|
||||
case 'entity':
|
||||
return [FilterOperand.Is, FilterOperand.IsNot];
|
||||
return [ViewFilterOperand.Is, ViewFilterOperand.IsNot];
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import { QueryMode } from '~/generated/graphql';
|
||||
import { QueryMode, ViewFilterOperand } from '~/generated/graphql';
|
||||
|
||||
import { Filter } from '../types/Filter';
|
||||
import { FilterOperand } from '../types/FilterOperand';
|
||||
|
||||
export const turnFilterIntoWhereClause = (filter: Filter) => {
|
||||
switch (filter.operand) {
|
||||
case FilterOperand.IsNotNull:
|
||||
case ViewFilterOperand.IsNotNull:
|
||||
return {
|
||||
[filter.key]: {
|
||||
not: null,
|
||||
@ -15,14 +14,14 @@ export const turnFilterIntoWhereClause = (filter: Filter) => {
|
||||
switch (filter.type) {
|
||||
case 'text':
|
||||
switch (filter.operand) {
|
||||
case FilterOperand.Contains:
|
||||
case ViewFilterOperand.Contains:
|
||||
return {
|
||||
[filter.key]: {
|
||||
contains: filter.value,
|
||||
mode: QueryMode.Insensitive,
|
||||
},
|
||||
};
|
||||
case FilterOperand.DoesNotContain:
|
||||
case ViewFilterOperand.DoesNotContain:
|
||||
return {
|
||||
[filter.key]: {
|
||||
not: {
|
||||
@ -38,13 +37,13 @@ export const turnFilterIntoWhereClause = (filter: Filter) => {
|
||||
}
|
||||
case 'number':
|
||||
switch (filter.operand) {
|
||||
case FilterOperand.GreaterThan:
|
||||
case ViewFilterOperand.GreaterThan:
|
||||
return {
|
||||
[filter.key]: {
|
||||
gte: parseFloat(filter.value),
|
||||
},
|
||||
};
|
||||
case FilterOperand.LessThan:
|
||||
case ViewFilterOperand.LessThan:
|
||||
return {
|
||||
[filter.key]: {
|
||||
lte: parseFloat(filter.value),
|
||||
@ -57,13 +56,13 @@ export const turnFilterIntoWhereClause = (filter: Filter) => {
|
||||
}
|
||||
case 'date':
|
||||
switch (filter.operand) {
|
||||
case FilterOperand.GreaterThan:
|
||||
case ViewFilterOperand.GreaterThan:
|
||||
return {
|
||||
[filter.key]: {
|
||||
gte: filter.value,
|
||||
},
|
||||
};
|
||||
case FilterOperand.LessThan:
|
||||
case ViewFilterOperand.LessThan:
|
||||
return {
|
||||
[filter.key]: {
|
||||
lte: filter.value,
|
||||
@ -76,13 +75,13 @@ export const turnFilterIntoWhereClause = (filter: Filter) => {
|
||||
}
|
||||
case 'entity':
|
||||
switch (filter.operand) {
|
||||
case FilterOperand.Is:
|
||||
case ViewFilterOperand.Is:
|
||||
return {
|
||||
[filter.key]: {
|
||||
equals: filter.value,
|
||||
},
|
||||
};
|
||||
case FilterOperand.IsNot:
|
||||
case ViewFilterOperand.IsNot:
|
||||
return {
|
||||
[filter.key]: {
|
||||
not: { equals: filter.value },
|
||||
|
||||
Reference in New Issue
Block a user