Skip to content

Commit ab6c1a7

Browse files
[productcatalog] - allow products to be extended (#1363)
* allow products to be extended Signed-off-by: Pierre Tessier <pierre@pierretessier.com> * allow products to be extended Signed-off-by: Pierre Tessier <pierre@pierretessier.com> * fix products path Signed-off-by: Pierre Tessier <pierre@pierretessier.com> * fix merge conflict Signed-off-by: Pierre Tessier <pierre@pierretessier.com> --------- Signed-off-by: Pierre Tessier <pierre@pierretessier.com> Co-authored-by: Juliano Costa <julianocosta89@outlook.com>
1 parent b8cc894 commit ab6c1a7

File tree

11 files changed

+62
-27
lines changed

11 files changed

+62
-27
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ the release.
5050
([#1358](https://github.com/open-telemetry/opentelemetry-demo/pull/1358))
5151
* [loadgenerator] fix browser traffic enabled flag
5252
([#1359](https://github.com/open-telemetry/opentelemetry-demo/pull/1359))
53+
* [productcatalog] allow products to be extended
54+
([#1363](https://github.com/open-telemetry/opentelemetry-demo/pull/1363))
5355

5456
## 1.7.2
5557

src/frontend/components/CartDropdown/CartDropdown.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ const CartDropdown = ({ productList, isOpen, onClose }: IProps) => {
4444
{productList.map(
4545
({ quantity, product: { name, picture, id, priceUsd = { nanos: 0, currencyCode: 'USD', units: 0 } } }) => (
4646
<S.Item key={id} data-cy={CypressFields.CartDropdownItem}>
47-
<S.ItemImage src={picture} alt={name} />
47+
<S.ItemImage src={"/images/products/" + picture} alt={name} />
4848
<S.ItemDetails>
4949
<S.ItemName>{name}</S.ItemName>
5050
<ProductPrice price={priceUsd} />

src/frontend/components/CartItems/CartItem.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const CartItem = ({
1919
<S.CartItem>
2020
<Link href={`/product/${id}`}>
2121
<S.NameContainer>
22-
<S.CartItemImage alt={name} src={picture} />
22+
<S.CartItemImage alt={name} src={"/images/products/" + picture} />
2323
<p>{name}</p>
2424
</S.NameContainer>
2525
</Link>

src/frontend/components/CheckoutItem/CheckoutItem.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const CheckoutItem = ({
2929
return (
3030
<S.CheckoutItem data-cy={CypressFields.CheckoutItem}>
3131
<S.ItemDetails>
32-
<S.ItemImage src={picture} alt={name} />
32+
<S.ItemImage src={"/images/products/" + picture} alt={name} />
3333
<S.Details>
3434
<S.ItemName>{name}</S.ItemName>
3535
<p>Quantity: {quantity}</p>

src/frontend/components/ProductCard/ProductCard.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const ProductCard = ({
2525
return (
2626
<S.Link href={`/product/${id}`}>
2727
<S.ProductCard data-cy={CypressFields.ProductCard}>
28-
<S.Image $src={picture} />
28+
<S.Image $src={"/images/products/" + picture} />
2929
<div>
3030
<S.ProductName>{name}</S.ProductName>
3131
<S.ProductPrice>

src/frontend/pages/product/[productId]/index.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ const ProductDetail: NextPage = () => {
6464
<Layout>
6565
<S.ProductDetail data-cy={CypressFields.ProductDetail}>
6666
<S.Container>
67-
<S.Image $src={picture} data-cy={CypressFields.ProductPicture} />
67+
<S.Image $src={"/images/products/" + picture} data-cy={CypressFields.ProductPicture} />
6868
<S.Details>
6969
<S.Name data-cy={CypressFields.ProductName}>{name}</S.Name>
7070
<S.Description data-cy={CypressFields.ProductDescription}>{description}</S.Description>

src/productcatalogservice/Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ FROM alpine AS release
1717

1818
WORKDIR /usr/src/app/
1919

20-
COPY ./src/productcatalogservice/products.json ./
20+
COPY ./src/productcatalogservice/products/ ./products/
2121
COPY --from=builder /go/bin/productcatalogservice/ ./
2222

2323
EXPOSE ${PRODUCT_SERVICE_PORT}

src/productcatalogservice/main.go

+42-9
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ package main
99
import (
1010
"context"
1111
"fmt"
12-
"io/ioutil"
12+
"io/fs"
13+
1314
"net"
1415
"os"
1516
"strings"
@@ -51,7 +52,12 @@ var (
5152

5253
func init() {
5354
log = logrus.New()
54-
catalog = readCatalogFile()
55+
var err error
56+
catalog, err = readProductFiles()
57+
if err != nil {
58+
log.Fatalf("Reading Product Files: %v", err)
59+
os.Exit(1)
60+
}
5561
}
5662

5763
func initResource() *sdkresource.Resource {
@@ -151,18 +157,45 @@ type productCatalog struct {
151157
pb.UnimplementedProductCatalogServiceServer
152158
}
153159

154-
func readCatalogFile() []*pb.Product {
155-
catalogJSON, err := ioutil.ReadFile("products.json")
160+
func readProductFiles() ([]*pb.Product, error) {
161+
162+
// find all .json files in the products directory
163+
entries, err := os.ReadDir("./products")
156164
if err != nil {
157-
log.Fatalf("Reading Catalog File: %v", err)
165+
return nil, err
166+
}
167+
168+
jsonFiles := make([]fs.FileInfo, 0, len(entries))
169+
for _, entry := range entries {
170+
if strings.HasSuffix(entry.Name(), ".json") {
171+
info, err := entry.Info()
172+
if err != nil {
173+
return nil, err
174+
}
175+
jsonFiles = append(jsonFiles, info)
176+
}
158177
}
159178

160-
var res pb.ListProductsResponse
161-
if err := protojson.Unmarshal(catalogJSON, &res); err != nil {
162-
log.Fatalf("Parsing Catalog JSON: %v", err)
179+
// read the contents of each .json file and unmarshal into a ListProductsResponse
180+
// then append the products to the catalog
181+
var products []*pb.Product
182+
for _, f := range jsonFiles {
183+
jsonData, err := os.ReadFile("./products/" + f.Name())
184+
if err != nil {
185+
return nil, err
186+
}
187+
188+
var res pb.ListProductsResponse
189+
if err := protojson.Unmarshal(jsonData, &res); err != nil {
190+
return nil, err
191+
}
192+
193+
products = append(products, res.Products...)
163194
}
164195

165-
return res.Products
196+
log.Infof("Loaded %d products", len(products))
197+
198+
return products, nil
166199
}
167200

168201
func mustMapEnv(target *string, key string) {

src/productcatalogservice/products.json src/productcatalogservice/products/products.json

+10-10
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"id": "OLJCESPC7Z",
55
"name": "National Park Foundation Explorascope",
66
"description": "The National Park Foundation’s (NPF) Explorascope 60AZ is a manual alt-azimuth, refractor telescope perfect for celestial viewing on the go. The NPF Explorascope 60 can view the planets, moon, star clusters and brighter deep sky objects like the Orion Nebula and Andromeda Galaxy.",
7-
"picture": "/images/products/NationalParkFoundationExplorascope.jpg",
7+
"picture": "NationalParkFoundationExplorascope.jpg",
88
"priceUsd": {
99
"currencyCode": "USD",
1010
"units": 101,
@@ -16,7 +16,7 @@
1616
"id": "66VCHSJNUP",
1717
"name": "Starsense Explorer Refractor Telescope",
1818
"description": "The first telescope that uses your smartphone to analyze the night sky and calculate its position in real time. StarSense Explorer is ideal for beginners thanks to the app’s user-friendly interface and detailed tutorials. It’s like having your own personal tour guide of the night sky",
19-
"picture": "/images/products/StarsenseExplorer.jpg",
19+
"picture": "StarsenseExplorer.jpg",
2020
"priceUsd": {
2121
"currencyCode": "USD",
2222
"units": 349,
@@ -28,7 +28,7 @@
2828
"id": "1YMWWN1N4O",
2929
"name": "Eclipsmart Travel Refractor Telescope",
3030
"description": "Dedicated white-light solar scope for the observer on the go. The 50mm refracting solar scope uses Solar Safe, ISO compliant, full-aperture glass filter material to ensure the safest view of solar events. The kit comes complete with everything you need, including the dedicated travel solar scope, a Solar Safe finderscope, tripod, a high quality 20mm (18x) Kellner eyepiece and a nylon backpack to carry everything in. This Travel Solar Scope makes it easy to share the Sun as well as partial and total solar eclipses with the whole family and offers much higher magnifications than you would otherwise get using handheld solar viewers or binoculars.",
31-
"picture": "/images/products/EclipsmartTravelRefractorTelescope.jpg",
31+
"picture": "EclipsmartTravelRefractorTelescope.jpg",
3232
"priceUsd": {
3333
"currencyCode": "USD",
3434
"units": 129,
@@ -40,7 +40,7 @@
4040
"id": "L9ECAV7KIM",
4141
"name": "Lens Cleaning Kit",
4242
"description": "Wipe away dust, dirt, fingerprints and other particles on your lenses to see clearly with the Lens Cleaning Kit. This cleaning kit works on all glass and optical surfaces, including telescopes, binoculars, spotting scopes, monoculars, microscopes, and even your camera lenses, computer screens, and mobile devices. The kit comes complete with a retractable lens brush to remove dust particles and dirt and two options to clean smudges and fingerprints off of your optics, pre-moistened lens wipes and a bottled lens cleaning fluid with soft cloth.",
43-
"picture": "/images/products/LensCleaningKit.jpg",
43+
"picture": "LensCleaningKit.jpg",
4444
"priceUsd": {
4545
"currencyCode": "USD",
4646
"units": 21,
@@ -52,7 +52,7 @@
5252
"id": "2ZYFJ3GM2N",
5353
"name": "Roof Binoculars",
5454
"description": "This versatile, all-around binocular is a great choice for the trail, the stadium, the arena, or just about anywhere you want a close-up view of the action without sacrificing brightness or detail. It’s an especially great companion for nature observation and bird watching, with ED glass that helps you spot the subtlest field markings and a close focus of just 6.5 feet.",
55-
"picture": "/images/products/RoofBinoculars.jpg",
55+
"picture": "RoofBinoculars.jpg",
5656
"priceUsd": {
5757
"currencyCode": "USD",
5858
"units": 209,
@@ -64,7 +64,7 @@
6464
"id": "0PUK6V6EV0",
6565
"name": "Solar System Color Imager",
6666
"description": "You have your new telescope and have observed Saturn and Jupiter. Now you're ready to take the next step and start imaging them. But where do you begin? The NexImage 10 Solar System Imager is the perfect solution.",
67-
"picture": "/images/products/SolarSystemColorImager.jpg",
67+
"picture": "SolarSystemColorImager.jpg",
6868
"priceUsd": {
6969
"currencyCode": "USD",
7070
"units": 175,
@@ -76,7 +76,7 @@
7676
"id": "LS4PSXUNUM",
7777
"name": "Red Flashlight",
7878
"description": "This 3-in-1 device features a 3-mode red flashlight, a hand warmer, and a portable power bank for recharging your personal electronics on the go. Whether you use it to light the way at an astronomy star party, a night walk, or wildlife research, ThermoTorch 3 Astro Red’s rugged, IPX4-rated design will withstand your everyday activities.",
79-
"picture": "/images/products/RedFlashlight.jpg",
79+
"picture": "RedFlashlight.jpg",
8080
"priceUsd": {
8181
"currencyCode": "USD",
8282
"units": 57,
@@ -88,7 +88,7 @@
8888
"id": "9SIQT8TOJO",
8989
"name": "Optical Tube Assembly",
9090
"description": "Capturing impressive deep-sky astroimages is easier than ever with Rowe-Ackermann Schmidt Astrograph (RASA) V2, the perfect companion to today’s top DSLR or astronomical CCD cameras. This fast, wide-field f/2.2 system allows for shorter exposure times compared to traditional f/10 astroimaging, without sacrificing resolution. Because shorter sub-exposure times are possible, your equatorial mount won’t need to accurately track over extended periods. The short focal length also lessens equatorial tracking demands. In many cases, autoguiding will not be required.",
91-
"picture": "/images/products/OpticalTubeAssembly.jpg",
91+
"picture": "OpticalTubeAssembly.jpg",
9292
"priceUsd": {
9393
"currencyCode": "USD",
9494
"units": 3599,
@@ -100,7 +100,7 @@
100100
"id": "6E92ZMYYFZ",
101101
"name": "Solar Filter",
102102
"description": "Enhance your viewing experience with EclipSmart Solar Filter for 8” telescopes. With two Velcro straps and four self-adhesive Velcro pads for added safety, you can be assured that the solar filter cannot be accidentally knocked off and will provide Solar Safe, ISO compliant viewing.",
103-
"picture": "/images/products/SolarFilter.jpg",
103+
"picture": "SolarFilter.jpg",
104104
"priceUsd": {
105105
"currencyCode": "USD",
106106
"units": 69,
@@ -112,7 +112,7 @@
112112
"id": "HQTGWGPNH4",
113113
"name": "The Comet Book",
114114
"description": "A 16th-century treatise on comets, created anonymously in Flanders (now northern France) and now held at the Universitätsbibliothek Kassel. Commonly known as The Comet Book (or Kometenbuch in German), its full title translates as “Comets and their General and Particular Meanings, According to Ptolomeé, Albumasar, Haly, Aliquind and other Astrologers”. The image is from https://publicdomainreview.org/collection/the-comet-book, made available by the Universitätsbibliothek Kassel under a CC-BY SA 4.0 license (https://creativecommons.org/licenses/by-sa/4.0/)",
115-
"picture": "/images/products/TheCometBook.jpg",
115+
"picture": "TheCometBook.jpg",
116116
"priceUsd": {
117117
"currencyCode": "USD",
118118
"units": 0,

test/Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@ ENV NODE_ENV production
2121
COPY --chown=node:node --from=build /app/node_modules/ ./node_modules/
2222
COPY ./test ./
2323
COPY ./pb/demo.proto ./
24-
COPY ./src/productcatalogservice/products.json ../src/productcatalogservice/products.json
24+
COPY ./src/productcatalogservice/products/products.json ../src/productcatalogservice/products/products.json
2525

2626
ENTRYPOINT ["npm", "test"]

test/test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const protoLoader = require("@grpc/proto-loader");
1212
const fetch = require("node-fetch");
1313
const dotenvExpand = require("dotenv-expand");
1414
const { resolve } = require("path");
15-
const productData = require("../src/productcatalogservice/products.json");
15+
const productData = require("../src/productcatalogservice/products/products.json");
1616

1717
const myEnv = dotEnv.config({
1818
path: resolve(__dirname, "../.env"),

0 commit comments

Comments
 (0)