Skip to content

Commit

Permalink
feat(queries): add filter stations by line ID or Name
Browse files Browse the repository at this point in the history
feat(queries): add filter stations by line ID or Name
  • Loading branch information
aalises authored Oct 23, 2020
2 parents 9144116 + 352bff9 commit 75b6f44
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 24 deletions.
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,28 @@ It provides information about bus stops and lines, metro stations/lines, and pub

### Feature Roadmap / Checklist for v1.0.0

#### Metro ✅

- [x] `metroStation` query with information about one metro station (find by name or id)
- [x] `metroStations` query with information about metro stations
- [x] `metroLine` query with information about one metro line (find by name or id)
- [x] `metroLines` query with information about metro lines
- [x] Add filtering of the stations by line ID or name

#### Bus

- [ ] `busStops` query with information about bus stops
- [ ] `busStop` query with information about one bus stop (find by name or id)
- [ ] `busLines` query with information about bus lines
- [ ] `busLine` query with information about a bus line (find by name or id)

#### Bike

- [ ] `bikeStations` query with information about bike stations
- [ ] `bikeStation` query with information about one bike station (find by name or id)
- [ ] Add bike availability information to the `bikeStations` query
- [ ] Add filtering of the stations by line ID or name (cannot do it on BusStops)

#### Tram

## GraphQL Playground 🚀

Expand Down
10 changes: 9 additions & 1 deletion schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ schema {

"""Root Query"""
type RootQuery {
metroStations(after: String, first: Int, before: String, last: Int): MetroStations
metroStations(after: String, first: Int, before: String, last: Int, filterBy: FilterByInput): MetroStations
metroStation(findBy: FindByInput!): MetroStation
metroLine(findBy: FindByInput!): MetroLine
metroLines(after: String, first: Int, before: String, last: Int): MetroLines
Expand Down Expand Up @@ -74,6 +74,14 @@ type Coordinates {
altitude: Float
}

"""
Input for the filterBy argument of the queries, which allows filtering a connection by some parameters (e.g. lineName or lineId)
"""
input FilterByInput {
lineId: Int
lineName: String
}

"""
Input for the FindBy argument of the queries, which allows finding an entity by some parameters (e.g. name or id)
"""
Expand Down
15 changes: 11 additions & 4 deletions src/datasources/MetroDataSource.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import TmbApiDataSource from "./TmbApiDataSource";
import type {
FindByInput,
FilterByInput,
MetroStation as MetroStationType,
MetroLine as MetroLineType,
} from "../../types";
Expand Down Expand Up @@ -167,7 +168,10 @@ export default class MetroDataSource extends TmbApiDataSource {
async getLineStations({
id,
name,
}: FindByInput): Promise<MetroStationType[] | null> {
}: FindByInput): Promise<{
numberOfStations: number | null;
stations: MetroStationType[];
}> {
const path = ["linies/metro", id, "estacions"].filter(Boolean).join("/");
const nameFilterParameter = name ? { filter: `NOM_LINIA='${name}'` } : {};

Expand All @@ -177,7 +181,10 @@ export default class MetroDataSource extends TmbApiDataSource {
response?.features?.map((station) => this.metroStationReducer(station)) ??
[];

return stations;
return {
numberOfStations: response?.numberReturned ?? null,
stations,
};
}

async getLine({ id, name }: FindByInput): Promise<MetroLineType | null> {
Expand Down Expand Up @@ -209,7 +216,7 @@ export default class MetroDataSource extends TmbApiDataSource {
return new ApolloError("The line object returned did not exist");
}

const stations = await this.getLineStations({ id, name });
const { stations } = await this.getLineStations({ id, name });

return {
...line,
Expand All @@ -232,7 +239,7 @@ export default class MetroDataSource extends TmbApiDataSource {
const lines = await Promise.all(
(response?.features ?? []).map(async (line: MetroLineAPIType) => {
const reducedLine = this.metroLineReducer(line);
const stations = await this.getLineStations({
const { stations } = await this.getLineStations({
id: reducedLine.id,
name: reducedLine.name,
});
Expand Down
7 changes: 4 additions & 3 deletions src/datasources/__tests__/MetroDataSource.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ describe("MetroDataSource", () => {
const mockGet = jest.fn();

MetroDataSource.get = mockGet;
MetroDataSource.getLineStations = jest
.fn()
.mockReturnValue(mockMetroLinesResponse.lines[0].stations);
MetroDataSource.getLineStations = jest.fn().mockReturnValue({
numberOfStations: 5,
stations: mockMetroLinesResponse.lines[0].stations,
});

describe("[getAllLines]", () => {
it("Correctly looks up the lines from the API", async () => {
Expand Down
15 changes: 15 additions & 0 deletions src/inputs/FilterByInput.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { GraphQLInt, GraphQLInputObjectType, GraphQLString } from "graphql";

export default new GraphQLInputObjectType({
name: "FilterByInput",
description:
"Input for the filterBy argument of the queries, which allows filtering a connection by some parameters (e.g. lineName or lineId)",
fields: {
lineId: {
type: GraphQLInt,
},
lineName: {
type: GraphQLString,
},
},
});
36 changes: 21 additions & 15 deletions src/queries/MetroStationsQuery.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import {
connectionArgs,
ConnectionArguments,
connectionFromArray,
} from "graphql-relay";
import { connectionArgs, connectionFromArray } from "graphql-relay";
import type {
MetroStations as MetroStationsType,
MetroStationConnection as MetroStationConnectionType,
} from "../../types";
import { MetroStationConnection } from "../outputs/MetroStation";
import { GraphQLObjectType, GraphQLInt } from "graphql";
import filterByInput from "../inputs/FilterByInput";

const MetroStations = new GraphQLObjectType({
name: "MetroStations",
Expand All @@ -27,16 +24,25 @@ const MetroStations = new GraphQLObjectType({

export default {
type: MetroStations,
args: connectionArgs,
resolve: async (
_,
args: ConnectionArguments,
{ dataSources }
): Promise<MetroStationsType> => {
const {
numberOfStations,
stations,
} = await dataSources.metro.getAllStations();
args: {
...connectionArgs,
filterBy: {
type: filterByInput,
},
},
resolve: async (_, args, { dataSources }): Promise<MetroStationsType> => {
const { filterBy } = args;

const { numberOfStations, stations } = await (async () => {
//We get all the stations if no filter provided, if not we get the lines stations
if (!filterBy?.lineId && !filterBy?.lineName) {
return await dataSources.metro.getAllStations();
}
return await dataSources.metro.getLineStations({
id: filterBy?.lineId ?? null,
name: filterBy?.lineName ?? null,
});
})();

return {
numberOfStations,
Expand Down
7 changes: 7 additions & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export type RootQueryMetroStationsArgs = {
first?: Maybe<Scalars['Int']>;
before?: Maybe<Scalars['String']>;
last?: Maybe<Scalars['Int']>;
filterBy?: Maybe<FilterByInput>;
};


Expand Down Expand Up @@ -109,6 +110,12 @@ export type Coordinates = {
altitude?: Maybe<Scalars['Float']>;
};

/** Input for the filterBy argument of the queries, which allows filtering a connection by some parameters (e.g. lineName or lineId) */
export type FilterByInput = {
lineId?: Maybe<Scalars['Int']>;
lineName?: Maybe<Scalars['String']>;
};

/** Input for the FindBy argument of the queries, which allows finding an entity by some parameters (e.g. name or id) */
export type FindByInput = {
id?: Maybe<Scalars['Int']>;
Expand Down

0 comments on commit 75b6f44

Please sign in to comment.