API fields are based on files in /app/graphql/types/**
, but converted to camelCase.
PlaceCal/app/graphql/types at main · geeksforsocialchange/PlaceCal
Either specified by the query with these fields or returned from the server in this structure
PingType: String
NeighbourhoodType {
name: String
abbreviatedName: String
unit: String
unitName: String
unitCodeKey: String
unitCodeValue: String
}
ContactType {
name: String
email: String
telephone: String
}
OpeningHoursType {
dayOfWeek: String
opens: String
closes: String
}
AddressType {
streetAddress: String
postalCode: String
addressLocality: String
addressRegion: String
neighbourhood: NeighbourhoodType
}
PartnerType {
id: ID
name: String
summary: String
description: String
accessibilitySummary: String
logo: String
url: String
facebookUrl: String
twitterUrl: String
address: AddressType
areasServed: [NeighbourhoodType]
contact: ContactType
openingHours: OpeningHoursType
articles: [Article]
}
EventType {
id: ID
name: String
summary: String
description: String
startDate: ISO88601Format
endDate: ISO88601Format
address: AddressType
organizer: PartnerType
}
ArticleType {
name: String
headline: String
text: String
articleBody: String
datePublished: ISO88601Format
dateCreated: ISO88601Format
dateUpdated: ISO88601Format
providers: [Partners]
}
Currently we only serve read queries and no mutations. The examples are written in javascript.
The following code is a bare-bones query wrapper using the node-fetch
npm module.
import fetch from 'node-fetch';
const endPoint = '<http://192.168.0.39:3000/api/v1/graphql>';
function query (query, variables) {
return new Promise((resolve, reject) => {
fetch(endPoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
body: JSON.stringify({
variables,
query
})
})
.then(r => r.json())
.then(data => resolve(data))
});
}
/*
An empty call that tests if you're code is working and responds
with a simple message.
*/
query("{ping}")
.then( (response) => {
console.log(response);
});
/* response */
{
data: { ping: 'Hello World! The time is 2022-03-21 11:10:20 +0000' }
}
let queryString = `
query Event($id: ID!) {
event(id: $id) {
id
name
summary
description
startDate
endDate
address {
streetAddress
postalCode
addressLocality
addressRegion
}
organizer {
id
name
}
}
}`;
query(queryString, { id: 2 })
.then( (response) => {
console.log(JSON.stringify(response, null, 2));
});
/* response */
{
"data": {
"event": {
"id": "2",
"name": "event 0: A summary of an event",
"summary": "event 0: A summary of an event",
"description": "A longer description of this event",
"startDate": "2022-02-10 00:00:00 +0000",
"endDate": null,
"address": {
"streetAddress": "123 A Street, A place",
"postalCode": "SE2 0QG",
"addressLocality": "Belvedere",
"addressRegion": "London (region)"
},
"organizer": null
}
}
}
Shows a set of events in managable chunks. Can be used to load events on demand for pagination/infinite scroll. It’s a bit tricky so there’s an explanation of how connections work.
let queryString = `
query EventConnection($first: Int, $after: String) {
eventConnection(first: $first, after: $after) {
pageInfo {
hasNextPage
endCursor
}
edges {
cursor
node {
id
name
summary
description
startDate
endDate
address {
streetAddress
postalCode
addressLocality
addressRegion
}
organizer {
id
name
}
}
}
}
}`;
/* return the first block of events */
query(queryString, {first: 5})
.then( (response) => {
console.log(JSON.stringify(response, null, 2));
});
/* first response */
"data": {
"eventConnection": {
"pageInfo": {
"hasNextPage": true
},
"edges": [
{
"cursor": "MQ",
"node": {
"id": "2",
"name": "event 0: A summary of an event",
"summary": "event 0: A summary of an event",
"description": "A longer description of this event",
"startDate": "2022-02-10 00:00:00 +0000",
"endDate": null,
"address": {
"streetAddress": "123 A Street, A place",
"postalCode": "SE2 0QG",
"addressLocality": "Belvedere",
"addressRegion": "London (region)"
},
"organizer": null
}
},
{
"cursor": "Mg",
"node": {
"id": "3",
"name": "event 1: A summary of an event",
"summary": "event 1: A summary of an event",
"description": "A longer description of this event",
"startDate": "2022-02-10 00:00:00 +0000",
"endDate": null,
"address": {
"streetAddress": "123 A Street, A place",
"postalCode": "SE2 0QG",
"addressLocality": "Belvedere",
"addressRegion": "London (region)"
},
"organizer": null
}
},
{
"cursor": "Mw",
"node": {
"id": "4",
"name": "event 2: A summary of an event",
"summary": "event 2: A summary of an event",
"description": "A longer description of this event",
"startDate": "2022-02-10 00:00:00 +0000",
"endDate": null,
"address": {
"streetAddress": "123 A Street, A place",
"postalCode": "SE2 0QG",
"addressLocality": "Belvedere",
"addressRegion": "London (region)"
},
"organizer": null
}
},
{
"cursor": "NA",
"node": {
"id": "5",
"name": "event 3: A summary of an event",
"summary": "event 3: A summary of an event",
"description": "A longer description of this event",
"startDate": "2022-02-10 00:00:00 +0000",
"endDate": null,
"address": {
"streetAddress": "123 A Street, A place",
"postalCode": "SE2 0QG",
"addressLocality": "Belvedere",
"addressRegion": "London (region)"
},
"organizer": null
}
},
{
"cursor": "NQ",
"node": {
"id": "6",
"name": "event 4: A summary of an event",
"summary": "event 4: A summary of an event",
"description": "A longer description of this event",
"startDate": "2022-02-10 00:00:00 +0000",
"endDate": null,
"address": {
"streetAddress": "123 A Street, A place",
"postalCode": "SE2 0QG",
"addressLocality": "Belvedere",
"addressRegion": "London (region)"
},
"organizer": null
}
}
]
}
}
}
/*
Notes on connection pagination:
Cursors are GraphQL's way of identifying a record in a connection.
They act like IDs but are more complicated for reasons.
Input parameters
first: limit the number of records to return
after: only fetch records that follow on from this cursor
In the response each record is wrapped in an 'edge' that contains
the GQL cursor identifier.
pageInfo:
hasNextPage: (boolean) there are records that follow from this block
endCursor: (string) the cursor of the last record retrieved
*/
/* then to get the next block of events */
query(queryString, {first: 5, after: "NQ"})
.then( (response) => {
console.log(JSON.stringify(response, null, 2));
});
/* second response */
{
"data": {
"eventConnection": {
"pageInfo": {
"hasNextPage": true
},
"edges": [
{
"cursor": "Ng",
"node": {
"id": "7",
"name": "event 5: A summary of an event",
"summary": "event 5: A summary of an event",
"description": "A longer description of this event",
"startDate": "2022-02-10 00:00:00 +0000",
"endDate": null,
"address": {
"streetAddress": "123 A Street, A place",
"postalCode": "SE2 0QG",
"addressLocality": "Belvedere",
"addressRegion": "London (region)"
},
"organizer": null
}
},
{
"cursor": "Nw",
"node": {
"id": "8",
"name": "event 6: A summary of an event",
"summary": "event 6: A summary of an event",
"description": "A longer description of this event",
"startDate": "2022-02-10 00:00:00 +0000",
"endDate": null,
"address": {
"streetAddress": "123 A Street, A place",
"postalCode": "SE2 0QG",
"addressLocality": "Belvedere",
"addressRegion": "London (region)"
},
"organizer": null
}
},
{
"cursor": "OA",
"node": {
"id": "9",
"name": "event 7: A summary of an event",
"summary": "event 7: A summary of an event",
"description": "A longer description of this event",
"startDate": "2022-02-10 00:00:00 +0000",
"endDate": null,
"address": {
"streetAddress": "123 A Street, A place",
"postalCode": "SE2 0QG",
"addressLocality": "Belvedere",
"addressRegion": "London (region)"
},
"organizer": null
}
},
{
"cursor": "OQ",
"node": {
"id": "10",
"name": "event 8: A summary of an event",
"summary": "event 8: A summary of an event",
"description": "A longer description of this event",
"startDate": "2022-02-10 00:00:00 +0000",
"endDate": null,
"address": {
"streetAddress": "123 A Street, A place",
"postalCode": "SE2 0QG",
"addressLocality": "Belvedere",
"addressRegion": "London (region)"
},
"organizer": null
}
},
{
"cursor": "MTA",
"node": {
"id": "11",
"name": "event 9: A summary of an event",
"summary": "event 9: A summary of an event",
"description": "A longer description of this event",
"startDate": "2022-02-10 00:00:00 +0000",
"endDate": null,
"address": {
"streetAddress": "123 A Street, A place",
"postalCode": "SE2 0QG",
"addressLocality": "Belvedere",
"addressRegion": "London (region)"
},
"organizer": null
}
}
]
}
}
}
Events can be filtered by date range, neighbourhood or tag. All events are returned in ascending order of start date.
let queryString = `
query EventsByFilter(
$fromDate: String,
$toDate: String,
$neighbourhoodId: Int,
$tagId: Int)
{
eventsByFilter(
fromDate: $fromDate,
toDate: $toDate,
neighbourhoodId: $neighbourhoodId,
tagId: $tagId)
{
id
name
summary
description
startDate
endDate
address {
streetAddress
postalCode
addressLocality
addressRegion
}
organizer {
id
name
}
}
}`;
/*
notes on event filter
The filter has the following parameters:
fromDate: the initial start point. defaults to
date request was made. can be in the past.
format is YYYY-MM-DD HH:MM
toDate: the end limit of query. must be after fromDate
neighbourhoodId: scope events to be in a
neighbourhood. returns events in BOTH
the address and service area.
tagId: scope events to only one tag
*/
query(queryString)
.then( (response) => {
console.log(JSON.stringify(response, null, 2));
});
/* response */
{
"data": {
"eventsByFilter": []
}
}