Skip to content

Commit 4d632a6

Browse files
authored
Merge pull request #59 from blinkmobile/ON-4682
Added search() function to Jobs class
2 parents 3a5523e + d31b8a5 commit 4d632a6

File tree

6 files changed

+311
-76
lines changed

6 files changed

+311
-76
lines changed

changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Unreleased
44

5+
### Added
6+
7+
- Added [`search()`](./docs/jobs#search) function to Jobs class
8+
59
# 0.4.0 (2019-12-18)
610

711
### Added

classes/Jobs.js

Lines changed: 86 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,32 @@ const Joi = require('joi')
66
const OneBlinkAPI = require('../lib/one-blink-api.js')
77
const setPreFillData = require('../lib/pre-fill-data.js')
88

9-
const newJobSchema = Joi.object().label('options').required().keys({
10-
username: Joi.string().required(),
11-
formId: Joi.number().required().min(1),
12-
externalId: Joi.string(),
13-
details: Joi.object().required().keys({
14-
key: Joi.string(),
15-
title: Joi.string().required(),
16-
description: Joi.string(),
17-
type: Joi.string()
9+
const newJobSchema = Joi.object()
10+
.label('options')
11+
.required()
12+
.keys({
13+
username: Joi.string().required(),
14+
formId: Joi.number()
15+
.required()
16+
.min(1),
17+
externalId: Joi.string(),
18+
details: Joi.object()
19+
.required()
20+
.keys({
21+
key: Joi.string(),
22+
title: Joi.string().required(),
23+
description: Joi.string(),
24+
type: Joi.string()
25+
})
1826
})
19-
})
2027

2128
module.exports = class Jobs extends OneBlinkAPI {
22-
constructor (
23-
options /* : ConstructorOptions */
24-
) {
29+
constructor(options /* : ConstructorOptions */) {
2530
options = options || {}
26-
super(
27-
options.oneBlinkAPIOrigin,
28-
options.accessKey,
29-
options.secretKey
30-
)
31+
super(options.oneBlinkAPIOrigin, options.accessKey, options.secretKey)
3132
}
3233

33-
async createJob (
34+
async createJob(
3435
options /* : ?mixed */,
3536
preFillData /* : ?mixed */
3637
) /* : Promise<Job> */ {
@@ -44,23 +45,84 @@ module.exports = class Jobs extends OneBlinkAPI {
4445
const newJob /* : NewJob */ = result.value
4546

4647
if (preFillData) {
47-
const preFillMeta = await super.postRequest(`/forms/${newJob.formId}/pre-fill-credentials`)
48+
const preFillMeta = await super.postRequest(
49+
`/forms/${newJob.formId}/pre-fill-credentials`
50+
)
4851
await setPreFillData(preFillMeta, preFillData)
4952
newJob.preFillFormDataId = preFillMeta.preFillFormDataId
5053
}
5154

52-
const job /* Job */ = await super.postRequest('/jobs', newJob)
55+
const job /* : Job */ = await super.postRequest('/jobs', newJob)
5356

5457
return job
5558
}
5659

57-
deleteJob (
58-
jobId /* : ?mixed */
59-
) /* : Promise<void> */ {
60+
deleteJob(jobId /* : ?mixed */) /* : Promise<void> */ {
6061
if (!jobId || typeof jobId !== 'string') {
6162
return Promise.reject(new TypeError('Must supply "jobId" as a string'))
6263
}
6364

6465
return super.deleteRequest(`/jobs/${jobId}`)
6566
}
67+
68+
async search(
69+
options /* : ?mixed */
70+
) /* : Promise<JobsSearchResult> */ {
71+
let searchOptions = {}
72+
73+
if (options) {
74+
if (options.externalId) {
75+
if (typeof options.externalId !== 'string') {
76+
throw new TypeError(
77+
`externalId must be provided as a string or not at all`
78+
)
79+
}
80+
searchOptions = Object.assign(searchOptions, { externalId: options.externalId })
81+
}
82+
83+
if (options.username) {
84+
if (typeof options.username !== 'string') {
85+
throw new TypeError(
86+
`username must be provided as a string or not at all`
87+
)
88+
}
89+
searchOptions = Object.assign(searchOptions, { username: options.username })
90+
}
91+
92+
if (options.isSubmitted) {
93+
if (typeof options.isSubmitted !== 'boolean') {
94+
throw new TypeError(
95+
`isSubmitted must be provided as a boolean or not at all`
96+
)
97+
}
98+
searchOptions = Object.assign(searchOptions, { isSubmitted: options.isSubmitted })
99+
}
100+
101+
if (options.formId) {
102+
if (typeof options.formId !== 'number') {
103+
throw new TypeError(`formId must be provided as a number or not at all`)
104+
}
105+
searchOptions = Object.assign(searchOptions, { formId: options.formId })
106+
}
107+
108+
if (options.limit) {
109+
if (typeof options.limit !== 'number') {
110+
throw new TypeError(`limit must be provided as a number or not at all`)
111+
}
112+
searchOptions = Object.assign(searchOptions, { limit: options.limit })
113+
}
114+
115+
if (options.offset) {
116+
if (typeof options.offset !== 'number') {
117+
throw new TypeError(`offset must be provided as a number or not at all`)
118+
}
119+
searchOptions = Object.assign(searchOptions, { offset: options.offset })
120+
}
121+
}
122+
123+
const results =
124+
await super.searchRequest/*:: <JobsSearchOptions, JobsSearchResult> */(`/jobs`, searchOptions)
125+
126+
return results
127+
}
66128
}

docs/jobs.md

Lines changed: 65 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,9 @@ const preFillData = {
3939
text_element: 'abc',
4040
number_element: 123
4141
}
42-
jobs.createJob(newJob, preFillData)
43-
.then((job) => {
44-
// job.id can be used to delete the Job
45-
})
42+
jobs.createJob(newJob, preFillData).then(job => {
43+
// job.id can be used to delete the Job
44+
})
4645
```
4746

4847
### Parameters
@@ -53,12 +52,12 @@ jobs.createJob(newJob, preFillData)
5352
| `newJob.username` | Yes | `string` | The identifier of the User to assign the Job to |
5453
| `newJob.formId` | Yes | `number` | The identifier of the Form the User must complete |
5554
| `newJob.externalId` | No | `string` | The external identifier of the form submission you wish to use, this identifier will be returned to you with the `submissionId` after a successful submission to allow you to retrieve the data later |
56-
| `newJob.details` | Yes | `Object` | Extra Job details that will be displayed to the User |
55+
| `newJob.details` | Yes | `Object` | Extra Job details that will be displayed to the User |
5756
| `newJob.details.key` | No | `string` | A key for the User the identify the Job |
5857
| `newJob.details.title` | Yes | `string` | A title for the User the identify the Job |
5958
| `newJob.details.description` | No | `string` | A short description of the what the job may entail |
6059
| `newJob.details.type` | No | `string` | A type for the User to categorise the Job |
61-
| `preFillData` | No | `Object` | key/value pairs with the form field names as keys and the pre-fill data as the values |
60+
| `preFillData` | No | `Object` | key/value pairs with the form field names as keys and the pre-fill data as the values |
6261

6362
### Result (Resolved Promise)
6463

@@ -85,18 +84,70 @@ jobs.createJob(newJob, preFillData)
8584

8685
```javascript
8786
const jobId = 'f73985fd-2dba-4bf7-abbe-e204889f5216'
88-
jobs.deleteJob(jobId)
89-
.then(() => {
90-
// Job has been deleted
91-
})
87+
jobs.deleteJob(jobId).then(() => {
88+
// Job has been deleted
89+
})
9290
```
9391

9492
### Parameters
9593

96-
| Parameter | Required | Type | Description |
97-
| --------- | -------- | -------- | --------------------------------------- |
98-
| `keyId` | Yes | `string` | The exact id of the key you wish to get |
94+
| Parameter | Required | Type | Description |
95+
| --------- | -------- | -------- | ------------------------------------------ |
96+
| `jobId` | Yes | `string` | The exact id of the job you wish to delete |
9997

10098
### Result (Resolved Promise)
10199

102-
- No return value (`undefined`)
100+
- No return value (`undefined`)
101+
102+
## Search
103+
104+
### Example
105+
106+
```javascript
107+
const results = await jobs.search({
108+
username: '[email protected]',
109+
formId: 10
110+
})
111+
112+
// an array of jobs
113+
const jobs = results.jobs
114+
```
115+
116+
### Parameters
117+
118+
| Parameter | Required | Type | Description |
119+
| --------------------- | -------- | --------- | ------------------------------------------------------------------------------------- |
120+
| `options` | No | `Object` | Search options |
121+
| `options.externalId` | No | `string` | The `externalId` property of a job |
122+
| `options.formId` | No | `number` | The `formId` matching the form that a job was created for |
123+
| `options.username` | No | `string` | The `username` that the job was assigned to |
124+
| `options.isSubmitted` | No | `boolean` | Whether the job has been submitted or not |
125+
| `options.limit` | No | `number` | Limit the number of jobs returned |
126+
| `options.offset` | No | `number` | Skip a specific number of results, used in conjunction with `limit` to enforce paging |
127+
128+
### Result (Resolved Promise)
129+
130+
```json
131+
{
132+
"meta": {
133+
"limit": null,
134+
"offset": null
135+
},
136+
"jobs": [
137+
{
138+
"id": "f73985fd-2dba-4bf7-abbe-e204889f5216",
139+
"isSubmitted": false,
140+
"createdAt": "2019-02-10T23:00:35.566Z",
141+
"username": "[email protected]",
142+
"formId": 10,
143+
"externalId": "your-job-identifier",
144+
"details": {
145+
"key": "JOB-123",
146+
"title": "Job Title",
147+
"description": "Job description",
148+
"type": "Type"
149+
}
150+
}
151+
]
152+
}
153+
```

flow-typed/types.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,5 +249,22 @@ type Role = {
249249
createdAt: string,
250250
updatedAt: string
251251
}
252+
253+
declare type JobsSearchOptions = {
254+
username?: string,
255+
externalId?: string,
256+
formId?: number,
257+
isSubmitted?: boolean,
258+
limit?: number,
259+
offset?: number
260+
}
261+
262+
declare type JobsSearchResult = {
263+
meta: {
264+
limit: number,
265+
offset: number
266+
},
267+
jobs: Job[]
268+
}
252269
*/
253270

lib/one-blink-api.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ module.exports = class OneBlinkAPI {
4343
typeof apiOrigin === 'string' ? apiOrigin : 'https://auth-api.blinkm.io'
4444
})
4545

46-
this.oneBlinkAPI.defaults.headers.common['User-Agent'] = `Node.js ${
47-
pkg.name
48-
} / ${pkg.version}`
46+
const userAgentHeader = `Node.js ${pkg.name} / ${pkg.version}`
47+
48+
this.oneBlinkAPI.defaults.headers.common['User-Agent'] = userAgentHeader
4949
}
5050

5151
get defaultRequestConfig() {
@@ -60,19 +60,20 @@ module.exports = class OneBlinkAPI {
6060
}
6161
}
6262

63-
getRequest(path /* : string */) /* Promise<Object> */ {
63+
getRequest /* :: <TOut> */(path /* : string */) /* : Promise<TOut> */ {
6464
// 5 minute expiry
6565
return this.oneBlinkAPI
6666
.get(path, this.defaultRequestConfig)
6767
.then(response => response.data)
6868
.catch(errorHandler)
6969
}
7070

71-
searchRequest(
71+
searchRequest /*:: <T, TOut> */(
7272
path /* : string */,
73-
searchParams /* : ?{ [key: string]: mixed } */
74-
) /* Promise<Object> */ {
73+
searchParams /* : ?T */
74+
) /* : Promise<TOut> */ {
7575
const search = querystring.stringify(searchParams || {})
76+
7677
return this.getRequest(`${path}?${search}`)
7778
}
7879

0 commit comments

Comments
 (0)