diff --git a/src/helpers/location-helpers.ts b/src/helpers/location-helpers.ts index bb34809e..c1ff4460 100644 --- a/src/helpers/location-helpers.ts +++ b/src/helpers/location-helpers.ts @@ -13,3 +13,40 @@ export function getCountryName(countryId: string | null): string | null { return null; } + +type FilterInput = { + locationName?: string | null; +}; + +type FilterQuery = { + name?: Record; +}; + +type LocationOrderingInput = { + sortKey: 'name'; + direction: 'ASC' | 'DESC'; +}; + +function getLocationNameQuery(locationName?: string | null): Record | undefined { + return locationName ? { contains: locationName, mode: 'insensitive' } : undefined; +} + +export function getLocationFilterQuery(filter?: FilterInput | null): FilterQuery | undefined { + if (!filter) { + return undefined; + } + const { locationName } = filter; + return { + name: getLocationNameQuery(locationName), + }; +} + +export function getLocationOrderingQuery(ordering?: LocationOrderingInput | null): Record | undefined { + if (!ordering) { + return undefined; + } + + return { + orderBy: [{ [ordering.sortKey]: ordering.direction.toLowerCase() }], + }; +} diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 884e86ce..6b230bc6 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -380,6 +380,10 @@ input FilterLabelsInput { name: String! } +input FilterLocationsInput { + name: String +} + input FilterNeighborInput { deviceName: String! topologyType: TopologyType! @@ -512,6 +516,11 @@ type LocationEdge { node: Location! } +input LocationOrderByInput { + direction: SortDirection! + sortKey: SortLocationBy! +} + type LspPath { metadata: LspPathMetadata path: [String!]! @@ -769,7 +778,14 @@ type Query { ): DeviceConnection! kafkaHealthCheck: IsOkResponse labels(after: String, before: String, filter: FilterLabelsInput, first: Int, last: Int): LabelConnection! - locations(after: String, before: String, first: Int, last: Int): LocationConnection! + locations( + after: String + before: String + filter: FilterLocationsInput + first: Int + last: Int + orderBy: LocationOrderByInput + ): LocationConnection! lspPath(deviceId: String!, lspId: String!): LspPath mplsLspCount(deviceId: String!): MplsLspCount mplsTopology: MplsTopology @@ -831,6 +847,10 @@ enum SortDirection { DESC } +enum SortLocationBy { + name +} + enum SortStreamBy { createdAt deviceName diff --git a/src/schema/location.ts b/src/schema/location.ts index 5498075e..b92eed8d 100644 --- a/src/schema/location.ts +++ b/src/schema/location.ts @@ -1,10 +1,10 @@ import { findManyCursorConnection } from '@devoxa/prisma-relay-cursor-connection'; import { connectionFromArray } from 'graphql-relay'; import countries from 'i18n-iso-countries'; -import { arg, extendType, inputObjectType, nonNull, objectType, stringArg } from 'nexus'; +import { arg, enumType, extendType, inputObjectType, nonNull, objectType, stringArg } from 'nexus'; import { fromGraphId, toGraphId } from '../helpers/id-helper'; -import { Node, PageInfo, PaginationConnectionArgs } from './global-types'; -import { getCountryName } from '../helpers/location-helpers'; +import { Node, PageInfo, PaginationConnectionArgs, SortDirection } from './global-types'; +import { getCountryName, getLocationFilterQuery, getLocationOrderingQuery } from '../helpers/location-helpers'; export const Location = objectType({ name: 'Location', @@ -94,16 +94,40 @@ export const LocationConnection = objectType({ t.nonNull.int('totalCount'); }, }); +export const FilterLocationsInput = inputObjectType({ + name: 'FilterLocationsInput', + definition: (t) => { + t.string('name'); + }, +}); +export const SortLocationBy = enumType({ + name: 'SortLocationBy', + members: ['name'], +}); +export const LocationOrderByInput = inputObjectType({ + name: 'LocationOrderByInput', + definition: (t) => { + t.nonNull.field('sortKey', { type: SortLocationBy }); + t.nonNull.field('direction', { type: SortDirection }); + }, +}); export const LocationQuery = extendType({ type: 'Query', definition: (t) => { t.nonNull.field('locations', { type: LocationConnection, - args: PaginationConnectionArgs, + args: { + ...PaginationConnectionArgs, + filter: FilterLocationsInput, + orderBy: LocationOrderByInput, + }, resolve: async (_, args, { prisma, tenantId }) => { - const baseArgs = { where: { tenantId } }; + const { filter, orderBy } = args; + const filterQuery = getLocationFilterQuery({ locationName: filter?.name }); + const orderingArgs = getLocationOrderingQuery(orderBy); + const baseArgs = { where: { tenantId, ...filterQuery } }; const result = await findManyCursorConnection( - (paginationArgs) => prisma.location.findMany({ ...baseArgs, ...paginationArgs }), + (paginationArgs) => prisma.location.findMany({ ...baseArgs, ...orderingArgs, ...paginationArgs }), () => prisma.location.count(baseArgs), args, ); @@ -136,6 +160,7 @@ export const AddLocationInput = inputObjectType({ t.nonNull.field({ name: 'coordinates', type: Coordinates }); }, }); + export const AddLocationMutation = extendType({ type: 'Mutation', definition: (t) => { diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 444add32..282dbd04 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -143,6 +143,10 @@ export interface NexusGenInputs { // input type name: string; // String! }; + FilterLocationsInput: { + // input type + name?: string | null; // String + }; FilterNeighborInput: { // input type deviceName: string; // String! @@ -168,6 +172,11 @@ export interface NexusGenInputs { x: number; // Float! y: number; // Float! }; + LocationOrderByInput: { + // input type + direction: NexusGenEnums['SortDirection']; // SortDirection! + sortKey: NexusGenEnums['SortLocationBy']; // SortLocationBy! + }; PolygonInput: { // input type polygon?: number[][][] | null; // [[[Float!]!]!] @@ -231,6 +240,7 @@ export interface NexusGenEnums { Signalization: 'LDP' | 'RSVP'; SortDeviceBy: 'discoveredAt' | 'modelVersion' | 'name'; SortDirection: 'ASC' | 'DESC'; + SortLocationBy: 'name'; SortStreamBy: 'createdAt' | 'deviceName' | 'streamName'; TopologyLayer: 'ETH_TOPOLOGY' | 'MPLS_TOPOLOGY' | 'PHYSICAL_TOPOLOGY' | 'PTP_TOPOLOGY'; TopologyType: 'ETH_TOPOLOGY' | 'MPLS_TOPOLOGY' | 'NETWORK_TOPOLOGY' | 'PHYSICAL_TOPOLOGY' | 'PTP_TOPOLOGY'; @@ -2691,8 +2701,10 @@ export interface NexusGenArgTypes { // args after?: string | null; // String before?: string | null; // String + filter?: NexusGenInputs['FilterLocationsInput'] | null; // FilterLocationsInput first?: number | null; // Int last?: number | null; // Int + orderBy?: NexusGenInputs['LocationOrderByInput'] | null; // LocationOrderByInput }; lspPath: { // args