Skip to content

Commit be08494

Browse files
authored
Merge pull request #44 from imcaizheng/improve-search-taas-teams
GET /taas-teams supports params
2 parents cb5d9ed + bf56071 commit be08494

File tree

7 files changed

+163
-38
lines changed

7 files changed

+163
-38
lines changed

app.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ const logger = require('./src/common/logger')
1414
// setup express app
1515
const app = express()
1616

17-
app.use(cors())
17+
app.use(cors({
18+
// Allow browsers access pagination data in headers
19+
exposedHeaders: ['X-Page', 'X-Per-Page', 'X-Total', 'X-Total-Pages', 'X-Prev-Page', 'X-Next-Page']
20+
}))
1821
app.use(express.json())
1922
app.use(express.urlencoded({ extended: true }))
2023
app.set('port', config.PORT)

docs/Topcoder-bookings-api.postman_collection.json

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"info": {
3-
"_postman_id": "418b385c-5ce1-4810-b357-cddf05adf271",
3+
"_postman_id": "282e8342-2d5a-4566-8509-f2f240a594a0",
44
"name": "Topcoder-bookings-api",
55
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
66
},
@@ -14,7 +14,7 @@
1414
{
1515
"listen": "test",
1616
"script": {
17-
"id": "ff119e52-58f4-4501-8193-dd8c75f9ba4a",
17+
"id": "a2236151-22f2-46c7-869a-858eb7da1ab8",
1818
"exec": [
1919
"var data = JSON.parse(responseBody);\r",
2020
"postman.setEnvironmentVariable(\"jobId\",data.id);"
@@ -59,7 +59,7 @@
5959
{
6060
"listen": "test",
6161
"script": {
62-
"id": "66169f57-ba0e-4a88-85c3-e27ee380c332",
62+
"id": "91236482-d7b2-4acd-a47d-e9f9ac833bad",
6363
"exec": [
6464
"var data = JSON.parse(responseBody);\r",
6565
"postman.setEnvironmentVariable(\"jobId\",data.id);"
@@ -104,7 +104,7 @@
104104
{
105105
"listen": "test",
106106
"script": {
107-
"id": "31016a7d-5de6-4802-92f8-b1c7a9afcc4a",
107+
"id": "1e5b5bdf-6ff0-4d96-8018-8698bc359674",
108108
"exec": [
109109
"var data = JSON.parse(responseBody);",
110110
"postman.setEnvironmentVariable(\"jobIdCreatedByMember\",data.id);"
@@ -149,7 +149,7 @@
149149
{
150150
"listen": "test",
151151
"script": {
152-
"id": "0b96c49d-6fb7-49ab-bfe1-4623ffe1be10",
152+
"id": "0b469a8d-8119-4907-ac37-a69a1766754d",
153153
"exec": [
154154
""
155155
],
@@ -193,7 +193,7 @@
193193
{
194194
"listen": "test",
195195
"script": {
196-
"id": "bce80082-b100-466d-a196-73e9c38e2b9d",
196+
"id": "fec863ef-1db6-4008-8a9d-ef616e3cac4d",
197197
"exec": [
198198
""
199199
],
@@ -785,7 +785,7 @@
785785
{
786786
"listen": "test",
787787
"script": {
788-
"id": "40f37d6f-508f-47ba-bbd4-41e1e0c3a4a2",
788+
"id": "28720714-8006-4fd5-b3b8-0c588266bb5e",
789789
"exec": [
790790
"pm.test(\"Status code is 403\", function () {",
791791
" pm.response.to.have.status(403);",
@@ -997,7 +997,7 @@
997997
{
998998
"listen": "test",
999999
"script": {
1000-
"id": "5d25999b-14ec-432c-bf11-028ec73a7140",
1000+
"id": "aa7fa1f8-cca2-4323-8266-ff4e770dae10",
10011001
"exec": [
10021002
"pm.test(\"Status code is 403\", function () {",
10031003
" pm.response.to.have.status(403);",
@@ -1209,7 +1209,7 @@
12091209
{
12101210
"listen": "test",
12111211
"script": {
1212-
"id": "5f89405c-6907-41c8-8630-ccb5d5d640e6",
1212+
"id": "8299d83c-e5c3-4639-8c4a-bf783f178fb2",
12131213
"exec": [
12141214
"pm.test(\"Status code is 403\", function () {",
12151215
" pm.response.to.have.status(403);",
@@ -1328,7 +1328,7 @@
13281328
{
13291329
"listen": "test",
13301330
"script": {
1331-
"id": "865f0f13-444b-4247-902d-b3e6cdb1898e",
1331+
"id": "cbee0ff6-5824-447c-915d-466bfd5242bc",
13321332
"exec": [
13331333
"var data = JSON.parse(responseBody);\r",
13341334
"postman.setEnvironmentVariable(\"jobCandidateId\",data.id);"
@@ -1373,7 +1373,7 @@
13731373
{
13741374
"listen": "test",
13751375
"script": {
1376-
"id": "37973c93-a13f-448d-8f02-af7f18818df2",
1376+
"id": "6a1b4404-55ef-40e8-981a-3cb9e960d6ea",
13771377
"exec": [
13781378
"var data = JSON.parse(responseBody);\r",
13791379
"postman.setEnvironmentVariable(\"jobCandidateId\",data.id);"
@@ -1418,7 +1418,7 @@
14181418
{
14191419
"listen": "test",
14201420
"script": {
1421-
"id": "79490454-9392-42f1-8f07-7ab1950318df",
1421+
"id": "a42f6045-fdb2-4d61-8dd4-a919573f5d24",
14221422
"exec": [
14231423
"var data = JSON.parse(responseBody);\r",
14241424
"postman.setEnvironmentVariable(\"jobCandidateId\",data.id);"
@@ -1463,7 +1463,7 @@
14631463
{
14641464
"listen": "test",
14651465
"script": {
1466-
"id": "99a176e1-645b-47ca-91b4-940fbebc65f6",
1466+
"id": "b133db18-fa52-4a59-9e35-5e7d340b7f1d",
14671467
"exec": [
14681468
"var data = JSON.parse(responseBody);\r",
14691469
"postman.setEnvironmentVariable(\"jobCandidateId\",data.id);"
@@ -1508,7 +1508,7 @@
15081508
{
15091509
"listen": "test",
15101510
"script": {
1511-
"id": "92b01e89-a317-4663-95f0-ecb861fceefb",
1511+
"id": "6cd47ee8-4139-4309-8cb1-ceb74d2d06eb",
15121512
"exec": [
15131513
""
15141514
],
@@ -2325,7 +2325,7 @@
23252325
{
23262326
"listen": "test",
23272327
"script": {
2328-
"id": "d8fcb38d-6699-4710-9db2-13fb3c814dff",
2328+
"id": "2722fecc-08fa-4d6e-9895-e7ed844f21c9",
23292329
"exec": [
23302330
"var data = JSON.parse(responseBody);\r",
23312331
"postman.setEnvironmentVariable(\"resourceBookingId\",data.id);"
@@ -2370,7 +2370,7 @@
23702370
{
23712371
"listen": "test",
23722372
"script": {
2373-
"id": "45daab6c-adbd-4083-84e9-0e64640e6d95",
2373+
"id": "86edd7ff-eef6-4976-ae59-101fbe154e2c",
23742374
"exec": [
23752375
"var data = JSON.parse(responseBody);\r",
23762376
"postman.setEnvironmentVariable(\"resourceBookingId\",data.id);"
@@ -2415,7 +2415,7 @@
24152415
{
24162416
"listen": "test",
24172417
"script": {
2418-
"id": "daa443f9-6ba1-48b0-9c59-b7e7e4192244",
2418+
"id": "10be7afd-f528-4abf-a524-a9642678c436",
24192419
"exec": [
24202420
""
24212421
],
@@ -2459,7 +2459,7 @@
24592459
{
24602460
"listen": "test",
24612461
"script": {
2462-
"id": "693dffa5-7de5-4940-8e1b-3053cb6a5684",
2462+
"id": "ad50f131-aff8-4e32-acda-d647889d4dc3",
24632463
"exec": [
24642464
""
24652465
],
@@ -2503,7 +2503,7 @@
25032503
{
25042504
"listen": "test",
25052505
"script": {
2506-
"id": "dba6c30b-b9c8-4750-8f97-e98bb21aa436",
2506+
"id": "ebe085f5-b1ce-455b-b147-c4c6f4cd4283",
25072507
"exec": [
25082508
""
25092509
],
@@ -3365,12 +3365,37 @@
33653365
}
33663366
],
33673367
"url": {
3368-
"raw": "{{URL}}/taas-teams",
3368+
"raw": "{{URL}}/taas-teams?perPage=10&page=1&name=*taas*&sortBy=lastActivityAt&sortOrder=desc",
33693369
"host": [
33703370
"{{URL}}"
33713371
],
33723372
"path": [
33733373
"taas-teams"
3374+
],
3375+
"query": [
3376+
{
3377+
"key": "perPage",
3378+
"value": "10"
3379+
},
3380+
{
3381+
"key": "page",
3382+
"value": "1"
3383+
},
3384+
{
3385+
"key": "name",
3386+
"value": "*taas*",
3387+
"description": "case-insensitive; support wildcard match"
3388+
},
3389+
{
3390+
"key": "sortBy",
3391+
"value": "lastActivityAt",
3392+
"description": "allows: createdAt, updatedAt, lastActivityAt, id, status, name, type, best match"
3393+
},
3394+
{
3395+
"key": "sortOrder",
3396+
"value": "desc",
3397+
"description": "allows: asc, desc"
3398+
}
33743399
]
33753400
}
33763401
},

docs/swagger.yaml

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,6 +1278,44 @@ paths:
12781278
- Teams
12791279
description: |
12801280
Search my teams. Teams is project in topcoder with type=='talent-as-a-service'
1281+
parameters:
1282+
- in: query
1283+
name: page
1284+
required: false
1285+
schema:
1286+
type: integer
1287+
default: 1
1288+
description: The page number.
1289+
- in: query
1290+
name: perPage
1291+
required: false
1292+
schema:
1293+
type: integer
1294+
default: 20
1295+
description: The number of items to list per page.
1296+
- in: query
1297+
name: sortBy
1298+
required: false
1299+
schema:
1300+
type: string
1301+
default: createdAt
1302+
enum: ['createdAt', 'updatedAt', 'lastActivityAt', 'id', 'status', 'name', 'type', 'best match']
1303+
description: The sort by column.
1304+
- in: query
1305+
name: sortOrder
1306+
required: false
1307+
schema:
1308+
type: string
1309+
default: desc
1310+
enum: ['desc','asc']
1311+
description: The sort order. Not allowed when sortBy is `best match`.
1312+
- in: query
1313+
name: name
1314+
required: false
1315+
schema:
1316+
type: string
1317+
description: filter by name, case-insensitive; support wildcard match.
1318+
example: '*taas*'
12811319
security:
12821320
- bearerAuth: []
12831321
responses:
@@ -1289,6 +1327,35 @@ paths:
12891327
type: array
12901328
items:
12911329
$ref: '#/components/schemas/Team'
1330+
headers:
1331+
X-Next-Page:
1332+
schema:
1333+
type: integer
1334+
description: The index of the next page
1335+
X-Page:
1336+
schema:
1337+
type: integer
1338+
description: The index of the current page (starting at 1)
1339+
X-Per-Page:
1340+
schema:
1341+
type: integer
1342+
description: The number of items to list per page
1343+
X-Prev-Page:
1344+
schema:
1345+
type: integer
1346+
description: The index of the previous page
1347+
X-Total:
1348+
schema:
1349+
type: integer
1350+
description: The total number of items
1351+
X-Total-Pages:
1352+
schema:
1353+
type: integer
1354+
description: The total number of pages
1355+
Link:
1356+
schema:
1357+
type: string
1358+
description: Pagination link header.
12921359
'400':
12931360
description: Bad request
12941361
content:

src/bootstrap.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ const Joi = require('joi')
33
const path = require('path')
44
const logger = require('./common/logger')
55

6+
Joi.page = () => Joi.number().integer().min(1).default(1)
7+
Joi.perPage = () => Joi.number().integer().min(1).default(20)
68
Joi.rateType = () => Joi.string().valid('hourly', 'daily', 'weekly', 'monthly')
79
Joi.jobStatus = () => Joi.string().valid('sourcing', 'in-review', 'assigned', 'closed', 'cancelled')
810
Joi.workload = () => Joi.string().valid('full-time', 'fractional')

src/common/helper.js

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -124,14 +124,6 @@ function setResHeaders (req, res, result) {
124124
}
125125
res.set('Link', link)
126126
}
127-
128-
// Allow browsers access pagination data in headers
129-
let accessControlExposeHeaders = res.get('Access-Control-Expose-Headers') || ''
130-
accessControlExposeHeaders += accessControlExposeHeaders ? ', ' : ''
131-
// append new values, to not override values set by someone else
132-
accessControlExposeHeaders += 'X-Page, X-Per-Page, X-Total, X-Total-Pages, X-Prev-Page, X-Next-Page'
133-
134-
res.set('Access-Control-Expose-Headers', accessControlExposeHeaders)
135127
}
136128

137129
/**
@@ -305,19 +297,27 @@ function isDocumentMissingException (err) {
305297
/**
306298
* Function to get projects
307299
* @param {String} token the user request token
300+
* @param {Object} criteria the search criteria
308301
* @returns the request result
309302
*/
310-
async function getProjects (token) {
303+
async function getProjects (token, criteria = {}) {
311304
const url = `${config.TC_API}/projects?type=talent-as-a-service`
312305
const res = await request
313306
.get(url)
307+
.query(criteria)
314308
.set('Authorization', token)
315309
.set('Content-Type', 'application/json')
316310
.set('Accept', 'application/json')
317311
localLogger.debug({ context: 'getProjects', message: `response body: ${JSON.stringify(res.body)}` })
318-
return _.map(res.body, item => {
312+
const result = _.map(res.body, item => {
319313
return _.pick(item, ['id', 'name'])
320314
})
315+
return {
316+
total: Number(_.get(res.headers, 'x-total')),
317+
page: Number(_.get(res.headers, 'x-page')),
318+
perPage: Number(_.get(res.headers, 'x-per-page')),
319+
result
320+
}
321321
}
322322

323323
/**

src/controllers/TeamController.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@
22
* Controller for TaaS teams endpoints
33
*/
44
const service = require('../services/TeamService')
5+
const helper = require('../common/helper')
56

67
/**
78
* Search teams
89
* @param req the request
910
* @param res the response
1011
*/
1112
async function searchTeams (req, res) {
12-
res.send(await service.searchTeams(req.authUser))
13+
const result = await service.searchTeams(req.authUser, req.query)
14+
helper.setResHeaders(req, res, result)
15+
res.send({ result: result.result })
1316
}
1417

1518
/**

0 commit comments

Comments
 (0)