Skip to content
This repository has been archived by the owner on Sep 21, 2022. It is now read-only.

Commit

Permalink
Merge pull request #6 from outgrow/outgrow-add-sentEmails-query
Browse files Browse the repository at this point in the history
Implement emailJobs GraphQL query
  • Loading branch information
jrw421 committed Mar 2, 2021
2 parents fb3d3f2 + c665732 commit 94426b6
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 2 deletions.
2 changes: 2 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import pkg from "../package.json";
import i18n from "./i18n/index.js";
import mutations from "./mutations/index.js";
import policies from "./policies.json";
import queries from "./queries/index.js";
import startup from "./startup.js";
import resolvers from "./resolvers/index.js";
import schemas from "./schemas/index.js";
Expand Down Expand Up @@ -32,6 +33,7 @@ export default async function register(app) {
},
mutations,
policies,
queries,
functionsByType: {
startup: [startup]
}
Expand Down
24 changes: 24 additions & 0 deletions src/queries/emailJobs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* @name emailJobs
* @method
* @memberof Email
* @summary query the Jobs collection and return email jobs
* @param {Object} context - an object containing the per-request state
* @param {String[]} shopIds - ids of the shops to get emails for
* @returns {Object} group object
*/
export default async function emailJobs(context, shopIds) {
const { collections } = context;
const { Jobs } = collections;

const validatePermissionsForShopIds = shopIds.map((shopId) => context.validatePermissions("reaction:legacy:emails", "read", { shopId }));

await Promise.all(validatePermissionsForShopIds);

return Jobs.find({
"type": "sendEmail",
"data.shopId": {
$in: shopIds
}
});
}
5 changes: 5 additions & 0 deletions src/queries/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import emailJobs from "./emailJobs.js";

export default {
emailJobs
};
32 changes: 32 additions & 0 deletions src/resolvers/Query/emailJobs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import getPaginatedResponse from "@reactioncommerce/api-utils/graphql/getPaginatedResponse.js";
import wasFieldRequested from "@reactioncommerce/api-utils/graphql/wasFieldRequested.js";
import { decodeShopOpaqueId } from "../../xforms/id.js";

/**
* @name Query.emailJobs
* @method
* @memberof Routes/GraphQL
* @summary Returns a paginated list of `sendEmail` jobs
* @param {Object} parentResult unused
* @param {Object} args Arguments from the client
* @param {String} args.shopIds IDs of the shops to get emails for
* @param {Object} context - an object containing the per-request state
* @param {Object} info Info about the GraphQL request
* @returns {Promise<Object>} Email jobs connection
*/
export default async function emailJobs(parentResult, args, context, info) {
const {
shopIds: opaqueShopIds,
...connectionArgs
} = args;

const shopIds = opaqueShopIds.map((opaqueShopId) => decodeShopOpaqueId(opaqueShopId));

const cursor = await context.queries.emailJobs(context, shopIds);

return getPaginatedResponse(cursor, connectionArgs, {
includeHasNextPage: wasFieldRequested("pageInfo.hasNextPage", info),
includeHasPreviousPage: wasFieldRequested("pageInfo.hasPreviousPage", info),
includeTotalCount: wasFieldRequested("totalCount", info)
});
}
5 changes: 5 additions & 0 deletions src/resolvers/Query/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import emailJobs from "./emailJobs.js";

export default {
emailJobs
};
6 changes: 5 additions & 1 deletion src/resolvers/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import getConnectionTypeResolvers from "@reactioncommerce/api-utils/graphql/getConnectionTypeResolvers.js";
import Mutation from "./Mutation/index.js";
import Query from "./Query/index.js";

export default {
Mutation
Mutation,
Query,
...getConnectionTypeResolvers("EmailJob")
};
80 changes: 80 additions & 0 deletions src/schemas/emailJobs.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"The data of the e-mail"
type EmailJobData {
"The address the e-mail was/is being/will be sent to"
to: String!

"The subject of the e-mail"
subject: String!
}

"An e-mail job"
type EmailJob {
"The ID of the e-mail job"
_id: ID!

"The date and time of the last update to the e-mail job"
updated: DateTime!

"The status of the e-mail job"
status: String!

"The data of the e-mail"
data: EmailJobData!
}

"A connection edge in which each node is an `EmailJob` object"
type EmailJobEdge {
"The cursor that represents this node in the paginated results"
cursor: ConnectionCursor!

"The product"
node: EmailJob
}

"""
Wraps a list of `EmailJob`s, providing pagination cursors and information.
For information about what Relay-compatible connections are and how to use them, see the following articles:
- [Relay Connection Documentation](https://facebook.github.io/relay/docs/en/graphql-server-specification.html#connections)
- [Relay Connection Specification](https://facebook.github.io/relay/graphql/connections.htm)
- [Using Relay-style Connections With Apollo Client](https://www.apollographql.com/docs/react/recipes/pagination.html)
"""
type EmailJobConnection {
"The list of nodes that match the query, wrapped in an edge to provide a cursor string for each"
edges: [EmailJobEdge]

"""
You can request the `nodes` directly to avoid the extra wrapping that `NodeEdge` has,
if you know you will not need to paginate the results.
"""
nodes: [EmailJob]

"Information to help a client request the next or previous page"
pageInfo: PageInfo!

"The total number of nodes that match your query"
totalCount: Int!
}

extend type Query {
"Get e-mail jobs for a given set of shops"
emailJobs(
"The shop IDs to get e-mail jobs for"
shopIds: [ID]!,

"Return only results that come after this cursor. Use this with `first` to specify the number of results to return."
after: ConnectionCursor,

"Return only results that come before this cursor. Use this with `last` to specify the number of results to return."
before: ConnectionCursor,

"Return at most this many results. This parameter may be used with either `after` or `offset` parameters."
first: ConnectionLimitInt,

"Return at most this many results. This parameter may be used with the `before` parameter."
last: ConnectionLimitInt,

"Return only results that come after the Nth result. This parameter may be used with the `first` parameter."
offset: Int
): EmailJobConnection!
}
3 changes: 2 additions & 1 deletion src/schemas/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import importAsString from "@reactioncommerce/api-utils/importAsString.js";

const emailJobs = importAsString("./emailJobs.graphql");
const retryFailedEmail = importAsString("./retryFailedEmail.graphql");

export default [retryFailedEmail];
export default [emailJobs, retryFailedEmail];

0 comments on commit 94426b6

Please sign in to comment.