Skip to content

Commit 8617143

Browse files
authored
Merge pull request #78 from judemanutd/develop
Updated Fetch all components API & Updated Docs
2 parents 4883708 + b67f941 commit 8617143

File tree

7 files changed

+227
-20
lines changed

7 files changed

+227
-20
lines changed

functions/src/controllers/PortfolioController.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,12 @@ export default class PortfolioController {
6060
"Please specify components that need to be included in the portfolio",
6161
);
6262

63-
const result = await addPortfolio(parsedPayload.title, components, parsedPayload.description);
63+
const result = await addPortfolio(
64+
parsedPayload.title,
65+
components,
66+
payload,
67+
parsedPayload.description,
68+
);
6469
return result;
6570
} catch (error) {
6671
throw error;
@@ -117,6 +122,7 @@ export default class PortfolioController {
117122
portfolioId,
118123
parsedPayload.title,
119124
components,
125+
payload,
120126
parsedPayload.description,
121127
);
122128
return result;
@@ -148,12 +154,10 @@ export default class PortfolioController {
148154
* ADMIN
149155
*
150156
* fetch all portfolios
151-
*
152-
* @param showComponents - boolean to indicate if the components should be fetched as well
153157
*/
154-
public fetchPortfolios = async (showComponents: boolean = false) => {
158+
public fetchPortfolios = async () => {
155159
try {
156-
const result = await fetchPortFolios(showComponents);
160+
const result = await fetchPortFolios();
157161
return result;
158162
} catch (error) {
159163
throw error;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export default interface IPortfolioRefs {
2+
category: FirebaseFirestore.DocumentReference[];
3+
project: FirebaseFirestore.DocumentReference[];
4+
technology: FirebaseFirestore.DocumentReference[];
5+
component: FirebaseFirestore.DocumentReference[];
6+
}

functions/src/models/Portfolio.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ import nanoid from "nanoid";
33
import Component from "./Component";
44
import { STATUS_ACTIVE } from "~utils/constants";
55
import portfolioSchema from "~schemas/PortfolioSchema";
6+
import IPortfolioRefs from "~interfaces/IPortfolioRefs";
67

78
class Portfolio {
89
public static init = (
910
title: string,
1011
componentIdRefs: FirebaseFirestore.DocumentReference[],
12+
refs: IPortfolioRefs,
1113
description?: string,
1214
) => {
1315
const id = uuid();
@@ -18,6 +20,7 @@ class Portfolio {
1820
description,
1921
code: nanoid(10),
2022
components: componentIdRefs,
23+
refs,
2124
status: STATUS_ACTIVE,
2225
createdAt: new Date(),
2326
updatedAt: new Date(),

functions/src/repository/PortfolioRepo.ts

Lines changed: 154 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { parseRow as parseComponentRow } from "~repository/ComponentRepo";
66
import { entityNotFoundError } from "~exceptions/genericErrors";
77
import APIError from "~utils/APIError";
88
import { HTTP_BAD_REQUEST } from "~utils/http_code";
9+
import { IPortfolioPayload } from "~interfaces/IPortfolioPayload";
910

1011
/**
1112
* ADMIN
@@ -14,11 +15,13 @@ import { HTTP_BAD_REQUEST } from "~utils/http_code";
1415
*
1516
* @param title - title for the portfolio
1617
* @param components - components that belong to the given portfolio
18+
* @param payload - original payload so part of it can be saved in the db for future retrieval
1719
* @param description - optional descrition for the portfolio
1820
*/
1921
export const addPortfolio = async (
2022
title: string,
2123
components: Component[],
24+
payload: IPortfolioPayload,
2225
description?: string,
2326
) => {
2427
try {
@@ -28,7 +31,40 @@ export const addPortfolio = async (
2831
.doc(component.id),
2932
);
3033

31-
const insertObj = Portfolio.init(title, componentRefs, description);
34+
const { categoryId, componentId, projectId, technologyId } = payload;
35+
36+
const payloadComponentRefs = componentId.map(component =>
37+
getDb()
38+
.collection("components")
39+
.doc(component),
40+
);
41+
42+
const payloadCategoryRefs = categoryId.map(category =>
43+
getDb()
44+
.collection("categories")
45+
.doc(category),
46+
);
47+
48+
const payloadProjectRefs = projectId.map(project =>
49+
getDb()
50+
.collection("projects")
51+
.doc(project),
52+
);
53+
54+
const payloadTechnologyRefs = technologyId.map(technology =>
55+
getDb()
56+
.collection("technologies")
57+
.doc(technology),
58+
);
59+
60+
const refs = {
61+
category: payloadCategoryRefs,
62+
project: payloadProjectRefs,
63+
technology: payloadTechnologyRefs,
64+
component: payloadComponentRefs,
65+
};
66+
67+
const insertObj = Portfolio.init(title, componentRefs, refs, description);
3268

3369
await getDb()
3470
.collection("portfolios")
@@ -52,12 +88,14 @@ export const addPortfolio = async (
5288
* @param portfolioId - id of the portfolio that needs to be updated
5389
* @param title - title for the portfolio
5490
* @param components - components that belong to the given portfolio
91+
* @param payload - original payload so part of it can be saved in the db for future retrieval
5592
* @param description - optional descrition for the portfolio
5693
*/
5794
export const updatePortfolio = async (
5895
portfolioId: string,
5996
title: string,
6097
components: Component[],
98+
payload: IPortfolioPayload,
6199
description?: string,
62100
) => {
63101
try {
@@ -85,6 +123,41 @@ export const updatePortfolio = async (
85123
throw new APIError("No attributes specified for updation", undefined, HTTP_BAD_REQUEST);
86124
}
87125

126+
const { categoryId, componentId, projectId, technologyId } = payload;
127+
128+
const payloadComponentRefs = componentId.map(component =>
129+
getDb()
130+
.collection("components")
131+
.doc(component),
132+
);
133+
134+
const payloadCategoryRefs = categoryId.map(category =>
135+
getDb()
136+
.collection("categories")
137+
.doc(category),
138+
);
139+
140+
const payloadProjectRefs = projectId.map(project =>
141+
getDb()
142+
.collection("projects")
143+
.doc(project),
144+
);
145+
146+
const payloadTechnologyRefs = technologyId.map(technology =>
147+
getDb()
148+
.collection("technologies")
149+
.doc(technology),
150+
);
151+
152+
const refs = {
153+
category: payloadCategoryRefs,
154+
project: payloadProjectRefs,
155+
technology: payloadTechnologyRefs,
156+
component: payloadComponentRefs,
157+
};
158+
159+
obj.refs = refs;
160+
88161
await getDb()
89162
.collection("portfolios")
90163
.doc(portfolioId)
@@ -159,16 +232,93 @@ export const fetchPublicPortfolio = async (portfolioCode: string) => {
159232
*
160233
* fetch all portfolios
161234
*
162-
* @param showComponents - boolean to indicate if the components should be fetched as well
163235
*/
164-
export const fetchPortFolios = async (showComponents: boolean = false) => {
236+
export const fetchPortFolios = async () => {
165237
try {
166238
const portfolios = await getDb()
167239
.collection("portfolios")
168240
.where("status", "==", STATUS_ACTIVE)
169241
.get();
170242

171-
const promises = portfolios.docs.map(project => parseRow(project.data(), showComponents));
243+
const promises = portfolios.docs.map(async item => {
244+
const row = item.data();
245+
const references = row.refs;
246+
247+
let categoryData = [];
248+
let componentData = [];
249+
let projectData = [];
250+
let technologyData = [];
251+
252+
if (references) {
253+
const categoryPromises = row.refs.category.map(
254+
async (categoryRef: FirebaseFirestore.DocumentReference) => {
255+
const category = await categoryRef.get();
256+
const categoryData = category.exists ? category.data() : null;
257+
return {
258+
id: categoryData.id,
259+
name: categoryData.name,
260+
};
261+
},
262+
);
263+
264+
const componentPromises = row.refs.component.map(
265+
async (componentRef: FirebaseFirestore.DocumentReference) => {
266+
const component = await componentRef.get();
267+
const componentData = component.exists ? component.data() : null;
268+
return {
269+
id: componentData.id,
270+
name: componentData.name,
271+
};
272+
},
273+
);
274+
275+
const projectPromises = row.refs.project.map(
276+
async (projectRef: FirebaseFirestore.DocumentReference) => {
277+
const project = await projectRef.get();
278+
const projectData = project.exists ? project.data() : null;
279+
return {
280+
id: projectData.id,
281+
name: projectData.name,
282+
};
283+
},
284+
);
285+
286+
const technologyPromises = row.refs.technology.map(
287+
async (technologyRef: FirebaseFirestore.DocumentReference) => {
288+
const technology = await technologyRef.get();
289+
const technologyData = technology.exists ? technology.data() : null;
290+
return {
291+
id: technologyData.id,
292+
name: technologyData.name,
293+
};
294+
},
295+
);
296+
297+
const [category, component, project, technology] = await Promise.all([
298+
Promise.all(categoryPromises),
299+
Promise.all(componentPromises),
300+
Promise.all(projectPromises),
301+
Promise.all(technologyPromises),
302+
]);
303+
304+
categoryData = category;
305+
componentData = component;
306+
projectData = project;
307+
technologyData = technology;
308+
}
309+
310+
return {
311+
id: row.id,
312+
title: row.title,
313+
description: row.description,
314+
category: categoryData,
315+
component: componentData,
316+
project: projectData,
317+
technology: technologyData,
318+
createdAt: row.createdAt.toDate(),
319+
updatedAt: row.updatedAt.toDate(),
320+
};
321+
});
172322

173323
return await Promise.all(promises);
174324
} catch (error) {

functions/src/routes/adminRoutes/portfolioRoutes.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,7 @@ router.get("/:portfolioId", async (req: Request, res: Response, next: NextFuncti
6262
// fetch all portfolios
6363
router.get("/", async (req: Request, res: Response, next: NextFunction) => {
6464
try {
65-
const showComponents = !!req.query.showComponents;
66-
67-
const result = await portfolioController.fetchPortfolios(showComponents);
65+
const result = await portfolioController.fetchPortfolios();
6866

6967
return response(res, successResponse(result));
7068
} catch (error) {

functions/tslint.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"no-construct": true,
2323
"no-duplicate-super": true,
2424
"no-duplicate-variable": [true, "check-parameters"],
25-
"no-shadowed-variable": true,
25+
"no-shadowed-variable": false,
2626
"no-empty": [true, "allow-empty-catch"],
2727
"no-floating-promises": true,
2828
"no-implicit-dependencies": [

public/admin_api_doc.dev.yml

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -342,8 +342,58 @@ components:
342342
type: string
343343
description: long description for the portfolio
344344
example: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
345-
components:
345+
category:
346+
type: array
347+
items:
348+
type: object
349+
properties:
350+
id:
351+
type: string
352+
description: unique identifier for the category
353+
example: 31765c4c-2606-4e1b-a613-7866212a86b6
354+
name:
355+
type: string
356+
description: name of the category
357+
example: Mobile Development
358+
component:
359+
type: array
360+
items:
361+
type: object
362+
properties:
363+
id:
364+
type: string
365+
description: unique identifier for the component
366+
example: 31765c4c-2606-4e1b-a613-7866212a86b6
367+
name:
368+
type: string
369+
description: name of the component
370+
example: Components 1
371+
project:
346372
type: array
373+
items:
374+
type: object
375+
properties:
376+
id:
377+
type: string
378+
description: unique identifier for the project
379+
example: 31765c4c-2606-4e1b-a613-7866212a86b6
380+
name:
381+
type: string
382+
description: name of the project
383+
example: Project A
384+
technology:
385+
type: array
386+
items:
387+
type: object
388+
properties:
389+
id:
390+
type: string
391+
description: unique identifier for the technology
392+
example: 31765c4c-2606-4e1b-a613-7866212a86b6
393+
name:
394+
type: string
395+
description: name of the technology
396+
example: Node JS
347397
createdAt:
348398
type: string
349399
description: created at ISO string
@@ -1522,6 +1572,7 @@ paths:
15221572
type: string
15231573
required:
15241574
- title
1575+
- description
15251576
- componentId
15261577
- technologyId
15271578
- categoryId
@@ -1540,12 +1591,6 @@ paths:
15401591
- portfolio
15411592
summary: Fetch all portfolios listed
15421593
description: Fetch all portfolios listed in the system
1543-
parameters:
1544-
- in: query
1545-
name: showComponents
1546-
schema:
1547-
type: boolean
1548-
description: indicates if components should be returned for each portfolio or not, if false an empty components array is returned
15491594
responses:
15501595
200:
15511596
description: Successful response
@@ -1603,6 +1648,7 @@ paths:
16031648
type: string
16041649
required:
16051650
- title
1651+
- description
16061652
- componentId
16071653
- technologyId
16081654
- categoryId

0 commit comments

Comments
 (0)